@heybox/hb-sdk 0.7.3-alpha.0 → 0.7.3

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 (34) hide show
  1. package/CHANGELOG.md +28 -2
  2. package/README.md +4 -4
  3. package/dist/cli-chunks/{build-CIZIWLmV.cjs → build-0sZ873iU.cjs} +2 -2
  4. package/dist/cli-chunks/{context-DdKKaf1o.cjs → context-DNQEI7m7.cjs} +1 -1
  5. package/dist/cli-chunks/{create-C5CW72BF.cjs → create-BkE71M2U.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-CH2yODBH.cjs → dev-_tBlQ2WO.cjs} +5 -5
  7. package/dist/cli-chunks/{doctor-SHwm6xSx.cjs → doctor-B1wk8IpC.cjs} +1 -1
  8. package/dist/cli-chunks/{index-DIwi_FPa.cjs → index-BbDsxI94.cjs} +1 -1
  9. package/dist/cli-chunks/{index-DiGjTruv.cjs → index-CIucOD2H.cjs} +14 -14
  10. package/dist/cli-chunks/{login-BrtCvOEN.cjs → login-CnjEKlFT.cjs} +2 -2
  11. package/dist/cli-chunks/{project-vite-BoMy-fAP.cjs → project-vite-ESaxoAE1.cjs} +1 -1
  12. package/dist/cli-chunks/{remote-BDj3TcU7.cjs → remote-BaGzge7R.cjs} +4 -4
  13. package/dist/cli-chunks/{session-DyEpQQ67.cjs → session-C9KHqijL.cjs} +1 -1
  14. package/dist/cli.cjs +1 -1
  15. package/dist/devtools/mock-host/main.js +12 -1
  16. package/dist/index.cjs.js +6 -2
  17. package/dist/index.esm.js +6 -3
  18. package/dist/protocol.cjs.js +4 -0
  19. package/dist/protocol.esm.js +4 -1
  20. package/dist/vite.cjs.js +1 -1
  21. package/dist/vite.esm.js +1 -1
  22. package/package.json +1 -1
  23. package/skill/SKILL.md +1 -1
  24. package/skill/references/api-protocol.md +4 -2
  25. package/skill/references/api-root.md +6 -4
  26. package/skill/references/recipes.md +10 -10
  27. package/skill/references/safety-boundaries.md +1 -1
  28. package/skill/scripts/markdown-sections.mjs +36 -0
  29. package/skill/scripts/sync-references.mjs +11 -33
  30. package/skill/skill.json +4 -4
  31. package/types/index.d.ts +2 -0
  32. package/types/modules/user/get-info.d.ts +1 -1
  33. package/types/modules/user/types.d.ts +12 -8
  34. package/types/protocol.d.ts +2 -0
package/CHANGELOG.md CHANGED
@@ -1,11 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.3
4
+
5
+ ### SDK
6
+
7
+ - 无网络模式下,`user.getInfo()` 恢复隐式授予 `identity` 与 `profile` 全量 scope,并返回隔离身份、昵称和头像。
8
+ - 修复 Host 读取小程序存储对象时返回结果异常的问题。
9
+
10
+ ## 0.7.4-alpha.0
11
+
12
+ ### SDK / Runtime
13
+
14
+ - 修复无网络模式用户 scope 退化:`user.getInfo()` 重新隐式授予 `identity` 与 `profile`,静默返回隔离 `app_user_id`、昵称和头像;资料读取失败时保留身份结果,并拒绝账号切换或撤销后的旧上下文结果。
15
+ - 公开 canonical 用户信息 scope 目录,并让协议类型、Runtime、Browser Mock 与 Host presentation 共享同一 scope owner。
16
+
17
+ ## 0.7.3-alpha.2
18
+
19
+ ### SDK
20
+
21
+ - 对齐无网络用户全量 scope 契约,并公开 canonical 用户信息 scope 目录。
22
+
23
+ ## 0.7.3-alpha.1
24
+
25
+ ### Runtime
26
+
27
+ - 允许 `@heybox/hb-sdk-runtime` 与 `@heybox/hb-sdk` 独立演进版本。
28
+
3
29
  ## 0.7.2
4
30
 
5
31
  ### SDK / Runtime
6
32
 
7
- - 移除 `user.getLocalIdentity()`;未开通网络权限的小程序改用 `user.getInfo()` 静默获取 `userInfo.app_user_id`,不再展示身份授权弹窗。
8
- - 未开通网络权限且用户已登录时,`user.getInfo()` 会静默建立或读取当前小程序隔离身份,并在每次成功调用后广播 `identity: granted`;撤销授权后再次调用会建立新的隔离身份。
33
+ - 移除 `user.getLocalIdentity()`;未开通网络权限的小程序改用 `user.getInfo()` 静默获取隔离身份和公开资料,不再展示身份授权弹窗。
34
+ - 未开通网络权限且用户已登录时,`user.getInfo()` 会静默建立或读取当前小程序隔离身份,并在每次成功调用后广播 `identity: granted` 与 `profile: granted`;撤销授权后再次调用会建立新的隔离身份并恢复隐式授权。
9
35
  - Runtime 不再兼容缺少 canonical `miniProgramId` 的无参 `getUserInfo()` adapter 路径;身份缺失时 `user.getInfo()` 返回 `INVALID_STATE`。
10
36
 
11
37
  ## 0.7.1
package/README.md CHANGED
@@ -23,7 +23,7 @@ npm run dev
23
23
  npm install @heybox/hb-sdk
24
24
  ```
25
25
 
26
- SDK 会在导入时启动握手,能力调用会自动等待 SDK 就绪。未开通网络权限的小程序通过 `user.getInfo()` 静默读取当前小程序内的隔离身份:
26
+ SDK 会在导入时启动握手,能力调用会自动等待 SDK 就绪。未开通网络权限的小程序通过 `user.getInfo()` 静默读取当前小程序内的隔离身份和公开资料:
27
27
 
28
28
  需要可信用户手势的按钮不能在点击回调里等待握手。页面加载时先用 `getHandshakeState()` 读取当前状态,再用 `onHandshakeStateChange()` 订阅并立即接收当前状态;仅在 `status === 'ready'` 时启用按钮,并在组件或页面销毁时调用订阅返回的取消函数。`ready` 生命周期事件只是握手成功瞬间派发、不会重放的边沿通知,不能用来判断当前状态。
29
29
 
@@ -32,11 +32,11 @@ import hbSDK from '@heybox/hb-sdk';
32
32
 
33
33
  async function getCurrentUser() {
34
34
  const result = await hbSDK.user.getInfo();
35
- return result.userInfo?.app_user_id;
35
+ return result.userInfo;
36
36
  }
37
37
  ```
38
38
 
39
- `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回 `isHeyboxAppLoggedIn: false`;已登录时默认返回当前小程序隔离的 `app_user_id`。
39
+ `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回 `isHeyboxAppLoggedIn: false`;已登录时隐式授予当前本地用户 scopes(`identity`、`profile`),返回当前小程序隔离的 `app_user_id` 以及 `profile.nickname`、`profile.avatar`。
40
40
 
