ai_agent/bridge/
env_less_bridge_config.rs1use serde::{Deserialize, Serialize};
6use std::sync::OnceLock;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub struct EnvLessBridgeConfig {
16 pub init_retry_max_attempts: u32,
18 pub init_retry_base_delay_ms: u64,
20 pub init_retry_jitter_fraction: f64,
22 pub init_retry_max_delay_ms: u64,
24 pub http_timeout_ms: u64,
26 pub uuid_dedup_buffer_size: u32,
28 pub heartbeat_interval_ms: u64,
30 pub heartbeat_jitter_fraction: f64,
32 pub token_refresh_buffer_ms: u64,
34 pub teardown_archive_timeout_ms: u64,
36 pub connect_timeout_ms: u64,
38 pub min_version: &'static str,
40 pub should_show_app_upgrade_message: bool,
42}
43
44pub const DEFAULT_ENV_LESS_BRIDGE_CONFIG: EnvLessBridgeConfig = EnvLessBridgeConfig {
46 init_retry_max_attempts: 3,
47 init_retry_base_delay_ms: 500,
48 init_retry_jitter_fraction: 0.25,
49 init_retry_max_delay_ms: 4000,
50 http_timeout_ms: 10_000,
51 uuid_dedup_buffer_size: 2000,
52 heartbeat_interval_ms: 20_000,
53 heartbeat_jitter_fraction: 0.1,
54 token_refresh_buffer_ms: 300_000,
55 teardown_archive_timeout_ms: 1500,
56 connect_timeout_ms: 15_000,
57 min_version: &"0.0.0",
58 should_show_app_upgrade_message: false,
59};
60
61static ENV_LESS_BRIDGE_CONFIG: OnceLock<EnvLessBridgeConfig> = OnceLock::new();
66
67fn get_current_version() -> String {
69 env!("CARGO_PKG_VERSION").to_string()
70}
71
72fn version_lt(a: &str, b: &str) -> bool {
74 let a_parts: Vec<u32> = a.split('.').filter_map(|s| s.parse().ok()).collect();
75 let b_parts: Vec<u32> = b.split('.').filter_map(|s| s.parse().ok()).collect();
76 for (av, bv) in a_parts.iter().zip(b_parts.iter()) {
77 if av < bv {
78 return true;
79 }
80 if av > bv {
81 return false;
82 }
83 }
84 false
85}
86
87pub async fn get_env_less_bridge_config() -> EnvLessBridgeConfig {
90 ENV_LESS_BRIDGE_CONFIG
91 .get_or_init(|| DEFAULT_ENV_LESS_BRIDGE_CONFIG.clone())
92 .clone()
93}
94
95pub async fn check_env_less_bridge_min_version() -> Option<String> {
98 let cfg = get_env_less_bridge_config().await;
99 if !cfg.min_version.is_empty() && version_lt(&get_current_version(), &cfg.min_version) {
100 return Some(format!(
101 "Your version of AI Code ({}) is too old for Remote Control.\n\
102 Version {} or higher is required. Run `ai update` to update.",
103 get_current_version(),
104 cfg.min_version
105 ));
106 }
107 None
108}
109
110pub async fn should_show_app_upgrade_message() -> bool {
113 if !crate::bridge_enabled::is_env_less_bridge_enabled() {
115 return false;
116 }
117 let cfg = get_env_less_bridge_config().await;
118 cfg.should_show_app_upgrade_message
119}