@mearl/browser-core 3.0.0-beta.4 → 3.0.0-beta.7

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 (47) hide show
  1. package/README.md +2 -2
  2. package/dist/agentChat.d.ts +2 -0
  3. package/dist/agentSkills.d.ts +1 -1
  4. package/dist/app-profile-runtime/types.d.ts +10 -12
  5. package/dist/appProfileDefinition.d.ts +32 -14
  6. package/dist/appProfileDefinition.js +63 -69
  7. package/dist/axSnapshot.js +1 -1
  8. package/dist/boundedRequestBuffer.d.ts +4 -4
  9. package/dist/browserActionProtocol.d.ts +65 -42
  10. package/dist/browserActionProtocol.js +15 -15
  11. package/dist/browserCapabilities.d.ts +47 -0
  12. package/dist/browserCapabilities.js +63 -0
  13. package/dist/browserDiscovery.d.ts +3 -0
  14. package/dist/browserDiscovery.js +20 -0
  15. package/dist/browserEnhancement.d.ts +161 -0
  16. package/dist/browserEnhancement.js +80 -0
  17. package/dist/cookie.d.ts +6 -0
  18. package/dist/cookie.js +20 -5
  19. package/dist/dataStructure.d.ts +8 -0
  20. package/dist/dataStructure.js +58 -0
  21. package/dist/deviceEnvironmentObservation.d.ts +48 -0
  22. package/dist/deviceEnvironmentObservation.js +77 -0
  23. package/dist/domClicking.d.ts +14 -0
  24. package/dist/domClicking.js +98 -10
  25. package/dist/domInspection.js +13 -1
  26. package/dist/extensionServiceProtocol.d.ts +7 -0
  27. package/dist/extensionServiceProtocol.js +1 -0
  28. package/dist/index.d.ts +8 -0
  29. package/dist/index.js +8 -0
  30. package/dist/pageAct.d.ts +2 -0
  31. package/dist/pageAct.js +42 -10
  32. package/dist/pageDialog.d.ts +66 -0
  33. package/dist/pageDialog.js +175 -0
  34. package/dist/pageObserver.js +16 -5
  35. package/dist/pagePressing.d.ts +1 -1
  36. package/dist/providerAppResources.d.ts +39 -0
  37. package/dist/providerAppResources.js +2 -0
  38. package/dist/proxyPermissions.js +4 -3
  39. package/dist/requestMetadata.d.ts +9 -0
  40. package/dist/requestMetadata.js +8 -0
  41. package/dist/requestSerializer.d.ts +2 -2
  42. package/dist/requestSerializer.js +1 -29
  43. package/dist/requestStreamCapture.d.ts +5 -3
  44. package/dist/requestStreamCapture.js +2 -0
  45. package/dist/runActions.js +1 -1
  46. package/dist/types.d.ts +4 -2
  47. package/package.json +2 -2
@@ -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,14 @@ 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;
115
+ export interface NetworkControlSelection {
116
+ id: string;
117
+ value: string;
118
+ }
119
+ /** Parameters are interpreted and validated by the installed request protocol. */
120
+ export interface SendProtocolRequestParams {
119
121
  timeout?: number;
120
- headers?: Record<string, string>;
121
- ttid?: string;
122
+ [key: string]: unknown;
122
123
  }
123
124
  export type BrowserStatus = 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
124
125
  export type BrowserTransport = 'extension' | 'cdp' | 'provider';
@@ -184,6 +185,7 @@ export interface BrowserInfoBase {
184
185
  pairing?: BrowserPairingInfo;
185
186
  }
186
187
  export type BrowserScreenshotKind = 'native' | 'reconstructed' | 'none';
188
+ export type BrowserControlSessionMode = 'mearl' | 'external';
187
189
  /** Browser-targeted actions that an external provider may implement. */
188
190
  export type BrowserCapabilityAction = ExtensionBrowserAction | 'page_download';
189
191
  /** Capabilities advertised by an external browser-control provider. */
@@ -191,6 +193,8 @@ export interface BrowserCapabilities {
191
193
  actions: BrowserCapabilityAction[];
192
194
  /** Pixel fidelity of page_screenshot, or none when that action is unavailable. */
193
195
  screenshot: BrowserScreenshotKind;
196
+ /** Fixed per instance. Omitted means Mearl sessions; external delegates task control. */
197
+ controlSessionMode?: BrowserControlSessionMode;
194
198
  }
