@heybox/hb-sdk 0.8.2-alpha.1 → 0.8.2-alpha.5

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 (76) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/README.md +5 -1
  3. package/dist/cli-chunks/{build-DFwk1Xza.cjs → build-D2T3ky_9.cjs} +5 -5
  4. package/dist/cli-chunks/{context-DPwjjbIf.cjs → context-DEgmdpSL.cjs} +326 -104
  5. package/dist/cli-chunks/{create-Cbk708wm.cjs → create-DKqQhrG5.cjs} +5 -1
  6. package/dist/cli-chunks/{dev-B1dCAh3V.cjs → dev-BEXM7cmq.cjs} +17 -9
  7. package/dist/cli-chunks/{doctor-KX6cHAbM.cjs → doctor-B7UixGrd.cjs} +1 -1
  8. package/dist/cli-chunks/{index-B5GNdZS6.cjs → index-BtwfuoWI.cjs} +15 -17
  9. package/dist/cli-chunks/{index-D1CfvRqX.cjs → index-C69OtRug.cjs} +2 -2
  10. package/dist/cli-chunks/{index.esm-BvuovqBQ.cjs → index.esm-C86KlVdK.cjs} +11 -10
  11. package/dist/cli-chunks/{login-CqdIa3XD.cjs → login-Bp_HMx-i.cjs} +2 -2
  12. package/dist/cli-chunks/{project-vite-Bw3UJTnC.cjs → project-vite-DZxipd13.cjs} +1 -1
  13. package/dist/cli-chunks/{remote-t0V-fuAW.cjs → remote-B_sVsbQP.cjs} +80 -60
  14. package/dist/cli-chunks/runtime-gate-GR9jZd37.cjs +58 -0
  15. package/dist/cli-chunks/{runtime-gate-BWb8QIcX.cjs → runtime-permission-env-COWketgE.cjs} +4533 -40
  16. package/dist/cli-chunks/{session-DFY2dygN.cjs → session-6-AApcTZ.cjs} +1 -1
  17. package/dist/cli-chunks/{skill-D3xHcK8w.cjs → skill-CPDLk7t7.cjs} +2 -2
  18. package/dist/cli-chunks/{version-DkVq4CXN.cjs → version-hHrSPRwW.cjs} +1 -1
  19. package/dist/cli.cjs +1 -1
  20. package/dist/devtools/browser-dev-host/assets/browser-dev-host-CpwQQhA1.js +101 -0
  21. package/dist/devtools/browser-dev-host/assets/{desktop-app-launch-8J62MOi_.js → desktop-app-launch-BdWBOIvY.js} +1 -1
  22. package/dist/devtools/browser-dev-host/assets/{index-CrsPiYXy.js → index-BQSEynx6.js} +3 -3
  23. package/dist/devtools/browser-dev-host/index.html +2 -2
  24. package/dist/index.cjs.js +946 -42
  25. package/dist/index.esm.js +946 -42
  26. package/dist/miniapp-publish.cjs.js +9410 -122
  27. package/dist/miniapp-publish.esm.js +9406 -123
  28. package/dist/protocol.cjs.js +805 -0
  29. package/dist/protocol.esm.js +805 -0
  30. package/dist/templates/vanilla-vite-js/assets/heybox-placeholder.png +0 -0
  31. package/dist/templates/vanilla-vite-js/package.json.ejs +3 -0
  32. package/dist/vite.cjs.js +843 -507
  33. package/dist/vite.esm.js +844 -508
  34. package/package.json +8 -7
  35. package/skill/SKILL.md +5 -1
  36. package/skill/references/api-root.md +194 -9
  37. package/skill/references/cli.md +3 -3
  38. package/skill/references/recipes.md +43 -4
  39. package/skill/skill.json +5 -5
  40. package/types/core/errors.d.ts +33 -9
  41. package/types/core/handshake-state.d.ts +32 -2
  42. package/types/core/singleton.d.ts +265 -6
  43. package/types/miniapp-manifest/basic-info-browser.d.ts +9 -0
  44. package/types/miniapp-manifest/basic-info-image-header.d.ts +6 -0
  45. package/types/miniapp-manifest/basic-info-node.d.ts +17 -0
  46. package/types/miniapp-manifest/basic-info-placeholder.d.ts +1 -0
  47. package/types/miniapp-manifest/basic-info.d.ts +12 -0
  48. package/types/miniapp-manifest/bindings.d.ts +65 -0
  49. package/types/miniapp-manifest/schema.d.ts +143 -20
  50. package/types/miniapp-publish/index.d.ts +433 -29
  51. package/types/modules/auth/index.d.ts +159 -5
  52. package/types/modules/cloud/index.d.ts +514 -40
  53. package/types/modules/companion/index.d.ts +1518 -17
  54. package/types/modules/device/index.d.ts +140 -9
  55. package/types/modules/environment/index.d.ts +172 -4
  56. package/types/modules/files/types.d.ts +1396 -21
  57. package/types/modules/navigation/app-pages/types.d.ts +81 -24
  58. package/types/modules/navigation/index.d.ts +230 -7
  59. package/types/modules/network/index.d.ts +297 -26
  60. package/types/modules/share/copy-link.d.ts +35 -5
  61. package/types/modules/share/index.d.ts +210 -0
  62. package/types/modules/share/screenshot.d.ts +23 -5
  63. package/types/modules/share/show-share-menu.d.ts +18 -5
  64. package/types/modules/share/types.d.ts +148 -23
  65. package/types/modules/storage/index.d.ts +139 -9
  66. package/types/modules/ui/index.d.ts +249 -18
  67. package/types/modules/user/get-info.d.ts +29 -8
  68. package/types/modules/user/index.d.ts +157 -0
  69. package/types/modules/user/revoke-authorization.d.ts +26 -2
  70. package/types/modules/user/steam-game-list.d.ts +96 -15
  71. package/types/modules/viewport/index.d.ts +158 -22
  72. package/types/protocol/types.d.ts +19 -1
  73. package/types/vite/index.d.ts +159 -1
  74. package/dist/cli-chunks/runtime-permission-env-BgYjqHIE.cjs +0 -3942
  75. package/dist/devtools/browser-dev-host/assets/browser-dev-host-DqPIIvha.js +0 -101
  76. /package/types/{vite → miniapp-manifest}/runtime-gate.d.ts +0 -0
