agent_first_http/host/
bootstrap.rs1use std::path::PathBuf;
6
7use crate::host::listener::AppState;
8use crate::shared::error::Error;
9
10#[derive(Debug, Clone)]
13pub struct HostArgs {
14 pub listen: String,
15 pub profile: ProfileChoice,
17 pub display: DisplayMode,
18 pub takeover: Takeover,
19 pub display_quality: u8,
23 pub browser: BrowserChoice,
24 pub browser_bin: Option<PathBuf>,
25 pub token: Option<String>,
26 pub ops_enabled: bool,
27 pub health_enabled: bool,
28 pub health_public: HealthPublic,
29 pub engine_envs: Vec<(String, String)>,
34 pub browser_args: Vec<String>,
41 pub proxy: Option<String>,
48 pub recent_requests_cap: usize,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub enum ProfileChoice {
55 Ephemeral,
56 Persistent(String),
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum DisplayMode {
61 Headless,
62 Headful,
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum Takeover {
67 Off,
68 KasmVnc,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Default)]
72pub enum BrowserChoice {
73 #[default]
74 Auto,
75 Chromium,
76 Chrome,
77 ChromeShell,
78 FingerprintChromium,
79 Edge,
80 Brave,
81 Lightpanda,
82 Camoufox,
86}
87
88impl std::str::FromStr for BrowserChoice {
89 type Err = String;
90
91 fn from_str(s: &str) -> Result<Self, Self::Err> {
92 Ok(match s {
93 "auto" => Self::Auto,
94 "chromium" => Self::Chromium,
95 "chrome" => Self::Chrome,
96 "chrome_shell" | "chrome-headless-shell" => Self::ChromeShell,
97 "fingerprint_chromium" | "fingerprint-chromium" => Self::FingerprintChromium,
98 "edge" => Self::Edge,
99 "brave" => Self::Brave,
100 "lightpanda" => Self::Lightpanda,
101 "camoufox" => Self::Camoufox,
102 other => return Err(format!("unknown {other:?}")),
103 })
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108pub enum HealthPublic {
109 Off,
110 Minimal,
111}
112
113pub fn install_rustls_provider() {
114 let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
115}
116
117pub async fn run(args: HostArgs) -> Result<(), Error> {
120 install_rustls_provider();
121 let state = AppState::launch(&args).await?;
122 state.serve(&args.listen).await
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn browser_choice_default_is_auto() {
131 assert_eq!(BrowserChoice::default(), BrowserChoice::Auto);
132 }
133
134 #[test]
135 fn browser_choice_parses_every_variant_and_aliases() {
136 assert_eq!(
137 "auto".parse::<BrowserChoice>().unwrap(),
138 BrowserChoice::Auto
139 );
140 assert_eq!(
141 "chromium".parse::<BrowserChoice>().unwrap(),
142 BrowserChoice::Chromium
143 );
144 assert_eq!(
145 "chrome".parse::<BrowserChoice>().unwrap(),
146 BrowserChoice::Chrome
147 );
148 assert_eq!(
150 "chrome_shell".parse::<BrowserChoice>().unwrap(),
151 BrowserChoice::ChromeShell
152 );
153 assert_eq!(
154 "chrome-headless-shell".parse::<BrowserChoice>().unwrap(),
155 BrowserChoice::ChromeShell
156 );
157 assert_eq!(
158 "fingerprint_chromium".parse::<BrowserChoice>().unwrap(),
159 BrowserChoice::FingerprintChromium
160 );
161 assert_eq!(
162 "fingerprint-chromium".parse::<BrowserChoice>().unwrap(),
163 BrowserChoice::FingerprintChromium
164 );
165 assert_eq!(
166 "edge".parse::<BrowserChoice>().unwrap(),
167 BrowserChoice::Edge
168 );
169 assert_eq!(
170 "brave".parse::<BrowserChoice>().unwrap(),
171 BrowserChoice::Brave
172 );
173 assert_eq!(
174 "lightpanda".parse::<BrowserChoice>().unwrap(),
175 BrowserChoice::Lightpanda
176 );
177 assert_eq!(
178 "camoufox".parse::<BrowserChoice>().unwrap(),
179 BrowserChoice::Camoufox
180 );
181 }
182
183 #[test]
184 fn browser_choice_rejects_unknown() {
185 let err = "netscape".parse::<BrowserChoice>().unwrap_err();
186 assert!(err.contains("netscape"), "error was {err:?}");
187 }
188}