@mearl/client
Advanced tools
| import { PAGE_ACT_ACTIONS } from './generated-browser-action-protocol.js'; | ||
| const SEND_REQUEST_FILE_TRANSFER_TIMEOUT_MS = 120_000; | ||
| function boundedNumber(value, fallback, minimum, maximum) { | ||
@@ -19,3 +20,6 @@ const numeric = Number(value); | ||
| if (action === 'send_request') { | ||
| return Math.max(fallback, Math.ceil(((data.timeout ?? 30000) + 5000) / 1000)); | ||
| const transferTimeoutMs = Array.isArray(data.files) && data.files.length > 0 | ||
| ? SEND_REQUEST_FILE_TRANSFER_TIMEOUT_MS | ||
| : 0; | ||
| return Math.max(fallback, Math.ceil(((data.timeout ?? 30000) + transferTimeoutMs + 5000) / 1000)); | ||
| } | ||
@@ -37,2 +41,12 @@ if (action === 'send_mtop_request') { | ||
| return Math.max(fallback, 20); | ||
| if (action === 'run_actions') { | ||
| const actions = Array.isArray(data.actions) ? data.actions : [{}]; | ||
| const timeoutSec = actions.reduce((total, step) => { | ||
| const stepAction = String(step?.action ?? ''); | ||
| if (!stepAction || stepAction === 'run_actions') | ||
| return total + 15; | ||
| return total + resolveActionTimeoutSec(stepAction, step?.data ?? {}, 15); | ||
| }, 0); | ||
| return Math.max(fallback, timeoutSec); | ||
| } | ||
| // 页面交互动作默认内置观察,超时需覆盖观察与导航窗口;observe:false 时是裸动作,用默认超时 | ||
@@ -46,7 +60,3 @@ const observedAction = OBSERVED_PAGE_ACTIONS.has(action); | ||
| } | ||
| if (action === 'run_actions') { | ||
| const steps = Array.isArray(data.actions) ? data.actions.length : 1; | ||
| return Math.max(fallback, steps * 15); | ||
| } | ||
| return fallback; | ||
| } |
+15
-7
@@ -167,3 +167,3 @@ import type { BrowserCommandAction } from './generated-browser-action-protocol.js'; | ||
| readonly name: "send_request"; | ||
| readonly description: "发送 HTTP 请求,自动携带浏览器 Cookie"; | ||
| readonly description: "发送 HTTP 请求,自动携带浏览器 Cookie,支持 multipart 文件上传"; | ||
| readonly params: [{ | ||
@@ -191,2 +191,10 @@ readonly name: "url"; | ||
| }, { | ||
| readonly name: "formData"; | ||
| readonly type: "object"; | ||
| readonly description: "multipart 文本字段(值支持 string/number/boolean)"; | ||
| }, { | ||
| readonly name: "files"; | ||
| readonly type: "SendRequestFile[]"; | ||
| readonly description: "multipart 文件,最多 20 个、总计不超过 40 MiB;Base64 文件总计不超过 7 MiB。每项传 fieldName 和绝对 filePath,或传 base64 + filename"; | ||
| }, { | ||
| readonly name: "withCookies"; | ||
@@ -196,6 +204,2 @@ readonly type: "boolean"; | ||
| }, { | ||
| readonly name: "cookieDomain"; | ||
| readonly type: "string"; | ||
| readonly description: "指定 Cookie 域名,不填时从 url 提取"; | ||
| }, { | ||
| readonly name: "timeout"; | ||
@@ -205,3 +209,3 @@ readonly type: "number"; | ||
| }]; | ||
| readonly examples: ["send_request --payload '{\"url\":\"https://api.example.com/data\",\"method\":\"GET\"}'"]; | ||
| readonly examples: ["send_request --payload '{\"url\":\"https://api.example.com/data\",\"method\":\"GET\"}'", "send_request --payload '{\"url\":\"https://api.example.com/upload\",\"method\":\"POST\",\"formData\":{\"folder\":\"assets\"},\"files\":[{\"fieldName\":\"file\",\"filePath\":\"/absolute/path/image.png\"}]}'"]; | ||
| }, { | ||
@@ -359,2 +363,6 @@ readonly name: "send_mtop_request"; | ||
| }, { | ||
| readonly name: "openerTabId"; | ||
| readonly type: "number"; | ||
| readonly description: "来源 Tab ID;用于把目标 Tab 关联到来源侧边栏对话"; | ||
| }, { | ||
| readonly name: "closeExisting"; | ||
@@ -401,3 +409,3 @@ readonly type: "boolean"; | ||
| readonly name: "page_click"; | ||
| readonly description: "点击页面元素,支持 selector / text / point 三种定位方式;auto 在可见页按设备模拟状态使用可信 mouse/touch,隐藏页使用 DOM fallback"; | ||
| readonly description: "点击页面元素,支持 selector / text / point 三种定位方式;auto 在可见页按设备模拟状态使用可信 mouse/touch,隐藏页使用 DOM fallback;点击直接打开新标签页时 observation.openedTabs 返回目标信息"; | ||
| readonly params: [{ | ||
@@ -404,0 +412,0 @@ readonly name: "selector"; |
+21
-4
@@ -128,3 +128,3 @@ export const COMMANDS = [ | ||
| name: 'send_request', | ||
| description: '发送 HTTP 请求,自动携带浏览器 Cookie', | ||
| description: '发送 HTTP 请求,自动携带浏览器 Cookie,支持 multipart 文件上传', | ||
| params: [ | ||
@@ -136,7 +136,19 @@ { name: 'url', type: 'string', required: true, description: '完整目标 URL' }, | ||
| { name: 'body', type: 'any', description: '请求体(传对象时自动 JSON 序列化)' }, | ||
| { | ||
| name: 'formData', | ||
| type: 'object', | ||
| description: 'multipart 文本字段(值支持 string/number/boolean)', | ||
| }, | ||
| { | ||
| name: 'files', | ||
| type: 'SendRequestFile[]', | ||
| description: 'multipart 文件,最多 20 个、总计不超过 40 MiB;Base64 文件总计不超过 7 MiB。每项传 fieldName 和绝对 filePath,或传 base64 + filename', | ||
| }, | ||
| { name: 'withCookies', type: 'boolean', description: '是否附加浏览器 Cookie,默认 true' }, | ||
| { name: 'cookieDomain', type: 'string', description: '指定 Cookie 域名,不填时从 url 提取' }, | ||
| { name: 'timeout', type: 'number', description: '超时毫秒数,默认 30000' }, | ||
| ], | ||
| examples: [`send_request --payload '{"url":"https://api.example.com/data","method":"GET"}'`], | ||
| examples: [ | ||
| `send_request --payload '{"url":"https://api.example.com/data","method":"GET"}'`, | ||
| `send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}'`, | ||
| ], | ||
| }, | ||
@@ -265,2 +277,7 @@ { | ||
| { | ||
| name: 'openerTabId', | ||
| type: 'number', | ||
| description: '来源 Tab ID;用于把目标 Tab 关联到来源侧边栏对话', | ||
| }, | ||
| { | ||
| name: 'closeExisting', | ||
@@ -317,3 +334,3 @@ type: 'boolean', | ||
| name: 'page_click', | ||
| description: '点击页面元素,支持 selector / text / point 三种定位方式;auto 在可见页按设备模拟状态使用可信 mouse/touch,隐藏页使用 DOM fallback', | ||
| description: '点击页面元素,支持 selector / text / point 三种定位方式;auto 在可见页按设备模拟状态使用可信 mouse/touch,隐藏页使用 DOM fallback;点击直接打开新标签页时 observation.openedTabs 返回目标信息', | ||
| params: [ | ||
@@ -320,0 +337,0 @@ { |
@@ -51,2 +51,25 @@ export interface GetRequestsParams { | ||
| } | ||
| export declare const SEND_REQUEST_MAX_FILES = 20; | ||
| export declare const SEND_REQUEST_MAX_TOTAL_FILE_BYTES: number; | ||
| export declare const SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES: number; | ||
| export type SendRequestFormValue = string | number | boolean; | ||
| interface SendRequestFileMetadata { | ||
| /** multipart/form-data field name. */ | ||
| fieldName: string; | ||
| /** Defaults to a MIME type inferred from filename, then application/octet-stream. */ | ||
| contentType?: string; | ||
| } | ||
| export type SendRequestFile = SendRequestFileMetadata & ({ | ||
| /** Absolute path on the machine running Mearl native-host. */ | ||
| filePath: string; | ||
| base64?: never; | ||
| /** Defaults to the basename of filePath. */ | ||
| filename?: string; | ||
| } | { | ||
| filePath?: never; | ||
| /** Base64 payload; decoded Base64-backed files are limited to 7 MiB total. */ | ||
| base64: string; | ||
| /** Multipart filename for the Base64 payload. */ | ||
| filename: string; | ||
| }); | ||
| export interface SendRequestParams { | ||
@@ -58,4 +81,5 @@ url: string; | ||
| body?: unknown; | ||
| formData?: Record<string, SendRequestFormValue>; | ||
| files?: SendRequestFile[]; | ||
| withCookies?: boolean; | ||
| cookieDomain?: string; | ||
| responseType?: 'json' | 'text' | 'auto'; | ||
@@ -208,2 +232,4 @@ timeout?: number; | ||
| active?: boolean; | ||
| /** Source tab whose Agent conversation should own the opened or reused tab. */ | ||
| openerTabId?: number; | ||
| closeExisting?: boolean; | ||
@@ -681,1 +707,2 @@ reuse?: 'never' | 'prefer' | 'require'; | ||
| export declare function isExtensionBrowserAction(value: unknown): value is ExtensionBrowserAction; | ||
| export {}; |
| // Generated by scripts/generate-client-action-protocol.mjs. | ||
| // Do not edit directly; update browser-core/src/browserActionProtocol.ts. | ||
| export const SEND_REQUEST_MAX_FILES = 20; | ||
| // Bounds multipart buffering in native-host and the extension service worker. | ||
| export const SEND_REQUEST_MAX_TOTAL_FILE_BYTES = 40 * 1024 * 1024; | ||
| // Base64 expands by 4/3; 7 MiB leaves roughly 680 KiB for JSON framing under | ||
| // the 10 MiB cloud message limit. | ||
| export const SEND_REQUEST_MAX_TOTAL_BASE64_FILE_BYTES = 7 * 1024 * 1024; | ||
| export const PAGE_ACT_ACTIONS = [ | ||
@@ -4,0 +10,0 @@ 'page_click', |
+2
-2
@@ -9,4 +9,4 @@ /** | ||
| export type { InvokeOptions } from './socket.js'; | ||
| export { BROWSER_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PAGE_ACT_ACTIONS, isBrowserAction, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js'; | ||
| export type { ActionStep, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserReleaseFailure, BrowserReleaseResult, BrowserStatus, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, ManagedBrowserAccount, ManagedBrowserInfo, PageClickParams, PageActAction, PageEvalParams, PageFramesParams, PageHoverParams, PageNavigateParams, PageObservationWaitOptions, PagePressParams, PageScreenshotParams, PageScrollParams, PageSelectedElementParams, PageSnapshotParams, PageSnapshotQuery, PageTypeParams, PageUploadParams, PageWaitParams, RecordParams, RegularBrowserInfo, RequestDomainPermissionParams, RulesResult, RunActionName, RunActionsParams, SelectBrowserParams, SelectBrowserResult, SendMtopRequestParams, SendRequestParams, SetCookieParams, SetCookieResult, SetDeviceEmulationParams, SetMockParams, SetRuleParams, SetTimezoneParams, SetTimezoneResult, TabCloseParams, TabOpenParams, TdbankAccountParams, } from './generated-browser-action-protocol.js'; | ||
| 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'; | ||
| export type { ActionStep, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserReleaseFailure, BrowserReleaseResult, BrowserStatus, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, ManagedBrowserAccount, ManagedBrowserInfo, PageClickParams, PageActAction, 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'; | ||
| import type * as Protocol from './generated-browser-action-protocol.js'; | ||
@@ -13,0 +13,0 @@ export declare function getRequests(params?: Protocol.GetRequestsParams): Promise<Protocol.BrowserActionResponse<'get_requests'>>; |
+1
-1
@@ -8,3 +8,3 @@ /** | ||
| export { invoke } from './socket.js'; | ||
| export { BROWSER_ACTIONS, BROWSER_COMMAND_ACTIONS, EXTENSION_BROWSER_ACTIONS, PAGE_ACT_ACTIONS, isBrowserAction, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js'; | ||
| 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'; | ||
| import { invoke } from './socket.js'; | ||
@@ -11,0 +11,0 @@ export function getRequests(params = {}) { |
+1
-1
| { | ||
| "name": "@mearl/client", | ||
| "version": "2.2.0", | ||
| "version": "2.2.1", | ||
| "description": "Client SDK & CLI for Mearl — communicate with Chrome Extension via Unix Socket", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+4
-1
@@ -43,2 +43,5 @@ # @mearl/client | ||
| # 以 multipart/form-data 上传本地文件 | ||
| mearl send_request --payload '{"url":"https://api.example.com/upload","method":"POST","formData":{"folder":"assets"},"files":[{"fieldName":"file","filePath":"/absolute/path/image.png"}]}' | ||
| # 截图并保存 | ||
@@ -92,3 +95,3 @@ mearl page_screenshot --output ./screenshot.png | ||
| 页面交互动作(`page_click` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认内置观察:同一次调用内执行动作并等待异步稳定,返回 `{ action, observation }`;传 `observe: false` 可关闭观察仅执行裸动作。观察结果不替代完整页面理解:`mode: "delta"` 只返回主文档中的 `effects.notifications`、`effects.interactives` 和 `effects.focus` 等高置信度信号,并明确携带 `scope: "main-document"`;可交互节点会尽量携带真实 backend `node.ref`,后续动作优先使用 ref,缺少 ref 时使用 `node.selector`。`mode: "navigation"` 且 `ready: true` 时,页面已通过网络静默、骨架状态或保守的内容稳定判定,可在新页面重建快照。通常仅在 `fullSnapshotRecommended` 为 true 时根据 `snapshotReasons` 回退;滚动后若下一步需要读取新视口内容,可按需获取 viewport 快照。`page_eval` 默认裸执行,只有显式传入 `observe` 对象时才启用观察。 | ||
| 页面交互动作(`page_click` / `page_type` / `page_hover` / `page_scroll` / `page_press` / `page_upload`)默认内置观察:同一次调用内执行动作并等待异步稳定,返回 `{ action, observation }`;传 `observe: false` 可关闭观察仅执行裸动作。观察结果不替代完整页面理解:`mode: "delta"` 只返回主文档中的 `effects.notifications`、`effects.interactives` 和 `effects.focus` 等高置信度信号,并明确携带 `scope: "main-document"`;可交互节点会尽量携带真实 backend `node.ref`,后续动作优先使用 ref,缺少 ref 时使用 `node.selector`。`mode: "navigation"` 且 `ready: true` 时,页面已通过网络静默、骨架状态或保守的内容稳定判定,可在新页面重建快照。动作直接打开新标签页时,`observation.openedTabs` 返回新标签页的 `tabId`、URL、标题和加载状态,可直接把该 `tabId` 用于后续操作,不必调用 `tab_list`。通常仅在 `fullSnapshotRecommended` 为 true 时根据 `snapshotReasons` 回退;滚动后若下一步需要读取新视口内容,可按需获取 viewport 快照。`page_eval` 默认裸执行,只有显式传入 `observe` 对象时才启用观察。 | ||
@@ -95,0 +98,0 @@ `page_snapshot` 默认返回完整 AX Tree;长列表可传 `mode: "viewport"`,只需要当前视口内的控件时传 `mode: "interactive"`,已知 CSS 区域时传 `rootSelector`,已有 ref 时传 `rootRef`(可用 `ancestorDepth` 向上补充上下文),只查找特定文案或角色时传 `query`。视口内缺少 AX 控件语义时,`interactive` 会自动回退到 viewport,并返回 `fallbackMode: "viewport"`。`maxNodes` / `maxChars` 截断会同时保留首尾内容。 |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
172486
2.6%3909
1.85%129
2.38%12
-7.69%