@mearl/browser-core 3.0.0-beta.1 → 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 (54) 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 +8 -0
  35. package/dist/index.js +8 -0
  36. package/dist/pageAct.d.ts +2 -0
  37. package/dist/pageAct.js +42 -10
  38. package/dist/pageDialog.d.ts +66 -0
  39. package/dist/pageDialog.js +175 -0
  40. package/dist/pageObserver.js +16 -5
  41. package/dist/pagePressing.d.ts +1 -1
  42. package/dist/pluginPageHost.js +2 -2
  43. package/dist/providerAppResources.d.ts +39 -0
  44. package/dist/providerAppResources.js +2 -0
  45. package/dist/proxyPermissions.js +3 -3
  46. package/dist/requestMetadata.d.ts +9 -0
  47. package/dist/requestMetadata.js +8 -0
  48. package/dist/requestSerializer.d.ts +2 -2
  49. package/dist/requestSerializer.js +1 -29
  50. package/dist/requestStreamCapture.d.ts +5 -3
  51. package/dist/requestStreamCapture.js +2 -0
  52. package/dist/runActions.js +1 -1
  53. package/dist/types.d.ts +4 -2
  54. package/package.json +2 -2
package/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # @mearl/browser-core
2
2
 
3
- 浏览器与 Node 可共享的页面控制逻辑和协议:DOM/AX 快照、动作观察、输入、滚动、导航、请求序列化、捕获游标、设备模拟、通用设备外观、Cookie/域名权限和插件任务、页面、状态合同。模块没有浏览器扩展或本机进程的安装副作用。
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
4
 
5
- `APP_PROFILE_NAMES` 只列出飞猪、淘宝、微信、支付宝四个基础身份;动态档案 ID 由宿主的已激活能力目录校验。App 档案 schema、显式选项、revision 和页面运行时绑定是数据合同,完整桥实现由独立能力包提供。
5
+ Page control logic and protocols shared by browsers and Node: DOM/AX snapshots, action observation, input, scrolling, navigation, request serialization, capture cursors, device simulation, generic device appearance, Cookie/domain permissions, and plugin task, page, and state contracts. Modules have no browser extension or native process installation side effects.
6
6
 
