@mearl/browser-core 3.0.0-beta.5 → 3.0.0-beta.8

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 (41) hide show
  1. package/README.md +1 -1
  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 +4 -8
  5. package/dist/appProfileDefinition.d.ts +4 -7
  6. package/dist/appProfileDefinition.js +11 -49
  7. package/dist/axSnapshot.js +1 -1
  8. package/dist/boundedRequestBuffer.d.ts +4 -4
  9. package/dist/browserActionProtocol.d.ts +36 -32
  10. package/dist/browserActionProtocol.js +3 -6
  11. package/dist/browserCapabilities.d.ts +2 -0
  12. package/dist/browserCapabilities.js +19 -5
  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/deviceEnvironmentObservation.d.ts +48 -0
  18. package/dist/deviceEnvironmentObservation.js +77 -0
  19. package/dist/domClicking.d.ts +14 -0
  20. package/dist/domClicking.js +46 -10
  21. package/dist/extensionServiceProtocol.d.ts +6 -0
  22. package/dist/extensionServiceProtocol.js +1 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.js +6 -0
  25. package/dist/pageAct.d.ts +2 -0
  26. package/dist/pageAct.js +42 -10
  27. package/dist/pageDialog.d.ts +66 -0
  28. package/dist/pageDialog.js +175 -0
  29. package/dist/pageObserver.js +16 -5
  30. package/dist/pagePressing.d.ts +1 -1
  31. package/dist/pluginPageHost.js +2 -2
  32. package/dist/providerAppResources.d.ts +39 -0
  33. package/dist/providerAppResources.js +2 -0
  34. package/dist/proxyPermissions.js +2 -3
  35. package/dist/requestMetadata.d.ts +9 -0
  36. package/dist/requestMetadata.js +8 -0
  37. package/dist/requestSerializer.d.ts +2 -2
  38. package/dist/requestStreamCapture.d.ts +5 -3
  39. package/dist/requestStreamCapture.js +2 -0
  40. package/dist/types.d.ts +4 -2
  41. package/package.json +2 -2
package/README.md CHANGED
@@ -6,6 +6,6 @@
6
6
 
