@heybox/hb-sdk-protocol 0.8.1-alpha.3 → 0.8.1-alpha.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.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @heybox/hb-sdk-protocol
2
2
 
3
+ 目录引用的 `relativePath` 允许完整 `.` 表示当前根;普通相对路径及文件引用仍拒绝点段、父目录和绝对路径。
4
+
3
5
  小黑盒外部小程序 SDK 与宿主 Runtime 共用的零依赖 wire contract。它只描述跨 iframe 边界传输的数据和校验规则,不执行 bridge、网络、登录、存储或任何平台能力。
4
6
 
5
7
  ## 边界
@@ -39,7 +41,11 @@ import { MINI_PROGRAM_PROTOCOL_CAPABILITIES, type MiniProgramBridgeMessage } fro
39
41
 
40
42
  ## 权限快照
41
43
 
42
- `MINI_PROGRAM_PERMISSION_CATALOG` 定义 8 个公开权限,`MINI_PROGRAM_PROTOCOL_CAPABILITIES[].requirement` 将每个 bridge method 显式分类为无需声明或要求全部列出的权限。`parseMiniProgramRuntimePermissions()` 是 schema v1 的 fail-closed 解析器;旧 `network.request` entry 仅在解析边界归一为 `network`,不得进入新配置。跨语言目录由 `generated/permission-catalog.json` 提供。
44
+ `MINI_PROGRAM_PERMISSION_CATALOG` 定义 9 个公开权限,`MINI_PROGRAM_PROTOCOL_CAPABILITIES[].requirement` 将每个 bridge method 显式分类为无需声明或要求全部列出的权限。`companion` 是无配置项的高风险平台审批权限,覆盖准备、启动、活动 Session 控制、stdio、附件与通知 wire method。`parseMiniProgramRuntimePermissions()` 是 schema v1 的 fail-closed 解析器;旧 `network.request` entry 仅在解析边界归一为 `network`,不得进入新配置。未知权限 entry 会被忽略,即使 `config` 为 `null` 或缺失,也不能让已认识的批准失效。跨语言目录由 `generated/permission-catalog.json` 提供。
45
+
46
+ 耗时能力通过 `MiniProgramCapabilityProgressMap` 按 method 绑定进度 payload;当前覆盖 `network.download` 与 `companion.prepare`。Companion Session wire 只携带不透明 Session ID、controller generation、原始字节 chunk/ack、exit 和 ownership-lost 事件,不暴露 PID、路径或原生句柄。
47
+
48
+ `CompanionInfo.source` 由可信 Host 标识 `local-dev` 或 `released`,与 `signatureStatus` 一起供授权展示使用;旧 Host 未提供来源时保持未知,不能推定为已审核产物。
43
49
 
44
50
  协议包不决定业务授权。`auth.login()` 的 UI、账号会话、授权码签发和 OpenAPI 都由 Host/服务端负责;协议层只传递经过约束的 request/response 数据。
45
51
 
package/dist/index.cjs.js CHANGED
@@ -1,5 +1,17 @@
1
1
  'use strict';
2
2
 
3
+ const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
4
+ const MINI_PROGRAM_MESSAGE_VERSION = 2;
5
+ const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
6
+ const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
7
+ const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
8
+ const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
9
+ const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
10
+ const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress';
11
+ const COMPANION_SESSION_OUTPUT_EVENT = 'companion.session.output';
12
+ const COMPANION_SESSION_EXIT_EVENT = 'companion.session.exit';
13
+ const COMPANION_SESSION_OWNERSHIP_LOST_EVENT = 'companion.session.ownershipLost';
14
+
3
15
  const AUTH_LOGIN_METHOD = 'auth.login';
4
16
  const USER_GET_INFO_METHOD = 'user.getInfo';
5
17
  const USER_REVOKE_AUTHORIZATION_METHOD = 'user.revokeAuthorization';
@@ -41,6 +53,18 @@ const CLOUD_LEADERBOARD_GET_LIST_METHOD = 'cloud.leaderboard.getList';
41
53
  const CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.getCurrentUserEntry';
42
54
  const CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.deleteCurrentUserEntry';
43
55
  const CLOUD_LEADERBOARD_GET_INFO_METHOD = 'cloud.leaderboard.getInfo';
