@heybox/hb-sdk 0.9.1-alpha.9 → 0.9.1

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 (40) hide show
  1. package/CHANGELOG.md +104 -19
  2. package/README.md +17 -16
  3. package/dist/cli-chunks/{build-mIRvG3a8.cjs → build-DCp9C9V4.cjs} +5 -5
  4. package/dist/cli-chunks/{context-0uq4_H2M.cjs → context-Bg6C5ow7.cjs} +10 -5
  5. package/dist/cli-chunks/{create-DDPUUzi1.cjs → create-D5bX2Xvw.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-BOrmDVzH.cjs → dev-CFjwhG3q.cjs} +194 -81
  7. package/dist/cli-chunks/{doctor-BtOKr1SN.cjs → doctor-CMz_Kf7-.cjs} +1 -1
  8. package/dist/cli-chunks/{index-MMLoNdeZ.cjs → index-B_KKGIBN.cjs} +16 -16
  9. package/dist/cli-chunks/{index-DYqbUZfk.cjs → index-YnVa6S_p.cjs} +1 -1
  10. package/dist/cli-chunks/{index.esm-DYKzLyvN.cjs → index.esm-CgZPnqEA.cjs} +6 -6
  11. package/dist/cli-chunks/{login-Be95cDi7.cjs → login-Df_v6jNs.cjs} +1 -1
  12. package/dist/cli-chunks/{project-vite-Si5Tyi7Q.cjs → project-vite-By8cnIwP.cjs} +1 -1
  13. package/dist/cli-chunks/{remote-D2XvKzs6.cjs → remote-ClIJz-e2.cjs} +28 -16
  14. package/dist/cli-chunks/{runtime-gate-B0YPKxEd.cjs → runtime-gate-DKiyNwX2.cjs} +2 -2
  15. package/dist/cli-chunks/{runtime-permission-env-CzhGcDRj.cjs → runtime-permission-env-BNQ2fx4w.cjs} +77 -4
  16. package/dist/cli-chunks/{skill-7n-Yn9ny.cjs → skill-Bk-EBSbJ.cjs} +2 -2
  17. package/dist/cli-chunks/{version-B1aYSptt.cjs → version-CG_VNZGM.cjs} +1 -1
  18. package/dist/cli.cjs +1 -1
  19. package/dist/devtools/browser-dev-host/assets/browser-dev-host-C1g2tadT.js +102 -0
  20. package/dist/devtools/browser-dev-host/assets/{desktop-app-launch-DzaVQPma.js → desktop-app-launch-sH2a_jbj.js} +1 -1
  21. package/dist/devtools/browser-dev-host/assets/{index-BRxbUJVN.css → index-7Cq8iNcD.css} +1 -1
  22. package/dist/devtools/browser-dev-host/assets/{index-hh0NzK3n.js → index-Bpxbe1lP.js} +4 -4
  23. package/dist/devtools/browser-dev-host/index.html +3 -3
  24. package/dist/index.cjs.js +16 -8
  25. package/dist/index.esm.js +16 -8
  26. package/dist/miniapp-publish.cjs.js +27 -0
  27. package/dist/miniapp-publish.esm.js +27 -0
  28. package/dist/protocol.cjs.js +1 -1
  29. package/dist/protocol.esm.js +1 -1
  30. package/dist/vite.cjs.js +36 -1
  31. package/dist/vite.esm.js +36 -1
  32. package/docs/runtime-host-migration.md +4 -2
  33. package/package.json +4 -4
  34. package/skill/SKILL.md +10 -0
  35. package/skill/skill.json +5 -5
  36. package/types/index.d.ts +124 -94
  37. package/types/miniapp-publish/index.d.ts +3 -0
  38. package/types/protocol.d.ts +47 -39
  39. package/types/vite/index.d.ts +1 -0
  40. package/dist/devtools/browser-dev-host/assets/browser-dev-host-Iyo4aIMO.js +0 -102
@@ -5,9 +5,9 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#f4f5f7" />
7
7
  <title>小程序工坊调试台</title>
