@mearl/browser-core 3.0.0-beta.0 → 3.0.0-beta.10

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.
Files changed (56) hide show
  1. package/README.md +7 -5
  2. package/README.zh-CN.md +13 -0
  3. package/dist/agentChat.d.ts +10 -1
  4. package/dist/agentChat.js +8 -0
  5. package/dist/agentServiceProtocol.d.ts +23 -0
  6. package/dist/agentServiceProtocol.js +3 -0
  7. package/dist/agentSkills.d.ts +1 -1
  8. package/dist/app-profile-runtime/types.d.ts +10 -12
  9. package/dist/appProfileDefinition.d.ts +32 -14
  10. package/dist/appProfileDefinition.js +63 -69
  11. package/dist/axSnapshot.js +1 -1
  12. package/dist/boundedRequestBuffer.d.ts +4 -4
  13. package/dist/browserActionProtocol.d.ts +55 -45
  14. package/dist/browserActionProtocol.js +12 -15
  15. package/dist/browserCapabilities.d.ts +47 -0
  16. package/dist/browserCapabilities.js +63 -0
  17. package/dist/browserDiscovery.d.ts +3 -0
  18. package/dist/browserDiscovery.js +20 -0
  19. package/dist/browserEnhancement.d.ts +161 -0
  20. package/dist/browserEnhancement.js +80 -0
  21. package/dist/cookie.d.ts +6 -0
  22. package/dist/cookie.js +20 -5
  23. package/dist/dataStructure.d.ts +8 -0
  24. package/dist/dataStructure.js +58 -0
  25. package/dist/deviceEmulation.d.ts +6 -0
  26. package/dist/deviceEmulation.js +13 -0
  27. package/dist/deviceEnvironmentObservation.d.ts +48 -0
  28. package/dist/deviceEnvironmentObservation.js +77 -0
  29. package/dist/domClicking.d.ts +14 -0
  30. package/dist/domClicking.js +98 -10
  31. package/dist/domInspection.js +13 -1
  32. package/dist/extensionServiceProtocol.d.ts +7 -0
  33. package/dist/extensionServiceProtocol.js +8 -0
  34. package/dist/index.d.ts +9 -0
  35. package/dist/index.js +9 -0
  36. package/dist/nativeHostNames.d.ts +6 -0
  37. package/dist/nativeHostNames.js +5 -0
  38. package/dist/pageAct.d.ts +2 -0
  39. package/dist/pageAct.js +42 -10
  40. package/dist/pageDialog.d.ts +66 -0
  41. package/dist/pageDialog.js +175 -0
  42. package/dist/pageObserver.js +16 -5
  43. package/dist/pagePressing.d.ts +1 -1
  44. package/dist/pluginPageHost.js +2 -2
  45. package/dist/providerAppResources.d.ts +39 -0
  46. package/dist/providerAppResources.js +2 -0
  47. package/dist/proxyPermissions.js +3 -3
  48. package/dist/requestMetadata.d.ts +9 -0
  49. package/dist/requestMetadata.js +8 -0
  50. package/dist/requestSerializer.d.ts +2 -2
  51. package/dist/requestSerializer.js +1 -29
  52. package/dist/requestStreamCapture.d.ts +5 -3
  53. package/dist/requestStreamCapture.js +2 -0
  54. package/dist/runActions.js +1 -1
  55. package/dist/types.d.ts +4 -2
  56. package/package.json +6 -1
