@heybox/hb-sdk 0.7.5-alpha.0 → 0.8.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +99 -352
  2. package/README.md +103 -26
  3. package/THIRD_PARTY_NOTICES.md +1755 -0
  4. package/dist/cli-chunks/{build-V1YBdpzY.cjs → build-aDJbiFqF.cjs} +9 -5
  5. package/dist/cli-chunks/{context-Ba1Je-wT.cjs → context-Dp36pZ9a.cjs} +39 -81
  6. package/dist/cli-chunks/{create-CKGjqo9E.cjs → create-P3g0ricz.cjs} +2 -2
  7. package/dist/cli-chunks/{dev-XopYKLYZ.cjs → dev-CisJkXuQ.cjs} +396 -576
  8. package/dist/cli-chunks/doctor-B-LF5-uj.cjs +65 -0
  9. package/dist/cli-chunks/{index-C9mpajVG.cjs → index-BDaeBI_B.cjs} +50 -30
  10. package/dist/cli-chunks/{index-DKWfX6Ut.cjs → index-CZGkk7fQ.cjs} +2 -2
  11. package/dist/cli-chunks/{index.esm-SXAQ3WVR.cjs → index.esm-NNLG29Tt.cjs} +8 -7
  12. package/dist/cli-chunks/{login-BVWicWqe.cjs → login-DTY5GolC.cjs} +2 -2
  13. package/dist/cli-chunks/{project-vite-CBb38HJ3.cjs → project-vite-DlCjHlu_.cjs} +1 -1
  14. package/dist/cli-chunks/{remote-BG1u0NKT.cjs → remote-BBMr7j8W.cjs} +61 -27
  15. package/dist/cli-chunks/{runtime-gate-CtV7rWyX.cjs → runtime-gate-BppCl1r3.cjs} +30 -3
  16. package/dist/cli-chunks/{runtime-permission-env-D-8_jPG3.cjs → runtime-permission-env-CqsTHeas.cjs} +364 -13
  17. package/dist/cli-chunks/{session-CJS_SEp9.cjs → session-CnGeZCRZ.cjs} +1 -1
  18. package/dist/cli-chunks/skill-B0yAnPOJ.cjs +83 -0
  19. package/dist/cli-chunks/version-DN5jrixS.cjs +8 -0
  20. package/dist/cli.cjs +1 -1
  21. package/dist/devtools/browser-dev-host/assets/browser-dev-host-BhZGUyYw.js +97 -0
  22. package/dist/devtools/browser-dev-host/assets/heybox-logo-CogNENsk.svg +6 -0
  23. package/dist/devtools/browser-dev-host/assets/index-DJFB5ySU.css +1 -0
  24. package/dist/devtools/browser-dev-host/assets/index-Dh9H1JOm.js +567 -0
  25. package/dist/devtools/browser-dev-host/assets/workbench-state-wHgWRb7I.js +5 -0
  26. package/dist/devtools/browser-dev-host/index.html +6 -435
  27. package/dist/index.cjs.js +1051 -91
  28. package/dist/index.esm.js +1051 -92
  29. package/dist/miniapp-publish.cjs.js +13 -13
  30. package/dist/miniapp-publish.esm.js +13 -13
  31. package/dist/protocol.cjs.js +381 -37
  32. package/dist/protocol.esm.js +355 -38
  33. package/dist/templates/{vue3-vite-ts → vanilla-vite-js}/.gitignore.ejs +0 -1
  34. package/dist/templates/vanilla-vite-js/README.md.ejs +14 -0
  35. package/dist/templates/vanilla-vite-js/index.html.ejs +20 -0
  36. package/dist/templates/vanilla-vite-js/package.json.ejs +22 -0
  37. package/dist/templates/vanilla-vite-js/src/assets/heybox-logo.svg +8 -0
  38. package/dist/templates/vanilla-vite-js/src/main.js +39 -0
  39. package/dist/templates/vanilla-vite-js/src/styles.css +155 -0
  40. package/dist/templates/{vue3-vite-ts/vite.config.ts → vanilla-vite-js/vite.config.js} +1 -2
  41. package/dist/vite.cjs.js +256 -10
  42. package/dist/vite.esm.js +256 -11
  43. package/package.json +37 -11
  44. package/skill/SKILL.md +22 -20
  45. package/skill/references/api-protocol.md +112 -6
  46. package/skill/references/api-root.md +194 -30
  47. package/skill/references/cli.md +41 -24
  48. package/skill/references/examples.md +31 -2
  49. package/skill/references/llms-index.md +1 -1
  50. package/skill/references/recipes.md +139 -36
  51. package/skill/references/safety-boundaries.md +15 -6
  52. package/skill/skill.json +10 -5
  53. package/types/core/client.d.ts +17 -1
  54. package/types/core/errors.d.ts +5 -5
  55. package/types/core/sdk.d.ts +8 -5
  56. package/types/core/singleton.d.ts +59 -6
  57. package/types/index.d.ts +4 -2
  58. package/types/miniapp-manifest/index.d.ts +1 -0
  59. package/types/miniapp-manifest/node.d.ts +3 -0
  60. package/types/miniapp-manifest/permissions.d.ts +37 -0
  61. package/types/miniapp-manifest/schema.d.ts +10 -0
  62. package/types/miniapp-publish/index.d.ts +8 -8
  63. package/types/modules/auth/index.d.ts +15 -1
  64. package/types/modules/cloud/index.d.ts +75 -5
  65. package/types/modules/device/index.d.ts +31 -3
  66. package/types/modules/files/index.d.ts +5 -0
  67. package/types/modules/files/registry.d.ts +35 -0
  68. package/types/modules/files/types.d.ts +159 -0
  69. package/types/modules/navigation/index.d.ts +46 -4
  70. package/types/modules/network/index.d.ts +72 -14
  71. package/types/modules/share/copy-link.d.ts +3 -3
  72. package/types/modules/share/index.d.ts +61 -5
  73. package/types/modules/share/screenshot.d.ts +3 -3
  74. package/types/modules/share/show-share-menu.d.ts +4 -4
  75. package/types/modules/share/types.d.ts +2 -4
  76. package/types/modules/storage/index.d.ts +38 -10
  77. package/types/modules/ui/index.d.ts +46 -4
  78. package/types/modules/user/get-info.d.ts +1 -1
  79. package/types/modules/user/index.d.ts +46 -4
  80. package/types/modules/user/steam-game-list.d.ts +2 -2
  81. package/types/modules/viewport/index.d.ts +36 -8
  82. package/types/protocol/capabilities.d.ts +2 -2
  83. package/types/protocol/constants.d.ts +1 -1
  84. package/types/protocol/guards.d.ts +1 -1
  85. package/types/protocol/types.d.ts +1 -1
  86. package/types/protocol.d.ts +4 -3
  87. package/types/skill-metadata.d.ts +0 -4
  88. package/types/vite/index.d.ts +15 -7
  89. package/dist/cli-chunks/doctor-BHbrYQqT.cjs +0 -204
  90. package/dist/devtools/browser-dev-host/main.js +0 -12158
  91. package/dist/templates/vue3-vite-ts/README.md.ejs +0 -45
  92. package/dist/templates/vue3-vite-ts/index.html.ejs +0 -12
  93. package/dist/templates/vue3-vite-ts/package.json.ejs +0 -33
  94. package/dist/templates/vue3-vite-ts/src/App.vue +0 -78
  95. package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +0 -148
  96. package/dist/templates/vue3-vite-ts/src/auth-handoff.ts +0 -46
  97. package/dist/templates/vue3-vite-ts/src/main.ts +0 -5
  98. package/dist/templates/vue3-vite-ts/src/styles.css +0 -60
  99. package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +0 -1
  100. package/dist/templates/vue3-vite-ts/tsconfig.app.json +0 -17
  101. package/dist/templates/vue3-vite-ts/tsconfig.json +0 -11
  102. package/dist/templates/vue3-vite-ts/tsconfig.node.json +0 -11
  103. package/dist/templates/vue3-vite-ts/vitest.config.ts +0 -10
  104. package/skill/scripts/check-references.mjs +0 -14
  105. package/skill/scripts/markdown-sections.mjs +0 -36
  106. package/skill/scripts/package-skill.mjs +0 -60
  107. package/skill/scripts/package-skill.sh +0 -6
  108. package/skill/scripts/skill-metadata.mjs +0 -77
  109. package/skill/scripts/sync-agent-skills-payload.mjs +0 -359
  110. package/skill/scripts/sync-references.mjs +0 -792
  111. package/skill/scripts/validate-skill.mjs +0 -263
