ai_agent/utils/plugins/
zip_cache_adapters.rs1#![allow(dead_code)]
3
4use std::collections::HashMap;
5
6use super::schemas::{KnownMarketplace, KnownMarketplacesFile};
7use super::types::PluginMarketplace;
8use super::zip_cache::{
9 atomic_write_to_zip_cache, get_marketplace_json_relative_path, get_plugin_zip_cache_path,
10 get_zip_cache_known_marketplaces_path,
11};
12
13pub async fn read_zip_cache_known_marketplaces() -> KnownMarketplacesFile {
15 let path = match get_zip_cache_known_marketplaces_path() {
16 Ok(p) => p,
17 Err(_) => return HashMap::new(),
18 };
19
20 match tokio::fs::read_to_string(&path).await {
21 Ok(content) => match serde_json::from_str::<KnownMarketplacesFile>(&content) {
22 Ok(parsed) => parsed,
23 Err(e) => {
24 log::debug!("Invalid known_marketplaces.json in zip cache: {}", e);
25 HashMap::new()
26 }
27 },
28 Err(_) => HashMap::new(),
29 }
30}
31
32pub async fn write_zip_cache_known_marketplaces(
34 data: &KnownMarketplacesFile,
35) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
36 let path = get_zip_cache_known_marketplaces_path()?;
37 let content = serde_json::to_string_pretty(data)?;
38 atomic_write_to_zip_cache(&path, content.as_bytes()).await
39}
40
41pub async fn read_marketplace_json(marketplace_name: &str) -> Option<PluginMarketplace> {
43 let zip_cache_path = get_plugin_zip_cache_path()?;
44 let rel_path = get_marketplace_json_relative_path(marketplace_name);
45 let full_path = format!("{}/{}", zip_cache_path, rel_path);
46
47 match tokio::fs::read_to_string(&full_path).await {
48 Ok(content) => match serde_json::from_str::<PluginMarketplace>(&content) {
49 Ok(parsed) => Some(parsed),
50 Err(e) => {
51 log::debug!("Invalid marketplace JSON for {}: {}", marketplace_name, e);
52 None
53 }
54 },
55 Err(_) => None,
56 }
57}
58
59pub async fn save_marketplace_json_to_zip_cache(
61 marketplace_name: &str,
62 install_location: &str,
63) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
64 let zip_cache_path = match get_plugin_zip_cache_path() {
65 Some(p) => p,
66 None => return Ok(()),
67 };
68
69 if let Some(content) = read_marketplace_json_content(install_location).await {
70 let rel_path = get_marketplace_json_relative_path(marketplace_name);
71 let full_path = format!("{}/{}", zip_cache_path, rel_path);
72 atomic_write_to_zip_cache(&full_path, content.as_bytes()).await?;
73 }
74
75 Ok(())
76}
77
78async fn read_marketplace_json_content(dir: &str) -> Option<String> {
80 let candidates = [
81 format!("{}/.claude-plugin/marketplace.json", dir),
82 format!("{}/marketplace.json", dir),
83 dir.to_string(), ];
85
86 for candidate in candidates {
87 if let Ok(content) = tokio::fs::read_to_string(&candidate).await {
88 return Some(content);
89 }
90 }
91
92 None
93}
94
95pub async fn sync_marketplaces_to_zip_cache() -> Result<(), Box<dyn std::error::Error + Send + Sync>>
97{
98 let known_marketplaces =
99 match super::marketplace_manager::load_known_marketplaces_config_safe().await {
100 Ok(m) => m,
101 Err(e) => {
102 log::debug!("Failed to load known marketplaces config: {}", e);
103 return Ok(());
104 }
105 };
106
107 for (name, entry) in &known_marketplaces {
109 let install_location = &entry.install_location;
110 if !install_location.is_empty() {
111 if let Err(e) = save_marketplace_json_to_zip_cache(name, install_location).await {
112 log::debug!("Failed to save marketplace JSON for {}: {}", name, e);
113 }
114 }
115 }
116
117 let zip_cache_known_marketplaces = read_zip_cache_known_marketplaces().await;
119 let mut merged = zip_cache_known_marketplaces;
120 merged.extend(known_marketplaces);
121
122 write_zip_cache_known_marketplaces(&merged).await?;
123
124 Ok(())
125}