@@ -1,3 +1,8 @@
1
+ import type { BrowserCapabilityCatalog } from './browserCapabilities.js';
2
+ export interface GetCapabilitiesParams {
3
+ /** Include method and setting details for this installed App ID. */
4
+ app?: string;
5
+ }
1
6
  export interface GetRequestsParams {
2
7
  tabId: number;
3
8
  count?: number;
@@ -13,7 +18,7 @@ export interface GetRequestsParams {
13
18
  fields?: string[];
14
19
  keysOnly?: boolean;
15
20
  applyHiddenFilter?: boolean;
16
- source?: 'mtop' | 'requests' | 'all';
21
+ source?: 'protocol' | 'requests' | 'all';
17
22
  }
18
23
  export interface GetLogsParams {
19
24
  tabId: number;
@@ -107,18 +112,9 @@ export interface SendRequestParams {
107
112
  responseType?: 'json' | 'text' | 'auto';
108
113
  timeout?: number;
109
114
  }
110
- export type MtopEnvironmentTarget = 'prod' | 'pre';
111
- export type MtopEnvironment = 'default' | MtopEnvironmentTarget;
112
- export interface SendMtopRequestParams {
113
- api: string;
114
- data?: unknown;
115
- version?: string;
116
- method?: string;
117
- appKey?: string;
118
- env?: MtopEnvironmentTarget;
119
- timeout?: number;
120
- headers?: Record<string, string>;
121
- ttid?: string;
115
+ export interface NetworkControlSelection {
116
+ id: string;
117
+ value: string;
122
118
  }
123
119
  export type BrowserStatus = 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
124
120
  export type BrowserTransport = 'extension' | 'cdp' | 'provider';
@@ -184,6 +180,7 @@ export interface BrowserInfoBase {
184
180
  pairing?: BrowserPairingInfo;
185
181
  }
186
182
  export type BrowserScreenshotKind = 'native' | 'reconstructed' | 'none';
183
+ export type BrowserControlSessionMode = 'mearl' | 'external';
187
184
  /** Browser-targeted actions that an external provider may implement. */
188
185
  export type BrowserCapabilityAction = ExtensionBrowserAction | 'page_download';
189
186
  /** Capabilities advertised by an external browser-control provider. */
@@ -191,6 +188,8 @@ export interface BrowserCapabilities {
191
188
  actions: BrowserCapabilityAction[];
192
189
  /** Pixel fidelity of page_screenshot, or none when that action is unavailable. */
193
190
  screenshot: BrowserScreenshotKind;
191
+ /** Fixed per instance. Omitted means Mearl sessions; external delegates task control. */
192
+ controlSessionMode?: BrowserControlSessionMode;
194
193
  }
195
194
  export interface RegularBrowserInfo extends BrowserInfoBase {
196
195
  type: 'regular';
@@ -204,6 +203,13 @@ export interface ManagedBrowserInfo extends BrowserInfoBase {
204
203
  operations: BrowserProviderOperation[];
205
204
  }
206
205
  export type BrowserInfo = RegularBrowserInfo | ManagedBrowserInfo;
206
+ export interface BrowserListParams {
207
+ provider: string;
208
+ launchForm: {
209
+ variant?: string;
210
+ values: Record<string, BrowserJsonValue>;
211
+ };
212
+ }
207
213
  export interface BrowserListResult {
208
214
  count: number;
209
215
  connectedCount: number;
@@ -211,6 +217,11 @@ export interface BrowserListResult {
211
217
  browsers: BrowserInfo[];
212
218
  /** Partial discovery failures; successfully inspected browser sources remain in the result. */
213
219
  warnings?: string[];
220
+ /** Present only for an explicit, source-local Provider launch-form query. */
221
+ discovery?: {
222
+ provider: string;
223
+ launchForm: BrowserProviderLaunchForm;
224
+ };
214
225
  }
215
226
  export interface SelectBrowserParams {
216
227
  browser?: string;
@@ -366,6 +377,7 @@ export interface BrowserProviderDefinition {
366
377
  provider: BrowserProviderIdentity;
367
378
  browserType: {
368
379
  name: string;
380
+ controlSessionModes?: readonly BrowserControlSessionMode[];
369
381
  documentationUrl?: string;
370
382
  inputSchema: BrowserProviderObjectSchema;
371
383
  configuration?: {
@@ -457,7 +469,8 @@ export interface BrowserEmulationOptions {
457
469
  /** App 容器横屏时将根页面与业务页面分置左右 WebView;仅与 deviceShell、App 档案同时生效。 */
458
470
  splitScreen?: boolean;
459
471
  }
460
- export type AppBridgeConfigBehavior = 'navigate' | 'closeAll' | 'closeBackData' | 'postMessage' | 'notifySubscribe' | 'notifyUnsubscribe' | 'notifyPost' | 'sharedFileRead' | 'sharedFileWrite' | 'sharedDataGet' | 'sharedDataSet' | 'legacyBroadcastCreate' | 'legacyBroadcastPost' | 'legacyBroadcastClose' | 'memoryGet' | 'memorySet' | 'memoryDelete' | 'availabilityMap' | 'userInfo' | 'authCode' | 'networkInfo' | 'geolocation' | 'permission' | 'imagePicker' | 'prefetch' | 'fptTrack' | 'mtopStream' | 'previewFile' | 'toast' | 'unsupportedNativeInput' | 'payment' | 'userTrack' | 'calendar' | 'networkQualityMonitor' | 'beaconRequest' | 'voiceRecognition';
472
+ /** Provider-defined behavior ID; core does not execute or enumerate business behaviors. */
473
+ export type AppBridgeConfigBehavior = string;
461
474
  /** 单个桥方法的声明式覆盖;行为、固定回包、成功空实现三选一。 */
462
475
  export interface AppBridgeMethodConfig {
463
476
  behavior?: AppBridgeConfigBehavior;
@@ -486,8 +499,8 @@ export interface TabOpenParams {
486
499
  emulation?: BrowserEmulationOptions;
487
500
  group?: string;
488
501
  /**
489
- * 客户端容器模拟档案名(如 'fliggy')。只注入容器 UA、环境变量、JSBridge 与桥协议;
490
- * 设备视口和 iframe 系统外壳由 emulation.deviceShell 独立控制。可用档案见 APP_PROFILE_NAMES。
502
+ * 客户端容器模拟档案名(由已安装能力目录提供)。只注入容器 UA、环境变量、JSBridge 与桥协议;
503
+ * 设备视口和 iframe 系统外壳由 emulation.deviceShell 独立控制。可用档案通过 get_capabilities 查询。
491
504
  */
492
505
  appProfile?: AppProfileName;
493
506
  /** 与 appProfile 配合使用;容器系统,默认 ios */
@@ -504,16 +517,9 @@ export type TabGroupParams = {
504
517
  ungroup: true;
505
518
  title?: never;
506
519
  };
507
- /**
508
- * 客户端容器模拟可用档案名。
509
- *
510
- * 档案数据(UA / 桥对象 / 方法映射)在 @mearl/app-profiles 维护,但名单属于协议:
511
- * 它是 set_app_profile.profile 与 tab_open.appProfile 的取值域,CLI 帮助与 MCP 工具
512
- * schema 的 enum 也由它生成。app-profiles 反向引用本清单约束自己的档案表,
513
- * 因此新增档案时只需改两处(名单 + 档案数据),且漏改会在类型检查时暴露。
514
- */
515
- export declare const APP_PROFILE_NAMES: readonly ["fliggy", "taobao", "wechat", "alipay"];
516
- export type BuiltinAppProfileName = (typeof APP_PROFILE_NAMES)[number];
520
+ /** App identities are supplied by installed capability catalogs. */
521
+ export declare const APP_PROFILE_NAMES: readonly string[];
522
+ export type BuiltinAppProfileName = string;
517
523
  /** Hosts validate dynamic profile IDs against the active capability catalog. */
518
524
  export type AppProfileName = string;
519
525
  export interface SetAppProfileParams {
@@ -534,10 +540,10 @@ export interface SetAppProfileParams {
534
540
  /** 按方法覆盖档案内置桥配置,仅支持受控行为、固定 JSON 回包和成功空实现 */
535
541
  bridgeConfig?: AppBridgeConfig;
536
542
  /**
537
- * 可选 MTop 接口环境。default 关闭环境改写;省略时保持当前设置。
543
+ * 可选已安装的网络控件选择;null 清除,省略时保持当前设置。
538
544
  * 仅作用于目标 tab,扩展模式与该 tab 的快捷设置共享。
539
545
  */
540
- mtopEnv?: MtopEnvironment;
546
+ networkControl?: NetworkControlSelection | null;
541
547
  /**
542
548
  * 可选设备联动参数。传入时显式字段覆盖档案推荐设备,空对象使用推荐设备且默认开启
543
549
  * deviceShell;省略时不设置或清除该 tab 的设备状态。
@@ -672,6 +678,10 @@ export interface PageInspectParams {
672
678
  export interface PagePressParams {
673
679
  tabId: number;
674
680
  key: string;
681
+ /** Explicit native JavaScript dialog target obtained from a receipt or page_snapshot. */
682
+ dialogId?: string;
683
+ /** Only for accepting a native prompt with dialogId + Enter. */
684
+ promptText?: string;
675
685
  modifiers?: string[];
676
686
  /** Dispatch strategy. Auto uses DOM events when the page is hidden. */
677
687
  pressMode?: 'auto' | 'dom' | 'keyboard';
@@ -762,10 +772,10 @@ export interface SetCookieResult {
762
772
  path: string;
763
773
  reloaded: boolean;
764
774
  }
765
- export interface RequestDomainPermissionParams {
775
+ export interface RequestPermissionParams {
766
776
  domain: string;
767
777
  }
768
- export type RunActionName = Exclude<ExtensionBrowserAction, 'run_actions' | 'browser_release'>;
778
+ export type RunActionName = Exclude<ExtensionBrowserAction, 'run_actions' | 'browser_release' | 'get_capabilities'>;
769
779
  export interface ActionStep {
770
780
  action: RunActionName;
771
781
  data?: Record<string, unknown>;
@@ -775,6 +785,10 @@ export interface RunActionsParams {
775
785
  tabId: number;
776
786
  }
777
787
  export interface BrowserActionMap {
788
+ get_capabilities: {
789
+ request: GetCapabilitiesParams;
790
+ response: BrowserCapabilityCatalog;
791
+ };
778
792
  tab_checkpoint: {
779
793
  request: CaptureCheckpointParams;
780
794
  response: CaptureCheckpointResult;
@@ -816,12 +830,8 @@ export interface BrowserActionMap {
816
830
  request: SendRequestParams;
817
831
  response: unknown;
818
832
  };
819
- send_mtop_request: {
820
- request: SendMtopRequestParams;
821
- response: unknown;
822
- };
823
833
  browser_list: {
824
- request: undefined;
834
+ request: BrowserListParams | undefined;
825
835
  response: BrowserListResult;
826
836
  };
827
837
  browser_select_browser: {
@@ -946,8 +956,8 @@ export interface BrowserActionMap {
946
956
  request: SetCookieParams;
947
957
  response: SetCookieResult;
948
958
  };
949
- request_domain_permission: {
950
- request: RequestDomainPermissionParams;
959
+ request_permission: {
960
+ request: RequestPermissionParams;
951
961
  response: unknown;
952
962
  };
953
963
  run_actions: {
@@ -979,8 +989,8 @@ export declare const BROWSER_ACTIONS: {
979
989
  readonly get_mocks: true;
980
990
  readonly set_rule: true;
981
991
  readonly get_rules: true;
992
+ readonly get_capabilities: true;
982
993
  readonly send_request: true;
983
- readonly send_mtop_request: true;
984
994
  readonly browser_list: true;
985
995
  readonly browser_select_browser: true;
986
996
  readonly browser_release: true;
@@ -1012,7 +1022,7 @@ export declare const BROWSER_ACTIONS: {
1012
1022
  readonly set_timezone: true;
1013
1023
  readonly get_cookie: true;
1014
1024
  readonly set_cookie: true;
1015
- readonly request_domain_permission: true;
1025
+ readonly request_permission: true;
1016
1026
  readonly run_actions: true;
1017
1027
  };
1018
1028
  export declare const BROWSER_COMMAND_ACTIONS: {
@@ -1025,8 +1035,8 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1025
1035
  readonly get_mocks: true;
1026
1036
  readonly set_rule: true;
1027
1037
  readonly get_rules: true;
1038
+ readonly get_capabilities: true;
1028
1039
  readonly send_request: true;
1029
- readonly send_mtop_request: true;
1030
1040
  readonly browser_list: true;
1031
1041
  readonly browser_release: true;
1032
1042
  readonly browser_control: true;
@@ -1057,7 +1067,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1057
1067
  readonly set_timezone: true;
1058
1068
  readonly get_cookie: true;
1059
1069
  readonly set_cookie: true;
1060
- readonly request_domain_permission: true;
1070
+ readonly request_permission: true;
1061
1071
  readonly run_actions: true;
1062
1072
  };
1063
1073
  export declare const EXTENSION_BROWSER_ACTIONS: {
@@ -1070,8 +1080,8 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1070
1080
  readonly get_mocks: true;
1071
1081
  readonly set_rule: true;
1072
1082
  readonly get_rules: true;
1083
+ readonly get_capabilities: true;
1073
1084
  readonly send_request: true;
1074
- readonly send_mtop_request: true;
1075
1085
  readonly browser_release: true;
1076
1086
  readonly page_screenshot: true;
1077
1087
  readonly tab_open: true;
@@ -1097,7 +1107,7 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1097
1107
  readonly set_timezone: true;
1098
1108
  readonly get_cookie: true;
1099
1109
  readonly set_cookie: true;
1100
- readonly request_domain_permission: true;
1110
+ readonly request_permission: true;
1101
1111
  readonly run_actions: true;
1102
1112
  };
1103
1113
  export declare const BROWSER_CAPABILITY_ACTIONS: {
@@ -1111,8 +1121,8 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1111
1121
  readonly get_mocks: true;
1112
1122
  readonly set_rule: true;
1113
1123
  readonly get_rules: true;
1124
+ readonly get_capabilities: true;
1114
1125
  readonly send_request: true;
1115
- readonly send_mtop_request: true;
1116
1126
  readonly browser_release: true;
1117
1127
  readonly page_screenshot: true;
1118
1128
  readonly tab_open: true;
@@ -1138,7 +1148,7 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1138
1148
  readonly set_timezone: true;
1139
1149
  readonly get_cookie: true;
1140
1150
  readonly set_cookie: true;
1141
- readonly request_domain_permission: true;
1151
+ readonly request_permission: true;
1142
1152
  readonly run_actions: true;
1143
1153
  };
1144
1154
  export declare function isBrowserAction(value: unknown): value is BrowserAction;
@@ -20,15 +20,8 @@ export const BROWSER_DEVICE_PRESET_NAMES = [
20
20
  'ipad-mini',
21
21
  'galaxy-s23',
22
22
  ];
23
- /**
24
- * 客户端容器模拟可用档案名。
25
- *
26
- * 档案数据(UA / 桥对象 / 方法映射)在 @mearl/app-profiles 维护,但名单属于协议:
27
- * 它是 set_app_profile.profile 与 tab_open.appProfile 的取值域,CLI 帮助与 MCP 工具
28
- * schema 的 enum 也由它生成。app-profiles 反向引用本清单约束自己的档案表,
29
- * 因此新增档案时只需改两处(名单 + 档案数据),且漏改会在类型检查时暴露。
30
- */
31
- export const APP_PROFILE_NAMES = ['fliggy', 'taobao', 'wechat', 'alipay'];
23
+ /** App identities are supplied by installed capability catalogs. */
24
+ export const APP_PROFILE_NAMES = [];
32
25
  export function resolvePageEvalExpression(params) {
33
26
  if (typeof params.expression !== 'string' || !params.expression.trim())
34
27
  throw new Error('Invalid expression');
@@ -83,6 +76,10 @@ export function actionRequiresTabId(action) {
83
76
  return typeof action === 'string' && TAB_ID_REQUIRED_ACTION_SET.has(action);
84
77
  }
85
78
  export function validateRequiredActionTabId(action, data) {
79
+ if (action === 'get_capabilities' && data && typeof data === 'object' &&
80
+ ['tabId', 'tabIds', 'openerTabId'].some(key => Object.hasOwn(data, key))) {
81
+ throw new Error('get_capabilities does not accept page targets');
82
+ }
86
83
  const cookieAction = action === 'get_cookie' || action === 'set_cookie';
87
84
  if (!actionRequiresTabId(action) && !cookieAction)
88
85
  return;
@@ -123,8 +120,8 @@ export const BROWSER_ACTIONS = {
123
120
  get_mocks: true,
124
121
  set_rule: true,
125
122
  get_rules: true,
123
+ get_capabilities: true,
126
124
  send_request: true,
127
- send_mtop_request: true,
128
125
  browser_list: true,
129
126
  browser_select_browser: true,
130
127
  browser_release: true,
@@ -156,7 +153,7 @@ export const BROWSER_ACTIONS = {
156
153
  set_timezone: true,
157
154
  get_cookie: true,
158
155
  set_cookie: true,
159
- request_domain_permission: true,
156
+ request_permission: true,
160
157
  run_actions: true,
161
158
  };
162
159
  export const BROWSER_COMMAND_ACTIONS = {
@@ -169,8 +166,8 @@ export const BROWSER_COMMAND_ACTIONS = {
169
166
  get_mocks: true,
170
167
  set_rule: true,
171
168
  get_rules: true,
169
+ get_capabilities: true,
172
170
  send_request: true,
173
- send_mtop_request: true,
174
171
  browser_list: true,
175
172
  browser_release: true,
176
173
  browser_control: true,
@@ -201,7 +198,7 @@ export const BROWSER_COMMAND_ACTIONS = {
201
198
  set_timezone: true,
202
199
  get_cookie: true,
203
200
  set_cookie: true,
204
- request_domain_permission: true,
201
+ request_permission: true,
205
202
  run_actions: true,
206
203
  };
207
204
  export const EXTENSION_BROWSER_ACTIONS = {
@@ -214,8 +211,8 @@ export const EXTENSION_BROWSER_ACTIONS = {
214
211
  get_mocks: true,
215
212
  set_rule: true,
216
213
  get_rules: true,
214
+ get_capabilities: true,
217
215
  send_request: true,
218
- send_mtop_request: true,
219
216
  browser_release: true,
220
217
  page_screenshot: true,
221
218
  tab_open: true,
@@ -241,7 +238,7 @@ export const EXTENSION_BROWSER_ACTIONS = {
241
238
  set_timezone: true,
242
239
  get_cookie: true,
243
240
  set_cookie: true,
244
- request_domain_permission: true,
241
+ request_permission: true,
245
242
  run_actions: true,
246
243
  };
247
244
  export const BROWSER_CAPABILITY_ACTIONS = {
@@ -0,0 +1,47 @@
1
+ import type { AppProfileCatalogEntry, AppProfileSetting, AppProfileUsage } from './appProfileDefinition.js';
2
+ import type { GetCapabilitiesParams } from './browserActionProtocol.js';
3
+ export interface AppCapability {
4
+ id: string;
5
+ label: string;
6
+ source: AppProfileCatalogEntry['source'];
7
+ plugin?: string;
8
+ available: boolean;
9
+ features: string[];
10
+ usage?: AppProfileUsage;
11
+ details?: {
12
+ defaultAppVersion: string;
13
+ bridges: string[];
14
+ methods: Record<string, string[]>;
15
+ behaviors: Record<string, string>;
16
+ settings: AppProfileSetting[];
17
+ };
18
+ }
19
+ export interface BrowserCapabilityCatalog {
20
+ /** Supported operations, not a grant of page permissions or business authorization. */
21
+ actions: string[];
22
+ devicePresets: string[];
23
+ apps: {
24
+ status: 'available' | 'partial' | 'unsupported';
25
+ entries: AppCapability[];
26
+ issues: Array<{
27
+ plugin: string;
28
+ error: string;
29
+ }>;
30
+ };
31
+ limitations: string[];
32
+ help: {
33
+ skill: string;
34
+ commands: string[];
35
+ };
36
+ }
37
+ /** Project validated installed metadata without scripts, global values or Mock response bodies. */
38
+ export declare function describeBrowserCapabilities(actions: readonly string[], catalog: {
39
+ profiles: AppProfileCatalogEntry[];
40
+ errors: Array<{
41
+ plugin: string;
42
+ error: string;
43
+ }>;
44
+ offline?: boolean;
45
+ } | {
46
+ apps: BrowserCapabilityCatalog['apps'];
47
+ } | undefined, params?: GetCapabilitiesParams): BrowserCapabilityCatalog;
@@ -0,0 +1,63 @@
1
+ import { BROWSER_DEVICE_PRESET_NAMES } from './browserActionProtocol.js';
2
+ /** Project validated installed metadata without scripts, global values or Mock response bodies. */
3
+ export function describeBrowserCapabilities(actions, catalog, params = {}) {
4
+ if (!params || typeof params !== 'object' || Array.isArray(params))
5
+ throw new Error('Invalid capability query');
6
+ if (params.app !== undefined && (typeof params.app !== 'string' || !params.app || params.app.length > 161))
7
+ throw new Error('Invalid App capability ID');
8
+ const installed = catalog && 'profiles' in catalog ? catalog : undefined;
9
+ const projected = catalog && 'apps' in catalog ? catalog.apps : undefined;
10
+ if (params.app && installed && !installed.offline && !installed.errors.length && !installed.profiles.some(entry => entry.id === params.app))
11
+ throw new Error(`App profile is not installed: ${params.app}`);
12
+ if (params.app && projected?.status === 'available' && !projected.entries.some(entry => entry.id === params.app))
13
+ throw new Error(`App profile is not installed: ${params.app}`);
14
+ const supportsApps = actions.includes('set_app_profile');
15
+ const profiles = supportsApps ? installed?.profiles ?? [] : [];
16
+ return {
17
+ actions: [...new Set(actions)],
18
+ devicePresets: actions.includes('set_device_emulation') ? [...BROWSER_DEVICE_PRESET_NAMES] : [],
19
+ apps: supportsApps && projected ? {
20
+ status: projected.status,
21
+ entries: projected.entries.filter(entry => !params.app || entry.id === params.app).map(entry => ({
22
+ id: entry.id, label: entry.label, source: entry.source,
23
+ ...(entry.plugin ? { plugin: entry.plugin } : {}), available: entry.available,
24
+ features: [...entry.features],
25
+ ...(entry.usage ? { usage: structuredClone(entry.usage) } : {}),
26
+ ...(params.app && entry.details ? { details: structuredClone(entry.details) } : {}),
27
+ })),
28
+ issues: projected.issues.map(({ plugin, error }) => ({ plugin, error })),
29
+ } : {
30
+ status: !supportsApps || !installed ? 'unsupported' : installed.offline || installed.errors.length || profiles.some(entry => entry.available === false) ? 'partial' : 'available',
31
+ entries: profiles.filter(entry => !params.app || entry.id === params.app).map(entry => {
32
+ const definition = entry.definition;
33
+ const methods = {};
34
+ for (const [name, values] of Object.entries(definition.actions)) {
35
+ const names = Array.isArray(values) ? values : Object.keys(values ?? {});
36
+ if (names.length)
37
+ methods[name] = [...names];
38
+ }
39
+ return {
40
+ id: entry.id, label: entry.label, source: entry.source, plugin: entry.plugin,
41
+ available: entry.available !== false,
42
+ features: ['userAgent', ...(definition.bridges.length ? ['jsBridge'] : []), ...Object.keys(methods), ...(definition.schemes.length ? ['schemes'] : []), ...(definition.settings?.length ? ['settings'] : [])],
43
+ ...(definition.usage ? { usage: structuredClone(definition.usage) } : {}),
44
+ ...(params.app ? { details: {
45
+ defaultAppVersion: definition.defaultAppVersion,
46
+ bridges: definition.bridges.map(bridge => bridge.global),
47
+ methods,
48
+ behaviors: { ...definition.actions.behaviors },
49
+ settings: structuredClone(definition.settings ?? []),
50
+ } } : {}),
51
+ };
52
+ }),
53
+ issues: (installed?.errors ?? projected?.issues)?.map(({ plugin, error }) => ({ plugin, error })) ?? [],
54
+ },
55
+ limitations: [
56
+ 'Actions describe support, not current domain permissions, login state or device connectivity.',
57
+ 'App profiles simulate a WebView. Declared bridge methods, behaviors and response stubs do not guarantee real native authorization, payment or other business effects.',
58
+ 'Package usage and Skill names are guidance from the package author; referenced Skills may need separate installation. Read the relevant help only when needed.',
59
+ ...(!catalog && supportsApps ? ['This Provider does not expose an installed App catalog.'] : []),
60
+ ],
61
+ help: { skill: 'mearl', commands: ['mearl get_capabilities --help', 'mearl set_device_emulation --help', 'mearl set_app_profile --help', 'mearl tab_open --help'] },
62
+ };
63
+ }
@@ -0,0 +1,3 @@
1
+ import type { BrowserListParams } from './browserActionProtocol.js';
2
+ /** An empty request retains ordinary discovery; partial or unknown options cannot be ignored. */
3
+ export declare function parseBrowserListParams(value: unknown): BrowserListParams | undefined;
@@ -0,0 +1,20 @@
1
+ /** An empty request retains ordinary discovery; partial or unknown options cannot be ignored. */
2
+ export function parseBrowserListParams(value) {
3
+ if (value === undefined)
4
+ return undefined;
5
+ if (!value || typeof value !== 'object' || Array.isArray(value))
6
+ throw new Error('Invalid browser_list request');
7
+ const keys = Object.keys(value);
8
+ if (!keys.length)
9
+ return undefined;
10
+ const params = value;
11
+ const form = params.launchForm;
12
+ if (keys.some(key => key !== 'provider' && key !== 'launchForm') ||
13
+ typeof params.provider !== 'string' || !params.provider.trim() ||
14
+ !form || typeof form !== 'object' || Array.isArray(form) ||
15
+ Object.keys(form).some(key => key !== 'variant' && key !== 'values') ||
16
+ (form.variant !== undefined && typeof form.variant !== 'string') ||
17
+ !form.values || typeof form.values !== 'object' || Array.isArray(form.values))
18
+ throw new Error('browser_list discovery requires provider and launchForm with values');
19
+ return params;
20
+ }
@@ -0,0 +1,161 @@
1
+ import type { BrowserActionMap } from './browserActionProtocol.js';
2
+ import { type DeviceEnvironmentObservation } from './deviceEnvironmentObservation.js';
3
+ export declare const BROWSER_ENHANCEMENT_PROTOCOL_VERSION = 1;
4
+ export declare const BROWSER_ENHANCEMENT_NAVIGATION_ORIGIN_VERSION = 1;
5
+ export declare const BROWSER_ENHANCEMENT_PREPARATION_VERSION = 1;
6
+ export declare const BROWSER_ENHANCEMENT_HOST_ENVIRONMENT_VERSION = 1;
7
+ export declare const BROWSER_ENHANCEMENT_PREPARATION_PATH = "src/pages/browser-transport/index.html";
8
+ /** Only the installed Extension's inert top-level page can prepare a new document. */
9
+ export declare function isBrowserEnhancementPreparationUrl(value: unknown): value is string;
10
+ /** Narrow internal host contract. Ordinary input, navigation and browser lifecycle are excluded. */
11
+ export type BrowserEnhancementAction = 'set_device_emulation' | 'set_app_profile' | 'set_timezone';
12
+ export declare function isBrowserEnhancementAction(value: unknown): value is BrowserEnhancementAction;
13
+ export type BrowserEnhancementInvocation = {
14
+ [A in BrowserEnhancementAction]: {
15
+ action: A;
16
+ data: BrowserActionMap[A]['request'];
17
+ };
18
+ }[BrowserEnhancementAction];
19
+ export declare function requiredBrowserEnhancementActions(invocation: BrowserEnhancementInvocation): BrowserEnhancementAction[];
20
+ export interface BrowserEnhancementBinding {
21
+ bindingId: string;
22
+ generation: number;
23
+ tabId: number;
24
+ mainFrameId: string;
25
+ targetId?: string;
26
+ actions: BrowserEnhancementAction[];
27
+ }
28
+ export interface BrowserEnhancementCapabilities {
29
+ protocolVersion: typeof BROWSER_ENHANCEMENT_PROTOCOL_VERSION;
30
+ actions: BrowserEnhancementAction[];
31
+ navigationOriginVersion?: typeof BROWSER_ENHANCEMENT_NAVIGATION_ORIGIN_VERSION;
32
+ preparationVersion?: typeof BROWSER_ENHANCEMENT_PREPARATION_VERSION;
33
+ hostEnvironmentVersion?: typeof BROWSER_ENHANCEMENT_HOST_ENVIRONMENT_VERSION;
34
+ }
35
+ export interface BrowserEnhancementPreparation {
36
+ tabId: number;
37
+ targetId: string;
38
+ url: string;
39
+ capabilities: BrowserEnhancementCapabilities;
40
+ }
41
+ export interface ProviderEnhancementPreparation extends BrowserEnhancementPreparation {
42
+ nativeBrowserId: string;
43
+ providerTabId: number;
44
+ }
45
+ /** Captured by the accepted external owner immediately after creating this target. */
46
+ export interface ProviderInitialEnvironment {
47
+ device: DeviceEnvironmentObservation;
48
+ /** Keep the physical root's captured platform while logical App/device identities remain unchanged. */
49
+ preserveHostPlatform?: true;
50
+ /** The external host owns native pointer/touch delivery; Chrome must not convert its mouse events. */
51
+ preserveHostInput?: true;
52
+ }
53
+ export declare function isProviderInitialEnvironment(value: unknown): value is ProviderInitialEnvironment;
54
+ export declare function isEnhancementNavigationOrigin(value: unknown): value is string;
55
+ /** owner is derived by the accepted Provider control host, never from an ordinary action payload. */
56
+ export type BrowserEnhancementRequest = ({
57
+ operation: 'probe';
58
+ tabId: number;
59
+ } | {
60
+ operation: 'inspect';
61
+ owner: string;
62
+ tabId: number;
63
+ targetId: string;
64
+ actions: BrowserEnhancementAction[];
65
+ navigationOrigin: string;
66
+ } | {
67
+ operation: 'bind';
68
+ owner: string;
69
+ tabId: number;
70
+ mainFrameId: string;
71
+ targetId?: string;
72
+ actions: BrowserEnhancementAction[];
73
+ navigationOrigin?: string;
74
+ initialEnvironment?: ProviderInitialEnvironment;
75
+ } | ({
76
+ operation: 'invoke';
77
+ owner: string;
78
+ bindingId: string;
79
+ generation: number;
80
+ } & BrowserEnhancementInvocation) | {
81
+ operation: 'release';
82
+ owner: string;
83
+ bindingId: string;
84
+ generation: number;
85
+ }) & {
86
+ deadline?: number;
87
+ };
88
+ export type BrowserEnhancementResponse = {
89
+ capabilities: BrowserEnhancementCapabilities;
90
+ tabId: number;
91
+ mainFrameId: string;
92
+ targetId?: string;
93
+ } | {
94
+ preparation: BrowserEnhancementPreparation;
95
+ } | {
96
+ binding: BrowserEnhancementBinding;
97
+ } | {
98
+ result: unknown;
99
+ } | {
100
+ released: boolean;
101
+ conflicts?: string[];
102
+ };
103
+ export interface ProviderEnhancementBinding extends BrowserEnhancementBinding {
104
+ nativeBrowserId: string;
105
+ providerTabId: number;
106
+ }
107
+ /** Read-only control/identity preflight supplied by the external page owner. */
108
+ export type ProviderEnhancementTarget = {
109
+ tabId: number;
110
+ ready: false;
111
+ } | {
112
+ tabId: number;
113
+ ready: true;
114
+ mainFrameId?: string;
115
+ targetId?: string;
116
+ url: string;
117
+ initialEnvironment?: ProviderInitialEnvironment;
118
+ };
119
+ export declare function isProviderEnhancementTarget(value: unknown): value is ProviderEnhancementTarget;
120
+ /** Match every identity asserted by the external owner; URL alone is never proof. */
121
+ export declare function matchesProviderEnhancementTarget(target: Extract<ProviderEnhancementTarget, {
122
+ ready: true;
123
+ }>, physical: {
124
+ mainFrameId: string;
125
+ targetId?: string;
126
+ }): boolean;
127
+ export declare function requireReadyProviderEnhancementTarget(value: unknown, tabId: number): Extract<ProviderEnhancementTarget, {
128
+ ready: true;
129
+ }>;
130
+ /** Provider-side request. The control host supplies ownership and physical tab mappings. */
131
+ export type ProviderEnhancementRequest = {
132
+ operation: 'inspect';
133
+ providerTabId: number;
134
+ nativeBrowserId?: string;
135
+ actions: BrowserEnhancementAction[];
136
+ navigationOrigin: string;
137
+ } | {
138
+ operation: 'bind';
139
+ providerTabId: number;
140
+ nativeBrowserId?: string;
141
+ actions: BrowserEnhancementAction[];
142
+ navigationOrigin?: string;
143
+ } | ({
144
+ operation: 'invoke';
145
+ bindingId: string;
146
+ generation: number;
147
+ } & BrowserEnhancementInvocation) | {
148
+ operation: 'release';
149
+ bindingId: string;
150
+ generation: number;
151
+ };
152
+ export type ProviderEnhancementResponse = {
153
+ preparation: ProviderEnhancementPreparation;
154
+ } | {
155
+ binding: ProviderEnhancementBinding;
156
+ } | {
157
+ result: unknown;
158
+ } | {
159
+ released: boolean;
160
+ conflicts?: string[];
161
+ };