7
7
  `@mearl/browser-core/appProfileRuntime` 的内置安装器只同步 UA、navigator.appVersion、navigator.platform 和触摸点,不安装 App 桥、业务全局变量、容器栈或授权处理。有 pageRuntime 绑定时,宿主必须先从已安装的能力包准备确切代码,再通过页面运行时派发器执行;不能调用基础安装器代替。资源准备和派发见 [能力包](../../docs/browser-bundles.md#页面运行时)。
8
8
 
9
- 默认代理授权地址只有 localhost 与 127.0.0.1。其余站点由宿主取得权限后传入授权列表;组织域名和员工身份不属于本包默认值。业务请求辅助、业务事件解析、测试账号登录及用户 Cookie 身份推导留在独立能力中。
9
+ 默认代理授权地址为 localhost 与 127.0.0.1。其余站点由宿主取得权限后传入授权列表。核心内置 Aplus/RUM/ARMS 事件解析;扩展解析器通过能力包注册。
10
10
 
11
11
  Agent 合同源在本包的 agentChat.ts、agentSkills.ts 和 pluginModels.ts;分别通过同名子路径导出,agent-runtime 使用这些合同,避免并行维护副本。可序列化的页面函数保持自包含,便于 Extension 与 CDP 共同使用。
@@ -15,6 +15,8 @@ export interface AgentChatProviderDescriptor {
15
15
  id: string;
16
16
  name: string;
17
17
  available: boolean;
18
+ /** False while accepted conversations retain a removed or superseded runtime. */
19
+ acceptsNewSessions?: boolean;
18
20
  capabilities: {
19
21
  streaming: boolean;
20
22
  resume: boolean;
@@ -1,4 +1,4 @@
1
- export type AgentSkillProviderId = 'codex' | 'qoder';
1
+ export type AgentSkillProviderId = string;
2
2
  export type AgentSkillScope = 'project' | 'global';
3
3
  export type AgentInstalledSkillScope = AgentSkillScope | 'system' | 'admin' | 'built-in' | 'unknown';
4
4
  export interface AgentInstalledSkill {
@@ -9,7 +9,8 @@ export interface AppBridgeSpec {
9
9
  /** 页面脚本重设全局对象时仍保留桥叶子,同时接纳页面对象上的其他 API。 */
10
10
  persistent?: boolean;
11
11
  }
12
- export type AppBridgeBehavior = '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';
12
+ /** Provider-defined identifier, interpreted by its installed page runtime. */
13
+ export type AppBridgeBehavior = string;
13
14
  /** 桥方法名到标准化动作的映射。命名空间桥使用 `Class.method`,其余使用 api 名。 */
14
15
  export interface BridgeActionMap {
15
16
  open: string[];
@@ -18,7 +19,7 @@ export interface BridgeActionMap {
18
19
  navigationBar?: string[];
19
20
  statusBar?: string[];
20
21
  systemInfo: string[];
21
- mtop: string[];
22
+ protocol: string[];
22
23
  kvGet?: string[];
23
24
  kvSet?: string[];
24
25
  kvDelete?: string[];
@@ -209,11 +210,6 @@ export interface InjectedAppProfileConfig {
209
210
  schemes: AppSchemeRule[];
210
211
  miniProgram?: AppMiniProgramConfig;
211
212
  imagePicker?: AppImagePickerConfig;
212
- /** 原生定位返回地址时使用的逆地理编码服务,复用容器的 MTop 传输。 */
213
- geolocation?: {
214
- reverseGeocodeApi: string;
215
- version: string;
216
- };
217
213
  overlay?: AppOverlayConfig;
218
214
  /** URL 参数为真时以新 WebView 替换当前业务层。 */
219
215
  popBeforeOpenParam?: string;
@@ -223,7 +219,7 @@ export interface InjectedAppProfileConfig {
223
219
  layerUrlProxy?: AppLayerUrlProxyConfig;
224
220
  urlSyncHostSuffixes?: string[];
225
221
  animationMs?: number;
226
- forceH5Mtop?: boolean;
222
+ runtimeOptions?: Record<string, unknown>;
227
223
  titleBar?: AppTitleBarConfig;
228
224
  rootContainer?: AppRootContainerConfig;
229
225
  simulateSystemBars?: boolean;
@@ -111,10 +111,6 @@ export interface AppProfileDefinition {
111
111
  miniProgram?: AppMiniProgramConfig;
112
112
  /** 原生图片页 scheme 的浏览器选图与上传配置 */
113
113
  imagePicker?: AppImagePickerConfig;
114
- geolocation?: {
115
- reverseGeocodeApi: string;
116
- version: string;
117
- };
118
114
  /**
119
115
  * 地址栏借位同步的可选 host 白名单:容器栈顶 URL 的 host 命中时,地址栏借 top
120
116
  * 域名同步其 path+query+hash(pushState 同源约束下保持域名不变只改 path);
@@ -145,10 +141,11 @@ export interface AppProfileDefinition {
145
141
  statusBarBackgroundColors?: Record<string, string>;
146
142
  /** 按业务根域配置标题栏与状态栏样式。 */
147
143
  titleBarHostStyles?: AppTitleBarHostStyle[];
148
- /** 桥存在时仍将 MTOP 传输固定在浏览器 H5 通道 */
149
- forceH5Mtop?: boolean;
144
+ /** Opaque configuration owned by the installed page runtime. */
145
+ runtimeOptions?: Record<string, unknown>;
150
146
  }
151
- export declare const APP_BRIDGE_BEHAVIORS: readonly ["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"];
147
+ /** Behavior IDs belong to the installed page runtime, never to a host-side enum. */
148
+ export declare function isAppBridgeBehavior(value: unknown): value is string;
152
149
  /** Validate plain data before registration or compiling a document-start configuration. */
153
150
  export declare function validateAppProfileDefinition(value: unknown): AppProfileDefinition;
154
151
  export declare function validateAppProfileContribution(value: unknown): AppProfileContribution | undefined;
@@ -1,42 +1,7 @@
1
- export const APP_BRIDGE_BEHAVIORS = [
2
- 'navigate',
3
- 'closeAll',
4
- 'closeBackData',
5
- 'postMessage',
6
- 'notifySubscribe',
7
- 'notifyUnsubscribe',
8
- 'notifyPost',
9
- 'sharedFileRead',
10
- 'sharedFileWrite',
11
- 'sharedDataGet',
12
- 'sharedDataSet',
13
- 'legacyBroadcastCreate',
14
- 'legacyBroadcastPost',
15
- 'legacyBroadcastClose',
16
- 'memoryGet',
17
- 'memorySet',
18
- 'memoryDelete',
19
- 'availabilityMap',
20
- 'userInfo',
21
- 'authCode',
22
- 'networkInfo',
23
- 'geolocation',
24
- 'permission',
25
- 'imagePicker',
26
- 'prefetch',
27
- 'fptTrack',
28
- 'mtopStream',
29
- 'previewFile',
30
- 'toast',
31
- 'unsupportedNativeInput',
32
- 'payment',
33
- 'userTrack',
34
- 'calendar',
35
- 'networkQualityMonitor',
36
- 'beaconRequest',
37
- 'voiceRecognition',
38
- ];
39
- const BEHAVIORS = new Set(APP_BRIDGE_BEHAVIORS);
1
+ /** Behavior IDs belong to the installed page runtime, never to a host-side enum. */
2
+ export function isAppBridgeBehavior(value) {
3
+ return typeof value === 'string' && /^[a-zA-Z][a-zA-Z0-9_.:-]{0,95}$/.test(value);
4
+ }
40
5
  function record(value) {
41
6
  return value !== null && typeof value === 'object' && !Array.isArray(value);
42
7
  }
@@ -80,7 +45,7 @@ function validateActions(value) {
80
45
  'navigationBar',
81
46
  'statusBar',
82
47
  'systemInfo',
83
- 'mtop',
48
+ 'protocol',
84
49
  'kvGet',
85
50
  'kvSet',
86
51
  'kvDelete',
@@ -88,7 +53,7 @@ function validateActions(value) {
88
53
  'noop',
89
54
  'silent',
90
55
  ];
91
- fields(value, ['open', 'close', 'title', 'systemInfo', 'mtop', 'noop'], [...arrays, 'responses', 'behaviors'], 'actions');
56
+ fields(value, ['open', 'close', 'title', 'systemInfo', 'protocol', 'noop'], [...arrays, 'responses', 'behaviors'], 'actions');
92
57
  for (const key of arrays)
93
58
  if (value[key] !== undefined && !strings(value[key]))
94
59
  invalid(`actions.${key}`);
@@ -96,7 +61,7 @@ function validateActions(value) {
96
61
  invalid('actions.responses');
97
62
  if (value.behaviors !== undefined &&
98
63
  (!stringMap(value.behaviors) ||
99
- !Object.values(value.behaviors).every(item => BEHAVIORS.has(item))))
64
+ !Object.values(value.behaviors).every(item => isAppBridgeBehavior(item))))
100
65
  invalid('actions.behaviors');
101
66
  }
102
67
  /** Validate plain data before registration or compiling a document-start configuration. */
@@ -131,7 +96,6 @@ export function validateAppProfileDefinition(value) {
131
96
  'authorization',
132
97
  'miniProgram',
133
98
  'imagePicker',
134
- 'geolocation',
135
99
  'urlSyncHostSuffixes',
136
100
  'overlay',
137
101
  'popBeforeOpenParam',
@@ -142,7 +106,7 @@ export function validateAppProfileDefinition(value) {
142
106
  'titleBarHiddenPathnames',
143
107
  'statusBarBackgroundColors',
144
108
  'titleBarHostStyles',
145
- 'forceH5Mtop',
109
+ 'runtimeOptions',
146
110
  ];
147
111
  fields(value, required, optional, 'definition');
148
112
  for (const key of ['name', 'label', 'appName', 'defaultAppVersion'])
@@ -313,7 +277,7 @@ export function validateAppProfileDefinition(value) {
313
277
  'navigationBar',
314
278
  'statusBar',
315
279
  'systemInfo',
316
- 'mtop',
280
+ 'protocol',
317
281
  'kvGet',
318
282
  'kvSet',
319
283
  'kvDelete',
@@ -339,9 +303,8 @@ export function validateAppProfileDefinition(value) {
339
303
  invalid('setting.option type');
340
304
  }
341
305
  }
342
- for (const key of ['forceH5Mtop'])
343
- if (value[key] !== undefined && typeof value[key] !== 'boolean')
344
- invalid(key);
306
+ if (value.runtimeOptions !== undefined && (!record(value.runtimeOptions) || !json(value.runtimeOptions)))
307
+ invalid('runtimeOptions');
345
308
  for (const key of ['popBeforeOpenParam', 'messageEvent'])
346
309
  if (value[key] !== undefined && !text(value[key]))
347
310
  invalid(key);
@@ -353,7 +316,6 @@ export function validateAppProfileDefinition(value) {
353
316
  function validateStructuredOptions(value) {
354
317
  const shapes = {
355
318
  nativeBack: [[], ['event', 'controlFunction', 'handler']],
356
- geolocation: [['reverseGeocodeApi', 'version'], []],
357
319
  layerUrlProxy: [
358
320
  ['sourceHostPrefix', 'pathPrefix', 'targetHostSuffixes'],
359
321
  ['defaultTargetHost'],
@@ -290,7 +290,7 @@ export function resolvePageSnapshotQuery(query) {
290
290
  if (query === undefined)
291
291
  return undefined;
292
292
  if (!query || typeof query !== 'object' || Array.isArray(query)) {
293
- throw new Error('page_snapshot: query must be an object');
293
+ throw new Error('page_snapshot: query must be an object, for example {"query":{"text":"提交","exact":false}}.');
294
294
  }
295
295
  const { text, role, exact } = query;
296
296
  if (text !== undefined && (typeof text !== 'string' || !text.trim())) {
@@ -1,4 +1,4 @@
1
- import type { MtopRequest } from './types.js';
1
+ import type { CapturedRequest } from './types.js';
2
2
  export declare const REQUEST_BUFFER_MAX_ENTRIES = 500;
3
3
  export declare const REQUEST_BUFFER_MAX_BYTES: number;
4
4
  export declare const REQUEST_BUFFER_MAX_FIELD_BYTES: number;
@@ -12,7 +12,7 @@ export interface RequestBufferLimits {
12
12
  maxFieldBytes?: number;
13
13
  }
14
14
  export declare function limitBufferedField(value: any, maxBytes: number): any;
15
- export declare function estimateRequestBufferBytes(request: MtopRequest): number;
15
+ export declare function estimateRequestBufferBytes(request: CapturedRequest): number;
16
16
  export declare function createRequestBufferAccounting(): RequestBufferAccounting;
17
- export declare function appendRequestToBuffer(requests: MtopRequest[], accounting: RequestBufferAccounting, request: MtopRequest, limits?: RequestBufferLimits): MtopRequest[];
18
- export declare function refreshRequestInBuffer(requests: MtopRequest[], accounting: RequestBufferAccounting, request: MtopRequest, limits?: RequestBufferLimits): MtopRequest[];
17
+ export declare function appendRequestToBuffer(requests: CapturedRequest[], accounting: RequestBufferAccounting, request: CapturedRequest, limits?: RequestBufferLimits): CapturedRequest[];
18
+ export declare function refreshRequestInBuffer(requests: CapturedRequest[], accounting: RequestBufferAccounting, request: CapturedRequest, limits?: RequestBufferLimits): CapturedRequest[];
@@ -18,7 +18,7 @@ export interface GetRequestsParams {
18
18
  fields?: string[];
19
19
  keysOnly?: boolean;
20
20
  applyHiddenFilter?: boolean;
21
- source?: 'mtop' | 'requests' | 'all';
21
+ source?: 'protocol' | 'requests' | 'all';
22
22
  }
23
23
  export interface GetLogsParams {
24
24
  tabId: number;
@@ -112,18 +112,9 @@ export interface SendRequestParams {
112
112
  responseType?: 'json' | 'text' | 'auto';
113
113
  timeout?: number;
114
114
  }
115
- export type MtopEnvironmentTarget = 'prod' | 'pre';
116
- export type MtopEnvironment = 'default' | MtopEnvironmentTarget;
117
- export interface SendMtopRequestParams {
118
- api: string;
119
- data?: unknown;
120
- version?: string;
121
- method?: string;
122
- appKey?: string;
123
- env?: MtopEnvironmentTarget;
124
- timeout?: number;
125
- headers?: Record<string, string>;
126
- ttid?: string;
115
+ export interface NetworkControlSelection {
116
+ id: string;
117
+ value: string;
127
118
  }
128
119
  export type BrowserStatus = 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
129
120
  export type BrowserTransport = 'extension' | 'cdp' | 'provider';
@@ -189,6 +180,7 @@ export interface BrowserInfoBase {
189
180
  pairing?: BrowserPairingInfo;
190
181
  }
191
182
  export type BrowserScreenshotKind = 'native' | 'reconstructed' | 'none';
183
+ export type BrowserControlSessionMode = 'mearl' | 'external';
192
184
  /** Browser-targeted actions that an external provider may implement. */
193
185
  export type BrowserCapabilityAction = ExtensionBrowserAction | 'page_download';
194
186
  /** Capabilities advertised by an external browser-control provider. */
@@ -196,6 +188,8 @@ export interface BrowserCapabilities {
196
188
  actions: BrowserCapabilityAction[];
197
189
  /** Pixel fidelity of page_screenshot, or none when that action is unavailable. */
198
190
  screenshot: BrowserScreenshotKind;
191
+ /** Fixed per instance. Omitted means Mearl sessions; external delegates task control. */
192
+ controlSessionMode?: BrowserControlSessionMode;
199
193
  }
200
194
  export interface RegularBrowserInfo extends BrowserInfoBase {
201
195
  type: 'regular';
@@ -209,6 +203,13 @@ export interface ManagedBrowserInfo extends BrowserInfoBase {
209
203
  operations: BrowserProviderOperation[];
210
204
  }
211
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
+ }
212
213
  export interface BrowserListResult {
213
214
  count: number;
214
215
  connectedCount: number;
@@ -216,6 +217,11 @@ export interface BrowserListResult {
216
217
  browsers: BrowserInfo[];
217
218
  /** Partial discovery failures; successfully inspected browser sources remain in the result. */
218
219
  warnings?: string[];
220
+ /** Present only for an explicit, source-local Provider launch-form query. */
221
+ discovery?: {
222
+ provider: string;
223
+ launchForm: BrowserProviderLaunchForm;
224
+ };
219
225
  }
220
226
  export interface SelectBrowserParams {
221
227
  browser?: string;
@@ -371,6 +377,7 @@ export interface BrowserProviderDefinition {
371
377
  provider: BrowserProviderIdentity;
372
378
  browserType: {
373
379
  name: string;
380
+ controlSessionModes?: readonly BrowserControlSessionMode[];
374
381
  documentationUrl?: string;
375
382
  inputSchema: BrowserProviderObjectSchema;
376
383
  configuration?: {
@@ -462,7 +469,8 @@ export interface BrowserEmulationOptions {
462
469
  /** App 容器横屏时将根页面与业务页面分置左右 WebView;仅与 deviceShell、App 档案同时生效。 */
463
470
  splitScreen?: boolean;
464
471
  }
465
- 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;
466
474
  /** 单个桥方法的声明式覆盖;行为、固定回包、成功空实现三选一。 */
467
475
  export interface AppBridgeMethodConfig {
468
476
  behavior?: AppBridgeConfigBehavior;
@@ -532,10 +540,10 @@ export interface SetAppProfileParams {
532
540
  /** 按方法覆盖档案内置桥配置,仅支持受控行为、固定 JSON 回包和成功空实现 */
533
541
  bridgeConfig?: AppBridgeConfig;
534
542
  /**
535
- * 可选 MTop 接口环境。default 关闭环境改写;省略时保持当前设置。
543
+ * 可选已安装的网络控件选择;null 清除,省略时保持当前设置。
536
544
  * 仅作用于目标 tab,扩展模式与该 tab 的快捷设置共享。
537
545
  */
538
- mtopEnv?: MtopEnvironment;
546
+ networkControl?: NetworkControlSelection | null;
539
547
  /**
540
548
  * 可选设备联动参数。传入时显式字段覆盖档案推荐设备,空对象使用推荐设备且默认开启
541
549
  * deviceShell;省略时不设置或清除该 tab 的设备状态。
@@ -670,6 +678,10 @@ export interface PageInspectParams {
670
678
  export interface PagePressParams {
671
679
  tabId: number;
672
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;
673
685
  modifiers?: string[];
674
686
  /** Dispatch strategy. Auto uses DOM events when the page is hidden. */
675
687
  pressMode?: 'auto' | 'dom' | 'keyboard';
@@ -760,7 +772,7 @@ export interface SetCookieResult {
760
772
  path: string;
761
773
  reloaded: boolean;
762
774
  }
763
- export interface RequestDomainPermissionParams {
775
+ export interface RequestPermissionParams {
764
776
  domain: string;
765
777
  }
766
778
  export type RunActionName = Exclude<ExtensionBrowserAction, 'run_actions' | 'browser_release' | 'get_capabilities'>;
@@ -818,12 +830,8 @@ export interface BrowserActionMap {
818
830
  request: SendRequestParams;
819
831
  response: unknown;
820
832
  };
821
- send_mtop_request: {
822
- request: SendMtopRequestParams;
823
- response: unknown;
824
- };
825
833
  browser_list: {
826
- request: undefined;
834
+ request: BrowserListParams | undefined;
827
835
  response: BrowserListResult;
828
836
  };
829
837
  browser_select_browser: {
@@ -948,8 +956,8 @@ export interface BrowserActionMap {
948
956
  request: SetCookieParams;
949
957
  response: SetCookieResult;
950
958
  };
951
- request_domain_permission: {
952
- request: RequestDomainPermissionParams;
959
+ request_permission: {
960
+ request: RequestPermissionParams;
953
961
  response: unknown;
954
962
  };
955
963
  run_actions: {
@@ -983,7 +991,6 @@ export declare const BROWSER_ACTIONS: {
983
991
  readonly get_rules: true;
984
992
  readonly get_capabilities: true;
985
993
  readonly send_request: true;
986
- readonly send_mtop_request: true;
987
994
  readonly browser_list: true;
988
995
  readonly browser_select_browser: true;
989
996
  readonly browser_release: true;
@@ -1015,7 +1022,7 @@ export declare const BROWSER_ACTIONS: {
1015
1022
  readonly set_timezone: true;
1016
1023
  readonly get_cookie: true;
1017
1024
  readonly set_cookie: true;
1018
- readonly request_domain_permission: true;
1025
+ readonly request_permission: true;
1019
1026
  readonly run_actions: true;
1020
1027
  };
1021
1028
  export declare const BROWSER_COMMAND_ACTIONS: {
@@ -1030,7 +1037,6 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1030
1037
  readonly get_rules: true;
1031
1038
  readonly get_capabilities: true;
1032
1039
  readonly send_request: true;
1033
- readonly send_mtop_request: true;
1034
1040
  readonly browser_list: true;
1035
1041
  readonly browser_release: true;
1036
1042
  readonly browser_control: true;
@@ -1061,7 +1067,7 @@ export declare const BROWSER_COMMAND_ACTIONS: {
1061
1067
  readonly set_timezone: true;
1062
1068
  readonly get_cookie: true;
1063
1069
  readonly set_cookie: true;
1064
- readonly request_domain_permission: true;
1070
+ readonly request_permission: true;
1065
1071
  readonly run_actions: true;
1066
1072
  };
1067
1073
  export declare const EXTENSION_BROWSER_ACTIONS: {
@@ -1076,7 +1082,6 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1076
1082
  readonly get_rules: true;
1077
1083
  readonly get_capabilities: true;
1078
1084
  readonly send_request: true;
1079
- readonly send_mtop_request: true;
1080
1085
  readonly browser_release: true;
1081
1086
  readonly page_screenshot: true;
1082
1087
  readonly tab_open: true;
@@ -1102,7 +1107,7 @@ export declare const EXTENSION_BROWSER_ACTIONS: {
1102
1107
  readonly set_timezone: true;
1103
1108
  readonly get_cookie: true;
1104
1109
  readonly set_cookie: true;
1105
- readonly request_domain_permission: true;
1110
+ readonly request_permission: true;
1106
1111
  readonly run_actions: true;
1107
1112
  };
1108
1113
  export declare const BROWSER_CAPABILITY_ACTIONS: {
@@ -1118,7 +1123,6 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1118
1123
  readonly get_rules: true;
1119
1124
  readonly get_capabilities: true;
1120
1125
  readonly send_request: true;
1121
- readonly send_mtop_request: true;
1122
1126
  readonly browser_release: true;
1123
1127
  readonly page_screenshot: true;
1124
1128
  readonly tab_open: true;
@@ -1144,7 +1148,7 @@ export declare const BROWSER_CAPABILITY_ACTIONS: {
1144
1148
  readonly set_timezone: true;
1145
1149
  readonly get_cookie: true;
1146
1150
  readonly set_cookie: true;
1147
- readonly request_domain_permission: true;
1151
+ readonly request_permission: true;
1148
1152
  readonly run_actions: true;
1149
1153
  };
1150
1154
  export declare function isBrowserAction(value: unknown): value is BrowserAction;
@@ -122,7 +122,6 @@ export const BROWSER_ACTIONS = {
122
122
  get_rules: true,
123
123
  get_capabilities: true,
124
124
  send_request: true,
125
- send_mtop_request: true,
126
125
  browser_list: true,
127
126
  browser_select_browser: true,
128
127
  browser_release: true,
@@ -154,7 +153,7 @@ export const BROWSER_ACTIONS = {
154
153
  set_timezone: true,
155
154
  get_cookie: true,
156
155
  set_cookie: true,
157
- request_domain_permission: true,
156
+ request_permission: true,
158
157
  run_actions: true,
159
158
  };
160
159
  export const BROWSER_COMMAND_ACTIONS = {
@@ -169,7 +168,6 @@ export const BROWSER_COMMAND_ACTIONS = {
169
168
  get_rules: true,
170
169
  get_capabilities: true,
171
170
  send_request: true,
172
- send_mtop_request: true,
173
171
  browser_list: true,
174
172
  browser_release: true,
175
173
  browser_control: true,
@@ -200,7 +198,7 @@ export const BROWSER_COMMAND_ACTIONS = {
200
198
  set_timezone: true,
201
199
  get_cookie: true,
202
200
  set_cookie: true,
203
- request_domain_permission: true,
201
+ request_permission: true,
204
202
  run_actions: true,
205
203
  };
206
204
  export const EXTENSION_BROWSER_ACTIONS = {
@@ -215,7 +213,6 @@ export const EXTENSION_BROWSER_ACTIONS = {
215
213
  get_rules: true,
216
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 = {
@@ -42,4 +42,6 @@ export declare function describeBrowserCapabilities(actions: readonly string[],
42
42
  error: string;
43
43
  }>;
44
44
  offline?: boolean;
45
+ } | {
46
+ apps: BrowserCapabilityCatalog['apps'];
45
47
  } | undefined, params?: GetCapabilitiesParams): BrowserCapabilityCatalog;
@@ -5,15 +5,29 @@ export function describeBrowserCapabilities(actions, catalog, params = {}) {
5
5
  throw new Error('Invalid capability query');
6
6
  if (params.app !== undefined && (typeof params.app !== 'string' || !params.app || params.app.length > 161))
7
7
  throw new Error('Invalid App capability ID');
8
- if (params.app && catalog && !catalog.offline && !catalog.errors.length && !catalog.profiles.some(entry => entry.id === params.app))
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))
9
13
  throw new Error(`App profile is not installed: ${params.app}`);
10
14
  const supportsApps = actions.includes('set_app_profile');
11
- const profiles = supportsApps ? catalog?.profiles ?? [] : [];
15
+ const profiles = supportsApps ? installed?.profiles ?? [] : [];
12
16
  return {
13
17
  actions: [...new Set(actions)],
14
18
  devicePresets: actions.includes('set_device_emulation') ? [...BROWSER_DEVICE_PRESET_NAMES] : [],
15
- apps: {
16
- status: !supportsApps || !catalog ? 'unsupported' : catalog.offline || catalog.errors.length || profiles.some(entry => entry.available === false) ? 'partial' : 'available',
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',
17
31
  entries: profiles.filter(entry => !params.app || entry.id === params.app).map(entry => {
18
32
  const definition = entry.definition;
19
33
  const methods = {};
@@ -36,7 +50,7 @@ export function describeBrowserCapabilities(actions, catalog, params = {}) {
36
50
  } } : {}),
37
51
  };
38
52
  }),
39
- issues: catalog?.errors.map(issue => ({ ...issue })) ?? [],
53
+ issues: (installed?.errors ?? projected?.issues)?.map(({ plugin, error }) => ({ plugin, error })) ?? [],
40
54
  },
41
55
  limitations: [
42
56
  'Actions describe support, not current domain permissions, login state or device connectivity.',
@@ -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
+ }