package/dist/index.cjs.js CHANGED
@@ -279,12 +279,34 @@ function isPlainObject$1(value) {
279
279
  * @remarks
280
280
  * 该错误用于表示握手失败、bridge 调用失败、父容器运行时错误等
281
281
  * 非 HTTP 结果错误。其 `code` 字段可用于业务分支处理,
282
- * `data` 仅作为可选调试信息,不保证结构稳定。
282
+ * `data` 仅作为可选调试信息,不保证结构稳定。错误码是跨 Host 的分支契约;
283
+ * `message` 只用于日志和开发者提示,不应作为机器判断条件。
284
+ *
285
+ * 常见处理类别包括:`INVALID_PARAMS`(修正调用参数)、`PERMISSION_NOT_DECLARED`
286
+ * 或 `PERMISSION_DENIED`(检查 Manifest/平台批准)、`USER_GESTURE_REQUIRED`
287
+ *(改为用户点击后重试)、`AUTHORIZATION_CANCELLED`(结束当前流程),以及
288
+ * `METHOD_FORBIDDEN`(当前 Host 不支持该能力)。具体能力还可能返回模块专属错误码。
289
+ * 不要把所有错误都当作可重试错误,也不要把 `data` 当成稳定的序列化协议。
290
+ *
291
+ * @example
292
+ * ```ts
293
+ * import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
294
+ *
295
+ * try {
296
+ * await hbSDK.auth.login({ scopes: ['profile'] })
297
+ * } catch (error) {
298
+ * if (error instanceof HbMiniProgramSDKError && error.code === 'USER_GESTURE_REQUIRED') {
299
+ * showRetryButton()
300
+ * return
301
+ * }
302
+ * throw error
303
+ * }
304
+ * ```
283
305
  */
284
306
  class HbMiniProgramSDKError extends Error {
285
- /** 稳定错误码。 */
307
+ /** 稳定错误码;业务分支应比较该字段,不要比较 `message`。 */
286
308
  code;
287
- /** 可选调试数据。 */
309
+ /** 可选调试数据;结构由具体错误码决定,可能随 Host 版本变化。 */
288
310
  data;
289
311
  constructor(error) {
290
312
  super(error.message);
@@ -316,20 +338,22 @@ function createSDKError(code, message, data) {
316
338
  *
317
339
  * @remarks
318
340
  * 仅在请求已经成功走完 bridge / runtime / 宿主调用链、但最终 HTTP 状态不满足
319
- * `validateStatus` 时抛出。它不表示握手失败或 bridge 级错误。
341
+ * `validateStatus` 时抛出。它不表示握手失败或 bridge 级错误。网络请求没有收到
342
+ * 可判定的 HTTP 响应时,SDK 会抛出 `HbMiniProgramSDKError` 或原始 transport 错误,
343
+ * 不应把本类当作网络不可达的统一错误类型。
320
344
  *
321
345
  * @typeParam T - 标准化响应数据的类型。
322
346
  */
323
347
  class HbMiniProgramNetworkError extends Error {
324
- /** HTTP 状态码。 */
348
+ /** HTTP 状态码;由 `validateStatus` 判定为失败的响应状态。 */
325
349
  status;
326
- /** 标准化响应数据。 */
350
+ /** 标准化响应数据;类型由 `network.request<T>()` 的泛型参数决定。 */
327
351
  data;
328
- /** 标准化响应头。 */
352
+ /** 标准化响应头;敏感响应头会在进入错误对象前被脱敏或移除。 */
329
353
  headers;
330
- /** SDK 公共请求配置快照。 */
354
+ /** SDK 公共请求配置快照;可能含原始 URL、请求头或请求数据,记录日志前必须自行脱敏。 */
331
355
  config;
332
- /** 完整标准化响应。 */
356
+ /** 完整标准化响应,包含状态、头、数据和请求配置。 */
333
357
  response;
334
358
  /**
335
359
  * @param response - 已完成请求的标准化网络响应。
@@ -564,9 +588,31 @@ function restoreMethod(history, name, patchedValue, original) {
564
588
  }
565
589
  }
566
590
 
591
+ /**
592
+ * 所有小程序 iframe bridge envelope 共用的固定 namespace。
593
+ *
594
+ * @remarks 该值用于排除无关 `postMessage` 数据,不负责验证消息来源;接收方仍须校验 source 和 nonce,
595
+ * 并在 origin 可以固定且协议模式要求时校验 origin。
596
+ */
567
597
  const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
598
+ /**
599
+ * 新消息默认发送的当前 bridge wire 版本。
600
+ *
601
+ * @remarks 接收 guard 为握手协商继续接受 v1 与 v2 envelope;cancel 与 operation progress 等 v2-only 消息仍必须使用 v2。
602
+ */
568
603
  const MINI_PROGRAM_MESSAGE_VERSION = 2;
604
+ /**
605
+ * Runtime 在 iframe URL 中传递 bridge nonce 的 query 参数名。
606
+ *
607
+ * @remarks nonce 用于把消息关联到当前 iframe 实例,不是独立的身份认证凭据;接收方还必须校验 source,
608
+ * 并在 origin 可以固定且协议模式要求时校验 origin。
609
+ */
569
610
  const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
611
+ /**
612
+ * SDK 发起 bridge 握手时使用的保留 method。
613
+ *
614
+ * @remarks `type: 'handshake'` 的消息必须使用该 method;Runtime 的可选握手响应也可携带该 method 供 SDK 识别环境快照。
615
+ */
570
616
  const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
571
617
  const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
572
618
  const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
@@ -630,6 +676,76 @@ const COMPANION_SESSION_ACK_OUTPUT_METHOD = 'companion.session.ackOutput';
630
676
  const COMPANION_OPEN_ATTACHMENT_METHOD = 'companion.openAttachment';
631
677
  const COMPANION_SHOW_NOTIFICATION_METHOD = 'companion.showNotification';
632
678
 
679
+ /**
680
+ * 判断不可信输入是否具有受支持的小程序 bridge 消息结构。
681
+ *
682
+ * @param value - 从 `MessageEvent.data`、反序列化结果或其他外部边界取得的未知值。`null`、数组和非对象值会直接返回 `false`。
683
+ * @returns 输入满足 v1/v2 envelope 及当前 `type` 的最低结构要求时返回 `true`,并将 TypeScript 类型收窄为
684
+ * {@link MiniProgramBridgeMessage};否则返回 `false`。
685
+ *
686
+ * @remarks
687
+ * 所有通过的消息都必须使用 {@link MINI_PROGRAM_MESSAGE_NAMESPACE},`version` 必须为 `1` 或 `2`,
688
+ * `nonce` 必须为非空字符串。随后按 `type` 执行以下最低校验:
689
+ *
690
+ * - `handshake`(v1/v2):`id` 非空,`method` 固定为 {@link SDK_HANDSHAKE_METHOD},`error` 必须为 `undefined`;
691
+ * `payload` 必须是对象,且包含非空 `href`、字符串 `userAgent` 和非空 `sdkVersion`。
692
+ * - `request`(v1/v2):`id` 与 `method` 都是非空字符串,且 `error` 必须为 `undefined`;`payload` 不在此处校验。
693
+ * - `response`(v1/v2):`id` 非空;`method` 可省略,提供时必须非空;`error` 可省略,提供时必须含非空
694
+ * `code` 与字符串 `message`。该最低结构允许 `payload` 与合法 `error` 同时存在,终态语义由消费端决定。
695
+ * - 普通 `event`(v1/v2):`method` 非空、`error` 必须为 `undefined`,`id` 可省略或为非空字符串;事件名和
696
+ * `payload` 不在此处校验。
697
+ * - `operation.progress` 与 `cancel` 只接受 v2。progress 还要求非空 `id` 和受支持的下载或 companion
698
+ * prepare 进度 payload;cancel 要求非空 `id`,且 `method`、`payload`、`error` 都必须为 `undefined`。
699
+ *
700
+ * 返回 `true` 只表示 wire envelope 可识别,不建立信任或授权边界。该函数不会校验
701
+ * `MessageEvent.source` / `origin`,只检查 nonce 非空而不会与当前 iframe 的预期 nonce 比较,也不会确认
702
+ * 握手状态、协商后的版本、请求 ID 是否重复或对应 pending request。除握手和 operation progress 外,它也不校验
703
+ * payload schema;不会把普通 `method` / 事件名限制在公开目录,不会检查 Manifest 权限、Runtime 权限状态、
704
+ * Host 支持、可信用户手势或业务策略。顶层 envelope、握手 payload 与 bridge error 中的额外字段也不会被拒绝。
705
+ *
706
+ * [MINI_PROGRAM_MESSAGE_VERSION](/reference/symbols/protocol/constants/MINI_PROGRAM_MESSAGE_VERSION)
707
+ * 是新消息的发送版本,不是本 guard 的唯一接收版本;接受 v1 是兼容行为,
708
+ * 调用方仍须在握手后确认消息版本与已协商版本一致。method 是否公开及其权限 requirement 应查询
709
+ * [MINI_PROGRAM_PROTOCOL_CAPABILITIES](/reference/symbols/protocol/constants/MINI_PROGRAM_PROTOCOL_CAPABILITIES),
710
+ * 权限快照应先交给
711
+ * [parseMiniProgramRuntimePermissions](/reference/symbols/protocol/functions/parseMiniProgramRuntimePermissions) 解析。
712
+ *
713
+ * 类型谓词只收窄到宽泛的 {@link MiniProgramBridgeMessage}:`payload` 仍为 `unknown`,`method` 等字段仍保持可选。
714
+ * 需要精确处理 v2 cancel 或 operation progress 时,应在检查判别字段后使用
715
+ * [MiniProgramBridgeCancelMessage](/reference/symbols/protocol/interfaces/MiniProgramBridgeCancelMessage) 或
716
+ * [MiniProgramBridgeProgressMessage](/reference/symbols/protocol/interfaces/MiniProgramBridgeProgressMessage)。
717
+ *
718
+ * @example
719
+ * ```ts
720
+ * import {
721
+ * MINI_PROGRAM_PROTOCOL_CAPABILITIES,
722
+ * isMiniProgramBridgeMessage,
723
+ * } from '@heybox/hb-sdk/protocol';
724
+ *
725
+ * const publicMethods = new Set<string>(
726
+ * MINI_PROGRAM_PROTOCOL_CAPABILITIES.map(({ method }) => method),
727
+ * );
728
+ *
729
+ * window.addEventListener('message', (event) => {
730
+ * if (event.source !== iframe.contentWindow) return;
731
+ * if (expectedOrigin && expectedOrigin !== '*' && event.origin !== expectedOrigin) return;
732
+ * if (!isMiniProgramBridgeMessage(event.data)) return;
733
+ * if (event.data.nonce !== expectedNonce) return;
734
+ *
735
+ * if (event.data.type === 'request') {
736
+ * const method = event.data.method;
737
+ * if (!method || !publicMethods.has(method)) return;
738
+ * // 继续检查握手状态、权限与 method 对应的 payload。
739
+ * }
740
+ * });
741
+ * ```
742
+ *
743
+ * @see [MiniProgramBridgeMessage](/reference/symbols/protocol/interfaces/MiniProgramBridgeMessage) 宽泛的顶层 envelope 类型。
744
+ * @see [MINI_PROGRAM_MESSAGE_VERSION](/reference/symbols/protocol/constants/MINI_PROGRAM_MESSAGE_VERSION) 新消息的默认发送版本。
745
+ * @see [MINI_PROGRAM_BRIDGE_NONCE_PARAM](/reference/symbols/protocol/constants/MINI_PROGRAM_BRIDGE_NONCE_PARAM) iframe URL 中的 nonce 参数名。
746
+ * @see [MINI_PROGRAM_PROTOCOL_CAPABILITIES](/reference/symbols/protocol/constants/MINI_PROGRAM_PROTOCOL_CAPABILITIES) 公开 method 与权限 requirement 目录。
747
+ * @see [parseMiniProgramRuntimePermissions](/reference/symbols/protocol/functions/parseMiniProgramRuntimePermissions) Runtime 权限快照解析器。
748
+ */
633
749
  function isMiniProgramBridgeMessage(value) {
634
750
  if (!isRecord$2(value))
635
751
  return false;
@@ -660,6 +776,60 @@ function isMiniProgramBridgeMessage(value) {
660
776
  }
661
777
  return false;
662
778
  }
779
+ /**
780
+ * 判断未知值是否为以 `/` 分隔的规范逻辑相对路径。
781
+ *
782
+ * @param value - 来自 files API、derived ref、Host payload 或其他不可信边界的候选路径。
783
+ * @returns 值是满足协议语法的字符串时返回 `true`,并将 TypeScript 类型收窄为 `string`;否则返回 `false`。
784
+ *
785
+ * @remarks
786
+ * 该 guard 直接检查输入字符串,规则如下:
787
+ *
788
+ * - 必须是非空字符串;空串和非字符串值失败。
789
+ * - 不能以 `/` 开头或结尾,因此 `/absolute`、`nested/` 与 `/` 失败。
790
+ * - 不能包含反斜杠 `\\`、U+0000-U+001F 控制字符或 U+007F;Windows 风格分隔符不会被转换。
791
+ * - 按 `/` 分段后,每段必须非空且不能精确等于 `.` 或 `..`,因此连续 `/`、`nested/./file` 与
792
+ * `nested/../file` 失败。
793
+ *
794
+ * 只拒绝完整的 dot segment:`.env`、`..cache`、`file.` 与包含普通点号的名称都可通过;单独的 `'.'`
795
+ * 本身失败。{@link isMiniProgramDirectoryRef} 在外层显式允许 `relativePath: '.'` 表示 root 目录自身,
796
+ * {@link isMiniProgramFileRef} 则始终要求本 guard 通过,因此文件引用不能指向 root 自身。
797
+ *
798
+ * 该函数不 trim 空白、不 URL/percent decode、不 Unicode normalize、不折叠分隔符,也不应用平台保留名或
799
+ * 字符规则。空白段、`%2e%2e`、全角字符和 `C:/file` 等只要满足上述原始字符串规则就可能通过;路径长度、
800
+ * 段长度和段数量也没有在此限制。调用方不能把“通过”解释为操作系统级 canonical path。
801
+ *
802
+ * 返回 `true` 只证明语法可作为协议逻辑相对路径,不证明目标存在、末段是文件还是目录、root/handle 属于
803
+ * 当前 session/origin、`filesystem` 权限已启用、访问 mode 允许当前操作或 Host 支持该 capability。
804
+ * `normalizeRelativePath()` 这类 SDK/Runtime helper 只是复用本 predicate:合法时原样返回同一个字符串,非法时
805
+ * 转成对应 SDK/bridge 错误;它不会进一步规范化路径。
806
+ *
807
+ * @example
808
+ * ```ts
809
+ * import { isMiniProgramRelativePath } from '@heybox/hb-sdk/protocol';
810
+ *
811
+ * const paths: unknown[] = [
812
+ * 'data.json',
813
+ * 'nested/data.json',
814
+ * '.env',
815
+ * '.',
816
+ * '../secret',
817
+ * 'nested//file',
818
+ * 'nested\\file',
819
+ * ];
820
+ *
821
+ * const validPaths = paths.filter(isMiniProgramRelativePath);
822
+ * // ['data.json', 'nested/data.json', '.env']
823
+ * console.log(validPaths);
824
+ * ```
825
+ *
826
+ * @see [isMiniProgramFileRef](/reference/symbols/protocol/functions/isMiniProgramFileRef) 始终使用本规则的 derived 文件引用。
827
+ * @see [isMiniProgramDirectoryRef](/reference/symbols/protocol/functions/isMiniProgramDirectoryRef) 额外允许 `'.'` 的 derived 目录引用。
828
+ * @see [isMiniProgramPathRootRef](/reference/symbols/protocol/functions/isMiniProgramPathRootRef) 与相对路径组合的逻辑 root guard。
829
+ * @see [PathRoot](/reference/symbols/root/interfaces/PathRoot) 提供 `file()` / `directory()` 的 SDK 路径入口。
830
+ * @see [FileSystem](/reference/symbols/root/interfaces/FileSystem) `files.sandbox` 逻辑路径能力。
831
+ * @see [DirectoryHandle](/reference/symbols/root/interfaces/DirectoryHandle) 已授权目录下的相对路径能力。
832
+ */
663
833
  function isMiniProgramRelativePath(value) {
664
834
  if (typeof value !== 'string' || !value || value.startsWith('/') || value.endsWith('/')) {
665
835
  return false;
@@ -668,6 +838,64 @@ function isMiniProgramRelativePath(value) {
668
838
  return false;
669
839
  return value.split('/').every((segment) => Boolean(segment) && segment !== '.' && segment !== '..');
670
840
  }
841
+ /**
842
+ * 判断未知值是否可作为 derived file/directory ref 的逻辑路径 root。
843
+ *
844
+ * @param value - 来自文件引用、目录引用或其他不可信 wire 边界的候选 root。
845
+ * @returns 值满足 sandbox root 或 direct directory root 任一结构时返回 `true`,并将 TypeScript 类型
846
+ * 收窄为 {@link MiniProgramPathRootRef} 判别联合;否则返回 `false`。
847
+ *
848
+ * @remarks
849
+ * 支持两个以 `kind` 区分的分支:
850
+ *
851
+ * - Sandbox root:`{ kind: 'sandbox' }`。对通常的对象字面量,除 `kind` 外不能携带任何字段。
852
+ * - Directory root:`{ kind: 'directory', handleId }`。`handleId` 必须是非空字符串;空白字符串仍满足
853
+ * 本 guard 的最低结构,格式、长度和归属由 Runtime 继续校验。
854
+ *
855
+ * direct file ref、derived directory ref、普通路径字符串以及其他 `kind` 都不能作为 PathRoot。特别是
856
+ * `{ kind: 'directory', root, relativePath }` 会因额外 canonical 外字段而失败:derived ref 只能引用 sandbox
857
+ * 或 direct directory root,不能递归嵌套另一层 derived root。
858
+ *
859
+ * 两个分支都会拒绝 canonical 集合之外的可枚举自有字符串键,包括值为 `undefined` 的额外键。检查基于
860
+ * `Object.keys()`,因此非枚举属性、symbol 键和继承属性不会被列入;必需属性本身也不要求是自有或可枚举
861
+ * 属性。该函数不会复制、冻结或规范化输入。
862
+ *
863
+ * 返回 `true` 只建立结构类型收窄,不证明 directory `handleId` 由当前 Runtime 签发、属于当前 session/origin、
864
+ * 仍然有效且确为目录,也不证明 `filesystem` 权限、目录访问 mode、provenance 或 Host capability。sandbox
865
+ * 标记同样不自行建立隔离边界;Runtime 必须把它解析到当前 Mini-program 的私有 root 并执行实际权限策略。
866
+ *
867
+ * {@link isMiniProgramFileRef} 与 {@link isMiniProgramDirectoryRef} 都用该 guard 校验 derived ref 的 `root`;
868
+ * 它只校验 root 身份,不校验各自的 `relativePath`。
869
+ *
870
+ * @example
871
+ * ```ts
872
+ * import { isMiniProgramPathRootRef } from '@heybox/hb-sdk/protocol';
873
+ *
874
+ * const candidates: unknown[] = [
875
+ * { kind: 'sandbox' },
876
+ * { kind: 'directory', handleId: 'directory_1' },
877
+ * ];
878
+ *
879
+ * for (const candidate of candidates) {
880
+ * if (!isMiniProgramPathRootRef(candidate)) continue;
881
+ * if (candidate.kind === 'sandbox') {
882
+ * console.log('private sandbox root');
883
+ * } else {
884
+ * console.log('authorized directory root', candidate.handleId);
885
+ * }
886
+ * }
887
+ *
888
+ * isMiniProgramPathRootRef({ kind: 'file', handleId: 'file_1' }); // false
889
+ * isMiniProgramPathRootRef({ kind: 'directory', root: { kind: 'sandbox' }, relativePath: 'nested' }); // false
890
+ * ```
891
+ *
892
+ * @see [MiniProgramPathRootRef](/reference/symbols/protocol/types/MiniProgramPathRootRef) sandbox/direct-directory 联合类型。
893
+ * @see [isMiniProgramFileRef](/reference/symbols/protocol/functions/isMiniProgramFileRef) 使用 PathRoot 的 derived 文件引用。
894
+ * @see [isMiniProgramDirectoryRef](/reference/symbols/protocol/functions/isMiniProgramDirectoryRef) 使用 PathRoot 的 derived 目录引用。
895
+ * @see [PathRoot](/reference/symbols/root/interfaces/PathRoot) SDK 公开的逻辑路径 root 能力。
896
+ * @see [FilesModule](/reference/symbols/root/interfaces/FilesModule) 提供 `files.sandbox` 与目录 picker 的入口。
897
+ * @see [DirectoryHandle](/reference/symbols/root/interfaces/DirectoryHandle) 可作为 derived path root 的目录代理。
898
+ */
671
899
  function isMiniProgramPathRootRef(value) {
672
900
  if (!isRecord$2(value))
673
901
  return false;
@@ -675,6 +903,65 @@ function isMiniProgramPathRootRef(value) {
675
903
  return hasOnlyKeys(value, ['kind']);
676
904
  return value.kind === 'directory' && isNonEmptyString$1(value.handleId) && hasOnlyKeys(value, ['kind', 'handleId']);
677
905
  }
906
+ /**
907
+ * 判断未知值是否为 direct handle 或 path-derived 文件引用。
908
+ *
909
+ * @param value - 来自 descriptor、capability payload 或其他不可信 wire 边界的候选文件引用。
910
+ * @returns 值满足 {@link MiniProgramFileRef} 任一分支的最低结构时返回 `true`,并将 TypeScript 类型
911
+ * 收窄为 direct/derived 文件引用联合;否则返回 `false`。
912
+ *
913
+ * @remarks
914
+ * 两个分支都要求 `kind === 'file'`,并对通常的对象字面量使用互斥的 canonical key 集合:
915
+ *
916
+ * - Direct ref:`{ kind: 'file', handleId }`。`handleId` 必须是非空字符串;不能同时携带 `root` 或
917
+ * `relativePath`。
918
+ * - Derived ref:`{ kind: 'file', root, relativePath }`。不能携带 `handleId`;`root` 必须通过
919
+ * {@link isMiniProgramPathRootRef},即精确的 `{ kind: 'sandbox' }`,或带非空 `handleId` 的 direct
920
+ * directory root。file ref 与再次嵌套的 derived directory ref 都不能作为 root。
921
+ *
922
+ * Derived ref 的 `relativePath` 必须通过 {@link isMiniProgramRelativePath}:非空、不以 `/` 开头或结尾,
923
+ * 不含空段、`.` / `..` 点段、反斜杠、U+0000-U+001F 控制字符或 U+007F。文件必须指向 root 下的具体路径,
924
+ * 因此与 {@link isMiniProgramDirectoryRef} 不同,`relativePath: '.'` 不合法。该 guard 不会 URL decode、
925
+ * Unicode normalize、解析平台分隔符、限制路径长度,或确认末段是文件而不是目录。
926
+ *
927
+ * direct 与 derived 分支都会拒绝 canonical 集合之外的可枚举自有字符串键,包括值为 `undefined` 的额外键。
928
+ * 检查基于 `Object.keys()`,因此非枚举属性、symbol 键和继承属性不会被列入;必需属性本身也不要求是自有
929
+ * 或可枚举属性。返回对象不会被复制、冻结或规范化。
930
+ *
931
+ * 返回 `true` 只证明当前结构可按 wire 类型读取,不证明 direct `handleId` 或 root handle 由当前 Runtime 签发、
932
+ * 属于当前 session/origin、仍然有效且类型匹配,也不证明目标文件存在、`filesystem` 权限已启用、访问 mode
933
+ * 允许当前操作或 Host 支持对应 capability。Runtime 在实际解析 ref 时仍须查询 handle registry,执行权限、
934
+ * provenance 与目标类型校验,并解析 derived path。
935
+ *
936
+ * @example
937
+ * ```ts
938
+ * import { isMiniProgramFileRef } from '@heybox/hb-sdk/protocol';
939
+ *
940
+ * const candidate: unknown = {
941
+ * kind: 'file',
942
+ * root: { kind: 'directory', handleId: 'directory_1' },
943
+ * relativePath: 'screenshots/cover.png',
944
+ * };
945
+ *
946
+ * if (isMiniProgramFileRef(candidate)) {
947
+ * if ('handleId' in candidate) {
948
+ * console.log('direct', candidate.handleId);
949
+ * } else {
950
+ * console.log('derived', candidate.root, candidate.relativePath);
951
+ * }
952
+ * }
953
+ *
954
+ * isMiniProgramFileRef({ kind: 'file', handleId: 'file_1' }); // true
955
+ * isMiniProgramFileRef({ kind: 'file', root: { kind: 'sandbox' }, relativePath: '.' }); // false
956
+ * ```
957
+ *
958
+ * @see [MiniProgramFileRef](/reference/symbols/protocol/types/MiniProgramFileRef) direct/derived 联合类型。
959
+ * @see [isMiniProgramPathRootRef](/reference/symbols/protocol/functions/isMiniProgramPathRootRef) derived ref 的 root guard。
960
+ * @see [isMiniProgramRelativePath](/reference/symbols/protocol/functions/isMiniProgramRelativePath) derived 文件路径规则。
961
+ * @see [isMiniProgramFileDescriptor](/reference/symbols/protocol/functions/isMiniProgramFileDescriptor) 包含名称和 mode 的文件 descriptor guard。
962
+ * @see [isMiniProgramDirectoryRef](/reference/symbols/protocol/functions/isMiniProgramDirectoryRef) 可用 `'.'` 指向 root 自身的目录引用 guard。
963
+ * @see [FileHandle](/reference/symbols/root/interfaces/FileHandle) 使用文件引用的公开 I/O 代理。
964
+ */
678
965
  function isMiniProgramFileRef(value) {
679
966
  if (!isRecord$2(value) || value.kind !== 'file')
680
967
  return false;
@@ -683,6 +970,65 @@ function isMiniProgramFileRef(value) {
683
970
  }
684
971
  return (isMiniProgramPathRootRef(value.root) && isMiniProgramRelativePath(value.relativePath) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
685
972
  }
973
+ /**
974
+ * 判断未知值是否为 direct handle 或 path-derived 目录引用。
975
+ *
976
+ * @param value - 来自 descriptor、capability payload 或其他不可信 wire 边界的候选目录引用。
977
+ * @returns 值满足 {@link MiniProgramDirectoryRef} 任一分支的最低结构时返回 `true`,并将 TypeScript 类型
978
+ * 收窄为 direct/derived 目录引用联合;否则返回 `false`。
979
+ *
980
+ * @remarks
981
+ * 两个分支都要求 `kind === 'directory'`,并对通常的对象字面量使用互斥的 canonical key 集合:
982
+ *
983
+ * - Direct ref:`{ kind: 'directory', handleId }`。`handleId` 必须是非空字符串;不能同时携带 `root` 或
984
+ * `relativePath`。
985
+ * - Derived ref:`{ kind: 'directory', root, relativePath }`。不能携带 `handleId`;`root` 必须通过
986
+ * {@link isMiniProgramPathRootRef},即精确的 `{ kind: 'sandbox' }`,或带非空 `handleId` 的 direct
987
+ * directory root。file ref 与再次嵌套的 derived directory ref 都不能作为 root。
988
+ *
989
+ * Derived ref 的 `relativePath` 可以是 `'.'`,表示 root 目录自身;这是目录引用专属规则,普通
990
+ * {@link isMiniProgramRelativePath} 和 file ref 都不接受 `'.'`。其他相对路径必须非空,不以 `/` 开头或结尾,
991
+ * 不含空段、`.` / `..` 点段、反斜杠、U+0000-U+001F 控制字符或 U+007F。该校验不会 URL decode、
992
+ * Unicode normalize、解析平台分隔符、限制长度,或判断路径指向的目录是否存在。
993
+ *
994
+ * direct 与 derived 分支都会拒绝 canonical 集合之外的可枚举自有字符串键,包括值为 `undefined` 的额外键。
995
+ * 检查基于 `Object.keys()`,因此非枚举属性、symbol 键和继承属性不会被列入;必需属性本身也不要求是自有
996
+ * 或可枚举属性。返回对象不会被复制、冻结或规范化。
997
+ *
998
+ * 返回 `true` 只证明当前结构可按 wire 类型读取,不证明 direct `handleId` 或 root handle 由当前 Runtime 签发、
999
+ * 属于当前 session/origin、仍然有效且确为目录,也不证明目标存在、`filesystem` 权限已启用、访问模式允许
1000
+ * 当前操作或 Host 支持对应 capability。Runtime 在实际解析 ref 时仍须查询 handle registry、执行权限与
1001
+ * provenance 校验,并解析 derived path。
1002
+ *
1003
+ * @example
1004
+ * ```ts
1005
+ * import { isMiniProgramDirectoryRef } from '@heybox/hb-sdk/protocol';
1006
+ *
1007
+ * const candidate: unknown = {
1008
+ * kind: 'directory',
1009
+ * root: { kind: 'directory', handleId: 'directory_1' },
1010
+ * relativePath: 'screenshots/2026',
1011
+ * };
1012
+ *
1013
+ * if (isMiniProgramDirectoryRef(candidate)) {
1014
+ * if ('handleId' in candidate) {
1015
+ * console.log('direct', candidate.handleId);
1016
+ * } else {
1017
+ * console.log('derived', candidate.root, candidate.relativePath);
1018
+ * }
1019
+ * }
1020
+ *
1021
+ * isMiniProgramDirectoryRef({ kind: 'directory', root: { kind: 'sandbox' }, relativePath: '.' }); // true
1022
+ * isMiniProgramDirectoryRef({ kind: 'directory', handleId: 'd1', relativePath: '.' }); // false:分支键混用
1023
+ * ```
1024
+ *
1025
+ * @see [MiniProgramDirectoryRef](/reference/symbols/protocol/types/MiniProgramDirectoryRef) direct/derived 联合类型。
1026
+ * @see [isMiniProgramPathRootRef](/reference/symbols/protocol/functions/isMiniProgramPathRootRef) derived ref 的 root guard。
1027
+ * @see [isMiniProgramRelativePath](/reference/symbols/protocol/functions/isMiniProgramRelativePath) 非 `'.'` 相对路径规则。
1028
+ * @see [isMiniProgramDirectoryDescriptor](/reference/symbols/protocol/functions/isMiniProgramDirectoryDescriptor) 包含名称和 mode 的目录 descriptor guard。
1029
+ * @see [isMiniProgramFileRef](/reference/symbols/protocol/functions/isMiniProgramFileRef) 不接受 root 自身 `'.'` 的文件引用 guard。
1030
+ * @see [DirectoryHandle](/reference/symbols/root/interfaces/DirectoryHandle) 使用目录引用的公开路径操作代理。
1031
+ */
686
1032
  function isMiniProgramDirectoryRef(value) {
687
1033
  if (!isRecord$2(value) || value.kind !== 'directory')
688
1034
  return false;
@@ -691,9 +1037,117 @@ function isMiniProgramDirectoryRef(value) {
691
1037
  }
692
1038
  return (isMiniProgramPathRootRef(value.root) && (value.relativePath === '.' || isMiniProgramRelativePath(value.relativePath)) && hasOnlyKeys(value, ['kind', 'root', 'relativePath']));
693
1039
  }
1040
+ /**
1041
+ * 判断未知值是否为使用普通 `ArrayBuffer` 存储的 `Uint8Array` 字节视图。
1042
+ *
1043
+ * @param value - 来自 bridge payload、Host 返回值或其他不可信边界的候选字节数据。
1044
+ * @returns 值是当前 realm 的 `Uint8Array`(或其子类),且 `buffer` 是 `ArrayBuffer` 时返回 `true`,
1045
+ * 并将 TypeScript 类型收窄为 `Uint8Array`;否则返回 `false`。
1046
+ *
1047
+ * @remarks
1048
+ * `Uint8Array` 的每个索引元素由 JavaScript 保证为 `0` 到 `255` 的整数。本 guard 接受空视图、非零
1049
+ * `byteOffset` 以及只覆盖底层 buffer 一部分的视图;它不要求视图覆盖整个 `ArrayBuffer`,也不限制
1050
+ * `byteLength`、文件大小或 Companion stdio 消息大小。
1051
+ *
1052
+ * 普通数组无论是否稀疏、`ArrayBuffer` 本身、`DataView`、`Int8Array`、`Uint8ClampedArray` 及其他 typed array
1053
+ * 都会被拒绝。使用 `SharedArrayBuffer` 作为 backing buffer 的 `Uint8Array` 也会被拒绝。由于判断依赖
1054
+ * `instanceof`,由另一个 JavaScript realm 创建且未经过 structured clone 重建的 `Uint8Array` 可能无法通过;
1055
+ * 当前 realm 的 `Uint8Array` 子类则可能通过。
1056
+ *
1057
+ * 该函数不会枚举键,因此挂在 `Uint8Array` 实例上的额外自有属性不会导致失败;它也不会检查 buffer
1058
+ * 是否已 detached、数据来源是否可信、内容是否符合业务格式,或调用方是否拥有文件/Companion 权限。
1059
+ * 返回 `true` 后仍得到原来的可变视图,而不是副本或冻结值。跨异步边界持有或交给其他消费者前,建议使用
1060
+ * `new Uint8Array(value)` 创建只包含当前视图字节的快照。
1061
+ *
1062
+ * 文件 `readBytes()` 用它识别 Host 返回的
1063
+ * [FileReadBytesResult](/reference/symbols/protocol/types/FileReadBytesResult),`writeBytes()` 的
1064
+ * [FileWriteBytesPayload](/reference/symbols/protocol/interfaces/FileWriteBytesPayload) `content` 也采用同一字节表示;
1065
+ * 路径、句柄类型和访问模式由文件引用与 descriptor guards 单独校验。Companion stdio 的 stdin、stdout 和 stderr
1066
+ * 同样传输 `Uint8Array`,但 Session ownership、controller generation、stream、sequence、framing、容量与权限
1067
+ * 都不属于本 guard 的职责。
1068
+ *
1069
+ * @example
1070
+ * ```ts
1071
+ * import { isMiniProgramByteArray } from '@heybox/hb-sdk/protocol';
1072
+ *
1073
+ * const candidate: unknown = new Uint8Array([0, 128, 255]);
1074
+ * if (!isMiniProgramByteArray(candidate)) {
1075
+ * throw new TypeError('需要 ArrayBuffer-backed Uint8Array');
1076
+ * }
1077
+ *
1078
+ * // guard 只做结构收窄;复制后再跨异步边界使用。
1079
+ * const snapshot = new Uint8Array(candidate);
1080
+ *
1081
+ * isMiniProgramByteArray([0, 128, 255]); // false:普通数组不是 wire 字节视图
1082
+ * isMiniProgramByteArray(new DataView(new ArrayBuffer(3))); // false
1083
+ * ```
1084
+ *
1085
+ * @see [FileHandle](/reference/symbols/root/interfaces/FileHandle) `readBytes()` 与 `writeBytes()` 的业务入口。
1086
+ * @see [FileReadBytesResult](/reference/symbols/protocol/types/FileReadBytesResult) 文件二进制读取结果。
1087
+ * @see [FileWriteBytesPayload](/reference/symbols/protocol/interfaces/FileWriteBytesPayload) 文件二进制写入 payload。
1088
+ * @see [CompanionStdio](/reference/symbols/root/interfaces/CompanionStdio) Companion 原始字节 stdin/stdout/stderr。
1089
+ * @see [isMiniProgramFileDescriptor](/reference/symbols/protocol/functions/isMiniProgramFileDescriptor) 文件 descriptor guard。
1090
+ * @see [isMiniProgramDirectoryDescriptor](/reference/symbols/protocol/functions/isMiniProgramDirectoryDescriptor) 目录 descriptor guard。
1091
+ */
694
1092
  function isMiniProgramByteArray(value) {
695
1093
  return value instanceof Uint8Array && value.buffer instanceof ArrayBuffer;
696
1094
  }
1095
+ /**
1096
+ * 判断未知值是否具有文件元数据快照的最低 wire 结构。
1097
+ *
1098
+ * @param value - 来自 `file.stat` Host 返回值、bridge response 或其他不可信边界的候选元数据。
1099
+ * @returns `kind`、`size` 与可选时间字段满足 {@link MiniProgramFileStat} 结构时返回 `true`,并将
1100
+ * TypeScript 类型收窄为文件元数据;否则返回 `false`。
1101
+ *
1102
+ * @remarks
1103
+ * 对通常的对象字面量,仅允许 `kind`、`size`、`modifiedAt`、`createdAt` 四个 canonical key:
1104
+ *
1105
+ * - `kind` 必须固定为 `'file'`。
1106
+ * - `size` 必须是 `0` 到 `Number.MAX_SAFE_INTEGER` 范围内的整数。`0` 表示空文件;负数、小数、`NaN`、
1107
+ * `Infinity`、unsafe integer、bigint 和数字字符串都会被拒绝。文件 API 将该值解释为字节数,但本 guard
1108
+ * 只验证数字结构,不能证明 Host 使用了正确单位。
1109
+ * - `modifiedAt` 与 `createdAt` 相互独立且都可省略,也可显式为 `undefined`;提供时必须是非负有限 number。
1110
+ * 与 `size` 不同,时间值不要求是整数或 safe integer,因此非负小数以及大于 `Number.MAX_SAFE_INTEGER`
1111
+ * 但仍有限的值都可通过。
1112
+ *
1113
+ * 文件 API 把时间字段解释为 Unix epoch milliseconds,但该 guard 不验证值是否落在 JavaScript `Date`
1114
+ * 可表示范围内,也不要求 `createdAt <= modifiedAt`、时间不晚于当前时刻,或两项同时存在。消费者若要排序、
1115
+ * 格式化或比较时间,仍须按自己的业务范围继续校验。
1116
+ *
1117
+ * canonical 集合之外的可枚举自有字符串键会导致失败,包括值为 `undefined` 的额外键;非枚举属性、
1118
+ * symbol 键和继承属性不在 `Object.keys()` 检查范围内,必需字段本身也不要求是自有或可枚举属性。
1119
+ * 该函数不会复制、冻结或规范化输入,返回的仍是原始可变对象。
1120
+ *
1121
+ * 返回 `true` 只建立结构类型收窄,不证明该快照来自可信 Host、对应当前 `FileHandle` 或当前 request,也不证明
1122
+ * 文件仍然存在、`size` 与磁盘内容一致、时间由文件系统提供、handle 属于当前 session/origin、`filesystem`
1123
+ * 权限已启用或 Host 支持 `file.stat`。这些关联、权限与 I/O 错误必须由 Runtime 和 `FileHandle.stat()` 调用链处理。
1124
+ *
1125
+ * @example
1126
+ * ```ts
1127
+ * import { isMiniProgramFileStat } from '@heybox/hb-sdk/protocol';
1128
+ *
1129
+ * const candidate: unknown = {
1130
+ * kind: 'file',
1131
+ * size: 4096,
1132
+ * modifiedAt: 1_795_027_200_000,
1133
+ * };
1134
+ *
1135
+ * if (isMiniProgramFileStat(candidate)) {
1136
+ * console.log(`${candidate.size} bytes`);
1137
+ * if (candidate.modifiedAt !== undefined) {
1138
+ * console.log(candidate.modifiedAt);
1139
+ * }
1140
+ * }
1141
+ *
1142
+ * isMiniProgramFileStat({ kind: 'file', size: 0 }); // true:时间字段可全部省略
1143
+ * isMiniProgramFileStat({ kind: 'file', size: 1.5 }); // false:size 必须是 safe integer
1144
+ * ```
1145
+ *
1146
+ * @see [MiniProgramFileStat](/reference/symbols/protocol/interfaces/MiniProgramFileStat) bridge 使用的元数据字段类型。
1147
+ * @see [FileStatResult](/reference/symbols/protocol/types/FileStatResult) `file.stat` 的 wire 返回类型。
1148
+ * @see [FileStat](/reference/symbols/root/interfaces/FileStat) SDK 向业务返回的元数据快照。
1149
+ * @see [FileHandle](/reference/symbols/root/interfaces/FileHandle) 提供 `stat()` 的当前 session 文件代理。
1150
+ */
697
1151
  function isMiniProgramFileStat(value) {
698
1152
  return (isRecord$2(value) &&
699
1153
  value.kind === 'file' &&
@@ -702,6 +1156,58 @@ function isMiniProgramFileStat(value) {
702
1156
  (value.createdAt === undefined || isNonNegativeFiniteNumber(value.createdAt)) &&
703
1157
  hasOnlyKeys(value, ['kind', 'size', 'modifiedAt', 'createdAt']));
704
1158
  }
1159
+ /**
1160
+ * 判断未知值是否为单个 `network.download` 进度 payload。
1161
+ *
1162
+ * @param value - 来自 operation progress 事件、Host adapter 或其他不可信边界的候选进度快照。
1163
+ * @returns 字段组合满足 {@link DownloadProgressPayload} 的最低 wire 约束时返回 `true`,并将 TypeScript
1164
+ * 类型收窄为下载进度 payload;否则返回 `false`。
1165
+ *
1166
+ * @remarks
1167
+ * 对通常的对象字面量,仅允许 `loaded`、`total`、`lengthComputable` 三个 canonical key,并执行以下组合校验:
1168
+ *
1169
+ * - `loaded` 始终必需,必须是 `0` 到 `Number.MAX_SAFE_INTEGER` 范围内的整数。负数、小数、`NaN`、
1170
+ * `Infinity`、unsafe integer、bigint 和数字字符串都会被拒绝。
1171
+ * - `lengthComputable` 必须是 boolean,不能使用 `0` / `1` 或其他 truthy/falsy 值代替。
1172
+ * - `lengthComputable === false` 时,`total` 必须为 `undefined`;既可以省略该 key,也可以显式写成
1173
+ * `total: undefined`。此分支不对 `loaded` 应达到的最终值作推断。
1174
+ * - `lengthComputable === true` 时,`total` 必须是非负 safe integer,且 `loaded <= total`。
1175
+ * `{ loaded: 0, total: 0, lengthComputable: true }` 是有效的空内容进度。
1176
+ *
1177
+ * canonical 集合之外的可枚举自有字符串键会导致失败;非枚举属性、symbol 键和继承属性不在
1178
+ * `Object.keys()` 检查范围内,必需字段本身也不要求是自有或可枚举属性。该函数不会复制、冻结或
1179
+ * 规范化输入。类型谓词只收窄到字段仍为可变、`total` 仍为可选的 {@link DownloadProgressPayload},
1180
+ * 不会在 TypeScript 中建立以 `lengthComputable` 为判别字段的精确联合。
1181
+ *
1182
+ * 单个 payload 通过不表示进度来自当前 request、使用当前 pending operation 的 ID,或由可信 Host 产生;
1183
+ * 也不保证单位确为字节、事件按时间排序、`loaded` 相对前一事件单调、`total` 跨事件稳定、这是最终进度,
1184
+ * 或对应字节已经原子提交到目标文件。`network.download` 的 Runtime 状态机必须另行绑定 request ID,校验
1185
+ * 可信响应 framing、`maxBytes`、取消与终态,并过滤倒退或越界值。
1186
+ *
1187
+ * @example
1188
+ * ```ts
1189
+ * import { isMiniProgramDownloadProgressPayload } from '@heybox/hb-sdk/protocol';
1190
+ *
1191
+ * function renderProgress(candidate: unknown) {
1192
+ * if (!isMiniProgramDownloadProgressPayload(candidate)) return;
1193
+ *
1194
+ * if (candidate.lengthComputable && candidate.total !== undefined) {
1195
+ * console.log(`${candidate.loaded}/${candidate.total}`);
1196
+ * } else {
1197
+ * console.log(`${candidate.loaded} bytes`);
1198
+ * }
1199
+ * }
1200
+ *
1201
+ * renderProgress({ loaded: 512, total: 1024, lengthComputable: true }); // valid
1202
+ * renderProgress({ loaded: 512, lengthComputable: false }); // valid:总长度未知
1203
+ * renderProgress({ loaded: 5, total: 4, lengthComputable: true }); // ignored:loaded > total
1204
+ * ```
1205
+ *
1206
+ * @see [DownloadProgressPayload](/reference/symbols/protocol/interfaces/DownloadProgressPayload) bridge 使用的进度字段类型。
1207
+ * @see [DownloadProgress](/reference/symbols/root/interfaces/DownloadProgress) `onProgress` 接收的公开 SDK 进度类型。
1208
+ * @see [network.download](/reference/sdk/network/download) 产生并消费该进度的下载能力。
1209
+ * @see [isMiniProgramBridgeMessage](/reference/symbols/protocol/functions/isMiniProgramBridgeMessage) operation progress envelope 的最低校验。
1210
+ */
705
1211
  function isMiniProgramDownloadProgressPayload(value) {
706
1212
  if (!isRecord$2(value) ||
707
1213
  !isNonNegativeSafeInteger(value.loaded) ||
@@ -835,7 +1341,7 @@ function createMessageId() {
835
1341
  /** 构建时替换为当前发布包的实际版本。 */
836
1342
  const HB_SDK_VERSION = typeof undefined === 'string'
837
1343
  ? undefined
838
- : '0.8.2-alpha.1';
1344
+ : '0.8.2-alpha.5';
839
1345
 
840
1346
  const RUNTIME_MODES = new Set(['production', 'preview', 'development', 'unknown']);
841
1347
  const OPERATING_SYSTEM_NAMES = new Set(['android', 'ios', 'ohos', 'windows', 'macos', 'linux', 'unknown']);
@@ -1384,12 +1890,24 @@ function waitForHandshakeOrAbort(handshake, signal, createAbortError, getTermina
1384
1890
  });
1385
1891
  }
1386
1892
 
1387
- /** 获取短期授权码。 */
1893
+ /**
1894
+ * 获取短期授权码。
1895
+ *
1896
+ * @param requester - SDK 内部的能力请求器。
1897
+ * @param options - 可选的资料 scope;不传时不附带请求载荷。
1898
+ * @returns 与 {@link MiniProgramAuthModule.login} 相同的授权码结果。
1899
+ * @throws {@link HbMiniProgramSDKError} 当 Host 拒绝请求、用户取消授权或 SDK 状态无效时抛出。
1900
+ */
1388
1901
  function login(requester, options) {
1389
1902
  const payload = options?.scopes === undefined ? undefined : { scopes: options.scopes };
1390
1903
  return requester.request(AUTH_LOGIN_METHOD, payload);
1391
1904
  }
1392
- /** 创建授权模块。 */
1905
+ /**
1906
+ * 创建授权模块。
1907
+ *
1908
+ * @param requester - SDK 内部的能力请求器。
1909
+ * @returns 绑定到该 requester 的授权模块。
1910
+ */
1393
1911
  function createAuthModule(requester) {
1394
1912
  return {
1395
1913
  login: (options) => login(requester, options),
@@ -2039,9 +2557,35 @@ function createCompanionModule(requester) {
2039
2557
  * 复制当前小程序的通用分享链接。
2040
2558
  *
2041
2559
  * @param requester - 底层 bridge 请求能力。
2042
- * @param options - 分享扩展数据;不传时复制默认首页链接。
2043
- * @returns 已写入系统剪贴板的完整分享链接。
2044
- * @throws {@link HbMiniProgramSDKError} 当参数、bridge、父容器或剪贴板能力调用失败时抛出。
2560
+ * @param options - 可选配置;只接受本次链接需要携带的 `extra`。省略 `options` 或
2561
+ * `options.extra` 时生成不带扩展数据的链接。
2562
+ * @returns Host 完成剪贴板写入后 resolve 的完整分享链接;返回字符串与剪贴板内容一致。
2563
+ * @throws {@link HbMiniProgramSDKError} 参数、`extra` 编码或小程序身份不合法时返回
2564
+ * `INVALID_PARAMS`;未声明或未启用 `share` 权限时分别返回
2565
+ * `PERMISSION_NOT_DECLARED` 或 `PERMISSION_DENIED`;当前 Host 未开放剪贴板能力时可返回
2566
+ * `METHOD_FORBIDDEN` 或 `REQUEST_UNSUPPORTED`。握手、bridge 超时和其他 Host 写入失败会保留
2567
+ * 对应错误码。
2568
+ *
2569
+ * @remarks 该方法生成当前小程序的固定通用落地页,不复制当前页面路径或 hash,也不继承
2570
+ * 启动 URL 中已有的 `extra`。显式传入的 `extra` 会先编码,再作为 Base64URL 参数写入链接;
2571
+ * 接收方使用 {@link MiniProgramShareModule.getExtra | share.getExtra} 读取还原值。
2572
+ *
2573
+ * 该调用需要声明 `share` 权限,但不额外要求 `clipboard` 权限或可信用户手势。它只写入
2574
+ * 系统剪贴板,不会打开分享面板或自动显示成功提示。
2575
+ *
2576
+ * @example
2577
+ * ```ts
2578
+ * import hbSDK from '@heybox/hb-sdk'
2579
+ *
2580
+ * const copiedUrl = await hbSDK.share.copyLink({
2581
+ * extra: { page: 'ranking', season: 12 },
2582
+ * })
2583
+ *
2584
+ * console.log('已复制分享链接', copiedUrl)
2585
+ * ```
2586
+ *
2587
+ * @see {@link MiniProgramShareModule.getExtra | share.getExtra}
2588
+ * @see {@link MiniProgramShareModule.showShareMenu | share.showShareMenu}
2045
2589
  */
2046
2590
  function copyLink(requester, options) {
2047
2591
  return requester.request(SHARE_COPY_LINK_METHOD, options);
@@ -3242,9 +3786,16 @@ function decodeBase64Url(value) {
3242
3786
  * 截图并唤起分享。
3243
3787
  *
3244
3788
  * @param requester - 底层 bridge 请求能力。
3245
- * @param options - 截图区域、延迟与保存相册等配置。
3246
- * @returns 由宿主客户端协议决定的结果。
3247
- * @throws {@link HbMiniProgramSDKError} 当 bridge、父容器或宿主能力调用失败时抛出。
3789
+ * @param options - 可选截图配置;省略时截取当前可见窗口。
3790
+ * @returns Host 返回的不透明截图分享结果;不要依赖其具体结构。
3791
+ * @throws {@link HbMiniProgramSDKError} 参数、权限、bridge、Runtime 或 Host 截图能力失败时抛出。
3792
+ *
3793
+ * @remarks
3794
+ * 公开业务代码通常通过 {@link MiniProgramShareModule.screenshot | share.screenshot} 调用;
3795
+ * 完整参数、平台和恢复语义见该方法。
3796
+ *
3797
+ * @see {@link MiniProgramShareModule.screenshot | share.screenshot}
3798
+ * @see {@link MiniProgramScreenshotOptions}
3248
3799
  */
3249
3800
  function screenshot(requester, options) {
3250
3801
  return requester.request(SHARE_SCREENSHOT_METHOD, options);
@@ -3254,9 +3805,12 @@ function screenshot(requester, options) {
3254
3805
  * 展示以当前小程序通用分享页为落地页的基础分享面板。
3255
3806
  *
3256
3807
  * @param requester - 底层 bridge 请求能力。
3257
- * @param options - 基础分享参数。
3258
- * @returns 由宿主客户端协议决定的结果。
3259
- * @throws {@link HbMiniProgramSDKError} 当 bridge、父容器或宿主能力调用失败时抛出。
3808
+ * @param options - 标题、描述,以及可选缩略图、渠道、扩展数据和社区发帖预置。
3809
+ * @returns Host 分享面板返回的 `unknown` 不透明值;不能依赖字段或真假值判断分享结果。
3810
+ * @throws {@link HbMiniProgramSDKError} 参数、固定落地页身份、`extra` 或开发态 `post` 校验失败
3811
+ * 时返回 `INVALID_PARAMS`;权限、Host 能力及生命周期错误见公开模块方法文档。
3812
+ * @remarks 不支持自定义 `url`、宿主回调或直接发布;社区预置仍由用户在客户端修改确认。
3813
+ * @see [share.showShareMenu](/reference/sdk/share/showShareMenu)
3260
3814
  */
3261
3815
  function showShareMenu(requester, options) {
3262
3816
  return requester.request(SHARE_SHOW_SHARE_MENU_METHOD, options);
@@ -3266,6 +3820,7 @@ function showShareMenu(requester, options) {
3266
3820
  * 创建分享模块。
3267
3821
  *
3268
3822
  * @param requester - 底层 bridge 请求能力。
3823
+ * @param launchHref - 可选的小程序启动 URL;`getExtra()` 从这里同步解析分享扩展数据。
3269
3824
  * @returns 面向业务层的分享模块对象。
3270
3825
  */
3271
3826
  function createShareModule(requester, launchHref) {
@@ -3651,7 +4206,14 @@ function isDirectChildFileRef(directory, file) {
3651
4206
  function invalidDownloadResult(message) {
3652
4207
  throw createSDKError('INVALID_NETWORK_RESPONSE', message);
3653
4208
  }
3654
- /** 发起不使用 bridge 固定总时长 timer 的流式下载。 */
4209
+ /**
4210
+ * 发起不使用 bridge 固定总时长 timer 的流式下载。
4211
+ *
4212
+ * @param requester - 支持 request-scoped 取消与进度的 bridge 请求能力。
4213
+ * @param options - 下载地址、受控写入目标、限制、取消信号与进度回调。
4214
+ * @returns 原子提交完成后的 File 代理。
4215
+ * @throws {@link HbMiniProgramSDKError} 参数、权限、目标、网络、取消或 Host 响应不符合公开合同时抛出。
4216
+ */
3655
4217
  async function download(requester, options) {
3656
4218
  if (options?.signal?.aborted) {
3657
4219
  throw createSDKError('DOWNLOAD_CANCELLED', '下载已取消');
@@ -3848,18 +4410,46 @@ function createViewportModule(requester) {
3848
4410
  /**
3849
4411
  * 获取当前访问小程序用户的公开基础资料。
3850
4412
  *
3851
- * @returns 当前用户的登录态与公开基础资料。
4413
+ * @param requester - SDK 内部的 bridge 请求器;业务代码应通过 `hbSDK.user.getInfo()` 调用。
4414
+ * @returns 以 `isHeyboxAppLoggedIn` 为判别字段的登录态、用户授权状态和已获准披露资料。
3852
4415
  *
3853
- * 未开通网络权限且当前黑盒 APP 用户已登录时,该能力会静默建立或读取按小程序隔离的
3854
- * `app_user_id`,并隐式授予 `identity` 与 `profile` 后返回昵称与头像,不展示授权 UI。未登录时返回
3855
- * `{ isHeyboxAppLoggedIn: false, authorization: null, userInfo: null }`。
4416
+ * @throws {@link HbMiniProgramSDKError} `userInfo` 未声明或不可用、握手失败、Host 不支持该能力、
4417
+ * 当前小程序身份缺失、账号/隔离身份读取失败、返回结构不合法、Runtime 终止,或请求期间
4418
+ * 账号与授权上下文变化时抛出。
3856
4419
  *
3857
- * @throws {@link HbMiniProgramSDKError} 当 SDK 调用失败时抛出。
4420
+ * @remarks
4421
+ * 当前账号未登录属于正常返回分支,不抛错。账号已登录时,该能力不展示授权 UI,也不要求
4422
+ * 可信用户手势;Runtime 会静默建立或读取当前小程序的隔离 `app_user_id`,并授予
4423
+ * `identity` 与 `profile`。它只要求 Manifest 中声明 `userInfo`,不要求公开 `network`
4424
+ * 权限,也不返回可供服务端换票的授权码。
4425
+ *
4426
+ * @example
4427
+ * ```ts
4428
+ * const result = await hbSDK.user.getInfo()
4429
+ * if (!result.isHeyboxAppLoggedIn) {
4430
+ * showLoginHint()
4431
+ * } else if (result.userInfo) {
4432
+ * renderUser(result.userInfo.app_user_id, result.userInfo.profile)
4433
+ * }
4434
+ * ```
4435
+ *
4436
+ * @see [auth.login](/reference/sdk/auth/login)
4437
+ * @see [user.revokeAuthorization](/reference/sdk/user/revokeAuthorization)
3858
4438
  */
3859
4439
  function getInfo(requester) {
3860
4440
  return requester.request(USER_GET_INFO_METHOD);
3861
4441
  }
3862
4442
 
4443
+ /**
4444
+ * 撤销当前用户授予本小程序的授权。
4445
+ *
4446
+ * @param requester - 底层 bridge 请求能力。
4447
+ * @returns 撤销完成后 resolve `undefined`。
4448
+ * @throws {@link HbMiniProgramSDKError} 缺少可信用户手势、当前用户未登录、Host 请求失败、
4449
+ * 账号上下文变化或 SDK / Runtime 已终止时抛出;具体稳定错误码见公开模块方法文档。
4450
+ * @remarks 该能力无需 Manifest 权限;撤销成功后由调用方清理自己的持久化数据和服务端会话。
4451
+ * @see [user.revokeAuthorization](/reference/sdk/user/revokeAuthorization)
4452
+ */
3863
4453
  function revokeAuthorization(requester) {
3864
4454
  return requester.request(USER_REVOKE_AUTHORIZATION_METHOD);
3865
4455
  }
@@ -3868,8 +4458,12 @@ function revokeAuthorization(requester) {
3868
4458
  * 获取当前用户 Steam 游戏库。
3869
4459
  *
3870
4460
  * @param requester - 底层 bridge 请求能力。
3871
- * @param options - 查询与分页参数。
3872
- * @returns 当前用户 Steam 游戏库;未登录或未绑定 Steam 时返回状态对象。
4461
+ * @param options - 查询与分页参数;省略时采用默认 Steam 账号、分页和排序。
4462
+ * @returns 登录态、Steam 绑定态以及绑定成功时的规范化分页数据。
4463
+ * @throws {@link HbMiniProgramSDKError} 参数、权限、Host 能力、服务端响应、账号上下文或
4464
+ * SDK 生命周期不满足要求时抛出;具体稳定错误码见公开模块方法文档。
4465
+ * @remarks 该能力要求 `steamLibrary`,但不要求公开 `network` 权限或可信用户手势。
4466
+ * @see [user.getSteamGameList](/reference/sdk/user/getSteamGameList)
3873
4467
  */
3874
4468
  function getSteamGameList(requester, options) {
3875
4469
  return requester.request(USER_GET_STEAM_GAME_LIST_METHOD, options);
@@ -3883,19 +4477,44 @@ function createUserModule(requester) {
3883
4477
  };
3884
4478
  }
3885
4479
 
3886
- /** 展示 toast。 */
4480
+ /**
4481
+ * 通过底层 bridge 展示 Toast。
4482
+ *
4483
+ * @param requester - 底层 bridge 请求能力。
4484
+ * @param options - Toast 文案与可选语义状态。
4485
+ * @returns Host 接受并应用展示请求后 resolve。
4486
+ * @throws {@link HbMiniProgramSDKError} 参数、bridge、Runtime 或 Host 调用失败时抛出。
4487
+ */
3887
4488
  function showToast(requester, options) {
3888
4489
  return requester.request(UI_SHOW_TOAST_METHOD, options);
3889
4490
  }
3890
- /** 展示全局 loading。 */
4491
+ /**
4492
+ * 通过底层 bridge 展示或更新全局 Loading。
4493
+ *
4494
+ * @param requester - 底层 bridge 请求能力。
4495
+ * @param options - 可选展示配置;省略时使用不可手动关闭的 Loading。
4496
+ * @returns Host 接受并应用展示请求后 resolve。
4497
+ * @throws {@link HbMiniProgramSDKError} 参数、bridge、Runtime 或 Host 调用失败时抛出。
4498
+ */
3891
4499
  function showLoading(requester, options) {
3892
4500
  return requester.request(UI_SHOW_LOADING_METHOD, options ?? {});
3893
4501
  }
3894
- /** 隐藏全局 loading。 */
4502
+ /**
4503
+ * 通过底层 bridge 请求隐藏全局 Loading。
4504
+ *
4505
+ * @param requester - 底层 bridge 请求能力。
4506
+ * @returns Host 接受隐藏请求后 resolve。
4507
+ * @throws {@link HbMiniProgramSDKError} bridge、Runtime 或 Host 调用失败时抛出。
4508
+ */
3895
4509
  function hideLoading(requester) {
3896
4510
  return requester.request(UI_HIDE_LOADING_METHOD);
3897
4511
  }
3898
- /** 创建 UI 模块。 */
4512
+ /**
4513
+ * 创建绑定到指定 bridge requester 的 UI 模块。
4514
+ *
4515
+ * @param requester - 底层 bridge 请求能力。
4516
+ * @returns 可供 Mini-program 调用的 UI 模块。
4517
+ */
3899
4518
  function createUiModule(requester) {
3900
4519
  return {
3901
4520
  showToast: (options) => showToast(requester, options),
@@ -4005,15 +4624,41 @@ function isRecord(value) {
4005
4624
  return typeof value === 'object' && value !== null && !Array.isArray(value);
4006
4625
  }
4007
4626
 
4008
- /** 请求宿主关闭当前小程序容器。 */
4627
+ /**
4628
+ * 请求宿主关闭当前小程序容器。
4629
+ *
4630
+ * @param requester - 底层 bridge 请求能力。
4631
+ * @returns Host 接受关闭请求后 resolve `undefined`;当前页面上下文随后可能立即终止。
4632
+ * @throws {@link HbMiniProgramSDKError} Host 能力缺失、关闭失败或 SDK / Runtime 已终止时抛出。
4633
+ * @remarks 必须完成的持久化工作应在调用前结束;该能力无需 Manifest 权限或可信用户手势。
4634
+ * @see [navigation.close](/reference/sdk/navigation/close)
4635
+ */
4009
4636
  function close(requester) {
4010
4637
  return requester.request(NAVIGATION_CLOSE_METHOD);
4011
4638
  }
4012
- /** 请求宿主重载当前小程序容器。 */
4639
+ /**
4640
+ * 请求宿主重载当前小程序容器。
4641
+ *
4642
+ * @param requester - 底层 bridge 请求能力。
4643
+ * @returns Host 接受 reload 请求后 resolve `undefined`;旧页面上下文随后会被替换。
4644
+ * @throws {@link HbMiniProgramSDKError} Host 能力缺失、reload 失败或 SDK / Runtime 已终止时抛出。
4645
+ * @remarks 跨页面状态应在调用前持久化;该能力无需 Manifest 权限或可信用户手势。
4646
+ * @see [navigation.reload](/reference/sdk/navigation/reload)
4647
+ */
4013
4648
  function reload(requester) {
4014
4649
  return requester.request(NAVIGATION_RELOAD_METHOD);
4015
4650
  }
4016
- /** 请求宿主打开受 SDK 白名单约束的黑盒 App 页面。 */
4651
+ /**
4652
+ * 请求宿主打开受 SDK 白名单约束的黑盒 App 页面。
4653
+ *
4654
+ * @param requester - 底层 bridge 请求能力。
4655
+ * @param options - 由 `target` 判别的目标页参数;发送前会校验并规范化。
4656
+ * @returns Host 发起受控页面路由后 resolve `undefined`。
4657
+ * @throws {@link HbMiniProgramSDKError} 参数非法、目标不受 Host 支持、路由失败或 SDK /
4658
+ * Runtime 已终止时抛出。
4659
+ * @remarks 该能力不接受任意 URL 或内部路由,也无需 Manifest 权限或可信用户手势。
4660
+ * @see [navigation.openAppPage](/reference/sdk/navigation/openAppPage)
4661
+ */
4017
4662
  function openAppPage(requester, options) {
4018
4663
  try {
4019
4664
  return requester.request(NAVIGATION_OPEN_APP_PAGE_METHOD, normalizeOpenAppPageOptions(options));
@@ -4245,6 +4890,66 @@ function getDefaultSDK() {
4245
4890
  /**
4246
4891
  * 获取默认 SDK 实例的当前握手状态。
4247
4892
  *
4893
+ * @returns 当前冻结的
4894
+ * [MiniProgramSDKHandshakeState](/reference/symbols/root/types/MiniProgramSDKHandshakeState):
4895
+ * `connecting` 表示初始握手尚未落定,`ready` 表示握手成功;`failed` 表示握手失败,并通过
4896
+ * `error` 保留原始
4897
+ * [HbMiniProgramSDKError](/reference/symbols/root/classes/HbMiniProgramSDKError)。状态不变期间重复调用
4898
+ * 返回同一个对象引用,落定时只会替换一次。
4899
+ *
4900
+ * @remarks
4901
+ * 该函数不接收参数并同步返回当前快照,不等待 Promise、不轮询、不发送 bridge 请求,也不会因为
4902
+ * 握手失败而抛出 `failed.error`。读取状态无需在 `package.json#heybox.permissions` 中声明权限,
4903
+ * 不要求可信用户手势。根包导入时已经自动启动握手;普通异步能力调用也会自行等待,不需要用本
4904
+ * API 手动实现等待器。
4905
+ *
4906
+ * 状态 wrapper 已浅冻结。状态机只允许 `connecting -> ready` 或 `connecting -> failed` 一次迁移,
4907
+ * 终态不会回退或互相转换;`failed.error` 是握手 Promise 使用的同一个原始错误实例,可根据稳定的
4908
+ * `code` 分支处理。常见初始失败包括 `NOT_IN_IFRAME`、`MISSING_NONCE`、`READY_TIMEOUT`、
4909
+ * `HANDSHAKE_FAILED`、`RUNTIME_UNAVAILABLE` 或握手完成前的 `SDK_DESTROYED`。
4910
+ *
4911
+ * 需要让界面跟随状态变化时,使用
4912
+ * [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange):它会在订阅期间同步回放
4913
+ * 当前值,再通知至多一次终态迁移。不要轮询本函数。对于必须保留原始可信用户手势的按钮,可用
4914
+ * 该持久状态提前控制 `disabled`,但不要在点击回调里等待握手。
4915
+ *
4916
+ * [on('ready')](/reference/sdk/lifecycle/on) 是握手成功瞬间的事件:不会向晚订阅者重放,Host 重复
4917
+ * 派发时也可能再次触发事件 handler;持久状态则只迁移一次并始终可查询。`ready` 只表示初始握手
4918
+ * 已成功,后续 `unload` 不会把状态改回 `failed`,因此不能把它当作 Runtime 持续存活检查。
4919
+ *
4920
+ * SDK 会在发布 `ready` 状态前缓存环境快照,所以 `status === 'ready'` 时可以立即调用
4921
+ * [environment.getInfoSync()](/reference/sdk/environment/getInfoSync)。`failed` 时该同步环境 API 会抛出
4922
+ * 同一个 `state.error`;不要求同步读取时,优先使用会自动等待的
4923
+ * [environment.getInfo()](/reference/sdk/environment/getInfo)。
4924
+ *
4925
+ * @example
4926
+ * ```ts
4927
+ * import hbSDK from '@heybox/hb-sdk'
4928
+ *
4929
+ * const state = hbSDK.getHandshakeState()
4930
+ *
4931
+ * switch (state.status) {
4932
+ * case 'connecting':
4933
+ * submitButton.disabled = true
4934
+ * break
4935
+ * case 'ready': {
4936
+ * submitButton.disabled = false
4937
+ * const environment = hbSDK.environment.getInfoSync()
4938
+ * console.log(environment.runtime.mode)
4939
+ * break
4940
+ * }
4941
+ * case 'failed':
4942
+ * submitButton.disabled = true
4943
+ * console.error('SDK 握手失败', state.error.code)
4944
+ * break
4945
+ * }
4946
+ * ```
4947
+ *
4948
+ * @see [MiniProgramSDKHandshakeState](/reference/symbols/root/types/MiniProgramSDKHandshakeState) 三种状态及冻结语义。
4949
+ * @see [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange) 同步回放当前状态并订阅终态迁移。
4950
+ * @see [on('ready')](/reference/sdk/lifecycle/on) 不可重放的生命周期边沿事件。
4951
+ * @see [environment.getInfoSync()](/reference/sdk/environment/getInfoSync) 在 `ready` 后同步读取环境快照。
4952
+ *
4248
4953
  * @since 0.7.0-alpha.9
4249
4954
  * @hbPlatform android
4250
4955
  * @hbPlatform ios
@@ -4263,6 +4968,83 @@ function getHandshakeState() {
4263
4968
  /**
4264
4969
  * 订阅默认 SDK 实例的握手状态,并立即接收当前状态。
4265
4970
  *
4971
+ * @param handler - 接收
4972
+ * [MiniProgramSDKHandshakeState](/reference/symbols/root/types/MiniProgramSDKHandshakeState) 的处理函数。
4973
+ * 注册期间会在本函数返回前同步调用一次:`connecting` 表示初始握手仍在进行,`ready` 表示成功,
4974
+ * `failed.error` 是原始
4975
+ * [HbMiniProgramSDKError](/reference/symbols/root/classes/HbMiniProgramSDKError)。
4976
+ * @returns 从默认 SDK 状态 store 移除当前 handler 的 unsubscribe。调用一次或多次都返回 `void` 且
4977
+ * 不会抛错;取消后不再接收未来迁移,但不会撤销已经同步回放的当前状态。
4978
+ *
4979
+ * @remarks
4980
+ * 订阅是纯本地同步操作,不发送 bridge 请求、不等待握手,也无需在
4981
+ * `package.json#heybox.permissions` 中声明权限或保留可信用户手势。根包导入时握手已经自动启动;
4982
+ * 本 API 用于观察状态,不用于主动发起或重试握手。
4983
+ *
4984
+ * handler 会在加入订阅集合后、unsubscribe 返回前立即同步收到当前冻结状态:
4985
+ *
4986
+ * - 当前为 `connecting`:先立即收到 `connecting`,随后至多再收到一次 `ready` 或 `failed`;
4987
+ * - 当前已是 `ready` 或 `failed`:立即收到该终态,之后不会再迁移;
4988
+ * - 在终态通知过程中新增订阅:通过即时回放收到一次终态,不会因同一迁移重复调用。
4989
+ *
4990
+ * 状态只允许 `connecting -> ready` 或 `connecting -> failed`,终态不回退。`failed.error` 是握手失败
4991
+ * 和同步环境读取使用的同一个原始错误实例,可按稳定的 `code` 分支处理。`ready` 只表示初始握手
4992
+ * 已成功;后续 `unload` 不会把状态改回 `failed`,因此它不是 Runtime 持续存活探针。
4993
+ *
4994
+ * SDK 会逐个捕获 handler 的同步异常:初次即时回放或终态通知中抛错,都不会从本函数传播、改变
4995
+ * 状态、阻断握手 Promise 或阻止其他订阅者收到通知。handler 返回值会被忽略,Promise 也不会被
4996
+ * 等待;异步 handler 应在自身内部捕获 rejected Promise,避免未处理拒绝。
4997
+ *
4998
+ * 每个 handler 以 Set 语义保存;同一函数引用重复订阅只有一个未来通知注册,但每次调用本函数仍会
4999
+ * 同步回放当前状态,任一 unsubscribe 都会移除该注册。应在页面、组件或业务模块销毁时调用
5000
+ * unsubscribe。SDK 内部销毁会清空全部状态订阅;若销毁发生在握手落定前,会先发布携带
5001
+ * `SDK_DESTROYED` 的 `failed`,再清空订阅。此后重复调用已经返回的 unsubscribe 仍是安全空操作。
5002
+ * `unload` 发生在握手前时则以 `RUNTIME_UNAVAILABLE` 落为 `failed`;发生在 `ready` 后不会产生
5003
+ * 第二次状态通知。
5004
+ *
5005
+ * 与 [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 相比,本 API 适合让 UI 自动跟随
5006
+ * 唯一一次迁移,且即时回放意味着通常不需要先额外读取一次状态。
5007
+ * [on('ready')](/reference/sdk/lifecycle/on) 则是不可重放、可能因 Host 重复事件再次触发的边沿通知,
5008
+ * 不应用于驱动晚挂载按钮的可用状态。
5009
+ *
5010
+ * SDK 会在发布 `ready` 状态前缓存环境快照,因此可以在 `ready` handler 中立即调用
5011
+ * [environment.getInfoSync()](/reference/sdk/environment/getInfoSync)。在 `failed` handler 中调用该
5012
+ * API 会抛出同一个 `state.error`;一般异步读取可使用
5013
+ * [environment.getInfo()](/reference/sdk/environment/getInfo) 自动等待。
5014
+ *
5015
+ * @example
5016
+ * ```ts
5017
+ * import hbSDK from '@heybox/hb-sdk'
5018
+ *
5019
+ * const stop = hbSDK.onHandshakeStateChange(state => {
5020
+ * switch (state.status) {
5021
+ * case 'connecting':
5022
+ * submitButton.disabled = true
5023
+ * statusText.textContent = '正在连接'
5024
+ * break
5025
+ * case 'ready':
5026
+ * submitButton.disabled = false
5027
+ * statusText.textContent = hbSDK.environment.getInfoSync().runtime.mode
5028
+ * break
5029
+ * case 'failed':
5030
+ * submitButton.disabled = true
5031
+ * statusText.textContent = `连接失败:${state.error.code}`
5032
+ * break
5033
+ * }
5034
+ * })
5035
+ *
5036
+ * // 页面或组件真正销毁时执行;重复取消也安全。
5037
+ * window.addEventListener('unload', () => {
5038
+ * stop()
5039
+ * stop()
5040
+ * }, { once: true })
5041
+ * ```
5042
+ *
5043
+ * @see [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 一次性同步读取当前持久状态。
5044
+ * @see [on('ready')](/reference/sdk/lifecycle/on) 不可重放的握手成功边沿事件。
5045
+ * @see [environment.getInfoSync()](/reference/sdk/environment/getInfoSync) 在 `ready` handler 中同步读取环境。
5046
+ * @see [事件与生命周期](/guide/lifecycle) 握手与普通生命周期事件的使用建议。
5047
+ *
4266
5048
  * @since 0.7.0-alpha.9
4267
5049
  * @hbPlatform android
4268
5050
  * @hbPlatform ios
@@ -4281,9 +5063,83 @@ function onHandshakeStateChange(handler) {
4281
5063
  /**
4282
5064
  * 注册默认 SDK 实例的事件监听。
4283
5065
  *
4284
- * @param eventName - 要监听的事件名。
4285
- * @param handler - 事件处理函数。
4286
- * @returns 事件解绑函数。
5066
+ * @param eventName - 要监听的
5067
+ * [MiniProgramEventName](/reference/symbols/root/types/MiniProgramEventName)。泛型 `T` 通常由该字符串
5068
+ * 字面量推断,并决定 handler 的 payload 类型。
5069
+ * @param handler - 与 `eventName` 对应的
5070
+ * [MiniProgramEventHandler](/reference/symbols/root/types/MiniProgramEventHandler)。payload 由
5071
+ * [MiniProgramEventPayloadMap](/reference/symbols/root/interfaces/MiniProgramEventPayloadMap) 精确映射。
5072
+ * @returns 只解绑当前 `eventName` / handler 组合的函数。调用一次或多次都返回 `void` 且不会抛错,
5073
+ * 不影响同一事件上的其他 handler。
5074
+ *
5075
+ * @remarks
5076
+ * 事件名决定 payload 字段:
5077
+ *
5078
+ * - `launch`:`{ timestamp, url? }`;`ready`:`{ timestamp }`;
5079
+ * - `show` / `hide`:`{ timestamp, source? }`;`unload`:`{ timestamp }`;
5080
+ * - `error`:
5081
+ * [MiniProgramBridgeError](/reference/symbols/protocol/interfaces/MiniProgramBridgeError),包含 `code`、
5082
+ * `message` 与可选 `data`,不是 JavaScript `Error` 实例;
5083
+ * - `heybox_app_login_change`:`{ isHeyboxAppLoggedIn }`;
5084
+ * - `user_info_authorization_change`:
5085
+ * [UserInfoAuthorization](/reference/symbols/root/interfaces/UserInfoAuthorization),包含 `identity` 与
5086
+ * `profile` 两项授权状态;
5087
+ * - `companion.session.output`:`{ sessionId, controllerGeneration, stream, sequence, data }`;
5088
+ * - `companion.session.exit`:`{ sessionId, exit }`;
5089
+ * - `companion.session.ownershipLost`:`{ sessionId, controllerGeneration }`。
5090
+ *
5091
+ * `on()` 同步把 handler 加入默认 SDK 实例的本地 event bus,不等待握手、不发送 bridge 请求。
5092
+ * 注册本身无需在 `package.json#heybox.permissions` 中声明权限,不要求可信用户手势,也不会因当前
5093
+ * 握手处于 `connecting`、`ready` 或 `failed` 而抛出 SDK 错误。具体事件是否会产生,仍取决于 Host、
5094
+ * Runtime 生命周期和相关业务能力。
5095
+ *
5096
+ * event bus 使用 Set 保存每个事件的 handler。同一事件与同一函数引用重复注册只有一个有效监听;
5097
+ * 任一返回的 unsubscribe 或 [off()](/reference/sdk/lifecycle/off) 都会移除该唯一注册。不同函数引用
5098
+ * 不会去重,同一函数注册到不同事件也彼此独立。应保存 unsubscribe,并在页面、组件或业务模块销毁
5099
+ * 时调用;unsubscribe 可安全重复调用。
5100
+ *
5101
+ * handler 在事件派发时同步执行。SDK 不捕获普通事件 handler 的同步异常,也不等待其 Promise;某个
5102
+ * handler 抛错可能阻断同次派发中的后续 handler,异步拒绝也可能成为未处理 Promise。需要隔离时在
5103
+ * handler 内自行 `try/catch`,并显式处理异步任务的 rejected Promise。
5104
+ *
5105
+ * 所有生命周期与业务事件都不会重放:只派发给事件到达时已经注册的 handler,晚注册无法取回
5106
+ * `launch`、`ready` 或其他历史事件。`ready` 只是握手成功瞬间的边沿通知,Host 重复派发时 handler
5107
+ * 也可能再次执行;需要可查询、会向订阅者立即回放且只迁移一次的握手状态时,使用
5108
+ * [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 和
5109
+ * [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange)。
5110
+ *
5111
+ * 收到 `unload` 后当前 Runtime 上下文不可恢复,在途请求会失败,也不应再依赖后续 bridge 事件;
5112
+ * SDK 内部销毁会移除底层 message listener。调用 unsubscribe 只清理该本地事件 handler,不取消
5113
+ * API 请求、业务任务、Companion 进程或握手状态订阅。
5114
+ *
5115
+ * @example
5116
+ * ```ts
5117
+ * import hbSDK from '@heybox/hb-sdk'
5118
+ *
5119
+ * const stopShow = hbSDK.on('show', ({ timestamp, source }) => {
5120
+ * try {
5121
+ * refreshVisibleData({ timestamp, source })
5122
+ * } catch (error) {
5123
+ * reportHandlerError(error)
5124
+ * }
5125
+ * })
5126
+ *
5127
+ * const stopError = hbSDK.on('error', ({ code, message }) => {
5128
+ * console.error(code, message)
5129
+ * })
5130
+ *
5131
+ * // 页面或组件销毁时;重复调用也安全。
5132
+ * stopShow()
5133
+ * stopShow()
5134
+ * stopError()
5135
+ * ```
5136
+ *
5137
+ * @see [MiniProgramEventPayloadMap](/reference/symbols/root/interfaces/MiniProgramEventPayloadMap) 所有事件与 payload 字段。
5138
+ * @see [off()](/reference/sdk/lifecycle/off) 使用事件名与 handler 引用精确移除监听。
5139
+ * @see [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 同步读取持久握手状态。
5140
+ * @see [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange) 订阅会立即回放的握手状态。
5141
+ * @see [事件与生命周期](/guide/lifecycle) 生命周期时机与清理建议。
5142
+ *
4287
5143
  * @since 0.2.0-alpha.0
4288
5144
  * @hbPlatform android
4289
5145
  * @hbPlatform ios
@@ -4302,9 +5158,57 @@ function on(eventName, handler) {
4302
5158
  /**
4303
5159
  * 移除默认 SDK 实例的事件监听。
4304
5160
  *
4305
- * @param eventName - 要移除的事件名。
4306
- * @param handler - 对应的事件处理函数。
4307
- * @returns 无返回值。
5161
+ * @param eventName - 注册 handler 时使用的同一个事件名。只检查该事件自己的监听集合,不影响
5162
+ * 其他事件上的注册。
5163
+ * @param handler - 传给 `on(eventName, handler)` 的同一个函数对象。签名或函数体相同的新函数不是
5164
+ * 同一引用,不能移除原监听。
5165
+ * @returns `void`。移除成功、目标从未注册或此前已经移除时都不返回状态。
5166
+ *
5167
+ * @remarks
5168
+ * 该函数同步修改默认 SDK 实例的本地 event bus,不等待握手、不发送 bridge 请求,也不会调用
5169
+ * handler。它无需在 `package.json#heybox.permissions` 中声明权限,不要求可信用户手势;握手处于
5170
+ * `connecting`、`ready` 或 `failed`,以及已经收到 `unload` 时,取消操作本身都不会产生 SDK 错误。
5171
+ *
5172
+ * 匹配规则是 `eventName` 与 handler 函数引用同时相等。匹配后只移除这一项,同一事件上的其他
5173
+ * handler、同一 handler 在其他事件上的注册均保留。event bus 对同一事件与同一函数引用使用集合
5174
+ * 语义,重复 `on()` 只有一个有效注册,一次 `off()` 即会移除;重复调用 `off()` 是幂等的,未知事件
5175
+ * 或未注册 handler 会被静默忽略。
5176
+ *
5177
+ * 大多数场景优先保存并调用 [on()](/reference/sdk/lifecycle/on) 返回的 unsubscribe:它已经闭包绑定
5178
+ * 正确的事件名和 handler,同样可以重复调用。只有调用方需要在另一处按具名 handler 精确移除时,
5179
+ * 才直接使用 `off()`。匿名函数必须先保存引用;重新创建一个内容相同的箭头函数无法取消旧监听。
5180
+ *
5181
+ * 生命周期与业务事件不会重放,只派发给事件到达时仍处于注册状态的 handler。`off()` 只阻止后续
5182
+ * 事件,不能撤销已经执行的 handler,也不能取回注册前错过的 `launch`、`ready`、`show`、`hide`、
5183
+ * `unload` 等事件。当前握手状态应通过
5184
+ * [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 或
5185
+ * [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange) 获取,不要通过重新注册
5186
+ * `ready` 事件补状态。
5187
+ *
5188
+ * Runtime `unload` 或 SDK 内部销毁后不会再有可依赖的未来 bridge 生命周期事件,但调用 unsubscribe
5189
+ * 或 `off()` 做本地清理仍可安全重复执行。取消监听不会取消已经开始的 API 请求、业务任务或
5190
+ * `onHandshakeStateChange()` 订阅;后者必须调用其自己返回的取消函数。
5191
+ *
5192
+ * @example
5193
+ * ```ts
5194
+ * import hbSDK from '@heybox/hb-sdk'
5195
+ *
5196
+ * const pauseOnHide = () => pausePolling()
5197
+ * const reportHide = () => reportVisibility('hidden')
5198
+ *
5199
+ * hbSDK.on('hide', pauseOnHide)
5200
+ * const stopReporting = hbSDK.on('hide', reportHide)
5201
+ *
5202
+ * hbSDK.off('hide', pauseOnHide) // 只移除 pauseOnHide
5203
+ * hbSDK.off('hide', pauseOnHide) // 已移除,仍然安全
5204
+ * stopReporting() // 推荐:使用 on() 返回的取消函数
5205
+ * ```
5206
+ *
5207
+ * @see [on()](/reference/sdk/lifecycle/on) 注册事件并取得绑定好的取消函数。
5208
+ * @see [getHandshakeState()](/reference/sdk/lifecycle/getHandshakeState) 同步读取持久握手状态。
5209
+ * @see [onHandshakeStateChange()](/reference/sdk/lifecycle/onHandshakeStateChange) 订阅会立即回放的握手状态。
5210
+ * @see [事件与生命周期](/guide/lifecycle) 生命周期事件列表与清理建议。
5211
+ *
4308
5212
  * @since 0.2.0-alpha.0
4309
5213
  * @hbPlatform android
4310
5214
  * @hbPlatform ios