@mearl/client 2.7.0 → 2.7.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/README.md +6 -3
- package/dist/actionTimeouts.js +6 -0
- package/dist/cli.js +52 -11
- package/dist/commandSuggestions.d.ts +13 -0
- package/dist/commandSuggestions.js +59 -0
- package/dist/commands.d.ts +31 -50
- package/dist/commands.js +40 -51
- package/dist/generated-browser-action-protocol.d.ts +14 -3
- package/dist/generated-browser-action-protocol.js +3 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -1
- package/dist/unified.js +11 -3
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -73,6 +73,9 @@ mearl browser_list
|
|
|
73
73
|
mearl browser_release
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
输入不存在或拼写有误的 action 时,CLI 会基于可用命令和常见别名直接返回最多三个候选及调用示例,
|
|
77
|
+
不连接浏览器,也不会自动执行推荐命令。例如 `mearl tab new` 会优先推荐 `mearl tab_open`。
|
|
78
|
+
|
|
76
79
|
**通用选项:**
|
|
77
80
|
|
|
78
81
|
| 选项 | 说明 |
|
|
@@ -91,7 +94,7 @@ mearl browser_release
|
|
|
91
94
|
|
|
92
95
|
| 分类 | Actions |
|
|
93
96
|
| ----------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
-
| API 调试 | `
|
|
97
|
+
| API 调试 | `tab_checkpoint` `get_requests` `get_logs` `get_events` `get_api_schema` |
|
|
95
98
|
| Mock & 规则 | `set_mock` `get_mocks` `set_rule` `get_rules` |
|
|
96
99
|
| 网络代理 | `send_request` `send_mtop_request` |
|
|
97
100
|
| 标签页 | `tab_open` `tab_close` `tab_list` |
|
|
@@ -103,11 +106,11 @@ mearl browser_release
|
|
|
103
106
|
| TDBank | `tdbank_account` |
|
|
104
107
|
| 浏览器 | `browser_list` `browser_release` `browser_launch` `browser_close` |
|
|
105
108
|
|
|
106
|
-
页面交互动作(`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload
|
|
109
|
+
页面交互动作(`page_click` / `page_drag` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认等待异步稳定并返回 `{ action, observation }`。参数、ref 或目标解析在派发前失败时返回 `action.stage: "precondition"`,省略无意义的 `observation` / `diagnostics`,CLI 退出码为 1。传 `observe: false` 可执行裸动作;需要同一动作期间的新增 error logs 和业务 requests 时传 `diagnostics: true`,埋点通过 `diagnostics.events` 按需开启。`page_eval` 默认裸执行,可按需开启观察或诊断。
|
|
107
110
|
|
|
108
111
|
`page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。视口内缺少 AX 控件语义时,`interactive` 会自动回退到 viewport,并返回 `fallbackMode: "viewport"`。`maxNodes` / `maxChars` 截断会同时保留首尾内容。
|
|
109
112
|
|
|
110
|
-
重复文本点击可用 `page_click.scope` 限定 CSS / ref 子树;ref 指向滚动容器内的子节点时,可用 `page_scroll.containerPolicy: "nearest"`
|
|
113
|
+
重复文本点击可用 `page_click.scope` 限定 CSS / ref 子树;ref 指向滚动容器内的子节点时,可用 `page_scroll.containerPolicy: "nearest"` 自动解析最近可滚动祖先。点击结果的 `resolvedTarget` 和滚动结果的前后位置、边界字段可用于诊断实际目标与效果。
|
|
111
114
|
|
|
112
115
|
`browser_list` 统一列出普通浏览器和托管浏览器。`type` 区分 `regular` / `managed`,`status` 区分 `connected` / `running_disconnected` / `stopped`;只有 `connected` 的浏览器可作为操作目标。
|
|
113
116
|
|
package/dist/actionTimeouts.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PAGE_ACT_ACTIONS } from './generated-browser-action-protocol.js';
|
|
2
2
|
const SEND_REQUEST_FILE_TRANSFER_TIMEOUT_MS = 120_000;
|
|
3
|
+
// AgentBay staging can spend up to 60s transferring bytes and then 120s syncing the session disk.
|
|
4
|
+
const PAGE_UPLOAD_FILE_TRANSFER_TIMEOUT_MS = 180_000;
|
|
3
5
|
// AgentBay context sync can poll for about 12 minutes before session deletion waits up to 5 more.
|
|
4
6
|
const BROWSER_CLOSE_TIMEOUT_SEC = 18 * 60;
|
|
5
7
|
function boundedNumber(value, fallback, minimum, maximum) {
|
|
@@ -56,6 +58,10 @@ export function resolveActionTimeoutSec(action, data, fallback = 15) {
|
|
|
56
58
|
const observationEnabled = action === 'page_eval'
|
|
57
59
|
? data.observe !== null && typeof data.observe === 'object' && !Array.isArray(data.observe)
|
|
58
60
|
: data.observe !== false;
|
|
61
|
+
if (action === 'page_upload') {
|
|
62
|
+
const actionTimeoutSec = observationEnabled ? resolveObservedActionTimeoutSec(data) : fallback;
|
|
63
|
+
return Math.max(fallback, actionTimeoutSec + Math.ceil(PAGE_UPLOAD_FILE_TRANSFER_TIMEOUT_MS / 1000));
|
|
64
|
+
}
|
|
59
65
|
if (observedAction && observationEnabled) {
|
|
60
66
|
return Math.max(fallback, resolveObservedActionTimeoutSec(data));
|
|
61
67
|
}
|
package/dist/cli.js
CHANGED
|
@@ -2,14 +2,15 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { resolveActionTimeoutSec } from './actionTimeouts.js';
|
|
4
4
|
import { runUnifiedCheck, parseCheckTimeout } from './check.js';
|
|
5
|
-
import {
|
|
5
|
+
import { commandInput, findCommandSuggestions, formatCommandSuggestions, } from './commandSuggestions.js';
|
|
6
|
+
import { COMMANDS, COMMAND_MAP } from './commands.js';
|
|
6
7
|
import { CLIENT_VERSION } from './socket.js';
|
|
7
8
|
import { UnifiedClient } from './unified.js';
|
|
8
9
|
import { getCloudServerConfigPath, loadCloudServerConfig } from './unifiedConfig.js';
|
|
9
10
|
const CATEGORIES = [
|
|
10
11
|
{
|
|
11
12
|
title: 'API 调试',
|
|
12
|
-
names: ['
|
|
13
|
+
names: ['tab_checkpoint', 'get_requests', 'get_logs', 'get_events', 'get_api_schema'],
|
|
13
14
|
},
|
|
14
15
|
{ title: 'Mock & 规则', names: ['set_mock', 'get_mocks', 'set_rule', 'get_rules'] },
|
|
15
16
|
{ title: '网络代理', names: ['send_request', 'send_mtop_request'] },
|
|
@@ -45,6 +46,15 @@ const CATEGORIES = [
|
|
|
45
46
|
names: ['browser_list', 'browser_release', 'browser_launch', 'browser_close'],
|
|
46
47
|
},
|
|
47
48
|
];
|
|
49
|
+
const BUILTIN_COMMANDS = [
|
|
50
|
+
{
|
|
51
|
+
name: 'check',
|
|
52
|
+
description: '检查指定浏览器,未指定时检查全部已连接浏览器',
|
|
53
|
+
examples: ['check'],
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
const SUGGESTABLE_COMMANDS = [...COMMANDS, ...BUILTIN_COMMANDS];
|
|
57
|
+
const ADVANCED_BUILTIN_COMMANDS = new Set(['connector_list']);
|
|
48
58
|
function optionValue(args, name) {
|
|
49
59
|
const index = args.indexOf(name);
|
|
50
60
|
return index >= 0 ? args[index + 1] : undefined;
|
|
@@ -76,7 +86,6 @@ function printUsage(commandName, version) {
|
|
|
76
86
|
'',
|
|
77
87
|
'内置命令:',
|
|
78
88
|
' check 检查指定浏览器,未指定时检查全部已连接浏览器',
|
|
79
|
-
' connector_list 列出 cloud-server 下的 connector',
|
|
80
89
|
];
|
|
81
90
|
for (const category of CATEGORIES) {
|
|
82
91
|
lines.push('', ` ${category.title}`);
|
|
@@ -89,6 +98,17 @@ function printUsage(commandName, version) {
|
|
|
89
98
|
lines.push('', `运行 ${commandName} <action> --help 查看 action 参数。`);
|
|
90
99
|
console.error(lines.join('\n'));
|
|
91
100
|
}
|
|
101
|
+
function printAdvancedCommandHelp(commandName, action) {
|
|
102
|
+
if (action !== 'connector_list')
|
|
103
|
+
return;
|
|
104
|
+
console.error([
|
|
105
|
+
'connector_list',
|
|
106
|
+
' 列出 cloud-server 下的 connector(高级诊断)',
|
|
107
|
+
'',
|
|
108
|
+
'用法:',
|
|
109
|
+
` ${commandName} connector_list [--server <url>] [--timeout <seconds>]`,
|
|
110
|
+
].join('\n'));
|
|
111
|
+
}
|
|
92
112
|
function printCommandHelp(commandName, command) {
|
|
93
113
|
const lines = [
|
|
94
114
|
`${command.name}`,
|
|
@@ -102,7 +122,7 @@ function printCommandHelp(commandName, command) {
|
|
|
102
122
|
lines.push('参数(--payload JSON 字段):');
|
|
103
123
|
for (const parameter of command.params) {
|
|
104
124
|
const required = parameter.required ? '必填' : '可选';
|
|
105
|
-
lines.push(` ${parameter.name.padEnd(22)}${required.padEnd(6)}${parameter.type.padEnd(28)}${parameter.description}`);
|
|
125
|
+
lines.push(` ${parameter.name.padEnd(22)}${required.padEnd(6)}${parameter.type.padEnd(28)} ${parameter.description}`);
|
|
106
126
|
}
|
|
107
127
|
lines.push('');
|
|
108
128
|
}
|
|
@@ -113,6 +133,18 @@ function printCommandHelp(commandName, command) {
|
|
|
113
133
|
}
|
|
114
134
|
console.error(lines.join('\n'));
|
|
115
135
|
}
|
|
136
|
+
function printUnknownCommand(commandName, args) {
|
|
137
|
+
const input = commandInput(args) || args[0] || '';
|
|
138
|
+
const suggestions = findCommandSuggestions(args, SUGGESTABLE_COMMANDS);
|
|
139
|
+
const lines = [`不支持的命令: ${input}`];
|
|
140
|
+
if (suggestions.length > 0) {
|
|
141
|
+
lines.push('', '你可能想用:', ...formatCommandSuggestions(commandName, suggestions));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
lines.push(`运行 ${commandName} --help 查看所有可用命令`);
|
|
145
|
+
}
|
|
146
|
+
console.error(lines.join('\n'));
|
|
147
|
+
}
|
|
116
148
|
function parsePositiveTimeout(value, fallback) {
|
|
117
149
|
if (value === undefined)
|
|
118
150
|
return fallback;
|
|
@@ -230,6 +262,8 @@ function writeOutput(action, result, outputPath) {
|
|
|
230
262
|
export async function runMearlCli(args, options = {}) {
|
|
231
263
|
const commandName = options.commandName ?? 'mearl';
|
|
232
264
|
const clientVersion = options.clientVersion ?? CLIENT_VERSION;
|
|
265
|
+
if (args[0] === 'capture_checkpoint')
|
|
266
|
+
args = ['tab_checkpoint', ...args.slice(1)];
|
|
233
267
|
if (args.includes('--version') || args.includes('-v')) {
|
|
234
268
|
console.log(clientVersion);
|
|
235
269
|
return 0;
|
|
@@ -242,10 +276,22 @@ export async function runMearlCli(args, options = {}) {
|
|
|
242
276
|
const command = COMMAND_MAP.get(args[0]);
|
|
243
277
|
if (command)
|
|
244
278
|
printCommandHelp(commandName, command);
|
|
245
|
-
else
|
|
279
|
+
else if (ADVANCED_BUILTIN_COMMANDS.has(args[0])) {
|
|
280
|
+
printAdvancedCommandHelp(commandName, args[0]);
|
|
281
|
+
}
|
|
282
|
+
else if (args[0]?.startsWith('-') || BUILTIN_COMMANDS.some(item => item.name === args[0])) {
|
|
246
283
|
printUsage(commandName, clientVersion);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
printUnknownCommand(commandName, args);
|
|
287
|
+
return 2;
|
|
288
|
+
}
|
|
247
289
|
return 0;
|
|
248
290
|
}
|
|
291
|
+
if (args[0] !== 'check' && args[0] !== 'connector_list' && !COMMAND_MAP.has(args[0])) {
|
|
292
|
+
printUnknownCommand(commandName, args);
|
|
293
|
+
return 2;
|
|
294
|
+
}
|
|
249
295
|
let parsed;
|
|
250
296
|
try {
|
|
251
297
|
parsed = parseArgs(args);
|
|
@@ -272,11 +318,6 @@ export async function runMearlCli(args, options = {}) {
|
|
|
272
318
|
});
|
|
273
319
|
return ok ? 0 : 1;
|
|
274
320
|
}
|
|
275
|
-
if (parsed.action !== 'connector_list' && !COMMAND_MAP.has(parsed.action)) {
|
|
276
|
-
console.error(`不支持的 action: ${parsed.action}`);
|
|
277
|
-
console.error(`运行 ${commandName} --help 查看所有可用命令`);
|
|
278
|
-
return 2;
|
|
279
|
-
}
|
|
280
321
|
if (parsed.action === 'page_selected_element' && parsed.outputPath) {
|
|
281
322
|
parsed.payload = { ...parsed.payload, includeScreenshot: true };
|
|
282
323
|
}
|
|
@@ -298,7 +339,7 @@ export async function runMearlCli(args, options = {}) {
|
|
|
298
339
|
else {
|
|
299
340
|
process.stdout.write(`${parsed.compact ? JSON.stringify(result) : JSON.stringify(result, null, 2)}\n`);
|
|
300
341
|
}
|
|
301
|
-
return 0;
|
|
342
|
+
return result?.action?.success === false ? 1 : 0;
|
|
302
343
|
}
|
|
303
344
|
catch (error) {
|
|
304
345
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SuggestableCommand {
|
|
2
|
+
readonly aliases?: readonly string[];
|
|
3
|
+
readonly description: string;
|
|
4
|
+
readonly examples?: readonly string[];
|
|
5
|
+
readonly name: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CommandSuggestion {
|
|
8
|
+
command: SuggestableCommand;
|
|
9
|
+
score: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function commandInput(args: readonly string[]): string;
|
|
12
|
+
export declare function findCommandSuggestions(args: readonly string[], commands: readonly SuggestableCommand[], limit?: number): CommandSuggestion[];
|
|
13
|
+
export declare function formatCommandSuggestions(commandName: string, suggestions: readonly CommandSuggestion[]): string[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { distance } from 'fastest-levenshtein';
|
|
2
|
+
const MIN_SIMILARITY = 0.5;
|
|
3
|
+
const MAX_SCORE_GAP = 0.1;
|
|
4
|
+
function normalizeCommand(value) {
|
|
5
|
+
return value
|
|
6
|
+
.normalize('NFKC')
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
9
|
+
.replace(/^_+|_+$/g, '');
|
|
10
|
+
}
|
|
11
|
+
function leadingCommandParts(args) {
|
|
12
|
+
const parts = [];
|
|
13
|
+
for (const arg of args) {
|
|
14
|
+
if (arg.startsWith('-'))
|
|
15
|
+
break;
|
|
16
|
+
parts.push(arg);
|
|
17
|
+
}
|
|
18
|
+
return parts;
|
|
19
|
+
}
|
|
20
|
+
function commandQueries(args) {
|
|
21
|
+
const parts = leadingCommandParts(args);
|
|
22
|
+
const queries = new Set();
|
|
23
|
+
for (let length = parts.length; length > 0; length -= 1) {
|
|
24
|
+
const query = normalizeCommand(parts.slice(0, length).join('_'));
|
|
25
|
+
if (query)
|
|
26
|
+
queries.add(query);
|
|
27
|
+
}
|
|
28
|
+
return [...queries];
|
|
29
|
+
}
|
|
30
|
+
function similarity(left, right) {
|
|
31
|
+
const length = Math.max(left.length, right.length);
|
|
32
|
+
return length === 0 ? 0 : (length - distance(left, right)) / length;
|
|
33
|
+
}
|
|
34
|
+
export function commandInput(args) {
|
|
35
|
+
return leadingCommandParts(args).join(' ');
|
|
36
|
+
}
|
|
37
|
+
export function findCommandSuggestions(args, commands, limit = 3) {
|
|
38
|
+
const queries = commandQueries(args);
|
|
39
|
+
if (queries.length === 0 || limit <= 0)
|
|
40
|
+
return [];
|
|
41
|
+
const ranked = commands
|
|
42
|
+
.map(command => {
|
|
43
|
+
const keys = [command.name, ...(command.aliases ?? [])].map(normalizeCommand);
|
|
44
|
+
const score = Math.max(...queries.flatMap(query => keys.map(key => similarity(query, key))));
|
|
45
|
+
return { command, score };
|
|
46
|
+
})
|
|
47
|
+
.filter(suggestion => suggestion.score >= MIN_SIMILARITY)
|
|
48
|
+
.sort((left, right) => right.score - left.score || left.command.name.localeCompare(right.command.name));
|
|
49
|
+
const bestScore = ranked[0]?.score;
|
|
50
|
+
if (bestScore === undefined)
|
|
51
|
+
return [];
|
|
52
|
+
return ranked.filter(suggestion => bestScore - suggestion.score <= MAX_SCORE_GAP).slice(0, limit);
|
|
53
|
+
}
|
|
54
|
+
export function formatCommandSuggestions(commandName, suggestions) {
|
|
55
|
+
return suggestions.map(({ command }) => {
|
|
56
|
+
const invocation = command.examples?.[0] ?? command.name;
|
|
57
|
+
return ` ${commandName} ${invocation}\n ${command.description}`;
|
|
58
|
+
});
|
|
59
|
+
}
|
package/dist/commands.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface ParamDef {
|
|
|
8
8
|
export interface CommandDef {
|
|
9
9
|
name: BrowserCommandAction;
|
|
10
10
|
description: string;
|
|
11
|
+
/** CLI 中用于推荐 canonical action 的常见表达,不会作为可执行 action。 */
|
|
12
|
+
aliases?: readonly string[];
|
|
11
13
|
/** payload 字段说明 */
|
|
12
14
|
params?: ParamDef[];
|
|
13
15
|
/** 是否支持 --output */
|
|
@@ -15,14 +17,14 @@ export interface CommandDef {
|
|
|
15
17
|
examples?: string[];
|
|
16
18
|
}
|
|
17
19
|
export declare const COMMANDS: readonly [{
|
|
18
|
-
readonly name: "
|
|
19
|
-
readonly description: "
|
|
20
|
+
readonly name: "tab_checkpoint";
|
|
21
|
+
readonly description: "为目标标签页建立日志、请求和埋点增量边界";
|
|
20
22
|
readonly params: [{
|
|
21
23
|
readonly name: "tabId";
|
|
22
24
|
readonly type: "number";
|
|
23
25
|
readonly description: "目标标签页 ID,从 tab_open 获取";
|
|
24
26
|
}];
|
|
25
|
-
readonly examples: ["
|
|
27
|
+
readonly examples: ["tab_checkpoint --payload '{\"tabId\":12345}'"];
|
|
26
28
|
}, {
|
|
27
29
|
readonly name: "get_requests";
|
|
28
30
|
readonly description: "获取最近的网络请求(mtop 或普通 xhr/fetch)";
|
|
@@ -49,7 +51,7 @@ export declare const COMMANDS: readonly [{
|
|
|
49
51
|
}, {
|
|
50
52
|
readonly name: "after";
|
|
51
53
|
readonly type: "string";
|
|
52
|
-
readonly description: "只返回指定
|
|
54
|
+
readonly description: "只返回指定 tab checkpoint 或同类查询 cursor 之后的请求";
|
|
53
55
|
}, {
|
|
54
56
|
readonly name: "includeBody";
|
|
55
57
|
readonly type: "boolean";
|
|
@@ -82,7 +84,7 @@ export declare const COMMANDS: readonly [{
|
|
|
82
84
|
}, {
|
|
83
85
|
readonly name: "after";
|
|
84
86
|
readonly type: "string";
|
|
85
|
-
readonly description: "只返回指定
|
|
87
|
+
readonly description: "只返回指定 tab checkpoint 或同类查询 cursor 之后的日志";
|
|
86
88
|
}];
|
|
87
89
|
readonly examples: ["get_logs --payload '{\"limit\":10,\"level\":\"error\"}'"];
|
|
88
90
|
}, {
|
|
@@ -108,6 +110,10 @@ export declare const COMMANDS: readonly [{
|
|
|
108
110
|
readonly name: "since";
|
|
109
111
|
readonly type: "number";
|
|
110
112
|
readonly description: "只返回最近 N 秒内的事件";
|
|
113
|
+
}, {
|
|
114
|
+
readonly name: "after";
|
|
115
|
+
readonly type: "string";
|
|
116
|
+
readonly description: "只返回指定 tab checkpoint 之后的事件";
|
|
111
117
|
}, {
|
|
112
118
|
readonly name: "limit";
|
|
113
119
|
readonly type: "number";
|
|
@@ -383,6 +389,7 @@ export declare const COMMANDS: readonly [{
|
|
|
383
389
|
}, {
|
|
384
390
|
readonly name: "tab_open";
|
|
385
391
|
readonly description: "打开或按 URL 规则复用 Tab,并等待新页面加载完成";
|
|
392
|
+
readonly aliases: readonly ["tab_new", "new_tab", "tab_create", "create_tab"];
|
|
386
393
|
readonly params: [{
|
|
387
394
|
readonly name: "url";
|
|
388
395
|
readonly type: "string";
|
|
@@ -425,6 +432,7 @@ export declare const COMMANDS: readonly [{
|
|
|
425
432
|
}, {
|
|
426
433
|
readonly name: "tab_close";
|
|
427
434
|
readonly description: "关闭指定标签页";
|
|
435
|
+
readonly aliases: readonly ["tab_remove", "remove_tab", "tab_delete", "delete_tab"];
|
|
428
436
|
readonly params: [{
|
|
429
437
|
readonly name: "tabId";
|
|
430
438
|
readonly type: "number";
|
|
@@ -435,10 +443,11 @@ export declare const COMMANDS: readonly [{
|
|
|
435
443
|
}, {
|
|
436
444
|
readonly name: "tab_list";
|
|
437
445
|
readonly description: "获取当前窗口所有标签页列表";
|
|
446
|
+
readonly aliases: readonly ["tabs", "list_tabs", "show_tabs"];
|
|
438
447
|
readonly examples: ["tab_list"];
|
|
439
448
|
}, {
|
|
440
449
|
readonly name: "page_click";
|
|
441
|
-
readonly description: "点击页面元素,支持
|
|
450
|
+
readonly description: "点击页面元素,支持 CSS/@ref、可见文本或视口坐标定位";
|
|
442
451
|
readonly params: [{
|
|
443
452
|
readonly name: "selector";
|
|
444
453
|
readonly type: "string";
|
|
@@ -466,12 +475,8 @@ export declare const COMMANDS: readonly [{
|
|
|
466
475
|
}, {
|
|
467
476
|
readonly name: "clickMode";
|
|
468
477
|
readonly type: "\"auto\" | \"dom\" | \"mouse\" | \"touch\"";
|
|
469
|
-
readonly description: "
|
|
470
|
-
}, {
|
|
471
|
-
readonly name: "observe";
|
|
472
|
-
readonly type: "object | false";
|
|
473
|
-
readonly description: "观察选项(quietMs/firstChangeTimeoutMs/timeoutMs/navigationGraceMs/navigationTimeoutMs/networkIdleMs/contentReadyAfterMs);传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
474
|
-
}, ParamDef, {
|
|
478
|
+
readonly description: "默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式";
|
|
479
|
+
}, ParamDef, ParamDef, {
|
|
475
480
|
readonly name: "tabId";
|
|
476
481
|
readonly type: "number";
|
|
477
482
|
readonly required: true;
|
|
@@ -480,7 +485,7 @@ export declare const COMMANDS: readonly [{
|
|
|
480
485
|
readonly examples: ["page_click --payload '{\"text\":\"提交\"}'", "page_click --payload '{\"text\":\"退款明细\",\"role\":\"button\"}'", "page_click --payload '{\"text\":\"确定\",\"scope\":\"@e12\"}'", "page_click --payload '{\"selector\":\"@e3\"}'", "page_click --payload '{\"selector\":\".submit-btn\"}'", "page_click --payload '{\"selector\":\".gesture-btn\",\"clickMode\":\"touch\"}'", "page_click --payload '{\"point\":{\"x\":336,\"y\":117}}'"];
|
|
481
486
|
}, {
|
|
482
487
|
readonly name: "page_drag";
|
|
483
|
-
readonly description: "
|
|
488
|
+
readonly description: "拖动页面元素或视口坐标,适用于轮播图、滑块和拖放";
|
|
484
489
|
readonly params: [{
|
|
485
490
|
readonly name: "from";
|
|
486
491
|
readonly type: "string | { x: number; y: number }";
|
|
@@ -493,17 +498,13 @@ export declare const COMMANDS: readonly [{
|
|
|
493
498
|
readonly description: "终点:原生 CSS、@eN ref,或 { x, y } 视口坐标(CSS 像素)";
|
|
494
499
|
}, {
|
|
495
500
|
readonly name: "dragMode";
|
|
496
|
-
readonly type: "\"auto\" | \"mouse\" | \"touch\"";
|
|
497
|
-
readonly description: "
|
|
501
|
+
readonly type: "\"auto\" | \"dom\" | \"mouse\" | \"touch\"";
|
|
502
|
+
readonly description: "默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式";
|
|
498
503
|
}, {
|
|
499
504
|
readonly name: "durationMs";
|
|
500
505
|
readonly type: "number";
|
|
501
506
|
readonly description: "拖动持续时间,0–5000ms,默认 400ms;内部自动分段移动";
|
|
502
|
-
}, {
|
|
503
|
-
readonly name: "observe";
|
|
504
|
-
readonly type: "object | false";
|
|
505
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
506
|
-
}, ParamDef, {
|
|
507
|
+
}, ParamDef, ParamDef, {
|
|
507
508
|
readonly name: "tabId";
|
|
508
509
|
readonly type: "number";
|
|
509
510
|
readonly required: true;
|
|
@@ -512,7 +513,7 @@ export declare const COMMANDS: readonly [{
|
|
|
512
513
|
readonly examples: ["page_drag --payload '{\"from\":{\"x\":350,\"y\":80},\"to\":{\"x\":80,\"y\":80}}'", "page_drag --payload '{\"from\":\"@e3\",\"to\":\"#drop-zone\",\"dragMode\":\"mouse\"}'"];
|
|
513
514
|
}, {
|
|
514
515
|
readonly name: "page_type";
|
|
515
|
-
readonly description: "向输入框填写文本,兼容 React
|
|
516
|
+
readonly description: "向输入框填写文本,兼容 React 受控组件";
|
|
516
517
|
readonly params: [{
|
|
517
518
|
readonly name: "selector";
|
|
518
519
|
readonly type: "string";
|
|
@@ -527,11 +528,7 @@ export declare const COMMANDS: readonly [{
|
|
|
527
528
|
readonly name: "clearFirst";
|
|
528
529
|
readonly type: "boolean";
|
|
529
530
|
readonly description: "是否先清空原有内容,默认 true";
|
|
530
|
-
}, {
|
|
531
|
-
readonly name: "observe";
|
|
532
|
-
readonly type: "object | false";
|
|
533
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
534
|
-
}, ParamDef, {
|
|
531
|
+
}, ParamDef, ParamDef, {
|
|
535
532
|
readonly name: "tabId";
|
|
536
533
|
readonly type: "number";
|
|
537
534
|
readonly required: true;
|
|
@@ -540,17 +537,13 @@ export declare const COMMANDS: readonly [{
|
|
|
540
537
|
readonly examples: ["page_type --payload '{\"selector\":\"@e6\",\"text\":\"搜索关键词\"}'"];
|
|
541
538
|
}, {
|
|
542
539
|
readonly name: "page_hover";
|
|
543
|
-
readonly description: "
|
|
540
|
+
readonly description: "将鼠标悬停在页面元素上";
|
|
544
541
|
readonly params: [{
|
|
545
542
|
readonly name: "selector";
|
|
546
543
|
readonly type: "string";
|
|
547
544
|
readonly required: true;
|
|
548
545
|
readonly description: "原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 @eN ref(必须带 @ 前缀)";
|
|
549
|
-
}, {
|
|
550
|
-
readonly name: "observe";
|
|
551
|
-
readonly type: "object | false";
|
|
552
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
553
|
-
}, ParamDef, {
|
|
546
|
+
}, ParamDef, ParamDef, {
|
|
554
547
|
readonly name: "tabId";
|
|
555
548
|
readonly type: "number";
|
|
556
549
|
readonly required: true;
|
|
@@ -559,7 +552,7 @@ export declare const COMMANDS: readonly [{
|
|
|
559
552
|
readonly examples: ["page_hover --payload '{\"selector\":\".nav-menu\"}'"];
|
|
560
553
|
}, {
|
|
561
554
|
readonly name: "page_scroll";
|
|
562
|
-
readonly description: "
|
|
555
|
+
readonly description: "滚动页面或指定容器";
|
|
563
556
|
readonly params: [{
|
|
564
557
|
readonly name: "direction";
|
|
565
558
|
readonly type: "\"up\" | \"down\" | \"top\" | \"bottom\"";
|
|
@@ -577,11 +570,7 @@ export declare const COMMANDS: readonly [{
|
|
|
577
570
|
readonly name: "containerPolicy";
|
|
578
571
|
readonly type: "\"self\" | \"nearest\"";
|
|
579
572
|
readonly description: "默认 self,要求 selector 本身可滚动;nearest 会在其不可滚动时使用最近的可滚动祖先";
|
|
580
|
-
}, {
|
|
581
|
-
readonly name: "observe";
|
|
582
|
-
readonly type: "object | false";
|
|
583
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
584
|
-
}, ParamDef, {
|
|
573
|
+
}, ParamDef, ParamDef, {
|
|
585
574
|
readonly name: "tabId";
|
|
586
575
|
readonly type: "number";
|
|
587
576
|
readonly required: true;
|
|
@@ -613,7 +602,7 @@ export declare const COMMANDS: readonly [{
|
|
|
613
602
|
readonly examples: ["page_eval --payload '{\"expression\":\"document.title\"}'"];
|
|
614
603
|
}, {
|
|
615
604
|
readonly name: "page_press";
|
|
616
|
-
readonly description: "
|
|
605
|
+
readonly description: "在页面中按下键盘按键或组合键";
|
|
617
606
|
readonly params: [{
|
|
618
607
|
readonly name: "key";
|
|
619
608
|
readonly type: "string";
|
|
@@ -623,11 +612,7 @@ export declare const COMMANDS: readonly [{
|
|
|
623
612
|
readonly name: "modifiers";
|
|
624
613
|
readonly type: "string[]";
|
|
625
614
|
readonly description: "修饰键数组:ctrl/alt/shift/meta/cmd";
|
|
626
|
-
}, {
|
|
627
|
-
readonly name: "observe";
|
|
628
|
-
readonly type: "object | false";
|
|
629
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
630
|
-
}, ParamDef, {
|
|
615
|
+
}, ParamDef, ParamDef, {
|
|
631
616
|
readonly name: "tabId";
|
|
632
617
|
readonly type: "number";
|
|
633
618
|
readonly required: true;
|
|
@@ -688,7 +673,7 @@ export declare const COMMANDS: readonly [{
|
|
|
688
673
|
readonly examples: ["page_navigate --payload '{\"tabId\":12345,\"url\":\"https://example.com/page2\"}'", "page_navigate --payload '{\"tabId\":12345,\"refresh\":true}'", "page_navigate --payload '{\"tabId\":12345,\"history\":\"back\"}'"];
|
|
689
674
|
}, {
|
|
690
675
|
readonly name: "page_upload";
|
|
691
|
-
readonly description: "向 <input type=\"file\">
|
|
676
|
+
readonly description: "向 <input type=\"file\"> 元素上传一个或多个文件";
|
|
692
677
|
readonly params: [{
|
|
693
678
|
readonly name: "selector";
|
|
694
679
|
readonly type: "string";
|
|
@@ -699,11 +684,7 @@ export declare const COMMANDS: readonly [{
|
|
|
699
684
|
readonly type: "string[]";
|
|
700
685
|
readonly required: true;
|
|
701
686
|
readonly description: "本地文件路径数组";
|
|
702
|
-
}, {
|
|
703
|
-
readonly name: "observe";
|
|
704
|
-
readonly type: "object | false";
|
|
705
|
-
readonly description: "观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回";
|
|
706
|
-
}, ParamDef, {
|
|
687
|
+
}, ParamDef, ParamDef, {
|
|
707
688
|
readonly name: "tabId";
|
|
708
689
|
readonly type: "number";
|
|
709
690
|
readonly required: true;
|
package/dist/commands.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
const PAGE_DIAGNOSTICS_PARAM = {
|
|
2
2
|
name: 'diagnostics',
|
|
3
3
|
type: 'object | boolean',
|
|
4
|
-
description: '
|
|
4
|
+
description: '默认关闭;传 true 返回动作期间新增的 error logs/业务 requests,或传对象自定义通道与过滤',
|
|
5
|
+
};
|
|
6
|
+
const PAGE_OBSERVE_PARAM = {
|
|
7
|
+
name: 'observe',
|
|
8
|
+
type: 'object | false',
|
|
9
|
+
description: '默认开启 DOM/导航观察;传 false 关闭,不影响显式请求的 diagnostics',
|
|
5
10
|
};
|
|
6
11
|
export const COMMANDS = [
|
|
7
12
|
// ── API 调试 ──────────────────────────────────────────────────────────────
|
|
8
13
|
{
|
|
9
|
-
name: '
|
|
10
|
-
description: '
|
|
14
|
+
name: 'tab_checkpoint',
|
|
15
|
+
description: '为目标标签页建立日志、请求和埋点增量边界',
|
|
11
16
|
params: [{ name: 'tabId', type: 'number', description: '目标标签页 ID,从 tab_open 获取' }],
|
|
12
|
-
examples: [`
|
|
17
|
+
examples: [`tab_checkpoint --payload '{"tabId":12345}'`],
|
|
13
18
|
},
|
|
14
19
|
{
|
|
15
20
|
name: 'get_requests',
|
|
@@ -24,7 +29,11 @@ export const COMMANDS = [
|
|
|
24
29
|
},
|
|
25
30
|
{ name: 'filter', type: 'string', description: '按 URL 或 API 名称过滤,支持正则' },
|
|
26
31
|
{ name: 'since', type: 'number', description: '只返回最近 N 秒内的请求' },
|
|
27
|
-
{
|
|
32
|
+
{
|
|
33
|
+
name: 'after',
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: '只返回指定 tab checkpoint 或同类查询 cursor 之后的请求',
|
|
36
|
+
},
|
|
28
37
|
{ name: 'includeBody', type: 'boolean', description: '是否包含请求/响应体,默认 true' },
|
|
29
38
|
],
|
|
30
39
|
examples: [
|
|
@@ -41,7 +50,11 @@ export const COMMANDS = [
|
|
|
41
50
|
{ name: 'level', type: 'string', description: '按日志级别过滤:log/info/warn/error' },
|
|
42
51
|
{ name: 'filter', type: 'string', description: '按内容过滤,支持正则' },
|
|
43
52
|
{ name: 'since', type: 'number', description: '只返回最近 N 秒内的日志' },
|
|
44
|
-
{
|
|
53
|
+
{
|
|
54
|
+
name: 'after',
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: '只返回指定 tab checkpoint 或同类查询 cursor 之后的日志',
|
|
57
|
+
},
|
|
45
58
|
],
|
|
46
59
|
examples: [`get_logs --payload '{"limit":10,"level":"error"}'`],
|
|
47
60
|
},
|
|
@@ -58,6 +71,7 @@ export const COMMANDS = [
|
|
|
58
71
|
{ name: 'event_type', type: 'string', description: '按事件类型过滤,支持正则,如 CLK/PV' },
|
|
59
72
|
{ name: 'filter', type: 'string', description: '按 name 或 url 过滤,支持正则' },
|
|
60
73
|
{ name: 'since', type: 'number', description: '只返回最近 N 秒内的事件' },
|
|
74
|
+
{ name: 'after', type: 'string', description: '只返回指定 tab checkpoint 之后的事件' },
|
|
61
75
|
{ name: 'limit', type: 'number', description: '返回条数,默认 20' },
|
|
62
76
|
{
|
|
63
77
|
name: 'includeRaw',
|
|
@@ -311,6 +325,7 @@ export const COMMANDS = [
|
|
|
311
325
|
{
|
|
312
326
|
name: 'tab_open',
|
|
313
327
|
description: '打开或按 URL 规则复用 Tab,并等待新页面加载完成',
|
|
328
|
+
aliases: ['tab_new', 'new_tab', 'tab_create', 'create_tab'],
|
|
314
329
|
params: [
|
|
315
330
|
{ name: 'url', type: 'string', required: true, description: '要打开的 URL' },
|
|
316
331
|
{ name: 'active', type: 'boolean', description: '是否激活新 Tab,默认 false' },
|
|
@@ -360,18 +375,20 @@ export const COMMANDS = [
|
|
|
360
375
|
{
|
|
361
376
|
name: 'tab_close',
|
|
362
377
|
description: '关闭指定标签页',
|
|
378
|
+
aliases: ['tab_remove', 'remove_tab', 'tab_delete', 'delete_tab'],
|
|
363
379
|
params: [{ name: 'tabId', type: 'number', required: true, description: '要关闭的标签页 ID' }],
|
|
364
380
|
examples: [`tab_close --payload '{"tabId":123}'`],
|
|
365
381
|
},
|
|
366
382
|
{
|
|
367
383
|
name: 'tab_list',
|
|
368
384
|
description: '获取当前窗口所有标签页列表',
|
|
385
|
+
aliases: ['tabs', 'list_tabs', 'show_tabs'],
|
|
369
386
|
examples: ['tab_list'],
|
|
370
387
|
},
|
|
371
388
|
// ── 页面操作 ──────────────────────────────────────────────────────────────
|
|
372
389
|
{
|
|
373
390
|
name: 'page_click',
|
|
374
|
-
description: '点击页面元素,支持
|
|
391
|
+
description: '点击页面元素,支持 CSS/@ref、可见文本或视口坐标定位',
|
|
375
392
|
params: [
|
|
376
393
|
{
|
|
377
394
|
name: 'selector',
|
|
@@ -406,13 +423,9 @@ export const COMMANDS = [
|
|
|
406
423
|
{
|
|
407
424
|
name: 'clickMode',
|
|
408
425
|
type: '"auto" | "dom" | "mouse" | "touch"',
|
|
409
|
-
description: '
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
name: 'observe',
|
|
413
|
-
type: 'object | false',
|
|
414
|
-
description: '观察选项(quietMs/firstChangeTimeoutMs/timeoutMs/navigationGraceMs/navigationTimeoutMs/networkIdleMs/contentReadyAfterMs);传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
426
|
+
description: '默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式',
|
|
415
427
|
},
|
|
428
|
+
PAGE_OBSERVE_PARAM,
|
|
416
429
|
PAGE_DIAGNOSTICS_PARAM,
|
|
417
430
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
418
431
|
],
|
|
@@ -428,7 +441,7 @@ export const COMMANDS = [
|
|
|
428
441
|
},
|
|
429
442
|
{
|
|
430
443
|
name: 'page_drag',
|
|
431
|
-
description: '
|
|
444
|
+
description: '拖动页面元素或视口坐标,适用于轮播图、滑块和拖放',
|
|
432
445
|
params: [
|
|
433
446
|
{
|
|
434
447
|
name: 'from',
|
|
@@ -444,19 +457,15 @@ export const COMMANDS = [
|
|
|
444
457
|
},
|
|
445
458
|
{
|
|
446
459
|
name: 'dragMode',
|
|
447
|
-
type: '"auto" | "mouse" | "touch"',
|
|
448
|
-
description: '
|
|
460
|
+
type: '"auto" | "dom" | "mouse" | "touch"',
|
|
461
|
+
description: '默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式',
|
|
449
462
|
},
|
|
450
463
|
{
|
|
451
464
|
name: 'durationMs',
|
|
452
465
|
type: 'number',
|
|
453
466
|
description: '拖动持续时间,0–5000ms,默认 400ms;内部自动分段移动',
|
|
454
467
|
},
|
|
455
|
-
|
|
456
|
-
name: 'observe',
|
|
457
|
-
type: 'object | false',
|
|
458
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
459
|
-
},
|
|
468
|
+
PAGE_OBSERVE_PARAM,
|
|
460
469
|
PAGE_DIAGNOSTICS_PARAM,
|
|
461
470
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
462
471
|
],
|
|
@@ -467,7 +476,7 @@ export const COMMANDS = [
|
|
|
467
476
|
},
|
|
468
477
|
{
|
|
469
478
|
name: 'page_type',
|
|
470
|
-
description: '向输入框填写文本,兼容 React
|
|
479
|
+
description: '向输入框填写文本,兼容 React 受控组件',
|
|
471
480
|
params: [
|
|
472
481
|
{
|
|
473
482
|
name: 'selector',
|
|
@@ -477,11 +486,7 @@ export const COMMANDS = [
|
|
|
477
486
|
},
|
|
478
487
|
{ name: 'text', type: 'string', required: true, description: '要填写的文本' },
|
|
479
488
|
{ name: 'clearFirst', type: 'boolean', description: '是否先清空原有内容,默认 true' },
|
|
480
|
-
|
|
481
|
-
name: 'observe',
|
|
482
|
-
type: 'object | false',
|
|
483
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
484
|
-
},
|
|
489
|
+
PAGE_OBSERVE_PARAM,
|
|
485
490
|
PAGE_DIAGNOSTICS_PARAM,
|
|
486
491
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
487
492
|
],
|
|
@@ -489,7 +494,7 @@ export const COMMANDS = [
|
|
|
489
494
|
},
|
|
490
495
|
{
|
|
491
496
|
name: 'page_hover',
|
|
492
|
-
description: '
|
|
497
|
+
description: '将鼠标悬停在页面元素上',
|
|
493
498
|
params: [
|
|
494
499
|
{
|
|
495
500
|
name: 'selector',
|
|
@@ -497,11 +502,7 @@ export const COMMANDS = [
|
|
|
497
502
|
required: true,
|
|
498
503
|
description: '原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 @eN ref(必须带 @ 前缀)',
|
|
499
504
|
},
|
|
500
|
-
|
|
501
|
-
name: 'observe',
|
|
502
|
-
type: 'object | false',
|
|
503
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
504
|
-
},
|
|
505
|
+
PAGE_OBSERVE_PARAM,
|
|
505
506
|
PAGE_DIAGNOSTICS_PARAM,
|
|
506
507
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
507
508
|
],
|
|
@@ -509,7 +510,7 @@ export const COMMANDS = [
|
|
|
509
510
|
},
|
|
510
511
|
{
|
|
511
512
|
name: 'page_scroll',
|
|
512
|
-
description: '
|
|
513
|
+
description: '滚动页面或指定容器',
|
|
513
514
|
params: [
|
|
514
515
|
{
|
|
515
516
|
name: 'direction',
|
|
@@ -528,11 +529,7 @@ export const COMMANDS = [
|
|
|
528
529
|
type: '"self" | "nearest"',
|
|
529
530
|
description: '默认 self,要求 selector 本身可滚动;nearest 会在其不可滚动时使用最近的可滚动祖先',
|
|
530
531
|
},
|
|
531
|
-
|
|
532
|
-
name: 'observe',
|
|
533
|
-
type: 'object | false',
|
|
534
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
535
|
-
},
|
|
532
|
+
PAGE_OBSERVE_PARAM,
|
|
536
533
|
PAGE_DIAGNOSTICS_PARAM,
|
|
537
534
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
538
535
|
],
|
|
@@ -565,7 +562,7 @@ export const COMMANDS = [
|
|
|
565
562
|
},
|
|
566
563
|
{
|
|
567
564
|
name: 'page_press',
|
|
568
|
-
description: '
|
|
565
|
+
description: '在页面中按下键盘按键或组合键',
|
|
569
566
|
params: [
|
|
570
567
|
{
|
|
571
568
|
name: 'key',
|
|
@@ -574,11 +571,7 @@ export const COMMANDS = [
|
|
|
574
571
|
description: '按键名称:Enter/Tab/Escape/Backspace 等',
|
|
575
572
|
},
|
|
576
573
|
{ name: 'modifiers', type: 'string[]', description: '修饰键数组:ctrl/alt/shift/meta/cmd' },
|
|
577
|
-
|
|
578
|
-
name: 'observe',
|
|
579
|
-
type: 'object | false',
|
|
580
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
581
|
-
},
|
|
574
|
+
PAGE_OBSERVE_PARAM,
|
|
582
575
|
PAGE_DIAGNOSTICS_PARAM,
|
|
583
576
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
584
577
|
],
|
|
@@ -638,7 +631,7 @@ export const COMMANDS = [
|
|
|
638
631
|
},
|
|
639
632
|
{
|
|
640
633
|
name: 'page_upload',
|
|
641
|
-
description: '向 <input type="file">
|
|
634
|
+
description: '向 <input type="file"> 元素上传一个或多个文件',
|
|
642
635
|
params: [
|
|
643
636
|
{
|
|
644
637
|
name: 'selector',
|
|
@@ -647,11 +640,7 @@ export const COMMANDS = [
|
|
|
647
640
|
description: '原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 @eN ref(必须带 @ 前缀),必须指向 input[type=file]',
|
|
648
641
|
},
|
|
649
642
|
{ name: 'filePaths', type: 'string[]', required: true, description: '本地文件路径数组' },
|
|
650
|
-
|
|
651
|
-
name: 'observe',
|
|
652
|
-
type: 'object | false',
|
|
653
|
-
description: '观察选项;传 false 只关闭 DOM/导航观察,默认诊断仍会返回',
|
|
654
|
-
},
|
|
643
|
+
PAGE_OBSERVE_PARAM,
|
|
655
644
|
PAGE_DIAGNOSTICS_PARAM,
|
|
656
645
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
657
646
|
],
|
|
@@ -4,7 +4,7 @@ export interface GetRequestsParams {
|
|
|
4
4
|
filter?: string;
|
|
5
5
|
/** Relative time window in seconds. */
|
|
6
6
|
since?: number;
|
|
7
|
-
/** Opaque cursor returned by
|
|
7
|
+
/** Opaque cursor returned by tab_checkpoint or a previous query. */
|
|
8
8
|
after?: string;
|
|
9
9
|
includeBody?: boolean;
|
|
10
10
|
includeHeaders?: boolean;
|
|
@@ -19,7 +19,7 @@ export interface GetLogsParams {
|
|
|
19
19
|
level?: 'log' | 'warn' | 'error' | 'info' | 'all';
|
|
20
20
|
/** Relative time window in seconds. */
|
|
21
21
|
since?: number;
|
|
22
|
-
/** Opaque cursor returned by
|
|
22
|
+
/** Opaque cursor returned by tab_checkpoint or a previous query. */
|
|
23
23
|
after?: string;
|
|
24
24
|
limit?: number;
|
|
25
25
|
filter?: string;
|
|
@@ -39,6 +39,8 @@ export interface GetEventsParams {
|
|
|
39
39
|
event_type?: string;
|
|
40
40
|
filter?: string;
|
|
41
41
|
since?: number;
|
|
42
|
+
/** Opaque cursor returned by tab_checkpoint or a previous event query. */
|
|
43
|
+
after?: string;
|
|
42
44
|
limit?: number;
|
|
43
45
|
includeRaw?: boolean;
|
|
44
46
|
}
|
|
@@ -299,6 +301,7 @@ export interface PageObservationWaitOptions {
|
|
|
299
301
|
export interface PageDiagnosticsOptions {
|
|
300
302
|
logs?: boolean | Pick<GetLogsParams, 'level' | 'limit' | 'filter'>;
|
|
301
303
|
requests?: boolean | Pick<GetRequestsParams, 'count' | 'filter' | 'includeBody' | 'includeHeaders' | 'maxBodySize' | 'fields' | 'keysOnly' | 'source'>;
|
|
304
|
+
events?: boolean | Pick<GetEventsParams, 'source' | 'event_type' | 'filter' | 'limit' | 'includeRaw'>;
|
|
302
305
|
}
|
|
303
306
|
export type PageDiagnosticsSetting = PageDiagnosticsOptions | boolean;
|
|
304
307
|
export interface PageClickParams {
|
|
@@ -325,7 +328,7 @@ export interface PageDragParams {
|
|
|
325
328
|
tabId?: number;
|
|
326
329
|
from: PageDragEndpoint;
|
|
327
330
|
to: PageDragEndpoint;
|
|
328
|
-
dragMode?: 'auto' | 'mouse' | 'touch';
|
|
331
|
+
dragMode?: 'auto' | 'dom' | 'mouse' | 'touch';
|
|
329
332
|
durationMs?: number;
|
|
330
333
|
observe?: PageObservationWaitOptions | false;
|
|
331
334
|
diagnostics?: PageDiagnosticsSetting;
|
|
@@ -471,6 +474,11 @@ export interface RunActionsParams {
|
|
|
471
474
|
tabId: number;
|
|
472
475
|
}
|
|
473
476
|
export interface BrowserActionMap {
|
|
477
|
+
tab_checkpoint: {
|
|
478
|
+
request: CaptureCheckpointParams;
|
|
479
|
+
response: CaptureCheckpointResult;
|
|
480
|
+
};
|
|
481
|
+
/** Compatibility alias for tab_checkpoint. */
|
|
474
482
|
capture_checkpoint: {
|
|
475
483
|
request: CaptureCheckpointParams;
|
|
476
484
|
response: CaptureCheckpointResult;
|
|
@@ -652,6 +660,7 @@ export type ExtensionBrowserAction = Exclude<BrowserCommandAction, 'browser_list
|
|
|
652
660
|
export declare const PAGE_ACT_ACTIONS: readonly ["page_click", "page_drag", "page_type", "page_hover", "page_scroll", "page_press", "page_upload", "page_eval"];
|
|
653
661
|
export type PageActAction = (typeof PAGE_ACT_ACTIONS)[number];
|
|
654
662
|
export declare const BROWSER_ACTIONS: {
|
|
663
|
+
readonly tab_checkpoint: true;
|
|
655
664
|
readonly capture_checkpoint: true;
|
|
656
665
|
readonly get_requests: true;
|
|
657
666
|
readonly get_logs: true;
|
|
@@ -697,6 +706,7 @@ export declare const BROWSER_ACTIONS: {
|
|
|
697
706
|
readonly run_actions: true;
|
|
698
707
|
};
|
|
699
708
|
export declare const BROWSER_COMMAND_ACTIONS: {
|
|
709
|
+
readonly tab_checkpoint: true;
|
|
700
710
|
readonly capture_checkpoint: true;
|
|
701
711
|
readonly get_requests: true;
|
|
702
712
|
readonly get_logs: true;
|
|
@@ -741,6 +751,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
|
|
|
741
751
|
readonly run_actions: true;
|
|
742
752
|
};
|
|
743
753
|
export declare const EXTENSION_BROWSER_ACTIONS: {
|
|
754
|
+
readonly tab_checkpoint: true;
|
|
744
755
|
readonly capture_checkpoint: true;
|
|
745
756
|
readonly get_requests: true;
|
|
746
757
|
readonly get_logs: true;
|
|
@@ -17,6 +17,7 @@ export const PAGE_ACT_ACTIONS = [
|
|
|
17
17
|
'page_eval',
|
|
18
18
|
];
|
|
19
19
|
export const BROWSER_ACTIONS = {
|
|
20
|
+
tab_checkpoint: true,
|
|
20
21
|
capture_checkpoint: true,
|
|
21
22
|
get_requests: true,
|
|
22
23
|
get_logs: true,
|
|
@@ -62,6 +63,7 @@ export const BROWSER_ACTIONS = {
|
|
|
62
63
|
run_actions: true,
|
|
63
64
|
};
|
|
64
65
|
export const BROWSER_COMMAND_ACTIONS = {
|
|
66
|
+
tab_checkpoint: true,
|
|
65
67
|
capture_checkpoint: true,
|
|
66
68
|
get_requests: true,
|
|
67
69
|
get_logs: true,
|
|
@@ -106,6 +108,7 @@ export const BROWSER_COMMAND_ACTIONS = {
|
|
|
106
108
|
run_actions: true,
|
|
107
109
|
};
|
|
108
110
|
export const EXTENSION_BROWSER_ACTIONS = {
|
|
111
|
+
tab_checkpoint: true,
|
|
109
112
|
capture_checkpoint: true,
|
|
110
113
|
get_requests: true,
|
|
111
114
|
get_logs: true,
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,9 @@ export { BROWSER_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PA
|
|
|
10
10
|
export type { ActionStep, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserReleaseFailure, BrowserReleaseResult, BrowserSource, BrowserStatus, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, ManagedBrowserAccount, ManagedBrowserInfo, PageClickParams, PageDragEndpoint, PageDragParams, PageDragPoint, PageActAction, PageDiagnosticsOptions, PageDiagnosticsSetting, PageEvalParams, PageFramesParams, PageHoverParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSelectedElementParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RecordParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendRequestFile, SendRequestFormValue, SendMtopRequestParams, SendRequestParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, TdbankAccountParams, } from './generated-browser-action-protocol.js';
|
|
11
11
|
import { type UnifiedInvokeOptions } from './unified.js';
|
|
12
12
|
import type * as Protocol from './generated-browser-action-protocol.js';
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function tabCheckpoint(params?: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_checkpoint'>>;
|
|
14
|
+
/** Compatibility wrapper for tabCheckpoint. */
|
|
15
|
+
export declare function captureCheckpoint(params?: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_checkpoint'>>;
|
|
14
16
|
export declare function getRequests(params?: Protocol.GetRequestsParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_requests'>>;
|
|
15
17
|
export declare function getLogs(params?: Protocol.GetLogsParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_logs'>>;
|
|
16
18
|
export declare function getEvents(params?: Protocol.GetEventsParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'get_events'>>;
|
package/dist/index.js
CHANGED
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invoke, listCloudConnectors, } from './unified.js';
|
|
8
8
|
export { BROWSER_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PAGE_ACT_ACTIONS, SEND_REQUEST_MAX_FILES, SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES, SEND_REQUEST_MAX_TOTAL_FILE_BYTES, isBrowserAction, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js';
|
|
9
9
|
import { invoke } from './unified.js';
|
|
10
|
+
export function tabCheckpoint(params = {}, options) {
|
|
11
|
+
return invoke('tab_checkpoint', params, options);
|
|
12
|
+
}
|
|
13
|
+
/** Compatibility wrapper for tabCheckpoint. */
|
|
10
14
|
export function captureCheckpoint(params = {}, options) {
|
|
11
|
-
return
|
|
15
|
+
return tabCheckpoint(params, options);
|
|
12
16
|
}
|
|
13
17
|
export function getRequests(params = {}, options) {
|
|
14
18
|
return invoke('get_requests', params, options);
|
package/dist/unified.js
CHANGED
|
@@ -205,7 +205,12 @@ export class UnifiedClient {
|
|
|
205
205
|
if (!localAvailable && connectors.length === 0) {
|
|
206
206
|
throw new Error('No browser host is available. Install @mearl/native-host locally or connect a cloud connector.');
|
|
207
207
|
}
|
|
208
|
-
|
|
208
|
+
const availableHosts = [
|
|
209
|
+
...(localAvailable ? ['this machine [--local]'] : []),
|
|
210
|
+
...connectors.map(connector => `${connector.name} [${connector.connectorId}]`),
|
|
211
|
+
].join(', ');
|
|
212
|
+
throw new Error('The browser host for browser_launch is ambiguous. ' +
|
|
213
|
+
`Pass --local, --connector <id|name>, or --browser <global-id>. Available: ${availableHosts}`);
|
|
209
214
|
}
|
|
210
215
|
async selectDefaultBrowser(data, options, timeoutSec) {
|
|
211
216
|
const selector = typeof data.browser === 'string' ? data.browser.trim() : '';
|
|
@@ -261,11 +266,14 @@ export class UnifiedClient {
|
|
|
261
266
|
async resolveConnector(selector, timeoutSec) {
|
|
262
267
|
const connectors = (await this.listConnectors(timeoutSec)).connectors;
|
|
263
268
|
const selection = resolveCloudConnectorSelector(connectors, selector);
|
|
269
|
+
const available = connectors
|
|
270
|
+
.map(connector => `${connector.name} [${connector.connectorId}]`)
|
|
271
|
+
.join(', ');
|
|
264
272
|
if (selection.status === 'ambiguous') {
|
|
265
|
-
throw new Error(`Cloud connector selector "${selector}" is ambiguous. Use an exact connectorId
|
|
273
|
+
throw new Error(`Cloud connector selector "${selector}" is ambiguous. Use an exact connectorId. Available: ${available}`);
|
|
266
274
|
}
|
|
267
275
|
if (selection.status !== 'matched') {
|
|
268
|
-
throw new Error(`No cloud connector matches "${selector}"
|
|
276
|
+
throw new Error(`No cloud connector matches "${selector}". Available: ${available}`);
|
|
269
277
|
}
|
|
270
278
|
return selection.connector;
|
|
271
279
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/client",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.2",
|
|
4
4
|
"description": "Unified Mearl SDK & CLI for local and remote browsers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -48,8 +48,9 @@
|
|
|
48
48
|
"registry": "https://registry.npmjs.org"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"fastest-levenshtein": "^1.0.16",
|
|
51
52
|
"ws": "^8.18.0",
|
|
52
|
-
"@mearl/cloud-types": "2.7.
|
|
53
|
+
"@mearl/cloud-types": "2.7.2"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/node": "^24.9.1",
|