Release binaries / Build macOS ARM64 (push) Has been cancelled
Release binaries / Build macOS x64 (push) Has been cancelled
Release binaries / Build Linux ARM64 (push) Has been cancelled
Release binaries / Build Linux musl ARM64 (push) Has been cancelled
Release binaries / Build Linux musl x64 (push) Has been cancelled
Release binaries / Build Linux x64 (push) Has been cancelled
Release binaries / Build Windows x64 (push) Has been cancelled
Release binaries / Attach binaries to GitHub Release (push) Has been cancelled
Standalone product rename across the whole repo (issue: project identity): - Binary/package/repo/skill/docs: agent-browser[-stealth] → chrome-use (single binary name `chrome-use`; old aliases agent-browser/abs dropped). - Version: 0.27.0-fork.51 → 1.0.0 (drop the upstream-fork counter). - Native-messaging host: com.agent_browser.connect → com.leeguoo.chrome_use (CLI + ab-connect extension in lockstep — this is a breaking handshake change, extension bumped 0.4.2 → 0.5.0, needs a Web Store republish). - Config dir: ~/.agent-browser → ~/.chrome-use. - README/zh: reframed from "stealth fork of agent-browser" to a standalone product with a small `originally based on vercel-labs/agent-browser` credit. - Kept AGENT_BROWSER_* env vars working (63 vars across the codebase; renaming them would break every existing script/skill for no user-facing gain). Build green, 802 unit tests pass, fmt + clippy clean. Upstream attribution to vercel-labs/agent-browser preserved.
157 lines
4.9 KiB
Rust
157 lines
4.9 KiB
Rust
//! Check the Chrome install: binary path, version, cache dirs, user-data
|
|
//! dir, and the optional lightpanda engine.
|
|
|
|
use std::env;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use super::helpers::which_exists;
|
|
use super::{Check, Status};
|
|
|
|
pub(super) fn check(checks: &mut Vec<Check>) {
|
|
let category = "Chrome";
|
|
|
|
let chrome = crate::native::cdp::chrome::find_chrome();
|
|
match chrome {
|
|
Some(path) => {
|
|
let label = path.display().to_string();
|
|
match query_chrome_version(&path) {
|
|
Some(version) => checks.push(Check::new(
|
|
"chrome.installed",
|
|
category,
|
|
Status::Pass,
|
|
format!("{} at {}", version, label),
|
|
)),
|
|
None => checks.push(Check::new(
|
|
"chrome.installed",
|
|
category,
|
|
Status::Pass,
|
|
format!("Chrome at {} (version unknown)", label),
|
|
)),
|
|
}
|
|
}
|
|
None => checks.push(
|
|
Check::new(
|
|
"chrome.installed",
|
|
category,
|
|
Status::Fail,
|
|
"No Chrome binary found",
|
|
)
|
|
.with_fix("chrome-use install"),
|
|
),
|
|
}
|
|
|
|
let cache_dir = crate::install::get_browsers_dir();
|
|
if cache_dir.exists() {
|
|
checks.push(Check::new(
|
|
"chrome.cache_dir",
|
|
category,
|
|
Status::Info,
|
|
format!("Cache dir {}", cache_dir.display()),
|
|
));
|
|
}
|
|
|
|
if let Some(puppeteer_dir) = puppeteer_cache_dir() {
|
|
if puppeteer_dir.exists() {
|
|
checks.push(Check::new(
|
|
"chrome.puppeteer_cache",
|
|
category,
|
|
Status::Info,
|
|
format!(
|
|
"Puppeteer cache also present: {} (will be used as a fallback)",
|
|
puppeteer_dir.display()
|
|
),
|
|
));
|
|
}
|
|
}
|
|
|
|
if let Some(user_data_dir) = crate::native::cdp::chrome::find_chrome_user_data_dir() {
|
|
let profiles = crate::native::cdp::chrome::list_chrome_profiles(&user_data_dir);
|
|
let count = profiles.len();
|
|
let dir_label = user_data_dir.display().to_string();
|
|
if count == 0 {
|
|
checks.push(Check::new(
|
|
"chrome.user_data_dir",
|
|
category,
|
|
Status::Info,
|
|
format!(
|
|
"Chrome user data dir found ({}), no profiles parsed",
|
|
dir_label
|
|
),
|
|
));
|
|
} else {
|
|
checks.push(Check::new(
|
|
"chrome.user_data_dir",
|
|
category,
|
|
Status::Info,
|
|
format!("{} Chrome profile(s) at {}", count, dir_label),
|
|
));
|
|
}
|
|
}
|
|
|
|
if let Ok(engine) = env::var("AGENT_BROWSER_ENGINE") {
|
|
if engine == "lightpanda" {
|
|
// Best-effort PATH lookup; absence is FAIL only when the user
|
|
// explicitly opted into the lightpanda engine.
|
|
if which_exists("lightpanda") {
|
|
checks.push(Check::new(
|
|
"chrome.engine_lightpanda",
|
|
category,
|
|
Status::Pass,
|
|
"Lightpanda binary on PATH",
|
|
));
|
|
} else {
|
|
checks.push(
|
|
Check::new(
|
|
"chrome.engine_lightpanda",
|
|
category,
|
|
Status::Fail,
|
|
"AGENT_BROWSER_ENGINE=lightpanda but no lightpanda binary on PATH",
|
|
)
|
|
.with_fix("install lightpanda or unset AGENT_BROWSER_ENGINE"),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn query_chrome_version(path: &Path) -> Option<String> {
|
|
let output = std::process::Command::new(path)
|
|
.arg("--version")
|
|
.output()
|
|
.ok()?;
|
|
if !output.status.success() {
|
|
return None;
|
|
}
|
|
let s = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
if s.is_empty() {
|
|
None
|
|
} else {
|
|
Some(s)
|
|
}
|
|
}
|
|
|
|
pub(super) fn puppeteer_cache_dir() -> Option<PathBuf> {
|
|
if let Ok(p) = env::var("PUPPETEER_CACHE_DIR") {
|
|
return Some(PathBuf::from(p));
|
|
}
|
|
dirs::home_dir().map(|h| h.join(".cache").join("puppeteer"))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_puppeteer_cache_dir_returns_sensible_default() {
|
|
// When PUPPETEER_CACHE_DIR is unset, we fall back to
|
|
// ~/.cache/puppeteer. Mutating env vars here would race with other
|
|
// tests, so just verify the fallback path is shaped correctly.
|
|
if env::var("PUPPETEER_CACHE_DIR").is_err() {
|
|
let dir = puppeteer_cache_dir().expect("home dir should resolve in tests");
|
|
let s = dir.to_string_lossy();
|
|
assert!(s.contains(".cache"));
|
|
assert!(s.ends_with("puppeteer"));
|
|
}
|
|
}
|
|
}
|