1use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11use crate::amalgamation;
12use crate::common::ApiState;
13use crate::common::{ApiError, ApiResult, Json, State};
14
15#[allow(non_snake_case)] #[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
21pub struct FatigueInfo {
22 pub fatigue_index: Option<u8>,
24 pub fatigue_active: Option<bool>,
26 pub regular_neuron_util: Option<u8>,
28 pub memory_neuron_util: Option<u8>,
30 pub synapse_util: Option<u8>,
32}
33
34#[allow(non_snake_case)] #[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
36pub struct HealthCheckResponse {
37 pub burst_engine: bool,
38 pub connected_agents: Option<i32>,
39 pub influxdb_availability: bool,
40 pub neuron_count_max: i64,
41 pub synapse_count_max: i64,
42 pub latest_changes_saved_externally: bool,
43 pub genome_availability: bool,
44 pub genome_validity: Option<bool>,
45 pub brain_readiness: bool,
46 pub feagi_session: Option<i64>,
47 pub fitness: Option<f64>,
48 pub cortical_area_count: Option<i32>,
49 pub neuron_count: Option<i64>,
50 pub memory_neuron_count: Option<i64>,
51 pub regular_neuron_count: Option<i64>,
52 pub synapse_count: Option<i64>,
53 pub estimated_brain_size_in_MB: Option<f64>,
54 pub genome_num: Option<i32>,
55 pub genome_timestamp: Option<i64>,
56 pub simulation_timestep: Option<f64>,
57 pub memory_area_stats: Option<HashMap<String, HashMap<String, serde_json::Value>>>,
58 pub amalgamation_pending: Option<HashMap<String, serde_json::Value>>,
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub brain_regions_hash: Option<u64>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub cortical_areas_hash: Option<u64>,
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub brain_geometry_hash: Option<u64>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub morphologies_hash: Option<u64>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub cortical_mappings_hash: Option<u64>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub agent_data_hash: Option<u64>,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub brain_regions_root: Option<String>,
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub fatigue: Option<FatigueInfo>,
83}
84
85#[utoipa::path(
91 get,
92 path = "/v1/system/health_check",
93 responses(
94 (status = 200, description = "System health retrieved successfully", body = HealthCheckResponse),
95 (status = 500, description = "Internal server error")
96 ),
97 tag = "system"
98)]
99pub async fn get_health_check(
100 State(state): State<ApiState>,
101) -> ApiResult<Json<HealthCheckResponse>> {
102 let analytics_service = state.analytics_service.as_ref();
103
104 let health = analytics_service
106 .get_system_health()
107 .await
108 .map_err(|e| ApiError::internal(format!("Failed to get system health: {}", e)))?;
109
110 let runtime_status = state.runtime_service.get_status().await.ok();
112 let burst_engine_active = runtime_status
113 .as_ref()
114 .map(|status| status.is_running)
115 .unwrap_or(false);
116
117 let _burst_count = state.runtime_service.get_burst_count().await.ok();
118
119 let connected_agents = if let Some(agent_service) = state.agent_service.as_ref() {
121 agent_service
122 .list_agents()
123 .await
124 .ok()
125 .map(|agents| agents.len() as i32)
126 } else {
127 None
128 };
129
130 let synapse_count = analytics_service
132 .get_total_synapse_count()
133 .await
134 .ok()
135 .map(|count| count as i64);
136
137 let regular_neuron_count = analytics_service
139 .get_regular_neuron_count()
140 .await
141 .ok()
142 .map(|count| count as i64);
143
144 let memory_neuron_count = analytics_service
145 .get_memory_neuron_count()
146 .await
147 .ok()
148 .map(|count| count as i64);
149
150 let genome_info = state.genome_service.get_genome_info().await.ok();
152
153 let runtime_timestep = runtime_status.as_ref().map(|status| {
155 if status.frequency_hz > 0.0 {
156 1.0 / status.frequency_hz
157 } else {
158 0.0
159 }
160 });
161 let simulation_timestep =
162 runtime_timestep.or_else(|| genome_info.as_ref().map(|info| info.simulation_timestep));
163 let genome_num = genome_info.as_ref().and_then(|info| info.genome_num);
164 let genome_timestamp = genome_info.as_ref().and_then(|info| info.genome_timestamp);
165
166 #[allow(non_snake_case)] let estimated_brain_size_in_MB = {
170 let neuron_bytes = health.neuron_count * 64;
171 let synapse_bytes = synapse_count.unwrap_or(0) as usize * 16;
172 let metadata_bytes = health.cortical_area_count * 512; let total_bytes = neuron_bytes + synapse_bytes + metadata_bytes;
174 Some((total_bytes as f64) / (1024.0 * 1024.0))
175 };
176
177 let neuron_count_max = health.neuron_capacity as i64;
179 let synapse_count_max = health.synapse_capacity as i64;
180
181 let influxdb_availability = false; let latest_changes_saved_externally = false; let genome_availability = health.cortical_area_count > 0;
185 let genome_validity = Some(health.brain_readiness);
186
187 let feagi_session = Some(state.feagi_session_timestamp);
189
190 let fitness = None; let (memory_area_stats, memory_neuron_count_from_cache) = state
199 .memory_stats_cache
200 .as_ref()
201 .map(|cache| {
202 let snapshot = feagi_npu_plasticity::memory_stats_cache::get_stats_snapshot(cache);
203 let total = snapshot
204 .values()
205 .map(|s| s.neuron_count as i64)
206 .sum::<i64>();
207 let per_area = snapshot
208 .into_iter()
209 .map(|(name, stats)| {
210 let mut inner_map = HashMap::new();
211 inner_map.insert(
212 "neuron_count".to_string(),
213 serde_json::json!(stats.neuron_count),
214 );
215 inner_map.insert(
216 "created_total".to_string(),
217 serde_json::json!(stats.created_total),
218 );
219 inner_map.insert(
220 "deleted_total".to_string(),
221 serde_json::json!(stats.deleted_total),
222 );
223 inner_map.insert(
224 "last_updated".to_string(),
225 serde_json::json!(stats.last_updated),
226 );
227 (name, inner_map)
228 })
229 .collect::<HashMap<String, HashMap<String, serde_json::Value>>>();
230 (Some(per_area), Some(total))
231 })
232 .unwrap_or((None, None));
233
234 let memory_neuron_count = memory_neuron_count_from_cache.or(memory_neuron_count);
236
237 let amalgamation_pending = state.amalgamation_state.read().pending.as_ref().map(|p| {
242 let v = amalgamation::pending_summary_to_health_json(&p.summary);
243 v.as_object()
244 .cloned()
245 .unwrap_or_default()
246 .into_iter()
247 .collect::<HashMap<String, serde_json::Value>>()
248 });
249
250 #[cfg(feature = "services")]
252 let brain_regions_root = feagi_brain_development::ConnectomeManager::instance()
253 .read()
254 .get_root_region_id();
255 #[cfg(not(feature = "services"))]
256 let brain_regions_root = None; #[cfg(feature = "services")]
261 let fatigue = {
262 use feagi_state_manager::StateManager;
263 match StateManager::instance().try_read() {
265 Some(state_manager) => {
266 let core_state = state_manager.get_core_state();
267 Some(FatigueInfo {
268 fatigue_index: Some(core_state.get_fatigue_index()),
269 fatigue_active: Some(core_state.is_fatigue_active()),
270 regular_neuron_util: Some(core_state.get_regular_neuron_util()),
271 memory_neuron_util: Some(core_state.get_memory_neuron_util()),
272 synapse_util: Some(core_state.get_synapse_util()),
273 })
274 }
275 None => {
276 tracing::warn!(target: "feagi-api", "StateManager is locked, cannot read fatigue data");
278 None
279 }
280 }
281 };
282 #[cfg(not(feature = "services"))]
283 let fatigue = {
284 tracing::debug!(target: "feagi-api", "Services feature not enabled, fatigue data unavailable");
285 None
286 };
287
288 let (
289 brain_regions_hash,
290 cortical_areas_hash,
291 brain_geometry_hash,
292 morphologies_hash,
293 cortical_mappings_hash,
294 agent_data_hash,
295 ) = {
296 let state_manager = feagi_state_manager::StateManager::instance();
297 let state_manager = state_manager.read();
298 (
299 Some(state_manager.get_brain_regions_hash()),
300 Some(state_manager.get_cortical_areas_hash()),
301 Some(state_manager.get_brain_geometry_hash()),
302 Some(state_manager.get_morphologies_hash()),
303 Some(state_manager.get_cortical_mappings_hash()),
304 Some(state_manager.get_agent_data_hash()),
305 )
306 };
307
308 Ok(Json(HealthCheckResponse {
309 burst_engine: burst_engine_active,
310 connected_agents,
311 influxdb_availability,
312 neuron_count_max,
313 synapse_count_max,
314 latest_changes_saved_externally,
315 genome_availability,
316 genome_validity,
317 brain_readiness: health.brain_readiness,
318 feagi_session,
319 fitness,
320 cortical_area_count: Some(health.cortical_area_count as i32),
321 neuron_count: Some(health.neuron_count as i64),
322 memory_neuron_count,
323 regular_neuron_count,
324 synapse_count,
325 estimated_brain_size_in_MB,
326 genome_num,
327 genome_timestamp,
328 simulation_timestep,
329 memory_area_stats,
330 amalgamation_pending,
331 brain_regions_hash,
332 cortical_areas_hash,
333 brain_geometry_hash,
334 morphologies_hash,
335 cortical_mappings_hash,
336 agent_data_hash,
337 brain_regions_root, fatigue,
339 }))
340}
341
342#[utoipa::path(
344 get,
345 path = "/v1/system/cortical_area_visualization_skip_rate",
346 responses(
347 (status = 200, description = "Skip rate retrieved successfully", body = i32),
348 (status = 500, description = "Internal server error")
349 ),
350 tag = "system"
351)]
352pub async fn get_cortical_area_visualization_skip_rate(
353 State(_state): State<ApiState>,
354) -> ApiResult<Json<i32>> {
355 Ok(Json(1))
358}
359
360#[utoipa::path(
362 put,
363 path = "/v1/system/cortical_area_visualization_skip_rate",
364 request_body = i32,
365 responses(
366 (status = 200, description = "Skip rate updated successfully"),
367 (status = 500, description = "Internal server error")
368 ),
369 tag = "system"
370)]
371pub async fn set_cortical_area_visualization_skip_rate(
372 State(_state): State<ApiState>,
373 Json(skip_rate): Json<i32>,
374) -> ApiResult<Json<serde_json::Value>> {
375 Ok(Json(serde_json::json!({
377 "message": format!("Skip rate set to {}", skip_rate)
378 })))
379}
380
381#[utoipa::path(
383 get,
384 path = "/v1/system/cortical_area_visualization_suppression_threshold",
385 responses(
386 (status = 200, description = "Threshold retrieved successfully", body = i32),
387 (status = 500, description = "Internal server error")
388 ),
389 tag = "system"
390)]
391pub async fn get_cortical_area_visualization_suppression_threshold(
392 State(_state): State<ApiState>,
393) -> ApiResult<Json<i32>> {
394 Ok(Json(0))
397}
398
399#[utoipa::path(
401 put,
402 path = "/v1/system/cortical_area_visualization_suppression_threshold",
403 request_body = i32,
404 responses(
405 (status = 200, description = "Threshold updated successfully"),
406 (status = 500, description = "Internal server error")
407 ),
408 tag = "system"
409)]
410pub async fn set_cortical_area_visualization_suppression_threshold(
411 State(_state): State<ApiState>,
412 Json(threshold): Json<i32>,
413) -> ApiResult<Json<serde_json::Value>> {
414 Ok(Json(serde_json::json!({
416 "message": format!("Suppression threshold set to {}", threshold)
417 })))
418}
419
420#[utoipa::path(
426 get,
427 path = "/v1/system/version",
428 tag = "system",
429 responses(
430 (status = 200, description = "Version string", body = String)
431 )
432)]
433pub async fn get_version(State(_state): State<ApiState>) -> ApiResult<Json<String>> {
434 Ok(Json(env!("CARGO_PKG_VERSION").to_string()))
435}
436
437#[utoipa::path(
439 get,
440 path = "/v1/system/versions",
441 tag = "system",
442 responses(
443 (status = 200, description = "Version information", body = HashMap<String, String>)
444 )
445)]
446pub async fn get_versions(
447 State(state): State<ApiState>,
448) -> ApiResult<Json<HashMap<String, String>>> {
449 match state.system_service.get_version().await {
452 Ok(version_info) => {
453 let mut versions = version_info.crates.clone();
454
455 versions.insert("rust".to_string(), version_info.rust_version);
457 versions.insert("build_timestamp".to_string(), version_info.build_timestamp);
458
459 Ok(Json(versions))
460 }
461 Err(e) => {
462 tracing::warn!(
464 "Failed to get version from system service: {}, using fallback",
465 e
466 );
467 let mut versions = HashMap::new();
468 versions.insert(
469 "error".to_string(),
470 "system service unavailable".to_string(),
471 );
472 Ok(Json(versions))
473 }
474 }
475}
476
477#[utoipa::path(
479 get,
480 path = "/v1/system/configuration",
481 tag = "system",
482 responses(
483 (status = 200, description = "System configuration", body = HashMap<String, serde_json::Value>)
484 )
485)]
486pub async fn get_configuration(
487 State(state): State<ApiState>,
488) -> ApiResult<Json<HashMap<String, serde_json::Value>>> {
489 let health = state
491 .analytics_service
492 .get_system_health()
493 .await
494 .map_err(|e| ApiError::internal(format!("Failed to get system health: {}", e)))?;
495
496 let mut config = HashMap::new();
497 config.insert("api_host".to_string(), serde_json::json!("0.0.0.0"));
498 config.insert("api_port".to_string(), serde_json::json!(8000));
499 config.insert(
501 "max_neurons".to_string(),
502 serde_json::json!(health.neuron_capacity),
503 );
504 config.insert(
505 "max_synapses".to_string(),
506 serde_json::json!(health.synapse_capacity),
507 );
508
509 Ok(Json(config))
510}
511
512#[utoipa::path(
514 get,
515 path = "/v1/system/user_preferences",
516 tag = "system",
517 responses(
518 (status = 200, description = "User preferences", body = HashMap<String, serde_json::Value>)
519 )
520)]
521pub async fn get_user_preferences(
522 State(_state): State<ApiState>,
523) -> ApiResult<Json<HashMap<String, serde_json::Value>>> {
524 let mut prefs = HashMap::new();
525 prefs.insert("adv_mode".to_string(), serde_json::json!(false));
526 prefs.insert("ui_magnification".to_string(), serde_json::json!(1.0));
527 prefs.insert(
528 "auto_pns_area_creation".to_string(),
529 serde_json::json!(true),
530 );
531
532 Ok(Json(prefs))
533}
534
535#[utoipa::path(
537 put,
538 path = "/v1/system/user_preferences",
539 tag = "system",
540 responses(
541 (status = 200, description = "Preferences updated", body = HashMap<String, String>)
542 )
543)]
544pub async fn put_user_preferences(
545 State(_state): State<ApiState>,
546 Json(_prefs): Json<HashMap<String, serde_json::Value>>,
547) -> ApiResult<Json<HashMap<String, String>>> {
548 Ok(Json(HashMap::from([(
549 "message".to_string(),
550 "User preferences updated successfully".to_string(),
551 )])))
552}
553
554#[utoipa::path(
556 get,
557 path = "/v1/system/cortical_area_types",
558 tag = "system",
559 responses(
560 (status = 200, description = "Cortical area types", body = Vec<String>)
561 )
562)]
563pub async fn get_cortical_area_types_list(
564 State(_state): State<ApiState>,
565) -> ApiResult<Json<Vec<String>>> {
566 Ok(Json(vec![
567 "Sensory".to_string(),
568 "Motor".to_string(),
569 "Custom".to_string(),
570 "Memory".to_string(),
571 "Core".to_string(),
572 ]))
573}
574
575#[utoipa::path(
577 post,
578 path = "/v1/system/enable_visualization_fq_sampler",
579 tag = "system",
580 responses(
581 (status = 200, description = "FQ sampler enabled", body = HashMap<String, String>)
582 )
583)]
584pub async fn post_enable_visualization_fq_sampler(
585 State(state): State<ApiState>,
586) -> ApiResult<Json<HashMap<String, String>>> {
587 let runtime_service = state.runtime_service.as_ref();
588
589 runtime_service
590 .set_fcl_sampler_config(None, Some(1))
591 .await
592 .map_err(|e| ApiError::internal(format!("Failed to enable FQ sampler: {}", e)))?;
593
594 Ok(Json(HashMap::from([(
595 "message".to_string(),
596 "Visualization FQ sampler enabled".to_string(),
597 )])))
598}
599
600#[utoipa::path(
602 post,
603 path = "/v1/system/disable_visualization_fq_sampler",
604 tag = "system",
605 responses(
606 (status = 200, description = "FQ sampler disabled", body = HashMap<String, String>)
607 )
608)]
609pub async fn post_disable_visualization_fq_sampler(
610 State(state): State<ApiState>,
611) -> ApiResult<Json<HashMap<String, String>>> {
612 let runtime_service = state.runtime_service.as_ref();
613
614 runtime_service
615 .set_fcl_sampler_config(None, Some(0))
616 .await
617 .map_err(|e| ApiError::internal(format!("Failed to disable FQ sampler: {}", e)))?;
618
619 Ok(Json(HashMap::from([(
620 "message".to_string(),
621 "Visualization FQ sampler disabled".to_string(),
622 )])))
623}
624
625#[utoipa::path(
627 get,
628 path = "/v1/system/fcl_status",
629 tag = "system",
630 responses(
631 (status = 200, description = "FCL status", body = HashMap<String, serde_json::Value>)
632 )
633)]
634pub async fn get_fcl_status_system(
635 State(state): State<ApiState>,
636) -> ApiResult<Json<HashMap<String, serde_json::Value>>> {
637 let runtime_service = state.runtime_service.as_ref();
638
639 let (frequency, consumer) = runtime_service
640 .get_fcl_sampler_config()
641 .await
642 .map_err(|e| ApiError::internal(format!("Failed to get FCL status: {}", e)))?;
643
644 let mut response = HashMap::new();
645 response.insert("available".to_string(), serde_json::json!(true));
646 response.insert("frequency".to_string(), serde_json::json!(frequency));
647 response.insert("consumer".to_string(), serde_json::json!(consumer));
648 response.insert("enabled".to_string(), serde_json::json!(consumer > 0));
649
650 Ok(Json(response))
651}
652
653#[utoipa::path(
655 post,
656 path = "/v1/system/fcl_reset",
657 tag = "system",
658 responses(
659 (status = 200, description = "FCL reset", body = HashMap<String, String>)
660 )
661)]
662pub async fn post_fcl_reset_system(
663 State(_state): State<ApiState>,
664) -> ApiResult<Json<HashMap<String, String>>> {
665 tracing::info!(target: "feagi-api", "FCL reset requested");
666
667 Ok(Json(HashMap::from([(
668 "message".to_string(),
669 "FCL reset successfully".to_string(),
670 )])))
671}
672
673#[utoipa::path(
675 get,
676 path = "/v1/system/processes",
677 tag = "system",
678 responses(
679 (status = 200, description = "Active processes", body = HashMap<String, serde_json::Value>)
680 )
681)]
682pub async fn get_processes(
683 State(state): State<ApiState>,
684) -> ApiResult<Json<HashMap<String, serde_json::Value>>> {
685 let runtime_service = state.runtime_service.as_ref();
686
687 let status = runtime_service
688 .get_status()
689 .await
690 .map_err(|e| ApiError::internal(format!("Failed to get processes: {}", e)))?;
691
692 let mut processes = HashMap::new();
693 processes.insert(
694 "burst_engine".to_string(),
695 serde_json::json!({
696 "active": status.is_running,
697 "paused": status.is_paused
698 }),
699 );
700 processes.insert(
701 "api_server".to_string(),
702 serde_json::json!({"active": true}),
703 );
704
705 Ok(Json(processes))
706}
707
708#[utoipa::path(
710 get,
711 path = "/v1/system/unique_logs",
712 tag = "system",
713 responses(
714 (status = 200, description = "Unique logs", body = HashMap<String, Vec<String>>)
715 )
716)]
717pub async fn get_unique_logs(
718 State(_state): State<ApiState>,
719) -> ApiResult<Json<HashMap<String, Vec<String>>>> {
720 let mut response = HashMap::new();
721 response.insert("logs".to_string(), Vec::new());
722
723 Ok(Json(response))
724}
725
726#[utoipa::path(
728 post,
729 path = "/v1/system/logs",
730 tag = "system",
731 responses(
732 (status = 200, description = "Log config updated", body = HashMap<String, String>)
733 )
734)]
735pub async fn post_logs(
736 State(_state): State<ApiState>,
737 Json(_config): Json<HashMap<String, serde_json::Value>>,
738) -> ApiResult<Json<HashMap<String, String>>> {
739 Ok(Json(HashMap::from([(
740 "message".to_string(),
741 "Log configuration updated".to_string(),
742 )])))
743}
744
745#[utoipa::path(
747 get,
748 path = "/v1/system/beacon/subscribers",
749 tag = "system",
750 responses(
751 (status = 200, description = "Beacon subscribers", body = Vec<String>)
752 )
753)]
754pub async fn get_beacon_subscribers(
755 State(_state): State<ApiState>,
756) -> ApiResult<Json<Vec<String>>> {
757 Ok(Json(Vec::new()))
758}
759
760#[utoipa::path(
762 post,
763 path = "/v1/system/beacon/subscribe",
764 tag = "system",
765 responses(
766 (status = 200, description = "Subscribed", body = HashMap<String, String>)
767 )
768)]
769pub async fn post_beacon_subscribe(
770 State(_state): State<ApiState>,
771 Json(_request): Json<HashMap<String, String>>,
772) -> ApiResult<Json<HashMap<String, String>>> {
773 Ok(Json(HashMap::from([(
774 "message".to_string(),
775 "Subscribed to beacon".to_string(),
776 )])))
777}
778
779#[utoipa::path(
781 delete,
782 path = "/v1/system/beacon/unsubscribe",
783 tag = "system",
784 responses(
785 (status = 200, description = "Unsubscribed", body = HashMap<String, String>)
786 )
787)]
788pub async fn delete_beacon_unsubscribe(
789 State(_state): State<ApiState>,
790 Json(_request): Json<HashMap<String, String>>,
791) -> ApiResult<Json<HashMap<String, String>>> {
792 Ok(Json(HashMap::from([(
793 "message".to_string(),
794 "Unsubscribed from beacon".to_string(),
795 )])))
796}
797
798#[utoipa::path(
800 get,
801 path = "/v1/system/global_activity_visualization",
802 tag = "system",
803 responses(
804 (status = 200, description = "Global activity viz status", body = HashMap<String, serde_json::Value>)
805 )
806)]
807pub async fn get_global_activity_visualization(
808 State(_state): State<ApiState>,
809) -> ApiResult<Json<HashMap<String, serde_json::Value>>> {
810 let mut response = HashMap::new();
811 response.insert("enabled".to_string(), serde_json::json!(false));
812 response.insert("frequency_hz".to_string(), serde_json::json!(30.0));
813
814 Ok(Json(response))
815}
816
817#[utoipa::path(
819 put,
820 path = "/v1/system/global_activity_visualization",
821 tag = "system",
822 responses(
823 (status = 200, description = "Configured", body = HashMap<String, String>)
824 )
825)]
826pub async fn put_global_activity_visualization(
827 State(_state): State<ApiState>,
828 Json(_config): Json<HashMap<String, serde_json::Value>>,
829) -> ApiResult<Json<HashMap<String, String>>> {
830 Ok(Json(HashMap::from([(
831 "message".to_string(),
832 "Global activity visualization configured".to_string(),
833 )])))
834}
835
836#[utoipa::path(
838 post,
839 path = "/v1/system/circuit_library_path",
840 tag = "system",
841 responses(
842 (status = 200, description = "Path set", body = HashMap<String, String>)
843 )
844)]
845pub async fn post_circuit_library_path(
846 State(_state): State<ApiState>,
847 Json(_request): Json<HashMap<String, String>>,
848) -> ApiResult<Json<HashMap<String, String>>> {
849 Ok(Json(HashMap::from([(
850 "message".to_string(),
851 "Circuit library path updated".to_string(),
852 )])))
853}
854
855#[utoipa::path(
857 get,
858 path = "/v1/system/db/influxdb/test",
859 tag = "system",
860 responses(
861 (status = 200, description = "Test result", body = HashMap<String, bool>)
862 )
863)]
864pub async fn get_influxdb_test(
865 State(_state): State<ApiState>,
866) -> ApiResult<Json<HashMap<String, bool>>> {
867 let mut response = HashMap::new();
868 response.insert("connected".to_string(), false);
869 response.insert("available".to_string(), false);
870
871 Ok(Json(response))
872}
873
874#[utoipa::path(
876 post,
877 path = "/v1/system/register",
878 tag = "system",
879 responses(
880 (status = 200, description = "Registered", body = HashMap<String, String>)
881 )
882)]
883pub async fn post_register_system(
884 State(_state): State<ApiState>,
885 Json(_request): Json<HashMap<String, serde_json::Value>>,
886) -> ApiResult<Json<HashMap<String, String>>> {
887 Ok(Json(HashMap::from([(
888 "message".to_string(),
889 "System component registered".to_string(),
890 )])))
891}