Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/extension/src/session-manager/agent-window-tab-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,11 @@ export class AgentWindowTabGroups {
return;
}
}
if (groupId !== undefined && (group?.title !== "BrowserSkill" || group.color !== "orange")) {
const title = task.taskName?.trim() || "BrowserSkill";
if (groupId !== undefined && (group?.title !== title || group.color !== "orange")) {
// Do not continually expand the group after the user has collapsed it.
await this.api.tabGroups.update(groupId, {
title: "BrowserSkill",
title,
color: "orange",
...(!group ? { collapsed: false } : {}),
});
Expand Down
7 changes: 6 additions & 1 deletion apps/extension/src/session-manager/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { AGENT_WINDOW_HOME, type AgentWindowApi, chromeAgentWindowApi } from "./
import { RefStore } from "./ref-store";

export interface SessionContext {
/** Optional display name; never used to identify or grant control of a session. */
taskName?: string;
/** Incognito sessions cannot borrow user tabs. Absent means a normal window. */
incognito?: boolean;
/** Remote connections retain dedicated windows, with explicit page ownership. */
Expand Down Expand Up @@ -51,6 +53,8 @@ export interface SessionManagerOptions {

/** Options for starting a session's Agent Window. */
export interface SessionStartOptions {
/** Optional display name for the Agent Window's tab group. */
taskName?: string;
/** Use Chrome's shared incognito browsing session. */
incognito?: boolean;
/** Optional Agent Window outer size in CSS pixels. */
Expand Down Expand Up @@ -260,7 +264,7 @@ export class SessionManager {
let windowId: number | null = null;
const agentCreatedTabs = new Set<number>();
try {
const { signal: _signal, ...createOptions } = opts;
const { signal: _signal, taskName: _taskName, ...createOptions } = opts;
const created = await this.agentWindow.create(AGENT_WINDOW_HOME, createOptions);
windowId = created.windowId;
for (const tabId of created.initialTabIds) agentCreatedTabs.add(tabId);
Expand All @@ -279,6 +283,7 @@ export class SessionManager {
throwIfSessionStartAborted(opts.signal);

const ctx: SessionContext = {
taskName: opts.taskName,
incognito: created.incognito ?? false,
...(this.remote() ? { remote: true } : {}),
sessionId,
Expand Down
6 changes: 6 additions & 0 deletions apps/extension/src/tools/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export function validateWindowSize(

export interface SessionStartParams {
session_id: string;
/** Optional task name displayed in the Agent Window's tab group. */
task_name?: string;
/** Opt in to Chrome's shared incognito browsing session. */
incognito?: boolean;
browser_instance_id?: string;
Expand Down Expand Up @@ -138,11 +140,15 @@ export async function handleSessionStart(
if (params.incognito !== undefined && typeof params.incognito !== "boolean") {
return { code: "invalid_params", message: "incognito must be a boolean" };
}
if (params.task_name !== undefined && typeof params.task_name !== "string") {
return { code: "invalid_params", message: "task_name must be a string" };
}
const sizeOrErr = validateWindowSize(params.width, params.height);
if (isRpcError(sizeOrErr)) return sizeOrErr;
try {
await deps.preferences?.readyOrFallback();
const ctx = await manager.start(params.session_id, {
taskName: params.task_name,
incognito: params.incognito,
size: sizeOrErr,
focused: params.focused,
Expand Down
2 changes: 1 addition & 1 deletion crates/bsk-cli/src/cli/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub struct SessionStartArgs {
/// Recoverable request token: <expiry-unix-ms>:<UUID>. Valid for at most ten minutes.
#[arg(long)]
pub request_id: Option<String>,
/// Optional task name displayed in local operation history.
/// Optional task name displayed in the browser tab group and local operation history.
#[arg(long)]
pub name: Option<String>,
/// Target browser instance ID or unique label. Always set this when
Expand Down
1 change: 1 addition & 0 deletions crates/bsk-cli/src/daemon/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,7 @@ pub(super) async fn handle_session_start(
&state.tool_queues,
params.browser_instance_id.as_deref(),
AgentWindowOptions {
task_name: task_name.clone(),
incognito: params.incognito,
size: window_size,
focused: params.focused,
Expand Down
5 changes: 4 additions & 1 deletion crates/bsk-cli/src/daemon/sessions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,10 @@ const SESSION_ID_MAX_RESERVE_ATTEMPTS: u32 = 64;
/// Agent Window creation hints forwarded to the extension on
/// `tool.session_start`. `None` fields keep the extension-side defaults
/// (background window, browser-chosen size).
#[derive(Debug, Default, Clone, Copy)]
#[derive(Debug, Default, Clone)]
pub struct AgentWindowOptions {
/// Optional task name for the Agent Window's tab group.
pub task_name: Option<String>,
/// Opt in to Chrome's shared incognito browsing session.
pub incognito: bool,
/// Optional outer size as `(width, height)` CSS pixels.
Expand Down Expand Up @@ -685,6 +687,7 @@ pub(crate) async fn start_session_recoverable(
sessions.starting.lock().unwrap().insert(session_id.clone());
}
let params = SessionStartParams {
task_name: window.task_name,
incognito: window.incognito,
session_id: session_id.0.clone(),
browser_instance_id: Some(client.id.0.clone()),
Expand Down
7 changes: 7 additions & 0 deletions crates/bsk-protocol/schema/tool_session_start_params.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
"session_id": {
"type": "string"
},
"task_name": {
"description": "Optional task name displayed in the Agent Window's tab group.",
"type": [
"string",
"null"
]
},
"width": {
"description": "Optional Agent Window outer width in CSS pixels (100..=7680).",
"type": [
Expand Down
3 changes: 3 additions & 0 deletions crates/bsk-protocol/src/tools/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub struct InteractionPolicy {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct SessionStartParams {
pub session_id: String,
/// Optional task name displayed in the Agent Window's tab group.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub task_name: Option<String>,
/// Use Chrome's shared incognito browsing session. Omitted means normal.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub incognito: bool,
Expand Down
2 changes: 2 additions & 0 deletions docs/operation-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ BrowserSkill 作者不接收这些记录;远程部署的数据流向见[远程
bsk session start --name "整理本周待办"
```

任务名同时显示在 Agent Window 的浏览器标签分组中;未传名称或名称仅含空白时,分组使用默认标题 `BrowserSkill`。需要同时更新 CLI/daemon 和扩展,旧版本仍使用默认分组标题。

未命名时,显示网站与任务开始时间。任务状态为「执行中」「已结束」「已中断」,不代表用户的业务目标已完成。操作状态表示工具返回成功、失败、取消或结果未知;超时、缺少返回值以及中途停录均不能推断成成功。脚本内部执行的多个动作只能作为一次脚本调用记录,不能还原为逐次点击。

中途开启只记录之后的操作,并标注「部分记录」。关闭开关会停止收集新操作,保留已有记录,且不停止任务;再次开启会在同一任务中标出暂停和恢复位置。已开始记录的任务在关闭开关后仍会写入最终生命周期状态,以免长期显示执行中。服务重启或浏览器断开后,无法证明正常结束的任务显示为已中断。
Expand Down