41
41
  已开通网络权限的小程序在按钮点击等明确的用户操作中调用 `auth.login()`:
42
42
 
@@ -128,7 +128,7 @@ SDK 还提供 `getHandshakeState()` / `onHandshakeStateChange()` 管理持久握
128
128
  - 需要授权 UI 时,`auth.login()` 必须来自可信用户手势,否则返回 `USER_GESTURE_REQUIRED`;用户取消或关闭时返回 `AUTHORIZATION_CANCELLED`。已授权时可以静默返回新 code。
129
129
  - `user.getSteamGameList()` 仅供未开通网络权限的小程序通过 Host 读取;已开通网络权限时返回 `SERVER_API_REQUIRED`,且授权码与 OpenAPI 不提供 Steam 游戏库 scope 或资源接口。
130
130
  - 已开通网络权限时,公开的 `user.getInfo()` 返回 `SERVER_API_REQUIRED`;对应身份和资料数据应由开发者服务端通过 OpenAPI 获取。
131
- - 未开通网络权限时,使用 `user.getInfo()` 静默读取 `userInfo.app_user_id`,不能获取 code 或调用 OpenAPI。
131
+ - 未开通网络权限时,`user.getInfo()` 隐式授予 `identity` 与 `profile`,静默返回 `userInfo.app_user_id`、昵称和头像;这条路径仍不能获取 code 或调用 OpenAPI。
132
132
  - `user.revokeAuthorization()` 在两种网络模式下都要求可信用户手势;成功后必须停止使用并清理业务缓存的旧身份、资料和服务端会话。
133
133
  - `on()` 返回取消监听函数,组件卸载或页面销毁时需要调用。
134
134
  - 业务网络请求使用 `network.request()`,不要依赖浏览器原生网络出口。
@@ -5,8 +5,8 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var runtimePermissionEnv = require('./runtime-permission-env-D-8_jPG3.cjs');
7
7
  var runtimeGate = require('./runtime-gate-CtV7rWyX.cjs');
8
- var index = require('./index-DiGjTruv.cjs');
9
- var projectVite = require('./project-vite-BoMy-fAP.cjs');
8
+ var index = require('./index-CIucOD2H.cjs');
9
+ var projectVite = require('./project-vite-ESaxoAE1.cjs');
10
10
  require('node:async_hooks');
11
11
  require('node:module');
12
12
  require('path');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var session = require('./session-DyEpQQ67.cjs');
3
+ var session = require('./session-C9KHqijL.cjs');
4
4
  var runtimePermissionEnv = require('./runtime-permission-env-D-8_jPG3.cjs');
5
5
  var fs$1 = require('node:fs');
6
6
  var fs = require('node:fs/promises');
@@ -5,7 +5,7 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var require$$0 = require('fs');
7
7
  var require$$1 = require('path');
8
- var index = require('./index-DiGjTruv.cjs');
8
+ var index = require('./index-CIucOD2H.cjs');
9
9
  require('node:module');
10
10
  require('os');
11
11
  require('readline');
@@ -6,15 +6,15 @@ var path = require('node:path');
6
6
  var net = require('node:net');
7
7
  var promises = require('node:dns/promises');
8
8
  var node_http = require('node:http');
9
- var context = require('./context-DdKKaf1o.cjs');
9
+ var context = require('./context-DNQEI7m7.cjs');
10
10
  var node_crypto = require('node:crypto');
11
11
  var undici = require('undici');
12
12
  var browser = require('./browser-RAy8e8cV.cjs');
13
- var index = require('./index-DiGjTruv.cjs');
14
- var projectVite = require('./project-vite-BoMy-fAP.cjs');
13
+ var index = require('./index-CIucOD2H.cjs');
14
+ var projectVite = require('./project-vite-ESaxoAE1.cjs');
15
15
  var fs$1 = require('node:fs/promises');
16
16
  var runtimePermissionEnv = require('./runtime-permission-env-D-8_jPG3.cjs');
17
- require('./session-DyEpQQ67.cjs');
17
+ require('./session-C9KHqijL.cjs');
18
18
  require('fs');
19
19
  require('constants');
20
20
  require('stream');
