@heybox/hb-sdk 0.8.1-alpha.3 → 0.8.1-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +47 -3
  3. package/dist/cli-chunks/{build-B5Sbi8Sq.cjs → build-C8oN_Ms9.cjs} +7 -5
  4. package/dist/cli-chunks/{context-DuxaBL3Y.cjs → context-DZkqvg9S.cjs} +8 -3
  5. package/dist/cli-chunks/{create-CIfZrg3F.cjs → create-CToSHRfO.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-CFubP5kW.cjs → dev-CTA0lsLD.cjs} +479 -140
  7. package/dist/cli-chunks/{doctor-IPKn3PBn.cjs → doctor-DRa_kjP1.cjs} +1 -1
  8. package/dist/cli-chunks/{index-KHhdZ8eZ.cjs → index-Bkl5YmtN.cjs} +2 -2
  9. package/dist/cli-chunks/{index-DCJN-V1y.cjs → index-zNpZDWhc.cjs} +87 -15
  10. package/dist/cli-chunks/{index.esm-8hgZlNF8.cjs → index.esm-CGoUW47e.cjs} +9 -8
  11. package/dist/cli-chunks/{login-CoB9jXxC.cjs → login-CCEPk2Ok.cjs} +2 -2
  12. package/dist/cli-chunks/{project-vite-DMxdOWsU.cjs → project-vite-couFw5bL.cjs} +1 -1
  13. package/dist/cli-chunks/{remote-D4ZcngLn.cjs → remote-DQ70o-Km.cjs} +33 -24
  14. package/dist/cli-chunks/{runtime-permission-env-XAZFauvZ.cjs → runtime-permission-env-BN43V7d0.cjs} +181 -16
  15. package/dist/cli-chunks/{session-BnoHxzFq.cjs → session-C1R_39si.cjs} +1 -1
  16. package/dist/cli-chunks/{skill-CDEJtATn.cjs → skill-CVXOE5jH.cjs} +83 -27
  17. package/dist/cli-chunks/{version-BGzCIQhE.cjs → version-DbDVL6vm.cjs} +1 -1
  18. package/dist/cli.cjs +1 -1
  19. package/dist/devtools/browser-dev-host/assets/browser-dev-host-CH6L1ZJI.js +101 -0
  20. package/dist/devtools/browser-dev-host/assets/desktop-app-launch-DnPRjCa3.js +6 -0
  21. package/dist/devtools/browser-dev-host/assets/index-D-aNERAr.css +1 -0
  22. package/dist/devtools/browser-dev-host/assets/index-DocojUxT.js +567 -0
  23. package/dist/devtools/browser-dev-host/index.html +3 -3
  24. package/dist/index.cjs.js +1893 -1571
  25. package/dist/index.esm.js +1893 -1572
  26. package/dist/miniapp-publish.cjs.js +61 -0
  27. package/dist/miniapp-publish.esm.js +59 -1
  28. package/dist/protocol.cjs.js +64 -13
  29. package/dist/protocol.esm.js +64 -13
  30. package/dist/vite.cjs.js +1316 -10
  31. package/dist/vite.esm.js +1317 -12
  32. package/package.json +7 -7
  33. package/skill/SKILL.md +8 -3
  34. package/skill/references/api-protocol.md +3 -3
  35. package/skill/references/api-root.md +224 -208
  36. package/skill/references/cli.md +7 -1
  37. package/skill/references/examples.md +4 -0
  38. package/skill/references/recipes.md +161 -0
  39. package/skill/references/safety-boundaries.md +8 -2
  40. package/skill/skill.json +5 -5
  41. package/types/core/client.d.ts +2 -0
  42. package/types/core/sdk.d.ts +3 -0
  43. package/types/core/singleton.d.ts +3 -0
  44. package/types/devtools/device-logs.d.ts +48 -0
  45. package/types/index.d.ts +3 -1
  46. package/types/miniapp-manifest/companion-directory.d.ts +2 -0
  47. package/types/miniapp-manifest/companion-executable.d.ts +4 -0
  48. package/types/miniapp-manifest/companion-types.d.ts +38 -0
  49. package/types/miniapp-manifest/companions.d.ts +17 -0
  50. package/types/miniapp-manifest/index.d.ts +2 -0
  51. package/types/miniapp-manifest/node.d.ts +7 -0
  52. package/types/miniapp-manifest/permissions.d.ts +1 -1
  53. package/types/miniapp-manifest/schema.d.ts +4 -1
  54. package/types/miniapp-publish/index.d.ts +17 -2
  55. package/types/modules/companion/index.d.ts +57 -0
  56. package/types/modules/network/index.d.ts +1 -4
  57. package/types/modules/network/observability.d.ts +0 -1
  58. package/types/protocol/dev-session.d.ts +6 -0
  59. package/types/vite/index.d.ts +10 -0
  60. package/dist/devtools/browser-dev-host/assets/browser-dev-host-DzEst9n7.js +0 -99
  61. package/dist/devtools/browser-dev-host/assets/index-B-NHlLsr.js +0 -567
  62. package/dist/devtools/browser-dev-host/assets/index-P-ra4m1y.css +0 -1
  63. package/dist/devtools/browser-dev-host/assets/workbench-state-BwV7bm4n.js +0 -5