@@ -0,0 +1,155 @@
1
+ :root {
2
+ --page-background: #f7f8f9;
3
+ --text-primary: #14191e;
4
+ --text-secondary: #64696e;
5
+ --button-background: #14191e;
6
+ --button-foreground: #ffffff;
7
+ --button-hover: #393d40;
8
+ --button-pressed: #000000;
9
+ --button-disabled: #c8cdd2;
10
+ --focus-ring: #009015;
11
+ --error: #c92228;
12
+ color-scheme: light dark;
13
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
14
+ color: var(--text-primary);
15
+ background: var(--page-background);
16
+ }
17
+
18
+ * {
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ html,
23
+ body {
24
+ margin: 0;
25
+ min-width: 0;
26
+ min-height: 100%;
27
+ background: var(--page-background);
28
+ }
29
+
30
+ body {
31
+ min-height: 100vh;
32
+ min-height: 100dvh;
33
+ }
34
+
35
+ .page {
36
+ display: grid;
37
+ min-height: 100vh;
38
+ min-height: 100dvh;
39
+ place-items: center;
40
+ padding: max(32px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right)) max(32px, env(safe-area-inset-bottom))
41
+ max(24px, env(safe-area-inset-left));
42
+ }
43
+
44
+ .content {
45
+ width: min(100%, 360px);
46
+ text-align: center;
47
+ }
48
+
49
+ .logo {
50
+ display: block;
51
+ width: 36px;
52
+ height: 36px;
53
+ margin: 0 auto 32px;
54
+ object-fit: contain;
55
+ }
56
+
57
+ h1 {
58
+ margin: 0;
59
+ color: var(--text-primary);
60
+ font-size: 32px;
61
+ line-height: 1.25;
62
+ letter-spacing: 0;
63
+ }
64
+
65
+ .welcome {
66
+ margin: 12px 0 32px;
67
+ color: var(--text-secondary);
68
+ font-size: 16px;
69
+ line-height: 1.5;
70
+ }
71
+
72
+ button {
73
+ width: 160px;
74
+ min-height: 48px;
75
+ border: 0;
76
+ border-radius: 6px;
77
+ color: var(--button-foreground);
78
+ background: var(--button-background);
79
+ font: inherit;
80
+ font-weight: 600;
81
+ cursor: pointer;
82
+ transition:
83
+ background-color 160ms ease,
84
+ transform 160ms ease;
85
+ }
86
+
87
+ button:active:not(:disabled) {
88
+ background: var(--button-pressed);
89
+ transform: scale(0.98);
90
+ }
91
+
92
+ button:focus-visible {
93
+ outline: 3px solid var(--focus-ring);
94
+ outline-offset: 3px;
95
+ }
96
+
97
+ button:disabled {
98
+ background: var(--button-disabled);
99
+ cursor: wait;
100
+ }
101
+
102
+ .error {
103
+ min-height: 24px;
104
+ margin: 12px 0 0;
105
+ color: var(--error);
106
+ font-size: 14px;
107
+ line-height: 24px;
108
+ }
109
+
110
+ @media (hover: hover) {
111
+ button:hover:not(:disabled) {
112
+ background: var(--button-hover);
113
+ }
114
+ }
115
+
116
+ @media (prefers-color-scheme: dark) {
117
+ :root {
118
+ --page-background: #14191e;
119
+ --text-primary: #f7f8f9;
120
+ --text-secondary: #91959a;
121
+ --button-background: #f7f8f9;
122
+ --button-foreground: #14191e;
123
+ --button-hover: #ffffff;
124
+ --button-pressed: #c4c8cc;
125
+ --button-disabled: #696e72;
126
+ --focus-ring: #32b846;
127
+ --error: #fa3c4b;
128
+ }
129
+
130
+ .logo {
131
+ filter: invert(1);
132
+ }
133
+ }
134
+
135
+ @media (max-height: 420px) and (orientation: landscape) {
136
+ .page {
137
+ place-items: start center;
138
+ padding-top: max(20px, env(safe-area-inset-top));
139
+ padding-bottom: max(20px, env(safe-area-inset-bottom));
140
+ }
141
+
142
+ .logo {
143
+ margin-bottom: 16px;
144
+ }
145
+
146
+ .welcome {
147
+ margin-bottom: 20px;
148
+ }
149
+ }
150
+
151
+ @media (prefers-reduced-motion: reduce) {
152
+ button {
153
+ transition: none;
154
+ }
155
+ }
@@ -1,8 +1,7 @@
1
- import vue from '@vitejs/plugin-vue';
2
1
  import { miniappManifest } from '@heybox/hb-sdk/vite';