56
+ const COMPANION_GET_INFO_METHOD = 'companion.getInfo';
57
+ const COMPANION_GET_PREPARATION_STATUS_METHOD = 'companion.getPreparationStatus';
58
+ const COMPANION_PREPARE_METHOD = 'companion.prepare';
59
+ const COMPANION_CANCEL_PREPARATION_METHOD = 'companion.cancelPreparation';
60
+ const COMPANION_GET_ACTIVE_SESSION_METHOD = 'companion.getActiveSession';
61
+ const COMPANION_LAUNCH_METHOD = 'companion.launch';
62
+ const COMPANION_SESSION_WRITE_METHOD = 'companion.session.write';
63
+ const COMPANION_SESSION_CLOSE_STDIN_METHOD = 'companion.session.closeStdin';
64
+ const COMPANION_SESSION_TERMINATE_METHOD = 'companion.session.terminate';
65
+ const COMPANION_SESSION_ACK_OUTPUT_METHOD = 'companion.session.ackOutput';
66
+ const COMPANION_OPEN_ATTACHMENT_METHOD = 'companion.openAttachment';
67
+ const COMPANION_SHOW_NOTIFICATION_METHOD = 'companion.showNotification';
44
68
  const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
45
69
  {
46
70
  method: AUTH_LOGIN_METHOD,
@@ -287,17 +311,28 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
287
311
  requirement: { kind: 'all', permissions: ['leaderboard'] },
288
312
  risk: 'low',
289
313
  },
314
+ ...[
315
+ COMPANION_GET_INFO_METHOD,
316
+ COMPANION_GET_PREPARATION_STATUS_METHOD,
317
+ COMPANION_PREPARE_METHOD,
318
+ COMPANION_CANCEL_PREPARATION_METHOD,
319
+ COMPANION_GET_ACTIVE_SESSION_METHOD,
320
+ COMPANION_LAUNCH_METHOD,
321
+ COMPANION_SESSION_WRITE_METHOD,
322
+ COMPANION_SESSION_CLOSE_STDIN_METHOD,
323
+ COMPANION_SESSION_TERMINATE_METHOD,
324
+ COMPANION_SESSION_ACK_OUTPUT_METHOD,
325
+ COMPANION_OPEN_ATTACHMENT_METHOD,
326
+ COMPANION_SHOW_NOTIFICATION_METHOD,
327
+ ].map((method) => ({
328
+ method,
329
+ module: 'companion',
330
+ capability: method,
331
+ requirement: { kind: 'all', permissions: ['companion'] },
332
+ risk: 'high',
333
+ })),
290
334
  ];
291
335
 
