New:Socket for Asana Is Now Available.Learn more
Get Started

@mearl/client

Package Overview
Dependencies
Maintainers
2
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mearl/client - npm Package Compare versions

Comparing version
2.8.1
to
2.8.2
+51
-0
dist/check.d.ts

@@ -0,2 +1,48 @@

import type { CloudConnectorInfo } from '@mearl/cloud-types';
import { type UnifiedClientOptions, type UnifiedInvokeOptions } from './unified.js';
export interface UnifiedCheckVersions {
nativeHost?: string;
extension?: string | null;
browser?: string | null;
}
interface BrowserInfo {
browserId: string;
extensionVersion?: string;
name: string;
nativeHostVersion?: string;
originalBrowserId?: string;
originalName?: string;
status: string;
type?: string;
provider?: 'local' | 'agentbay';
transport?: 'extension' | 'cdp';
}
interface CheckItem {
status: 'ok' | 'warning' | 'error';
label: string;
details?: string[];
}
export interface ExtensionInstallationInfo {
extensionId: string;
setupManagedPath: string | null;
}
export interface UnifiedCheckBrowserResult extends BrowserInfo {
agentbayAccessUrl?: string;
check?: {
errors?: string[];
label: string;
status: CheckItem['status'];
warnings?: string[];
};
extensionInstallation?: ExtensionInstallationInfo;
selected: boolean;
versions?: UnifiedCheckVersions;
}
export interface UnifiedCheckResult {
browsers: UnifiedCheckBrowserResult[];
clientVersion: string;
connectors: CloudConnectorInfo[];
environment: CheckItem[];
ok: boolean;
}
interface CheckClient {

@@ -15,9 +61,14 @@ invoke(action: string, data?: Record<string, any>, options?: UnifiedInvokeOptions): Promise<any>;

transport?: 'cdp';
json?: boolean;
}
export interface UnifiedCheckDependencies {
createClient?: (options: UnifiedClientOptions) => CheckClient;
writeJson?: (json: string) => void;
writeLine?: (line: string) => void;
}
export declare function parseCheckTimeout(value: string | undefined): number | null;
export declare function runUnifiedCheck(options: UnifiedCheckOptions & {
json: true;
}, dependencies?: UnifiedCheckDependencies): Promise<UnifiedCheckResult>;
export declare function runUnifiedCheck(options: UnifiedCheckOptions, dependencies?: UnifiedCheckDependencies): Promise<boolean>;
export {};
+64
-3

@@ -76,2 +76,3 @@ import { UnifiedClient } from './unified.js';

const writeLine = dependencies.writeLine ?? (line => console.error(line));
const writeJson = dependencies.writeJson ?? (json => process.stdout.write(`${json}\n`));
const createClient = dependencies.createClient ??

@@ -198,2 +199,7 @@ ((clientOptions) => new UnifiedClient(clientOptions));

}));
const publicVersions = {
...(versions.nativeHost ? { nativeHost: versions.nativeHost } : {}),
...(versions.extension !== undefined ? { extension: versions.extension } : {}),
...(versions.browser !== undefined ? { browser: versions.browser } : {}),
};
const details = [

@@ -204,2 +210,14 @@ versions.nativeHost ? `native-host v${versions.nativeHost}` : null,

].filter((value) => value !== null);
let extensionInstallation;
if (options.local &&
browser.transport === 'extension' &&
typeof versions.extensionId === 'string' &&
typeof versions.extension === 'string' &&
(typeof versions.setupManagedPath === 'string' || versions.setupManagedPath === null)) {
extensionInstallation = {
extensionId: versions.extensionId,
setupManagedPath: versions.setupManagedPath,
};
}
let agentbayAccessUrl;
let accessUrlWarning;

@@ -215,2 +233,3 @@ if (browser.provider === 'agentbay' && options.browser) {

}
agentbayAccessUrl = access.agentbayAccessUrl;
details.push(`AgentBay access URL (temporary, sensitive): ${access.agentbayAccessUrl}`);

@@ -224,3 +243,5 @@ }

