Skip to main content

ai_agent/utils/plugins/
zip_cache_adapters.rs

1// Source: ~/claudecode/openclaudecode/src/utils/plugins/zipCacheAdapters.ts
2#![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
13/// Read known_marketplaces.json from the zip cache.
14pub 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
32/// Write known_marketplaces.json to the zip cache atomically.
33pub 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
41/// Read a marketplace JSON file from the zip cache.
42pub 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
59/// Save a marketplace JSON to the zip cache from its install location.
60pub 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
78/// Read marketplace.json content from a cloned marketplace directory or file.
79async 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(), // For URL sources, installLocation IS the marketplace JSON file
84    ];
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
95/// Sync marketplace data to zip cache for offline access.
96pub 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    // Save marketplace JSONs to zip cache
108    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    // Merge with previously cached data
118    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}