292
- const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
293
- const MINI_PROGRAM_MESSAGE_VERSION = 2;
294
- const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
295
- const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
296
- const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
297
- const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
298
- const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
299
- const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress';
300
-
301
336
  function isMiniProgramBridgeMessage(value) {
302
337
  if (!isRecord$1(value))
303
338
  return false;
@@ -319,7 +354,7 @@ function isMiniProgramBridgeMessage(value) {
319
354
  if (!isNonEmptyString(value.method) || value.error !== undefined)
320
355
  return false;
321
356
  if (value.method === MINI_PROGRAM_OPERATION_PROGRESS_METHOD) {
322
- return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramDownloadProgressPayload(value.payload);
357
+ return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramOperationProgressPayload(value.payload);
323
358
  }
324
359
  return value.id === undefined || isNonEmptyString(value.id);
325
360
  }
@@ -357,7 +392,7 @@ function isMiniProgramDirectoryRef(value) {
357
392
  if (isNonEmptyString(value.handleId)) {
358
393
  return hasOnlyKeys(value, ['kind', 'handleId']);
359
394
  }
360
- return (isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
395
+ return (isMiniProgramPathRootRef(value.root) && (value.relativePath === '.' || isMiniProgramRelativePath(value.relativePath)) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
361
396
  }
362
397
  function isMiniProgramFileDescriptor(value) {
363
398
  return (isRecord$1(value) &&
@@ -400,6 +435,24 @@ function isMiniProgramDownloadProgressPayload(value) {
400
435
  return value.total === undefined;
401
436
  return isNonNegativeSafeInteger(value.total) && value.loaded <= value.total;
402
437
  }
438
+ function isMiniProgramCompanionPrepareProgress(value) {
439
+ if (!isRecord$1(value))
440
+ return false;
441
+ if (value.phase === 'downloading') {
442
+ return (isNonNegativeSafeInteger(value.loaded) &&
443
+ (value.total === undefined || (isNonNegativeSafeInteger(value.total) && value.loaded <= value.total)) &&
444
+ hasOnlyKeys(value, ['phase', 'loaded', 'total']));
445
+ }
446
+ if (value.phase !== 'verifying' && value.phase !== 'extracting')
447
+ return false;
448
+ return (isNonNegativeSafeInteger(value.processed) &&
449
+ isNonNegativeSafeInteger(value.total) &&
450
+ value.processed <= value.total &&
451
+ hasOnlyKeys(value, ['phase', 'processed', 'total']));
452
+ }
453
+ function isMiniProgramOperationProgressPayload(value) {
454
+ return isMiniProgramDownloadProgressPayload(value) || isMiniProgramCompanionPrepareProgress(value);
455
+ }
403
456
  function isSDKHandshakePayload(value) {
404
457
  return isRecord$1(value) && isNonEmptyString(value.href) && typeof value.userAgent === 'string' && isNonEmptyString(value.sdkVersion);
405
458
  }
@@ -428,6 +481,34 @@ function isRecord$1(value) {
428
481
 
429
482
  /** 当前用户信息与登录能力支持的完整 scope 目录。 */
430
483
  const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
484
+ /** Companion alias 的跨构建、Runtime 与 Host 规范。 */
485
+ const COMPANION_ALIAS_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
486
+ /** Companion Host 可跨 bridge 保留的稳定领域错误码。 */
487
+ const COMPANION_ERROR_CODES = [
488
+ 'COMPANION_UNSUPPORTED',
489
+ 'COMPANION_NOT_DECLARED',
490
+ 'COMPANION_TARGET_UNSUPPORTED',
491
+ 'COMPANION_NOT_PREPARED',
492
+ 'COMPANION_PREPARATION_CANCELLED',
493
+ 'COMPANION_DOWNLOAD_FAILED',
494
+ 'COMPANION_DESCRIPTOR_UNAVAILABLE',
495
+ 'COMPANION_ARCHIVE_INVALID',
496
+ 'COMPANION_INTEGRITY_FAILED',
497
+ 'COMPANION_ENTRYPOINT_INVALID',
498
+ 'COMPANION_USER_CANCELLED',
499
+ 'COMPANION_ELEVATION_DENIED',
500
+ 'COMPANION_OS_BLOCKED',
501
+ 'COMPANION_LAUNCH_FAILED',
502
+ 'COMPANION_SESSION_VERSION_MISMATCH',
503
+ 'COMPANION_SESSION_OWNERSHIP_LOST',
504
+ 'COMPANION_SESSION_EXITED',
505
+ 'COMPANION_PIPE_CLOSED',
506
+ 'COMPANION_OUTPUT_LIMIT',
507
+ 'COMPANION_PROCESS_CRASHED',
508
+ 'COMPANION_ATTACHMENT_NOT_FOUND',
509
+ 'COMPANION_NOTIFICATION_UNAVAILABLE',
510
+ 'COMPANION_TERMINATE_FAILED',
511
+ ];
431
512
 
432
513
  const MINI_PROGRAM_PERMISSION_KEYS = [
433
514
  'userInfo',
@@ -438,6 +519,7 @@ const MINI_PROGRAM_PERMISSION_KEYS = [
438
519
  'clipboard',
439
520
  'leaderboard',
440
521
  'network',
522
+ 'companion',
441
523
  ];
442
524
  const MINI_PROGRAM_PERMISSION_CATALOG = [
443
525
  {
@@ -550,6 +632,29 @@ const MINI_PROGRAM_PERMISSION_CATALOG = [
550
632
  methods: ['network.request', 'network.download'],
551
633
  conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
552
634
  },
635
+ {
636
+ key: 'companion',
637
+ name: '桌面辅助应用',
638
+ description: '下载、准备并运行随当前小程序版本发布的受管桌面程序。',
639
+ access: 'platform-approval',
640
+ risk: 'high',
641
+ config: {},
642
+ methods: [
643
+ 'companion.getInfo',
644
+ 'companion.getPreparationStatus',
645
+ 'companion.prepare',
646
+ 'companion.cancelPreparation',
647
+ 'companion.getActiveSession',
648
+ 'companion.launch',
649
+ 'companion.session.write',
650
+ 'companion.session.closeStdin',
651
+ 'companion.session.terminate',
652
+ 'companion.session.ackOutput',
653
+ 'companion.openAttachment',
654
+ 'companion.showNotification',
655
+ ],
656
+ conditions: ['声明后仍需平台批准,并继续执行可信用户手势、Host 能力和当前版本 Manifest 校验。'],
657
+ },
553
658
  ];
554
659
  const MINI_PROGRAM_NO_DECLARATION_METHODS = [
555
660
  'user.revokeAuthorization',
@@ -592,8 +697,8 @@ function parseMiniProgramRuntimePermissions(snapshot) {
592
697
  }
593
698
  seenKeys.add(key);
594
699
  if (!isManagedMiniProgramRuntimePermissionKey(key)) {
595
- if (!isRecord(rawEntry.config))
596
- return { valid: false, permissions: {} };
700
+ // 未知权限必须忽略,不能让 config:null / 缺字段把已认识的批准一起否掉。
701
+ // 服务端会对无 config message 字段输出 null(Rylai EmitUnpopulated)。
597
702
  continue;
598
703
  }
599
704
  if (key === 'network') {
@@ -629,6 +734,23 @@ exports.CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = CLOUD_LEADERBOARD_GET_
629
734
  exports.CLOUD_LEADERBOARD_GET_INFO_METHOD = CLOUD_LEADERBOARD_GET_INFO_METHOD;
630
735
  exports.CLOUD_LEADERBOARD_GET_LIST_METHOD = CLOUD_LEADERBOARD_GET_LIST_METHOD;
631
736
  exports.CLOUD_LEADERBOARD_SUBMIT_METHOD = CLOUD_LEADERBOARD_SUBMIT_METHOD;
737
+ exports.COMPANION_ALIAS_PATTERN = COMPANION_ALIAS_PATTERN;
738
+ exports.COMPANION_CANCEL_PREPARATION_METHOD = COMPANION_CANCEL_PREPARATION_METHOD;
739
+ exports.COMPANION_ERROR_CODES = COMPANION_ERROR_CODES;
740
+ exports.COMPANION_GET_ACTIVE_SESSION_METHOD = COMPANION_GET_ACTIVE_SESSION_METHOD;
741
+ exports.COMPANION_GET_INFO_METHOD = COMPANION_GET_INFO_METHOD;
742
+ exports.COMPANION_GET_PREPARATION_STATUS_METHOD = COMPANION_GET_PREPARATION_STATUS_METHOD;
743
+ exports.COMPANION_LAUNCH_METHOD = COMPANION_LAUNCH_METHOD;
744
+ exports.COMPANION_OPEN_ATTACHMENT_METHOD = COMPANION_OPEN_ATTACHMENT_METHOD;
745
+ exports.COMPANION_PREPARE_METHOD = COMPANION_PREPARE_METHOD;
746
+ exports.COMPANION_SESSION_ACK_OUTPUT_METHOD = COMPANION_SESSION_ACK_OUTPUT_METHOD;
747
+ exports.COMPANION_SESSION_CLOSE_STDIN_METHOD = COMPANION_SESSION_CLOSE_STDIN_METHOD;
748
+ exports.COMPANION_SESSION_EXIT_EVENT = COMPANION_SESSION_EXIT_EVENT;
749
+ exports.COMPANION_SESSION_OUTPUT_EVENT = COMPANION_SESSION_OUTPUT_EVENT;
750
+ exports.COMPANION_SESSION_OWNERSHIP_LOST_EVENT = COMPANION_SESSION_OWNERSHIP_LOST_EVENT;
751
+ exports.COMPANION_SESSION_TERMINATE_METHOD = COMPANION_SESSION_TERMINATE_METHOD;
752
+ exports.COMPANION_SESSION_WRITE_METHOD = COMPANION_SESSION_WRITE_METHOD;
753
+ exports.COMPANION_SHOW_NOTIFICATION_METHOD = COMPANION_SHOW_NOTIFICATION_METHOD;
632
754
  exports.DEVICE_SET_CLIPBOARD_METHOD = DEVICE_SET_CLIPBOARD_METHOD;
633
755
  exports.DEVICE_VIBRATE_METHOD = DEVICE_VIBRATE_METHOD;
634
756
  exports.DIRECTORY_CREATE_METHOD = DIRECTORY_CREATE_METHOD;
@@ -680,6 +802,7 @@ exports.VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = VIEWPORT_SET_NAVIGATION_BAR_S
680
802
  exports.isManagedMiniProgramRuntimePermissionKey = isManagedMiniProgramRuntimePermissionKey;
681
803
  exports.isMiniProgramBridgeMessage = isMiniProgramBridgeMessage;
682
804
  exports.isMiniProgramByteArray = isMiniProgramByteArray;
805
+ exports.isMiniProgramCompanionPrepareProgress = isMiniProgramCompanionPrepareProgress;
683
806
  exports.isMiniProgramDirectoryDescriptor = isMiniProgramDirectoryDescriptor;
684
807
  exports.isMiniProgramDirectoryRef = isMiniProgramDirectoryRef;
685
808
  exports.isMiniProgramDownloadProgressPayload = isMiniProgramDownloadProgressPayload;
@@ -687,6 +810,7 @@ exports.isMiniProgramFileDescriptor = isMiniProgramFileDescriptor;
687
810
  exports.isMiniProgramFileRef = isMiniProgramFileRef;
688
811
  exports.isMiniProgramFileStat = isMiniProgramFileStat;
689
812
  exports.isMiniProgramFileSystemEntityDescriptor = isMiniProgramFileSystemEntityDescriptor;
813
+ exports.isMiniProgramOperationProgressPayload = isMiniProgramOperationProgressPayload;
690
814
  exports.isMiniProgramPathRootRef = isMiniProgramPathRootRef;
691
815
  exports.isMiniProgramPermissionKey = isMiniProgramPermissionKey;
692
816
  exports.isMiniProgramRelativePath = isMiniProgramRelativePath;
package/dist/index.esm.js CHANGED
@@ -1,3 +1,15 @@
1
+ const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
2
+ const MINI_PROGRAM_MESSAGE_VERSION = 2;
3
+ const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
4
+ const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
5
+ const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
6
+ const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
7
+ const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
8
+ const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress';
9
+ const COMPANION_SESSION_OUTPUT_EVENT = 'companion.session.output';
10
+ const COMPANION_SESSION_EXIT_EVENT = 'companion.session.exit';
11
+ const COMPANION_SESSION_OWNERSHIP_LOST_EVENT = 'companion.session.ownershipLost';
12
+
1
13
  const AUTH_LOGIN_METHOD = 'auth.login';
2
14
  const USER_GET_INFO_METHOD = 'user.getInfo';
3
15
  const USER_REVOKE_AUTHORIZATION_METHOD = 'user.revokeAuthorization';
@@ -39,6 +51,18 @@ const CLOUD_LEADERBOARD_GET_LIST_METHOD = 'cloud.leaderboard.getList';
39
51
  const CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.getCurrentUserEntry';
40
52
  const CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.deleteCurrentUserEntry';
41
53
  const CLOUD_LEADERBOARD_GET_INFO_METHOD = 'cloud.leaderboard.getInfo';
54
+ const COMPANION_GET_INFO_METHOD = 'companion.getInfo';
55
+ const COMPANION_GET_PREPARATION_STATUS_METHOD = 'companion.getPreparationStatus';
56
+ const COMPANION_PREPARE_METHOD = 'companion.prepare';
57
+ const COMPANION_CANCEL_PREPARATION_METHOD = 'companion.cancelPreparation';
58
+ const COMPANION_GET_ACTIVE_SESSION_METHOD = 'companion.getActiveSession';
59
+ const COMPANION_LAUNCH_METHOD = 'companion.launch';
60
+ const COMPANION_SESSION_WRITE_METHOD = 'companion.session.write';
61
+ const COMPANION_SESSION_CLOSE_STDIN_METHOD = 'companion.session.closeStdin';
62
+ const COMPANION_SESSION_TERMINATE_METHOD = 'companion.session.terminate';
63
+ const COMPANION_SESSION_ACK_OUTPUT_METHOD = 'companion.session.ackOutput';
64
+ const COMPANION_OPEN_ATTACHMENT_METHOD = 'companion.openAttachment';
65
+ const COMPANION_SHOW_NOTIFICATION_METHOD = 'companion.showNotification';
42
66
  const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
43
67
  {
44
68
  method: AUTH_LOGIN_METHOD,
@@ -285,17 +309,28 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
285
309
  requirement: { kind: 'all', permissions: ['leaderboard'] },
286
310
  risk: 'low',
287
311
  },
312
+ ...[
313
+ COMPANION_GET_INFO_METHOD,
314
+ COMPANION_GET_PREPARATION_STATUS_METHOD,
315
+ COMPANION_PREPARE_METHOD,
316
+ COMPANION_CANCEL_PREPARATION_METHOD,
317
+ COMPANION_GET_ACTIVE_SESSION_METHOD,
318
+ COMPANION_LAUNCH_METHOD,
319
+ COMPANION_SESSION_WRITE_METHOD,
320
+ COMPANION_SESSION_CLOSE_STDIN_METHOD,
321
+ COMPANION_SESSION_TERMINATE_METHOD,
322
+ COMPANION_SESSION_ACK_OUTPUT_METHOD,
323
+ COMPANION_OPEN_ATTACHMENT_METHOD,
324
+ COMPANION_SHOW_NOTIFICATION_METHOD,
325
+ ].map((method) => ({
326
+ method,
327
+ module: 'companion',
328
+ capability: method,
329
+ requirement: { kind: 'all', permissions: ['companion'] },
330
+ risk: 'high',
331
+ })),
288
332
  ];
289
333
 
290
- const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
291
- const MINI_PROGRAM_MESSAGE_VERSION = 2;
292
- const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
293
- const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
294
- const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
295
- const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
296
- const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
297
- const MINI_PROGRAM_OPERATION_PROGRESS_METHOD = 'operation.progress';
298
-
299
334
  function isMiniProgramBridgeMessage(value) {
300
335
  if (!isRecord$1(value))
301
336
  return false;
@@ -317,7 +352,7 @@ function isMiniProgramBridgeMessage(value) {
317
352
  if (!isNonEmptyString(value.method) || value.error !== undefined)
318
353
  return false;
319
354
  if (value.method === MINI_PROGRAM_OPERATION_PROGRESS_METHOD) {
320
- return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramDownloadProgressPayload(value.payload);
355
+ return value.version === 2 && isNonEmptyString(value.id) && isMiniProgramOperationProgressPayload(value.payload);
321
356
  }
322
357
  return value.id === undefined || isNonEmptyString(value.id);
323
358
  }
@@ -355,7 +390,7 @@ function isMiniProgramDirectoryRef(value) {
355
390
  if (isNonEmptyString(value.handleId)) {
356
391
  return hasOnlyKeys(value, ['kind', 'handleId']);
357
392
  }
358
- return (isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
393
+ return (isMiniProgramPathRootRef(value.root) && (value.relativePath === '.' || isMiniProgramRelativePath(value.relativePath)) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
359
394
  }
360
395
  function isMiniProgramFileDescriptor(value) {
361
396
  return (isRecord$1(value) &&
@@ -398,6 +433,24 @@ function isMiniProgramDownloadProgressPayload(value) {
398
433
  return value.total === undefined;
399
434
  return isNonNegativeSafeInteger(value.total) && value.loaded <= value.total;
400
435
  }
436
+ function isMiniProgramCompanionPrepareProgress(value) {
437
+ if (!isRecord$1(value))
438
+ return false;
439
+ if (value.phase === 'downloading') {
440
+ return (isNonNegativeSafeInteger(value.loaded) &&
441
+ (value.total === undefined || (isNonNegativeSafeInteger(value.total) && value.loaded <= value.total)) &&
442
+ hasOnlyKeys(value, ['phase', 'loaded', 'total']));
443
+ }
444
+ if (value.phase !== 'verifying' && value.phase !== 'extracting')
445
+ return false;
446
+ return (isNonNegativeSafeInteger(value.processed) &&
447
+ isNonNegativeSafeInteger(value.total) &&
448
+ value.processed <= value.total &&
449
+ hasOnlyKeys(value, ['phase', 'processed', 'total']));
450
+ }
451
+ function isMiniProgramOperationProgressPayload(value) {
452
+ return isMiniProgramDownloadProgressPayload(value) || isMiniProgramCompanionPrepareProgress(value);
453
+ }
401
454
  function isSDKHandshakePayload(value) {
402
455
  return isRecord$1(value) && isNonEmptyString(value.href) && typeof value.userAgent === 'string' && isNonEmptyString(value.sdkVersion);
403
456
  }
@@ -426,6 +479,34 @@ function isRecord$1(value) {
426
479
 
427
480
  /** 当前用户信息与登录能力支持的完整 scope 目录。 */
428
481
  const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
482
+ /** Companion alias 的跨构建、Runtime 与 Host 规范。 */
483
+ const COMPANION_ALIAS_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
484
+ /** Companion Host 可跨 bridge 保留的稳定领域错误码。 */
485
+ const COMPANION_ERROR_CODES = [
486
+ 'COMPANION_UNSUPPORTED',
487
+ 'COMPANION_NOT_DECLARED',
488
+ 'COMPANION_TARGET_UNSUPPORTED',
489
+ 'COMPANION_NOT_PREPARED',
490
+ 'COMPANION_PREPARATION_CANCELLED',
491
+ 'COMPANION_DOWNLOAD_FAILED',
492
+ 'COMPANION_DESCRIPTOR_UNAVAILABLE',
493
+ 'COMPANION_ARCHIVE_INVALID',
494
+ 'COMPANION_INTEGRITY_FAILED',
495
+ 'COMPANION_ENTRYPOINT_INVALID',
496
+ 'COMPANION_USER_CANCELLED',
497
+ 'COMPANION_ELEVATION_DENIED',
498
+ 'COMPANION_OS_BLOCKED',
499
+ 'COMPANION_LAUNCH_FAILED',
500
+ 'COMPANION_SESSION_VERSION_MISMATCH',
501
+ 'COMPANION_SESSION_OWNERSHIP_LOST',
502
+ 'COMPANION_SESSION_EXITED',
503
+ 'COMPANION_PIPE_CLOSED',
504
+ 'COMPANION_OUTPUT_LIMIT',
505
+ 'COMPANION_PROCESS_CRASHED',
506
+ 'COMPANION_ATTACHMENT_NOT_FOUND',
507
+ 'COMPANION_NOTIFICATION_UNAVAILABLE',
508
+ 'COMPANION_TERMINATE_FAILED',
509
+ ];
429
510
 
430
511
  const MINI_PROGRAM_PERMISSION_KEYS = [
431
512
  'userInfo',
@@ -436,6 +517,7 @@ const MINI_PROGRAM_PERMISSION_KEYS = [
436
517
  'clipboard',
437
518
  'leaderboard',
438
519
  'network',
520
+ 'companion',
439
521
  ];
440
522
  const MINI_PROGRAM_PERMISSION_CATALOG = [
441
523
  {
@@ -548,6 +630,29 @@ const MINI_PROGRAM_PERMISSION_CATALOG = [
548
630
  methods: ['network.request', 'network.download'],
549
631
  conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
550
632
  },
633
+ {
634
+ key: 'companion',
635
+ name: '桌面辅助应用',
636
+ description: '下载、准备并运行随当前小程序版本发布的受管桌面程序。',
637
+ access: 'platform-approval',
638
+ risk: 'high',
639
+ config: {},
640
+ methods: [
641
+ 'companion.getInfo',
642
+ 'companion.getPreparationStatus',
643
+ 'companion.prepare',
644
+ 'companion.cancelPreparation',
645
+ 'companion.getActiveSession',
646
+ 'companion.launch',
647
+ 'companion.session.write',
648
+ 'companion.session.closeStdin',
649
+ 'companion.session.terminate',
650
+ 'companion.session.ackOutput',
651
+ 'companion.openAttachment',
652
+ 'companion.showNotification',
653
+ ],
654
+ conditions: ['声明后仍需平台批准,并继续执行可信用户手势、Host 能力和当前版本 Manifest 校验。'],
655
+ },
551
656
  ];
552
657
  const MINI_PROGRAM_NO_DECLARATION_METHODS = [
553
658
  'user.revokeAuthorization',
@@ -590,8 +695,8 @@ function parseMiniProgramRuntimePermissions(snapshot) {
590
695
  }
591
696
  seenKeys.add(key);
592
697
  if (!isManagedMiniProgramRuntimePermissionKey(key)) {
593
- if (!isRecord(rawEntry.config))
594
- return { valid: false, permissions: {} };
698
+ // 未知权限必须忽略,不能让 config:null / 缺字段把已认识的批准一起否掉。
699
+ // 服务端会对无 config message 字段输出 null(Rylai EmitUnpopulated)。
595
700
  continue;
596
701
  }
597
702
  if (key === 'network') {
@@ -621,4 +726,4 @@ function isRecord(value) {
621
726
  return typeof value === 'object' && value !== null && !Array.isArray(value);
622
727
  }
623
728
 
624
- export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, DIRECTORY_CREATE_METHOD, DIRECTORY_EXISTS_METHOD, DIRECTORY_LIST_METHOD, DIRECTORY_REMOVE_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_PICK_FILES_METHOD, FILES_SAVE_FILE_METHOD, FILE_CREATE_METHOD, FILE_EXISTS_METHOD, FILE_READ_BYTES_METHOD, FILE_READ_TEXT_METHOD, FILE_REMOVE_METHOD, FILE_STAT_METHOD, FILE_WRITE_BYTES_METHOD, FILE_WRITE_TEXT_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NO_DECLARATION_METHODS, MINI_PROGRAM_OPERATION_PROGRESS_METHOD, MINI_PROGRAM_PERMISSION_CATALOG, MINI_PROGRAM_PERMISSION_KEYS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_DOWNLOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_COPY_LINK_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isMiniProgramByteArray, isMiniProgramDirectoryDescriptor, isMiniProgramDirectoryRef, isMiniProgramDownloadProgressPayload, isMiniProgramFileDescriptor, isMiniProgramFileRef, isMiniProgramFileStat, isMiniProgramFileSystemEntityDescriptor, isMiniProgramPathRootRef, isMiniProgramPermissionKey, isMiniProgramRelativePath, parseMiniProgramRuntimePermissions };
729
+ export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, COMPANION_ALIAS_PATTERN, COMPANION_CANCEL_PREPARATION_METHOD, COMPANION_ERROR_CODES, COMPANION_GET_ACTIVE_SESSION_METHOD, COMPANION_GET_INFO_METHOD, COMPANION_GET_PREPARATION_STATUS_METHOD, COMPANION_LAUNCH_METHOD, COMPANION_OPEN_ATTACHMENT_METHOD, COMPANION_PREPARE_METHOD, COMPANION_SESSION_ACK_OUTPUT_METHOD, COMPANION_SESSION_CLOSE_STDIN_METHOD, COMPANION_SESSION_EXIT_EVENT, COMPANION_SESSION_OUTPUT_EVENT, COMPANION_SESSION_OWNERSHIP_LOST_EVENT, COMPANION_SESSION_TERMINATE_METHOD, COMPANION_SESSION_WRITE_METHOD, COMPANION_SHOW_NOTIFICATION_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, DIRECTORY_CREATE_METHOD, DIRECTORY_EXISTS_METHOD, DIRECTORY_LIST_METHOD, DIRECTORY_REMOVE_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_PICK_FILES_METHOD, FILES_SAVE_FILE_METHOD, FILE_CREATE_METHOD, FILE_EXISTS_METHOD, FILE_READ_BYTES_METHOD, FILE_READ_TEXT_METHOD, FILE_REMOVE_METHOD, FILE_STAT_METHOD, FILE_WRITE_BYTES_METHOD, FILE_WRITE_TEXT_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NO_DECLARATION_METHODS, MINI_PROGRAM_OPERATION_PROGRESS_METHOD, MINI_PROGRAM_PERMISSION_CATALOG, MINI_PROGRAM_PERMISSION_KEYS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_DOWNLOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_COPY_LINK_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isMiniProgramByteArray, isMiniProgramCompanionPrepareProgress, isMiniProgramDirectoryDescriptor, isMiniProgramDirectoryRef, isMiniProgramDownloadProgressPayload, isMiniProgramFileDescriptor, isMiniProgramFileRef, isMiniProgramFileStat, isMiniProgramFileSystemEntityDescriptor, isMiniProgramOperationProgressPayload, isMiniProgramPathRootRef, isMiniProgramPermissionKey, isMiniProgramRelativePath, parseMiniProgramRuntimePermissions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk-protocol",
3
- "version": "0.8.1-alpha.3",
3
+ "version": "0.8.1-alpha.7",
4
4
  "description": "Heybox mini-program iframe bridge wire contracts.",
5
5
  "sideEffects": false,
6
6
  "exports": {
package/src/bridge.ts CHANGED
@@ -1,5 +1,19 @@
1
- import { MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_OPERATION_PROGRESS_METHOD } from './constants';
2
- import type { DownloadProgressPayload, MiniProgramRuntimeEnvironmentInfo, UserInfoAuthorization } from './payloads';
1
+ import {
2
+ COMPANION_SESSION_EXIT_EVENT,
3
+ COMPANION_SESSION_OUTPUT_EVENT,
4
+ COMPANION_SESSION_OWNERSHIP_LOST_EVENT,
5
+ MINI_PROGRAM_MESSAGE_NAMESPACE,
6
+ MINI_PROGRAM_OPERATION_PROGRESS_METHOD,
7
+ } from './constants';
8
+ import type {
9
+ CompanionSessionExitPayload,
10
+ CompanionSessionOutputPayload,
11
+ CompanionSessionOwnershipLostPayload,
12
+ DownloadProgressPayload,
13
+ MiniProgramRuntimeEnvironmentInfo,
14
+ UserInfoAuthorization,
15
+ } from './payloads';
16
+ import type { MiniProgramCapabilityProgress, MiniProgramProgressMethod } from './capabilities';
3
17
 
4
18
  export type MiniProgramBridgeMessageType = 'handshake' | 'request' | 'response' | 'event' | 'cancel';
5
19
  export type MiniProgramEventName =
@@ -10,7 +24,10 @@ export type MiniProgramEventName =
10
24
  | 'unload'
11
25
  | 'error'
12
26
  | 'heybox_app_login_change'
13
- | 'user_info_authorization_change';
27
+ | 'user_info_authorization_change'
28
+ | typeof COMPANION_SESSION_OUTPUT_EVENT
29
+ | typeof COMPANION_SESSION_EXIT_EVENT
30
+ | typeof COMPANION_SESSION_OWNERSHIP_LOST_EVENT;
14
31
 
15
32
  export interface MiniProgramBridgeError {
16
33
  code: string;
@@ -71,12 +88,14 @@ export interface MiniProgramBridgeCancelMessage extends MiniProgramBridgeMessage
71
88
  error?: never;
72
89
  }
73
90
 
74
- export interface MiniProgramBridgeProgressMessage extends MiniProgramBridgeMessage<DownloadProgressPayload> {
91
+ export interface MiniProgramBridgeProgressMessage<
92
+ TMethod extends MiniProgramProgressMethod = MiniProgramProgressMethod,
93
+ > extends MiniProgramBridgeMessage<MiniProgramCapabilityProgress<TMethod>> {
75
94
  version: 2;
76
95
  type: 'event';
77
96
  id: string;
78
97
  method: typeof MINI_PROGRAM_OPERATION_PROGRESS_METHOD;
79
- payload: DownloadProgressPayload;
98
+ payload: MiniProgramCapabilityProgress<TMethod>;
80
99
  error?: never;
81
100
  }
82
101
  export interface MiniProgramEventPayloadMap {
@@ -88,4 +107,7 @@ export interface MiniProgramEventPayloadMap {
88
107
  error: MiniProgramBridgeError;
89
108
  heybox_app_login_change: { isHeyboxAppLoggedIn: boolean };
90
109
  user_info_authorization_change: UserInfoAuthorization;
110
+ [COMPANION_SESSION_OUTPUT_EVENT]: CompanionSessionOutputPayload;
111
+ [COMPANION_SESSION_EXIT_EVENT]: CompanionSessionExitPayload;
112
+ [COMPANION_SESSION_OWNERSHIP_LOST_EVENT]: CompanionSessionOwnershipLostPayload;
91
113
  }