browserChecks.push({
...(agentbayAccessUrl ? { agentbayAccessUrl } : {}),
browser,
...(extensionInstallation ? { extensionInstallation } : {}),
item: {

@@ -233,2 +254,4 @@ status: accessUrlWarning ? 'warning' : 'ok',

},
versions: publicVersions,
...(accessUrlWarning ? { warnings: [accessUrlWarning] } : {}),
});

@@ -240,2 +263,5 @@ }

browser,
...(message.includes('Unknown action')
? { warnings: ['Update @mearl/native-host for complete diagnostics.'] }
: { errors: [message] }),
item: message.includes('Unknown action')

@@ -255,2 +281,40 @@ ? {

}));
const hasError = environment.some(item => item.status === 'error') ||
browserChecks.some(check => check.item.status === 'error');
const listedBrowsers = browserList?.browsers ?? [];
if (options.json) {
const result = {
browsers: listedBrowsers.map(browser => {
const check = browserChecks.find(item => item.browser.browserId === browser.browserId);
const browserIdentity = { ...browser };
delete browserIdentity.extensionVersion;
delete browserIdentity.nativeHostVersion;
return {
...browserIdentity,
selected: targets.some(target => target.browserId === browser.browserId),
...(check?.agentbayAccessUrl ? { agentbayAccessUrl: check.agentbayAccessUrl } : {}),
...(check?.item
? {
check: {
label: check.item.label,
status: check.item.status,
...(check.errors ? { errors: check.errors } : {}),
...(check.warnings ? { warnings: check.warnings } : {}),
},
}
: {}),
...(check?.extensionInstallation
? { extensionInstallation: check.extensionInstallation }
: {}),
...(check?.versions ? { versions: check.versions } : {}),
};
}),
clientVersion: options.clientVersion,
connectors,
environment,
ok: !hasError,
};
writeJson(JSON.stringify(result, null, 2));
return result;
}
writeLine('');

@@ -264,3 +328,2 @@ printSection(writeLine, 'Environment', environment);

}
const listedBrowsers = browserList?.browsers ?? [];
if (listedBrowsers.length > 0) {

@@ -283,4 +346,2 @@ writeLine('Browsers');

}
const hasError = environment.some(item => item.status === 'error') ||
browserChecks.some(check => check.item.status === 'error');
if (hasError) {

@@ -287,0 +348,0 @@ writeLine('⚠️ Mearl checks failed. See the browser or source details above.');

+13
-4

@@ -84,2 +84,3 @@ import { readFileSync, writeFileSync } from 'node:fs';

' --compact 输出紧凑格式 JSON',
' --json check 输出机器可读 JSON',
' --output <path> 保存输出或截图',

@@ -196,3 +197,3 @@ ' --browser <id|名称> 指定 browser_list 返回的浏览器',

]);
const flags = new Set(['--compact', '--local', '--cdp', '--help', '-h']);
const flags = new Set(['--compact', '--json', '--local', '--cdp', '--help', '-h']);
for (let index = 1; index < args.length; index += 1) {

@@ -227,2 +228,5 @@ const arg = args[index];

const action = args[0];
const json = args.includes('--json');
if (json && action !== 'check')
throw new Error('--json 仅适用于 check');
const payload = parsePayload(args);

@@ -241,2 +245,3 @@ const fallbackTimeout = resolveActionTimeoutSec(action, payload, 60);

forceCdp,
json,
local,

@@ -319,3 +324,3 @@ ...(optionValue(args, '--output') ? { outputPath: optionValue(args, '--output') } : {}),

}
const ok = await runUnifiedCheck({
const checkOptions = {
clientVersion,

@@ -329,4 +334,8 @@ timeoutSec,

...(parsed.forceCdp ? { transport: 'cdp' } : {}),
});
return ok ? 0 : 1;
};
if (parsed.json) {
const result = await runUnifiedCheck({ ...checkOptions, json: true });
return result.ok ? 0 : 1;
}
return (await runUnifiedCheck(checkOptions)) ? 0 : 1;
}