195
199
  export interface RegularBrowserInfo extends BrowserInfoBase {
196
200
  type: 'regular';
@@ -204,6 +208,13 @@ export interface ManagedBrowserInfo extends BrowserInfoBase {
204
208
  operations: BrowserProviderOperation[];
205
209
  }
206
210
  export type BrowserInfo = RegularBrowserInfo | ManagedBrowserInfo;
211
+ export interface BrowserListParams {
212
+ provider: string;
213
+ launchForm: {
214
+ variant?: string;
215
+ values: Record<string, BrowserJsonValue>;
216
+ };
217
+ }
207
218
  export interface BrowserListResult {
208
219
  count: number;
209
220
  connectedCount: number;
@@ -211,6 +222,11 @@ export interface BrowserListResult {
211
222
  browsers: BrowserInfo[];
212
223
  /** Partial discovery failures; successfully inspected browser sources remain in the result. */
213
224
  warnings?: string[];
225
+ /** Present only for an explicit, source-local Provider launch-form query. */
226
+ discovery?: {
227
+ provider: string;
228
+ launchForm: BrowserProviderLaunchForm;
229
+ };
214
230
  }
215
231
  export interface SelectBrowserParams {
216
232
  browser?: string;
@@ -366,6 +382,7 @@ export interface BrowserProviderDefinition {
366
382
  provider: BrowserProviderIdentity;
367
383
  browserType: {
368
384
  name: string;
385
+ controlSessionModes?: readonly BrowserControlSessionMode[];
369
386
  documentationUrl?: string;
370
387
  inputSchema: BrowserProviderObjectSchema;
371
388
  configuration?: {
@@ -457,7 +474,8 @@ export interface BrowserEmulationOptions {
457
474
  /** App 容器横屏时将根页面与业务页面分置左右 WebView;仅与 deviceShell、App 档案同时生效。 */
458
475
  splitScreen?: boolean;
459
476
  }
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';
477
+ /** Provider-defined behavior ID; core does not execute or enumerate business behaviors. */
478
+ export type AppBridgeConfigBehavior = string;
461
479
  /** 单个桥方法的声明式覆盖;行为、固定回包、成功空实现三选一。 */
462
480
  export interface AppBridgeMethodConfig {
463
481
  behavior?: AppBridgeConfigBehavior;
@@ -486,8 +504,8 @@ export interface TabOpenParams {
486
504
  emulation?: BrowserEmulationOptions;
487
505
  group?: string;
488
506
  /**
489
- * 客户端容器模拟档案名(如 'fliggy')。只注入容器 UA、环境变量、JSBridge 与桥协议;
490
- * 设备视口和 iframe 系统外壳由 emulation.deviceShell 独立控制。可用档案见 APP_PROFILE_NAMES。
507
+ * 客户端容器模拟档案名(由已安装能力目录提供)。只注入容器 UA、环境变量、JSBridge 与桥协议;
508
+ * 设备视口和 iframe 系统外壳由 emulation.deviceShell 独立控制。可用档案通过 get_capabilities 查询。
491
509
  */
492
510
  appProfile?: AppProfileName;
493
511
  /** 与 appProfile 配合使用;容器系统,默认 ios */
@@ -504,16 +522,9 @@ export type TabGroupParams = {
504
522
  ungroup: true;
505
523
  title?: never;
506
524
  };
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];
525
+ /** App identities are supplied by installed capability catalogs. */
526
+ export declare const APP_PROFILE_NAMES: readonly string[];
527
+ export type BuiltinAppProfileName = string;
517
528
  /** Hosts validate dynamic profile IDs against the active capability catalog. */
518
529
  export type AppProfileName = string;
519
530
  export interface SetAppProfileParams {
@@ -534,10 +545,10 @@ export interface SetAppProfileParams {
534
545
  /** 按方法覆盖档案内置桥配置,仅支持受控行为、固定 JSON 回包和成功空实现 */
535
546
  bridgeConfig?: AppBridgeConfig;
536
547
  /**
537
- * 可选 MTop 接口环境。default 关闭环境改写;省略时保持当前设置。
548
+ * 可选已安装的网络控件选择;null 清除,省略时保持当前设置。
538
549
  * 仅作用于目标 tab,扩展模式与该 tab 的快捷设置共享。
539
550
  */
540
- mtopEnv?: MtopEnvironment;
551
+ networkControl?: NetworkControlSelection | null;
541
552
  /**
542
553
  * 可选设备联动参数。传入时显式字段覆盖档案推荐设备,空对象使用推荐设备且默认开启
543
554
  * deviceShell;省略时不设置或清除该 tab 的设备状态。
@@ -672,6 +683,10 @@ export interface PageInspectParams {
672
683
  export interface PagePressParams {
673
684
  tabId: number;
674
685
  key: string;
686
+ /** Explicit native JavaScript dialog target obtained from a receipt or page_snapshot. */
687
+ dialogId?: string;
688
+ /** Only for accepting a native prompt with dialogId + Enter. */
689
+ promptText?: string;
675
690
  modifiers?: string[];
676
691
  /** Dispatch strategy. Auto uses DOM events when the page is hidden. */
677
692
  pressMode?: 'auto' | 'dom' | 'keyboard';
@@ -762,10 +777,10 @@ export interface SetCookieResult {
762
777
  path: string;
763
778
  reloaded: boolean;
764
779
  }
765
- export interface RequestDomainPermissionParams {
780
+ export interface RequestPermissionParams {
766
781
  domain: string;
767
782
  }
768
- export type RunActionName = Exclude<ExtensionBrowserAction, 'run_actions' | 'browser_release'>;
783
+ export type RunActionName = Exclude<ExtensionBrowserAction, 'run_actions' | 'browser_release' | 'get_capabilities'>;
769
784
  export interface ActionStep {
770
785
  action: RunActionName;
771
786
  data?: Record<string, unknown>;
@@ -775,6 +790,10 @@ export interface RunActionsParams {
775
790
  tabId: number;
776
791
  }
777
792
  export interface BrowserActionMap {
793
+ get_capabilities: {
794
+ request: GetCapabilitiesParams;
795
+ response: BrowserCapabilityCatalog;
796
+ };
778
797
  tab_checkpoint: {
779
798
  request: CaptureCheckpointParams;
780
799
  response: CaptureCheckpointResult;
@@ -816,12 +835,12 @@ export interface BrowserActionMap {
816
835
  request: SendRequestParams;
817
836
  response: unknown;
818
837
  };
819
- send_mtop_request: {
820
- request: SendMtopRequestParams;
838
+ send_protocol_request: {
839
+ request: SendProtocolRequestParams;
821
840
  response: unknown;
822
841
  };
823
842
  browser_list: {
824
- request: undefined;
843
+ request: BrowserListParams | undefined;
825
844
  response: BrowserListResult;
826
845
  };
827
846
  browser_select_browser: {
@@ -946,8 +965,8 @@ export interface BrowserActionMap {
946
965
  request: SetCookieParams;
947
966
  response: SetCookieResult;
948
967
  };
949
- request_domain_permission: {
950
- request: RequestDomainPermissionParams;
968
+ request_permission: {
969
+ request: RequestPermissionParams;
951
970
  response: unknown;
952
971
  };
953
972
  run_actions: {
@@ -979,8 +998,9 @@ export declare const BROWSER_ACTIONS: {
979
998
  readonly get_mocks: true;
980
999
  readonly set_rule: true;
981
1000
  readonly get_rules: true;
1001
+ readonly get_capabilities: true;
982
1002
  readonly send_request: true;
983
- readonly send_mtop_request: true;
1003
+ readonly send_protocol_request: true;
984
1004
  readonly browser_list: true;
985
1005
  readonly browser_select_browser: true;
986
1006
  readonly browser_release: true;
@@ -1012,7 +1032,7 @@ export declare const BROWSER_ACTIONS: {
1012
1032
  readonly set_timezone: true;
1013
1033
  readonly get_cookie: true;
1014
1034
  readonly set_cookie: true;
1015
- readonly request_domain_permission: true;
1035
+ readonly request_permission: true;
1016
1036
  readonly run_actions: true;
1017
1037
  };
1018
1038
  export declare const BROWSER_COMMAND_ACTIONS: {
@@ -1025,8 +1045,9 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1025
1045
  readonly get_mocks: true;
1026
1046
  readonly set_rule: true;
1027
1047
  readonly get_rules: true;
1048
+ readonly get_capabilities: true;
1028
1049
  readonly send_request: true;
1029
- readonly send_mtop_request: true;
1050
+ readonly send_protocol_request: true;
1030
1051
  readonly browser_list: true;
1031
1052
  readonly browser_release: true;
1032
1053
  readonly browser_control: true;
@@ -1057,7 +1078,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1057
1078
  readonly set_timezone: true;
1058
1079
  readonly get_cookie: true;
1059
1080
  readonly set_cookie: true;
1060
- readonly request_domain_permission: true;
1081
+ readonly request_permission: true;
1061
1082
  readonly run_actions: true;
1062
1083
  };
1063
1084
  export declare const EXTENSION_BROWSER_ACTIONS: {
@@ -1070,8 +1091,9 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1070
1091
  readonly get_mocks: true;
1071
1092
  readonly set_rule: true;
1072
1093
  readonly get_rules: true;
1094
+ readonly get_capabilities: true;
1073
1095
  readonly send_request: true;
1074
- readonly send_mtop_request: true;
1096
+ readonly send_protocol_request: true;
1075
1097
  readonly browser_release: true;
1076
1098
  readonly page_screenshot: true;
1077
1099
  readonly tab_open: true;
@@ -1097,7 +1119,7 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1097
1119
  readonly set_timezone: true;
1098
1120
  readonly get_cookie: true;
1099
1121
  readonly set_cookie: true;
1100
- readonly request_domain_permission: true;
1122
+ readonly request_permission: true;
1101
1123
  readonly run_actions: true;
1102
1124
  };
1103
1125
  export declare const BROWSER_CAPABILITY_ACTIONS: {
@@ -1111,8 +1133,9 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1111
1133
  readonly get_mocks: true;
1112
1134
  readonly set_rule: true;
1113
1135
  readonly get_rules: true;
1136
+ readonly get_capabilities: true;
1114
1137
  readonly send_request: true;
1115
- readonly send_mtop_request: true;
1138
+ readonly send_protocol_request: true;
1116
1139
  readonly browser_release: true;
1117
1140
  readonly page_screenshot: true;
1118
1141
  readonly tab_open: true;
@@ -1138,7 +1161,7 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1138
1161
  readonly set_timezone: true;
1139
1162
  readonly get_cookie: true;
1140
1163
  readonly set_cookie: true;
1141
- readonly request_domain_permission: true;
1164
+ readonly request_permission: true;
1142
1165
  readonly run_actions: true;
1143
1166
  };
1144
1167
  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,9 @@ 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,
125
+ send_protocol_request: true,
128
126
  browser_list: true,
129
127
  browser_select_browser: true,
130
128
  browser_release: true,
@@ -156,7 +154,7 @@ export const BROWSER_ACTIONS = {
156
154
  set_timezone: true,
157
155
  get_cookie: true,
158
156
  set_cookie: true,
159
- request_domain_permission: true,
157
+ request_permission: true,
160
158
  run_actions: true,
161
159
  };
162
160
  export const BROWSER_COMMAND_ACTIONS = {
@@ -169,8 +167,9 @@ export const BROWSER_COMMAND_ACTIONS = {
169
167
  get_mocks: true,
170
168
  set_rule: true,
171
169
  get_rules: true,
170
+ get_capabilities: true,
172
171
  send_request: true,
173
- send_mtop_request: true,
172
+ send_protocol_request: true,
174
173
  browser_list: true,
175
174
  browser_release: true,
176
175
  browser_control: true,
@@ -201,7 +200,7 @@ export const BROWSER_COMMAND_ACTIONS = {
201
200
  set_timezone: true,
202
201
  get_cookie: true,
203
202
  set_cookie: true,
204
- request_domain_permission: true,
203
+ request_permission: true,
205
204
  run_actions: true,
206
205
  };
207
206
  export const EXTENSION_BROWSER_ACTIONS = {
@@ -214,8 +213,9 @@ export const EXTENSION_BROWSER_ACTIONS = {
214
213
  get_mocks: true,
215
214
  set_rule: true,
216
215
  get_rules: true,
216
+ get_capabilities: true,
217
217
  send_request: true,
218
- send_mtop_request: true,
218
+ send_protocol_request: true,
219
219
  browser_release: true,
220
220
  page_screenshot: true,
221
221
  tab_open: true,
@@ -241,7 +241,7 @@ export const EXTENSION_BROWSER_ACTIONS = {
241
241
  set_timezone: true,
242
242
  get_cookie: true,
243
243
  set_cookie: true,
244
- request_domain_permission: true,
244
+ request_permission: true,
245
245
  run_actions: true,
246
246
  };
247
247
  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
+ };