@mearl/client 2.13.0 → 2.14.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.
@@ -8,7 +8,7 @@
8
8
  * registry directory and record shape; reading scans every *.json in the dir,
9
9
  * so it never needs to replicate daemon-core's filename hashing.
10
10
  */
11
- import type { BrowserCapabilities, BrowserPairingInfo, BrowserTransport } from './generated-browser-action-protocol.js';
11
+ import type { BrowserCapabilities, BrowserDetails, BrowserPairingInfo, BrowserProviderIdentity, BrowserProviderOperation, BrowserReference, BrowserTransport } from './generated-browser-action-protocol.js';
12
12
  export interface LiveBrowser {
13
13
  pid: number;
14
14
  browserId: string;
@@ -18,13 +18,15 @@ export interface LiveBrowser {
18
18
  nativeHostVersion?: string;
19
19
  transport?: BrowserTransport;
20
20
  providerBrowserId?: string;
21
- providerId?: string;
22
- providerName?: string;
23
- providerVersion?: string;
24
- providerProtocolVersion?: number;
21
+ provider?: BrowserProviderIdentity;
25
22
  capabilities?: BrowserCapabilities;
26
- status?: 'connected' | 'pairing';
23
+ status?: 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
24
+ ownership?: 'owned' | 'attached';
25
+ persistence?: 'ephemeral' | 'persistent';
26
+ operations?: BrowserProviderOperation[];
27
27
  pairing?: BrowserPairingInfo;
28
+ references?: BrowserReference[];
29
+ details?: BrowserDetails;
28
30
  lastFocusedAt?: number;
29
31
  updatedAt?: number;
30
32
  }
package/dist/check.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CloudConnectorInfo } from '@mearl/cloud-types';
2
- import type { BrowserCapabilities } from './generated-browser-action-protocol.js';
2
+ import type { BrowserCapabilities, BrowserProviderIdentity, BrowserProviderOperation } from './generated-browser-action-protocol.js';
3
3
  import { type UnifiedClientOptions, type UnifiedInvokeOptions } from './unified.js';
