feat: add built-in upgrade command for self-update (#898)
Adds a new `agent-browser upgrade` command that automatically detects the installation method (npm, Homebrew, or Cargo) and runs the appropriate update command. **Changes:** - Added new `upgrade.rs` module with upgrade logic - Updated `main.rs` to handle the `upgrade` command - Added upgrade help text in `output.rs` - Updated README.md and documentation with upgrade instructions - Updated SKILL.md to mention the upgrade command **Implementation details:** - Fetches latest version from npm registry to show version diff - Auto-detects installation method by checking Homebrew, Cargo paths, and npm global packages - Provides fallback instructions if installation method cannot be determined - Uses existing color module for consistent styled output - Gracefully handles network failures and continues with upgrade Fixes #895
This commit is contained in:
@@ -58,6 +58,16 @@ On Linux, install system dependencies:
|
||||
agent-browser install --with-deps
|
||||
```
|
||||
|
||||
### Updating
|
||||
|
||||
Upgrade to the latest version:
|
||||
|
||||
```bash
|
||||
agent-browser upgrade
|
||||
```
|
||||
|
||||
Detects your installation method (npm, Homebrew, or Cargo) and runs the appropriate update command automatically.
|
||||
|
||||
### Requirements
|
||||
|
||||
- **Chrome** - Run `agent-browser install` to download Chrome from [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (Google's official automation channel). No Playwright or Node.js required for the daemon.
|
||||
@@ -339,6 +349,7 @@ agent-browser reload # Reload page
|
||||
```bash
|
||||
agent-browser install # Download Chrome from Chrome for Testing (Google's official automation channel)
|
||||
agent-browser install --with-deps # Also install system deps (Linux)
|
||||
agent-browser upgrade # Upgrade agent-browser to the latest version
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
@@ -7,6 +7,7 @@ mod native;
|
||||
mod output;
|
||||
#[cfg(test)]
|
||||
mod test_utils;
|
||||
mod upgrade;
|
||||
mod validation;
|
||||
|
||||
use serde_json::json;
|
||||
@@ -26,6 +27,7 @@ use install::run_install;
|
||||
use output::{
|
||||
print_command_help, print_help, print_response_with_opts, print_version, OutputOptions,
|
||||
};
|
||||
use upgrade::run_upgrade;
|
||||
|
||||
fn serialize_json_value(value: &serde_json::Value) -> String {
|
||||
serde_json::to_string(value).unwrap_or_else(|_| {
|
||||
@@ -226,6 +228,12 @@ fn main() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle upgrade separately
|
||||
if clean.first().map(|s| s.as_str()) == Some("upgrade") {
|
||||
run_upgrade();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle session separately (doesn't need daemon)
|
||||
if clean.first().map(|s| s.as_str()) == Some("session") {
|
||||
run_session(&clean, &flags.session, flags.json);
|
||||
|
||||
@@ -2266,6 +2266,22 @@ Examples:
|
||||
"##
|
||||
}
|
||||
|
||||
// === Upgrade ===
|
||||
"upgrade" => {
|
||||
r##"
|
||||
agent-browser upgrade - Upgrade to the latest version
|
||||
|
||||
Usage: agent-browser upgrade
|
||||
|
||||
Detects the current installation method (npm, Homebrew, or Cargo) and runs
|
||||
the appropriate update command. Displays the version change on success, or
|
||||
informs you if you are already on the latest version.
|
||||
|
||||
Examples:
|
||||
agent-browser upgrade
|
||||
"##
|
||||
}
|
||||
|
||||
// === Connect ===
|
||||
"connect" => {
|
||||
r##"
|
||||
@@ -2572,6 +2588,7 @@ Sessions:
|
||||
Setup:
|
||||
install Install browser binaries
|
||||
install --with-deps Also install system dependencies (Linux)
|
||||
upgrade Upgrade to the latest version
|
||||
|
||||
Snapshot Options:
|
||||
-i, --interactive Only interactive elements
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
use crate::color;
|
||||
use std::process::{exit, Command, Stdio};
|
||||
|
||||
const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const NPM_REGISTRY_URL: &str = "https://registry.npmjs.org/agent-browser/latest";
|
||||
|
||||
enum InstallMethod {
|
||||
Npm,
|
||||
Homebrew,
|
||||
Cargo,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
async fn fetch_latest_version() -> Result<String, String> {
|
||||
let resp = reqwest::get(NPM_REGISTRY_URL)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to fetch version info: {}", e))?;
|
||||
|
||||
let body: serde_json::Value = resp
|
||||
.json()
|
||||
.await
|
||||
.map_err(|e| format!("Failed to parse version info: {}", e))?;
|
||||
|
||||
body.get("version")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| "No version field in registry response".to_string())
|
||||
}
|
||||
|
||||
fn detect_install_method() -> InstallMethod {
|
||||
// Check Homebrew (available on macOS and Linux)
|
||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||
{
|
||||
let brew_check = Command::new("brew")
|
||||
.args(["list", "agent-browser"])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status();
|
||||
if brew_check.map(|s| s.success()).unwrap_or(false) {
|
||||
return InstallMethod::Homebrew;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Cargo installation by executable path
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
let path_str = exe.to_string_lossy();
|
||||
if path_str.contains("/.cargo/bin/") || path_str.contains("\\.cargo\\bin\\") {
|
||||
return InstallMethod::Cargo;
|
||||
}
|
||||
}
|
||||
|
||||
// Check npm global installation
|
||||
let npm_check = Command::new("npm")
|
||||
.args(["list", "-g", "agent-browser", "--depth=0"])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status();
|
||||
if npm_check.map(|s| s.success()).unwrap_or(false) {
|
||||
return InstallMethod::Npm;
|
||||
}
|
||||
|
||||
InstallMethod::Unknown
|
||||
}
|
||||
|
||||
fn run_upgrade_command(method: &InstallMethod) -> bool {
|
||||
match method {
|
||||
InstallMethod::Npm => {
|
||||
println!("Running: npm install -g agent-browser@latest");
|
||||
Command::new("npm")
|
||||
.args(["install", "-g", "agent-browser@latest"])
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
InstallMethod::Homebrew => {
|
||||
println!("Running: brew upgrade agent-browser");
|
||||
Command::new("brew")
|
||||
.args(["upgrade", "agent-browser"])
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
InstallMethod::Cargo => {
|
||||
println!("Running: cargo install agent-browser --force");
|
||||
Command::new("cargo")
|
||||
.args(["install", "agent-browser", "--force"])
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
InstallMethod::Unknown => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_upgrade() {
|
||||
let current = CURRENT_VERSION;
|
||||
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!(
|
||||
"{} Failed to create runtime: {}",
|
||||
color::error_indicator(),
|
||||
e
|
||||
);
|
||||
exit(1);
|
||||
});
|
||||
|
||||
let latest = match rt.block_on(fetch_latest_version()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"{} Could not check latest version: {}",
|
||||
color::warning_indicator(),
|
||||
e
|
||||
);
|
||||
String::new()
|
||||
}
|
||||
};
|
||||
|
||||
if !latest.is_empty() && current == latest.as_str() {
|
||||
println!(
|
||||
"{} agent-browser is already at the latest version (v{})",
|
||||
color::success_indicator(),
|
||||
current
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let method = detect_install_method();
|
||||
|
||||
let method_name = match &method {
|
||||
InstallMethod::Npm => "npm",
|
||||
InstallMethod::Homebrew => "Homebrew",
|
||||
InstallMethod::Cargo => "Cargo",
|
||||
InstallMethod::Unknown => "",
|
||||
};
|
||||
|
||||
if matches!(method, InstallMethod::Unknown) {
|
||||
eprintln!(
|
||||
"{} Could not detect installation method.",
|
||||
color::error_indicator()
|
||||
);
|
||||
eprintln!(" To update manually, run one of:");
|
||||
eprintln!(" npm install -g agent-browser@latest # npm");
|
||||
eprintln!(" brew upgrade agent-browser # Homebrew");
|
||||
eprintln!(" cargo install agent-browser --force # Cargo");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
println!("Detected installation via {}.", method_name);
|
||||
|
||||
if !latest.is_empty() {
|
||||
println!(
|
||||
"{}",
|
||||
color::cyan(&format!(
|
||||
"Upgrading agent-browser... v{} → v{}",
|
||||
current, latest
|
||||
))
|
||||
);
|
||||
} else {
|
||||
println!(
|
||||
"{}",
|
||||
color::cyan(&format!("Upgrading agent-browser (v{})...", current))
|
||||
);
|
||||
}
|
||||
|
||||
let success = run_upgrade_command(&method);
|
||||
|
||||
if success {
|
||||
if !latest.is_empty() {
|
||||
println!(
|
||||
"{} Done! v{} → v{}",
|
||||
color::success_indicator(),
|
||||
current,
|
||||
latest
|
||||
);
|
||||
} else {
|
||||
println!("{} Done!", color::success_indicator());
|
||||
}
|
||||
} else {
|
||||
eprintln!("{} Upgrade failed.", color::error_indicator());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,16 @@ On Linux, install system dependencies:
|
||||
agent-browser install --with-deps
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
Upgrade to the latest version:
|
||||
|
||||
```bash
|
||||
agent-browser upgrade
|
||||
```
|
||||
|
||||
Detects your installation method (npm, Homebrew, or Cargo) and runs the appropriate update command automatically. Displays the version change on success, or informs you if you are already on the latest version.
|
||||
|
||||
## Custom browser
|
||||
|
||||
Use a custom browser executable instead of bundled Chromium:
|
||||
|
||||
@@ -6,7 +6,7 @@ allowed-tools: Bash(npx agent-browser:*), Bash(agent-browser:*)
|
||||
|
||||
# Browser Automation with agent-browser
|
||||
|
||||
The CLI uses Chrome/Chromium via CDP directly. Install via `npm i -g agent-browser`, `brew install agent-browser`, or `cargo install agent-browser`. Run `agent-browser install` to download Chrome.
|
||||
The CLI uses Chrome/Chromium via CDP directly. Install via `npm i -g agent-browser`, `brew install agent-browser`, or `cargo install agent-browser`. Run `agent-browser install` to download Chrome. Run `agent-browser upgrade` to update to the latest version.
|
||||
|
||||
## Core Workflow
|
||||
|
||||
|
||||
Reference in New Issue
Block a user