@@ -333,0 +342,0 @@ if (parsed.action === 'page_selected_element' && parsed.outputPath) {

@@ -505,4 +505,12 @@ import { type BrowserCommandAction } from './generated-browser-action-protocol.js';

readonly description: "开 tab 即进入 App 容器模拟态(客户端 UA + JSBridge 托管 + iframe 容器栈 + 自适应系统标题栏,首屏即容器态)。系统栏由 iframe 外层统一渲染,并根据页面协议与桥调用切换普通、沉浸或隐藏状态;档案名同 set_app_profile,如 \"fliggy\"";
}, {
readonly name: "os";
readonly type: "\"ios\" | \"android\"";
readonly description: "与 appProfile 配合;容器系统,默认 ios";
}, {
readonly name: "simulateSystemBars";
readonly type: "boolean";
readonly description: "与 appProfile 配合;是否模拟顶部状态/导航栏与底部手势栏,默认 true";
}];
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-15-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\",\"group\":\"验证任务\"}'"];
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-15-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\":\"验证任务\"}'"];
}, {

@@ -957,2 +965,6 @@ readonly name: "tab_close";

}, {
readonly name: "simulateSystemBars";
readonly type: "boolean";
readonly description: "是否模拟顶部状态/导航栏与底部手势栏,默认 true";
}, {
readonly name: "emulation";

@@ -971,3 +983,3 @@ readonly type: "object";

}];
readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"alipay\",\"os\":\"android\",\"deviceModel\":\"Pixel 8 Pro\"}'", "set_app_profile --payload '{\"enabled\":false}'"];
readonly examples: ["set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\"}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"fliggy\",\"simulateSystemBars\":false}'", "set_app_profile --payload '{\"enabled\":true,\"profile\":\"alipay\",\"os\":\"android\",\"deviceModel\":\"Pixel 8 Pro\"}'", "set_app_profile --payload '{\"enabled\":false}'"];
}, {

@@ -974,0 +986,0 @@ readonly name: "set_timezone";

@@ -413,2 +413,12 @@ import { APP_PROFILE_NAMES, } from './generated-browser-action-protocol.js';

},
{
name: 'os',
type: '"ios" | "android"',
description: '与 appProfile 配合;容器系统,默认 ios',
},
{
name: 'simulateSystemBars',
type: 'boolean',
description: '与 appProfile 配合;是否模拟顶部状态/导航栏与底部手势栏,默认 true',
},
],

@@ -420,2 +430,3 @@ examples: [

`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":"验证任务"}'`,

@@ -855,2 +866,7 @@ ],

{
name: 'simulateSystemBars',
type: 'boolean',
description: '是否模拟顶部状态/导航栏与底部手势栏,默认 true',
},
{
name: 'emulation',

@@ -865,2 +881,3 @@ type: 'object',

`set_app_profile --payload '{"enabled":true,"profile":"fliggy"}'`,
`set_app_profile --payload '{"enabled":true,"profile":"fliggy","simulateSystemBars":false}'`,
`set_app_profile --payload '{"enabled":true,"profile":"alipay","os":"android","deviceModel":"Pixel 8 Pro"}'`,

@@ -867,0 +884,0 @@ `set_app_profile --payload '{"enabled":false}'`,

@@ -296,2 +296,6 @@ export interface GetRequestsParams {

appProfile?: AppProfileName;
/** 与 appProfile 配合使用;容器系统,默认 ios */
os?: 'ios' | 'android';
/** 与 appProfile 配合使用;是否模拟顶部状态/导航栏与底部手势栏,默认 true */
simulateSystemBars?: boolean;
}

@@ -317,2 +321,4 @@ /**

deviceModel?: string;
/** 是否模拟顶部状态/导航栏与底部手势栏,默认 true */
simulateSystemBars?: boolean;
/** 覆盖档案推荐的设备模拟参数(视口/UA 默认取档案值) */

@@ -319,0 +325,0 @@ emulation?: BrowserEmulationOptions;

{
"name": "@mearl/client",
"version": "2.8.1",
"version": "2.8.2",
"description": "Unified Mearl SDK & CLI for local and remote browsers",

@@ -54,3 +54,3 @@ "type": "module",

"ws": "^8.18.0",
"@mearl/cloud-types": "2.8.1"
"@mearl/cloud-types": "2.8.2"
},

@@ -57,0 +57,0 @@ "devDependencies": {

@@ -58,2 +58,3 @@ # @mearl/client

mearl check
mearl check --local --json

@@ -60,0 +61,0 @@ # 更新本地环境