7
- `@mearl/browser-core/appProfileRuntime` 的内置安装器只同步 UA、navigator.appVersion、navigator.platform 和触摸点,不安装 App 桥、业务全局变量、容器栈或授权处理。有 pageRuntime 绑定时,宿主必须先从已安装的能力包准备确切代码,再通过页面运行时派发器执行;不能调用基础安装器代替。资源准备和派发见 [能力包](../../docs/browser-bundles.md#页面运行时)。
7
+ The core includes no preset App identities. The host validates profile IDs against its active capability catalog. App profile schemas, explicit options, revisions, and page runtime bindings are data contracts; independent capability packages supply complete bridge implementations.
8
8
 
9
- 默认代理授权地址只有 localhost 与 127.0.0.1。其余站点由宿主取得权限后传入授权列表;组织域名和员工身份不属于本包默认值。业务请求辅助、业务事件解析、测试账号登录及用户 Cookie 身份推导留在独立能力中。
9
+ The built-in installer at `@mearl/browser-core/appProfileRuntime` synchronizes only UA, navigator.appVersion, navigator.platform, and touch points. It does not install App bridges, business globals, container stacks, or authorization handlers. With a pageRuntime binding, the host must prepare the exact code from the installed capability package and execute it through the page runtime dispatcher; the base installer cannot substitute for this. See [browser bundles](../../docs/browser-bundles.md#page-runtimes) for resource preparation and dispatch.
10
10
 
11
- Agent 合同源在本包的 agentChat.ts、agentSkills.ts 和 pluginModels.ts;分别通过同名子路径导出,agent-runtime 使用这些合同,避免并行维护副本。可序列化的页面函数保持自包含,便于 Extension 与 CDP 共同使用。
11
+ The default proxy authorization addresses are localhost and 127.0.0.1. Hosts obtain permission for other sites and pass them in the authorization list. The core includes Aplus/RUM/ARMS event parsers; additional parsers register through capability packages.
12
+
13
+ Agent contracts are defined in agentChat.ts, agentSkills.ts, and pluginModels.ts and exported through the corresponding subpaths. agent-runtime uses these contracts to avoid duplicate definitions. Serializable page functions remain self-contained for shared use by the Extension and CDP.
@@ -0,0 +1,13 @@
1
+ # @mearl/browser-core
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ 浏览器与 Node 可共享的页面控制逻辑和协议:DOM/AX 快照、动作观察、输入、滚动、导航、请求序列化、捕获游标、设备模拟、通用设备外观、Cookie/域名权限和插件任务、页面、状态合同。模块没有浏览器扩展或本机进程的安装副作用。
6
+
7
+ 核心不预置 App 身份;档案 ID 由宿主的已激活能力目录校验。App 档案 schema、显式选项、revision 和页面运行时绑定是数据合同,完整桥实现由独立能力包提供。
8
+
9
+ `@mearl/browser-core/appProfileRuntime` 的内置安装器只同步 UA、navigator.appVersion、navigator.platform 和触摸点,不安装 App 桥、业务全局变量、容器栈或授权处理。有 pageRuntime 绑定时,宿主必须先从已安装的能力包准备确切代码,再通过页面运行时派发器执行;不能调用基础安装器代替。资源准备和派发见 [能力包](../../docs/browser-bundles.zh-CN.md#页面运行时)。
10
+
11
+ 默认代理授权地址为 localhost 与 127.0.0.1。其余站点由宿主取得权限后传入授权列表。核心内置 Aplus/RUM/ARMS 事件解析;扩展解析器通过能力包注册。
12
+
13
+ Agent 合同源在本包的 agentChat.ts、agentSkills.ts 和 pluginModels.ts;分别通过同名子路径导出,agent-runtime 使用这些合同,避免并行维护副本。可序列化的页面函数保持自包含,便于 Extension 与 CDP 共同使用。
@@ -1,5 +1,7 @@
1
1
  export type AgentChatEventKind = 'lifecycle' | 'notification' | 'request' | 'error';
2
2
  export type AgentChatSessionStatus = 'idle' | 'running' | 'waiting' | 'error';
3
+ export declare function isQoderAuthenticationError(message: unknown): boolean;
4
+ export declare function isQoderMissingSessionError(message: unknown): boolean;
3
5
  export type AgentChatCapabilitySupport = boolean | 'runtime';
4
6
  export declare const AGENT_CHAT_MAX_PAGE_URL_CHARS = 16384;
5
7
  export declare const AGENT_CHAT_MAX_PAGE_TITLE_CHARS = 2048;
@@ -15,6 +17,8 @@ export interface AgentChatProviderDescriptor {
15
17
  id: string;
16
18
  name: string;
17
19
  available: boolean;
20
+ /** False while accepted conversations retain a removed or superseded runtime. */
21
+ acceptsNewSessions?: boolean;
18
22
  capabilities: {
19
23
  streaming: boolean;
20
24
  resume: boolean;
@@ -26,7 +30,8 @@ export interface AgentChatProviderDescriptor {
26
30
  };
27
31
  error?: string;
28
32
  setup?: {
29
- installCommand: string;
33
+ installCommand?: string;
34
+ canInstall?: boolean;
30
35
  loginCommand?: string;
31
36
  docsUrl?: string;
32
37
  };
@@ -89,6 +94,7 @@ export interface AgentChatSendOptions {
89
94
  message: string;
90
95
  images?: AgentChatImageInput[];
91
96
  displayMessage?: string;
97
+ hasAdditionalContext?: boolean;
92
98
  clientMessageId?: string;
93
99
  }
94
100
  export interface AgentChatRunOptions {
@@ -155,6 +161,9 @@ export interface AgentChatStatus {
155
161
  sessions: AgentChatSession[];
156
162
  }
157
163
  export interface AgentChatKnownEventParams {
164
+ 'session/reconnected': {
165
+ providerSessionId: string;
166
+ };
158
167
  'turn/started': {
159
168
  turn: {
160
169
  id: string;
package/dist/agentChat.js CHANGED
@@ -1,3 +1,10 @@
1
+ export function isQoderAuthenticationError(message) {
2
+ return (typeof message === 'string' &&
3
+ /^(?:Authentication (?:is )?required|Unauthenticated|Sign-in required)(?:[:.\s]|$)/i.test(message));
4
+ }
5
+ export function isQoderMissingSessionError(message) {
6
+ return typeof message === 'string' && /^(?:Invalid params:\s*)?Invalid session identifier\b/i.test(message);
7
+ }
1
8
  export const AGENT_CHAT_MAX_PAGE_URL_CHARS = 16_384;
2
9
  export const AGENT_CHAT_MAX_PAGE_TITLE_CHARS = 2_048;
3
10
  export const AGENT_CHAT_MAX_TOOLBOX_CONTEXT_CHARS = 65_536;
@@ -123,6 +130,7 @@ function readAgentChatRequestParams(params) {
123
130
  return { ...params, requestId: params.requestId };
124
131
  }
125
132
  const AGENT_CHAT_EVENT_PARAM_READERS = {
133
+ 'session/reconnected': params => typeof params.providerSessionId === 'string' ? { providerSessionId: params.providerSessionId } : null,
126
134
  'turn/started': readAgentChatTurnParams,
127
135
  'turn/completed': readAgentChatTurnParams,
128
136
  'session/model/updated': readAgentChatModelParams,
@@ -11,6 +11,18 @@ export interface AgentServiceActionMap {
11
11
  request: undefined;
12
12
  response: AgentChatStatus;
13
13
  };
14
+ agent_chat_install_provider: {
15
+ request: {
16
+ providerId: string;
17
+ };
18
+ response: AgentChatStatus;
19
+ };
20
+ agent_chat_login_qoder: {
21
+ request: undefined;
22
+ response: {
23
+ url: string | null;
24
+ };
25
+ };
14
26
  agent_chat_prepare: {
15
27
  request: AgentChatPrepareOptions;
16
28
  response: {
@@ -51,6 +63,14 @@ export interface AgentServiceActionMap {
51
63
  request: AgentChatEventsOptions;
52
64
  response: AgentChatEventsResult;
53
65
  };
66
+ agent_chat_read_visualization: {
67
+ request: {
68
+ path: string;
69
+ };
70
+ response: {
71
+ html: string;
72
+ };
73
+ };
54
74
  agent_chat_refresh: {
55
75
  request: AgentChatEventsOptions;
56
76
  response: AgentChatRefreshResult;
@@ -112,6 +132,8 @@ export type AgentServiceHandlerMap = {
112
132
  export declare const AGENT_SERVICE_ACTIONS: {
113
133
  readonly agent_chat_pick_directory: true;
114
134
  readonly agent_chat_status: true;
135
+ readonly agent_chat_install_provider: true;
136
+ readonly agent_chat_login_qoder: true;
115
137
  readonly agent_chat_prepare: true;
116
138
  readonly agent_chat_list_sessions: true;
117
139
  readonly agent_chat_start: true;
@@ -120,6 +142,7 @@ export declare const AGENT_SERVICE_ACTIONS: {
120
142
  readonly agent_chat_interrupt: true;
121
143
  readonly agent_chat_close: true;
122
144
  readonly agent_chat_events: true;
145
+ readonly agent_chat_read_visualization: true;
123
146
  readonly agent_chat_refresh: true;
124
147
  readonly agent_chat_open_app: true;
125
148
  readonly agent_chat_open_workspace: true;
@@ -1,6 +1,8 @@
1
1
  export const AGENT_SERVICE_ACTIONS = {
2
2
  agent_chat_pick_directory: true,
3
3
  agent_chat_status: true,
4
+ agent_chat_install_provider: true,
5
+ agent_chat_login_qoder: true,
4
6
  agent_chat_prepare: true,
5
7
  agent_chat_list_sessions: true,
6
8
  agent_chat_start: true,
@@ -9,6 +11,7 @@ export const AGENT_SERVICE_ACTIONS = {
9
11
  agent_chat_interrupt: true,
10
12
  agent_chat_close: true,
11
13
  agent_chat_events: true,
14
+ agent_chat_read_visualization: true,
12
15
  agent_chat_refresh: true,
13
16
  agent_chat_open_app: true,
14
17
  agent_chat_open_workspace: true,
@@ -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 {
@@ -2,15 +2,16 @@ import type { AppProfileBinding, AppProfilePolicies, AppProfileSetting } from '.
2
2
  import type { BrowserDevicePresetName } from '../browserActionProtocol.js';
3
3
  import type { DeviceCutout } from '../deviceEmulation.js';
4
4
  /** 桥调用风格,与页面适配器使用的端内调用约定一一对应。 */
5
- export type AppBridgeStyle = 'windvane' | 'fliggy' | 'alipay' | 'callback' | 'btrip' | 'invoke' | 'callHandler' | 'amap' | 'didi' | 'easybikeNative' | 'mega' | 'wechat' | 'wechatMiniProgram';
5
+ export type AppBridgeStyle = string;
6
6
  export interface AppBridgeSpec {
7
7
  global: string;
8
8
  style: AppBridgeStyle;
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';
13
- /** 桥方法名到标准化动作的映射。WindVane 风格使用 `Class.method`,其余使用 api 名。 */
12
+ /** Provider-defined identifier, interpreted by its installed page runtime. */
13
+ export type AppBridgeBehavior = string;
14
+ /** 桥方法名到标准化动作的映射。命名空间桥使用 `Class.method`,其余使用 api 名。 */
14
15
  export interface BridgeActionMap {
15
16
  open: string[];
16
17
  close: 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[];
@@ -68,14 +69,14 @@ export interface AppMiniProgramMessageRule {
68
69
  }
69
70
  export type AppMiniProgramNativeAction = 'navigateMiniProgram' | 'subscribeMessage';
70
71
  export interface AppMiniProgramNativeRoute {
71
- /** 承接微信原生能力的小程序页面 pathname。 */
72
+ /** 承接原生能力的小程序页面 pathname。 */
72
73
  pathname: string;
73
74
  /** 该页面允许模拟的固定原生动作,动作名读取 URL 的 action 参数。 */
74
75
  actions: AppMiniProgramNativeAction[];
75
76
  /** 限制业务根域,避免其他小程序的同名页面被接管。 */
76
77
  hostSuffixes?: string[];
77
78
  }
78
- /** 微信小程序容器相关规则统一收口,避免为每种业务页增加顶层配置。 */
79
+ /** 小程序容器相关规则统一收口,避免为每种业务页增加顶层配置。 */
79
80
  export interface AppMiniProgramConfig {
80
81
  paymentRoutes?: AppMiniProgramPaymentRoute[];
81
82
  nativeRoutes?: AppMiniProgramNativeRoute[];
@@ -187,6 +188,8 @@ export interface InjectedAppProfileConfig {
187
188
  binding?: AppProfileBinding;
188
189
  policies?: AppProfilePolicies;
189
190
  settings?: AppProfileSetting[];
191
+ settingsUi?: 'runtime';
192
+ settingsGroup?: string;
190
193
  profile: string;
191
194
  label: string;
192
195
  globals: Record<string, string>;
@@ -207,11 +210,6 @@ export interface InjectedAppProfileConfig {
207
210
  schemes: AppSchemeRule[];
208
211
  miniProgram?: AppMiniProgramConfig;
209
212
  imagePicker?: AppImagePickerConfig;
210
- /** 原生定位返回地址时使用的逆地理编码服务,复用容器的 MTop 传输。 */
211
- geolocation?: {
212
- reverseGeocodeApi: string;
213
- version: string;
214
- };
215
213
  overlay?: AppOverlayConfig;
216
214
  /** URL 参数为真时以新 WebView 替换当前业务层。 */
217
215
  popBeforeOpenParam?: string;
@@ -221,7 +219,7 @@ export interface InjectedAppProfileConfig {
221
219
  layerUrlProxy?: AppLayerUrlProxyConfig;
222
220
  urlSyncHostSuffixes?: string[];
223
221
  animationMs?: number;
224
- forceH5Mtop?: boolean;
222
+ runtimeOptions?: Record<string, unknown>;
225
223
  titleBar?: AppTitleBarConfig;
226
224
  rootContainer?: AppRootContainerConfig;
227
225
  simulateSystemBars?: boolean;
@@ -1,9 +1,9 @@
1
1
  import type { BrowserDevicePresetName, AppBridgeConfig } from './browserActionProtocol.js';
2
2
  import type { AppBridgeSpec, AppImagePickerConfig, AppLayerUrlProxyConfig, AppMiniProgramConfig, AppNativeBackConfig, AppOverlayConfig, AppSchemeRule, AppTitleBarHostStyle, BridgeActionMap } from './app-profile-runtime/types.js';
3
3
  export interface AppProfilePolicies {
4
- titleBar?: 'default' | 'taobao' | 'fliggy' | 'alipay' | 'wechat';
4
+ titleBar?: string;
5
5
  navigatorLanguage?: boolean;
6
- networkResult?: 'default' | 'alipay';
6
+ networkResult?: string;
7
7
  languages?: string[];
8
8
  defaultLanguage?: string;
9
9
  }
@@ -56,28 +56,49 @@ export interface AppProfileCatalogEntry {
56
56
  revision: string;
57
57
  definition: AppProfileDefinition;
58
58
  }
59
+ /** Short, author-supplied guidance; discovery does not load Skills or follow links. */
60
+ export interface AppProfileUsage {
61
+ description?: string;
62
+ limitations?: string[];
63
+ skills?: string[];
64
+ documentation?: Array<{
65
+ title: string;
66
+ url: string;
67
+ }>;
68
+ }
59
69
  /** 单容器档案(纯数据) */
60
70
  export interface AppProfileDefinition {
61
71
  name: string;
72
+ usage?: AppProfileUsage;
62
73
  /** Content-addressed installer supplied by the selected browser capability package. */
63
74
  pageRuntime?: {
64
75
  id: string;
65
76
  sha256: string;
66
77
  };
67
78
  label: string;
68
- /** 容器的应用标识,如 LX / TB / AP / WeChat */
79
+ actionIcon?: string;
80
+ labels?: {
81
+ en: string;
82
+ zh_CN?: string;
83
+ };
84
+ /** 容器的应用标识,由能力包定义 */
69
85
  appName: string;
70
86
  defaultAppVersion: string;
71
- /** UA 主体格式;默认使用 AliApp(appName/version) */
72
- uaFamily?: 'aliapp' | 'wechatMiniProgram';
87
+ /** UA 主体格式;未提供时使用标准浏览器 UA */
88
+ uaFamily?: string;
73
89
  uaTemplate?: {
74
90
  ios: string;
75
91
  android: string;
76
92
  };
77
93
  policies?: AppProfilePolicies;
78
94
  settings?: AppProfileSetting[];
79
- settingsGroup?: 'fliggy' | 'alipay';
80
- /** AliApp UA 主体之后追加的 token,{v} 占位会被替换为 appVersion */
95
+ authorization?: {
96
+ hook: string;
97
+ method: string;
98
+ };
99
+ settingsUi?: 'runtime';
100
+ settingsGroup?: string;
101
+ /** UA 主体之后追加的 token,{v} 占位会被替换为 appVersion */
81
102
  uaTokens: string[];
82
103
  /** 额外注入到 window 的变量(公共变量由 resolve 统一生成) */
83
104
  globals: Record<string, string>;
@@ -90,10 +111,6 @@ export interface AppProfileDefinition {
90
111
  miniProgram?: AppMiniProgramConfig;
91
112
  /** 原生图片页 scheme 的浏览器选图与上传配置 */
92
113
  imagePicker?: AppImagePickerConfig;
93
- geolocation?: {
94
- reverseGeocodeApi: string;
95
- version: string;
96
- };
97
114
  /**
98
115
  * 地址栏借位同步的可选 host 白名单:容器栈顶 URL 的 host 命中时,地址栏借 top
99
116
  * 域名同步其 path+query+hash(pushState 同源约束下保持域名不变只改 path);
@@ -124,10 +141,11 @@ export interface AppProfileDefinition {
124
141
  statusBarBackgroundColors?: Record<string, string>;
125
142
  /** 按业务根域配置标题栏与状态栏样式。 */
126
143
  titleBarHostStyles?: AppTitleBarHostStyle[];
127
- /** 桥存在时仍将 MTOP 传输固定在浏览器 H5 通道 */
128
- forceH5Mtop?: boolean;
144
+ /** Opaque configuration owned by the installed page runtime. */
145
+ runtimeOptions?: Record<string, unknown>;
129
146
  }
130
- 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;
131
149
  /** Validate plain data before registration or compiling a document-start configuration. */
132
150
  export declare function validateAppProfileDefinition(value: unknown): AppProfileDefinition;
133
151
  export declare function validateAppProfileContribution(value: unknown): AppProfileContribution | undefined;
@@ -1,57 +1,7 @@
1
- const BRIDGE_STYLES = new Set([
2
- 'windvane',
3
- 'fliggy',
4
- 'alipay',
5
- 'callback',
6
- 'btrip',
7
- 'invoke',
8
- 'callHandler',
9
- 'amap',
10
- 'didi',
11
- 'easybikeNative',
12
- 'mega',
13
- 'wechat',
14
- 'wechatMiniProgram',
15
- ]);
16
- export const APP_BRIDGE_BEHAVIORS = [
17
- 'navigate',
18
- 'closeAll',
19
- 'closeBackData',
20
- 'postMessage',
21
- 'notifySubscribe',
22
- 'notifyUnsubscribe',
23
- 'notifyPost',
24
- 'sharedFileRead',
25
- 'sharedFileWrite',
26
- 'sharedDataGet',
27
- 'sharedDataSet',
28
- 'legacyBroadcastCreate',
29
- 'legacyBroadcastPost',
30
- 'legacyBroadcastClose',
31
- 'memoryGet',
32
- 'memorySet',
33
- 'memoryDelete',
34
- 'availabilityMap',
35
- 'userInfo',
36
- 'authCode',
37
- 'networkInfo',
38
- 'geolocation',
39
- 'permission',
40
- 'imagePicker',
41
- 'prefetch',
42
- 'fptTrack',
43
- 'mtopStream',
44
- 'previewFile',
45
- 'toast',
46
- 'unsupportedNativeInput',
47
- 'payment',
48
- 'userTrack',
49
- 'calendar',
50
- 'networkQualityMonitor',
51
- 'beaconRequest',
52
- 'voiceRecognition',
53
- ];
54
- 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
+ }
55
5
  function record(value) {
56
6
  return value !== null && typeof value === 'object' && !Array.isArray(value);
57
7
  }
@@ -95,7 +45,7 @@ function validateActions(value) {
95
45
  'navigationBar',
96
46
  'statusBar',
97
47
  'systemInfo',
98
- 'mtop',
48
+ 'protocol',
99
49
  'kvGet',
100
50
  'kvSet',
101
51
  'kvDelete',
@@ -103,7 +53,7 @@ function validateActions(value) {
103
53
  'noop',
104
54
  'silent',
105
55
  ];
106
- 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');
107
57
  for (const key of arrays)
108
58
  if (value[key] !== undefined && !strings(value[key]))
109
59
  invalid(`actions.${key}`);
@@ -111,7 +61,7 @@ function validateActions(value) {
111
61
  invalid('actions.responses');
112
62
  if (value.behaviors !== undefined &&
113
63
  (!stringMap(value.behaviors) ||
114
- !Object.values(value.behaviors).every(item => BEHAVIORS.has(item))))
64
+ !Object.values(value.behaviors).every(item => isAppBridgeBehavior(item))))
115
65
  invalid('actions.behaviors');
116
66
  }
117
67
  /** Validate plain data before registration or compiling a document-start configuration. */
@@ -133,15 +83,19 @@ export function validateAppProfileDefinition(value) {
133
83
  'schemes',
134
84
  ];
135
85
  const optional = [
86
+ 'usage',
87
+ 'actionIcon',
88
+ 'labels',
136
89
  'pageRuntime',
137
90
  'uaFamily',
138
91
  'uaTemplate',
139
92
  'policies',
140
93
  'settings',
141
94
  'settingsGroup',
95
+ 'settingsUi',
96
+ 'authorization',
142
97
  'miniProgram',
143
98
  'imagePicker',
144
- 'geolocation',
145
99
  'urlSyncHostSuffixes',
146
100
  'overlay',
147
101
  'popBeforeOpenParam',
@@ -152,7 +106,7 @@ export function validateAppProfileDefinition(value) {
152
106
  'titleBarHiddenPathnames',
153
107
  'statusBarBackgroundColors',
154
108
  'titleBarHostStyles',
155
- 'forceH5Mtop',
109
+ 'runtimeOptions',
156
110
  ];
157
111
  fields(value, required, optional, 'definition');
158
112
  for (const key of ['name', 'label', 'appName', 'defaultAppVersion'])
@@ -160,6 +114,37 @@ export function validateAppProfileDefinition(value) {
160
114
  invalid(key);
161
115
  if (!/^[a-z][a-z0-9-]*(?:\/[a-z][a-z0-9-]*)?$/.test(value.name))
162
116
  invalid('name');
117
+ if (value.usage !== undefined) {
118
+ const usage = value.usage;
119
+ fields(usage, [], ['description', 'limitations', 'skills', 'documentation'], 'usage');
120
+ if (new TextEncoder().encode(JSON.stringify(usage)).byteLength > 4096)
121
+ invalid('usage exceeds 4 KiB');
122
+ if (usage.description !== undefined && (!text(usage.description) || usage.description.length > 512))
123
+ invalid('usage.description');
124
+ for (const key of ['limitations', 'skills']) {
125
+ const items = usage[key];
126
+ if (items !== undefined && (!Array.isArray(items) || items.length > 8 || items.some(item => !text(item) || !item || item.length > 256)))
127
+ invalid(`usage.${key}`);
128
+ }
129
+ if (usage.documentation !== undefined) {
130
+ if (!Array.isArray(usage.documentation) || usage.documentation.length > 8)
131
+ invalid('usage.documentation');
132
+ for (const link of usage.documentation) {
133
+ fields(link, ['title', 'url'], [], 'usage.documentation');
134
+ if (!text(link.title) || !link.title || link.title.length > 128 || !text(link.url) || link.url.length > 1024)
135
+ invalid('usage.documentation');
136
+ let url;
137
+ try {
138
+ url = new URL(link.url);
139
+ }
140
+ catch {
141
+ invalid('usage.documentation.url');
142
+ }
143
+ if (url.protocol !== 'https:' || url.username || url.password)
144
+ invalid('usage.documentation.url');
145
+ }
146
+ }
147
+ }
163
148
  if (value.pageRuntime !== undefined) {
164
149
  fields(value.pageRuntime, ['id', 'sha256'], [], 'pageRuntime');
165
150
  const runtime = value.pageRuntime;
@@ -191,17 +176,28 @@ export function validateAppProfileDefinition(value) {
191
176
  .split('.')
192
177
  .some(part => ['__proto__', 'prototype', 'constructor'].includes(part)) ||
193
178
  globals.has(bridge.global) ||
194
- !BRIDGE_STYLES.has(bridge.style) ||
179
+ (typeof bridge.style !== 'string' || !/^[a-zA-Z][a-zA-Z0-9-]{0,63}$/.test(bridge.style)) ||
195
180
  (bridge.persistent !== undefined && typeof bridge.persistent !== 'boolean'))
196
181
  invalid('bridge');
197
182
  globals.add(bridge.global);
198
183
  }
199
184
  validateActions(value.actions);
185
+ if (value.labels !== undefined) {
186
+ fields(value.labels, ['en'], ['zh_CN'], 'labels');
187
+ if (!text(value.labels.en) || !value.labels.en || value.labels.en.length > 120 || value.labels.zh_CN !== undefined && (!text(value.labels.zh_CN) || value.labels.zh_CN.length > 120))
188
+ invalid('labels');
189
+ }
190
+ if (value.actionIcon !== undefined && (typeof value.actionIcon !== 'string' || value.actionIcon.length > 32768 || !/^data:image\/png;base64,iVBORw0KGgo[A-Za-z0-9+/]*={0,2}$/.test(value.actionIcon)))
191
+ invalid('actionIcon');
192
+ if (value.authorization !== undefined && (!record(value.authorization) || Object.keys(value.authorization).sort().join(',') !== 'hook,method' || typeof value.authorization.hook !== 'string' || !/^[a-z][a-zA-Z0-9_.-]{0,95}$/.test(value.authorization.hook) || typeof value.authorization.method !== 'string' || !value.authorization.method || value.authorization.method.length > 200))
193
+ invalid('authorization');
194
+ if (value.settingsUi !== undefined && value.settingsUi !== 'runtime')
195
+ throw new Error('Invalid App settings UI');
200
196
  if (value.settingsGroup !== undefined &&
201
- !['fliggy', 'alipay'].includes(value.settingsGroup))
197
+ (typeof value.settingsGroup !== 'string' || value.settingsGroup.length > 64))
202
198
  invalid('settingsGroup');
203
199
  if (value.uaFamily !== undefined &&
204
- !['aliapp', 'wechatMiniProgram'].includes(value.uaFamily))
200
+ (typeof value.uaFamily !== 'string' || value.uaFamily.length > 64))
205
201
  invalid('uaFamily');
206
202
  if (value.uaTemplate !== undefined) {
207
203
  fields(value.uaTemplate, ['ios', 'android'], [], 'uaTemplate');
@@ -212,9 +208,9 @@ export function validateAppProfileDefinition(value) {
212
208
  fields(value.policies, [], ['titleBar', 'navigatorLanguage', 'networkResult', 'languages', 'defaultLanguage'], 'policies');
213
209
  const p = value.policies;
214
210
  if (p.titleBar !== undefined &&
215
- !['default', 'taobao', 'fliggy', 'alipay', 'wechat'].includes(p.titleBar))
211
+ (typeof p.titleBar !== 'string' || p.titleBar.length > 64))
216
212
  invalid('policies.titleBar');
217
- if (p.networkResult !== undefined && !['default', 'alipay'].includes(p.networkResult))
213
+ if (p.networkResult !== undefined && (typeof p.networkResult !== 'string' || p.networkResult.length > 64))
218
214
  invalid('policies.networkResult');
219
215
  if (p.navigatorLanguage !== undefined && typeof p.navigatorLanguage !== 'boolean')
220
216
  invalid('policies.navigatorLanguage');
@@ -281,7 +277,7 @@ export function validateAppProfileDefinition(value) {
281
277
  'navigationBar',
282
278
  'statusBar',
283
279
  'systemInfo',
284
- 'mtop',
280
+ 'protocol',
285
281
  'kvGet',
286
282
  'kvSet',
287
283
  'kvDelete',
@@ -307,9 +303,8 @@ export function validateAppProfileDefinition(value) {
307
303
  invalid('setting.option type');
308
304
  }
309
305
  }
310
- for (const key of ['forceH5Mtop'])
311
- if (value[key] !== undefined && typeof value[key] !== 'boolean')
312
- invalid(key);
306
+ if (value.runtimeOptions !== undefined && (!record(value.runtimeOptions) || !json(value.runtimeOptions)))
307
+ invalid('runtimeOptions');
313
308
  for (const key of ['popBeforeOpenParam', 'messageEvent'])
314
309
  if (value[key] !== undefined && !text(value[key]))
315
310
  invalid(key);
@@ -321,7 +316,6 @@ export function validateAppProfileDefinition(value) {
321
316
  function validateStructuredOptions(value) {
322
317
  const shapes = {
323
318
  nativeBack: [[], ['event', 'controlFunction', 'handler']],
324
- geolocation: [['reverseGeocodeApi', 'version'], []],
325
319
  layerUrlProxy: [
326
320
  ['sourceHostPrefix', 'pathPrefix', 'targetHostSuffixes'],
327
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[];