1use anyhow::Result;
6use async_trait::async_trait;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::path::{Path, PathBuf};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub struct DependencySpec {
18 pub name: String,
19 pub uri: String,
20 pub version: Option<String>,
21 pub fingerprint: Option<String>,
22}
23
24#[derive(Debug, Clone)]
26pub struct ResolvedDependency {
27 pub spec: DependencySpec,
28 pub uri: String,
29 pub resolved_version: String,
30 pub fingerprint: String,
31 pub proto_files: Vec<ProtoFile>,
32}
33
34#[derive(Debug, Clone)]
36pub struct ProtoFile {
37 pub name: String,
38 pub path: PathBuf,
39 pub content: String,
40 pub services: Vec<ServiceDefinition>,
41}
42
43#[derive(Debug, Clone)]
45pub struct ServiceDefinition {
46 pub name: String,
47 pub methods: Vec<MethodDefinition>,
48}
49
50#[derive(Debug, Clone)]
52pub struct MethodDefinition {
53 pub name: String,
54 pub input_type: String,
55 pub output_type: String,
56}
57
58#[derive(Debug, Clone)]
60pub struct ServiceInfo {
61 pub name: String,
62 pub uri: String,
63 pub version: String,
64 pub fingerprint: String,
65 pub description: Option<String>,
66 pub methods: Vec<MethodDefinition>,
67}
68
69#[derive(Debug, Clone)]
71pub struct ServiceDetails {
72 pub info: ServiceInfo,
73 pub proto_files: Vec<ProtoFile>,
74 pub dependencies: Vec<String>,
75}
76
77#[derive(Debug, Clone, PartialEq)]
79pub struct Fingerprint {
80 pub algorithm: String,
81 pub value: String,
82}
83
84#[derive(Debug, Clone)]
86pub struct ValidationReport {
87 pub is_valid: bool,
88 pub config_validation: ConfigValidation,
89 pub dependency_validation: Vec<DependencyValidation>,
90 pub network_validation: Vec<NetworkValidation>,
91 pub fingerprint_validation: Vec<FingerprintValidation>,
92 pub conflicts: Vec<ConflictReport>,
93}
94
95#[derive(Debug, Clone)]
96pub struct ConfigValidation {
97 pub is_valid: bool,
98 pub errors: Vec<String>,
99 pub warnings: Vec<String>,
100}
101
102#[derive(Debug, Clone)]
103pub struct DependencyValidation {
104 pub dependency: String,
105 pub is_available: bool,
106 pub resolved_uri: Option<String>,
107 pub error: Option<String>,
108}
109
110#[derive(Debug, Clone)]
111pub struct NetworkValidation {
112 pub uri: String,
113 pub is_reachable: bool,
114 pub latency_ms: Option<u64>,
115 pub error: Option<String>,
116}
117
118#[derive(Debug, Clone)]
119pub struct FingerprintValidation {
120 pub dependency: String,
121 pub expected: Fingerprint,
122 pub actual: Option<Fingerprint>,
123 pub is_valid: bool,
124 pub error: Option<String>,
125}
126
127#[derive(Debug, Clone)]
128pub struct ConflictReport {
129 pub dependency_a: String,
130 pub dependency_b: String,
131 pub conflict_type: ConflictType,
132 pub description: String,
133}
134
135#[derive(Debug, Clone)]
136pub enum ConflictType {
137 VersionConflict,
138 FingerprintMismatch,
139 CircularDependency,
140}
141
142impl ValidationReport {
143 pub fn is_success(&self) -> bool {
144 self.is_valid
145 && self.config_validation.is_valid
146 && self.dependency_validation.iter().all(|d| d.is_available)
147 && self.network_validation.iter().all(|n| n.is_reachable)
148 && self.fingerprint_validation.iter().all(|f| f.is_valid)
149 && self.conflicts.is_empty()
150 }
151}
152
153#[async_trait]
159pub trait ConfigManager: Send + Sync {
160 async fn load_config(&self, path: &Path) -> Result<ActrConfig>;
162
163 async fn save_config(&self, config: &ActrConfig, path: &Path) -> Result<()>;
165
166 async fn update_dependency(&self, spec: &DependencySpec) -> Result<()>;
168
169 async fn validate_config(&self) -> Result<ConfigValidation>;
171
172 fn get_project_root(&self) -> &Path;
174
175 async fn backup_config(&self) -> Result<ConfigBackup>;
177
178 async fn restore_backup(&self, backup: ConfigBackup) -> Result<()>;
180
181 async fn remove_backup(&self, backup: ConfigBackup) -> Result<()>;
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct ActrConfig {
188 pub package: PackageConfig,
189 pub provides: Option<HashMap<String, String>>,
190 pub dependencies: Option<HashMap<String, DependencyConfig>>,
191 pub scripts: Option<HashMap<String, String>>,
192 pub routing: Option<HashMap<String, String>>,
193 pub signaling: Option<SignalingConfig>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct PackageConfig {
198 pub name: String,
199 pub version: String,
200 #[serde(rename = "type")]
201 pub package_type: Option<String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize)]
205#[serde(untagged)]
206pub enum DependencyConfig {
207 Simple(String),
208 Complex {
209 uri: String,
210 #[serde(default)]
211 version: Option<String>,
212 #[serde(default)]
213 fingerprint: Option<String>,
214 },
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct SignalingConfig {
219 pub url: String,
220 pub auth: Option<AuthConfig>,
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct AuthConfig {
225 pub token: Option<String>,
226 pub username: Option<String>,
227 pub password: Option<String>,
228}
229
230#[derive(Debug, Clone)]
232pub struct ConfigBackup {
233 pub original_path: PathBuf,
234 pub backup_path: PathBuf,
235 pub timestamp: std::time::SystemTime,
236}
237
238#[async_trait]
244pub trait DependencyResolver: Send + Sync {
245 async fn resolve_spec(&self, spec: &str) -> Result<DependencySpec>;
247
248 async fn resolve_dependencies(
250 &self,
251 specs: &[DependencySpec],
252 ) -> Result<Vec<ResolvedDependency>>;
253
254 async fn check_conflicts(&self, deps: &[ResolvedDependency]) -> Result<Vec<ConflictReport>>;
256
257 async fn build_dependency_graph(&self, deps: &[ResolvedDependency]) -> Result<DependencyGraph>;
259}
260
261#[derive(Debug, Clone)]
262pub struct DependencyGraph {
263 pub nodes: Vec<String>,
264 pub edges: Vec<(String, String)>,
265 pub has_cycles: bool,
266}
267
268#[async_trait]
274pub trait ServiceDiscovery: Send + Sync {
275 async fn discover_services(&self, filter: Option<&ServiceFilter>) -> Result<Vec<ServiceInfo>>;
277
278 async fn get_service_details(&self, uri: &str) -> Result<ServiceDetails>;
280
281 async fn check_service_availability(&self, uri: &str) -> Result<AvailabilityStatus>;
283
284 async fn get_service_proto(&self, uri: &str) -> Result<Vec<ProtoFile>>;
286}
287
288#[derive(Debug, Clone)]
289pub struct ServiceFilter {
290 pub name_pattern: Option<String>,
291 pub version_range: Option<String>,
292 pub tags: Option<Vec<String>>,
293}
294
295#[derive(Debug, Clone)]
296pub struct AvailabilityStatus {
297 pub is_available: bool,
298 pub last_seen: Option<std::time::SystemTime>,
299 pub health: HealthStatus,
300}
301
302#[derive(Debug, Clone)]
303pub enum HealthStatus {
304 Healthy,
305 Degraded,
306 Unhealthy,
307 Unknown,
308}
309
310#[async_trait]
316pub trait NetworkValidator: Send + Sync {
317 async fn check_connectivity(&self, uri: &str) -> Result<ConnectivityStatus>;
319
320 async fn verify_service_health(&self, uri: &str) -> Result<HealthStatus>;
322
323 async fn test_latency(&self, uri: &str) -> Result<LatencyInfo>;
325
326 async fn batch_check(&self, uris: &[String]) -> Result<Vec<NetworkCheckResult>>;
328}
329
330#[derive(Debug, Clone)]
331pub struct ConnectivityStatus {
332 pub is_reachable: bool,
333 pub response_time_ms: Option<u64>,
334 pub error: Option<String>,
335}
336
337#[derive(Debug, Clone)]
338pub struct LatencyInfo {
339 pub min_ms: u64,
340 pub max_ms: u64,
341 pub avg_ms: u64,
342 pub samples: u32,
343}
344
345#[derive(Debug, Clone)]
346pub struct NetworkCheckResult {
347 pub uri: String,
348 pub connectivity: ConnectivityStatus,
349 pub health: HealthStatus,
350 pub latency: Option<LatencyInfo>,
351}
352
353#[async_trait]
359pub trait FingerprintValidator: Send + Sync {
360 async fn compute_service_fingerprint(&self, service: &ServiceInfo) -> Result<Fingerprint>;
362
363 async fn verify_fingerprint(
365 &self,
366 expected: &Fingerprint,
367 actual: &Fingerprint,
368 ) -> Result<bool>;
369
370 async fn compute_project_fingerprint(&self, project_path: &Path) -> Result<Fingerprint>;
372
373 async fn generate_lock_fingerprint(&self, deps: &[ResolvedDependency]) -> Result<Fingerprint>;
375}
376
377#[async_trait]
383pub trait ProtoProcessor: Send + Sync {
384 async fn discover_proto_files(&self, path: &Path) -> Result<Vec<ProtoFile>>;
386
387 async fn parse_proto_services(&self, files: &[ProtoFile]) -> Result<Vec<ServiceDefinition>>;
389
390 async fn generate_code(&self, input: &Path, output: &Path) -> Result<GenerationResult>;
392
393 async fn validate_proto_syntax(&self, files: &[ProtoFile]) -> Result<ValidationReport>;
395}
396
397#[derive(Debug, Clone)]
398pub struct GenerationResult {
399 pub generated_files: Vec<PathBuf>,
400 pub warnings: Vec<String>,
401 pub errors: Vec<String>,
402}
403
404#[async_trait]
410pub trait CacheManager: Send + Sync {
411 async fn get_cached_proto(&self, uri: &str) -> Result<Option<CachedProto>>;
413
414 async fn cache_proto(&self, uri: &str, proto: &[ProtoFile]) -> Result<()>;
416
417 async fn invalidate_cache(&self, uri: &str) -> Result<()>;
419
420 async fn clear_cache(&self) -> Result<()>;
422
423 async fn get_cache_stats(&self) -> Result<CacheStats>;
425}
426
427#[derive(Debug, Clone)]
428pub struct CachedProto {
429 pub uri: String,
430 pub files: Vec<ProtoFile>,
431 pub fingerprint: Fingerprint,
432 pub cached_at: std::time::SystemTime,
433 pub expires_at: Option<std::time::SystemTime>,
434}
435
436#[derive(Debug, Clone)]
437pub struct CacheStats {
438 pub total_entries: usize,
439 pub total_size_bytes: u64,
440 pub hit_rate: f64,
441 pub miss_rate: f64,
442}
443
444#[async_trait]
450pub trait UserInterface: Send + Sync {
451 async fn prompt_input(&self, prompt: &str) -> Result<String>;
453
454 async fn confirm(&self, message: &str) -> Result<bool>;
456
457 async fn select_service_from_list(
459 &self,
460 items: &[ServiceInfo],
461 formatter: fn(&ServiceInfo) -> String,
462 ) -> Result<usize>;
463
464 async fn select_string_from_list(
466 &self,
467 items: &[String],
468 formatter: fn(&String) -> String,
469 ) -> Result<usize>;
470
471 async fn display_service_table(
473 &self,
474 items: &[ServiceInfo],
475 headers: &[&str],
476 formatter: fn(&ServiceInfo) -> Vec<String>,
477 );
478
479 async fn show_progress(&self, message: &str) -> Result<Box<dyn ProgressBar>>;
481}
482
483pub trait ProgressBar: Send + Sync {
485 fn update(&self, progress: f64);
486 fn set_message(&self, message: &str);
487 fn finish(&self);
488}