8
- <script type="module" crossorigin src="/assets/index-hh0NzK3n.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/desktop-app-launch-DzaVQPma.js">
10
- <link rel="stylesheet" crossorigin href="/assets/index-BRxbUJVN.css">
8
+ <script type="module" crossorigin src="/assets/index-Bpxbe1lP.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/desktop-app-launch-sH2a_jbj.js">
10
+ <link rel="stylesheet" crossorigin href="/assets/index-7Cq8iNcD.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="app"></div>
package/dist/index.cjs.js CHANGED
@@ -282,10 +282,12 @@ function isPlainObject$2(value) {
282
282
  * `data` 仅作为可选调试信息,不保证结构稳定。错误码是跨 Host 的分支契约;
283
283
  * `message` 只用于日志和开发者提示,不应作为机器判断条件。
284
284
  *
285
- * 常见处理类别包括:`INVALID_PARAMS`(修正调用参数)、`PERMISSION_NOT_DECLARED`
286
- * 或 `PERMISSION_DENIED`(检查 Manifest/平台批准)、`USER_GESTURE_REQUIRED`
285
+ * 常见处理类别包括:`INVALID_PARAMS`(修正调用参数)、`PERMISSION_NOT_IN_SNAPSHOT`
286
+ *(当前运行快照缺少权限,需发布含声明的新版本或重新打开调试)、
287
+ * `PERMISSION_DENIED`(检查权限启用状态与平台批准)、`USER_GESTURE_REQUIRED`
287
288
  *(改为用户点击后重试)、`AUTHORIZATION_CANCELLED`(结束当前流程),以及
288
289
  * `METHOD_FORBIDDEN`(当前 Host 不支持该能力)。具体能力还可能返回模块专属错误码。
290
+ * 旧 Runtime 仍可能返回 `PERMISSION_NOT_DECLARED`;SDK 会保留 Host 返回的错误码。
289
291
  * 不要把所有错误都当作可重试错误,也不要把 `data` 当成稳定的序列化协议。
290
292
  *
291
293
  * @example
@@ -7278,7 +7280,7 @@ function createMessageId() {
7278
7280
  /** 构建时替换为当前发布包的实际版本。 */
7279
7281
  const HB_SDK_VERSION = typeof undefined === 'string'
7280
7282
  ? undefined
7281
- : '0.9.1-alpha.9';
7283
+ : '0.9.1';
7282
7284
 
7283
7285
  const RUNTIME_MODES = new Set(['production', 'preview', 'development', 'unknown']);
7284
7286
  const OPERATING_SYSTEM_NAMES = new Set(['android', 'ios', 'ohos', 'windows', 'macos', 'linux', 'unknown']);
@@ -7324,8 +7326,8 @@ function readRecord$1(value) {
7324
7326
  }
7325
7327
 
7326
7328
  const DEFAULT_TIMEOUT = 10000;
7327
- // 选择器等待由用户决定,使用长操作的生命周期清理,不设固定总时长。
7328
- const FILE_PICKER_METHODS = new Set([FILES_PICK_FILES_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_SAVE_FILE_METHOD]);
7329
+ // 选择器等待、截图延迟与排队由 Host 管理,使用长操作生命周期,不设固定总时长。
7330
+ const HOST_MANAGED_TIMEOUT_METHODS = new Set([FILES_PICK_FILES_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_SAVE_FILE_METHOD, SHARE_SCREENSHOT_METHOD]);
7329
7331
  const HANDSHAKE_RETRY_INTERVAL = 250;
7330
7332
  /** 底层 bridge client,负责握手、请求响应、事件分发与超时清理。 */
7331
7333
  class MiniProgramBridgeClient {
@@ -7407,7 +7409,7 @@ class MiniProgramBridgeClient {
7407
7409
  }
7408
7410
  /** 调用父容器开放能力。 */
7409
7411
  async request(method, ...args) {
7410
- return this.performRequest(method, args[0], !FILE_PICKER_METHODS.has(method));
7412
+ return this.performRequest(method, args[0], !HOST_MANAGED_TIMEOUT_METHODS.has(method));
7411
7413
  }
7412
7414
  /** 发起不使用固定总时长 timer 的长操作。 */
7413
7415
  async requestOperation(method, payload, options = {}) {
@@ -8509,8 +8511,8 @@ function createCompanionModule(requester) {
8509
8511
  * `options.extra` 时生成不带扩展数据的链接。
8510
8512
  * @returns Host 完成剪贴板写入后 resolve 的完整分享链接;返回字符串与剪贴板内容一致。
8511
8513
  * @throws {@link HbMiniProgramSDKError} 参数、`extra` 编码或小程序身份不合法时返回
8512
- * `INVALID_PARAMS`;未声明或未启用 `share` 权限时分别返回
8513
- * `PERMISSION_NOT_DECLARED` 或 `PERMISSION_DENIED`;当前 Host 未开放剪贴板能力时可返回
8514
+ * `INVALID_PARAMS`;当前运行快照缺少或未启用 `share` 权限时分别返回
8515
+ * `PERMISSION_NOT_IN_SNAPSHOT` 或 `PERMISSION_DENIED`;当前 Host 未开放剪贴板能力时可返回
8514
8516
  * `METHOD_FORBIDDEN` 或 `REQUEST_UNSUPPORTED`。握手、bridge 超时和其他 Host 写入失败会保留
8515
8517
  * 对应错误码。
8516
8518
  *
@@ -10270,6 +10272,12 @@ function decodeBase64Url(value) {
10270
10272
  * @see {@link MiniProgramScreenshotOptions}
10271
10273
  */
10272
10274
  function screenshot(requester, options) {
10275
+ try {
10276
+ console.warn('[hb-sdk] share.screenshot 行为变更提醒:正式版 SDK 0.9.1 及以上默认添加小程序品牌水印;低于 0.9.1(含预发布版本)的 SDK 保持无水印截图。升级前请在目标截图区域底部预留至少 57 个逻辑像素,避免遮挡重要内容;watermarkTheme 的 light 为黑色水印,dark 为白色水印且是默认值,不自动跟随系统主题。系统按键截图不在此能力范围内。');
10277
+ }
10278
+ catch {
10279
+ // 日志输出失败不能阻断截图调用。
10280
+ }
10273
10281
  return requester.request(SHARE_SCREENSHOT_METHOD, options);
10274
10282
  }
10275
10283
 
package/dist/index.esm.js CHANGED
@@ -278,10 +278,12 @@ function isPlainObject$2(value) {
278
278
  * `data` 仅作为可选调试信息,不保证结构稳定。错误码是跨 Host 的分支契约;
279
279
  * `message` 只用于日志和开发者提示,不应作为机器判断条件。
280
280
  *
281
- * 常见处理类别包括:`INVALID_PARAMS`(修正调用参数)、`PERMISSION_NOT_DECLARED`
282
- * 或 `PERMISSION_DENIED`(检查 Manifest/平台批准)、`USER_GESTURE_REQUIRED`
281
+ * 常见处理类别包括:`INVALID_PARAMS`(修正调用参数)、`PERMISSION_NOT_IN_SNAPSHOT`
282
+ *(当前运行快照缺少权限,需发布含声明的新版本或重新打开调试)、
283
+ * `PERMISSION_DENIED`(检查权限启用状态与平台批准)、`USER_GESTURE_REQUIRED`
283
284
  *(改为用户点击后重试)、`AUTHORIZATION_CANCELLED`(结束当前流程),以及
284
285
  * `METHOD_FORBIDDEN`(当前 Host 不支持该能力)。具体能力还可能返回模块专属错误码。
286
+ * 旧 Runtime 仍可能返回 `PERMISSION_NOT_DECLARED`;SDK 会保留 Host 返回的错误码。
285
287
  * 不要把所有错误都当作可重试错误,也不要把 `data` 当成稳定的序列化协议。
286
288
  *
287
289
  * @example
@@ -7274,7 +7276,7 @@ function createMessageId() {
7274
7276
  /** 构建时替换为当前发布包的实际版本。 */
7275
7277
  const HB_SDK_VERSION = typeof undefined === 'string'
7276
7278
  ? undefined
7277
- : '0.9.1-alpha.9';
7279
+ : '0.9.1';
7278
7280
 
7279
7281
  const RUNTIME_MODES = new Set(['production', 'preview', 'development', 'unknown']);
7280
7282
  const OPERATING_SYSTEM_NAMES = new Set(['android', 'ios', 'ohos', 'windows', 'macos', 'linux', 'unknown']);
@@ -7320,8 +7322,8 @@ function readRecord$1(value) {
7320
7322
  }
7321
7323
 
7322
7324
  const DEFAULT_TIMEOUT = 10000;
7323
- // 选择器等待由用户决定,使用长操作的生命周期清理,不设固定总时长。
7324
- const FILE_PICKER_METHODS = new Set([FILES_PICK_FILES_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_SAVE_FILE_METHOD]);
7325
+ // 选择器等待、截图延迟与排队由 Host 管理,使用长操作生命周期,不设固定总时长。
7326
+ const HOST_MANAGED_TIMEOUT_METHODS = new Set([FILES_PICK_FILES_METHOD, FILES_PICK_DIRECTORY_METHOD, FILES_SAVE_FILE_METHOD, SHARE_SCREENSHOT_METHOD]);
7325
7327
  const HANDSHAKE_RETRY_INTERVAL = 250;
7326
7328
  /** 底层 bridge client,负责握手、请求响应、事件分发与超时清理。 */
7327
7329
  class MiniProgramBridgeClient {
@@ -7403,7 +7405,7 @@ class MiniProgramBridgeClient {
7403
7405
  }
7404
7406
  /** 调用父容器开放能力。 */
7405
7407
  async request(method, ...args) {
7406
- return this.performRequest(method, args[0], !FILE_PICKER_METHODS.has(method));
7408
+ return this.performRequest(method, args[0], !HOST_MANAGED_TIMEOUT_METHODS.has(method));
7407
7409
  }
7408
7410
  /** 发起不使用固定总时长 timer 的长操作。 */
7409
7411
  async requestOperation(method, payload, options = {}) {
@@ -8505,8 +8507,8 @@ function createCompanionModule(requester) {
8505
8507
  * `options.extra` 时生成不带扩展数据的链接。
8506
8508
  * @returns Host 完成剪贴板写入后 resolve 的完整分享链接;返回字符串与剪贴板内容一致。
8507
8509
  * @throws {@link HbMiniProgramSDKError} 参数、`extra` 编码或小程序身份不合法时返回
8508
- * `INVALID_PARAMS`;未声明或未启用 `share` 权限时分别返回
8509
- * `PERMISSION_NOT_DECLARED` 或 `PERMISSION_DENIED`;当前 Host 未开放剪贴板能力时可返回
8510
+ * `INVALID_PARAMS`;当前运行快照缺少或未启用 `share` 权限时分别返回
8511
+ * `PERMISSION_NOT_IN_SNAPSHOT` 或 `PERMISSION_DENIED`;当前 Host 未开放剪贴板能力时可返回
8510
8512
  * `METHOD_FORBIDDEN` 或 `REQUEST_UNSUPPORTED`。握手、bridge 超时和其他 Host 写入失败会保留
8511
8513
  * 对应错误码。
8512
8514
  *
@@ -10266,6 +10268,12 @@ function decodeBase64Url(value) {
10266
10268
  * @see {@link MiniProgramScreenshotOptions}
10267
10269
  */
10268
10270
  function screenshot(requester, options) {
10271
+ try {
10272
+ console.warn('[hb-sdk] share.screenshot 行为变更提醒:正式版 SDK 0.9.1 及以上默认添加小程序品牌水印;低于 0.9.1(含预发布版本)的 SDK 保持无水印截图。升级前请在目标截图区域底部预留至少 57 个逻辑像素,避免遮挡重要内容;watermarkTheme 的 light 为黑色水印,dark 为白色水印且是默认值,不自动跟随系统主题。系统按键截图不在此能力范围内。');
10273
+ }
10274
+ catch {
10275
+ // 日志输出失败不能阻断截图调用。
10276
+ }
10269
10277
  return requester.request(SHARE_SCREENSHOT_METHOD, options);
10270
10278
  }
10271
10279
 
@@ -9531,6 +9531,31 @@ function parseMiniappBindAppIds(value, options = {}) {
9531
9531
  return Object.freeze(appIds);
9532
9532
  }
9533
9533
 
9534
+ /** 小程序简介最大长度(Unicode code point),与服务端截断口径一致。 */
9535
+ const MINIAPP_DESC_MAX_LENGTH = 200;
9536
+ /**
9537
+ * 校验并规范化 `package.json#heybox.desc` / `manifest.desc`。
9538
+ *
9539
+ * @param value - 原始声明;未声明时为 `undefined`。
9540
+ * @param sourceLabel - 错误消息中的字段来源,默认 `package.json#heybox.desc`。
9541
+ * @returns 去除首尾空白后的简介;未声明或为空串时返回 `undefined`。
9542
+ * @throws `Error` 非字符串、超过 200 个字符,或包含除换行外的控制字符时抛出。
9543
+ */
9544
+ function parseMiniappDesc(value, sourceLabel = 'package.json#heybox.desc') {
9545
+ if (value === undefined)
9546
+ return undefined;
9547
+ if (typeof value !== 'string')
9548
+ throw new Error(`${sourceLabel} 必须是字符串`);
9549
+ const desc = value.replace(/^\p{White_Space}+|\p{White_Space}+$/gu, '');
9550
+ if (!desc)
9551
+ return undefined;
9552
+ if (Array.from(desc).length > MINIAPP_DESC_MAX_LENGTH)
9553
+ throw new Error(`${sourceLabel} 不能超过 ${MINIAPP_DESC_MAX_LENGTH} 个字符`);
9554
+ if (/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(desc.replace(/\n/g, '')))
9555
+ throw new Error(`${sourceLabel} 不能包含控制字符`);
9556
+ return desc;
9557
+ }
9558
+
9534
9559
  const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
9535
9560
  function parseMiniappPermissions(value, options) {
9536
9561
  const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
@@ -9703,6 +9728,7 @@ function validateMiniappManifestForDeploy(manifest) {
9703
9728
  throw new Error('manifest.category 缺失,请在 package.json#heybox.category 声明 tool、game 或 other 后重新构建');
9704
9729
  }
9705
9730
  const bindAppIds = parseMiniappBindAppIds(manifest.bindAppIds, { sourceLabel: 'manifest.bindAppIds' });
9731
+ const desc = parseMiniappDesc(manifest.desc, 'manifest.desc');
9706
9732
  return {
9707
9733
  version,
9708
9734
  sdkVersion,
@@ -9714,6 +9740,7 @@ function validateMiniappManifestForDeploy(manifest) {
9714
9740
  ...(window === undefined ? {} : { window }),
9715
9741
  ...(bindAppIds.length === 0 ? {} : { bindAppIds }),
9716
9742
  ...(category === undefined ? {} : { category }),
9743
+ ...(desc === undefined ? {} : { desc }),
9717
9744
  };
9718
9745
  }
9719
9746
  function validateGeneratedCompanions(value) {
@@ -9529,6 +9529,31 @@ function parseMiniappBindAppIds(value, options = {}) {
9529
9529
  return Object.freeze(appIds);
9530
9530
  }
9531
9531
 
9532
+ /** 小程序简介最大长度(Unicode code point),与服务端截断口径一致。 */
9533
+ const MINIAPP_DESC_MAX_LENGTH = 200;
9534
+ /**
9535
+ * 校验并规范化 `package.json#heybox.desc` / `manifest.desc`。
9536
+ *
9537
+ * @param value - 原始声明;未声明时为 `undefined`。
9538
+ * @param sourceLabel - 错误消息中的字段来源,默认 `package.json#heybox.desc`。
9539
+ * @returns 去除首尾空白后的简介;未声明或为空串时返回 `undefined`。
9540
+ * @throws `Error` 非字符串、超过 200 个字符,或包含除换行外的控制字符时抛出。
9541
+ */
9542
+ function parseMiniappDesc(value, sourceLabel = 'package.json#heybox.desc') {
9543
+ if (value === undefined)
9544
+ return undefined;
9545
+ if (typeof value !== 'string')
9546
+ throw new Error(`${sourceLabel} 必须是字符串`);
9547
+ const desc = value.replace(/^\p{White_Space}+|\p{White_Space}+$/gu, '');
9548
+ if (!desc)
9549
+ return undefined;
9550
+ if (Array.from(desc).length > MINIAPP_DESC_MAX_LENGTH)
9551
+ throw new Error(`${sourceLabel} 不能超过 ${MINIAPP_DESC_MAX_LENGTH} 个字符`);
9552
+ if (/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(desc.replace(/\n/g, '')))
9553
+ throw new Error(`${sourceLabel} 不能包含控制字符`);
9554
+ return desc;
9555
+ }
9556
+
9532
9557
  const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
9533
9558
  function parseMiniappPermissions(value, options) {
9534
9559
  const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
@@ -9701,6 +9726,7 @@ function validateMiniappManifestForDeploy(manifest) {
9701
9726
  throw new Error('manifest.category 缺失,请在 package.json#heybox.category 声明 tool、game 或 other 后重新构建');
9702
9727
  }
9703
9728
  const bindAppIds = parseMiniappBindAppIds(manifest.bindAppIds, { sourceLabel: 'manifest.bindAppIds' });
9729
+ const desc = parseMiniappDesc(manifest.desc, 'manifest.desc');
9704
9730
  return {
9705
9731
  version,
9706
9732
  sdkVersion,
@@ -9712,6 +9738,7 @@ function validateMiniappManifestForDeploy(manifest) {
9712
9738
  ...(window === undefined ? {} : { window }),
9713
9739
  ...(bindAppIds.length === 0 ? {} : { bindAppIds }),
9714
9740
  ...(category === undefined ? {} : { category }),
9741
+ ...(desc === undefined ? {} : { desc }),
9715
9742
  };
9716
9743
  }
9717
9744
  function validateGeneratedCompanions(value) {
@@ -1299,7 +1299,7 @@ function isManagedMiniProgramRuntimePermissionKey(key) {
1299
1299
  * `requirement`:`kind: 'none'` 不读取权限;`kind: 'all'` 要求列出的每个 canonical entry 都存在
1300
1300
  * 且 `status === 'enabled'`。之后仍需通过 Host capability、可信手势、用户授权、参数和业务
1301
1301
  * policy。当前 Runtime 对 `valid: false` 按空权限表 fail closed,受保护 method 会得到
1302
- * `PERMISSION_NOT_DECLARED`,而不是沿用输入中的部分 enabled entry。
1302
+ * `PERMISSION_NOT_IN_SNAPSHOT`,而不是沿用输入中的部分 enabled entry。
1303
1303
  *
1304
1304
  * @example
1305
1305
  * ```ts
@@ -1297,7 +1297,7 @@ function isManagedMiniProgramRuntimePermissionKey(key) {
1297
1297
  * `requirement`:`kind: 'none'` 不读取权限;`kind: 'all'` 要求列出的每个 canonical entry 都存在
1298
1298
  * 且 `status === 'enabled'`。之后仍需通过 Host capability、可信手势、用户授权、参数和业务
1299
1299
  * policy。当前 Runtime 对 `valid: false` 按空权限表 fail closed,受保护 method 会得到
1300
- * `PERMISSION_NOT_DECLARED`,而不是沿用输入中的部分 enabled entry。
1300
+ * `PERMISSION_NOT_IN_SNAPSHOT`,而不是沿用输入中的部分 enabled entry。
1301
1301
  *
1302
1302
  * @example
1303
1303
  * ```ts
package/dist/vite.cjs.js CHANGED
@@ -10282,7 +10282,7 @@ async function ensureBasicInfoDirectory(rootPath, relative) {
10282
10282
  /** 构建时替换为当前发布包的实际版本。 */
10283
10283
  const HB_SDK_VERSION = typeof undefined === 'string'
10284
10284
  ? undefined
10285
- : '0.9.1-alpha.9';
10285
+ : '0.9.1';
10286
10286
 
10287
10287
  /**
10288
10288
  * iframe 与调试台页面的开发期 console 捕获转发。
@@ -10700,6 +10700,31 @@ function parseMiniappCategory(value, sourceLabel = 'package.json#heybox.category
10700
10700
  throw new Error(`${sourceLabel} 必须是 tool、game 或 other`);
10701
10701
  }
10702
10702
 
10703
+ /** 小程序简介最大长度(Unicode code point),与服务端截断口径一致。 */
10704
+ const MINIAPP_DESC_MAX_LENGTH = 200;
10705
+ /**
10706
+ * 校验并规范化 `package.json#heybox.desc` / `manifest.desc`。
10707
+ *
10708
+ * @param value - 原始声明;未声明时为 `undefined`。
10709
+ * @param sourceLabel - 错误消息中的字段来源,默认 `package.json#heybox.desc`。
10710
+ * @returns 去除首尾空白后的简介;未声明或为空串时返回 `undefined`。
10711
+ * @throws `Error` 非字符串、超过 200 个字符,或包含除换行外的控制字符时抛出。
10712
+ */
10713
+ function parseMiniappDesc(value, sourceLabel = 'package.json#heybox.desc') {
10714
+ if (value === undefined)
10715
+ return undefined;
10716
+ if (typeof value !== 'string')
10717
+ throw new Error(`${sourceLabel} 必须是字符串`);
10718
+ const desc = value.replace(/^\p{White_Space}+|\p{White_Space}+$/gu, '');
10719
+ if (!desc)
10720
+ return undefined;
10721
+ if (Array.from(desc).length > MINIAPP_DESC_MAX_LENGTH)
10722
+ throw new Error(`${sourceLabel} 不能超过 ${MINIAPP_DESC_MAX_LENGTH} 个字符`);
10723
+ if (/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(desc.replace(/\n/g, '')))
10724
+ throw new Error(`${sourceLabel} 不能包含控制字符`);
10725
+ return desc;
10726
+ }
10727
+
10703
10728
  const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
10704
10729
  function parseMiniappPermissions(value, options) {
10705
10730
  const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
@@ -10811,6 +10836,7 @@ function renderMiniappManifest(manifest) {
10811
10836
  const window = validateMiniappWindow(manifest.window, 'manifest.window');
10812
10837
  const category = parseMiniappCategory(manifest.category, 'manifest.category');
10813
10838
  const bindAppIds = parseMiniappBindAppIds(manifest.bindAppIds, { sourceLabel: 'manifest.bindAppIds' });
10839
+ const desc = parseMiniappDesc(manifest.desc, 'manifest.desc');
10814
10840
  const output = {
10815
10841
  version: manifest.version,
10816
10842
  sdkVersion: manifest.sdkVersion,
@@ -10822,6 +10848,7 @@ function renderMiniappManifest(manifest) {
10822
10848
  ...(window === undefined ? {} : { window }),
10823
10849
  ...(bindAppIds.length === 0 ? {} : { bindAppIds }),
10824
10850
  ...(category === undefined ? {} : { category }),
10851
+ ...(desc === undefined ? {} : { desc }),
10825
10852
  };
10826
10853
  return `${JSON.stringify(output, null, 2)}\n`;
10827
10854
  }
@@ -10992,6 +11019,11 @@ function readMiniappCategoryFromPackageJson(root) {
10992
11019
  const { packageJson } = readMiniappPackageJson(root, false);
10993
11020
  return parseMiniappCategory(readMiniappHeyboxConfig(packageJson)?.category);
10994
11021
  }
11022
+ /** 读取并校验 `package.json#heybox.desc`;未声明或为空时返回 `undefined`。 */
11023
+ function readMiniappDescFromPackageJson(root) {
11024
+ const { packageJson } = readMiniappPackageJson(root, false);
11025
+ return parseMiniappDesc(readMiniappHeyboxConfig(packageJson)?.desc);
11026
+ }
10995
11027
  function readMiniappPackageJson(root, requireVersion) {
10996
11028
  const packageJsonPath = findNearestPackageJsonPath(root);
10997
11029
  let content;
@@ -20529,6 +20561,7 @@ const devSnapshotStores = devSnapshotRegistry[devSnapshotStoreKey];
20529
20561
  * 图片源路径相对项目目录;icon 为 200×200,封面 1–5 张,每张不超过 10 MiB / 4000 万像素。
20530
20562
  * build 会复制图片到输出目录 `_hb/basic-info/`,并将 Manifest 路径改为生成路径,不改写源图片;
20531
20563
  * - `heybox.category`:`tool`、`game` 或 `other`;构建时允许缺省,发布预检要求提供;
20564
+ * - `heybox.desc`:可选简介,最多 200 个字符,写入 manifest 后在小程序简介页展示;
20532
20565
  * - `heybox.platforms`:项目实际承诺适配的非空、无重复平台 allowlist;输出按平台词表规范排序。
20533
20566
  * 声明仍停留在旧模板移动端默认(`android`、`ios`、`ohos`)时,`serve` 与 `build` 都只输出
20534
20567
  * 一条非阻断提示,不影响构建结果;
@@ -20983,6 +21016,7 @@ function miniappManifest() {
20983
21016
  const companionDeclarations = includeCompanions ? companionConfig.declarations : undefined;
20984
21017
  const bindAppIds = readMiniappBindAppIdsFromPackageJson(root);
20985
21018
  const category = readMiniappCategoryFromPackageJson(root);
21019
+ const desc = readMiniappDescFromPackageJson(root);
20986
21020
  if (companionDeclarations && !parsedPermissions.permissions?.companion) {
20987
21021
  throw new Error('配置 companions 时必须声明 package.json#heybox.permissions.companion.enabled=true');
20988
21022
  }
@@ -21020,6 +21054,7 @@ function miniappManifest() {
21020
21054
  const companions = prepareMiniappCompanions(companionDeclarations, { root: companionConfig.projectRoot, outputRoot, platforms });
21021
21055
  node_fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
21022
21056
  const manifestText = renderMiniappManifest({
21057
+ ...(desc === undefined ? {} : { desc }),
21023
21058
  version,
21024
21059
  sdkVersion,
21025
21060
  platforms,
package/dist/vite.esm.js CHANGED
@@ -10279,7 +10279,7 @@ async function ensureBasicInfoDirectory(rootPath, relative) {
10279
10279
  /** 构建时替换为当前发布包的实际版本。 */
10280
10280
  const HB_SDK_VERSION = typeof undefined === 'string'
10281
10281
  ? undefined
10282
- : '0.9.1-alpha.9';
10282
+ : '0.9.1';
10283
10283
 
10284
10284
  /**
10285
10285
  * iframe 与调试台页面的开发期 console 捕获转发。
@@ -10697,6 +10697,31 @@ function parseMiniappCategory(value, sourceLabel = 'package.json#heybox.category
10697
10697
  throw new Error(`${sourceLabel} 必须是 tool、game 或 other`);
10698
10698
  }
10699
10699
 
10700
+ /** 小程序简介最大长度(Unicode code point),与服务端截断口径一致。 */
10701
+ const MINIAPP_DESC_MAX_LENGTH = 200;
10702
+ /**
10703
+ * 校验并规范化 `package.json#heybox.desc` / `manifest.desc`。
10704
+ *
10705
+ * @param value - 原始声明;未声明时为 `undefined`。
10706
+ * @param sourceLabel - 错误消息中的字段来源,默认 `package.json#heybox.desc`。
10707
+ * @returns 去除首尾空白后的简介;未声明或为空串时返回 `undefined`。
10708
+ * @throws `Error` 非字符串、超过 200 个字符,或包含除换行外的控制字符时抛出。
10709
+ */
10710
+ function parseMiniappDesc(value, sourceLabel = 'package.json#heybox.desc') {
10711
+ if (value === undefined)
10712
+ return undefined;
10713
+ if (typeof value !== 'string')
10714
+ throw new Error(`${sourceLabel} 必须是字符串`);
10715
+ const desc = value.replace(/^\p{White_Space}+|\p{White_Space}+$/gu, '');
10716
+ if (!desc)
10717
+ return undefined;
10718
+ if (Array.from(desc).length > MINIAPP_DESC_MAX_LENGTH)
10719
+ throw new Error(`${sourceLabel} 不能超过 ${MINIAPP_DESC_MAX_LENGTH} 个字符`);
10720
+ if (/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(desc.replace(/\n/g, '')))
10721
+ throw new Error(`${sourceLabel} 不能包含控制字符`);
10722
+ return desc;
10723
+ }
10724
+
10700
10725
  const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
10701
10726
  function parseMiniappPermissions(value, options) {
10702
10727
  const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
@@ -10808,6 +10833,7 @@ function renderMiniappManifest(manifest) {
10808
10833
  const window = validateMiniappWindow(manifest.window, 'manifest.window');
10809
10834
  const category = parseMiniappCategory(manifest.category, 'manifest.category');
10810
10835
  const bindAppIds = parseMiniappBindAppIds(manifest.bindAppIds, { sourceLabel: 'manifest.bindAppIds' });
10836
+ const desc = parseMiniappDesc(manifest.desc, 'manifest.desc');
10811
10837
  const output = {
10812
10838
  version: manifest.version,
10813
10839
  sdkVersion: manifest.sdkVersion,
@@ -10819,6 +10845,7 @@ function renderMiniappManifest(manifest) {
10819
10845
  ...(window === undefined ? {} : { window }),
10820
10846
  ...(bindAppIds.length === 0 ? {} : { bindAppIds }),
10821
10847
  ...(category === undefined ? {} : { category }),
10848
+ ...(desc === undefined ? {} : { desc }),
10822
10849
  };
10823
10850
  return `${JSON.stringify(output, null, 2)}\n`;
10824
10851
  }
@@ -10989,6 +11016,11 @@ function readMiniappCategoryFromPackageJson(root) {
10989
11016
  const { packageJson } = readMiniappPackageJson(root, false);
10990
11017
  return parseMiniappCategory(readMiniappHeyboxConfig(packageJson)?.category);
10991
11018
  }
11019
+ /** 读取并校验 `package.json#heybox.desc`;未声明或为空时返回 `undefined`。 */
11020
+ function readMiniappDescFromPackageJson(root) {
11021
+ const { packageJson } = readMiniappPackageJson(root, false);
11022
+ return parseMiniappDesc(readMiniappHeyboxConfig(packageJson)?.desc);
11023
+ }
10992
11024
  function readMiniappPackageJson(root, requireVersion) {
10993
11025
  const packageJsonPath = findNearestPackageJsonPath(root);
10994
11026
  let content;
@@ -20526,6 +20558,7 @@ const devSnapshotStores = devSnapshotRegistry[devSnapshotStoreKey];
20526
20558
  * 图片源路径相对项目目录;icon 为 200×200,封面 1–5 张,每张不超过 10 MiB / 4000 万像素。
20527
20559
  * build 会复制图片到输出目录 `_hb/basic-info/`,并将 Manifest 路径改为生成路径,不改写源图片;
20528
20560
  * - `heybox.category`:`tool`、`game` 或 `other`;构建时允许缺省,发布预检要求提供;
20561
+ * - `heybox.desc`:可选简介,最多 200 个字符,写入 manifest 后在小程序简介页展示;
20529
20562
  * - `heybox.platforms`:项目实际承诺适配的非空、无重复平台 allowlist;输出按平台词表规范排序。
20530
20563
  * 声明仍停留在旧模板移动端默认(`android`、`ios`、`ohos`)时,`serve` 与 `build` 都只输出
20531
20564
  * 一条非阻断提示,不影响构建结果;
@@ -20980,6 +21013,7 @@ function miniappManifest() {
20980
21013
  const companionDeclarations = includeCompanions ? companionConfig.declarations : undefined;
20981
21014
  const bindAppIds = readMiniappBindAppIdsFromPackageJson(root);
20982
21015
  const category = readMiniappCategoryFromPackageJson(root);
21016
+ const desc = readMiniappDescFromPackageJson(root);
20983
21017
  if (companionDeclarations && !parsedPermissions.permissions?.companion) {
20984
21018
  throw new Error('配置 companions 时必须声明 package.json#heybox.permissions.companion.enabled=true');
20985
21019
  }
@@ -21017,6 +21051,7 @@ function miniappManifest() {
21017
21051
  const companions = prepareMiniappCompanions(companionDeclarations, { root: companionConfig.projectRoot, outputRoot, platforms });
21018
21052
  mkdirSync(path.dirname(manifestPath), { recursive: true });
21019
21053
  const manifestText = renderMiniappManifest({
21054
+ ...(desc === undefined ? {} : { desc }),
21020
21055
  version,
21021
21056
  sdkVersion,
21022
21057
  platforms,
@@ -89,7 +89,9 @@ Storage 面板只通过 `runtime.diagnostics.storage?.getSnapshot()` 读取 Runt
89
89
  | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
90
90
  | Browser Dev Host | 私有 WebSocket channel 优先,HTTP/SSE 保留为兼容路径。账号 identity 的 canonical 读取仍由 HTTP session status 完成;channel 只发 revision hint,收到 hint 后重新读取 HTTP 状态。 | WebSocket 握手、重连或消息失败不阻断 Browser Mock;回退 HTTP/SSE 并继续有界轮询。 |
91
91
  | Mobile Release | 当前稳定客户端继续把原生 `mini_url` launch 交给详情 H5/Native Host;二维码保持 HTTPS `open_inapp` 与 `heybox://` `openWindow`,但短链这一跳是普通 H5。跳转页打开完整 sandbox query(`mini_url`、身份、启动票和 LAN Dev Context)后延迟 `closeWindow`。真机 WebView 基址是 `http://127.0.0.1` 详情页且 HTML 来自线上缓存。 | 生成真机二维码前仍需 CLI 登录、项目绑定和有效 Dev Context;这些条件不阻断 Browser 调试台启动。 |
92
- | Mobile Debug/Ad-Hoc H5 | `dev_context_url` 是可选的 Dev Session 输入;读取成功后采用本地 network proxy,代理不参与 Runtime 权限判断。 | Dev Context 缺失、过期、不可达或校验失败时记录脱敏诊断,继续使用原生 Host 的账号、网络与远端权限。 |
92
+ | Mobile Debug/Ad-Hoc H5 | `dev_context_url` 是可选的 Dev Session 输入;读取成功后采用本地 network proxy,代理不参与 Runtime 权限判断。 | 历史协议 Dev Context 不可用时保留原生适配;新开发协议缺少有效描述时阻断并提示重试或更新 CLI。 |
93
+
94
+ 开发快照与凭据续期的权威约定见[开发会话](./development-session.md)。
93
95
 
94
96
  `DevSession` 同时携带本地声明、独立的 `local_dev_grant` 与 context revision,不会反向修改线上配置。真实 H5 必须先以启动票取得 canonical identity,再将可信线上基线与声明及严格解析的 grant 合成普通 Runtime 快照;没有有效票据或非法 grant 时不临时放权。临时授权仅允许 `network` / `companion`,不包含 `useOfficialDomain`,且每次启动由用户确认。
95
97
 
@@ -101,7 +103,7 @@ Node 负责 CLI-owned stable context endpoint、短跳转 registry 和 Launch Re
101
103
 
102
104
  ## Mobile 短跳转安全边界
103
105
 
104
- 默认 Mobile 二维码编码现有 `https://api.xiaoheihe.cn/open_inapp/#heybox://...` 启动契约,但短链这一跳是普通 H5 `openWindow`(不带 `mini_program`),`webview.url` 只放局域网短链 `http://<lan-ip>:<port>/l/<token>`。短链返回 HTML 跳转页:先 `location.href` 打开完整 `heybox-mini-dev://sandbox` 协议,约 500ms 后再发 `closeWindow` 关掉中间页。不要对自定义协议做 HTTP 302,WebView 会把它当成相对路径。真机 WebView 基址是 `http://127.0.0.1/tools/user_miniprogram/detail`,HTML 来自线上详情页缓存,因此最终协议携带 `mini_url`、`mini_program_id`、`local_dev_launch_token`、`sdk_version` 和稳定 CLI-owned `dev_context_url`;二维码短期 token 轮换不会让已打开页面失效。`launch.json` 仍可作为同分支详情 Host 的补充发现。Dev Context 过期或校验失败时记录脱敏诊断,继续使用原生网络与已发现的权限。
106
+ 默认 Mobile 二维码编码现有 `https://api.xiaoheihe.cn/open_inapp/#heybox://...` 启动契约,但短链这一跳是普通 H5 `openWindow`(不带 `mini_program`),`webview.url` 只放局域网短链 `http://<lan-ip>:<port>/l/<token>`。短链返回 HTML 跳转页:先 `location.href` 打开完整 `heybox-mini-dev://sandbox` 协议,约 500ms 后再发 `closeWindow` 关掉中间页。不要对自定义协议做 HTTP 302,WebView 会把它当成相对路径。真机 WebView 基址是 `http://127.0.0.1/tools/user_miniprogram/detail`,HTML 来自线上详情页缓存,因此最终协议携带 `mini_url`、`mini_program_id`、`local_dev_launch_token`、`sdk_version` 和稳定 CLI-owned `dev_context_url`;二维码短期 token 轮换不会让已打开页面失效。`launch.json` 仍可作为同分支详情 Host 的补充发现。新开发协议的 Dev Context 过期或校验失败时不能生成新运行快照;历史适配边界见开发会话文档。
105
107
 
106
108
  `launch.json` 和短链都只减少二维码编码长度,不是认证、加密、签名或 HMAC:
107
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk",
3
- "version": "0.9.1-alpha.9",
3
+ "version": "0.9.1",
4
4
  "sideEffects": [
5
5
  "./src/index.ts",
6
6
  "./src/core/singleton.ts",
@@ -76,7 +76,7 @@
76
76
  "undici": "^7.28.0",
77
77
  "ws": "^8.18.0",
78
78
  "sharp": "^0.34.5",
79
- "@heybox/hb-sdk-protocol": "0.9.1-alpha.9"
79
+ "@heybox/hb-sdk-protocol": "0.9.1"
80
80
  },
81
81
  "peerDependencies": {
82
82
  "vite": ">=5"
@@ -128,10 +128,10 @@
128
128
  "vitest": "^3.2.4",
129
129
  "@ai-desktop/view-contract": "file:../hb-sdk-protocol/vendor/view-contract-2.2.2-6ac49bbf6410.tgz",
130
130
  "rollup-plugin-dts": "6.4.0",
131
- "@heybox-domain/heybox-vue3-ui": "~0.1.0",
132
131
  "@heybox-domain/heybox-theme": "~0.1.0",
133
- "@heybox/hb-sdk-runtime": "~0.9.1-alpha.9",
132
+ "@heybox/hb-sdk-runtime": "~0.9.1",
134
133
  "@heybox/hb-api": "~1.28.14",
134
+ "@heybox-domain/heybox-vue3-ui": "~0.1.0",
135
135
  "@heybox/runtime": "~0.2.1",
136
136
  "@heybox/runtime-policy": "~0.2.1",
137
137
  "@heybox/runtime-transport-fetch": "~0.2.1"
package/skill/SKILL.md CHANGED
@@ -7,6 +7,16 @@ description: Uses @heybox/hb-sdk and the hb-sdk CLI to build, debug, review, and
7
7
 
8
8
  Use this Skill for workshop mini-program application code, project declarations, public SDK APIs, CLI workflows, Host/Runtime protocol maintenance, and publishing review.
9
9
 
10
+ ## Screenshot API Changes: Mandatory Upgrade Checks
11
+
12
+ Before implementing screenshot flows or upgrading the SDK, use the canonical documentation index to read the screenshot Reference, community-sharing Recipe, and upgrade notes. Explicitly explain these changes to the developer:
13
+
14
+ - Check the installed SDK against the watermark version cutoff, including prerelease ordering. Explain the warning emitted by the SDK screenshot entry and the Runtime's compatibility behavior for legacy screenshots versus the default watermark behavior for newer SDKs.
15
+ - Check the required reserved area at the bottom of the capture region, the content that must remain unobstructed, and the corresponding rules for custom capture rectangles.
16
+ - Check the light/dark theme option, default colors, system-theme behavior, and the support boundary between SDK screenshots and physical-button screenshots.
17
+
18
+ Before upgrading, verify both the page layout and the captured image. Do not only update the dependency or invocation without explaining screenshot behavior changes. Read exact version cutoffs, dimensions, parameters, and Host support from the canonical documentation fetched for this task; never substitute an older installed Skill snapshot.
19
+
10
20
  ## Canonical Documentation
11
21
 
12
22
  The only maintained hb-sdk guidance source is:
package/skill/skill.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "hb-sdk",
3
- "skillVersion": "0.9.1-alpha.9+skill.3260e7d71ada",
3
+ "skillVersion": "0.9.1+skill.c3a240ca503a",
4
4
  "sdk": {
5
5
  "package": "@heybox/hb-sdk",
6
- "version": "0.9.1-alpha.9",
7
- "compatibility": "0.9.1-alpha.9"
6
+ "version": "0.9.1",
7
+ "compatibility": "0.9.1"
8
8
  },
9
9
  "distribution": {
10
10
  "type": "npm",
11
11
  "package": "@heybox/hb-sdk",
12
- "version": "0.9.1-alpha.9",
12
+ "version": "0.9.1",
13
13
  "path": "skill"
14
14
  },
15
- "integrity": "sha256-3260e7d71ada646d5d8b269490e3de4b5ecd3fe824b18cdb73fe64247738ffea"
15
+ "integrity": "sha256-c3a240ca503a1e5f3b15033e091f1fa79a8b70585aa0d8d8fa0b332daec60ac5"
16
16
  }