@mearl/client 2.9.6 → 2.10.0
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 +1 -1
- package/dist/check.d.ts +11 -1
- package/dist/check.js +23 -15
- package/dist/commands.d.ts +22 -22
- package/dist/commands.js +33 -27
- package/dist/generated-browser-action-protocol.d.ts +11 -9
- package/dist/generated-browser-action-protocol.js +14 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ mearl browser_release
|
|
|
122
122
|
|
|
123
123
|
`browser_release` 仅在用户明确要求结束调试、退出接管或清理会话资源时使用,不作为普通任务收尾。它会释放当前目标浏览器的 debugger/CDP 控制和会话级临时状态(包括设备/时区模拟),保留浏览器及全部标签页;后续浏览器操作可自动重新建立控制。
|
|
124
124
|
|
|
125
|
-
托管浏览器使用独立 Profile。控制浏览器需先登录 TDBank;生成的 SSO 地址在本地内部传递,本地实例可以使用 `headless: true`(默认)完成测试账号登录。AgentBay 固定为非 headless,传 `headless: true` 会被拒绝;`imageId` 可指定镜像别名或具体镜像 ID,省略时使用已验证的 Linux Browser Use 内网镜像。`persistent: true` 会让本地实例保留 Profile,让 AgentBay 同名实例绑定稳定的云端 Browser Context;正常关闭时同步 Cookie、LocalStorage、IndexedDB 等状态,下次启动无需再次复制本地登录态。`deleteProfile: true` 会显式删除对应 Profile 或 Context。AgentBay 的 `reuse` 支持 `never`(默认)、`prefer` 和 `require`:`prefer` 存在运行实例时复用、否则创建,`require` 只复用且不会意外创建计费会话。`copyCookieDomains` 传数组时把控制浏览器指定域的 Cookie 写入目标,传 `"mearl-services"` 时同步 Mearl 依赖平台登录态。Cookie 值不会经过 cloud-server,也不会出现在命令结果或日志中;`userAgentMode: "desktop"` 让本地实例使用匹配本机 Chrome 版本的桌面 UA,AgentBay 则复用当前控制浏览器的桌面 UA。`browser_list`
|
|
125
|
+
托管浏览器使用独立 Profile。控制浏览器需先登录 TDBank;生成的 SSO 地址在本地内部传递,本地实例可以使用 `headless: true`(默认)完成测试账号登录。AgentBay 固定为非 headless,传 `headless: true` 会被拒绝;`imageId` 可指定镜像别名或具体镜像 ID,省略时使用已验证的 Linux Browser Use 内网镜像。`persistent: true` 会让本地实例保留 Profile,让 AgentBay 同名实例绑定稳定的云端 Browser Context;正常关闭时同步 Cookie、LocalStorage、IndexedDB 等状态,下次启动无需再次复制本地登录态。`deleteProfile: true` 会显式删除对应 Profile 或 Context。AgentBay 的 `reuse` 支持 `never`(默认)、`prefer` 和 `require`:`prefer` 存在运行实例时复用、否则创建,`require` 只复用且不会意外创建计费会话。`copyCookieDomains` 传数组时把控制浏览器指定域的 Cookie 写入目标,传 `"mearl-services"` 时同步 Mearl 依赖平台登录态。Cookie 值不会经过 cloud-server,也不会出现在命令结果或日志中;`userAgentMode: "desktop"` 让本地实例使用匹配本机 Chrome 版本的桌面 UA,AgentBay 则复用当前控制浏览器的桌面 UA。`browser_list` 仅返回浏览器的稳定配置,不携带 AgentBay 串流入口或沙箱 noVNC 地址。需要时显式运行 `mearl check --browser <id|名称>`,由统一的浏览器访问入口能力实时返回 `browserAccess`;AgentBay、OpenSandbox 和 AONE Sandbox 地址都应按敏感信息处理。完整设计见 [托管浏览器与 TDBank 多账号设计](../../docs/managed-browsers.md)。
|
|
126
126
|
|
|
127
127
|
## 架构
|
|
128
128
|
|
package/dist/check.d.ts
CHANGED
|
@@ -5,6 +5,16 @@ export interface UnifiedCheckVersions {
|
|
|
5
5
|
extension?: string | null;
|
|
6
6
|
browser?: string | null;
|
|
7
7
|
}
|
|
8
|
+
export type BrowserAccessCapability = {
|
|
9
|
+
kind: 'agentbay';
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'sandbox-novnc';
|
|
12
|
+
environment: 'opensandbox' | 'aone';
|
|
13
|
+
port: number;
|
|
14
|
+
};
|
|
15
|
+
export type BrowserAccess = BrowserAccessCapability & {
|
|
16
|
+
url: string;
|
|
17
|
+
};
|
|
8
18
|
interface BrowserInfo {
|
|
9
19
|
browserId: string;
|
|
10
20
|
extensionVersion?: string;
|
|
@@ -27,7 +37,7 @@ export interface ExtensionInstallationInfo {
|
|
|
27
37
|
setupManagedPath: string | null;
|
|
28
38
|
}
|
|
29
39
|
export interface UnifiedCheckBrowserResult extends BrowserInfo {
|
|
30
|
-
|
|
40
|
+
browserAccess?: BrowserAccess;
|
|
31
41
|
check?: {
|
|
32
42
|
errors?: string[];
|
|
33
43
|
label: string;
|
package/dist/check.js
CHANGED
|
@@ -2,6 +2,20 @@ import { UnifiedClient, normalizeBrowserSelector, } from './unified.js';
|
|
|
2
2
|
function formatError(error) {
|
|
3
3
|
return error instanceof Error ? error.message : String(error);
|
|
4
4
|
}
|
|
5
|
+
function browserAccessLabel(access) {
|
|
6
|
+
if (access.kind === 'agentbay')
|
|
7
|
+
return 'AgentBay, temporary';
|
|
8
|
+
return access.environment === 'opensandbox' ? 'OpenSandbox noVNC' : 'AONE Sandbox noVNC';
|
|
9
|
+
}
|
|
10
|
+
async function getBrowserAccess(client, browser, capability, timeoutSec) {
|
|
11
|
+
const result = (await client.invoke('get_browser_access_url', {}, { timeoutSec, browser: browser.browserId }));
|
|
12
|
+
if (!result.browserAccess?.url)
|
|
13
|
+
throw new Error('Browser host did not return an access URL');
|
|
14
|
+
if (result.browserAccess.kind !== capability.kind) {
|
|
15
|
+
throw new Error('Browser host returned an unexpected access URL type');
|
|
16
|
+
}
|
|
17
|
+
return result.browserAccess;
|
|
18
|
+
}
|
|
5
19
|
function redactServerUrl(serverUrl) {
|
|
6
20
|
try {
|
|
7
21
|
const parsed = new URL(serverUrl);
|
|
@@ -223,33 +237,27 @@ export async function runUnifiedCheck(options, dependencies = {}) {
|
|
|
223
237
|
setupManagedPath: versions.setupManagedPath,
|
|
224
238
|
};
|
|
225
239
|
}
|
|
226
|
-
let
|
|
240
|
+
let browserAccess;
|
|
227
241
|
let accessUrlWarning;
|
|
228
|
-
|
|
242
|
+
const browserAccessCapability = versions.browserAccess;
|
|
243
|
+
if (browserAccessCapability && options.browser) {
|
|
229
244
|
try {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
browser: browser.browserId,
|
|
233
|
-
}));
|
|
234
|
-
if (!access.agentbayAccessUrl) {
|
|
235
|
-
throw new Error('AgentBay did not return a browser access URL');
|
|
236
|
-
}
|
|
237
|
-
agentbayAccessUrl = access.agentbayAccessUrl;
|
|
238
|
-
details.push(`AgentBay access URL (temporary, sensitive): ${access.agentbayAccessUrl}`);
|
|
245
|
+
browserAccess = await getBrowserAccess(client, browser, browserAccessCapability, timeoutSec);
|
|
246
|
+
details.push(`Browser access URL (${browserAccessLabel(browserAccess)}; sensitive): ${browserAccess.url}`);
|
|
239
247
|
}
|
|
240
248
|
catch (error) {
|
|
241
249
|
accessUrlWarning = formatError(error);
|
|
242
|
-
details.push(`
|
|
250
|
+
details.push(`Browser access URL unavailable: ${accessUrlWarning}`);
|
|
243
251
|
}
|
|
244
252
|
}
|
|
245
253
|
browserChecks.push({
|
|
246
|
-
...(
|
|
254
|
+
...(browserAccess ? { browserAccess } : {}),
|
|
247
255
|
browser,
|
|
248
256
|
...(extensionInstallation ? { extensionInstallation } : {}),
|
|
249
257
|
item: {
|
|
250
258
|
status: accessUrlWarning ? 'warning' : 'ok',
|
|
251
259
|
label: accessUrlWarning
|
|
252
|
-
? 'Browser command path ready;
|
|
260
|
+
? 'Browser command path ready; browser access URL unavailable'
|
|
253
261
|
: options.transport === 'cdp'
|
|
254
262
|
? 'CDP command path'
|
|
255
263
|
: 'Browser command path',
|
|
@@ -293,7 +301,7 @@ export async function runUnifiedCheck(options, dependencies = {}) {
|
|
|
293
301
|
return {
|
|
294
302
|
...browserIdentity,
|
|
295
303
|
selected: targets.some(target => target.browserId === browser.browserId),
|
|
296
|
-
...(check?.
|
|
304
|
+
...(check?.browserAccess ? { browserAccess: check.browserAccess } : {}),
|
|
297
305
|
...(check?.item
|
|
298
306
|
? {
|
|
299
307
|
check: {
|
package/dist/commands.d.ts
CHANGED
|
@@ -509,25 +509,21 @@ export declare const COMMANDS: readonly [{
|
|
|
509
509
|
}, {
|
|
510
510
|
readonly name: "emulation";
|
|
511
511
|
readonly type: "object";
|
|
512
|
-
readonly description: "开 tab 即进入移动端模拟态(首屏即移动态、无需 reload)。字段同 set_device_emulation 去掉 enabled
|
|
512
|
+
readonly description: "开 tab 即进入移动端模拟态(首屏即移动态、无需 reload)。字段同 set_device_emulation 去掉 enabled/reload;deviceShell=true 时页面从首屏起在 iframe WebView 中渲染设备系统外壳";
|
|
513
513
|
}, {
|
|
514
514
|
readonly name: "appProfile";
|
|
515
515
|
readonly type: "string";
|
|
516
|
-
readonly description: "开 tab
|
|
516
|
+
readonly description: "开 tab 即注入 App 客户端环境与 JSBridge;档案名同 set_app_profile,如 \"fliggy\"。需要 iframe WebView 和系统栏时同时传 emulation.deviceShell=true";
|
|
517
517
|
}, {
|
|
518
518
|
readonly name: "os";
|
|
519
519
|
readonly type: "\"ios\" | \"android\"";
|
|
520
520
|
readonly description: "与 appProfile 配合;容器系统,默认 ios";
|
|
521
|
-
}, {
|
|
522
|
-
readonly name: "simulateSystemBars";
|
|
523
|
-
readonly type: "boolean";
|
|
524
|
-
readonly description: "与 appProfile 配合;是否模拟顶部状态/导航栏与底部手势栏,默认 true";
|
|
525
521
|
}, {
|
|
526
522
|
readonly name: "bridgeConfig";
|
|
527
523
|
readonly type: "object";
|
|
528
524
|
readonly description: "与 appProfile 配合;声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}}";
|
|
529
525
|
}];
|
|
530
|
-
readonly examples: ["tab_open --payload '{\"url\":\"https://example.com\"}'", "tab_open --payload '{\"url\":\"https://example.com/page\",\"reuse\":\"prefer\",\"match\":{\"ignoreSearch\":true}}'", "tab_open --payload '{\"url\":\"https://m.example.com\",\"emulation\":{\"preset\":\"iphone-
|
|
526
|
+
readonly examples: ["tab_open --payload '{\"url\":\"https://example.com\"}'", "tab_open --payload '{\"url\":\"https://example.com/page\",\"reuse\":\"prefer\",\"match\":{\"ignoreSearch\":true}}'", "tab_open --payload '{\"url\":\"https://m.example.com\",\"emulation\":{\"preset\":\"iphone-17-pro\"}}'", "tab_open --payload '{\"url\":\"https://market.m.taobao.com/app/trip/rx-home/pages/home\",\"appProfile\":\"fliggy\"}'", "tab_open --payload '{\"url\":\"https://example.com\",\"appProfile\":\"fliggy\",\"os\":\"android\"}'", "tab_open --payload '{\"url\":\"https://example.com\",\"group\":\"验证任务\"}'"];
|
|
531
527
|
}, {
|
|
532
528
|
readonly name: "tab_close";
|
|
533
529
|
readonly description: "关闭指定标签页";
|
|
@@ -912,7 +908,7 @@ export declare const COMMANDS: readonly [{
|
|
|
912
908
|
readonly examples: ["record_stop"];
|
|
913
909
|
}, {
|
|
914
910
|
readonly name: "set_device_emulation";
|
|
915
|
-
readonly description: "把目标 tab 切换为移动端模拟(视口/UA
|
|
911
|
+
readonly description: "把目标 tab 切换为移动端模拟(视口/DPR/UA/触摸/视觉比例),等价 DevTools 设备工具栏,作用域 per-tab;需保持调试控制才持续生效";
|
|
916
912
|
readonly summary: "设置或清除目标标签页的设备模拟";
|
|
917
913
|
readonly params: [{
|
|
918
914
|
readonly name: "enabled";
|
|
@@ -921,8 +917,8 @@ export declare const COMMANDS: readonly [{
|
|
|
921
917
|
readonly description: "true=启用,false=清除";
|
|
922
918
|
}, {
|
|
923
919
|
readonly name: "preset";
|
|
924
|
-
readonly type:
|
|
925
|
-
readonly description: "内置设备预设,提供 width/height/DPR/UA
|
|
920
|
+
readonly type: string;
|
|
921
|
+
readonly description: "内置设备预设,提供 width/height/DPR/UA 默认值;旧机型 ID 继续兼容";
|
|
926
922
|
}, {
|
|
927
923
|
readonly name: "width";
|
|
928
924
|
readonly type: "number";
|
|
@@ -935,6 +931,10 @@ export declare const COMMANDS: readonly [{
|
|
|
935
931
|
readonly name: "deviceScaleFactor";
|
|
936
932
|
readonly type: "number";
|
|
937
933
|
readonly description: "DPR(覆盖 preset)";
|
|
934
|
+
}, {
|
|
935
|
+
readonly name: "scale";
|
|
936
|
+
readonly type: "number";
|
|
937
|
+
readonly description: "画面视觉比例,不改变视口尺寸或 DPR;必须为有限正数,默认 1";
|
|
938
938
|
}, {
|
|
939
939
|
readonly name: "mobile";
|
|
940
940
|
readonly type: "boolean";
|
|
@@ -950,7 +950,11 @@ export declare const COMMANDS: readonly [{
|
|
|
950
950
|
}, {
|
|
951
951
|
readonly name: "touch";
|
|
952
952
|
readonly type: "boolean";
|
|
953
|
-
readonly description: "
|
|
953
|
+
readonly description: "是否启用触摸事件,默认从 preset 推断;无 preset 时跟随 mobile";
|
|
954
|
+
}, {
|
|
955
|
+
readonly name: "deviceShell";
|
|
956
|
+
readonly type: "boolean";
|
|
957
|
+
readonly description: "是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false";
|
|
954
958
|
}, {
|
|
955
959
|
readonly name: "reload";
|
|
956
960
|
readonly type: "boolean";
|
|
@@ -961,10 +965,10 @@ export declare const COMMANDS: readonly [{
|
|
|
961
965
|
readonly required: true;
|
|
962
966
|
readonly description: "目标标签页 ID";
|
|
963
967
|
}];
|
|
964
|
-
readonly examples: ["set_device_emulation --payload '{\"enabled\":true,\"preset\":\"iphone-
|
|
968
|
+
readonly examples: ["set_device_emulation --payload '{\"enabled\":true,\"preset\":\"iphone-17-pro\"}'", "set_device_emulation --payload '{\"enabled\":true,\"preset\":\"pixel-11\",\"orientation\":\"landscape\"}'", "set_device_emulation --payload '{\"enabled\":false}'"];
|
|
965
969
|
}, {
|
|
966
970
|
readonly name: "set_app_profile";
|
|
967
|
-
readonly description: "
|
|
971
|
+
readonly description: "设置 App 客户端环境与 JSBridge;传 emulation 时由同一个命令联动设备模拟,省略时不改变设备状态";
|
|
968
972
|
readonly summary: "设置或清除目标标签页的 App 容器模拟";
|
|
969
973
|
readonly params: [{
|
|
970
974
|
readonly name: "enabled";
|
|
@@ -987,18 +991,14 @@ export declare const COMMANDS: readonly [{
|
|
|
987
991
|
readonly name: "deviceModel";
|
|
988
992
|
readonly type: "string";
|
|
989
993
|
readonly description: "Android 机型名(拼入 UA 与 __DEVICE_MODEL__)";
|
|
990
|
-
}, {
|
|
991
|
-
readonly name: "simulateSystemBars";
|
|
992
|
-
readonly type: "boolean";
|
|
993
|
-
readonly description: "是否模拟顶部状态/导航栏与底部手势栏,默认 true";
|
|
994
|
-
}, {
|
|
995
|
-
readonly name: "emulation";
|
|
996
|
-
readonly type: "object";
|
|
997
|
-
readonly description: "覆盖档案推荐的设备模拟参数,字段同 set_device_emulation 去掉 enabled";
|
|
998
994
|
}, {
|
|
999
995
|
readonly name: "bridgeConfig";
|
|
1000
996
|
readonly type: "object";
|
|
1001
997
|
readonly description: "声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};不执行配置脚本";
|
|
998
|
+
}, {
|
|
999
|
+
readonly name: "emulation";
|
|
1000
|
+
readonly type: "object";
|
|
1001
|
+
readonly description: "可选设备联动参数,字段同 set_device_emulation 去掉 enabled/reload;字段覆盖档案推荐设备,deviceShell 默认 true。省略时不设置或清除设备";
|
|
1002
1002
|
}, {
|
|
1003
1003
|
readonly name: "reload";
|
|
1004
1004
|
readonly type: "boolean";
|
|
@@ -1009,7 +1009,7 @@ export declare const COMMANDS: readonly [{
|
|
|
1009
1009
|
readonly required: true;
|
|
1010
1010
|
readonly description: "目标标签页 ID";
|
|
1011
1011
|
}];
|
|
1012
|
-
readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"
|
|
1012
|
+
readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"emulation\":{}}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"alipay\",\"emulation\":{\"preset\":\"pixel-11\",\"deviceShell\":true}}'", "set_app_profile --payload '{\"enabled\":false}'", "set_app_profile --payload '{\"enabled\":false,\"emulation\":{}}'"];
|
|
1013
1013
|
}, {
|
|
1014
1014
|
readonly name: "set_timezone";
|
|
1015
1015
|
readonly description: "覆盖目标 tab 的时区,传空字符串恢复浏览器默认时区";
|
package/dist/commands.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { APP_PROFILE_NAMES, } from './generated-browser-action-protocol.js';
|
|
1
|
+
import { APP_PROFILE_NAMES, BROWSER_DEVICE_PRESET_NAMES, } from './generated-browser-action-protocol.js';
|
|
2
2
|
/** 容器档案名列表(拼进参数说明,新增档案无需改本文件) */
|
|
3
3
|
const APP_PROFILE_NAME_LIST = APP_PROFILE_NAMES.join('/');
|
|
4
|
+
const DEVICE_PRESET_TYPE = BROWSER_DEVICE_PRESET_NAMES.map(name => JSON.stringify(name)).join(' | ');
|
|
4
5
|
const PAGE_DIAGNOSTICS_PARAM = {
|
|
5
6
|
name: 'diagnostics',
|
|
6
7
|
type: 'object | boolean',
|
|
@@ -424,23 +425,18 @@ export const COMMANDS = [
|
|
|
424
425
|
{
|
|
425
426
|
name: 'emulation',
|
|
426
427
|
type: 'object',
|
|
427
|
-
description: '开 tab 即进入移动端模拟态(首屏即移动态、无需 reload)。字段同 set_device_emulation 去掉 enabled
|
|
428
|
+
description: '开 tab 即进入移动端模拟态(首屏即移动态、无需 reload)。字段同 set_device_emulation 去掉 enabled/reload;deviceShell=true 时页面从首屏起在 iframe WebView 中渲染设备系统外壳',
|
|
428
429
|
},
|
|
429
430
|
{
|
|
430
431
|
name: 'appProfile',
|
|
431
432
|
type: 'string',
|
|
432
|
-
description: '开 tab
|
|
433
|
+
description: '开 tab 即注入 App 客户端环境与 JSBridge;档案名同 set_app_profile,如 "fliggy"。需要 iframe WebView 和系统栏时同时传 emulation.deviceShell=true',
|
|
433
434
|
},
|
|
434
435
|
{
|
|
435
436
|
name: 'os',
|
|
436
437
|
type: '"ios" | "android"',
|
|
437
438
|
description: '与 appProfile 配合;容器系统,默认 ios',
|
|
438
439
|
},
|
|
439
|
-
{
|
|
440
|
-
name: 'simulateSystemBars',
|
|
441
|
-
type: 'boolean',
|
|
442
|
-
description: '与 appProfile 配合;是否模拟顶部状态/导航栏与底部手势栏,默认 true',
|
|
443
|
-
},
|
|
444
440
|
{
|
|
445
441
|
name: 'bridgeConfig',
|
|
446
442
|
type: 'object',
|
|
@@ -450,7 +446,7 @@ export const COMMANDS = [
|
|
|
450
446
|
examples: [
|
|
451
447
|
`tab_open --payload '{"url":"https://example.com"}'`,
|
|
452
448
|
`tab_open --payload '{"url":"https://example.com/page","reuse":"prefer","match":{"ignoreSearch":true}}'`,
|
|
453
|
-
`tab_open --payload '{"url":"https://m.example.com","emulation":{"preset":"iphone-
|
|
449
|
+
`tab_open --payload '{"url":"https://m.example.com","emulation":{"preset":"iphone-17-pro"}}'`,
|
|
454
450
|
`tab_open --payload '{"url":"https://market.m.taobao.com/app/trip/rx-home/pages/home","appProfile":"fliggy"}'`,
|
|
455
451
|
`tab_open --payload '{"url":"https://example.com","appProfile":"fliggy","os":"android"}'`,
|
|
456
452
|
`tab_open --payload '{"url":"https://example.com","group":"验证任务"}'`,
|
|
@@ -853,18 +849,23 @@ export const COMMANDS = [
|
|
|
853
849
|
// ── 移动端模拟 ────────────────────────────────────────────────────────────
|
|
854
850
|
{
|
|
855
851
|
name: 'set_device_emulation',
|
|
856
|
-
description: '把目标 tab 切换为移动端模拟(视口/UA
|
|
852
|
+
description: '把目标 tab 切换为移动端模拟(视口/DPR/UA/触摸/视觉比例),等价 DevTools 设备工具栏,作用域 per-tab;需保持调试控制才持续生效',
|
|
857
853
|
summary: '设置或清除目标标签页的设备模拟',
|
|
858
854
|
params: [
|
|
859
855
|
{ name: 'enabled', type: 'boolean', required: true, description: 'true=启用,false=清除' },
|
|
860
856
|
{
|
|
861
857
|
name: 'preset',
|
|
862
|
-
type:
|
|
863
|
-
description: '内置设备预设,提供 width/height/DPR/UA
|
|
858
|
+
type: DEVICE_PRESET_TYPE,
|
|
859
|
+
description: '内置设备预设,提供 width/height/DPR/UA 默认值;旧机型 ID 继续兼容',
|
|
864
860
|
},
|
|
865
861
|
{ name: 'width', type: 'number', description: '视口宽度(覆盖 preset)' },
|
|
866
862
|
{ name: 'height', type: 'number', description: '视口高度(覆盖 preset)' },
|
|
867
863
|
{ name: 'deviceScaleFactor', type: 'number', description: 'DPR(覆盖 preset)' },
|
|
864
|
+
{
|
|
865
|
+
name: 'scale',
|
|
866
|
+
type: 'number',
|
|
867
|
+
description: '画面视觉比例,不改变视口尺寸或 DPR;必须为有限正数,默认 1',
|
|
868
|
+
},
|
|
868
869
|
{ name: 'mobile', type: 'boolean', description: '是否走移动渲染模式,默认从 preset 推断' },
|
|
869
870
|
{ name: 'userAgent', type: 'string', description: '自定义 UA(覆盖 preset)' },
|
|
870
871
|
{
|
|
@@ -872,19 +873,28 @@ export const COMMANDS = [
|
|
|
872
873
|
type: '"portrait" | "landscape"',
|
|
873
874
|
description: '横竖屏,默认 portrait',
|
|
874
875
|
},
|
|
875
|
-
{
|
|
876
|
+
{
|
|
877
|
+
name: 'touch',
|
|
878
|
+
type: 'boolean',
|
|
879
|
+
description: '是否启用触摸事件,默认从 preset 推断;无 preset 时跟随 mobile',
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
name: 'deviceShell',
|
|
883
|
+
type: 'boolean',
|
|
884
|
+
description: '是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false',
|
|
885
|
+
},
|
|
876
886
|
{ name: 'reload', type: 'boolean', description: '启用后是否重载页面,默认 true' },
|
|
877
887
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
878
888
|
],
|
|
879
889
|
examples: [
|
|
880
|
-
`set_device_emulation --payload '{"enabled":true,"preset":"iphone-
|
|
881
|
-
`set_device_emulation --payload '{"enabled":true,"preset":"pixel-
|
|
890
|
+
`set_device_emulation --payload '{"enabled":true,"preset":"iphone-17-pro"}'`,
|
|
891
|
+
`set_device_emulation --payload '{"enabled":true,"preset":"pixel-11","orientation":"landscape"}'`,
|
|
882
892
|
`set_device_emulation --payload '{"enabled":false}'`,
|
|
883
893
|
],
|
|
884
894
|
},
|
|
885
895
|
{
|
|
886
896
|
name: 'set_app_profile',
|
|
887
|
-
description: '
|
|
897
|
+
description: '设置 App 客户端环境与 JSBridge;传 emulation 时由同一个命令联动设备模拟,省略时不改变设备状态',
|
|
888
898
|
summary: '设置或清除目标标签页的 App 容器模拟',
|
|
889
899
|
params: [
|
|
890
900
|
{ name: 'enabled', type: 'boolean', required: true, description: 'true=启用,false=清除' },
|
|
@@ -901,28 +911,24 @@ export const COMMANDS = [
|
|
|
901
911
|
description: 'Android 机型名(拼入 UA 与 __DEVICE_MODEL__)',
|
|
902
912
|
},
|
|
903
913
|
{
|
|
904
|
-
name: '
|
|
905
|
-
type: 'boolean',
|
|
906
|
-
description: '是否模拟顶部状态/导航栏与底部手势栏,默认 true',
|
|
907
|
-
},
|
|
908
|
-
{
|
|
909
|
-
name: 'emulation',
|
|
914
|
+
name: 'bridgeConfig',
|
|
910
915
|
type: 'object',
|
|
911
|
-
description: '
|
|
916
|
+
description: '声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};不执行配置脚本',
|
|
912
917
|
},
|
|
913
918
|
{
|
|
914
|
-
name: '
|
|
919
|
+
name: 'emulation',
|
|
915
920
|
type: 'object',
|
|
916
|
-
description: '
|
|
921
|
+
description: '可选设备联动参数,字段同 set_device_emulation 去掉 enabled/reload;字段覆盖档案推荐设备,deviceShell 默认 true。省略时不设置或清除设备',
|
|
917
922
|
},
|
|
918
923
|
{ name: 'reload', type: 'boolean', description: '应用/清除后是否重载页面,默认 true' },
|
|
919
924
|
{ name: 'tabId', type: 'number', required: true, description: '目标标签页 ID' },
|
|
920
925
|
],
|
|
921
926
|
examples: [
|
|
922
927
|
`set_app_profile --payload '{"enabled":true,"profile":"fliggy"}'`,
|
|
923
|
-
`set_app_profile --payload '{"enabled":true,"profile":"fliggy","
|
|
924
|
-
`set_app_profile --payload '{"enabled":true,"profile":"alipay","
|
|
928
|
+
`set_app_profile --payload '{"enabled":true,"profile":"fliggy","emulation":{}}'`,
|
|
929
|
+
`set_app_profile --payload '{"enabled":true,"profile":"alipay","emulation":{"preset":"pixel-11","deviceShell":true}}'`,
|
|
925
930
|
`set_app_profile --payload '{"enabled":false}'`,
|
|
931
|
+
`set_app_profile --payload '{"enabled":false,"emulation":{}}'`,
|
|
926
932
|
],
|
|
927
933
|
},
|
|
928
934
|
{
|
|
@@ -262,16 +262,20 @@ export interface PageSelectedElementParams {
|
|
|
262
262
|
includeOuterHTML?: boolean;
|
|
263
263
|
includeScreenshot?: boolean;
|
|
264
264
|
}
|
|
265
|
-
export
|
|
265
|
+
export declare const BROWSER_DEVICE_PRESET_NAMES: readonly ["iphone-17-pro", "iphone-17e", "pixel-11", "ipad-mini-a17-pro", "galaxy-s26", "pura-x-max", "iphone-15-pro", "iphone-se", "pixel-8", "ipad-mini", "galaxy-s23"];
|
|
266
|
+
export type BrowserDevicePresetName = (typeof BROWSER_DEVICE_PRESET_NAMES)[number];
|
|
266
267
|
export interface BrowserEmulationOptions {
|
|
267
268
|
preset?: BrowserDevicePresetName;
|
|
268
269
|
width?: number;
|
|
269
270
|
height?: number;
|
|
270
271
|
deviceScaleFactor?: number;
|
|
272
|
+
scale?: number;
|
|
271
273
|
mobile?: boolean;
|
|
272
274
|
userAgent?: string;
|
|
273
275
|
orientation?: 'portrait' | 'landscape';
|
|
274
276
|
touch?: boolean;
|
|
277
|
+
/** 在 iframe WebView 外渲染设备系统栏;默认 false,保持纯 CDP 设备模拟。 */
|
|
278
|
+
deviceShell?: boolean;
|
|
275
279
|
}
|
|
276
280
|
export type AppBridgeConfigBehavior = 'navigate' | 'closeAll' | 'closeBackData' | 'postMessage' | 'notifySubscribe' | 'notifyUnsubscribe' | 'notifyPost' | 'sharedFileRead' | 'sharedFileWrite' | 'sharedDataGet' | 'sharedDataSet' | 'legacyBroadcastCreate' | 'legacyBroadcastPost' | 'legacyBroadcastClose' | 'memoryGet' | 'memorySet' | 'memoryDelete' | 'availabilityMap' | 'userInfo' | 'networkInfo' | 'geolocation' | 'permission' | 'prefetch' | 'fptTrack' | 'mtopStream' | 'previewFile' | 'toast' | 'unsupportedNativeInput' | 'payment' | 'userTrack' | 'calendar' | 'networkQualityMonitor' | 'beaconRequest';
|
|
277
281
|
/** 单个桥方法的声明式覆盖;行为、固定回包、成功空实现三选一。 */
|
|
@@ -302,15 +306,12 @@ export interface TabOpenParams {
|
|
|
302
306
|
emulation?: BrowserEmulationOptions;
|
|
303
307
|
group?: string;
|
|
304
308
|
/**
|
|
305
|
-
* 客户端容器模拟档案名(如 'fliggy'
|
|
306
|
-
*
|
|
307
|
-
* 并根据页面协议与桥调用切换普通、沉浸或隐藏状态。可用档案见 APP_PROFILE_NAMES。
|
|
309
|
+
* 客户端容器模拟档案名(如 'fliggy')。只注入容器 UA、环境变量、JSBridge 与桥协议;
|
|
310
|
+
* 设备视口和 iframe 系统外壳由 emulation.deviceShell 独立控制。可用档案见 APP_PROFILE_NAMES。
|
|
308
311
|
*/
|
|
309
312
|
appProfile?: AppProfileName;
|
|
310
313
|
/** 与 appProfile 配合使用;容器系统,默认 ios */
|
|
311
314
|
os?: 'ios' | 'android';
|
|
312
|
-
/** 与 appProfile 配合使用;是否模拟顶部状态/导航栏与底部手势栏,默认 true */
|
|
313
|
-
simulateSystemBars?: boolean;
|
|
314
315
|
/** 与 appProfile 配合使用;按方法覆盖档案内置桥配置 */
|
|
315
316
|
bridgeConfig?: AppBridgeConfig;
|
|
316
317
|
}
|
|
@@ -333,11 +334,12 @@ export interface SetAppProfileParams {
|
|
|
333
334
|
os?: 'ios' | 'android';
|
|
334
335
|
appVersion?: string;
|
|
335
336
|
deviceModel?: string;
|
|
336
|
-
/** 是否模拟顶部状态/导航栏与底部手势栏,默认 true */
|
|
337
|
-
simulateSystemBars?: boolean;
|
|
338
337
|
/** 按方法覆盖档案内置桥配置,仅支持受控行为、固定 JSON 回包和成功空实现 */
|
|
339
338
|
bridgeConfig?: AppBridgeConfig;
|
|
340
|
-
/**
|
|
339
|
+
/**
|
|
340
|
+
* 可选设备联动参数。传入时显式字段覆盖档案推荐设备,空对象使用推荐设备且默认开启
|
|
341
|
+
* deviceShell;省略时不设置或清除该 tab 的设备状态。
|
|
342
|
+
*/
|
|
341
343
|
emulation?: BrowserEmulationOptions;
|
|
342
344
|
/** 默认 true:应用/清除后刷新页面使注入生效 */
|
|
343
345
|
reload?: boolean;
|
|
@@ -6,6 +6,20 @@ export const SEND_REQUEST_MAX_TOTAL_FILE_BYTES = 40 * 1024 * 1024;
|
|
|
6
6
|
// Base64 expands by 4/3; 7 MiB leaves roughly 680 KiB for JSON framing under
|
|
7
7
|
// the 10 MiB cloud message limit.
|
|
8
8
|
export const SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES = 7 * 1024 * 1024;
|
|
9
|
+
export const BROWSER_DEVICE_PRESET_NAMES = [
|
|
10
|
+
'iphone-17-pro',
|
|
11
|
+
'iphone-17e',
|
|
12
|
+
'pixel-11',
|
|
13
|
+
'ipad-mini-a17-pro',
|
|
14
|
+
'galaxy-s26',
|
|
15
|
+
'pura-x-max',
|
|
16
|
+
// 旧名称保留具体机型语义,供已有调用与历史回归基线继续使用。
|
|
17
|
+
'iphone-15-pro',
|
|
18
|
+
'iphone-se',
|
|
19
|
+
'pixel-8',
|
|
20
|
+
'ipad-mini',
|
|
21
|
+
'galaxy-s23',
|
|
22
|
+
];
|
|
9
23
|
/**
|
|
10
24
|
* 客户端容器模拟可用档案名。
|
|
11
25
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invoke, listCloudConnectors, } from './unified.js';
|
|
8
8
|
export type { UnifiedClientOptions, UnifiedInvokeOptions, UnifiedInvokeOptions as InvokeOptions, } from './unified.js';
|
|
9
|
-
export { APP_PROFILE_NAMES, 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
|
+
export { APP_PROFILE_NAMES, BROWSER_DEVICE_PRESET_NAMES, 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';
|
|
10
10
|
export type { ActionStep, AppProfileName, 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, SetAppProfileParams, 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';
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* then routes actions using the global browser ids returned by browser_list.
|
|
6
6
|
*/
|
|
7
7
|
export { UnifiedClient, UnifiedClient as MearlClient, decodeBrowserTarget, invoke, listCloudConnectors, } from './unified.js';
|
|
8
|
-
export { APP_PROFILE_NAMES, 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';
|
|
8
|
+
export { APP_PROFILE_NAMES, BROWSER_DEVICE_PRESET_NAMES, 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
10
|
export function tabCheckpoint(params = {}, options) {
|
|
11
11
|
return invoke('tab_checkpoint', params, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"description": "Unified Mearl SDK & CLI for local and remote browsers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"commander": "^15.0.0",
|
|
56
56
|
"fastest-levenshtein": "^1.0.16",
|
|
57
57
|
"ws": "^8.18.0",
|
|
58
|
-
"@mearl/cloud-types": "2.
|
|
58
|
+
"@mearl/cloud-types": "2.10.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/node": "^24.9.1",
|