bb-browser 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KATHFDYJ.js → chunk-YAVLEXUJ.js} +1 -1
- package/dist/chunk-YAVLEXUJ.js.map +1 -0
- package/dist/cli.js +118 -58
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/extension/background.js +23 -13
- package/extension/background.js.map +1 -1
- package/extension/dist/background.js +162 -98
- package/extension/dist/background.js.map +1 -1
- package/extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/dist/chunk-KATHFDYJ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/shared/src/protocol.ts","../packages/shared/src/constants.ts"],"sourcesContent":["/**\n * CLI 与 Chrome Extension 之间的通信协议类型定义\n */\n\n/** 支持的操作类型 */\nexport type ActionType =\n | \"open\"\n | \"snapshot\"\n | \"click\"\n | \"hover\"\n | \"fill\"\n | \"type\"\n | \"check\"\n | \"uncheck\"\n | \"select\"\n | \"get\"\n | \"screenshot\"\n | \"close\"\n | \"wait\"\n | \"press\"\n | \"scroll\"\n | \"back\"\n | \"forward\"\n | \"refresh\"\n | \"eval\"\n | \"tab_list\"\n | \"tab_new\"\n | \"tab_select\"\n | \"tab_close\"\n | \"frame\"\n | \"frame_main\"\n | \"dialog\"\n | \"network\"\n | \"console\"\n | \"errors\"\n | \"trace\";\n\n/** 请求类型 */\nexport interface Request {\n /** 请求唯一标识 */\n id: string;\n /** 操作类型 */\n action: ActionType;\n /** 目标 URL(open 操作时必填) */\n url?: string;\n /** 元素引用(click, fill, get 操作时使用) */\n ref?: string;\n /** 输入文本(fill 操作时使用) */\n text?: string;\n /** 获取属性类型(get 操作时使用) */\n attribute?: string;\n /** 截图保存路径(screenshot 操作时使用) */\n path?: string;\n /** 是否只输出可交互元素(snapshot 命令使用) */\n interactive?: boolean;\n /** JavaScript 代码(eval 命令使用) */\n script?: string;\n /** 选项值(select 命令使用) */\n value?: string;\n /** 标签页索引(tab_select, tab_close 命令使用) */\n index?: number;\n /** 标签页 ID(tab_select, tab_close 命令使用,优先于 index) */\n tabId?: number | string;\n /** CSS 选择器(frame 命令使用,定位 iframe) */\n selector?: string;\n /** dialog 响应类型(dialog 命令使用) */\n dialogResponse?: \"accept\" | \"dismiss\";\n /** prompt 对话框的输入文本(dialog accept 时可选) */\n promptText?: string;\n /** network 子命令:requests, route, unroute, clear */\n networkCommand?: \"requests\" | \"route\" | \"unroute\" | \"clear\";\n /** network route 选项 */\n routeOptions?: {\n abort?: boolean;\n body?: string;\n status?: number;\n headers?: Record<string, string>;\n };\n /** 过滤字符串(network requests, console 使用) */\n filter?: string;\n /** console 子命令:get, clear */\n consoleCommand?: \"get\" | \"clear\";\n /** errors 子命令:get, clear */\n errorsCommand?: \"get\" | \"clear\";\n /** trace 子命令:start, stop, status */\n traceCommand?: \"start\" | \"stop\" | \"status\";\n}\n\n/** 元素引用信息 */\nexport interface RefInfo {\n /** 元素的 XPath */\n xpath: string;\n /** 可访问性角色 */\n role: string;\n /** 可访问名称 */\n name?: string;\n /** 标签名 */\n tagName: string;\n}\n\n/** 标签页信息 */\nexport interface TabInfo {\n /** 标签页在窗口中的索引(0-based) */\n index: number;\n /** 标签页 URL */\n url: string;\n /** 标签页标题 */\n title: string;\n /** 是否是当前活动标签页 */\n active: boolean;\n /** 标签页 ID */\n tabId: number;\n}\n\n/** Snapshot 命令返回的数据 */\nexport interface SnapshotData {\n /** 文本格式的可访问性树 */\n snapshot: string;\n /** 元素引用映射,key 为 ref ID */\n refs: Record<string, RefInfo>;\n}\n\n/** 网络请求信息 */\nexport interface NetworkRequestInfo {\n requestId: string;\n url: string;\n method: string;\n type: string;\n timestamp: number;\n status?: number;\n statusText?: string;\n failed?: boolean;\n failureReason?: string;\n}\n\n/** 控制台消息 */\nexport interface ConsoleMessageInfo {\n type: 'log' | 'info' | 'warn' | 'error' | 'debug';\n text: string;\n timestamp: number;\n url?: string;\n lineNumber?: number;\n}\n\n/** JS 错误信息 */\nexport interface JSErrorInfo {\n message: string;\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n stackTrace?: string;\n timestamp: number;\n}\n\n/** Trace 事件类型 - 录制用户操作 */\nexport interface TraceEvent {\n /** 事件类型 */\n type: 'click' | 'fill' | 'select' | 'check' | 'press' | 'scroll' | 'navigation';\n /** 时间戳 */\n timestamp: number;\n /** 事件发生时的页面 URL */\n url: string;\n \n /** 元素引用 - highlightIndex,可直接用于 @ref */\n ref?: number;\n /** 备用定位 - XPath */\n xpath?: string;\n /** CSS 选择器 */\n cssSelector?: string;\n \n /** 操作参数 - fill/select 的值 */\n value?: string;\n /** 操作参数 - press 的按键 */\n key?: string;\n /** 操作参数 - scroll 方向 */\n direction?: 'up' | 'down' | 'left' | 'right';\n /** 操作参数 - scroll 距离 */\n pixels?: number;\n /** 操作参数 - check/uncheck 状态 */\n checked?: boolean;\n \n /** 语义信息 - 元素角色 */\n elementRole?: string;\n /** 语义信息 - 元素名称 */\n elementName?: string;\n /** 语义信息 - 元素标签 */\n elementTag?: string;\n}\n\n/** Trace 录制状态 */\nexport interface TraceStatus {\n /** 是否正在录制 */\n recording: boolean;\n /** 已录制事件数量 */\n eventCount: number;\n /** 录制的标签页 ID */\n tabId?: number;\n}\n\n/** 响应数据 */\nexport interface ResponseData {\n /** 页面标题 */\n title?: string;\n /** 当前 URL */\n url?: string;\n /** Tab ID */\n tabId?: number;\n /** Snapshot 数据(snapshot 操作返回) */\n snapshotData?: SnapshotData;\n /** 获取的文本或属性值(get 操作返回) */\n value?: string;\n /** 截图路径(screenshot 操作返回) */\n screenshotPath?: string;\n /** eval 执行结果 */\n result?: unknown;\n /** 标签页列表(tab_list 命令返回) */\n tabs?: TabInfo[];\n /** 当前活动标签页索引(tab_list 命令返回) */\n activeIndex?: number;\n /** Frame 信息(frame 命令返回) */\n frameInfo?: {\n /** iframe 的 CSS 选择器 */\n selector?: string;\n /** iframe 的 name 属性 */\n name?: string;\n /** iframe 的 URL */\n url?: string;\n /** frame ID */\n frameId?: number;\n };\n /** dialog 信息(dialog 命令返回) */\n dialogInfo?: {\n /** 对话框类型:alert, confirm, prompt, beforeunload */\n type: string;\n /** 对话框消息 */\n message: string;\n /** 是否成功处理 */\n handled: boolean;\n };\n /** 网络请求列表(network requests 命令返回) */\n networkRequests?: NetworkRequestInfo[];\n /** 网络路由规则数量(network route/unroute 命令返回) */\n routeCount?: number;\n /** 控制台消息列表(console 命令返回) */\n consoleMessages?: ConsoleMessageInfo[];\n /** JS 错误列表(errors 命令返回) */\n jsErrors?: JSErrorInfo[];\n /** Trace 事件列表(trace stop 命令返回) */\n traceEvents?: TraceEvent[];\n /** Trace 录制状态(trace status 命令返回) */\n traceStatus?: TraceStatus;\n}\n\n/** 响应类型 */\nexport interface Response {\n /** 对应请求的 ID */\n id: string;\n /** 操作是否成功 */\n success: boolean;\n /** 成功时返回的数据 */\n data?: ResponseData;\n /** 失败时的错误信息 */\n error?: string;\n}\n\n/** SSE 事件类型 */\nexport type SSEEventType = \"connected\" | \"heartbeat\" | \"command\";\n\n/** SSE 事件数据 */\nexport interface SSEEvent {\n type: SSEEventType;\n data: unknown;\n}\n\n/** Daemon 状态 */\nexport interface DaemonStatus {\n running: boolean;\n extensionConnected: boolean;\n pendingRequests: number;\n uptime: number;\n}\n\n/**\n * 生成唯一请求 ID\n * @returns UUID v4 格式的字符串\n */\nexport function generateId(): string {\n return crypto.randomUUID();\n}\n","/**\n * bb-browser 共享常量\n */\n\n/** Daemon HTTP 服务端口 */\nexport const DAEMON_PORT = 19824;\n\n/** Daemon 主机地址 */\nexport const DAEMON_HOST = \"localhost\";\n\n/** Daemon 基础 URL */\nexport const DAEMON_BASE_URL = `http://${DAEMON_HOST}:${DAEMON_PORT}`;\n\n/** SSE 心跳间隔(毫秒) - 15秒确保 MV3 Service Worker 不休眠 */\nexport const SSE_HEARTBEAT_INTERVAL = 15000; // 15 秒\n\n/** 命令执行超时时间(毫秒) */\nexport const COMMAND_TIMEOUT = 30000; // 30 秒\n\n/** SSE 重连延迟(毫秒) */\nexport const SSE_RECONNECT_DELAY = 3000; // 3 秒\n\n/** SSE 最大重连尝试次数 */\nexport const SSE_MAX_RECONNECT_ATTEMPTS = 5;\n"],"mappings":";;;AA8RO,SAAS,aAAqB;AACnC,SAAO,OAAO,WAAW;AAC3B;AC3RO,IAAM,cAAc;AAGpB,IAAM,cAAc;AAGpB,IAAM,kBAAkB,UAAU,WAAW,IAAI,WAAW;AAG5D,IAAM,yBAAyB;AAG/B,IAAM,kBAAkB;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
COMMAND_TIMEOUT,
|
|
4
4
|
DAEMON_BASE_URL,
|
|
5
5
|
generateId
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YAVLEXUJ.js";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/client.ts
|
|
9
9
|
async function sendCommand(request) {
|
|
@@ -186,7 +186,8 @@ async function snapshotCommand(options = {}) {
|
|
|
186
186
|
const request = {
|
|
187
187
|
id: generateId(),
|
|
188
188
|
action: "snapshot",
|
|
189
|
-
interactive: options.interactive
|
|
189
|
+
interactive: options.interactive,
|
|
190
|
+
tabId: options.tabId
|
|
190
191
|
};
|
|
191
192
|
const response = await sendCommand(request);
|
|
192
193
|
if (options.json) {
|
|
@@ -219,7 +220,8 @@ async function clickCommand(ref, options = {}) {
|
|
|
219
220
|
const request = {
|
|
220
221
|
id: generateId(),
|
|
221
222
|
action: "click",
|
|
222
|
-
ref: parsedRef
|
|
223
|
+
ref: parsedRef,
|
|
224
|
+
tabId: options.tabId
|
|
223
225
|
};
|
|
224
226
|
const response = await sendCommand(request);
|
|
225
227
|
if (options.json) {
|
|
@@ -253,7 +255,8 @@ async function hoverCommand(ref, options = {}) {
|
|
|
253
255
|
const request = {
|
|
254
256
|
id: generateId(),
|
|
255
257
|
action: "hover",
|
|
256
|
-
ref: parsedRef
|
|
258
|
+
ref: parsedRef,
|
|
259
|
+
tabId: options.tabId
|
|
257
260
|
};
|
|
258
261
|
const response = await sendCommand(request);
|
|
259
262
|
if (options.json) {
|
|
@@ -291,7 +294,8 @@ async function fillCommand(ref, text, options = {}) {
|
|
|
291
294
|
id: generateId(),
|
|
292
295
|
action: "fill",
|
|
293
296
|
ref: parsedRef,
|
|
294
|
-
text
|
|
297
|
+
text,
|
|
298
|
+
tabId: options.tabId
|
|
295
299
|
};
|
|
296
300
|
const response = await sendCommand(request);
|
|
297
301
|
if (options.json) {
|
|
@@ -330,7 +334,8 @@ async function typeCommand(ref, text, options = {}) {
|
|
|
330
334
|
id: generateId(),
|
|
331
335
|
action: "type",
|
|
332
336
|
ref: parsedRef,
|
|
333
|
-
text
|
|
337
|
+
text,
|
|
338
|
+
tabId: options.tabId
|
|
334
339
|
};
|
|
335
340
|
const response = await sendCommand(request);
|
|
336
341
|
if (options.json) {
|
|
@@ -357,7 +362,8 @@ async function closeCommand(options = {}) {
|
|
|
357
362
|
await ensureDaemonRunning();
|
|
358
363
|
const request = {
|
|
359
364
|
id: generateId(),
|
|
360
|
-
action: "close"
|
|
365
|
+
action: "close",
|
|
366
|
+
tabId: options.tabId
|
|
361
367
|
};
|
|
362
368
|
const response = await sendCommand(request);
|
|
363
369
|
if (options.json) {
|
|
@@ -390,7 +396,8 @@ async function getCommand(attribute, ref, options = {}) {
|
|
|
390
396
|
id: generateId(),
|
|
391
397
|
action: "get",
|
|
392
398
|
attribute,
|
|
393
|
-
ref: ref ? parseRef5(ref) : void 0
|
|
399
|
+
ref: ref ? parseRef5(ref) : void 0,
|
|
400
|
+
tabId: options.tabId
|
|
394
401
|
};
|
|
395
402
|
const response = await sendCommand(request);
|
|
396
403
|
if (options.json) {
|
|
@@ -429,7 +436,8 @@ async function screenshotCommand(outputPath, options = {}) {
|
|
|
429
436
|
const filePath = outputPath ? path.resolve(outputPath) : getDefaultPath();
|
|
430
437
|
const request = {
|
|
431
438
|
id: generateId(),
|
|
432
|
-
action: "screenshot"
|
|
439
|
+
action: "screenshot",
|
|
440
|
+
tabId: options.tabId
|
|
433
441
|
};
|
|
434
442
|
const response = await sendCommand(request);
|
|
435
443
|
if (response.success && response.data?.dataUrl) {
|
|
@@ -473,7 +481,8 @@ async function waitCommand(target, options = {}) {
|
|
|
473
481
|
id: generateId(),
|
|
474
482
|
action: "wait",
|
|
475
483
|
waitType: "time",
|
|
476
|
-
ms
|
|
484
|
+
ms,
|
|
485
|
+
tabId: options.tabId
|
|
477
486
|
};
|
|
478
487
|
} else {
|
|
479
488
|
const ref = parseRef6(target);
|
|
@@ -481,7 +490,8 @@ async function waitCommand(target, options = {}) {
|
|
|
481
490
|
id: generateId(),
|
|
482
491
|
action: "wait",
|
|
483
492
|
waitType: "element",
|
|
484
|
-
ref
|
|
493
|
+
ref,
|
|
494
|
+
tabId: options.tabId
|
|
485
495
|
};
|
|
486
496
|
}
|
|
487
497
|
const response = await sendCommand(request);
|
|
@@ -529,7 +539,8 @@ async function pressCommand(keyString, options = {}) {
|
|
|
529
539
|
id: generateId(),
|
|
530
540
|
action: "press",
|
|
531
541
|
key,
|
|
532
|
-
modifiers
|
|
542
|
+
modifiers,
|
|
543
|
+
tabId: options.tabId
|
|
533
544
|
};
|
|
534
545
|
const response = await sendCommand(request);
|
|
535
546
|
if (options.json) {
|
|
@@ -569,7 +580,8 @@ async function scrollCommand(direction, pixels, options = {}) {
|
|
|
569
580
|
id: generateId(),
|
|
570
581
|
action: "scroll",
|
|
571
582
|
direction,
|
|
572
|
-
pixels: pixelValue
|
|
583
|
+
pixels: pixelValue,
|
|
584
|
+
tabId: options.tabId
|
|
573
585
|
};
|
|
574
586
|
const response = await sendCommand(request);
|
|
575
587
|
if (options.json) {
|
|
@@ -758,7 +770,8 @@ async function backCommand(options = {}) {
|
|
|
758
770
|
await ensureDaemonRunning();
|
|
759
771
|
const request = {
|
|
760
772
|
id: generateId(),
|
|
761
|
-
action: "back"
|
|
773
|
+
action: "back",
|
|
774
|
+
tabId: options.tabId
|
|
762
775
|
};
|
|
763
776
|
const response = await sendCommand(request);
|
|
764
777
|
if (options.json) {
|
|
@@ -781,7 +794,8 @@ async function forwardCommand(options = {}) {
|
|
|
781
794
|
await ensureDaemonRunning();
|
|
782
795
|
const request = {
|
|
783
796
|
id: generateId(),
|
|
784
|
-
action: "forward"
|
|
797
|
+
action: "forward",
|
|
798
|
+
tabId: options.tabId
|
|
785
799
|
};
|
|
786
800
|
const response = await sendCommand(request);
|
|
787
801
|
if (options.json) {
|
|
@@ -804,7 +818,8 @@ async function refreshCommand(options = {}) {
|
|
|
804
818
|
await ensureDaemonRunning();
|
|
805
819
|
const request = {
|
|
806
820
|
id: generateId(),
|
|
807
|
-
action: "refresh"
|
|
821
|
+
action: "refresh",
|
|
822
|
+
tabId: options.tabId
|
|
808
823
|
};
|
|
809
824
|
const response = await sendCommand(request);
|
|
810
825
|
if (options.json) {
|
|
@@ -837,7 +852,8 @@ async function checkCommand(ref, options = {}) {
|
|
|
837
852
|
const request = {
|
|
838
853
|
id: generateId(),
|
|
839
854
|
action: "check",
|
|
840
|
-
ref: parsedRef
|
|
855
|
+
ref: parsedRef,
|
|
856
|
+
tabId: options.tabId
|
|
841
857
|
};
|
|
842
858
|
const response = await sendCommand(request);
|
|
843
859
|
if (options.json) {
|
|
@@ -875,7 +891,8 @@ async function uncheckCommand(ref, options = {}) {
|
|
|
875
891
|
const request = {
|
|
876
892
|
id: generateId(),
|
|
877
893
|
action: "uncheck",
|
|
878
|
-
ref: parsedRef
|
|
894
|
+
ref: parsedRef,
|
|
895
|
+
tabId: options.tabId
|
|
879
896
|
};
|
|
880
897
|
const response = await sendCommand(request);
|
|
881
898
|
if (options.json) {
|
|
@@ -922,7 +939,8 @@ async function selectCommand(ref, value, options = {}) {
|
|
|
922
939
|
id: generateId(),
|
|
923
940
|
action: "select",
|
|
924
941
|
ref: parsedRef,
|
|
925
|
-
value
|
|
942
|
+
value,
|
|
943
|
+
tabId: options.tabId
|
|
926
944
|
};
|
|
927
945
|
const response = await sendCommand(request);
|
|
928
946
|
if (options.json) {
|
|
@@ -959,7 +977,8 @@ async function evalCommand(script, options = {}) {
|
|
|
959
977
|
const request = {
|
|
960
978
|
id: generateId(),
|
|
961
979
|
action: "eval",
|
|
962
|
-
script
|
|
980
|
+
script,
|
|
981
|
+
tabId: options.tabId
|
|
963
982
|
};
|
|
964
983
|
const response = await sendCommand(request);
|
|
965
984
|
if (options.json) {
|
|
@@ -984,7 +1003,17 @@ async function evalCommand(script, options = {}) {
|
|
|
984
1003
|
}
|
|
985
1004
|
|
|
986
1005
|
// packages/cli/src/commands/tab.ts
|
|
987
|
-
function parseTabSubcommand(args) {
|
|
1006
|
+
function parseTabSubcommand(args, rawArgv) {
|
|
1007
|
+
let tabId;
|
|
1008
|
+
if (rawArgv) {
|
|
1009
|
+
const idIdx = rawArgv.indexOf("--id");
|
|
1010
|
+
if (idIdx >= 0 && rawArgv[idIdx + 1]) {
|
|
1011
|
+
tabId = parseInt(rawArgv[idIdx + 1], 10);
|
|
1012
|
+
if (isNaN(tabId)) {
|
|
1013
|
+
throw new Error(`\u65E0\u6548\u7684 tabId: ${rawArgv[idIdx + 1]}`);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
988
1017
|
if (args.length === 0) {
|
|
989
1018
|
return { action: "tab_list" };
|
|
990
1019
|
}
|
|
@@ -992,7 +1021,16 @@ function parseTabSubcommand(args) {
|
|
|
992
1021
|
if (first === "new") {
|
|
993
1022
|
return { action: "tab_new", url: args[1] };
|
|
994
1023
|
}
|
|
1024
|
+
if (first === "select") {
|
|
1025
|
+
if (tabId !== void 0) {
|
|
1026
|
+
return { action: "tab_select", tabId };
|
|
1027
|
+
}
|
|
1028
|
+
throw new Error("tab select \u9700\u8981 --id \u53C2\u6570\uFF0C\u7528\u6CD5\uFF1Abb-browser tab select --id <tabId>");
|
|
1029
|
+
}
|
|
995
1030
|
if (first === "close") {
|
|
1031
|
+
if (tabId !== void 0) {
|
|
1032
|
+
return { action: "tab_close", tabId };
|
|
1033
|
+
}
|
|
996
1034
|
const indexArg = args[1];
|
|
997
1035
|
if (indexArg !== void 0) {
|
|
998
1036
|
const index2 = parseInt(indexArg, 10);
|
|
@@ -1021,12 +1059,13 @@ function formatTabList(tabs, activeIndex) {
|
|
|
1021
1059
|
}
|
|
1022
1060
|
async function tabCommand(args, options = {}) {
|
|
1023
1061
|
await ensureDaemonRunning();
|
|
1024
|
-
const parsed = parseTabSubcommand(args);
|
|
1062
|
+
const parsed = parseTabSubcommand(args, process.argv);
|
|
1025
1063
|
const request = {
|
|
1026
1064
|
id: generateId(),
|
|
1027
1065
|
action: parsed.action,
|
|
1028
1066
|
url: parsed.url,
|
|
1029
|
-
index: parsed.index
|
|
1067
|
+
index: parsed.index,
|
|
1068
|
+
tabId: parsed.tabId
|
|
1030
1069
|
};
|
|
1031
1070
|
const response = await sendCommand(request);
|
|
1032
1071
|
if (options.json) {
|
|
@@ -1074,7 +1113,8 @@ async function frameCommand(selector, options = {}) {
|
|
|
1074
1113
|
const request = {
|
|
1075
1114
|
id: generateId(),
|
|
1076
1115
|
action: "frame",
|
|
1077
|
-
selector
|
|
1116
|
+
selector,
|
|
1117
|
+
tabId: options.tabId
|
|
1078
1118
|
};
|
|
1079
1119
|
const response = await sendCommand(request);
|
|
1080
1120
|
if (options.json) {
|
|
@@ -1097,7 +1137,8 @@ async function frameMainCommand(options = {}) {
|
|
|
1097
1137
|
await ensureDaemonRunning();
|
|
1098
1138
|
const request = {
|
|
1099
1139
|
id: generateId(),
|
|
1100
|
-
action: "frame_main"
|
|
1140
|
+
action: "frame_main",
|
|
1141
|
+
tabId: options.tabId
|
|
1101
1142
|
};
|
|
1102
1143
|
const response = await sendCommand(request);
|
|
1103
1144
|
if (options.json) {
|
|
@@ -1122,7 +1163,8 @@ async function dialogCommand(subCommand, promptText, options = {}) {
|
|
|
1122
1163
|
id: generateId(),
|
|
1123
1164
|
action: "dialog",
|
|
1124
1165
|
dialogResponse: subCommand,
|
|
1125
|
-
promptText: subCommand === "accept" ? promptText : void 0
|
|
1166
|
+
promptText: subCommand === "accept" ? promptText : void 0,
|
|
1167
|
+
tabId: options.tabId
|
|
1126
1168
|
};
|
|
1127
1169
|
const response = await sendCommand(request);
|
|
1128
1170
|
if (options.json) {
|
|
@@ -1154,7 +1196,8 @@ async function networkCommand(subCommand, urlOrFilter, options = {}) {
|
|
|
1154
1196
|
routeOptions: subCommand === "route" ? {
|
|
1155
1197
|
abort: options.abort,
|
|
1156
1198
|
body: options.body
|
|
1157
|
-
} : void 0
|
|
1199
|
+
} : void 0,
|
|
1200
|
+
tabId: options.tabId
|
|
1158
1201
|
});
|
|
1159
1202
|
if (options.json) {
|
|
1160
1203
|
console.log(JSON.stringify(response));
|
|
@@ -1217,7 +1260,8 @@ async function consoleCommand(options = {}) {
|
|
|
1217
1260
|
const response = await sendCommand({
|
|
1218
1261
|
id: crypto.randomUUID(),
|
|
1219
1262
|
action: "console",
|
|
1220
|
-
consoleCommand: options.clear ? "clear" : "get"
|
|
1263
|
+
consoleCommand: options.clear ? "clear" : "get",
|
|
1264
|
+
tabId: options.tabId
|
|
1221
1265
|
});
|
|
1222
1266
|
if (options.json) {
|
|
1223
1267
|
console.log(JSON.stringify(response));
|
|
@@ -1261,7 +1305,8 @@ async function errorsCommand(options = {}) {
|
|
|
1261
1305
|
const response = await sendCommand({
|
|
1262
1306
|
id: crypto.randomUUID(),
|
|
1263
1307
|
action: "errors",
|
|
1264
|
-
errorsCommand: options.clear ? "clear" : "get"
|
|
1308
|
+
errorsCommand: options.clear ? "clear" : "get",
|
|
1309
|
+
tabId: options.tabId
|
|
1265
1310
|
});
|
|
1266
1311
|
if (options.json) {
|
|
1267
1312
|
console.log(JSON.stringify(response));
|
|
@@ -1300,7 +1345,8 @@ async function traceCommand(subCommand, options = {}) {
|
|
|
1300
1345
|
const response = await sendCommand({
|
|
1301
1346
|
id: crypto.randomUUID(),
|
|
1302
1347
|
action: "trace",
|
|
1303
|
-
traceCommand: subCommand
|
|
1348
|
+
traceCommand: subCommand,
|
|
1349
|
+
tabId: options.tabId
|
|
1304
1350
|
});
|
|
1305
1351
|
if (options.json) {
|
|
1306
1352
|
console.log(JSON.stringify(response));
|
|
@@ -1376,7 +1422,7 @@ async function traceCommand(subCommand, options = {}) {
|
|
|
1376
1422
|
}
|
|
1377
1423
|
|
|
1378
1424
|
// packages/cli/src/index.ts
|
|
1379
|
-
var VERSION = "0.1.
|
|
1425
|
+
var VERSION = "0.1.2";
|
|
1380
1426
|
var HELP_TEXT = `
|
|
1381
1427
|
bb-browser - AI Agent \u6D4F\u89C8\u5668\u81EA\u52A8\u5316\u5DE5\u5177
|
|
1382
1428
|
|
|
@@ -1412,8 +1458,10 @@ bb-browser - AI Agent \u6D4F\u89C8\u5668\u81EA\u52A8\u5316\u5DE5\u5177
|
|
|
1412
1458
|
refresh \u5237\u65B0\u9875\u9762
|
|
1413
1459
|
tab \u5217\u51FA\u6240\u6709\u6807\u7B7E\u9875
|
|
1414
1460
|
tab new [url] \u65B0\u5EFA\u6807\u7B7E\u9875
|
|
1415
|
-
tab <n> \u5207\u6362\u5230\u7B2C n \u4E2A\u6807\u7B7E\u9875
|
|
1416
|
-
tab
|
|
1461
|
+
tab <n> \u5207\u6362\u5230\u7B2C n \u4E2A\u6807\u7B7E\u9875\uFF08\u6309 index\uFF09
|
|
1462
|
+
tab select --id <id> \u5207\u6362\u5230\u6307\u5B9A tabId \u7684\u6807\u7B7E\u9875
|
|
1463
|
+
tab close [n] \u5173\u95ED\u6807\u7B7E\u9875\uFF08\u6309 index\uFF0C\u9ED8\u8BA4\u5F53\u524D\uFF09
|
|
1464
|
+
tab close --id <id> \u5173\u95ED\u6307\u5B9A tabId \u7684\u6807\u7B7E\u9875
|
|
1417
1465
|
frame <selector> \u5207\u6362\u5230\u6307\u5B9A iframe
|
|
1418
1466
|
frame main \u8FD4\u56DE\u4E3B frame
|
|
1419
1467
|
dialog accept [text] \u63A5\u53D7\u5BF9\u8BDD\u6846\uFF08alert/confirm/prompt\uFF09
|
|
@@ -1433,6 +1481,7 @@ bb-browser - AI Agent \u6D4F\u89C8\u5668\u81EA\u52A8\u5316\u5DE5\u5177
|
|
|
1433
1481
|
\u9009\u9879\uFF1A
|
|
1434
1482
|
--json \u4EE5 JSON \u683C\u5F0F\u8F93\u51FA
|
|
1435
1483
|
-i, --interactive \u53EA\u8F93\u51FA\u53EF\u4EA4\u4E92\u5143\u7D20\uFF08snapshot \u547D\u4EE4\uFF09
|
|
1484
|
+
--tab <tabId> \u6307\u5B9A\u64CD\u4F5C\u7684\u6807\u7B7E\u9875 ID
|
|
1436
1485
|
--help, -h \u663E\u793A\u5E2E\u52A9\u4FE1\u606F
|
|
1437
1486
|
--version, -v \u663E\u793A\u7248\u672C\u53F7
|
|
1438
1487
|
|
|
@@ -1461,7 +1510,12 @@ function parseArgs(argv) {
|
|
|
1461
1510
|
interactive: false
|
|
1462
1511
|
}
|
|
1463
1512
|
};
|
|
1513
|
+
let skipNext = false;
|
|
1464
1514
|
for (const arg of args) {
|
|
1515
|
+
if (skipNext) {
|
|
1516
|
+
skipNext = false;
|
|
1517
|
+
continue;
|
|
1518
|
+
}
|
|
1465
1519
|
if (arg === "--json") {
|
|
1466
1520
|
result.flags.json = true;
|
|
1467
1521
|
} else if (arg === "--help" || arg === "-h") {
|
|
@@ -1470,6 +1524,10 @@ function parseArgs(argv) {
|
|
|
1470
1524
|
result.flags.version = true;
|
|
1471
1525
|
} else if (arg === "--interactive" || arg === "-i") {
|
|
1472
1526
|
result.flags.interactive = true;
|
|
1527
|
+
} else if (arg === "--id") {
|
|
1528
|
+
skipNext = true;
|
|
1529
|
+
} else if (arg === "--tab" && !result.command) {
|
|
1530
|
+
skipNext = true;
|
|
1473
1531
|
} else if (arg.startsWith("-")) {
|
|
1474
1532
|
} else if (result.command === null) {
|
|
1475
1533
|
result.command = arg;
|
|
@@ -1481,6 +1539,8 @@ function parseArgs(argv) {
|
|
|
1481
1539
|
}
|
|
1482
1540
|
async function main() {
|
|
1483
1541
|
const parsed = parseArgs(process.argv);
|
|
1542
|
+
const tabArgIdx = process.argv.indexOf("--tab");
|
|
1543
|
+
const globalTabId = tabArgIdx >= 0 && process.argv[tabArgIdx + 1] ? parseInt(process.argv[tabArgIdx + 1], 10) : void 0;
|
|
1484
1544
|
if (parsed.flags.version) {
|
|
1485
1545
|
console.log(VERSION);
|
|
1486
1546
|
return;
|
|
@@ -1504,7 +1564,7 @@ async function main() {
|
|
|
1504
1564
|
break;
|
|
1505
1565
|
}
|
|
1506
1566
|
case "snapshot": {
|
|
1507
|
-
await snapshotCommand({ json: parsed.flags.json, interactive: parsed.flags.interactive });
|
|
1567
|
+
await snapshotCommand({ json: parsed.flags.json, interactive: parsed.flags.interactive, tabId: globalTabId });
|
|
1508
1568
|
break;
|
|
1509
1569
|
}
|
|
1510
1570
|
case "click": {
|
|
@@ -1515,7 +1575,7 @@ async function main() {
|
|
|
1515
1575
|
console.error("\u793A\u4F8B\uFF1Abb-browser click @5");
|
|
1516
1576
|
process.exit(1);
|
|
1517
1577
|
}
|
|
1518
|
-
await clickCommand(ref, { json: parsed.flags.json });
|
|
1578
|
+
await clickCommand(ref, { json: parsed.flags.json, tabId: globalTabId });
|
|
1519
1579
|
break;
|
|
1520
1580
|
}
|
|
1521
1581
|
case "hover": {
|
|
@@ -1526,7 +1586,7 @@ async function main() {
|
|
|
1526
1586
|
console.error("\u793A\u4F8B\uFF1Abb-browser hover @5");
|
|
1527
1587
|
process.exit(1);
|
|
1528
1588
|
}
|
|
1529
|
-
await hoverCommand(ref, { json: parsed.flags.json });
|
|
1589
|
+
await hoverCommand(ref, { json: parsed.flags.json, tabId: globalTabId });
|
|
1530
1590
|
break;
|
|
1531
1591
|
}
|
|
1532
1592
|
case "check": {
|
|
@@ -1537,7 +1597,7 @@ async function main() {
|
|
|
1537
1597
|
console.error("\u793A\u4F8B\uFF1Abb-browser check @5");
|
|
1538
1598
|
process.exit(1);
|
|
1539
1599
|
}
|
|
1540
|
-
await checkCommand(ref, { json: parsed.flags.json });
|
|
1600
|
+
await checkCommand(ref, { json: parsed.flags.json, tabId: globalTabId });
|
|
1541
1601
|
break;
|
|
1542
1602
|
}
|
|
1543
1603
|
case "uncheck": {
|
|
@@ -1548,7 +1608,7 @@ async function main() {
|
|
|
1548
1608
|
console.error("\u793A\u4F8B\uFF1Abb-browser uncheck @5");
|
|
1549
1609
|
process.exit(1);
|
|
1550
1610
|
}
|
|
1551
|
-
await uncheckCommand(ref, { json: parsed.flags.json });
|
|
1611
|
+
await uncheckCommand(ref, { json: parsed.flags.json, tabId: globalTabId });
|
|
1552
1612
|
break;
|
|
1553
1613
|
}
|
|
1554
1614
|
case "fill": {
|
|
@@ -1566,7 +1626,7 @@ async function main() {
|
|
|
1566
1626
|
console.error('\u793A\u4F8B\uFF1Abb-browser fill @3 "hello world"');
|
|
1567
1627
|
process.exit(1);
|
|
1568
1628
|
}
|
|
1569
|
-
await fillCommand(ref, text, { json: parsed.flags.json });
|
|
1629
|
+
await fillCommand(ref, text, { json: parsed.flags.json, tabId: globalTabId });
|
|
1570
1630
|
break;
|
|
1571
1631
|
}
|
|
1572
1632
|
case "type": {
|
|
@@ -1584,7 +1644,7 @@ async function main() {
|
|
|
1584
1644
|
console.error('\u793A\u4F8B\uFF1Abb-browser type @3 "append text"');
|
|
1585
1645
|
process.exit(1);
|
|
1586
1646
|
}
|
|
1587
|
-
await typeCommand(ref, text, { json: parsed.flags.json });
|
|
1647
|
+
await typeCommand(ref, text, { json: parsed.flags.json, tabId: globalTabId });
|
|
1588
1648
|
break;
|
|
1589
1649
|
}
|
|
1590
1650
|
case "select": {
|
|
@@ -1602,7 +1662,7 @@ async function main() {
|
|
|
1602
1662
|
console.error('\u793A\u4F8B\uFF1Abb-browser select @4 "option1"');
|
|
1603
1663
|
process.exit(1);
|
|
1604
1664
|
}
|
|
1605
|
-
await selectCommand(ref, value, { json: parsed.flags.json });
|
|
1665
|
+
await selectCommand(ref, value, { json: parsed.flags.json, tabId: globalTabId });
|
|
1606
1666
|
break;
|
|
1607
1667
|
}
|
|
1608
1668
|
case "eval": {
|
|
@@ -1613,7 +1673,7 @@ async function main() {
|
|
|
1613
1673
|
console.error('\u793A\u4F8B\uFF1Abb-browser eval "document.title"');
|
|
1614
1674
|
process.exit(1);
|
|
1615
1675
|
}
|
|
1616
|
-
await evalCommand(script, { json: parsed.flags.json });
|
|
1676
|
+
await evalCommand(script, { json: parsed.flags.json, tabId: globalTabId });
|
|
1617
1677
|
break;
|
|
1618
1678
|
}
|
|
1619
1679
|
case "get": {
|
|
@@ -1631,7 +1691,7 @@ async function main() {
|
|
|
1631
1691
|
process.exit(1);
|
|
1632
1692
|
}
|
|
1633
1693
|
const ref = parsed.args[1];
|
|
1634
|
-
await getCommand(attribute, ref, { json: parsed.flags.json });
|
|
1694
|
+
await getCommand(attribute, ref, { json: parsed.flags.json, tabId: globalTabId });
|
|
1635
1695
|
break;
|
|
1636
1696
|
}
|
|
1637
1697
|
case "daemon":
|
|
@@ -1652,24 +1712,24 @@ async function main() {
|
|
|
1652
1712
|
break;
|
|
1653
1713
|
}
|
|
1654
1714
|
case "close": {
|
|
1655
|
-
await closeCommand({ json: parsed.flags.json });
|
|
1715
|
+
await closeCommand({ json: parsed.flags.json, tabId: globalTabId });
|
|
1656
1716
|
break;
|
|
1657
1717
|
}
|
|
1658
1718
|
case "back": {
|
|
1659
|
-
await backCommand({ json: parsed.flags.json });
|
|
1719
|
+
await backCommand({ json: parsed.flags.json, tabId: globalTabId });
|
|
1660
1720
|
break;
|
|
1661
1721
|
}
|
|
1662
1722
|
case "forward": {
|
|
1663
|
-
await forwardCommand({ json: parsed.flags.json });
|
|
1723
|
+
await forwardCommand({ json: parsed.flags.json, tabId: globalTabId });
|
|
1664
1724
|
break;
|
|
1665
1725
|
}
|
|
1666
1726
|
case "refresh": {
|
|
1667
|
-
await refreshCommand({ json: parsed.flags.json });
|
|
1727
|
+
await refreshCommand({ json: parsed.flags.json, tabId: globalTabId });
|
|
1668
1728
|
break;
|
|
1669
1729
|
}
|
|
1670
1730
|
case "screenshot": {
|
|
1671
1731
|
const outputPath = parsed.args[0];
|
|
1672
|
-
await screenshotCommand(outputPath, { json: parsed.flags.json });
|
|
1732
|
+
await screenshotCommand(outputPath, { json: parsed.flags.json, tabId: globalTabId });
|
|
1673
1733
|
break;
|
|
1674
1734
|
}
|
|
1675
1735
|
case "wait": {
|
|
@@ -1681,7 +1741,7 @@ async function main() {
|
|
|
1681
1741
|
console.error(" bb-browser wait @5");
|
|
1682
1742
|
process.exit(1);
|
|
1683
1743
|
}
|
|
1684
|
-
await waitCommand(target, { json: parsed.flags.json });
|
|
1744
|
+
await waitCommand(target, { json: parsed.flags.json, tabId: globalTabId });
|
|
1685
1745
|
break;
|
|
1686
1746
|
}
|
|
1687
1747
|
case "press": {
|
|
@@ -1693,7 +1753,7 @@ async function main() {
|
|
|
1693
1753
|
console.error(" bb-browser press Control+a");
|
|
1694
1754
|
process.exit(1);
|
|
1695
1755
|
}
|
|
1696
|
-
await pressCommand(key, { json: parsed.flags.json });
|
|
1756
|
+
await pressCommand(key, { json: parsed.flags.json, tabId: globalTabId });
|
|
1697
1757
|
break;
|
|
1698
1758
|
}
|
|
1699
1759
|
case "scroll": {
|
|
@@ -1706,7 +1766,7 @@ async function main() {
|
|
|
1706
1766
|
console.error(" bb-browser scroll up 500");
|
|
1707
1767
|
process.exit(1);
|
|
1708
1768
|
}
|
|
1709
|
-
await scrollCommand(direction, pixels, { json: parsed.flags.json });
|
|
1769
|
+
await scrollCommand(direction, pixels, { json: parsed.flags.json, tabId: globalTabId });
|
|
1710
1770
|
break;
|
|
1711
1771
|
}
|
|
1712
1772
|
case "tab": {
|
|
@@ -1723,9 +1783,9 @@ async function main() {
|
|
|
1723
1783
|
process.exit(1);
|
|
1724
1784
|
}
|
|
1725
1785
|
if (selectorOrMain === "main") {
|
|
1726
|
-
await frameMainCommand({ json: parsed.flags.json });
|
|
1786
|
+
await frameMainCommand({ json: parsed.flags.json, tabId: globalTabId });
|
|
1727
1787
|
} else {
|
|
1728
|
-
await frameCommand(selectorOrMain, { json: parsed.flags.json });
|
|
1788
|
+
await frameCommand(selectorOrMain, { json: parsed.flags.json, tabId: globalTabId });
|
|
1729
1789
|
}
|
|
1730
1790
|
break;
|
|
1731
1791
|
}
|
|
@@ -1740,7 +1800,7 @@ async function main() {
|
|
|
1740
1800
|
process.exit(1);
|
|
1741
1801
|
}
|
|
1742
1802
|
const promptText = parsed.args[1];
|
|
1743
|
-
await dialogCommand(subCommand, promptText, { json: parsed.flags.json });
|
|
1803
|
+
await dialogCommand(subCommand, promptText, { json: parsed.flags.json, tabId: globalTabId });
|
|
1744
1804
|
break;
|
|
1745
1805
|
}
|
|
1746
1806
|
case "network": {
|
|
@@ -1749,17 +1809,17 @@ async function main() {
|
|
|
1749
1809
|
const abort = process.argv.includes("--abort");
|
|
1750
1810
|
const bodyIndex = process.argv.findIndex((a) => a === "--body");
|
|
1751
1811
|
const body = bodyIndex >= 0 ? process.argv[bodyIndex + 1] : void 0;
|
|
1752
|
-
await networkCommand(subCommand, urlOrFilter, { json: parsed.flags.json, abort, body });
|
|
1812
|
+
await networkCommand(subCommand, urlOrFilter, { json: parsed.flags.json, abort, body, tabId: globalTabId });
|
|
1753
1813
|
break;
|
|
1754
1814
|
}
|
|
1755
1815
|
case "console": {
|
|
1756
1816
|
const clear = process.argv.includes("--clear");
|
|
1757
|
-
await consoleCommand({ json: parsed.flags.json, clear });
|
|
1817
|
+
await consoleCommand({ json: parsed.flags.json, clear, tabId: globalTabId });
|
|
1758
1818
|
break;
|
|
1759
1819
|
}
|
|
1760
1820
|
case "errors": {
|
|
1761
1821
|
const clear = process.argv.includes("--clear");
|
|
1762
|
-
await errorsCommand({ json: parsed.flags.json, clear });
|
|
1822
|
+
await errorsCommand({ json: parsed.flags.json, clear, tabId: globalTabId });
|
|
1763
1823
|
break;
|
|
1764
1824
|
}
|
|
1765
1825
|
case "trace": {
|
|
@@ -1772,7 +1832,7 @@ async function main() {
|
|
|
1772
1832
|
console.error(" bb-browser trace status");
|
|
1773
1833
|
process.exit(1);
|
|
1774
1834
|
}
|
|
1775
|
-
await traceCommand(subCmd, { json: parsed.flags.json });
|
|
1835
|
+
await traceCommand(subCmd, { json: parsed.flags.json, tabId: globalTabId });
|
|
1776
1836
|
break;
|
|
1777
1837
|
}
|
|
1778
1838
|
default: {
|