browser-opt 1.0.2 → 1.0.5
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/browser-core/agent.d.ts +131 -0
- package/dist/browser-core/agent.d.ts.map +1 -0
- package/dist/browser-core/agent.js +437 -0
- package/dist/browser-core/agent.js.map +1 -0
- package/dist/browser-core/browser-executable.d.ts +3 -0
- package/dist/browser-core/browser-executable.d.ts.map +1 -0
- package/dist/browser-core/browser-executable.js +49 -0
- package/dist/browser-core/browser-executable.js.map +1 -0
- package/dist/browser-core/index.d.ts +9 -0
- package/dist/browser-core/index.d.ts.map +1 -0
- package/dist/browser-core/index.js +7 -0
- package/dist/browser-core/index.js.map +1 -0
- package/dist/browser-core/proxy-env.d.ts +9 -0
- package/dist/browser-core/proxy-env.d.ts.map +1 -0
- package/dist/browser-core/proxy-env.js +77 -0
- package/dist/browser-core/proxy-env.js.map +1 -0
- package/dist/browser-core/skill-install.d.ts +15 -0
- package/dist/browser-core/skill-install.d.ts.map +1 -0
- package/dist/browser-core/skill-install.js +42 -0
- package/dist/browser-core/skill-install.js.map +1 -0
- package/dist/browser-core/types.d.ts +111 -0
- package/dist/browser-core/types.d.ts.map +1 -0
- package/dist/browser-core/types.js +2 -0
- package/dist/browser-core/types.js.map +1 -0
- package/dist/browser-opt/runner/actions/index.d.ts +1 -1
- package/dist/browser-opt/runner/actions/index.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/click-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/click-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/date-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/date-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/dom-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/dom-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/fill-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/fill-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/open-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/open-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/actions/utils/upload-action.d.ts +1 -1
- package/dist/browser-opt/runner/actions/utils/upload-action.d.ts.map +1 -1
- package/dist/browser-opt/runner/evidence.d.ts +1 -1
- package/dist/browser-opt/runner/evidence.d.ts.map +1 -1
- package/dist/browser-opt/runner/handoff.d.ts +1 -1
- package/dist/browser-opt/runner/handoff.d.ts.map +1 -1
- package/dist/browser-opt/runner/index.d.ts +1 -1
- package/dist/browser-opt/runner/index.d.ts.map +1 -1
- package/dist/browser-opt/runner/index.js +3 -1
- package/dist/browser-opt/runner/index.js.map +1 -1
- package/dist/browser-opt/runner/step-executor.d.ts +1 -1
- package/dist/browser-opt/runner/step-executor.d.ts.map +1 -1
- package/dist/browser-opt/type.d.ts +2 -2
- package/dist/browser-opt/type.d.ts.map +1 -1
- package/dist/browser-opt/utils.d.ts +1 -1
- package/dist/browser-opt/utils.d.ts.map +1 -1
- package/dist/browser-opt/workflow/matcher.d.ts.map +1 -1
- package/dist/browser-opt/workflow/matcher.js +12 -3
- package/dist/browser-opt/workflow/matcher.js.map +1 -1
- package/dist/cli/browser-opt.js +0 -0
- package/dist/cli/commands/browser-opt.d.ts.map +1 -1
- package/dist/cli/commands/browser-opt.js +22 -8
- package/dist/cli/commands/browser-opt.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +12 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +89 -11
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/utils/constants.d.ts +1 -1
- package/dist/cli/utils/constants.d.ts.map +1 -1
- package/dist/cli/utils/constants.js +11 -10
- package/dist/cli/utils/constants.js.map +1 -1
- package/package.json +19 -5
- package/skills/browser-opt/SKILL.md +36 -24
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { AgentOptions } from './types.js';
|
|
2
|
+
export interface AgentBrowserJsonResult {
|
|
3
|
+
raw: string;
|
|
4
|
+
data: unknown | null;
|
|
5
|
+
parseError?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BrowserTabInfo {
|
|
8
|
+
/** 当前标签页是否处于激活状态。 */
|
|
9
|
+
active: boolean;
|
|
10
|
+
/** agent-browser 返回的稳定标签页标识,可用于后续切换。 */
|
|
11
|
+
tabId: string;
|
|
12
|
+
/** 浏览器标签页标题。 */
|
|
13
|
+
title: string;
|
|
14
|
+
/** 浏览器标签页类型,例如 `page`。 */
|
|
15
|
+
type: string;
|
|
16
|
+
/** 当前标签页地址。 */
|
|
17
|
+
url: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* `agent-browser` CLI 的封装层。
|
|
21
|
+
*
|
|
22
|
+
* 每个实例都维护一个由 `sessionId` 标识的独立浏览器会话,并通过 `spawnSync`
|
|
23
|
+
* 同步执行命令,让上层无需自行处理额外的子进程异步编排。
|
|
24
|
+
*/
|
|
25
|
+
export declare class BrowserAgent {
|
|
26
|
+
private static autoOpenedDashboardUrls;
|
|
27
|
+
private readonly sessionId;
|
|
28
|
+
private readonly namespace;
|
|
29
|
+
private readonly sessionName;
|
|
30
|
+
private readonly timeout;
|
|
31
|
+
private readonly headed;
|
|
32
|
+
private readonly forceHeadless;
|
|
33
|
+
private readonly openLiveDashboard;
|
|
34
|
+
private readonly profile;
|
|
35
|
+
private readonly executablePath;
|
|
36
|
+
private readonly statePath;
|
|
37
|
+
private readonly reuseRunningBrowser;
|
|
38
|
+
private readonly browserArgs;
|
|
39
|
+
private liveViewportReady;
|
|
40
|
+
private browserOpened;
|
|
41
|
+
constructor(options?: AgentOptions);
|
|
42
|
+
/** 返回当前 agent 使用的 agent-browser 会话 id。 */
|
|
43
|
+
getSessionId(): string;
|
|
44
|
+
getLiveViewportUrl(): string | null;
|
|
45
|
+
/** 统一拼接 agent-browser 的全局参数,保证不同命令共享同一套会话与启动策略。 */
|
|
46
|
+
private buildGlobalArgs;
|
|
47
|
+
private resultErrorMessage;
|
|
48
|
+
/** 固定 agent-browser 使用系统标准 Chrome,防止已下载的测试浏览器被优先选中。 */
|
|
49
|
+
private createCommandEnvironment;
|
|
50
|
+
/** 底层命令执行入口,负责调用单条 agent-browser 命令并返回 stdout。 */
|
|
51
|
+
private run;
|
|
52
|
+
private runBestEffort;
|
|
53
|
+
private runSystemBestEffort;
|
|
54
|
+
private autoOpenDashboard;
|
|
55
|
+
private ensureLiveViewport;
|
|
56
|
+
detectHandoffChallenge(extraText?: string): {
|
|
57
|
+
detected: boolean;
|
|
58
|
+
categories: string[];
|
|
59
|
+
evidence: string[];
|
|
60
|
+
};
|
|
61
|
+
/** 打开指定 URL。 */
|
|
62
|
+
open(url: string): string;
|
|
63
|
+
/** 通过当前浏览器的 CDP 连接,在活动页面所在 Chrome 窗口中打开原生 DevTools。 */
|
|
64
|
+
inspect(): Promise<string>;
|
|
65
|
+
/** 等待 CDP WebSocket 建立连接,并在 agent 超时时间内给出明确失败。 */
|
|
66
|
+
private waitForWebSocketOpen;
|
|
67
|
+
/** 发送单条 CDP 指令并校验协议响应,避免实验性能力失败时仍报告成功。 */
|
|
68
|
+
private sendCdpCommand;
|
|
69
|
+
/** 刷新当前页面,用于处理 SPA 首次进入后卡在半初始化状态的场景。 */
|
|
70
|
+
reload(): string;
|
|
71
|
+
/** 通过 ref 点击元素,例如 snapshot 结果中的 e5。 */
|
|
72
|
+
click(ref: string): string;
|
|
73
|
+
/** 通过 ref 填充输入框,例如 snapshot 结果中的 e10。 */
|
|
74
|
+
fill(ref: string, value: string): string;
|
|
75
|
+
/** 通过 ref 或选择器把本地文件上传到文件选择控件。 */
|
|
76
|
+
upload(refOrSelector: string, filePaths: string[]): string;
|
|
77
|
+
/** 等待 URL 命中某个模式,例如 `/Home`。 */
|
|
78
|
+
waitForUrl(pattern: string): string;
|
|
79
|
+
/** 等待页面出现指定文本。 */
|
|
80
|
+
waitForText(text: string): string;
|
|
81
|
+
/** 按毫秒固定等待一段时间。 */
|
|
82
|
+
waitMs(ms: number): string;
|
|
83
|
+
/** 滚动页面,让当前可交互快照覆盖更大范围的长表单。 */
|
|
84
|
+
scroll(direction: 'up' | 'down' | 'left' | 'right', amount?: number): string;
|
|
85
|
+
/**
|
|
86
|
+
* 通过 `agent-browser chat` 执行自然语言指令。
|
|
87
|
+
* CLI 会解释这段指令,并完成对应的浏览器动作。
|
|
88
|
+
*/
|
|
89
|
+
chat(instruction: string): string;
|
|
90
|
+
/** 在 agent-browser 支持时,以 JSON 输出执行自然语言指令。 */
|
|
91
|
+
chatJson(instruction: string): AgentBrowserJsonResult;
|
|
92
|
+
/** 获取只包含可交互元素的无障碍树快照,便于做断言。 */
|
|
93
|
+
snapshot(): string;
|
|
94
|
+
/** 获取机器可读的可交互无障碍树快照。 */
|
|
95
|
+
snapshotJson(): AgentBrowserJsonResult;
|
|
96
|
+
/** 保存当前会话的 cookies 与 storage,用于后续以干净窗口复用登录态。 */
|
|
97
|
+
stateSave(path: string): string;
|
|
98
|
+
/** 加载已保存的 cookies 与 storage,用于干净窗口复用登录态。 */
|
|
99
|
+
stateLoad(path: string): string;
|
|
100
|
+
/** 截图。 */
|
|
101
|
+
screenshot(path?: string): string;
|
|
102
|
+
/** 在页面上下文中执行 JavaScript,用于读取快照无法可靠表达的控件状态。 */
|
|
103
|
+
evaluate(script: string): string;
|
|
104
|
+
/** 获取当前页面标题。 */
|
|
105
|
+
getTitle(): string;
|
|
106
|
+
/** 获取当前页面 URL。 */
|
|
107
|
+
getUrl(): string;
|
|
108
|
+
/** 获取当前浏览器窗口中的页面标签页,供上层从意外的空白活动页恢复。 */
|
|
109
|
+
getTabs(): BrowserTabInfo[];
|
|
110
|
+
/** 切换到指定稳定标签页 id。 */
|
|
111
|
+
switchTab(tabId: string): string;
|
|
112
|
+
/**
|
|
113
|
+
* 在一次进程调用中串行执行多条命令,减少多次启动命令的开销。
|
|
114
|
+
* `commands` 中的每一项都是参数数组,例如 `['open', 'https://example.com']`。
|
|
115
|
+
*/
|
|
116
|
+
batch(commands: string[][]): string;
|
|
117
|
+
/** 记录项目级人工接管状态;暂停与恢复由上层控制,不向 agent-browser 发送伪命令。 */
|
|
118
|
+
handoff(message: string): string;
|
|
119
|
+
/** 标记项目级人工接管结束;后续自动化直接复用当前浏览器 session。 */
|
|
120
|
+
resume(): string;
|
|
121
|
+
/** 关闭浏览器会话;这里吞掉异常,保证清理阶段尽量顺利完成。 */
|
|
122
|
+
close(): void;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 创建 {@link BrowserAgent} 的工厂函数。
|
|
126
|
+
* 这里作为首选入口,方便测试时替换实现,而不需要直接 mock ES module 类构造函数。
|
|
127
|
+
*/
|
|
128
|
+
export declare function createBrowserAgent(options?: AgentOptions): BrowserAgent;
|
|
129
|
+
/** agent 工厂的类型别名,便于调用方约束注入的工厂签名。 */
|
|
130
|
+
export type BrowserAgentFactory = typeof createBrowserAgent;
|
|
131
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../browser-core/src/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 封装 agent-browser CLI,提供两个对外产物共享的浏览器 session、截图和 handoff 能力。
|
|
3
|
+
*/
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { resolveSystemChromeExecutable } from './browser-executable.js';
|
|
7
|
+
import { createAgentBrowserEnvironment } from './proxy-env.js';
|
|
8
|
+
const DEFAULT_TIMEOUT = 30_000;
|
|
9
|
+
const DEFAULT_DASHBOARD_PORT = 4848;
|
|
10
|
+
const DEFAULT_STREAM_PORT = 9223;
|
|
11
|
+
const DEFAULT_CLEAN_BROWSER_ARGS = [
|
|
12
|
+
'--disable-session-crashed-bubble',
|
|
13
|
+
'--no-first-run',
|
|
14
|
+
'--no-default-browser-check',
|
|
15
|
+
];
|
|
16
|
+
const AGENT_BROWSER_INSTALL_HINT = '请先安装 agent-browser,例如:npm install -g agent-browser。';
|
|
17
|
+
function parseJsonOutput(raw) {
|
|
18
|
+
try {
|
|
19
|
+
return {
|
|
20
|
+
raw,
|
|
21
|
+
data: JSON.parse(raw),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return {
|
|
26
|
+
raw,
|
|
27
|
+
data: null,
|
|
28
|
+
parseError: err instanceof Error ? err.message : String(err),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `agent-browser` CLI 的封装层。
|
|
34
|
+
*
|
|
35
|
+
* 每个实例都维护一个由 `sessionId` 标识的独立浏览器会话,并通过 `spawnSync`
|
|
36
|
+
* 同步执行命令,让上层无需自行处理额外的子进程异步编排。
|
|
37
|
+
*/
|
|
38
|
+
export class BrowserAgent {
|
|
39
|
+
static autoOpenedDashboardUrls = new Set();
|
|
40
|
+
sessionId;
|
|
41
|
+
namespace;
|
|
42
|
+
sessionName;
|
|
43
|
+
timeout;
|
|
44
|
+
headed;
|
|
45
|
+
forceHeadless;
|
|
46
|
+
openLiveDashboard;
|
|
47
|
+
profile;
|
|
48
|
+
executablePath;
|
|
49
|
+
statePath;
|
|
50
|
+
reuseRunningBrowser;
|
|
51
|
+
browserArgs;
|
|
52
|
+
liveViewportReady;
|
|
53
|
+
browserOpened;
|
|
54
|
+
constructor(options = {}) {
|
|
55
|
+
this.sessionId = options.sessionId ?? `browser-agent-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
56
|
+
this.namespace = options.namespace ?? null;
|
|
57
|
+
this.sessionName = options.sessionName ?? null;
|
|
58
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
59
|
+
this.headed = options.headed ?? options.liveViewport ?? false;
|
|
60
|
+
this.forceHeadless = options.headless ?? false;
|
|
61
|
+
this.openLiveDashboard = options.openLiveDashboard ?? true;
|
|
62
|
+
this.profile = options.profile ?? null;
|
|
63
|
+
this.executablePath = options.executablePath ?? resolveSystemChromeExecutable() ?? null;
|
|
64
|
+
this.statePath = options.statePath ?? null;
|
|
65
|
+
this.reuseRunningBrowser = options.reuseRunningBrowser ?? false;
|
|
66
|
+
this.browserArgs =
|
|
67
|
+
options.browserArgs ??
|
|
68
|
+
(!this.profile && (!this.reuseRunningBrowser || this.statePath) ? DEFAULT_CLEAN_BROWSER_ARGS : []);
|
|
69
|
+
this.liveViewportReady = false;
|
|
70
|
+
this.browserOpened = false;
|
|
71
|
+
}
|
|
72
|
+
/** 返回当前 agent 使用的 agent-browser 会话 id。 */
|
|
73
|
+
getSessionId() {
|
|
74
|
+
return this.sessionId;
|
|
75
|
+
}
|
|
76
|
+
getLiveViewportUrl() {
|
|
77
|
+
return this.headed ? `http://localhost:${DEFAULT_DASHBOARD_PORT}` : null;
|
|
78
|
+
}
|
|
79
|
+
/** 统一拼接 agent-browser 的全局参数,保证不同命令共享同一套会话与启动策略。 */
|
|
80
|
+
buildGlobalArgs(args, useHeaded, options = {}) {
|
|
81
|
+
const profile = Object.hasOwn(options, 'profile') ? options.profile ?? null : this.profile;
|
|
82
|
+
const statePath = Object.hasOwn(options, 'statePath') ? options.statePath ?? null : this.statePath;
|
|
83
|
+
const reuseRunningBrowser = options.reuseRunningBrowser ?? (this.reuseRunningBrowser && !profile && !statePath);
|
|
84
|
+
const browserArgs = options.browserArgs ?? this.browserArgs;
|
|
85
|
+
const isBrowserLaunch = args[0] === 'open' && !this.browserOpened;
|
|
86
|
+
const hasBrowserLaunch = args[0] === 'open' || this.browserOpened;
|
|
87
|
+
const useNamedSession = !profile;
|
|
88
|
+
return [
|
|
89
|
+
// profile 模式不使用 session id,后续命令必须持续携带 profile 才能命中同一浏览器会话。
|
|
90
|
+
...(profile ? ['--profile', profile] : []),
|
|
91
|
+
...(this.sessionName ? ['--session-name', this.sessionName] : []),
|
|
92
|
+
...(statePath && isBrowserLaunch ? ['--state', statePath] : []),
|
|
93
|
+
...(reuseRunningBrowser ? ['--auto-connect'] : []),
|
|
94
|
+
...(useNamedSession ? ['--session', this.sessionId] : []),
|
|
95
|
+
...(useHeaded ? ['--headed'] : this.forceHeadless ? ['--headed', 'false'] : []),
|
|
96
|
+
...(hasBrowserLaunch && browserArgs.length > 0
|
|
97
|
+
? ['--args', browserArgs.join(',')]
|
|
98
|
+
: []),
|
|
99
|
+
...args,
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
resultErrorMessage(result, fallback) {
|
|
103
|
+
const stderr = result.stderr?.trim() || '';
|
|
104
|
+
const stdout = result.stdout?.trim() || '';
|
|
105
|
+
return stderr || stdout || fallback;
|
|
106
|
+
}
|
|
107
|
+
/** 固定 agent-browser 使用系统标准 Chrome,防止已下载的测试浏览器被优先选中。 */
|
|
108
|
+
createCommandEnvironment() {
|
|
109
|
+
return {
|
|
110
|
+
...createAgentBrowserEnvironment(),
|
|
111
|
+
...(this.namespace ? { AGENT_BROWSER_NAMESPACE: this.namespace } : {}),
|
|
112
|
+
...(this.executablePath ? { AGENT_BROWSER_EXECUTABLE_PATH: this.executablePath } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** 底层命令执行入口,负责调用单条 agent-browser 命令并返回 stdout。 */
|
|
116
|
+
run(args, options = {}) {
|
|
117
|
+
const useHeaded = options.headed ?? this.headed;
|
|
118
|
+
const result = spawnSync('agent-browser', this.buildGlobalArgs(args, useHeaded, Object.hasOwn(options, 'statePath') ? { statePath: options.statePath } : {}), { encoding: 'utf-8', timeout: this.timeout, env: this.createCommandEnvironment() });
|
|
119
|
+
if (result.error) {
|
|
120
|
+
throw new Error(`无法启动 agent-browser:${result.error.message}。${AGENT_BROWSER_INSTALL_HINT}`);
|
|
121
|
+
}
|
|
122
|
+
if (result.status !== 0) {
|
|
123
|
+
throw new Error(this.resultErrorMessage(result, `agent-browser exited with code ${result.status}`));
|
|
124
|
+
}
|
|
125
|
+
if (args[0] === 'open') {
|
|
126
|
+
this.browserOpened = true;
|
|
127
|
+
}
|
|
128
|
+
else if (args[0] === 'close') {
|
|
129
|
+
this.browserOpened = false;
|
|
130
|
+
}
|
|
131
|
+
if (useHeaded && this.openLiveDashboard && args[0] === 'open') {
|
|
132
|
+
this.ensureLiveViewport();
|
|
133
|
+
}
|
|
134
|
+
return result.stdout ?? '';
|
|
135
|
+
}
|
|
136
|
+
runBestEffort(args) {
|
|
137
|
+
return spawnSync('agent-browser', args, {
|
|
138
|
+
encoding: 'utf-8',
|
|
139
|
+
timeout: this.timeout,
|
|
140
|
+
env: this.createCommandEnvironment(),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
runSystemBestEffort(command, args) {
|
|
144
|
+
return spawnSync(command, args, {
|
|
145
|
+
encoding: 'utf-8',
|
|
146
|
+
timeout: this.timeout,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
autoOpenDashboard(url) {
|
|
150
|
+
if (BrowserAgent.autoOpenedDashboardUrls.has(url)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
BrowserAgent.autoOpenedDashboardUrls.add(url);
|
|
154
|
+
if (process.platform === 'darwin') {
|
|
155
|
+
this.runSystemBestEffort('open', [url]);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (process.platform === 'win32') {
|
|
159
|
+
this.runSystemBestEffort('cmd', ['/c', 'start', '', url]);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.runSystemBestEffort('xdg-open', [url]);
|
|
163
|
+
}
|
|
164
|
+
ensureLiveViewport() {
|
|
165
|
+
if (this.liveViewportReady) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.runBestEffort(['dashboard', 'start', '--port', String(DEFAULT_DASHBOARD_PORT)]);
|
|
169
|
+
const statusResult = this.runBestEffort(['--session', this.sessionId, 'stream', 'status']);
|
|
170
|
+
const statusText = `${statusResult?.stdout ?? ''}\n${statusResult?.stderr ?? ''}`;
|
|
171
|
+
if (!statusText.includes(`:${DEFAULT_STREAM_PORT}`)) {
|
|
172
|
+
if (/Streaming enabled/i.test(statusText)) {
|
|
173
|
+
this.runBestEffort(['--session', this.sessionId, 'stream', 'disable']);
|
|
174
|
+
}
|
|
175
|
+
this.runBestEffort(['--session', this.sessionId, 'stream', 'enable', '--port', String(DEFAULT_STREAM_PORT)]);
|
|
176
|
+
}
|
|
177
|
+
const dashboardUrl = this.getLiveViewportUrl();
|
|
178
|
+
if (dashboardUrl) {
|
|
179
|
+
this.autoOpenDashboard(dashboardUrl);
|
|
180
|
+
}
|
|
181
|
+
this.liveViewportReady = true;
|
|
182
|
+
}
|
|
183
|
+
detectHandoffChallenge(extraText) {
|
|
184
|
+
const evidence = [];
|
|
185
|
+
const categories = [];
|
|
186
|
+
let snapshotText = '';
|
|
187
|
+
let urlText = '';
|
|
188
|
+
try {
|
|
189
|
+
snapshotText = this.snapshot().toLowerCase();
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// 这里只做尽力探测,不影响主流程。
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
urlText = this.getUrl().toLowerCase();
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// 这里只做尽力探测,不影响主流程。
|
|
199
|
+
}
|
|
200
|
+
const combined = `${snapshotText}\n${urlText}\n${extraText ?? ''}`.toLowerCase();
|
|
201
|
+
const patterns = [
|
|
202
|
+
{ category: 'CAPTCHA', regex: /(recaptcha|g-recaptcha|hcaptcha|h-captcha|turnstile|cloudflare\s*challenge|verify\s*you\s*are\s*human|机器人验证|验证码)/i, hint: 'captcha/bot verification markers' },
|
|
203
|
+
{ category: 'OAuth', regex: /(oauth|authorize\b|consent\b|continue\s+with|sign\s+in\s+with|登录授权|第三方登录)/i, hint: 'oauth or third-party authorization markers' },
|
|
204
|
+
{ category: 'MFA', regex: /(two[ -]?factor|2fa|mfa|authenticator|one[ -]?time\s*password|otp|sms\s*code|verification\s*code|动态码|短信验证码)/i, hint: 'multi-factor verification markers' },
|
|
205
|
+
];
|
|
206
|
+
for (const pattern of patterns) {
|
|
207
|
+
if (pattern.regex.test(combined)) {
|
|
208
|
+
categories.push(pattern.category);
|
|
209
|
+
evidence.push(pattern.hint);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
detected: categories.length > 0,
|
|
214
|
+
categories,
|
|
215
|
+
evidence,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/** 打开指定 URL。 */
|
|
219
|
+
open(url) {
|
|
220
|
+
return this.run(['open', url]);
|
|
221
|
+
}
|
|
222
|
+
/** 通过当前浏览器的 CDP 连接,在活动页面所在 Chrome 窗口中打开原生 DevTools。 */
|
|
223
|
+
async inspect() {
|
|
224
|
+
const currentUrl = this.getUrl();
|
|
225
|
+
const cdpUrl = this.run(['get', 'cdp-url']).trim();
|
|
226
|
+
const socket = new WebSocket(cdpUrl);
|
|
227
|
+
try {
|
|
228
|
+
await this.waitForWebSocketOpen(socket);
|
|
229
|
+
const targetList = await this.sendCdpCommand(socket, 1, 'Target.getTargets');
|
|
230
|
+
const target = targetList.targetInfos.find((candidate) => (candidate.type === 'page' && candidate.url === currentUrl));
|
|
231
|
+
if (!target) {
|
|
232
|
+
throw new Error(`无法在 CDP target 列表中定位当前页面:${currentUrl}`);
|
|
233
|
+
}
|
|
234
|
+
const opened = await this.sendCdpCommand(socket, 2, 'Target.openDevTools', {
|
|
235
|
+
targetId: target.targetId,
|
|
236
|
+
});
|
|
237
|
+
return `Chrome 原生 DevTools 已打开:${opened.targetId}`;
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
socket.close();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** 等待 CDP WebSocket 建立连接,并在 agent 超时时间内给出明确失败。 */
|
|
244
|
+
waitForWebSocketOpen(socket) {
|
|
245
|
+
return new Promise((resolve, reject) => {
|
|
246
|
+
const timer = setTimeout(() => reject(new Error('连接 Chrome DevTools Protocol 超时')), this.timeout);
|
|
247
|
+
socket.addEventListener('open', () => {
|
|
248
|
+
clearTimeout(timer);
|
|
249
|
+
resolve();
|
|
250
|
+
}, { once: true });
|
|
251
|
+
socket.addEventListener('error', () => {
|
|
252
|
+
clearTimeout(timer);
|
|
253
|
+
reject(new Error('无法连接 Chrome DevTools Protocol'));
|
|
254
|
+
}, { once: true });
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/** 发送单条 CDP 指令并校验协议响应,避免实验性能力失败时仍报告成功。 */
|
|
258
|
+
sendCdpCommand(socket, id, method, params) {
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
const timer = setTimeout(() => reject(new Error(`CDP 指令超时:${method}`)), this.timeout);
|
|
261
|
+
const handleMessage = (event) => {
|
|
262
|
+
const response = JSON.parse(String(event.data));
|
|
263
|
+
if (response.id !== id) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
clearTimeout(timer);
|
|
267
|
+
socket.removeEventListener('message', handleMessage);
|
|
268
|
+
if (response.error) {
|
|
269
|
+
reject(new Error(`CDP ${method} 失败:${response.error.message}`));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (!response.result) {
|
|
273
|
+
reject(new Error(`CDP ${method} 未返回结果`));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
resolve(response.result);
|
|
277
|
+
};
|
|
278
|
+
socket.addEventListener('message', handleMessage);
|
|
279
|
+
socket.send(JSON.stringify({ id, method, ...(params ? { params } : {}) }));
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/** 刷新当前页面,用于处理 SPA 首次进入后卡在半初始化状态的场景。 */
|
|
283
|
+
reload() {
|
|
284
|
+
return this.evaluate('window.location.reload()');
|
|
285
|
+
}
|
|
286
|
+
/** 通过 ref 点击元素,例如 snapshot 结果中的 e5。 */
|
|
287
|
+
click(ref) {
|
|
288
|
+
return this.run(['click', `@${ref.replace(/^@/, '')}`]);
|
|
289
|
+
}
|
|
290
|
+
/** 通过 ref 填充输入框,例如 snapshot 结果中的 e10。 */
|
|
291
|
+
fill(ref, value) {
|
|
292
|
+
return this.run(['fill', `@${ref.replace(/^@/, '')}`, value]);
|
|
293
|
+
}
|
|
294
|
+
/** 通过 ref 或选择器把本地文件上传到文件选择控件。 */
|
|
295
|
+
upload(refOrSelector, filePaths) {
|
|
296
|
+
const target = /^@/.test(refOrSelector)
|
|
297
|
+
? refOrSelector
|
|
298
|
+
: /^[a-z]\d+$/i.test(refOrSelector)
|
|
299
|
+
? `@${refOrSelector}`
|
|
300
|
+
: refOrSelector;
|
|
301
|
+
return this.run(['upload', target, ...filePaths]);
|
|
302
|
+
}
|
|
303
|
+
/** 等待 URL 命中某个模式,例如 `/Home`。 */
|
|
304
|
+
waitForUrl(pattern) {
|
|
305
|
+
return this.run(['wait', '--url', pattern]);
|
|
306
|
+
}
|
|
307
|
+
/** 等待页面出现指定文本。 */
|
|
308
|
+
waitForText(text) {
|
|
309
|
+
return this.run(['wait', '--text', text]);
|
|
310
|
+
}
|
|
311
|
+
/** 按毫秒固定等待一段时间。 */
|
|
312
|
+
waitMs(ms) {
|
|
313
|
+
return this.run(['wait', String(ms)]);
|
|
314
|
+
}
|
|
315
|
+
/** 滚动页面,让当前可交互快照覆盖更大范围的长表单。 */
|
|
316
|
+
scroll(direction, amount = 600) {
|
|
317
|
+
return this.run(['scroll', direction, String(amount)]);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* 通过 `agent-browser chat` 执行自然语言指令。
|
|
321
|
+
* CLI 会解释这段指令,并完成对应的浏览器动作。
|
|
322
|
+
*/
|
|
323
|
+
chat(instruction) {
|
|
324
|
+
return this.run(['chat', instruction]);
|
|
325
|
+
}
|
|
326
|
+
/** 在 agent-browser 支持时,以 JSON 输出执行自然语言指令。 */
|
|
327
|
+
chatJson(instruction) {
|
|
328
|
+
return parseJsonOutput(this.run(['chat', instruction, '--json']));
|
|
329
|
+
}
|
|
330
|
+
/** 获取只包含可交互元素的无障碍树快照,便于做断言。 */
|
|
331
|
+
snapshot() {
|
|
332
|
+
return this.run(['snapshot', '-i']);
|
|
333
|
+
}
|
|
334
|
+
/** 获取机器可读的可交互无障碍树快照。 */
|
|
335
|
+
snapshotJson() {
|
|
336
|
+
return parseJsonOutput(this.run(['snapshot', '-i', '--json']));
|
|
337
|
+
}
|
|
338
|
+
/** 保存当前会话的 cookies 与 storage,用于后续以干净窗口复用登录态。 */
|
|
339
|
+
stateSave(path) {
|
|
340
|
+
return this.run(['state', 'save', path], { statePath: null });
|
|
341
|
+
}
|
|
342
|
+
/** 加载已保存的 cookies 与 storage,用于干净窗口复用登录态。 */
|
|
343
|
+
stateLoad(path) {
|
|
344
|
+
return this.run(['state', 'load', path], { statePath: null });
|
|
345
|
+
}
|
|
346
|
+
/** 截图。 */
|
|
347
|
+
screenshot(path) {
|
|
348
|
+
return this.run(path ? ['screenshot', path] : ['screenshot']);
|
|
349
|
+
}
|
|
350
|
+
/** 在页面上下文中执行 JavaScript,用于读取快照无法可靠表达的控件状态。 */
|
|
351
|
+
evaluate(script) {
|
|
352
|
+
return this.run(['eval', script]);
|
|
353
|
+
}
|
|
354
|
+
/** 获取当前页面标题。 */
|
|
355
|
+
getTitle() {
|
|
356
|
+
return this.run(['get', 'title']).trim();
|
|
357
|
+
}
|
|
358
|
+
/** 获取当前页面 URL。 */
|
|
359
|
+
getUrl() {
|
|
360
|
+
return this.run(['get', 'url']).trim();
|
|
361
|
+
}
|
|
362
|
+
/** 获取当前浏览器窗口中的页面标签页,供上层从意外的空白活动页恢复。 */
|
|
363
|
+
getTabs() {
|
|
364
|
+
const output = parseJsonOutput(this.run(['tab', 'list', '--json']));
|
|
365
|
+
if (!output.data || typeof output.data !== 'object') {
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
const data = output.data;
|
|
369
|
+
if (!Array.isArray(data.data?.tabs)) {
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
return data.data.tabs.filter((tab) => {
|
|
373
|
+
if (!tab || typeof tab !== 'object') {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
const candidate = tab;
|
|
377
|
+
return typeof candidate.tabId === 'string'
|
|
378
|
+
&& typeof candidate.url === 'string'
|
|
379
|
+
&& typeof candidate.title === 'string'
|
|
380
|
+
&& typeof candidate.type === 'string'
|
|
381
|
+
&& typeof candidate.active === 'boolean';
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/** 切换到指定稳定标签页 id。 */
|
|
385
|
+
switchTab(tabId) {
|
|
386
|
+
return this.run(['tab', tabId]);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* 在一次进程调用中串行执行多条命令,减少多次启动命令的开销。
|
|
390
|
+
* `commands` 中的每一项都是参数数组,例如 `['open', 'https://example.com']`。
|
|
391
|
+
*/
|
|
392
|
+
batch(commands) {
|
|
393
|
+
const result = spawnSync('agent-browser', this.buildGlobalArgs(['batch', '--json'], this.headed), {
|
|
394
|
+
input: JSON.stringify(commands),
|
|
395
|
+
encoding: 'utf-8',
|
|
396
|
+
timeout: this.timeout * commands.length,
|
|
397
|
+
env: this.createCommandEnvironment(),
|
|
398
|
+
});
|
|
399
|
+
if (result.error) {
|
|
400
|
+
throw new Error(`无法启动 agent-browser:${result.error.message}。${AGENT_BROWSER_INSTALL_HINT}`);
|
|
401
|
+
}
|
|
402
|
+
if (result.status !== 0) {
|
|
403
|
+
const stderr = result.stderr?.trim() || '';
|
|
404
|
+
throw new Error(stderr || `agent-browser batch exited with code ${result.status}`);
|
|
405
|
+
}
|
|
406
|
+
return result.stdout ?? '';
|
|
407
|
+
}
|
|
408
|
+
/** 记录项目级人工接管状态;暂停与恢复由上层控制,不向 agent-browser 发送伪命令。 */
|
|
409
|
+
handoff(message) {
|
|
410
|
+
return [
|
|
411
|
+
'HANDOFF: reusing the current browser session for manual interaction.',
|
|
412
|
+
`Session: ${this.sessionId}`,
|
|
413
|
+
`Reason: ${message}`,
|
|
414
|
+
].join('\n');
|
|
415
|
+
}
|
|
416
|
+
/** 标记项目级人工接管结束;后续自动化直接复用当前浏览器 session。 */
|
|
417
|
+
resume() {
|
|
418
|
+
return `RESUME: continuing browser session ${this.sessionId}.`;
|
|
419
|
+
}
|
|
420
|
+
/** 关闭浏览器会话;这里吞掉异常,保证清理阶段尽量顺利完成。 */
|
|
421
|
+
close() {
|
|
422
|
+
try {
|
|
423
|
+
this.run(['close']);
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
// 清理阶段忽略关闭失败,常见原因是会话已经提前结束。
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* 创建 {@link BrowserAgent} 的工厂函数。
|
|
432
|
+
* 这里作为首选入口,方便测试时替换实现,而不需要直接 mock ES module 类构造函数。
|
|
433
|
+
*/
|
|
434
|
+
export function createBrowserAgent(options) {
|
|
435
|
+
return new BrowserAgent(options);
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../browser-core/src/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-executable.d.ts","sourceRoot":"","sources":["../../../browser-core/src/browser-executable.ts"],"names":[],"mappings":"AAOA,qCAAqC;AACrC,wBAAgB,6BAA6B,CAAC,cAAc,qBAA4C,GAAG,MAAM,GAAG,SAAS,CAY5H"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 解析本机标准 Chrome 的可执行文件,供运行时和环境安装检查共用。
|
|
3
|
+
* 这里刻意不回退到 Playwright 下载的 Chrome for Testing,避免浏览器身份和用户登录态发生漂移。
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
/** 优先采用显式配置,否则按操作系统约定查找标准 Chrome。 */
|
|
8
|
+
export function resolveSystemChromeExecutable(configuredPath = process.env.AGENT_BROWSER_EXECUTABLE_PATH) {
|
|
9
|
+
const explicitPath = configuredPath?.trim();
|
|
10
|
+
if (explicitPath) {
|
|
11
|
+
return isExecutableFile(explicitPath) ? path.resolve(explicitPath) : undefined;
|
|
12
|
+
}
|
|
13
|
+
for (const candidate of systemChromeCandidates()) {
|
|
14
|
+
if (isExecutableFile(candidate)) {
|
|
15
|
+
return candidate;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/** 返回各平台标准 Chrome 的候选路径,不包含测试浏览器和 Playwright 缓存。 */
|
|
21
|
+
function systemChromeCandidates() {
|
|
22
|
+
if (process.platform === 'darwin') {
|
|
23
|
+
return [
|
|
24
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
25
|
+
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
if (process.platform === 'win32') {
|
|
29
|
+
return [
|
|
30
|
+
process.env.LOCALAPPDATA ? path.join(process.env.LOCALAPPDATA, 'Google/Chrome/Application/chrome.exe') : '',
|
|
31
|
+
'C:/Program Files/Google/Chrome/Application/chrome.exe',
|
|
32
|
+
'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe',
|
|
33
|
+
].filter(Boolean);
|
|
34
|
+
}
|
|
35
|
+
const executableNames = ['google-chrome', 'google-chrome-stable'];
|
|
36
|
+
return (process.env.PATH ?? '')
|
|
37
|
+
.split(path.delimiter)
|
|
38
|
+
.flatMap((directory) => executableNames.map((name) => path.join(directory, name)));
|
|
39
|
+
}
|
|
40
|
+
function isExecutableFile(filePath) {
|
|
41
|
+
try {
|
|
42
|
+
fs.accessSync(filePath, fs.constants.X_OK);
|
|
43
|
+
return fs.statSync(filePath).isFile();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=browser-executable.js.map
|