@@ -2,7 +2,8 @@
2
2
 
3
3
  var fs = require('node:fs');
4
4
  var path = require('node:path');
5
- var version = require('./version-BGzCIQhE.cjs');
5
+ var version = require('./version-DbDVL6vm.cjs');
6
+ require('node:crypto');
6
7
  var node_async_hooks = require('node:async_hooks');
7
8
 
8
9
  var re = {exports: {}};
@@ -2799,6 +2800,7 @@ const MINI_PROGRAM_PERMISSION_KEYS = [
2799
2800
  'clipboard',
2800
2801
  'leaderboard',
2801
2802
  'network',
2803
+ 'companion',
2802
2804
  ];
2803
2805
  const MINI_PROGRAM_PERMISSION_CATALOG = [
2804
2806
  {
@@ -2911,6 +2913,29 @@ const MINI_PROGRAM_PERMISSION_CATALOG = [
2911
2913
  methods: ['network.request', 'network.download'],
2912
2914
  conditions: ['声明后仍需平台批准,并继续执行网络安全策略。'],
2913
2915
  },
2916
+ {
2917
+ key: 'companion',
2918
+ name: '桌面辅助应用',
2919
+ description: '下载、准备并运行随当前小程序版本发布的受管桌面程序。',
2920
+ access: 'platform-approval',
2921
+ risk: 'high',
2922
+ config: {},
2923
+ methods: [
2924
+ 'companion.getInfo',
2925
+ 'companion.getPreparationStatus',
2926
+ 'companion.prepare',
2927
+ 'companion.cancelPreparation',
2928
+ 'companion.getActiveSession',
2929
+ 'companion.launch',
2930
+ 'companion.session.write',
2931
+ 'companion.session.closeStdin',
2932
+ 'companion.session.terminate',
2933
+ 'companion.session.ackOutput',
2934
+ 'companion.openAttachment',
2935
+ 'companion.showNotification',
2936
+ ],
2937
+ conditions: ['声明后仍需平台批准,并继续执行可信用户手势、Host 能力和当前版本 Manifest 校验。'],
2938
+ },
2914
2939
  ];
2915
2940
  new Set(MINI_PROGRAM_PERMISSION_KEYS);
2916
2941
 
@@ -2919,7 +2944,7 @@ function isManagedMiniProgramRuntimePermissionKey(key) {
2919
2944
  return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
2920
2945
  }
2921
2946
  function parseMiniProgramRuntimePermissions(snapshot) {
2922
- if (!isRecord$2(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
2947
+ if (!isRecord$4(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
2923
2948
  return { valid: false, permissions: {} };
2924
2949
  }
2925
2950
  if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
@@ -2928,7 +2953,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
2928
2953
  const seenKeys = new Set();
2929
2954
  const permissions = {};
2930
2955
  for (const rawEntry of snapshot.entries) {
2931
- if (!isRecord$2(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
2956
+ if (!isRecord$4(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
2932
2957
  return { valid: false, permissions: {} };
2933
2958
  }
2934
2959
  const inputKey = rawEntry.key.trim();
@@ -2938,13 +2963,13 @@ function parseMiniProgramRuntimePermissions(snapshot) {
2938
2963
  }
2939
2964
  seenKeys.add(key);
2940
2965
  if (!isManagedMiniProgramRuntimePermissionKey(key)) {
2941
- if (!isRecord$2(rawEntry.config))
2942
- return { valid: false, permissions: {} };
2966
+ // 未知权限必须忽略,不能让 config:null / 缺字段把已认识的批准一起否掉。
2967
+ // 服务端会对无 config message 字段输出 null(Rylai EmitUnpopulated)。
2943
2968
  continue;
2944
2969
  }
2945
2970
  if (key === 'network') {
2946
2971
  const config = rawEntry.config;
2947
- if (!isRecord$2(config) || typeof config.useOfficialDomain !== 'boolean') {
2972
+ if (!isRecord$4(config) || typeof config.useOfficialDomain !== 'boolean') {
2948
2973
  return { valid: false, permissions: {} };
2949
2974
  }
2950
2975
  permissions[key] = {
@@ -2954,7 +2979,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
2954
2979
  };
2955
2980
  continue;
2956
2981
  }
2957
- if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord$2(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
2982
+ if (rawEntry.config !== null && rawEntry.config !== undefined && (!isRecord$4(rawEntry.config) || Object.keys(rawEntry.config).length > 0)) {
2958
2983
  return { valid: false, permissions: {} };
2959
2984
  }
2960
2985
  permissions[key] = {
@@ -2965,7 +2990,7 @@ function parseMiniProgramRuntimePermissions(snapshot) {
2965
2990
  }
2966
2991
  return { valid: true, permissions };
2967
2992
  }
2968
- function isRecord$2(value) {
2993
+ function isRecord$4(value) {
2969
2994
  return typeof value === 'object' && value !== null && !Array.isArray(value);
2970
2995
  }
2971
2996
 
@@ -2978,7 +3003,7 @@ function parseMiniappPermissions(value, options) {
2978
3003
  }
2979
3004
  return { declared: false };
2980
3005
  }
2981
- if (!isRecord$1(value)) {
3006
+ if (!isRecord$3(value)) {
2982
3007
  throw new Error(`${sourceLabel} 必须是 JSON 对象`);
2983
3008
  }
2984
3009
  const knownKeys = new Set(MINIAPP_PERMISSION_KEYS);
@@ -2992,7 +3017,7 @@ function parseMiniappPermissions(value, options) {
2992
3017
  continue;
2993
3018
  const declaration = value[key];
2994
3019
  const itemLabel = `${sourceLabel}.${key}`;
2995
- if (!isRecord$1(declaration))
3020
+ if (!isRecord$3(declaration))
2996
3021
  throw new Error(`${itemLabel} 必须是 JSON 对象`);
2997
3022
  const definition = MINI_PROGRAM_PERMISSION_CATALOG.find((item) => item.key === key);
2998
3023
  if (!definition)
@@ -3028,7 +3053,7 @@ function getMissingPermissionsWarning(sourceLabel = 'package.json#heybox.permiss
3028
3053
  }
3029
3054
  function composeMiniappRuntimePermissions(local, approvals) {
3030
3055
  const parsedApprovals = parseMiniProgramRuntimePermissions(approvals);
3031
- const approvalRevision = isRecord$1(approvals) && Number.isInteger(approvals.revision) ? approvals.revision : undefined;
3056
+ const approvalRevision = isRecord$3(approvals) && Number.isInteger(approvals.revision) ? approvals.revision : undefined;
3032
3057
  const views = [];
3033
3058
  const entries = [];
3034
3059
  for (const definition of MINI_PROGRAM_PERMISSION_CATALOG) {
@@ -3042,9 +3067,22 @@ function composeMiniappRuntimePermissions(local, approvals) {
3042
3067
  }
3043
3068
  const approval = parsedApprovals.valid ? parsedApprovals.permissions[definition.key] : undefined;
3044
3069
  const approved = approval?.status === 'enabled';
3070
+ const effective = declared && approved;
3071
+ if (definition.key !== 'network') {
3072
+ views.push({
3073
+ key: definition.key,
3074
+ access: definition.access,
3075
+ declared,
3076
+ approved,
3077
+ effective,
3078
+ });
3079
+ if (declared) {
3080
+ entries.push({ key: definition.key, status: effective ? 'enabled' : 'disabled', config: {} });
3081
+ }
3082
+ continue;
3083
+ }
3045
3084
  const requestedOfficialDomain = declaration?.enabled === true && 'useOfficialDomain' in declaration && declaration.useOfficialDomain;
3046
3085
  const approvedOfficialDomain = approval?.config.useOfficialDomain === true;
3047
- const effective = declared && approved;
3048
3086
  const effectiveOfficialDomain = effective && (local.declared ? requestedOfficialDomain : true) && approvedOfficialDomain;
3049
3087
  views.push({
3050
3088
  key: definition.key,
@@ -3065,7 +3103,7 @@ function composeMiniappRuntimePermissions(local, approvals) {
3065
3103
  views,
3066
3104
  };
3067
3105
  }
3068
- function isRecord$1(value) {
3106
+ function isRecord$3(value) {
3069
3107
  return typeof value === 'object' && value !== null && !Array.isArray(value);
3070
3108
  }
3071
3109
 
@@ -3106,13 +3144,69 @@ function validateMiniappManifestForDeploy(manifest) {
3106
3144
  sdkVersion,
3107
3145
  sourceLabel: 'manifest.permissions',
3108
3146
  });
3147
+ const companions = validateGeneratedCompanions(manifest.companions);
3109
3148
  return {
3110
3149
  version,
3111
3150
  sdkVersion,
3112
3151
  platforms: validateMiniappPlatforms(manifest.platforms, 'manifest.platforms'),
3113
3152
  ...(permissions.permissions === undefined ? {} : { permissions: permissions.permissions }),
3153
+ ...(companions === undefined ? {} : { companions }),
3114
3154
  };
3115
3155
  }
3156
+ function validateGeneratedCompanions(value) {
3157
+ if (value === undefined)
3158
+ return undefined;
3159
+ if (!isRecord$2(value) || Object.keys(value).length === 0)
3160
+ throw new Error('manifest.companions 必须是非空对象');
3161
+ for (const [alias, definition] of Object.entries(value)) {
3162
+ if (!/^[a-z][a-z0-9-]{0,31}$/.test(alias) ||
3163
+ !isRecord$2(definition) ||
3164
+ typeof definition.displayName !== 'string' ||
3165
+ !definition.displayName ||
3166
+ Array.from(definition.displayName).length > 120 ||
3167
+ !Array.isArray(definition.capabilities) ||
3168
+ definition.capabilities.some((capability) => capability !== 'stdio' && capability !== 'attachments' && capability !== 'notifications') ||
3169
+ new Set(definition.capabilities).size !== definition.capabilities.length ||
3170
+ !isRecord$2(definition.targets) ||
3171
+ Object.keys(definition.targets).length === 0)
3172
+ throw new Error(`manifest.companions.${alias} 不合法`);
3173
+ for (const [target, artifact] of Object.entries(definition.targets)) {
3174
+ if (isRecord$2(artifact) && artifact.elevation === 'required') {
3175
+ throw new Error(`manifest.companions.${alias}.targets.${target}.elevation V1 仅支持 none,暂不支持管理员权限启动`);
3176
+ }
3177
+ if ((target !== 'windows-x64' && target !== 'macos-arm64') ||
3178
+ !isRecord$2(artifact) ||
3179
+ artifact.path !== `companions/${alias}/${target}.zip` ||
3180
+ !Number.isSafeInteger(artifact.size) ||
3181
+ Number(artifact.size) <= 0 ||
3182
+ typeof artifact.sha256 !== 'string' ||
3183
+ !/^[a-f0-9]{64}$/.test(artifact.sha256) ||
3184
+ !isRecord$2(artifact.entrypoint) ||
3185
+ (artifact.entrypoint.kind !== 'executable' && artifact.entrypoint.kind !== 'app-bundle') ||
3186
+ typeof artifact.entrypoint.path !== 'string' ||
3187
+ !artifact.entrypoint.path ||
3188
+ artifact.elevation !== 'none' ||
3189
+ !isValidGeneratedCompanionArgs(artifact.args)) {
3190
+ throw new Error(`manifest.companions.${alias}.targets.${target} 不合法`);
3191
+ }
3192
+ }
3193
+ }
3194
+ return value;
3195
+ }
3196
+ function isValidGeneratedCompanionArgs(value) {
3197
+ if (!Array.isArray(value) || value.length > 64)
3198
+ return false;
3199
+ let totalBytes = 0;
3200
+ for (const arg of value) {
3201
+ if (typeof arg !== 'string' || /[\u0000\r\n]/.test(arg))
3202
+ return false;
3203
+ const bytes = Buffer.byteLength(arg, 'utf8');
3204
+ if (bytes > 1024)
3205
+ return false;
3206
+ totalBytes += bytes;
3207
+ }
3208
+ return totalBytes <= 16_384;
3209
+ }
3116
3210
  function validateMiniappPlatforms(platforms, sourceLabel = 'platforms') {
3117
3211
  if (!Array.isArray(platforms) || platforms.length === 0) {
3118
3212
  throw new Error(`${sourceLabel} 必须是非空平台数组`);
@@ -3147,6 +3241,9 @@ function validateSdkVersion(version, sourceLabel = 'sdkVersion') {
3147
3241
  function isManifestRecord(value) {
3148
3242
  return typeof value === 'object' && value !== null && !Array.isArray(value);
3149
3243
  }
3244
+ function isRecord$2(value) {
3245
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
3246
+ }
3150
3247
  function getMiniappManifestVersionError(version) {
3151
3248
  if (typeof version !== 'string' || version.trim() === '') {
3152
3249
  return `必须是合法 SemVer:${String(version)}`;
@@ -3178,6 +3275,8 @@ const MINIAPP_UPLOAD_SCOPE = 'activity';
3178
3275
  const ACTIVITY_UPLOAD_KEY_MAX_LENGTH = 64;
3179
3276
  const MINIAPP_UPLOAD_BATCH_SIZE = 50;
3180
3277
  const MINIAPP_UPLOAD_TOTAL_SIZE_LIMIT_BYTES = 100 * 1024 * 1024;
3278
+ /** Phase 0 尚未冻结;当前仅作为可单点替换、可测试的保守临时上限。 */
3279
+ const MINIAPP_COMPANION_UPLOAD_TEMPORARY_SIZE_LIMIT_BYTES = 2 * 1024 * 1024 * 1024;
3181
3280
  const USER_MINIPROGRAM_ACCESS_STATUS_API_PATH = '/mall/developer/user_miniprogram/access_status';
3182
3281
  const DEVELOPER_ENTITY_LIST_API_PATH = '/mall/developer/entity/list';
3183
3282
  const DEVELOPER_ENTITY_SWITCH_API_PATH = '/mall/developer/entity/switch';
@@ -3237,6 +3336,18 @@ function validateUploadTotalSize(items, options = {}) {
3237
3336
  }
3238
3337
  return undefined;
3239
3338
  }
3339
+ function validateMiniappUploadSizeBudgets(items, options = {}) {
3340
+ const companionItems = items.filter((item) => normalizeRelativePath(item.relativePath).startsWith('companions/'));
3341
+ const webItems = items.filter((item) => !normalizeRelativePath(item.relativePath).startsWith('companions/'));
3342
+ const webError = validateUploadTotalSize(webItems, { limitBytes: options.webLimitBytes ?? MINIAPP_UPLOAD_TOTAL_SIZE_LIMIT_BYTES });
3343
+ if (webError)
3344
+ return webError;
3345
+ const companionTotal = companionItems.reduce((sum, item) => sum + (Number.isFinite(item.size) && item.size > 0 ? item.size : 0), 0);
3346
+ const companionLimit = options.companionLimitBytes ?? MINIAPP_COMPANION_UPLOAD_TEMPORARY_SIZE_LIMIT_BYTES;
3347
+ if (companionTotal > companionLimit)
3348
+ return 'Companion 归档总大小超过当前 2GiB 临时上限,请缩减归档后重新 deploy';
3349
+ return undefined;
3350
+ }
3240
3351
  function shouldUploadDistFile(relativePath) {
3241
3352
  const normalized = normalizeRelativePath(relativePath);
3242
3353
  if (!normalized) {
@@ -3335,6 +3446,7 @@ function resolveMiniappUploadSessionFiles(localFiles, serverFiles, uploadedKeys)
3335
3446
  }
3336
3447
  const mappings = new Map();
3337
3448
  const serverSizes = new Map();
3449
+ const serverHashes = new Map();
3338
3450
  const knownKeys = new Set();
3339
3451
  for (const serverFile of serverFiles) {
3340
3452
  const relativePath = normalizeMiniappArtifactRelativePath(serverFile.relative_path);
@@ -3352,8 +3464,13 @@ function resolveMiniappUploadSessionFiles(localFiles, serverFiles, uploadedKeys)
3352
3464
  if (!Number.isSafeInteger(size) || size < 0) {
3353
3465
  throw new Error(`上传会话返回文件大小异常:${relativePath}`);
3354
3466
  }
3467
+ const sha256 = String(serverFile.sha256 || '');
3468
+ if (!/^[a-f0-9]{64}$/.test(sha256)) {
3469
+ throw new Error(`上传会话返回文件 SHA-256 异常:${relativePath}`);
3470
+ }
3355
3471
  mappings.set(relativePath, key);
3356
3472
  serverSizes.set(relativePath, size);
3473
+ serverHashes.set(relativePath, sha256);
3357
3474
  knownKeys.add(key);
3358
3475
  }
3359
3476
  const files = preparedFiles.map((file) => {
@@ -3364,6 +3481,9 @@ function resolveMiniappUploadSessionFiles(localFiles, serverFiles, uploadedKeys)
3364
3481
  if (serverSizes.get(file.relativePath) !== file.size) {
3365
3482
  throw new Error(`上传会话文件大小与本地构建不一致:${file.relativePath}`);
3366
3483
  }
3484
+ if (!('sha256' in file) || serverHashes.get(file.relativePath) !== file.sha256) {
3485
+ throw new Error(`上传会话文件 SHA-256 与本地构建不一致:${file.relativePath}`);
3486
+ }
3367
3487
  return { file, key };
3368
3488
  });
3369
3489
  const completed = new Set();
@@ -3380,6 +3500,41 @@ function resolveMiniappUploadSessionFiles(localFiles, serverFiles, uploadedKeys)
3380
3500
  uploadedKeys: [...completed],
3381
3501
  };
3382
3502
  }
3503
+ /** 校验 Manifest 中所有 Companion 归档都精确属于当前上传 receipt。 */
3504
+ function validateMiniappCompanionFileReceipts(companions, files) {
3505
+ const companionFiles = new Map(files.filter((file) => file.relativePath.startsWith('companions/')).map((file) => [file.relativePath, file]));
3506
+ if (companions === undefined) {
3507
+ if (companionFiles.size > 0)
3508
+ throw new Error('dist 包含未被 manifest.companions 引用的 Companion 归档');
3509
+ return;
3510
+ }
3511
+ if (!isRecord$1(companions))
3512
+ throw new Error('manifest.companions 必须是对象');
3513
+ const referenced = new Set();
3514
+ for (const definition of Object.values(companions)) {
3515
+ if (!isRecord$1(definition) || !isRecord$1(definition.targets))
3516
+ throw new Error('manifest.companions targets 不合法');
3517
+ for (const artifact of Object.values(definition.targets)) {
3518
+ if (!isRecord$1(artifact) || typeof artifact.path !== 'string' || typeof artifact.size !== 'number' || typeof artifact.sha256 !== 'string') {
3519
+ throw new Error('manifest.companions artifact 不合法');
3520
+ }
3521
+ const file = companionFiles.get(artifact.path);
3522
+ if (!file)
3523
+ throw new Error(`manifest.companions 引用的归档不在当前上传 receipt:${artifact.path}`);
3524
+ if (file.size !== artifact.size)
3525
+ throw new Error(`Companion 归档大小与 manifest 不一致:${artifact.path}`);
3526
+ if (file.sha256 !== artifact.sha256)
3527
+ throw new Error(`Companion 归档 SHA-256 与 manifest 不一致:${artifact.path}`);
3528
+ referenced.add(artifact.path);
3529
+ }
3530
+ }
3531
+ const extra = [...companionFiles.keys()].find((relativePath) => !referenced.has(relativePath));
3532
+ if (extra)
3533
+ throw new Error(`Companion 归档未被 manifest.companions 引用:${extra}`);
3534
+ }
3535
+ function isRecord$1(value) {
3536
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
3537
+ }
3383
3538
  function normalizeMiniappArtifactRelativePath(relativePath) {
3384
3539
  const value = String(relativePath || '');
3385
3540
  if (!value) {
@@ -3502,10 +3657,12 @@ function readMiniappPackageJson(root, requireVersion) {
3502
3657
  catch (error) {
3503
3658
  throw new Error(`@heybox/hb-sdk 解析 package.json 失败:${formatReason(error)}`);
3504
3659
  }
3505
- return { packageJson, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
3660
+ return { packageJson, packageJsonPath, version: typeof packageJson.version === 'string' ? packageJson.version.trim() : '' };
3506
3661
  }
3507
3662
  function readMiniappHeyboxConfig(packageJson) {
3508
- if (packageJson.heybox !== undefined && !isRecord(packageJson.heybox)) {
3663
+ if (packageJson.heybox === undefined)
3664
+ return undefined;
3665
+ if (!isRecord(packageJson.heybox)) {
3509
3666
  throw new Error('@heybox/hb-sdk 提示:package.json#heybox 必须是 JSON 对象');
3510
3667
  }
3511
3668
  return packageJson.heybox;
@@ -3520,6 +3677,13 @@ function formatReason(error) {
3520
3677
  return String(error);
3521
3678
  }
3522
3679
 
3680
+ Array.from({ length: 256 }, (_, value) => {
3681
+ let crc = value;
3682
+ for (let bit = 0; bit < 8; bit++)
3683
+ crc = (crc >>> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
3684
+ return crc >>> 0;
3685
+ });
3686
+
3523
3687
  const HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN_ENV = 'HB_SDK_RUNTIME_USE_OFFICIAL_DOMAIN';
3524
3688
  const HB_SDK_RUNTIME_PERMISSION_CONTEXT_ENV = 'HB_SDK_RUNTIME_PERMISSION_CONTEXT';
3525
3689
  const VERIFIED_RUNTIME_PERMISSION_CONTEXT = 'verified';
@@ -3630,7 +3794,8 @@ exports.resolveMiniappSdkVersion = resolveMiniappSdkVersion;
3630
3794
  exports.resolveMiniappUploadSessionFiles = resolveMiniappUploadSessionFiles;
3631
3795
  exports.shouldSkipMiniappPlatformCspFromEnv = shouldSkipMiniappPlatformCspFromEnv;
3632
3796
  exports.shouldUploadDistFile = shouldUploadDistFile;
3797
+ exports.validateMiniappCompanionFileReceipts = validateMiniappCompanionFileReceipts;
3633
3798
  exports.validateMiniappManifestForDeploy = validateMiniappManifestForDeploy;
3634
3799
  exports.validateMiniappUploadPathLengths = validateMiniappUploadPathLengths;
3635
- exports.validateUploadTotalSize = validateUploadTotalSize;
3800
+ exports.validateMiniappUploadSizeBudgets = validateMiniappUploadSizeBudgets;
3636
3801
  exports.withMiniappPlatformCspEnv = withMiniappPlatformCspEnv;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DCJN-V1y.cjs');
3
+ var index = require('./index-zNpZDWhc.cjs');
4
4
  var node_crypto = require('node:crypto');
5
5
  var path = require('node:path');
6
6
  var require$$0$2 = require('fs');
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
+ var version = require('./version-DbDVL6vm.cjs');
4
+ var fs = require('node:fs/promises');
3
5
  var path = require('node:path');
4
- var version = require('./version-BGzCIQhE.cjs');
5
6
  var childProcess = require('node:child_process');
6
- var fs = require('node:fs/promises');
7
- var index = require('./index-DCJN-V1y.cjs');
7
+ var index = require('./index-zNpZDWhc.cjs');
8
8
  require('node:module');
9
9
  require('node:fs');
10
10
  require('path');
@@ -17,26 +17,6 @@ require('stream');
17
17
  require('buffer');
18
18
  require('util');
19
19
 
20
- function installSkill(options) {
21
- const binary = require.resolve('skills/bin/cli.mjs');
22
- const args = ['add', path.join(options.packageRoot, 'skill'), '--copy'];
23
- if (options.global)
24
- args.push('--global');
25
- if (options.allAgents)
26
- args.push('--agent', '*');
27
- else if (options.agents?.length)
28
- args.push('--agent', ...options.agents);
29
- if (options.force)
30
- args.push('--force');
31
- const env = { ...process.env, ...options.env, DISABLE_TELEMETRY: '1', DO_NOT_TRACK: '1' };
32
- const run = options.spawnImpl ?? childProcess.spawn;
33
- return new Promise((resolve, reject) => {
34
- const child = run(process.execPath, [binary, ...args], { cwd: options.cwd, env, stdio: 'inherit' });
35
- child.on('error', reject);
36
- child.on('close', (code) => resolve({ code: code ?? 1 }));
37
- });
38
- }
39
-
40
20
  async function findProjectPackageJson(cwd = process.cwd()) {
41
21
  let current = path.resolve(cwd);
42
22
  while (true) {
@@ -45,7 +25,45 @@ async function findProjectPackageJson(cwd = process.cwd()) {
45
25
  await fs.access(candidate);
46
26
  return candidate;
47
27
  }
48
- catch { /* continue */ }
28
+ catch {
29
+ /* continue */
30
+ }
31
+ const parent = path.dirname(current);
32
+ if (parent === current)
33
+ return undefined;
34
+ current = parent;
35
+ }
36
+ }
37
+ async function findSdkPackageRoot(startDir) {
38
+ let current = path.resolve(startDir);
39
+ while (true) {
40
+ const candidate = path.join(current, 'package.json');
41
+ try {
42
+ const pkg = JSON.parse(await fs.readFile(candidate, 'utf8'));
43
+ if (pkg.name === '@heybox/hb-sdk')
44
+ return current;
45
+ }
46
+ catch {
47
+ /* continue */
48
+ }
49
+ const parent = path.dirname(current);
50
+ if (parent === current)
51
+ return undefined;
52
+ current = parent;
53
+ }
54
+ }
55
+ async function readInstalledProjectSdkVersion(projectPackageJson) {
56
+ let current = path.dirname(projectPackageJson);
57
+ while (true) {
58
+ const candidate = path.join(current, 'node_modules', '@heybox', 'hb-sdk', 'package.json');
59
+ try {
60
+ const pkg = JSON.parse(await fs.readFile(candidate, 'utf8'));
61
+ if (pkg.name === '@heybox/hb-sdk' && typeof pkg.version === 'string' && pkg.version)
62
+ return pkg.version;
63
+ }
64
+ catch {
65
+ /* continue */
66
+ }
49
67
  const parent = path.dirname(current);
50
68
  if (parent === current)
51
69
  return undefined;
@@ -60,20 +78,58 @@ async function verifyProjectSdk(cwd, version) {
60
78
  const declared = pkg.dependencies?.['@heybox/hb-sdk'] ?? pkg.devDependencies?.['@heybox/hb-sdk'];
61
79
  if (!declared)
62
80
  throw new Error('项目缺少 @heybox/hb-sdk 依赖');
63
- if (declared !== version && !String(declared).includes(version)) {
81
+ const declaredVersion = String(declared);
82
+ if (declaredVersion.startsWith('workspace:')) {
83
+ const installedVersion = await readInstalledProjectSdkVersion(file);
84
+ if (installedVersion === version)
85
+ return;
86
+ if (installedVersion) {
87
+ throw new Error(`项目 @heybox/hb-sdk 版本 ${declaredVersion}(实际 ${installedVersion})与 CLI ${version} 不一致`);
88
+ }
89
+ }
90
+ if (declared !== version && !declaredVersion.includes(version)) {
64
91
  throw new Error(`项目 @heybox/hb-sdk 版本 ${declared} 与 CLI ${version} 不一致`);
65
92
  }
66
93
  }
67
94
 
95
+ function installSkill(options) {
96
+ const binary = require.resolve('skills/bin/cli.mjs');
97
+ const args = ['add', path.join(options.packageRoot, 'skill'), '--copy'];
98
+ if (options.global)
99
+ args.push('--global');
100
+ if (options.allAgents)
101
+ args.push('--agent', '*');
102
+ else if (options.agents?.length)
103
+ args.push('--agent', ...options.agents);
104
+ if (options.force)
105
+ args.push('--force');
106
+ const env = { ...process.env, ...options.env, DISABLE_TELEMETRY: '1', DO_NOT_TRACK: '1' };
107
+ const run = options.spawnImpl ?? childProcess.spawn;
108
+ return new Promise((resolve, reject) => {
109
+ const child = run(process.execPath, [binary, ...args], { cwd: options.cwd, env, stdio: 'inherit' });
110
+ child.on('error', reject);
111
+ child.on('close', (code) => resolve({ code: code ?? 1 }));
112
+ });
113
+ }
114
+
68
115
  async function runSkillInstallCommand(options = {}) {
69
116
  if (options.agent?.length && options.allAgents)
70
117
  throw new Error('--agent 与 --all-agents 互斥');
71
118
  const logger = options.logger ?? index.createCliLogger();
72
- const packageRoot = options.packageRoot ?? path.resolve(__dirname, '../../..');
119
+ const packageRoot = options.packageRoot ?? (await findSdkPackageRoot(__dirname));
120
+ if (!packageRoot)
121
+ throw new Error('未找到 @heybox/hb-sdk 包目录');
73
122
  const cwd = options.cwd ?? process.cwd();
74
123
  if (!options.global)
75
124
  await verifyProjectSdk(cwd, version.HB_SDK_VERSION);
76
- const result = await installSkill({ packageRoot, cwd, global: options.global, agents: options.agent, allAgents: options.allAgents, force: options.force });
125
+ const result = await installSkill({
126
+ packageRoot,
127
+ cwd,
128
+ global: options.global,
129
+ agents: options.agent,
130
+ allAgents: options.allAgents,
131
+ force: options.force,
132
+ });
77
133
  if (result.code !== 0)
78
134
  throw new Error(`Skill 安装失败(退出码 ${result.code})`);
79
135
  logger.success('hb-sdk Skill 安装完成');
@@ -3,6 +3,6 @@
3
3
  /** 构建时替换为当前发布包的实际版本。 */
4
4
  const HB_SDK_VERSION = typeof undefined === 'string'
5
5
  ? undefined
6
- : '0.8.1-alpha.3';
6
+ : '0.8.1-alpha.7';
7
7
 
8
8
  exports.HB_SDK_VERSION = HB_SDK_VERSION;
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./cli-chunks/index-DCJN-V1y.cjs');
3
+ var index = require('./cli-chunks/index-zNpZDWhc.cjs');
4
4
  require('node:module');
5
5
  require('node:fs');
6
6
  require('node:fs/promises');