Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8f484eded | ||
|
|
1eb40eabd5 | ||
|
|
601404ba72 | ||
|
|
fd10766762 |
Generated
+1
-1
@@ -290,7 +290,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrome-use"
|
name = "chrome-use"
|
||||||
version = "1.5.25"
|
version = "1.5.27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "chrome-use"
|
name = "chrome-use"
|
||||||
version = "1.5.25"
|
version = "1.5.27"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Fast browser automation CLI for AI agents"
|
description = "Fast browser automation CLI for AI agents"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -305,6 +305,49 @@ fn run_session(args: &[String], session: &str, json_mode: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Stop a specific session daemon (issue #48). Graceful: kill_stale_daemon
|
||||||
|
// sends SIGTERM first, so the daemon's shutdown handler runs `close()` and
|
||||||
|
// tidies the tabs IT created (its tab group) before exiting.
|
||||||
|
Some("stop") => {
|
||||||
|
let target = args.get(2).map(|s| s.as_str()).unwrap_or(session);
|
||||||
|
connection::kill_stale_daemon(target);
|
||||||
|
if json_mode {
|
||||||
|
print_json_value(json!({ "success": true, "data": { "stopped": target } }));
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"{} stopped session daemon: {}",
|
||||||
|
color::success_indicator(),
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reclaim ALL session daemons now (issue #48) — for clearing the pile of
|
||||||
|
// idle daemons left after a round of automation/debugging without waiting
|
||||||
|
// for the idle timeout. Each is stopped gracefully (closes its own tabs);
|
||||||
|
// they respawn clean on next use. The `__nm-host` relay is not a tracked
|
||||||
|
// session daemon, so the extension/live-Chrome connection survives.
|
||||||
|
Some("prune") => {
|
||||||
|
let sessions: Vec<String> = walk_daemons()
|
||||||
|
.sessions
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.name)
|
||||||
|
.collect();
|
||||||
|
for s in &sessions {
|
||||||
|
connection::kill_stale_daemon(s);
|
||||||
|
}
|
||||||
|
if json_mode {
|
||||||
|
print_json_value(json!({ "success": true, "data": { "pruned": sessions } }));
|
||||||
|
} else if sessions.is_empty() {
|
||||||
|
println!("No session daemons to prune");
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"{} pruned {} session daemon(s): {}",
|
||||||
|
color::success_indicator(),
|
||||||
|
sessions.len(),
|
||||||
|
sessions.join(", ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
None | Some(_) => {
|
None | Some(_) => {
|
||||||
// Just show current session
|
// Just show current session
|
||||||
if json_mode {
|
if json_mode {
|
||||||
|
|||||||
@@ -2070,6 +2070,46 @@ impl BrowserManager {
|
|||||||
self.active_page_index = index;
|
self.active_page_index = index;
|
||||||
self.pin_active_target();
|
self.pin_active_target();
|
||||||
|
|
||||||
|
// Close the daemon's leftover initial `about:blank` scratch tab once this
|
||||||
|
// real tab exists, so the session's tab group isn't left showing a stray
|
||||||
|
// blank page beside the work tab (every group otherwise carried one). Only
|
||||||
|
// on the RELAY — there the about:blank is a tab WE created as scratch; on a
|
||||||
|
// launched browser the initial about:blank is the browser's own first tab,
|
||||||
|
// which we must not close. Only when opening a real url, OWNED, still-blank.
|
||||||
|
if target_url != "about:blank" && self.agent_group().is_some() {
|
||||||
|
if let Some(new_tid) = self.pages.get(index).map(|p| p.target_id.clone()) {
|
||||||
|
let blanks: Vec<String> = self
|
||||||
|
.pages
|
||||||
|
.iter()
|
||||||
|
.filter(|p| {
|
||||||
|
p.target_id != new_tid
|
||||||
|
&& self.created_targets.contains(&p.target_id)
|
||||||
|
&& (p.url == "about:blank" || p.url.is_empty())
|
||||||
|
})
|
||||||
|
.map(|p| p.target_id.clone())
|
||||||
|
.collect();
|
||||||
|
for tid in blanks {
|
||||||
|
let _ = self
|
||||||
|
.client
|
||||||
|
.send_command_typed::<_, Value>(
|
||||||
|
"Target.closeTarget",
|
||||||
|
&CloseTargetParams {
|
||||||
|
target_id: tid.clone(),
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
self.created_targets.remove(&tid);
|
||||||
|
self.remove_page_by_target_id(&tid);
|
||||||
|
}
|
||||||
|
// Removing earlier pages shifts indices — re-pin the new tab.
|
||||||
|
if let Some(i) = self.pages.iter().position(|p| p.target_id == new_tid) {
|
||||||
|
self.active_page_index = i;
|
||||||
|
self.pin_active_target();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"tabId": format_tab_id(tab_id),
|
"tabId": format_tab_id(tab_id),
|
||||||
"label": label,
|
"label": label,
|
||||||
|
|||||||
@@ -3455,11 +3455,21 @@ Confirmation:
|
|||||||
Sessions:
|
Sessions:
|
||||||
session Show current session name
|
session Show current session name
|
||||||
session list List active sessions
|
session list List active sessions
|
||||||
|
session stop [name] Stop one session daemon (default: current) — graceful,
|
||||||
|
closes the tabs it created
|
||||||
|
session prune Stop ALL session daemons now (closes their tabs; they
|
||||||
|
respawn clean on next use). For clearing idle daemons.
|
||||||
sessions List running session daemons (alias of daemon status)
|
sessions List running session daemons (alias of daemon status)
|
||||||
daemon status List running session daemons (+ relay state)
|
daemon status List running session daemons (+ relay state)
|
||||||
daemon restart Kill all session daemons; keeps the extension relay
|
daemon restart Kill all session daemons; keeps the extension relay
|
||||||
up. Clears stale/cross-leaked state after an upgrade.
|
up. Clears stale/cross-leaked state after an upgrade.
|
||||||
|
|
||||||
|
Lifecycle: each --session <name> spawns a background daemon that drives that
|
||||||
|
session's tabs. A daemon auto-shuts-down after 10 min idle (no commands) —
|
||||||
|
AGENT_BROWSER_IDLE_TIMEOUT_MS overrides, 0 disables — and on shutdown closes
|
||||||
|
the scratch tabs IT created (its tab group). Use `keep` to leave a tab for the
|
||||||
|
user (exempt from auto-close), `session stop/prune` to reclaim now.
|
||||||
|
|
||||||
Chat (AI):
|
Chat (AI):
|
||||||
chat <message> Send a natural language instruction (single-shot)
|
chat <message> Send a natural language instruction (single-shot)
|
||||||
chat Start interactive chat (REPL mode when stdin is a TTY)
|
chat Start interactive chat (REPL mode when stdin is a TTY)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chrome-use",
|
"name": "chrome-use",
|
||||||
"version": "1.5.25",
|
"version": "1.5.27",
|
||||||
"description": "chrome-use — drive your real, logged-in Chrome from any AI agent, stealth by default",
|
"description": "chrome-use — drive your real, logged-in Chrome from any AI agent, stealth by default",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@11.1.3",
|
"packageManager": "pnpm@11.1.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user