4
4
  export interface UnifiedCheckVersions {
5
5
  nativeHost?: string;
@@ -8,8 +8,9 @@ export interface UnifiedCheckVersions {
8
8
  provider?: ProviderVersionInfo;
9
9
  }
10
10
  export interface ProviderVersionInfo {
11
- providerId: string;
11
+ id: string;
12
12
  name: string;
13
+ builtin: boolean;
13
14
  version: string;
14
15
  protocolVersion: number;
15
16
  }
@@ -19,6 +20,8 @@ export type BrowserAccessCapability = {
19
20
  kind: 'sandbox-novnc';
20
21
  environment: 'opensandbox' | 'aone';
21
22
  port: number;
23
+ } | {
24
+ kind: string;
22
25
  };
23
26
  export type BrowserAccess = BrowserAccessCapability & {
24
27
  url: string;
@@ -32,11 +35,10 @@ interface BrowserInfo {
32
35
  originalName?: string;
33
36
  status: string;
34
37
  type?: string;
35
- provider?: 'local' | 'agentbay';
36
- providerId?: string;
37
- providerName?: string;
38
- providerVersion?: string;
39
- providerProtocolVersion?: number;
38
+ provider?: BrowserProviderIdentity;
39
+ ownership?: 'owned' | 'attached';
40
+ persistence?: 'ephemeral' | 'persistent';
41
+ operations?: BrowserProviderOperation[];
40
42
  transport?: 'extension' | 'cdp' | 'provider';
41
43
  }
42
44
  interface CheckItem {
package/dist/check.js CHANGED
@@ -5,13 +5,16 @@ function formatError(error) {
5
5
  function browserAccessLabel(access) {
6
6
  if (access.kind === 'agentbay')
7
7
  return 'AgentBay, temporary';
8
- return access.environment === 'opensandbox' ? 'OpenSandbox noVNC' : 'AONE Sandbox noVNC';
8
+ if (access.kind === 'sandbox-novnc' && 'environment' in access) {
9
+ return access.environment === 'opensandbox' ? 'OpenSandbox noVNC' : 'AONE Sandbox noVNC';
10
+ }
11
+ return access.kind;
9
12
  }
10
13
  async function getBrowserAccess(client, browser, capability, timeoutSec) {
11
14
  const result = (await client.invoke('get_browser_access_url', {}, { timeoutSec, browser: browser.browserId }));
12
15
  if (!result.browserAccess?.url)
13
16
  throw new Error('Browser host did not return an access URL');
14
- if (result.browserAccess.kind !== capability.kind) {
17
+ if (capability && result.browserAccess.kind !== capability.kind) {
15
18
  throw new Error('Browser host returned an unexpected access URL type');
16
19
  }
17
20
  return result.browserAccess;
@@ -57,7 +60,7 @@ function formatBrowser(browser, isDefault) {
57
60
  : browser.transport === 'extension'
58
61
  ? ' [Extension]'
59
62
  : browser.transport === 'provider'
60
- ? ` [Provider: ${browser.providerName || browser.providerId || 'external'}]`
63
+ ? ` [Provider: ${browser.provider?.name || browser.provider?.id || 'external'}]`
61
64
  : '';
62
65
  const type = browser.type === 'managed' ? ' [Managed]' : '';
63
66
  return ` ${isDefault ? '★' : ' '} ${browser.name} [${shortBrowserId(browser.browserId)}]${type}${transport}`;
@@ -250,9 +253,10 @@ export async function runUnifiedCheck(options, dependencies = {}) {
250
253
  let browserAccess;
251
254
  let accessUrlWarning;
252
255
  const browserAccessCapability = versions.browserAccess;
253
- if (browserAccessCapability && options.browser) {
256
+ const providerAccess = browser.operations?.includes('access') === true;
257
+ if ((providerAccess || browserAccessCapability) && options.browser) {
254
258
  try {
255
- browserAccess = await getBrowserAccess(client, browser, browserAccessCapability, timeoutSec);
259
+ browserAccess = await getBrowserAccess(client, browser, providerAccess ? undefined : browserAccessCapability, timeoutSec);
256
260
  details.push(`Browser access URL (${browserAccessLabel(browserAccess)}; sensitive): ${browserAccess.url}`);
257
261
  }
258
262
  catch (error) {
@@ -402,8 +402,8 @@ export declare const COMMANDS: readonly [{
402
402
  readonly description: "运行环境,默认 local;可传 agentbay 或 mearl --help 中展示的已注册 Provider ID";
403
403
  }, {
404
404
  readonly name: "providerOptions";
405
- readonly type: "Record<string, string>";
406
- readonly description: "外部 Provider 注册时声明的实例创建参数";
405
+ readonly type: "Record<string, JSON value>";
406
+ readonly description: "所选 Provider 声明的结构化启动参数;不能与顶层启动字段混用";
407
407
  }, {
408
408
  readonly name: "sessionId";
409
409
  readonly type: "string";
package/dist/commands.js CHANGED
@@ -310,8 +310,8 @@ export const COMMANDS = [
310
310
  },
311
311
  {
312
312
  name: 'providerOptions',
313
- type: 'Record<string, string>',
314
- description: '外部 Provider 注册时声明的实例创建参数',
313
+ type: 'Record<string, JSON value>',
314
+ description: '所选 Provider 声明的结构化启动参数;不能与顶层启动字段混用',
315
315
  },
316
316
  {
317
317
  name: 'sessionId',
@@ -137,6 +137,38 @@ export interface BrowserSource {
137
137
  connectorId?: string;
138
138
  connectorName?: string;
139
139
  }
140
+ export type BrowserJsonPrimitive = string | number | boolean | null;
141
+ export type BrowserJsonValue = BrowserJsonPrimitive | BrowserJsonValue[] | {
142
+ [key: string]: BrowserJsonValue;
143
+ };
144
+ export type BrowserProviderOperation = 'start' | 'close' | 'detach' | 'deleteData' | 'access' | 'syncCookies';
145
+ export interface BrowserProviderIdentity {
146
+ id: string;
147
+ name: string;
148
+ builtin: boolean;
149
+ version?: string;
150
+ protocolVersion?: number;
151
+ }
152
+ /** Common safe metadata; additional Provider-specific keys must also be non-secret JSON. */
153
+ export type BrowserDetails = Record<string, BrowserJsonValue> & {
154
+ headless?: boolean;
155
+ createdAt?: string;
156
+ cdpPort?: number;
157
+ account?: {
158
+ nickname: string;
159
+ accountId?: string;
160
+ loginId?: string;
161
+ };
162
+ copiedCookies?: {
163
+ domains: string[];
164
+ count: number;
165
+ };
166
+ };
167
+ export interface BrowserReference {
168
+ kind: string;
169
+ id: string;
170
+ label?: string;
171
+ }
140
172
  export interface BrowserInfoBase {
141
173
  browserId: string;
142
174
  name: string;
@@ -148,12 +180,14 @@ export interface BrowserInfoBase {
148
180
  extensionVersion?: string;
149
181
  nativeHostVersion?: string;
150
182
  transport?: BrowserTransport;
151
- /** External control-provider identity. Present only when transport is provider. */
152
- providerId?: string;
153
- /** Human-readable Provider name; providerId remains the stable identity. */
154
- providerName?: string;
155
- providerVersion?: string;
156
- providerProtocolVersion?: number;
183
+ /** Provider identity, independent from the browser control transport. */
184
+ provider?: BrowserProviderIdentity;
185
+ ownership?: 'owned' | 'attached';
186
+ persistence?: 'ephemeral' | 'persistent';
187
+ operations?: BrowserProviderOperation[];
188
+ references?: BrowserReference[];
189
+ /** Safe, non-secret metadata suitable for display and remote connectors. */
190
+ details?: BrowserDetails;
157
191
  /** Setup information exposed by a provider while it waits for an external device. */
158
192
  pairing?: BrowserPairingInfo;
159
193
  }
@@ -170,33 +204,12 @@ export interface RegularBrowserInfo extends BrowserInfoBase {
170
204
  type: 'regular';
171
205
  status: 'connected' | 'pairing';
172
206
  }
173
- export interface ManagedBrowserAccount {
174
- accountId?: string;
175
- loginId?: string;
176
- nickname: string;
177
- }
178
207
  export interface ManagedBrowserInfo extends BrowserInfoBase {
179
208
  type: 'managed';
180
- status: 'connected' | 'running_disconnected' | 'stopped';
181
- provider?: 'local' | 'agentbay';
182
- headless: boolean;
183
- persistent: boolean;
184
- cdpPort?: number;
185
- agentbaySessionId?: string;
186
- /** Whether this host owns the AgentBay session lifecycle or only attaches to it. */
187
- agentbaySessionMode?: 'owned' | 'attached';
188
- /** AgentBay image used to create the session. */
189
- agentbayImageId?: string;
190
- /** Persistent AgentBay browser context ID when enabled for this instance. */
191
- agentbayContextId?: string;
192
- /** Stable AgentBay browser context name derived from the managed browser name. */
193
- agentbayContextName?: string;
194
- createdAt: string;
195
- account?: ManagedBrowserAccount;
196
- copiedCookies?: {
197
- domains: string[];
198
- count: number;
199
- };
209
+ status: 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
210
+ provider: BrowserProviderIdentity;
211
+ persistence: 'ephemeral' | 'persistent';
212
+ operations: BrowserProviderOperation[];
200
213
  }
201
214
  export type BrowserInfo = RegularBrowserInfo | ManagedBrowserInfo;
202
215
  export interface BrowserListResult {
@@ -245,8 +258,8 @@ export interface BrowserLaunchParams {
245
258
  name?: string;
246
259
  /** Built-in runtime or the id of a registered external Provider. */
247
260
  provider?: string;
248
- /** Creation parameters declared by a registered external Provider. */
249
- providerOptions?: Record<string, string>;
261
+ /** Structured launch parameters declared by the selected Provider. Cannot be mixed with flat options. */
262
+ providerOptions?: Record<string, BrowserJsonValue>;
250
263
  /** Attach to an exact live AgentBay session without creating or owning it. */
251
264
  sessionId?: string;
252
265
  /** AgentBay running-session reuse policy. Defaults to never. */
@@ -272,6 +285,61 @@ export interface BrowserCloseParams {
272
285
  browser: string;
273
286
  deleteProfile?: boolean;
274
287
  }
288
+ interface BrowserProviderSchemaBase {
289
+ title?: string;
290
+ description?: string;
291
+ default?: BrowserJsonValue;
292
+ }
293
+ export type BrowserProviderInputSchema = (BrowserProviderSchemaBase & {
294
+ type: 'string';
295
+ secret?: boolean;
296
+ enum?: readonly string[];
297
+ minLength?: number;
298
+ maxLength?: number;
299
+ pattern?: string;
300
+ placeholder?: string;
301
+ }) | (BrowserProviderSchemaBase & {
302
+ type: 'number';
303
+ integer?: boolean;
304
+ minimum?: number;
305
+ maximum?: number;
306
+ }) | (BrowserProviderSchemaBase & {
307
+ type: 'boolean';
308
+ }) | (BrowserProviderSchemaBase & {
309
+ type: 'array';
310
+ items: BrowserProviderInputSchema;
311
+ minItems?: number;
312
+ maxItems?: number;
313
+ }) | BrowserProviderObjectSchema;
314
+ export interface BrowserProviderObjectSchema extends BrowserProviderSchemaBase {
315
+ type: 'object';
316
+ properties: Record<string, BrowserProviderInputSchema>;
317
+ required?: readonly string[];
318
+ oneOf?: readonly BrowserProviderObjectSchema[];
319
+ not?: BrowserProviderObjectSchema;
320
+ additionalProperties?: boolean;
321
+ }
322
+ export interface BrowserProviderDefinition {
323
+ provider: BrowserProviderIdentity;
324
+ browserType: {
325
+ name: string;
326
+ documentationUrl?: string;
327
+ inputSchema: BrowserProviderObjectSchema;
328
+ configuration?: {
329
+ inputSchema: BrowserProviderObjectSchema;
330
+ };
331
+ };
332
+ }
333
+ export interface BrowserProviderListResult {
334
+ providers: BrowserProviderDefinition[];
335
+ }
336
+ export interface BrowserAccessResult {
337
+ browserAccess: {
338
+ kind: string;
339
+ url: string;
340
+ sensitive: true;
341
+ };
342
+ }
275
343
  export interface SetRuleParams {
276
344
  actionType: 'redirect' | 'block' | 'allow' | 'upgradeScheme' | 'modifyHeaders';
277
345
  filter: string;
@@ -647,7 +715,7 @@ export interface BrowserActionMap {
647
715
  };
648
716
  browser_launch: {
649
717
  request: BrowserLaunchParams;
650
- response: unknown;
718
+ response: ManagedBrowserInfo;
651
719
  };
652
720
  browser_close: {
653
721
  request: BrowserCloseParams;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@
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
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, isBrowserCapabilityAction, isBrowserCommandAction, isExtensionBrowserAction, } from './generated-browser-action-protocol.js';
10
- export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserLaunchParams, BrowserListResult, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, 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';
10
+ export type { ActionStep, AppProfileName, BrowserAction, BrowserActionMap, BrowserActionRequest, BrowserActionResponse, BrowserCapabilities, BrowserCapabilityAction, BrowserCloseParams, BrowserCommandAction, BrowserInfo, BrowserInfoBase, BrowserJsonValue, BrowserLaunchParams, BrowserProviderOperation, BrowserListResult, BrowserPairingInfo, BrowserReleaseFailure, BrowserReleaseResult, BrowserProviderDefinition, BrowserProviderIdentity, BrowserProviderInputSchema, BrowserProviderListResult, BrowserReference, BrowserDetails, BrowserSource, BrowserStatus, BrowserScreenshotKind, BrowserTransport, CaptureCheckpointParams, CaptureCheckpointResult, BrowserDevicePresetName, BrowserEmulationOptions, ExtensionBrowserAction, GetApiSchemaParams, GetCookieParams, GetCookieResult, GetEventsParams, GetLogsParams, GetMocksParams, GetRequestsParams, GetUserInfoParams, 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';
13
13
  export declare function tabCheckpoint(params?: Protocol.CaptureCheckpointParams, options?: UnifiedInvokeOptions): Promise<Protocol.BrowserActionResponse<'tab_checkpoint'>>;
package/dist/socket.js CHANGED
@@ -77,14 +77,16 @@ function browserListFromProviderRecords(browsers) {
77
77
  .map(browser => ({
78
78
  browserId: browser.browserId,
79
79
  name: browser.browserName,
80
- type: 'regular',
81
- status: browser.status === 'pairing' ? 'pairing' : 'connected',
80
+ type: 'managed',
81
+ status: browser.status ?? 'running_disconnected',
82
82
  transport: 'provider',
83
- providerId: browser.providerId,
84
- providerName: browser.providerName,
85
- providerVersion: browser.providerVersion,
86
- providerProtocolVersion: browser.providerProtocolVersion,
83
+ provider: browser.provider,
84
+ ownership: browser.ownership,
85
+ persistence: browser.persistence,
86
+ operations: browser.operations,
87
87
  pairing: browser.pairing,
88
+ references: browser.references,
89
+ details: browser.details,
88
90
  }));
89
91
  return {
90
92
  count: providerBrowsers.length,
@@ -99,11 +101,23 @@ function mergeWarnings(result, warnings) {
99
101
  const merged = [...new Set([...resultWarnings, ...warnings])];
100
102
  return { ...result, ...(merged.length > 0 ? { warnings: merged } : {}) };
101
103
  }
102
- function supportsAction(browser, action) {
103
- if (browser.transport === 'provider' &&
104
- (action === 'get_versions' || action === 'browser_close')) {
104
+ function isConnectedBrowser(browser) {
105
+ return browser.status === undefined || browser.status === 'connected';
106
+ }
107
+ function supportsAction(browser, action, data) {
108
+ if (action === 'get_versions')
105
109
  return true;
110
+ if (action === 'get_browser_access_url') {
111
+ return browser.transport !== 'provider' || browser.operations?.includes('access') === true;
112
+ }
113
+ if (action === 'browser_close') {
114
+ if (browser.transport !== 'provider')
115
+ return true;
116
+ const required = data.deleteProfile === true ? 'deleteData' : 'close';
117
+ return browser.operations?.includes(required) === true;
106
118
  }
119
+ if (!isConnectedBrowser(browser))
120
+ return false;
107
121
  return (browser.transport !== 'provider' ||
108
122
  browser.capabilities?.actions.some(capability => capability === action) === true);
109
123
  }
@@ -117,7 +131,7 @@ function selectBrowserResult(data) {
117
131
  };
118
132
  }
119
133
  const browsers = listLiveBrowsers();
120
- const controllableBrowsers = browsers.filter(browser => browser.status !== 'pairing');
134
+ const controllableBrowsers = browsers.filter(isConnectedBrowser);
121
135
  const match = findBrowser(controllableBrowsers, selector);
122
136
  if (!match)
123
137
  throw new Error(formatNoMatchError(selector, browsers));
@@ -218,20 +232,20 @@ async function dispatchInvoke(action, data, timeoutSec, transport, selector, con
218
232
  }
219
233
  }
220
234
  const browsers = listLiveBrowsers();
221
- const controllableBrowsers = browsers.filter(browser => browser.status !== 'pairing');
235
+ const controllableBrowsers = browsers.filter(isConnectedBrowser);
222
236
  // Explicit target: must match a live browser; do not silently fall back.
223
237
  if (selector) {
224
238
  const match = findBrowser(browsers, selector);
225
239
  if (!match) {
226
240
  throw new Error(formatNoMatchError(selector, browsers));
227
241
  }
228
- if (match.status === 'pairing' && action !== 'get_versions' && action !== 'browser_close') {
229
- throw new Error(`Browser ${describeBrowser(match)} is waiting for device pairing`);
230
- }
231
242
  if (transport === 'cdp' && match.transport === 'provider') {
232
243
  throw new Error(`Browser ${describeBrowser(match)} does not support the CDP transport`);
233
244
  }
234
- if (!supportsAction(match, action)) {
245
+ if (match.status === 'pairing' && action !== 'get_versions' && action !== 'browser_close') {
246
+ throw new Error(`Browser ${describeBrowser(match)} is waiting for device pairing`);
247
+ }
248
+ if (!supportsAction(match, action, data)) {
235
249
  throw new Error(`Browser ${describeBrowser(match)} does not support ${action}`);
236
250
  }
237
251
  try {
@@ -248,7 +262,8 @@ async function dispatchInvoke(action, data, timeoutSec, transport, selector, con
248
262
  }
249
263
  // No explicit target: prefer the most-recently-focused live browser; on a
250
264
  // stale socket, fall through to the legacy path + auto-spawn.
251
- const routableBrowsers = controllableBrowsers.filter(browser => !(transport === 'cdp' && browser.transport === 'provider') && supportsAction(browser, action));
265
+ const routableBrowsers = controllableBrowsers.filter(browser => !(transport === 'cdp' && browser.transport === 'provider') &&
266
+ supportsAction(browser, action, data));
252
267
  if (routableBrowsers.length > 0) {
253
268
  const target = routableBrowsers[0];
254
269
  try {
@@ -288,9 +303,9 @@ async function invokeViaLegacy(action, data, timeoutSec, transport, controlSourc
288
303
  /* isRetry */ true);
289
304
  }
290
305
  const browsers = listLiveBrowsers();
291
- const target = browsers.find(browser => browser.status !== 'pairing' &&
306
+ const target = browsers.find(browser => isConnectedBrowser(browser) &&
292
307
  !(transport === 'cdp' && browser.transport === 'provider') &&
293
- supportsAction(browser, action));
308
+ supportsAction(browser, action, data));
294
309
  if (target) {
295
310
  return invokeOnce(action, data, timeoutSec, transport, target.socketPath, controlSource, target.providerBrowserId);
296
311
  }
package/dist/unified.js CHANGED
@@ -420,17 +420,7 @@ export class UnifiedClient {
420
420
  decorateActionResult(action, result, source) {
421
421
  if (action !== 'browser_launch' || typeof result?.browserId !== 'string')
422
422
  return result;
423
- const safeResult = omitTransientBrowserSecrets(result);
424
- const originalBrowserId = result.browserId;
425
- return {
426
- ...safeResult,
427
- browserId: encodeBrowserTarget({
428
- browser: originalBrowserId,
429
- ...(source.connectorId ? { connector: source.connectorId } : {}),
430
- }),
431
- originalBrowserId,
432
- source,
433
- };
423
+ return decorateBrowser(result, source);
434
424
  }
435
425
  async ensureConnected() {
436
426
  if (this.ws?.readyState === WebSocket.OPEN)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/client",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "Unified Mearl SDK & CLI for local and remote browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -59,8 +59,8 @@
59
59
  "commander": "^15.0.0",
60
60
  "fastest-levenshtein": "^1.0.16",
61
61
  "ws": "^8.18.0",
62
- "@mearl/cloud-types": "2.13.0",
63
- "@mearl/provider": "2.13.0"
62
+ "@mearl/cloud-types": "2.14.0",
63
+ "@mearl/provider": "2.14.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/node": "^24.9.1",