systemprompt_loader/
services_root.rs1use std::collections::BTreeMap;
17use std::path::PathBuf;
18use std::sync::OnceLock;
19
20use serde::{Deserialize, Serialize};
21
22static ACTIVE_ROOT: OnceLock<ActiveServicesRoot> = OnceLock::new();
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25#[serde(tag = "kind", rename_all = "snake_case")]
26pub enum ServicesProvenance {
27 Bundled,
28
29 Fetched {
30 composed_hash: String,
31 versions: BTreeMap<String, String>,
32 },
33
34 LastGood {
35 composed_hash: String,
36 error: String,
37 },
38
39 BundledFallback {
40 error: String,
41 },
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct ActiveServicesRoot {
46 pub path: PathBuf,
47 pub provenance: ServicesProvenance,
48}
49
50#[derive(Debug, Clone, Copy)]
51pub struct ServicesRootBootstrap;
52
53impl ServicesRootBootstrap {
54 pub fn install(root: ActiveServicesRoot) -> &'static ActiveServicesRoot {
55 ACTIVE_ROOT.get_or_init(|| root)
56 }
57
58 #[must_use]
59 pub fn get() -> Option<&'static ActiveServicesRoot> {
60 ACTIVE_ROOT.get()
61 }
62
63 #[must_use]
64 pub fn is_initialized() -> bool {
65 ACTIVE_ROOT.get().is_some()
66 }
67
68 #[must_use]
69 pub fn active_root_or(fallback: &str) -> PathBuf {
70 ACTIVE_ROOT
71 .get()
72 .map_or_else(|| PathBuf::from(fallback), |root| root.path.clone())
73 }
74
75 #[must_use]
76 pub fn active_path_or(fallback: &str, relative: &str) -> PathBuf {
77 Self::active_root_or(fallback).join(relative)
78 }
79}