use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum BrowserEngine {
#[default]
Chrome,
Lightpanda,
}
impl BrowserEngine {
pub fn as_arg(&self) -> &'static str {
match self {
BrowserEngine::Chrome => "chrome",
BrowserEngine::Lightpanda => "lightpanda",
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BrowserConfig {
pub binary_path: Option<PathBuf>,
pub engine: BrowserEngine,
pub headless: bool,
pub timeout_ms: u64,
}
impl From<&limit_llm::BrowserConfigSection> for BrowserConfig {
fn from(section: &limit_llm::BrowserConfigSection) -> Self {
let engine = match section.engine.to_lowercase().as_str() {
"lightpanda" => BrowserEngine::Lightpanda,
_ => BrowserEngine::Chrome,
};
Self {
binary_path: section.binary_path.clone(),
engine,
headless: section.headless,
timeout_ms: section.timeout_ms,
}
}
}
impl Default for BrowserConfig {
fn default() -> Self {
Self {
binary_path: None,
engine: BrowserEngine::default(),
headless: true,
timeout_ms: 30_000,
}
}
}
impl BrowserConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_binary_path(mut self, path: PathBuf) -> Self {
self.binary_path = Some(path);
self
}
pub fn with_engine(mut self, engine: BrowserEngine) -> Self {
self.engine = engine;
self
}
pub fn with_headless(mut self, headless: bool) -> Self {
self.headless = headless;
self
}
pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = timeout_ms;
self
}
pub fn binary(&self) -> &std::path::Path {
self.binary_path
.as_deref()
.unwrap_or(std::path::Path::new("agent-browser"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_browser_engine_default() {
let engine = BrowserEngine::default();
assert_eq!(engine, BrowserEngine::Chrome);
}
#[test]
fn test_browser_engine_as_arg() {
assert_eq!(BrowserEngine::Chrome.as_arg(), "chrome");
assert_eq!(BrowserEngine::Lightpanda.as_arg(), "lightpanda");
}
#[test]
fn test_browser_config_default() {
let config = BrowserConfig::default();
assert!(config.binary_path.is_none());
assert_eq!(config.engine, BrowserEngine::Chrome);
assert!(config.headless);
assert_eq!(config.timeout_ms, 30_000);
}
#[test]
fn test_browser_config_builder() {
let config = BrowserConfig::new()
.with_engine(BrowserEngine::Lightpanda)
.with_headless(false)
.with_timeout_ms(60_000);
assert_eq!(config.engine, BrowserEngine::Lightpanda);
assert!(!config.headless);
assert_eq!(config.timeout_ms, 60_000);
}
#[test]
fn test_browser_config_binary() {
let config = BrowserConfig::default();
assert_eq!(config.binary().to_str().unwrap(), "agent-browser");
let config =
BrowserConfig::new().with_binary_path(PathBuf::from("/usr/local/bin/agent-browser"));
assert_eq!(
config.binary().to_str().unwrap(),
"/usr/local/bin/agent-browser"
);
}
#[test]
fn test_from_browser_config_section() {
let section = limit_llm::BrowserConfigSection {
enabled: true,
binary_path: Some(PathBuf::from("/custom/agent-browser")),
engine: "lightpanda".to_string(),
headless: false,
timeout_ms: 60_000,
};
let config = BrowserConfig::from(§ion);
assert_eq!(
config.binary_path,
Some(PathBuf::from("/custom/agent-browser"))
);
assert_eq!(config.engine, BrowserEngine::Lightpanda);
assert!(!config.headless);
assert_eq!(config.timeout_ms, 60_000);
}
#[test]
fn test_from_browser_config_section_default() {
let section = limit_llm::BrowserConfigSection::default();
let config = BrowserConfig::from(§ion);
assert!(config.binary_path.is_none());
assert_eq!(config.engine, BrowserEngine::Chrome);
assert!(config.headless);
assert_eq!(config.timeout_ms, 30_000);
}
}