@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.
- package/CHANGELOG.md +40 -0
- package/README.md +47 -3
- package/dist/cli-chunks/{build-B5Sbi8Sq.cjs → build-C8oN_Ms9.cjs} +7 -5
- package/dist/cli-chunks/{context-DuxaBL3Y.cjs → context-DZkqvg9S.cjs} +8 -3
- package/dist/cli-chunks/{create-CIfZrg3F.cjs → create-CToSHRfO.cjs} +1 -1
- package/dist/cli-chunks/{dev-CFubP5kW.cjs → dev-CTA0lsLD.cjs} +479 -140
- package/dist/cli-chunks/{doctor-IPKn3PBn.cjs → doctor-DRa_kjP1.cjs} +1 -1
- package/dist/cli-chunks/{index-KHhdZ8eZ.cjs → index-Bkl5YmtN.cjs} +2 -2
- package/dist/cli-chunks/{index-DCJN-V1y.cjs → index-zNpZDWhc.cjs} +87 -15
- package/dist/cli-chunks/{index.esm-8hgZlNF8.cjs → index.esm-CGoUW47e.cjs} +9 -8
- package/dist/cli-chunks/{login-CoB9jXxC.cjs → login-CCEPk2Ok.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-DMxdOWsU.cjs → project-vite-couFw5bL.cjs} +1 -1
- package/dist/cli-chunks/{remote-D4ZcngLn.cjs → remote-DQ70o-Km.cjs} +33 -24
- package/dist/cli-chunks/{runtime-permission-env-XAZFauvZ.cjs → runtime-permission-env-BN43V7d0.cjs} +181 -16
- package/dist/cli-chunks/{session-BnoHxzFq.cjs → session-C1R_39si.cjs} +1 -1
- package/dist/cli-chunks/{skill-CDEJtATn.cjs → skill-CVXOE5jH.cjs} +83 -27
- package/dist/cli-chunks/{version-BGzCIQhE.cjs → version-DbDVL6vm.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-CH6L1ZJI.js +101 -0
- package/dist/devtools/browser-dev-host/assets/desktop-app-launch-DnPRjCa3.js +6 -0
- package/dist/devtools/browser-dev-host/assets/index-D-aNERAr.css +1 -0
- package/dist/devtools/browser-dev-host/assets/index-DocojUxT.js +567 -0
- package/dist/devtools/browser-dev-host/index.html +3 -3
- package/dist/index.cjs.js +1893 -1571
- package/dist/index.esm.js +1893 -1572
- package/dist/miniapp-publish.cjs.js +61 -0
- package/dist/miniapp-publish.esm.js +59 -1
- package/dist/protocol.cjs.js +64 -13
- package/dist/protocol.esm.js +64 -13
- package/dist/vite.cjs.js +1316 -10
- package/dist/vite.esm.js +1317 -12
- package/package.json +7 -7
- package/skill/SKILL.md +8 -3
- package/skill/references/api-protocol.md +3 -3
- package/skill/references/api-root.md +224 -208
- package/skill/references/cli.md +7 -1
- package/skill/references/examples.md +4 -0
- package/skill/references/recipes.md +161 -0
- package/skill/references/safety-boundaries.md +8 -2
- package/skill/skill.json +5 -5
- package/types/core/client.d.ts +2 -0
- package/types/core/sdk.d.ts +3 -0
- package/types/core/singleton.d.ts +3 -0
- package/types/devtools/device-logs.d.ts +48 -0
- package/types/index.d.ts +3 -1
- package/types/miniapp-manifest/companion-directory.d.ts +2 -0
- package/types/miniapp-manifest/companion-executable.d.ts +4 -0
- package/types/miniapp-manifest/companion-types.d.ts +38 -0
- package/types/miniapp-manifest/companions.d.ts +17 -0
- package/types/miniapp-manifest/index.d.ts +2 -0
- package/types/miniapp-manifest/node.d.ts +7 -0
- package/types/miniapp-manifest/permissions.d.ts +1 -1
- package/types/miniapp-manifest/schema.d.ts +4 -1
- package/types/miniapp-publish/index.d.ts +17 -2
- package/types/modules/companion/index.d.ts +57 -0
- package/types/modules/network/index.d.ts +1 -4
- package/types/modules/network/observability.d.ts +0 -1
- package/types/protocol/dev-session.d.ts +6 -0
- package/types/vite/index.d.ts +10 -0
- package/dist/devtools/browser-dev-host/assets/browser-dev-host-DzEst9n7.js +0 -99
- package/dist/devtools/browser-dev-host/assets/index-B-NHlLsr.js +0 -567
- package/dist/devtools/browser-dev-host/assets/index-P-ra4m1y.css +0 -1
- package/dist/devtools/browser-dev-host/assets/workbench-state-BwV7bm4n.js +0 -5
package/dist/cli-chunks/{runtime-permission-env-XAZFauvZ.cjs → runtime-permission-env-BN43V7d0.cjs}
RENAMED
|
@@ -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-
|
|
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$
|
|
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$
|
|
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
|
-
|
|
2942
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
|
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.
|
|
3800
|
+
exports.validateMiniappUploadSizeBudgets = validateMiniappUploadSizeBudgets;
|
|
3636
3801
|
exports.withMiniappPlatformCspEnv = withMiniappPlatformCspEnv;
|
|
@@ -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
|
|
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 {
|
|
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
|
-
|
|
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 ??
|
|
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({
|
|
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 安装完成');
|