@@ -1347,7 +1347,7 @@ function createHeyboxProtocol(payload) {
1347
1347
  /** 构建时替换为当前发布包的实际版本。 */
1348
1348
  const HB_SDK_VERSION = typeof undefined === 'string'
1349
1349
  ? undefined
1350
- : '0.7.3-alpha.0';
1350
+ : '0.7.3';
1351
1351
 
1352
1352
  class DevPermissionOverrideStoreError extends Error {
1353
1353
  code;
@@ -4,7 +4,7 @@ var fs$1 = require('node:fs');
4
4
  var fs = require('node:fs/promises');
5
5
  var os = require('node:os');
6
6
  var path = require('node:path');
7
- var index = require('./index-DiGjTruv.cjs');
7
+ var index = require('./index-CIucOD2H.cjs');
8
8
  require('node:module');
9
9
  require('path');
10
10
  require('os');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index$2 = require('./index-DiGjTruv.cjs');
3
+ var index$2 = require('./index-CIucOD2H.cjs');
4
4
  var require$$0$2 = require('fs');
5
5
  var require$$2$1 = require('crypto');
6
6
  var require$$1$2 = require('path');
@@ -234,19 +234,19 @@ function requireArgument () {
234
234
 
235
235
  var command = {};
236
236
 
237
- const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DiGjTruv.cjs', document.baseURI).href)));
237
+ const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CIucOD2H.cjs', document.baseURI).href)));
238
238
  function __require$4() { return require$5("node:events"); }
239
239
 
240
- const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DiGjTruv.cjs', document.baseURI).href)));
240
+ const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CIucOD2H.cjs', document.baseURI).href)));
241
241
  function __require$3() { return require$4("node:child_process"); }
242
242
 
243
- const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DiGjTruv.cjs', document.baseURI).href)));
243
+ const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CIucOD2H.cjs', document.baseURI).href)));
244
244
  function __require$2() { return require$3("node:path"); }
245
245
 
246
- const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DiGjTruv.cjs', document.baseURI).href)));
246
+ const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CIucOD2H.cjs', document.baseURI).href)));
247
247
  function __require$1() { return require$2("node:fs"); }
248
248
 
249
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-DiGjTruv.cjs', document.baseURI).href)));
249
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CIucOD2H.cjs', document.baseURI).href)));
250
250
  function __require() { return require$1("node:process"); }
251
251
 
252
252
  var help = {};
@@ -13347,7 +13347,7 @@ function getPathname(pathWithQuery) {
13347
13347
  }
13348
13348
 
13349
13349
  const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
13350
- const BUILT_CLI_VERSION = '0.7.3-alpha.0';
13350
+ const BUILT_CLI_VERSION = '0.7.3';
13351
13351
  const PACKAGE_JSON_CANDIDATES = [
13352
13352
  path.resolve(__dirname, '..', '..', 'package.json'),
13353
13353
  path.resolve(__dirname, '..', 'package.json'),
@@ -13681,35 +13681,35 @@ function createCommandLoggerResolver(options) {
13681
13681
  };
13682
13682
  }
13683
13683
  const defaultClearLoginStatus = async (...args) => {
13684
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-BrtCvOEN.cjs'); });
13684
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-CnjEKlFT.cjs'); });
13685
13685
  return clearLoginStatus(...args);
13686
13686
  };
13687
13687
  const defaultLoginToHeybox = async (...args) => {
13688
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-BrtCvOEN.cjs'); });
13688
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-CnjEKlFT.cjs'); });
13689
13689
  return loginToHeybox(...args);
13690
13690
  };
13691
13691
  const defaultPrintLoginStatus = async (...args) => {
13692
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-BrtCvOEN.cjs'); });
13692
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-CnjEKlFT.cjs'); });
13693
13693
  return printLoginStatus(...args);
13694
13694
  };
13695
13695
  const defaultRunBuildCommand = async (...args) => {
13696
- const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-CIZIWLmV.cjs'); });
13696
+ const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-0sZ873iU.cjs'); });
13697
13697
  return runBuildCommand(...args);
13698
13698
  };
13699
13699
  const defaultRunCreateCommand = async (...args) => {
13700
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-C5CW72BF.cjs'); });
13700
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-BkE71M2U.cjs'); });
13701
13701
  return runCreateCommand(...args);
13702
13702
  };
13703
13703
  const defaultRunDevCommand = async (...args) => {
13704
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-CH2yODBH.cjs'); });
13704
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-_tBlQ2WO.cjs'); });
13705
13705
  return runDevCommand(...args);
13706
13706
  };
13707
13707
  const defaultRunDoctorCommand = async (...args) => {
13708
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-SHwm6xSx.cjs'); });
13708
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-B1wk8IpC.cjs'); });
13709
13709
  return runDoctorCommand(...args);
13710
13710
  };
13711
13711
  const defaultRunRemoteCommand = async (...args) => {
13712
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-BDj3TcU7.cjs'); });
13712
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-BaGzge7R.cjs'); });
13713
13713
  return runRemoteCommand(...args);
13714
13714
  };
13715
13715
  function resolveStandaloneLogger(options, verbose) {
@@ -3,9 +3,9 @@
3
3
  var promises = require('node:readline/promises');
4
4
  var node_crypto = require('node:crypto');
5
5
  var node_http = require('node:http');
6
- var session = require('./session-DyEpQQ67.cjs');
6
+ var session = require('./session-C9KHqijL.cjs');
7
7
  var browser = require('./browser-RAy8e8cV.cjs');
8
- var index = require('./index-DiGjTruv.cjs');
8
+ var index = require('./index-CIucOD2H.cjs');
9
9
  require('node:path');
10
10
  require('fs');
11
11
  require('constants');
@@ -5,7 +5,7 @@ var fs$1 = require('node:fs/promises');
5
5
  var node_module = require('node:module');
6
6
  var path = require('node:path');
7
7
  var node_url = require('node:url');
8
- var index = require('./index-DiGjTruv.cjs');
8
+ var index = require('./index-CIucOD2H.cjs');
9
9
 
10
10
  function findProjectRoot(startDir) {
11
11
  let current = path.resolve(startDir);
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var promises = require('node:readline/promises');
4
- var index = require('./index-DiGjTruv.cjs');
5
- var session = require('./session-DyEpQQ67.cjs');
4
+ var index = require('./index-CIucOD2H.cjs');
5
+ var session = require('./session-C9KHqijL.cjs');
6
6
  var childProcess = require('node:child_process');
7
7
  var fs = require('node:fs');
8
8
  var fs$1 = require('node:fs/promises');
@@ -10,7 +10,7 @@ var path = require('node:path');
10
10
  var runtimePermissionEnv = require('./runtime-permission-env-D-8_jPG3.cjs');
11
11
  var runtimeGate = require('./runtime-gate-CtV7rWyX.cjs');
12
12
  var node_crypto = require('node:crypto');
13
- var context = require('./context-DdKKaf1o.cjs');
13
+ var context = require('./context-DNQEI7m7.cjs');
14
14
  require('node:module');
15
15
  require('path');
16
16
  require('os');
@@ -271,7 +271,7 @@ function createDefaultCosClient(uploadToken, COS) {
271
271
  };
272
272
  }
273
273
  async function loadCosConstructor() {
274
- const cosModule = await Promise.resolve().then(function () { return require('./index-DIwi_FPa.cjs'); }).then(function (n) { return n.index; });
274
+ const cosModule = await Promise.resolve().then(function () { return require('./index-BbDsxI94.cjs'); }).then(function (n) { return n.index; });
275
275
  return cosModule.default;
276
276
  }
277
277
  function formatSize(bytes) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DiGjTruv.cjs');
3
+ var index = require('./index-CIucOD2H.cjs');
4
4
  var node_crypto = require('node:crypto');
5
5
  var path = require('node:path');
6
6
  var require$$0$2 = require('fs');
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./cli-chunks/index-DiGjTruv.cjs');
3
+ var index = require('./cli-chunks/index-CIucOD2H.cjs');
4
4
  require('node:module');
5
5
  require('node:fs');
6
6
  require('node:fs/promises');
@@ -419,6 +419,9 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
419
419
  },
420
420
  ];
421
421
 
422
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
423
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
424
+
422
425
  var browser = {};
423
426
 
424
427
  var canPromise;
@@ -5491,6 +5494,14 @@ function isNavigationBarForegroundStyle(value) {
5491
5494
  return value === 'light' || value === 'dark';
5492
5495
  }
5493
5496
 
5497
+ function authorizationFromGrantedScopes(scopes) {
5498
+ const grantedScopes = new Set(scopes);
5499
+ return {
5500
+ identity: grantedScopes.has('identity') ? 'granted' : 'not_requested',
5501
+ profile: grantedScopes.has('profile') ? 'granted' : 'not_requested',
5502
+ };
5503
+ }
5504
+
5494
5505
  /**
5495
5506
  * 当前小程序是否开通了 `network.request`。
5496
5507
  * 公开详情关网时只下发合法空 `entries`,没有 enabled 条目视为未开通。
@@ -5610,7 +5621,7 @@ function createBrowserMockRuntimePlatformAdapter(options) {
5610
5621
  return appUserId && miniProgramId
5611
5622
  ? {
5612
5623
  isHeyboxAppLoggedIn: true,
5613
- authorization: { identity: 'granted', profile: 'not_requested' },
5624
+ authorization: authorizationFromGrantedScopes(USER_INFO_AUTHORIZATION_SCOPES),
5614
5625
  userInfo: {
5615
5626
  app_user_id: `${appUserId}:${miniProgramId}`,
5616
5627
  profile: { nickname: currentUser?.nickname || '', avatar: currentUser?.avatar || '' },
package/dist/index.cjs.js CHANGED
@@ -640,7 +640,7 @@ function createMessageId() {
640
640
  /** 构建时替换为当前发布包的实际版本。 */
641
641
  const HB_SDK_VERSION = typeof undefined === 'string'
642
642
  ? undefined
643
- : '0.7.3-alpha.0';
643
+ : '0.7.3';
644
644
 
645
645
  /**
646
646
  * 判断未知数据是否符合小程序 bridge 消息信封。
@@ -1449,7 +1449,7 @@ function createViewportModule(requester) {
1449
1449
  * @returns 当前用户的登录态与公开基础资料。
1450
1450
  *
1451
1451
  * 未开通网络权限且当前黑盒 APP 用户已登录时,该能力会静默建立或读取按小程序隔离的
1452
- * `app_user_id`,不展示授权 UI;仅在 profile 授权后返回昵称与头像。未登录时返回
1452
+ * `app_user_id`,并隐式授予 `identity` 与 `profile` 后返回昵称与头像,不展示授权 UI。未登录时返回
1453
1453
  * `{ isHeyboxAppLoggedIn: false, authorization: null, userInfo: null }`。
1454
1454
  *
1455
1455
  * @throws {HbMiniProgramSDKError} 当 SDK 调用失败时抛出。
@@ -1473,6 +1473,9 @@ function getSteamGameList(requester, options) {
1473
1473
  return requester.request(USER_GET_STEAM_GAME_LIST_METHOD, options);
1474
1474
  }
1475
1475
 
1476
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
1477
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
1478
+
1476
1479
  function createUserModule(requester) {
1477
1480
  return {
1478
1481
  getInfo: () => getInfo(requester),
@@ -1847,6 +1850,7 @@ const hbSDK = {
1847
1850
 
1848
1851
  exports.HbMiniProgramNetworkError = HbMiniProgramNetworkError;
1849
1852
  exports.HbMiniProgramSDKError = HbMiniProgramSDKError;
1853
+ exports.USER_INFO_AUTHORIZATION_SCOPES = USER_INFO_AUTHORIZATION_SCOPES;
1850
1854
  exports.auth = auth;
1851
1855
  exports.cloud = cloud;
1852
1856
  exports.default = hbSDK;
package/dist/index.esm.js CHANGED
@@ -636,7 +636,7 @@ function createMessageId() {
636
636
  /** 构建时替换为当前发布包的实际版本。 */
637
637
  const HB_SDK_VERSION = typeof undefined === 'string'
638
638
  ? undefined
639
- : '0.7.3-alpha.0';
639
+ : '0.7.3';
640
640
 
641
641
  /**
642
642
  * 判断未知数据是否符合小程序 bridge 消息信封。
@@ -1445,7 +1445,7 @@ function createViewportModule(requester) {
1445
1445
  * @returns 当前用户的登录态与公开基础资料。
1446
1446
  *
1447
1447
  * 未开通网络权限且当前黑盒 APP 用户已登录时,该能力会静默建立或读取按小程序隔离的
1448
- * `app_user_id`,不展示授权 UI;仅在 profile 授权后返回昵称与头像。未登录时返回
1448
+ * `app_user_id`,并隐式授予 `identity` 与 `profile` 后返回昵称与头像,不展示授权 UI。未登录时返回
1449
1449
  * `{ isHeyboxAppLoggedIn: false, authorization: null, userInfo: null }`。
1450
1450
  *
1451
1451
  * @throws {HbMiniProgramSDKError} 当 SDK 调用失败时抛出。
@@ -1469,6 +1469,9 @@ function getSteamGameList(requester, options) {
1469
1469
  return requester.request(USER_GET_STEAM_GAME_LIST_METHOD, options);
1470
1470
  }
1471
1471
 
1472
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
1473
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
1474
+
1472
1475
  function createUserModule(requester) {
1473
1476
  return {
1474
1477
  getInfo: () => getInfo(requester),
@@ -1841,4 +1844,4 @@ const hbSDK = {
1841
1844
  cloud,
1842
1845
  };
1843
1846
 
1844
- export { HbMiniProgramNetworkError, HbMiniProgramSDKError, auth, cloud, hbSDK as default, device, getHandshakeState, navigation, network, off, on, onHandshakeStateChange, share, storage, ui, user, viewport };
1847
+ export { HbMiniProgramNetworkError, HbMiniProgramSDKError, USER_INFO_AUTHORIZATION_SCOPES, auth, cloud, hbSDK as default, device, getHandshakeState, navigation, network, off, on, onHandshakeStateChange, share, storage, ui, user, viewport };
@@ -444,6 +444,9 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
444
444
  },
445
445
  ];
446
446
 
447
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
448
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
449
+
447
450
  exports.AUTH_LOGIN_METHOD = AUTH_LOGIN_METHOD;
448
451
  exports.CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD = CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD;
449
452
  exports.CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD;
@@ -474,6 +477,7 @@ exports.UI_SHOW_LOADING_METHOD = UI_SHOW_LOADING_METHOD;
474
477
  exports.UI_SHOW_TOAST_METHOD = UI_SHOW_TOAST_METHOD;
475
478
  exports.USER_GET_INFO_METHOD = USER_GET_INFO_METHOD;
476
479
  exports.USER_GET_STEAM_GAME_LIST_METHOD = USER_GET_STEAM_GAME_LIST_METHOD;
480
+ exports.USER_INFO_AUTHORIZATION_SCOPES = USER_INFO_AUTHORIZATION_SCOPES;
477
481
  exports.USER_REVOKE_AUTHORIZATION_METHOD = USER_REVOKE_AUTHORIZATION_METHOD;
478
482
  exports.VIEWPORT_GET_WINDOW_INFO_METHOD = VIEWPORT_GET_WINDOW_INFO_METHOD;
479
483
  exports.VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD;
@@ -442,4 +442,7 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
442
442
  },
443
443
  ];
444
444
 
445
- export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NETWORK_PROTECTED_PATHS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, computeTrustedIframeUserGesture, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isOfficialMiniProgramNetworkUrl, isProtectedMiniProgramNetworkPath, normalizeMiniProgramNetworkPathname, parseMiniProgramRuntimePermissions };
445
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
446
+ const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
447
+
448
+ export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NETWORK_PROTECTED_PATHS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, computeTrustedIframeUserGesture, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isOfficialMiniProgramNetworkUrl, isProtectedMiniProgramNetworkPath, normalizeMiniProgramNetworkPathname, parseMiniProgramRuntimePermissions };
package/dist/vite.cjs.js CHANGED
@@ -8,7 +8,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
8
8
  /** 构建时替换为当前发布包的实际版本。 */
9
9
  const HB_SDK_VERSION = typeof undefined === 'string'
10
10
  ? undefined
11
- : '0.7.3-alpha.0';
11
+ : '0.7.3';
12
12
 
13
13
  var re = {exports: {}};
14
14
 
package/dist/vite.esm.js CHANGED
@@ -5,7 +5,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
5
5
  /** 构建时替换为当前发布包的实际版本。 */
6
6
  const HB_SDK_VERSION = typeof undefined === 'string'
7
7
  ? undefined
8
- : '0.7.3-alpha.0';
8
+ : '0.7.3';
9
9
 
10
10
  var re = {exports: {}};
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk",
3
- "version": "0.7.3-alpha.0",
3
+ "version": "0.7.3",
4
4
  "sideEffects": [
5
5
  "./src/index.ts",
6
6
  "./src/core/singleton.ts",
package/skill/SKILL.md CHANGED
@@ -41,7 +41,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
41
41
  1. Import the root package eagerly; the SDK starts its handshake automatically and capability calls wait for it internally.
42
42
  2. For a network-enabled mini-program, use `auth.login({ scopes? })` to obtain `{ code, expiresIn: 300, scopes }`. Identity is always implicit; request only optional scopes the business actually needs.
43
43
  3. Send the code only to the developer's backend. That backend follows the backend OpenAPI documentation to exchange it for a token; mini-program code must never exchange application credentials itself.
44
- 4. For a network-disabled mini-program, call `user.getInfo()` to read the current login state and `userInfo.app_user_id`. This read is silent and does not require a trusted user action. It cannot obtain a code or call OpenAPI.
44
+ 4. For a network-disabled mini-program, call `user.getInfo()` to read the current login state, `userInfo.app_user_id`, and `userInfo.profile`. The Host silently grants the current local user scopes (`identity` and `profile`), so this call does not require a trusted user action or authorization UI. It still cannot obtain a code or call OpenAPI.
45
45
  5. Handle `HbMiniProgramSDKError` for SDK initialization and capability failures.
46
46
  6. Handle `HbMiniProgramNetworkError` separately when HTTP completed but `validateStatus` rejected the status.
47
47
  7. Use `getHandshakeState()` for the current persistent handshake state and `onHandshakeStateChange()` for an immediate replay plus future changes. Cancel the returned subscription when the page or component unmounts.
@@ -131,6 +131,8 @@ export type {
131
131
  SteamGamePrice,
132
132
  SteamGameListSort,
133
133
  } from './modules/user';
134
+ export { USER_INFO_AUTHORIZATION_SCOPES } from './modules/user';
135
+ export type { UserInfoAuthorizationScope } from './modules/user';
134
136
  export type { ScreenshotPayload, ScreenshotResult } from './modules/share/screenshot';
135
137
  export type { ShowShareMenuPayload, ShowShareMenuResult } from './modules/share/show-share-menu';
136
138
  export type {
@@ -208,7 +210,7 @@ Reference 由 `@heybox/hb-sdk` 的公开导出与源码注释自动生成,不
208
210
 
209
211
  | 导出面 | Classes | Functions | Interfaces | Types | Constants |
210
212
  | --- | ---: | ---: | ---: | ---: | ---: |
211
- | Root API | 2 | 4 | 50 | 53 | 0 |
212
- | Protocol API | 0 | 7 | 46 | 64 | 30 |
213
+ | Root API | 2 | 4 | 50 | 54 | 1 |
214
+ | Protocol API | 0 | 7 | 46 | 65 | 31 |
213
215
  | Miniapp Publish API | 0 | 5 | 2 | 0 | 0 |
214
216
  | Vite API | 0 | 1 | 0 | 0 | 0 |
@@ -24,7 +24,7 @@
24
24
  ## Package metadata
25
25
 
26
26
  - Package: `@heybox/hb-sdk`
27
- - Version at generation time: `0.7.2`
27
+ - Version at generation time: `0.7.3`
28
28
  - Public root export: `@heybox/hb-sdk`
29
29
  - Protocol export: `@heybox/hb-sdk/protocol`
30
30
  - Vite plugin export: `@heybox/hb-sdk/vite`
@@ -86,6 +86,8 @@ export type {
86
86
  SteamGamePrice,
87
87
  SteamGameListSort,
88
88
  } from './modules/user';
89
+ export { USER_INFO_AUTHORIZATION_SCOPES } from './modules/user';
90
+ export type { UserInfoAuthorizationScope } from './modules/user';
89
91
  export type {
90
92
  MiniProgramScreenshotOptions,
91
93
  MiniProgramScreenshotRect,
@@ -413,18 +415,18 @@ onUnmounted(stopHandshakeState)
413
415
 
414
416
  ## 未开通网络权限
415
417
 
416
- 无网络小程序可以在本地能力中使用按小程序隔离的 `app_user_id`:
418
+ 无网络小程序可以在本地能力中使用按小程序隔离的 `app_user_id` 和公开资料:
417
419
 
418
420
  ```ts
419
421
  import hbSDK from '@heybox/hb-sdk'
420
422
 
421
423
  async function getCurrentUser() {
422
424
  const result = await hbSDK.user.getInfo()
423
- return result.userInfo?.app_user_id
425
+ return result.userInfo
424
426
  }
425
427
  ```
426
428
 
427
- `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回未登录状态;已登录时静默返回 `userInfo.app_user_id`。这条路径不能获取授权码或调用 OpenAPI,也不要把 `app_user_id` 发送到外部服务。
429
+ `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回未登录状态;已登录时隐式授予当前本地用户 scopes(`identity`、`profile`),静默返回 `userInfo.app_user_id`、`profile.nickname` `profile.avatar`。这条路径不能获取授权码或调用 OpenAPI,也不能把身份或资料发送到外部服务。
428
430
 
429
431
  ## 已开通网络权限
430
432
 
@@ -49,18 +49,18 @@ onUnmounted(stopHandshakeState)
49
49
 
50
50
  ## 未开通网络权限
51
51
 
52
- 无网络小程序可以在本地能力中使用按小程序隔离的 `app_user_id`:
52
+ 无网络小程序可以在本地能力中使用按小程序隔离的 `app_user_id` 和公开资料:
53
53
 
54
54
  ```ts
55
55
  import hbSDK from '@heybox/hb-sdk'
56
56
 
57
57
  async function getCurrentUser() {
58
58
  const result = await hbSDK.user.getInfo()
59
- return result.userInfo?.app_user_id
59
+ return result.userInfo
60
60
  }
61
61
  ```
62
62
 
63
- `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回未登录状态;已登录时静默返回 `userInfo.app_user_id`。这条路径不能获取授权码或调用 OpenAPI,也不要把 `app_user_id` 发送到外部服务。
63
+ `user.getInfo()` 不展示授权弹窗,也不要求可信用户手势。未登录时返回未登录状态;已登录时隐式授予当前本地用户 scopes(`identity`、`profile`),静默返回 `userInfo.app_user_id`、`profile.nickname` `profile.avatar`。这条路径不能获取授权码或调用 OpenAPI,也不能把身份或资料发送到外部服务。
64
64
 
65
65
  ## 已开通网络权限
66
66
 
@@ -109,7 +109,7 @@ async function loginFromUserAction() {
109
109
  | 小程序类型 | 身份入口 | 结果用途 |
110
110
  | -------------- | ------------------------- | ------------------------------------------------------ |
111
111
  | 已开通网络权限 | `auth.login({ scopes? })` | 获取短期授权码,由开发者服务端换取 OpenAPI token |
112
- | 未开通网络权限 | `user.getInfo()` | 静默读取当前小程序隔离的 `userInfo.app_user_id` |
112
+ | 未开通网络权限 | `user.getInfo()` | 静默读取隔离身份及昵称头像,隐式授予本地用户 scopes |
113
113
 
114
114
  不要混用两条路径。SDK 不向小程序页面提供 token、cookie、黑盒用户 ID 或平台私有凭据。
115
115
 
@@ -155,9 +155,9 @@ async function loginFromUserAction() {
155
155
 
156
156
  小程序页面只把 `code` 发送到自己的服务端。开发者服务端再按后端 OpenAPI 文档,用服务端保存的应用凭据交换 token;页面不得自行交换,也不得持有应用私密凭据。`auth.login()` 不返回 user、profile、`app_user_id` 或 token。
157
157
 
158
- 开发者服务端用 access token 调用 `GET /user_miniprogram/openapi/v1/user` 读取当前用户。响应始终包含 `app_user_id`;token 含 `profile` 时还会返回 `nickname` 和 `avatar`。不要再请求已下线的 `/user/identity` 或 `/user/profile`。
158
+ ## 后端 OpenAPI
159
159
 
160
- 服务端完成换票后,应只把业务需要的 `app_user_id`、`nickname`、`avatar` 等资料或业务 session 返回给页面;页面不接触 access token。
160
+ 开发者服务端按[在线用户身份与登录文档](https://docs.xiaoheihe.cn/hb_sdk/guide/auth)完成授权码交换和用户读取。小程序页面只提交 `auth.login()` 返回的短期 code,不持有服务端密钥、access token 或认证 header;Agent Skill 不分发服务端凭据操作示例。
161
161
 
162
162
  ## 用户操作和错误
163
163
 
@@ -196,20 +196,20 @@ async function revokeAuthorizationFromUserAction() {
196
196
 
197
197
  ## 未开通网络权限
198
198
 
199
- 未开通网络权限的小程序不走授权码流程。需要当前用户在本小程序内的稳定隔离身份时调用:
199
+ 未开通网络权限的小程序不走授权码流程。需要当前用户在本小程序内的稳定隔离身份和公开资料时调用:
200
200
 
201
201
  ```ts
202
202
  import hbSDK from '@heybox/hb-sdk'
203
203
 
204
204
  async function getCurrentUser() {
205
205
  const result = await hbSDK.user.getInfo()
206
- return result.userInfo?.app_user_id
206
+ return result.userInfo
207
207
  }
208
208
  ```
209
209
 
210
- `user.getInfo()` 是静默身份接口,不展示授权弹窗,也不要求可信用户手势。未登录时返回 `isHeyboxAppLoggedIn: false`;已登录时默认建立并返回当前小程序隔离的 `app_user_id`。调用该接口即表示允许平台为当前小程序建立隔离身份;每次成功调用都会广播一次 `user_info_authorization_change`,其中 `identity` `granted`,即使授权状态没有发生变化。撤销授权后再次调用仍会静默建立新的隔离身份。
210
+ `user.getInfo()` 是静默本地用户接口,不展示授权弹窗,也不要求可信用户手势。未登录时返回 `isHeyboxAppLoggedIn: false`;已登录时隐式授予当前本地用户 scopes(`identity`、`profile`),建立并返回当前小程序隔离的 `app_user_id`、`profile.nickname` `profile.avatar`。每次成功调用都会广播一次 `user_info_authorization_change`,其中 `identity` `profile` 均为 `granted`,即使授权状态没有发生变化。撤销授权后再次调用仍会静默建立新的隔离身份并恢复无网络模式的隐式授权。
211
211
 
212
- 这类小程序无法获取授权码,也无法调用 OpenAPI;在未开通网络权限时调用 `auth.login()` 同样返回 `SERVER_API_REQUIRED`。Host 提供的 current-user APIs 与平台代管能力继续按各自权限工作,但页面不能把其中的身份或资料发送到外部服务。
212
+ 这类小程序无法获取授权码,也无法调用 OpenAPI;在未开通网络权限时调用 `auth.login()` 同样返回 `SERVER_API_REQUIRED`。隐式 full-scope 仅适用于 Host 本地用户资料能力,不代表开放网络或服务端凭据;页面不能把其中的身份或资料发送到外部服务。
213
213
 
214
214
  ## 网络请求边界
215
215
 
@@ -17,7 +17,7 @@
17
17
  - 需要授权 UI 时,`auth.login()` 必须来自可信用户手势,否则返回 `USER_GESTURE_REQUIRED`;用户取消或关闭时返回 `AUTHORIZATION_CANCELLED`。已授权时可以静默返回新 code。
18
18
  - `user.getSteamGameList()` 仅供未开通网络权限的小程序通过 Host 读取;已开通网络权限时返回 `SERVER_API_REQUIRED`,且授权码与 OpenAPI 不提供 Steam 游戏库 scope 或资源接口。
19
19
  - 已开通网络权限时,公开的 `user.getInfo()` 返回 `SERVER_API_REQUIRED`;对应身份和资料数据应由开发者服务端通过 OpenAPI 获取。
20
- - 未开通网络权限时,使用 `user.getInfo()` 静默读取 `userInfo.app_user_id`,不能获取 code 或调用 OpenAPI。
20
+ - 未开通网络权限时,`user.getInfo()` 隐式授予 `identity` 与 `profile`,静默返回 `userInfo.app_user_id`、昵称和头像;这条路径仍不能获取 code 或调用 OpenAPI。
21
21
  - `user.revokeAuthorization()` 在两种网络模式下都要求可信用户手势;成功后必须停止使用并清理业务缓存的旧身份、资料和服务端会话。
22
22
  - `on()` 返回取消监听函数,组件卸载或页面销毁时需要调用。
23
23
  - 业务网络请求使用 `network.request()`,不要依赖浏览器原生网络出口。
@@ -0,0 +1,36 @@
1
+ export function extractSection(markdown, heading) {
2
+ const lines = markdown.split('\n');
3
+ const start = lines.findIndex((line) => line.trim() === heading);
4
+ if (start === -1) return '';
5
+ const level = heading.match(/^#+/)?.[0].length ?? 2;
6
+ const out = [lines[start]];
7
+ let fenceChar = '';
8
+ for (let index = start + 1; index < lines.length; index += 1) {
9
+ const line = lines[index];
10
+ const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
11
+
12
+ if (fenceChar) {
13
+ out.push(line);
14
+ if (fenceMatch?.[1]?.startsWith(fenceChar)) fenceChar = '';
15
+ continue;
16
+ }
17
+
18
+ if (fenceMatch) {
19
+ fenceChar = fenceMatch[1][0];
20
+ out.push(line);
21
+ continue;
22
+ }
23
+
24
+ const headingMatch = line.match(/^(#+)\s/);
25
+ if (headingMatch && headingMatch[1].length <= level) break;
26
+ out.push(line);
27
+ }
28
+ return out.join('\n').trimEnd();
29
+ }
30
+
31
+ export function replaceRequiredSection(markdown, heading, replacement) {
32
+ const section = extractSection(markdown, heading);
33
+ if (!section) throw new Error(`sync-references: 未找到待覆盖章节 ${heading}`);
34
+ const start = markdown.indexOf(section);
35
+ return `${markdown.slice(0, start)}${replacement.trimEnd()}${markdown.slice(start + section.length)}`;
36
+ }
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import process from 'node:process';
6
6
  import ts from 'typescript';
7
+ import { extractSection, replaceRequiredSection } from './markdown-sections.mjs';
7
8
  import { createSkillContentHash, createSkillManifest, normalizeSkillManifest } from './skill-metadata.mjs';
8
9
 
9
10
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
@@ -36,38 +37,6 @@ function read(relativePath) {
36
37
  return readFileSync(path.join(repoRoot, relativePath), 'utf8').trimEnd();
37
38
  }
38
39
 
39
- function extractSection(markdown, heading) {
40
- const lines = markdown.split('\n');
41
- const start = lines.findIndex((line) => line.trim() === heading);
42
- if (start === -1) return '';
43
- const level = heading.match(/^#+/)?.[0].length ?? 2;
44
- const out = [lines[start]];
45
- let fenceChar = '';
46
- for (let index = start + 1; index < lines.length; index += 1) {
47
- const line = lines[index];
48
- const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
49
-
50
- if (fenceChar) {
51
- out.push(line);
52
- if (fenceMatch?.[1]?.startsWith(fenceChar)) {
53
- fenceChar = '';
54
- }
55
- continue;
56
- }
57
-
58
- if (fenceMatch) {
59
- fenceChar = fenceMatch[1][0];
60
- out.push(line);
61
- continue;
62
- }
63
-
64
- const headingMatch = line.match(/^(#+)\s/);
65
- if (headingMatch && headingMatch[1].length <= level) break;
66
- out.push(line);
67
- }
68
- return out.join('\n').trimEnd();
69
- }
70
-
71
40
  function fenced(language, value) {
72
41
  const content = value.trimEnd();
73
42
  const longestFence = Math.max(2, ...Array.from(content.matchAll(/`{3,}/g), (match) => match[0].length));
@@ -239,6 +208,15 @@ const readme = read('packages/hb-sdk/README.md');
239
208
  const cliGuide = frontmatterless(read('apps/docs/hb-sdk/guide/cli.md'));
240
209
  const quickStart = frontmatterless(read('apps/docs/hb-sdk/guide/quick-start.md'));
241
210
  const authGuide = frontmatterless(read('apps/docs/hb-sdk/guide/auth.md'));
211
+ const authGuideForSkill = replaceRequiredSection(
212
+ authGuide,
213
+ '## 后端 OpenAPI',
214
+ [
215
+ '## 后端 OpenAPI',
216
+ '',
217
+ '开发者服务端按[在线用户身份与登录文档](https://docs.xiaoheihe.cn/hb_sdk/guide/auth)完成授权码交换和用户读取。小程序页面只提交 `auth.login()` 返回的短期 code,不持有服务端密钥、access token 或认证 header;Agent Skill 不分发服务端凭据操作示例。',
218
+ ].join('\n'),
219
+ );
242
220
  const lifecycleGuide = frontmatterless(read('apps/docs/hb-sdk/guide/lifecycle.md'));
243
221
  const errorGuide = frontmatterless(read('apps/docs/hb-sdk/guide/error-handling.md'));
244
222
  const loginGate = frontmatterless(read('apps/docs/hb-sdk/recipes/login-gate.md'));
@@ -535,7 +513,7 @@ ${rewriteBundledRecipeLinks(quickStart)}
535
513
 
536
514
  ## User and login
537
515
 
538
- ${rewriteBundledRecipeLinks(authGuide)}
516
+ ${rewriteBundledRecipeLinks(authGuideForSkill)}
539
517
 
540
518
  ## Lifecycle events
541
519
 
package/skill/skill.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "hb-sdk",
3
- "skillVersion": "0.7.2+skill.4dbf3cd47129",
3
+ "skillVersion": "0.7.3+skill.8bd4775c12e3",
4
4
  "sdk": {
5
5
  "package": "@heybox/hb-sdk",
6
- "version": "0.7.2",
7
- "compatibility": "0.7.2"
6
+ "version": "0.7.3",
7
+ "compatibility": "0.7.3"
8
8
  },
9
9
  "source": "https://open.xiaoheihe.cn/agent-skills/hb-sdk",
10
- "integrity": "sha256-4dbf3cd471293ade5b4b2cfe0f156d1365adffee4e7da36c6a30cb7dbb37319a"
10
+ "integrity": "sha256-8bd4775c12e3fa0efa4a8b14cb4ed4a730dbc3f325b1ebcf479e7a0026fcae30"
11
11
  }
package/types/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export type { MiniProgramEventHandler, MiniProgramEventName, MiniProgramEventPay
5
5
  export type { LoginOptions, LoginPayload, LoginResult, LoginScope, MiniProgramAuthModule } from './modules/auth';
6
6
  export type { DeleteCurrentUserLeaderboardEntryPayload, DeleteCurrentUserLeaderboardEntryResult, GetCurrentUserLeaderboardEntryPayload, GetCurrentUserLeaderboardEntryResult, GetLeaderboardInfoPayload, GetLeaderboardInfoResult, GetLeaderboardListPayload, GetLeaderboardListResult, LeaderboardEntry, LeaderboardOrder, MiniProgramCloudLeaderboardModule, MiniProgramCloudModule, SubmitLeaderboardEntryPayload, SubmitLeaderboardEntryResult, } from './modules/cloud';
7
7
  export type { AuthorizedUserInfo, GetUserInfoPayload, GetUserInfoResult, RevokeAuthorizationPayload, RevokeAuthorizationResult, GetSteamGameListOptions, GetSteamGameListPayload, GetSteamGameListResult, MiniProgramUserInfoResult, MiniProgramUserModule, UserInfoAuthorization, UserInfoAuthorizationStatus, SteamGameListData, SteamGameListItem, SteamGamePrice, SteamGameListSort, } from './modules/user';
8
+ export { USER_INFO_AUTHORIZATION_SCOPES } from './modules/user';
9
+ export type { UserInfoAuthorizationScope } from './modules/user';
8
10
  export type { MiniProgramScreenshotOptions, MiniProgramScreenshotRect, MiniProgramShareChannel, MiniProgramShareModule, MiniProgramSharePostOptions, MiniProgramShowShareMenuOptions, ScreenshotPayload, ScreenshotResult, ShowShareMenuPayload, ShowShareMenuResult, } from './modules/share';
9
11
  export type { GetWindowInfoPayload, GetWindowInfoResult, MiniProgramNavigationBarForegroundStyle, MiniProgramSafeArea, MiniProgramSetNavigationBarStyleOptions, MiniProgramViewportModule, MiniProgramWindowInfoResult, SetNavigationBarStylePayload, SetNavigationBarStyleResult, } from './modules/viewport';
10
12
  export type { GetStoragePayload, GetStorageResult, MiniProgramStorageModule, SetStoragePayload } from './modules/storage';
@@ -15,7 +15,7 @@ export type GetUserInfoResult = MiniProgramUserInfoResult;
15
15
  * @returns 当前用户的登录态与公开基础资料。
16
16
  *
17
17
  * 未开通网络权限且当前黑盒 APP 用户已登录时,该能力会静默建立或读取按小程序隔离的
18
- * `app_user_id`,不展示授权 UI;仅在 profile 授权后返回昵称与头像。未登录时返回
18
+ * `app_user_id`,并隐式授予 `identity` 与 `profile` 后返回昵称与头像,不展示授权 UI。未登录时返回
19
19
  * `{ isHeyboxAppLoggedIn: false, authorization: null, userInfo: null }`。
20
20
  *
21
21
  * @throws {HbMiniProgramSDKError} 当 SDK 调用失败时抛出。
@@ -1,16 +1,18 @@
1
1
  /** 用户资料授权状态。 */
2
2
  export type UserInfoAuthorizationStatus = 'not_required' | 'not_requested' | 'granted' | 'denied';
3
- /** 当前小程序对用户身份与公开资料的授权状态。 */
4
- export interface UserInfoAuthorization {
5
- identity: UserInfoAuthorizationStatus;
6
- profile: UserInfoAuthorizationStatus;
3
+ /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
4
+ export declare const USER_INFO_AUTHORIZATION_SCOPES: readonly ["identity", "profile"];
5
+ export type UserInfoAuthorizationScope = (typeof USER_INFO_AUTHORIZATION_SCOPES)[number];
6
+ type CanonicalUserInfoAuthorization = Record<UserInfoAuthorizationScope, UserInfoAuthorizationStatus>;
7
+ /** 当前小程序对 canonical 用户信息 scope 的授权状态。 */
8
+ export interface UserInfoAuthorization extends CanonicalUserInfoAuthorization {
7
9
  }
8
10
  /**
9
11
  * 已获准向当前小程序披露的用户资料。
10
12
  *
11
13
  * @remarks
12
- * 未开通网络权限且当前黑盒 APP 用户已登录时,Runtime 会静默建立或读取隔离身份,
13
- * `user.getInfo()` 随即返回该对象。撤销授权后旧身份失效,调用方应停止使用并清理
14
+ * 未开通网络权限且当前黑盒 APP 用户已登录时,Runtime 会隐式授予 `identity` 与
15
+ * `profile`,静默建立或读取隔离身份,并由 `user.getInfo()` 返回该对象。撤销授权后旧身份失效,调用方应停止使用并清理
14
16
  * 本地缓存;再次调用 `user.getInfo()` 会静默建立新的隔离身份。
15
17
  */
16
18
  export interface AuthorizedUserInfo {
@@ -24,7 +26,7 @@ export interface AuthorizedUserInfo {
24
26
  * 不应解析格式或依赖固定长度。
25
27
  */
26
28
  app_user_id: string;
27
- /** 仅在 `profile` 授权后返回昵称与头像。 */
29
+ /** `profile` 已授权时返回昵称与头像;当前 Heybox Runtime 在无网络模式下隐式授予该 scope。 */
28
30
  profile: {
29
31
  nickname: string;
30
32
  avatar: string;
@@ -35,7 +37,8 @@ export interface AuthorizedUserInfo {
35
37
  *
36
38
  * @remarks
37
39
  * 未登录时 `isHeyboxAppLoggedIn` 为 `false`,授权状态和用户资料均为 `null`。
38
- * 当前 Heybox Runtime 在无网络模式且已登录时会静默建立身份并返回 `userInfo`;
40
+ * 当前 Heybox Runtime 在无网络模式且已登录时会隐式授予 `identity` 与 `profile`,
41
+ * 静默建立身份并返回 `userInfo`;
39
42
  * Host 在已登录但身份暂不可用时仍可返回 `null`,调用方必须进行空值判断。
40
43
  */
41
44
  export type MiniProgramUserInfoResult = {
@@ -47,3 +50,4 @@ export type MiniProgramUserInfoResult = {
47
50
  authorization: UserInfoAuthorization;
48
51
  userInfo: AuthorizedUserInfo | null;
49
52
  };
53
+ export {};
@@ -10,6 +10,8 @@ export type { MiniProgramDeviceMethod, MiniProgramAuthMethod, MiniProgramBridgeM
10
10
  export type { LoginOptions, LoginPayload, LoginResult, LoginScope } from './modules/auth';
11
11
  export type { DeleteCurrentUserLeaderboardEntryPayload, DeleteCurrentUserLeaderboardEntryResult, GetCurrentUserLeaderboardEntryPayload, GetCurrentUserLeaderboardEntryResult, GetLeaderboardInfoPayload, GetLeaderboardInfoResult, GetLeaderboardListPayload, GetLeaderboardListResult, LeaderboardEntry, LeaderboardOrder, SubmitLeaderboardEntryPayload, SubmitLeaderboardEntryResult, } from './modules/cloud';
12
12
  export type { AuthorizedUserInfo, GetUserInfoPayload, GetUserInfoResult, RevokeAuthorizationPayload, RevokeAuthorizationResult, GetSteamGameListOptions, GetSteamGameListPayload, GetSteamGameListResult, MiniProgramUserInfoResult, UserInfoAuthorization, UserInfoAuthorizationStatus, SteamGameListData, SteamGameListItem, SteamGamePrice, SteamGameListSort, } from './modules/user';
13
+ export { USER_INFO_AUTHORIZATION_SCOPES } from './modules/user';
14
+ export type { UserInfoAuthorizationScope } from './modules/user';
13
15
  export type { ScreenshotPayload, ScreenshotResult } from './modules/share/screenshot';
14
16
  export type { ShowShareMenuPayload, ShowShareMenuResult } from './modules/share/show-share-menu';
15
17
  export type { MiniProgramScreenshotOptions, MiniProgramScreenshotRect, MiniProgramShareChannel, MiniProgramSharePostOptions, MiniProgramShowShareMenuOptions, } from './modules/share';