Skip to main content

systemprompt_sync/models/
local_sync.rs

1//! Plain-data structs returned by the local-sync diff calculators and the
2//! disk-side parsers. All fields are public so callers can render them
3//! directly into CLI tables or JSON responses.
4
5use chrono::{DateTime, Utc};
6use serde::Serialize;
7use std::fmt;
8use systemprompt_identifiers::{AgentId, SkillId, SourceId};
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
11pub enum LocalSyncDirection {
12    #[default]
13    ToDisk,
14    ToDatabase,
15}
16
17impl fmt::Display for LocalSyncDirection {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        match self {
20            Self::ToDisk => write!(f, "to_disk"),
21            Self::ToDatabase => write!(f, "to_database"),
22        }
23    }
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
27pub enum DiffStatus {
28    Added,
29    Removed,
30    Modified,
31}
32
33#[derive(Clone, Debug, Serialize)]
34pub struct ContentDiffItem {
35    pub slug: String,
36    pub source_id: SourceId,
37    pub status: DiffStatus,
38    pub disk_hash: Option<String>,
39    pub db_hash: Option<String>,
40    pub disk_updated_at: Option<DateTime<Utc>>,
41    pub db_updated_at: Option<DateTime<Utc>>,
42    pub title: Option<String>,
43}
44
45#[derive(Clone, Debug, Serialize)]
46pub struct SkillDiffItem {
47    pub skill_id: SkillId,
48    pub file_path: String,
49    pub status: DiffStatus,
50    pub disk_hash: Option<String>,
51    pub db_hash: Option<String>,
52    pub name: Option<String>,
53}
54
55#[derive(Clone, Debug, Serialize)]
56pub struct ContentDiffResult {
57    pub source_id: SourceId,
58    pub added: Vec<ContentDiffItem>,
59    pub removed: Vec<ContentDiffItem>,
60    pub modified: Vec<ContentDiffItem>,
61    pub unchanged: usize,
62}
63
64impl Default for ContentDiffResult {
65    fn default() -> Self {
66        Self {
67            source_id: SourceId::new(""),
68            added: Vec::new(),
69            removed: Vec::new(),
70            modified: Vec::new(),
71            unchanged: 0,
72        }
73    }
74}
75
76impl ContentDiffResult {
77    pub fn has_changes(&self) -> bool {
78        !self.added.is_empty() || !self.removed.is_empty() || !self.modified.is_empty()
79    }
80}
81
82#[derive(Clone, Debug, Default, Serialize)]
83pub struct SkillsDiffResult {
84    pub added: Vec<SkillDiffItem>,
85    pub removed: Vec<SkillDiffItem>,
86    pub modified: Vec<SkillDiffItem>,
87    pub unchanged: usize,
88}
89
90impl SkillsDiffResult {
91    pub fn has_changes(&self) -> bool {
92        !self.added.is_empty() || !self.removed.is_empty() || !self.modified.is_empty()
93    }
94}
95
96#[derive(Clone, Debug, Default, Serialize)]
97pub struct LocalSyncResult {
98    pub items_synced: usize,
99    pub items_skipped: usize,
100    pub items_skipped_modified: usize,
101    pub items_deleted: usize,
102    pub errors: Vec<String>,
103    pub direction: LocalSyncDirection,
104}
105
106#[derive(Debug)]
107pub struct DiskContent {
108    pub slug: String,
109    pub title: String,
110    pub body: String,
111}
112
113#[derive(Debug)]
114pub struct DiskSkill {
115    pub skill_id: SkillId,
116    pub name: String,
117    pub description: String,
118    pub instructions: String,
119    pub file_path: String,
120}
121
122#[derive(Clone, Debug, Serialize)]
123pub struct AgentDiffItem {
124    pub agent_id: AgentId,
125    pub name: String,
126    pub status: DiffStatus,
127    pub disk_hash: Option<String>,
128    pub db_hash: Option<String>,
129}
130
131#[derive(Clone, Debug, Default, Serialize)]
132pub struct AgentsDiffResult {
133    pub added: Vec<AgentDiffItem>,
134    pub removed: Vec<AgentDiffItem>,
135    pub modified: Vec<AgentDiffItem>,
136    pub unchanged: usize,
137}
138
139impl AgentsDiffResult {
140    pub fn has_changes(&self) -> bool {
141        !self.added.is_empty() || !self.removed.is_empty() || !self.modified.is_empty()
142    }
143}
144
145#[derive(Debug)]
146pub struct DiskAgent {
147    pub agent_id: AgentId,
148    pub name: String,
149    pub display_name: String,
150    pub description: String,
151    pub system_prompt: Option<String>,
152    pub port: u16,
153}