3
2
  import { defineConfig } from 'vite';
4
3
 
5
4
  export default defineConfig({
6
5
  base: './',
7
- plugins: [vue(), miniappManifest()],
6
+ plugins: [miniappManifest({ platforms: ['android', 'ios', 'ohos'] })],
8
7
  });
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.5-alpha.0';
11
+ : '0.8.0-alpha.10';
12
12
 
13
13
  var re = {exports: {}};
14
14
 
@@ -2795,6 +2795,198 @@ function requireSemver () {
2795
2795
 
2796
2796
  var semverExports = requireSemver();
2797
2797
 
2798
+ const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
2799
+ const MINI_PROGRAM_MESSAGE_VERSION = 2;
2800
+ const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
2801
+
2802
+ const MINI_PROGRAM_PERMISSION_KEYS = [
2803
+ 'userInfo',
2804
+ 'steamLibrary',
2805
+ 'share',
2806
+ 'storage',
2807
+ 'filesystem',
2808
+ 'clipboard',
2809
+ 'leaderboard',
2810
+ 'network',
2811
+ ];
2812
+ const MINI_PROGRAM_PERMISSION_CATALOG = [
2813
+ {
2814
+ key: 'userInfo',
2815
+ name: '用户信息',
2816
+ description: '登录小程序并读取当前用户的授权信息。',
2817
+ access: 'declaration',
2818
+ risk: 'medium',
2819
+ config: {},
2820
+ methods: ['auth.login', 'user.getInfo'],
2821
+ conditions: ['继续执行黑盒登录、用户授权和可信手势规则。'],
2822
+ },
2823
+ {
2824
+ key: 'steamLibrary',
2825
+ name: 'Steam 游戏库',
2826
+ description: '读取当前用户授权的 Steam 游戏库。',
2827
+ access: 'declaration',
2828
+ risk: 'high',
2829
+ config: {},
2830
+ methods: ['user.getSteamGameList'],
2831
+ conditions: ['继续执行账号绑定和数据可用性规则。'],
2832
+ },
2833
+ {
2834
+ key: 'share',
2835
+ name: '分享',
2836
+ description: '使用小程序分享、分享菜单和截图能力。',
2837
+ access: 'declaration',
2838
+ risk: 'medium',
2839
+ config: {},
2840
+ methods: ['share.copyLink', 'share.showShareMenu', 'share.screenshot'],
2841
+ conditions: ['继续执行分享参数校验和 Host 支持检查。'],
2842
+ },
2843
+ {
2844
+ key: 'storage',
2845
+ name: '键值存储',
2846
+ description: '读写按小程序隔离的简单键值数据。',
2847
+ access: 'declaration',
2848
+ risk: 'medium',
2849
+ config: {},
2850
+ methods: ['storage.getStorage', 'storage.setStorage'],
2851
+ conditions: ['仅用于简单键值存储,不包含文件系统。'],
2852
+ },
2853
+ {
2854
+ key: 'filesystem',
2855
+ name: '文件系统',
2856
+ description: '访问小程序沙盒文件和用户选择的外部文件。',
2857
+ access: 'declaration',
2858
+ risk: 'high',
2859
+ config: {},
2860
+ methods: [
2861
+ 'network.download',
2862
+ 'files.pickFiles',
2863
+ 'files.pickDirectory',
2864
+ 'files.saveFile',
2865
+ 'file.create',
2866
+ 'file.remove',
2867
+ 'file.exists',
2868
+ 'file.readText',
2869
+ 'file.writeText',
2870
+ 'file.readBytes',
2871
+ 'file.writeBytes',
2872
+ 'file.stat',
2873
+ 'directory.create',
2874
+ 'directory.remove',
2875
+ 'directory.exists',
2876
+ 'directory.list',
2877
+ ],
2878
+ conditions: ['外部文件继续要求有效的用户选择、会话句柄和匹配的读写模式。'],
2879
+ },
2880
+ {
2881
+ key: 'clipboard',
2882
+ name: '剪贴板',
2883
+ description: '向系统剪贴板写入文本。',
2884
+ access: 'declaration',
2885
+ risk: 'medium',
2886
+ config: {},
2887
+ methods: ['device.setClipboard'],
2888
+ conditions: ['继续执行文本长度和 Host 支持限制。'],
2889
+ },
2890
+ {
2891
+ key: 'leaderboard',
2892
+ name: '排行榜',
2893
+ description: '读写小程序云排行榜。',
2894
+ access: 'declaration',
2895
+ risk: 'medium',
2896
+ config: {},
2897
+ methods: [
2898
+ 'cloud.leaderboard.submit',
2899
+ 'cloud.leaderboard.getList',
2900
+ 'cloud.leaderboard.getCurrentUserEntry',
2901
+ 'cloud.leaderboard.deleteCurrentUserEntry',
2902
+ 'cloud.leaderboard.getInfo',
2903
+ ],
2904
+ conditions: ['排行榜必须已创建,用户和资源规则保持不变。'],
2905
+ },
2906
+ {
2907
+ key: 'network',
2908
+ name: '网络',
2909
+ description: '通过 network 模块请求或下载外部资源。',
2910
+ access: 'platform-approval',
2911
+ risk: 'high',
2912
+ config: {
2913
+ useOfficialDomain: {
2914
+ type: 'boolean',
2915
+ required: false,
2916
+ default: false,
2917
+ description: '是否申请访问小黑盒官方域名。',
2918
+ },
2919
+ },
2920
+ methods: ['network.request', 'network.download'],
2921
+ conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
2922
+ },
2923
+ ];
2924
+ new Set(MINI_PROGRAM_PERMISSION_KEYS);
2925
+
2926
+ new Set(MINI_PROGRAM_PERMISSION_KEYS);
2927
+
2928
+ const MINIAPP_PERMISSION_KEYS = MINI_PROGRAM_PERMISSION_KEYS;
2929
+ function parseMiniappPermissions(value, options) {
2930
+ const sourceLabel = options.sourceLabel ?? 'package.json#heybox.permissions';
2931
+ if (!options.present) {
2932
+ if (requiresExplicitPermissions(options.sdkVersion)) {
2933
+ throw new Error(`${sourceLabel} 在 @heybox/hb-sdk ${options.sdkVersion} 中必须声明;无权限需求时请配置空对象 {}`);
2934
+ }
2935
+ return { declared: false };
2936
+ }
2937
+ if (!isRecord$1(value)) {
2938
+ throw new Error(`${sourceLabel} 必须是 JSON 对象`);
2939
+ }
2940
+ const knownKeys = new Set(MINIAPP_PERMISSION_KEYS);
2941
+ for (const key of Object.keys(value)) {
2942
+ if (!knownKeys.has(key))
2943
+ throw new Error(`${sourceLabel} 包含未知权限:${key}`);
2944
+ }
2945
+ const permissions = {};
2946
+ for (const key of MINIAPP_PERMISSION_KEYS) {
2947
+ if (!Object.prototype.hasOwnProperty.call(value, key))
2948
+ continue;
2949
+ const declaration = value[key];
2950
+ const itemLabel = `${sourceLabel}.${key}`;
2951
+ if (!isRecord$1(declaration))
2952
+ throw new Error(`${itemLabel} 必须是 JSON 对象`);
2953
+ const definition = MINI_PROGRAM_PERMISSION_CATALOG.find((item) => item.key === key);
2954
+ if (!definition)
2955
+ throw new Error(`权限目录缺少定义:${key}`);
2956
+ const allowedFields = new Set(['enabled', ...Object.keys(definition.config)]);
2957
+ for (const field of Object.keys(declaration)) {
2958
+ if (!allowedFields.has(field))
2959
+ throw new Error(`${itemLabel} 包含未知字段:${field}`);
2960
+ }
2961
+ if (typeof declaration.enabled !== 'boolean')
2962
+ throw new Error(`${itemLabel}.enabled 必须是 boolean`);
2963
+ let useOfficialDomain = false;
2964
+ if (key === 'network') {
2965
+ if (declaration.useOfficialDomain !== undefined && typeof declaration.useOfficialDomain !== 'boolean') {
2966
+ throw new Error(`${itemLabel}.useOfficialDomain 必须是 boolean`);
2967
+ }
2968
+ useOfficialDomain = declaration.useOfficialDomain === true;
2969
+ }
2970
+ if (!declaration.enabled)
2971
+ continue;
2972
+ permissions[key] = key === 'network' ? { enabled: true, useOfficialDomain } : { enabled: true };
2973
+ }
2974
+ return { declared: true, permissions: permissions };
2975
+ }
2976
+ function requiresExplicitPermissions(sdkVersion) {
2977
+ const parsed = semverExports.parse(sdkVersion);
2978
+ if (!parsed)
2979
+ throw new Error(`sdkVersion 必须是合法 SemVer:${sdkVersion}`);
2980
+ return parsed.major > 0 || parsed.minor >= 9;
2981
+ }
2982
+ function getMissingPermissionsWarning(sourceLabel = 'package.json#heybox.permissions') {
2983
+ return `${sourceLabel} 尚未声明。当前按 0.8 兼容行为构建;0.9.0 起将拒绝构建,请尽快补充权限声明(无权限需求时配置 {})。`;
2984
+ }
2985
+ function isRecord$1(value) {
2986
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
2987
+ }
2988
+
2989
+ const MINIAPP_PLATFORM_VALUES = ['android', 'ios', 'ohos', 'windows', 'macos', 'linux'];
2798
2990
  function validateMiniappPackageVersionForBuild(version) {
2799
2991
  return validateMiniappManifestVersion(version, 'package.json.version');
2800
2992
  }
@@ -2806,7 +2998,31 @@ function validateMiniappManifestVersion(version, sourceLabel = 'manifest.version
2806
2998
  return String(version).trim();
2807
2999
  }
2808
3000
  function renderMiniappManifest(manifest) {
2809
- return `${JSON.stringify({ version: manifest.version, sdkVersion: manifest.sdkVersion }, null, 2)}\n`;
3001
+ const platforms = validateMiniappPlatforms(manifest.platforms, 'manifest.platforms');
3002
+ const output = {
3003
+ version: manifest.version,
3004
+ sdkVersion: manifest.sdkVersion,
3005
+ platforms,
3006
+ ...(manifest.permissions === undefined ? {} : { permissions: manifest.permissions }),
3007
+ };
3008
+ return `${JSON.stringify(output, null, 2)}\n`;
3009
+ }
3010
+ function validateMiniappPlatforms(platforms, sourceLabel = 'platforms') {
3011
+ if (!Array.isArray(platforms) || platforms.length === 0) {
3012
+ throw new Error(`${sourceLabel} 必须是非空平台数组`);
3013
+ }
3014
+ const allowedPlatforms = new Set(MINIAPP_PLATFORM_VALUES);
3015
+ const seen = new Set();
3016
+ for (const platform of platforms) {
3017
+ if (typeof platform !== 'string' || !allowedPlatforms.has(platform)) {
3018
+ throw new Error(`${sourceLabel} 包含不支持的平台:${String(platform)}`);
3019
+ }
3020
+ if (seen.has(platform)) {
3021
+ throw new Error(`${sourceLabel} 包含重复平台:${platform}`);
3022
+ }
3023
+ seen.add(platform);
3024
+ }
3025
+ return Object.freeze(MINIAPP_PLATFORM_VALUES.filter((platform) => seen.has(platform)));
2810
3026
  }
2811
3027
  function getMiniappManifestVersionError(version) {
2812
3028
  if (typeof version !== 'string' || version.trim() === '') {
@@ -2844,6 +3060,21 @@ function findNearestPackageJsonPath(startDir) {
2844
3060
  }
2845
3061
  }
2846
3062
  function readMiniappVersionFromPackageJson(root) {
3063
+ return readMiniappPackageJson(root, true).version;
3064
+ }
3065
+ function readMiniappPermissionsFromPackageJson(root, sdkVersion) {
3066
+ const { packageJson } = readMiniappPackageJson(root, false);
3067
+ const heybox = packageJson.heybox;
3068
+ if (heybox !== undefined && !isRecord(heybox)) {
3069
+ throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
3070
+ }
3071
+ const present = isRecord(heybox) && Object.prototype.hasOwnProperty.call(heybox, 'permissions');
3072
+ return parseMiniappPermissions(isRecord(heybox) ? heybox.permissions : undefined, {
3073
+ present,
3074
+ sdkVersion,
3075
+ });
3076
+ }
3077
+ function readMiniappPackageJson(root, requireVersion) {
2847
3078
  const packageJsonPath = findNearestPackageJsonPath(root);
2848
3079
  let content;
2849
3080
  try {
@@ -2859,10 +3090,13 @@ function readMiniappVersionFromPackageJson(root) {
2859
3090
  catch (error) {
2860
3091
  throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
2861
3092
  }
2862
- if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
3093
+ if (requireVersion && (typeof packageJson.version !== 'string' || packageJson.version.trim() === '')) {
2863
3094
  throw new Error('@heybox/hb-sdk 提示:package.json.version 必须是非空字符串');
2864
3095
  }
2865
- return packageJson.version.trim();
3096
+ return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
3097
+ }
3098
+ function isRecord(value) {
3099
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
2866
3100
  }
2867
3101
  function formatReason(error) {
2868
3102
  if (error instanceof Error && error.message) {
@@ -11301,10 +11535,6 @@ function parse(html, options) {
11301
11535
  return Parser.parse(html, options);
11302
11536
  }
11303
11537
 
11304
- const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
11305
- const MINI_PROGRAM_MESSAGE_VERSION = 2;
11306
- const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
11307
-
11308
11538
  const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
11309
11539
  const RUNTIME_GATE_MARKER = 'data-heybox-runtime-gate';
11310
11540
  const RUNTIME_GATE_STYLE_MARKER = 'data-heybox-runtime-gate-style';
@@ -11629,7 +11859,8 @@ function shouldSkipMiniappPlatformCspFromEnv(env = process.env) {
11629
11859
 
11630
11860
  const sdkVersionPlaceholder = ['__HB_SDK', 'VERSION__'].join('_');
11631
11861
  const sdkVersionBuildConstant = ['__HB_SDK_BUILD', 'VERSION__'].join('_');
11632
- function miniappManifest() {
11862
+ function miniappManifest(options) {
11863
+ const platforms = validateMiniappPlatforms(options?.platforms, 'miniappManifest().platforms');
11633
11864
  const skipPlatformCsp = shouldSkipMiniappPlatformCspFromEnv();
11634
11865
  let root = process.cwd();
11635
11866
  let outDir = 'dist';
@@ -11649,6 +11880,12 @@ function miniappManifest() {
11649
11880
  };
11650
11881
  },
11651
11882
  configResolved(resolved) {
11883
+ if (resolved.plugins) {
11884
+ const manifestPluginCount = resolved.plugins.filter((plugin) => plugin.name === 'heybox-miniapp-manifest').length;
11885
+ if (manifestPluginCount !== 1) {
11886
+ throw new Error(`Vite 配置必须且只能包含一个 miniappManifest() 插件,当前数量:${manifestPluginCount}`);
11887
+ }
11888
+ }
11652
11889
  root = resolved.root;
11653
11890
  outDir = resolved.build.outDir;
11654
11891
  command = resolved.command;
@@ -11673,6 +11910,9 @@ function miniappManifest() {
11673
11910
  }
11674
11911
  const version = validateMiniappPackageVersionForBuild(readMiniappVersionFromPackageJson(root));
11675
11912
  const sdkVersion = resolveSdkVersion();
11913
+ const parsedPermissions = readMiniappPermissionsFromPackageJson(root, sdkVersion);
11914
+ if (!parsedPermissions.declared)
11915
+ this.warn(getMissingPermissionsWarning());
11676
11916
  const outputRoot = path.resolve(root, outDir);
11677
11917
  const htmlFiles = collectHtmlFiles(outputRoot);
11678
11918
  const unexpectedHtmlFiles = htmlFiles.filter((file) => path.relative(outputRoot, file) !== 'index.html');
@@ -11688,7 +11928,12 @@ function miniappManifest() {
11688
11928
  node_fs.writeFileSync(indexHtmlPath, enforceMiniappHtmlPolicy(node_fs.readFileSync(indexHtmlPath, 'utf8'), { skipPlatformCsp }));
11689
11929
  const manifestPath = path.join(outputRoot, 'manifest.json');
11690
11930
  node_fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
11691
- node_fs.writeFileSync(manifestPath, renderMiniappManifest({ version, sdkVersion }));
11931
+ node_fs.writeFileSync(manifestPath, renderMiniappManifest({
11932
+ version,
11933
+ sdkVersion,
11934
+ platforms,
11935
+ ...(parsedPermissions.permissions === undefined ? {} : { permissions: parsedPermissions.permissions }),
11936
+ }));
11692
11937
  },
11693
11938
  };
11694
11939
  }
@@ -11734,4 +11979,5 @@ function resolveHmrWebSocketUrl(resolved) {
11734
11979
  return `${protocol}://${host}${port ? `:${port}` : ''}`;
11735
11980
  }
11736
11981
 
11982
+ exports.MINIAPP_PLATFORM_VALUES = MINIAPP_PLATFORM_VALUES;
11737
11983
  exports.miniappManifest = miniappManifest;