Skip to main content

systemprompt_loader/
extension_binary_index.rs

1//! In-memory index of discovered extensions used to resolve binary paths
2//! at runtime, with a separate code path for cloud deployments where
3//! every binary lives in a single configured directory.
4//!
5//! Copyright (c) systemprompt.io — Business Source License 1.1.
6//! See <https://systemprompt.io> for licensing details.
7
8use std::collections::HashMap;
9use std::path::{Path, PathBuf};
10
11use systemprompt_models::DiscoveredExtension;
12
13use crate::ExtensionLoader;
14use crate::error::{ExtensionLoadError, ExtensionLoadResult};
15
16#[derive(Debug)]
17pub struct ExtensionBinaryIndex {
18    discovered: HashMap<String, DiscoveredExtension>,
19    bin_path: PathBuf,
20    is_cloud: bool,
21}
22
23impl ExtensionBinaryIndex {
24    #[must_use]
25    pub fn build(project_root: &Path, is_cloud: bool, bin_path: &str) -> Self {
26        let discovered = if is_cloud {
27            HashMap::new()
28        } else {
29            ExtensionLoader::build_binary_map(project_root)
30        };
31
32        Self {
33            discovered,
34            bin_path: PathBuf::from(bin_path),
35            is_cloud,
36        }
37    }
38
39    pub fn get_path(&self, binary_name: &str) -> ExtensionLoadResult<PathBuf> {
40        if self.is_cloud {
41            let binary_path = self.bin_path.join(binary_name);
42            return binary_path
43                .exists()
44                .then(|| self.bin_path.clone())
45                .ok_or_else(|| ExtensionLoadError::BinaryNotFound {
46                    name: binary_name.to_owned(),
47                    path: binary_path,
48                });
49        }
50
51        self.discovered
52            .get(binary_name)
53            .map(|ext| ext.path.clone())
54            .ok_or_else(|| ExtensionLoadError::ManifestMissing(binary_name.to_owned()))
55    }
56
57    #[must_use]
58    pub fn get_extension(&self, binary_name: &str) -> Option<&DiscoveredExtension> {
59        self.discovered.get(binary_name)
60    }
61
62    #[must_use]
63    pub fn has_extension(&self, binary_name: &str) -> bool {
64        self.bin_path.join(binary_name).exists() || self.discovered.contains_key(binary_name)
65    }
66}