diff --git a/README.md b/README.md index 6fab7b0..2158bb6 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,39 @@ google-patent-cli config # Set custom browser path google-patent-cli config --set-browser "/path/to/chrome" ``` - + +### Configuration File + +The configuration file is located at: +- **Linux/macOS**: `~/.config/google-patent-cli/config.toml` +- **Windows**: `%APPDATA%\google-patent-cli\config.toml` + +You can manually edit the TOML file to configure additional Chrome arguments: + +```toml +# Path to Chrome/Chromium executable +browser_path = "/usr/bin/google-chrome" + +# Additional Chrome arguments (useful for Docker/CI environments) +chrome_args = [ + "--no-sandbox", + "--disable-setuid-sandbox" +] +``` + +### Docker/DevContainer Environment + +When running in Docker containers or devcontainers, Chrome requires additional flags to work properly. You can configure these flags via `chrome_args` in your config file: + +```toml +chrome_args = [ + "--no-sandbox", + "--disable-setuid-sandbox", + "--disable-gpu" +] +``` + +Alternatively, set the `CI=true` environment variable to automatically add these flags. + ## License MIT diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 299ff1f..835c037 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -141,9 +141,15 @@ pub async fn run_app(cli: Cli) -> Result<()> { } let config = Config::load()?; - let searcher = - PatentSearcher::new(config.browser_path, !args.head, args.debug, args.verbose) - .await?; + let chrome_args = config.chrome_args.clone(); + let searcher = PatentSearcher::new( + config.browser_path, + !args.head, + args.debug, + args.verbose, + chrome_args, + ) + .await?; let options = SearchOptions { query: args.query, @@ -162,9 +168,15 @@ pub async fn run_app(cli: Cli) -> Result<()> { } Commands::Fetch { args } => { let config = Config::load()?; - let searcher = - PatentSearcher::new(config.browser_path, !args.head, args.debug, args.verbose) - .await?; + let chrome_args = config.chrome_args.clone(); + let searcher = PatentSearcher::new( + config.browser_path, + !args.head, + args.debug, + args.verbose, + chrome_args, + ) + .await?; if args.raw { let html = searcher.get_raw_html(&args.patent_id, args.language.as_deref()).await?; diff --git a/src/core/cdp/browser.rs b/src/core/cdp/browser.rs index 1e1b0c2..cae7da8 100644 --- a/src/core/cdp/browser.rs +++ b/src/core/cdp/browser.rs @@ -335,11 +335,17 @@ pub struct BrowserManager { browser_path: Option, headless: bool, debug: bool, + chrome_args: Vec, state: Arc>, } impl BrowserManager { - pub fn new(browser_path: Option, headless: bool, debug: bool) -> Self { + pub fn new( + browser_path: Option, + headless: bool, + debug: bool, + chrome_args: Vec, + ) -> Self { let state = Arc::new(Mutex::new(BrowserState { browser: None, last_used: Instant::now() })); // Spawn the inactivity monitor task @@ -354,7 +360,7 @@ impl BrowserManager { } }); - Self { browser_path, headless, debug, state } + Self { browser_path, headless, debug, chrome_args, state } } pub async fn get_browser(&self) -> Result> { @@ -369,6 +375,13 @@ impl BrowserManager { if std::env::var("CI").is_ok() { args.push("--disable-gpu"); + args.push("--no-sandbox"); + args.push("--disable-setuid-sandbox"); + } + + // Add custom Chrome args from config + for arg in &self.chrome_args { + args.push(arg.as_str()); } let browser_path = self.browser_path.clone(); diff --git a/src/core/config.rs b/src/core/config.rs index 348a0e9..4db0675 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -7,6 +7,8 @@ use std::path::{Path, PathBuf}; #[derive(Debug, Serialize, Deserialize, Default, Clone)] pub struct Config { pub browser_path: Option, + #[serde(default)] + pub chrome_args: Vec, } impl Config { diff --git a/src/core/patent_search.rs b/src/core/patent_search.rs index a306154..bb9f852 100644 --- a/src/core/patent_search.rs +++ b/src/core/patent_search.rs @@ -59,8 +59,9 @@ impl PatentSearcher { headless: bool, debug: bool, verbose: bool, + chrome_args: Vec, ) -> Result { - let browser_manager = BrowserManager::new(browser_path, headless, debug); + let browser_manager = BrowserManager::new(browser_path, headless, debug, chrome_args); Ok(Self { browser_manager, verbose }) } diff --git a/src/mcp/mod.rs b/src/mcp/mod.rs index 7e91be9..2904b08 100644 --- a/src/mcp/mod.rs +++ b/src/mcp/mod.rs @@ -174,7 +174,8 @@ impl ServerHandler for PatentHandler { /// Run the MCP server over stdio pub async fn run() -> anyhow::Result<()> { let config = Config::load()?; - let searcher = PatentSearcher::new(config.browser_path, true, false, false) + let chrome_args = config.chrome_args.clone(); + let searcher = PatentSearcher::new(config.browser_path, true, false, false, chrome_args) .await .map_err(|e| anyhow::anyhow!("Failed to create PatentSearcher: {}", e))?; let handler = PatentHandler::new(Arc::new(searcher));