feat(session): support unfocused agent windows (--no-focus) (#87)

`bsk session start --no-focus` opens the Agent Window in the background
without stealing focus. The flag threads focused=false through
CLI -> daemon IPC -> tool.session_start -> chrome.windows.create; an
omitted `focused` keeps the extension default (true) so older clients
are unaffected.

Reworked onto current main so it composes with #52 window sizing:
AgentWindowApi.create / SessionManager.start (extension), start_session
(CLI) and the daemon's session start now take options objects/structs
({ size, focused }) instead of colliding positional params.

Co-authored-by: alectimison-maker <alec.timison@gmail.com>
This commit is contained in:
BB-fat
2026-08-12 19:58:53 +08:00
committed by GitHub
co-authored by alectimison-maker
parent 0ce497f017
commit f443cfae74
17 changed files with 235 additions and 43 deletions
+13
View File
@@ -5,6 +5,7 @@ use std::time::Duration;
use bsk::cli::daemon::{DaemonCmd, parse_duration};
use bsk::cli::navigate::NavigateCmd;
use bsk::cli::record::{RecordCmd, RecordSub};
use bsk::cli::session::{SessionCmd, SessionSub};
use bsk::{Cli, Command};
use clap::Parser;
@@ -500,3 +501,15 @@ fn rejects_invalid_emulate_values() {
.is_err()
);
}
#[test]
fn parses_session_start_no_focus() {
let cli = parse(&["bsk", "session", "start", "--no-focus"]);
let Command::Session(SessionCmd {
sub: SessionSub::Start(args),
}) = cli.command
else {
panic!("expected session start subcommand");
};
assert!(args.no_focus);
}
+4 -1
View File
@@ -144,8 +144,9 @@ async fn session_start_stop_round_trip_via_ipc() {
if let Frame::Request(req) = frame {
let reply = match req.method {
Method::ToolSessionStart => {
let _: SessionStartParams =
let params: SessionStartParams =
serde_json::from_value(req.params.clone().unwrap()).unwrap();
assert_eq!(params.focused, Some(false));
let result = SessionStartResult {
agent_window_id: Some(4242),
};
@@ -177,6 +178,7 @@ async fn session_start_stop_round_trip_via_ipc() {
#[derive(serde::Serialize)]
struct StartParams {
browser_instance_id: Option<String>,
focused: Option<bool>,
}
#[derive(serde::Deserialize, Debug)]
struct StartReply {
@@ -191,6 +193,7 @@ async fn session_start_stop_round_trip_via_ipc() {
Method::SessionStart,
Some(StartParams {
browser_instance_id: None,
focused: Some(false),
}),
Duration::from_secs(5),
)