@heybox/hb-sdk 0.9.5-alpha.0 → 0.9.5-alpha.2

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 (30) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli-chunks/{artifact-CuCw0Ist.cjs → artifact-BQm9xFcY.cjs} +3 -3
  3. package/dist/cli-chunks/{build-D7fJ6BEA.cjs → build-D6tP7Uje.cjs} +7 -5
  4. package/dist/cli-chunks/{create-B-Jsz3ik.cjs → create-BBXC3wLI.cjs} +3 -1
  5. package/dist/cli-chunks/{dev-y8113QN9.cjs → dev-XoWrqt1g.cjs} +8 -8
  6. package/dist/cli-chunks/{dev-context-BaWpob6H.cjs → dev-context-Gh3m20fd.cjs} +2 -2
  7. package/dist/cli-chunks/{doctor-BhKqJsAC.cjs → doctor-Cuc3EQQ8.cjs} +3 -1
  8. package/dist/cli-chunks/{games-DQx46pWD.cjs → games-CoddgAux.cjs} +5 -4
  9. package/dist/cli-chunks/{index-DBPhVlCg.cjs → index-CS6WpCn8.cjs} +502 -66
  10. package/dist/cli-chunks/{index-grzaqQfA.cjs → index-_1anHmAG.cjs} +1 -1
  11. package/dist/cli-chunks/{index.esm-DUwFJ64A.cjs → index.esm-CrdqnD7E.cjs} +8 -6
  12. package/dist/cli-chunks/{login-DqP3MO5K.cjs → login-Bk3T3PMe.cjs} +2 -1
  13. package/dist/cli-chunks/{project-vite-VEkDSWQG.cjs → project-vite-CL-SW3RW.cjs} +1 -1
  14. package/dist/cli-chunks/{remote-Bx-Pz3E9.cjs → remote-Dfg2HLIt.cjs} +8 -8
  15. package/dist/cli-chunks/{runtime-permission-env-CqU4F5WB.cjs → runtime-permission-env-CgH1Dz4q.cjs} +2 -2
  16. package/dist/cli-chunks/{skill-Fhveb4OH.cjs → skill-BGxlDR-g.cjs} +4 -2
  17. package/dist/cli-chunks/{version-CeN27XBV.cjs → version-B1hlMGq2.cjs} +1 -1
  18. package/dist/cli.cjs +3 -1
  19. package/dist/devtools/browser-dev-host/assets/{browser-dev-host-B-m1GRCg.js → browser-dev-host-BHv7t_Sz.js} +9 -9
  20. package/dist/devtools/browser-dev-host/assets/{desktop-app-launch-d7SJPK9b.js → desktop-app-launch-DlaXmxAI.js} +1 -1
  21. package/dist/devtools/browser-dev-host/assets/{index-DpmM52Ck.js → index-CmITJMxu.js} +3 -3
  22. package/dist/devtools/browser-dev-host/index.html +2 -2
  23. package/dist/index.cjs.js +1 -1
  24. package/dist/index.esm.js +1 -1
  25. package/dist/vite.cjs.js +1 -1
  26. package/dist/vite.esm.js +1 -1
  27. package/package.json +7 -7
  28. package/skill/SKILL.md +6 -0
  29. package/skill/skill.json +5 -5
  30. package/dist/cli-chunks/deploy-lock-BmDK-jPl.cjs +0 -148
@@ -17,6 +17,8 @@ var require$$0$7 = require('constants');
17
17
  var fs$3 = require('node:fs');
18
18
  var fs$2 = require('node:fs/promises');
19
19
  var node_zlib = require('node:zlib');
20
+ var promises = require('node:readline/promises');
21
+ var promises$1 = require('node:timers/promises');
20
22
 
21
23
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
22
24
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -238,19 +240,19 @@ function requireArgument () {
238
240
 
239
241
  var command = {};
240
242
 
241
- 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-DBPhVlCg.cjs', document.baseURI).href)));
243
+ 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-CS6WpCn8.cjs', document.baseURI).href)));
242
244
  function __require$4() { return require$5("node:events"); }
243
245
 
244
- 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-DBPhVlCg.cjs', document.baseURI).href)));
246
+ 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-CS6WpCn8.cjs', document.baseURI).href)));
245
247
  function __require$3() { return require$4("node:child_process"); }
246
248
 
247
- 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-DBPhVlCg.cjs', document.baseURI).href)));
249
+ 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-CS6WpCn8.cjs', document.baseURI).href)));
248
250
  function __require$2() { return require$3("node:path"); }
249
251
 
250
- 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-DBPhVlCg.cjs', document.baseURI).href)));
252
+ 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-CS6WpCn8.cjs', document.baseURI).href)));
251
253
  function __require$1() { return require$2("node:fs"); }
252
254
 
253
- 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-DBPhVlCg.cjs', document.baseURI).href)));
255
+ 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-CS6WpCn8.cjs', document.baseURI).href)));
254
256
  function __require() { return require$1("node:process"); }
255
257
 
256
258
  var help = {};
@@ -16259,9 +16261,9 @@ class AuthSessionError extends Error {
16259
16261
  }
16260
16262
  }
16261
16263
  const AUTH_CACHE_VERSION = 1;
16262
- const paths$1 = envPaths('hb-sdk', { suffix: '' });
16264
+ const paths$2 = envPaths('hb-sdk', { suffix: '' });
16263
16265
  function getAuthCacheFilePath(options = {}) {
16264
- return options.cacheFile ?? path.join(paths$1.cache, 'auth.json');
16266
+ return options.cacheFile ?? path.join(paths$2.cache, 'auth.json');
16265
16267
  }
16266
16268
  function createHeyboxAuthSession(payload, options = {}) {
16267
16269
  return {
@@ -16386,7 +16388,7 @@ function createCookie(name, value) {
16386
16388
  return `${name}=${value}`;
16387
16389
  }
16388
16390
  function isHeyboxAuthSession(value) {
16389
- if (!isRecord(value)) {
16391
+ if (!isRecord$1(value)) {
16390
16392
  return false;
16391
16393
  }
16392
16394
  return (typeof value.heyboxId === 'string' &&
@@ -16412,7 +16414,7 @@ function normalizeHeyboxAuthSession(session) {
16412
16414
  return normalized;
16413
16415
  }
16414
16416
  function normalizeSelectedDeveloperEntitySnapshot(value) {
16415
- if (!isRecord(value)) {
16417
+ if (!isRecord$1(value)) {
16416
16418
  return undefined;
16417
16419
  }
16418
16420
  if (typeof value.entityId !== 'number' || !Number.isFinite(value.entityId)) {
@@ -16434,7 +16436,7 @@ function normalizeSelectedDeveloperEntitySnapshot(value) {
16434
16436
  selectedAt: value.selectedAt,
16435
16437
  };
16436
16438
  }
16437
- function isRecord(value) {
16439
+ function isRecord$1(value) {
16438
16440
  return Object.prototype.toString.call(value) === '[object Object]';
16439
16441
  }
16440
16442
 
@@ -17249,7 +17251,7 @@ async function inspectFeedbackLog(file, size) {
17249
17251
  return { mimeType: 'text/plain', width: 0, height: 0 };
17250
17252
  }
17251
17253
  async function createFeedbackCosClient(getToken) {
17252
- const { default: COS } = await Promise.resolve().then(function () { return require('./index-grzaqQfA.cjs'); }).then(function (n) { return n.index; });
17254
+ const { default: COS } = await Promise.resolve().then(function () { return require('./index-_1anHmAG.cjs'); }).then(function (n) { return n.index; });
17253
17255
  const cos = new COS({
17254
17256
  getAuthorization(_options, callback) {
17255
17257
  void getToken().then((token) => callback({
@@ -20449,6 +20451,461 @@ function installDevLogCommands(dev) {
20449
20451
  }
20450
20452
  }
20451
20453
 
20454
+ const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
20455
+ const BUILT_CLI_VERSION = '0.9.5-alpha.2';
20456
+ const PACKAGE_JSON_CANDIDATES$1 = [
20457
+ path.resolve(__dirname, '..', '..', 'package.json'),
20458
+ path.resolve(__dirname, '..', 'package.json'),
20459
+ path.resolve(__dirname, '..', '..', '..', 'package.json'),
20460
+ ];
20461
+ function getCliVersion(packageJsonCandidates = PACKAGE_JSON_CANDIDATES$1) {
20462
+ if (BUILT_CLI_VERSION !== CLI_VERSION_PLACEHOLDER) {
20463
+ return BUILT_CLI_VERSION;
20464
+ }
20465
+ return readCurrentSdkVersion$1(packageJsonCandidates);
20466
+ }
20467
+ function readCurrentSdkVersion$1(packageJsonCandidates) {
20468
+ for (const candidate of packageJsonCandidates) {
20469
+ if (!pathExists$1(candidate)) {
20470
+ continue;
20471
+ }
20472
+ const packageJson = JSON.parse(fs$3.readFileSync(candidate, 'utf8'));
20473
+ if (typeof packageJson.version === 'string' && packageJson.version) {
20474
+ return packageJson.version;
20475
+ }
20476
+ }
20477
+ throw new Error('未能读取 @heybox/hb-sdk 当前版本号');
20478
+ }
20479
+ function pathExists$1(filePath) {
20480
+ try {
20481
+ fs$3.accessSync(filePath, fs$3.constants.F_OK);
20482
+ return true;
20483
+ }
20484
+ catch {
20485
+ return false;
20486
+ }
20487
+ }
20488
+
20489
+ const DEPLOY_LOCKED_MESSAGE = '当前设备已有同版本产物正在上传,请等待完成后重试';
20490
+ const DEPLOY_LOCK_DIRECTORY_NAME = 'deploy-locks';
20491
+ const DEPLOY_LOCK_OWNER_FILE = 'owner.json';
20492
+ const INCOMPLETE_LOCK_GRACE_MS = 30_000;
20493
+ const defaultPaths = envPaths('hb-sdk', { suffix: '' });
20494
+ class DeployLockConflictError extends Error {
20495
+ }
20496
+ async function withDeployLock(scope, operation, options = {}) {
20497
+ let lock;
20498
+ try {
20499
+ lock = await acquireDeployLock(scope, options);
20500
+ }
20501
+ catch (error) {
20502
+ if (error instanceof DeployLockConflictError) {
20503
+ throw error;
20504
+ }
20505
+ // 本地文件锁只减少重复操作,文件系统异常不阻断服务端上传流程。
20506
+ return operation();
20507
+ }
20508
+ try {
20509
+ return await operation();
20510
+ }
20511
+ finally {
20512
+ await lock.release().catch(() => undefined);
20513
+ }
20514
+ }
20515
+ async function acquireDeployLock(scope, options = {}) {
20516
+ const lockDirectory = getDeployLockDirectory(scope, options.cacheRoot);
20517
+ return acquireLocalLock(lockDirectory, options);
20518
+ }
20519
+ /** 配置文件复用相同的进程归属和崩溃回收机制;调用方决定是否等待锁。 */
20520
+ async function acquireLocalFileLock(file) {
20521
+ return acquireLocalLock(`${file}.lock`, {});
20522
+ }
20523
+ async function acquireLocalLock(lockDirectory, options) {
20524
+ const ownerFile = path.join(lockDirectory, DEPLOY_LOCK_OWNER_FILE);
20525
+ const owner = {
20526
+ version: 1,
20527
+ pid: options.pid ?? process.pid,
20528
+ token: options.token ?? node_crypto.randomBytes(16).toString('hex'),
20529
+ };
20530
+ await fs$2.mkdir(path.dirname(lockDirectory), { recursive: true, mode: 0o700 });
20531
+ for (let attempt = 0; attempt < 2; attempt += 1) {
20532
+ let created = false;
20533
+ try {
20534
+ await fs$2.mkdir(lockDirectory, { mode: 0o700 });
20535
+ created = true;
20536
+ await fs$2.writeFile(ownerFile, `${JSON.stringify(owner)}\n`, { encoding: 'utf8', mode: 0o600 });
20537
+ return createDeployLock(lockDirectory, ownerFile, owner.token);
20538
+ }
20539
+ catch (error) {
20540
+ if (created) {
20541
+ await fs$2.rm(lockDirectory, { force: true, recursive: true });
20542
+ throw error;
20543
+ }
20544
+ if (!isNodeError(error) || error.code !== 'EEXIST') {
20545
+ throw error;
20546
+ }
20547
+ if (!(await canReclaimDeployLock(lockDirectory, ownerFile, options))) {
20548
+ throw new DeployLockConflictError(DEPLOY_LOCKED_MESSAGE);
20549
+ }
20550
+ await reclaimDeployLock(lockDirectory, owner.token);
20551
+ }
20552
+ }
20553
+ throw new DeployLockConflictError(DEPLOY_LOCKED_MESSAGE);
20554
+ }
20555
+ function getDeployLockDirectory(scope, cacheRoot = defaultPaths.cache) {
20556
+ const scopeHash = node_crypto.createHash('sha256').update(`${scope.apiBaseUrl}\0${scope.miniProgramId}\0${scope.version}`).digest('hex');
20557
+ return path.join(cacheRoot, DEPLOY_LOCK_DIRECTORY_NAME, scopeHash);
20558
+ }
20559
+ function createDeployLock(lockDirectory, ownerFile, token) {
20560
+ let released = false;
20561
+ return {
20562
+ async release() {
20563
+ if (released)
20564
+ return;
20565
+ released = true;
20566
+ await removeOwnedLock(lockDirectory, ownerFile, token);
20567
+ },
20568
+ };
20569
+ }
20570
+ async function canReclaimDeployLock(lockDirectory, ownerFile, options) {
20571
+ const owner = await readDeployLockOwner(ownerFile);
20572
+ if (owner) {
20573
+ return !(options.isProcessRunning ?? isProcessRunning)(owner.pid);
20574
+ }
20575
+ try {
20576
+ const lockStat = await fs$2.stat(lockDirectory);
20577
+ return (options.now ?? Date.now)() - lockStat.mtimeMs >= INCOMPLETE_LOCK_GRACE_MS;
20578
+ }
20579
+ catch (error) {
20580
+ return isNodeError(error) && error.code === 'ENOENT';
20581
+ }
20582
+ }
20583
+ async function removeOwnedLock(lockDirectory, ownerFile, token) {
20584
+ const owner = await readDeployLockOwner(ownerFile);
20585
+ if (owner?.token === token) {
20586
+ await fs$2.rm(lockDirectory, { force: true, recursive: true });
20587
+ }
20588
+ }
20589
+ async function reclaimDeployLock(lockDirectory, token) {
20590
+ const reclaimDirectory = `${lockDirectory}.reclaim-${node_crypto.createHash('sha256').update(token).digest('hex')}`;
20591
+ try {
20592
+ await fs$2.rename(lockDirectory, reclaimDirectory);
20593
+ }
20594
+ catch (error) {
20595
+ if (isNodeError(error) && error.code === 'ENOENT')
20596
+ return;
20597
+ throw error;
20598
+ }
20599
+ await fs$2.rm(reclaimDirectory, { force: true, recursive: true });
20600
+ }
20601
+ async function readDeployLockOwner(ownerFile) {
20602
+ try {
20603
+ const value = JSON.parse(await fs$2.readFile(ownerFile, 'utf8'));
20604
+ return isDeployLockOwner(value) ? value : null;
20605
+ }
20606
+ catch (error) {
20607
+ if (isNodeError(error) && error.code === 'ENOENT')
20608
+ return null;
20609
+ if (error instanceof SyntaxError)
20610
+ return null;
20611
+ throw error;
20612
+ }
20613
+ }
20614
+ function isDeployLockOwner(value) {
20615
+ return (typeof value === 'object' &&
20616
+ value !== null &&
20617
+ value.version === 1 &&
20618
+ Number.isInteger(value.pid) &&
20619
+ typeof value.token === 'string');
20620
+ }
20621
+ function isProcessRunning(pid) {
20622
+ try {
20623
+ process.kill(pid, 0);
20624
+ return true;
20625
+ }
20626
+ catch (error) {
20627
+ return !isNodeError(error) || error.code !== 'ESRCH';
20628
+ }
20629
+ }
20630
+ function isNodeError(error) {
20631
+ return error instanceof Error && 'code' in error;
20632
+ }
20633
+
20634
+ /** npm 版本检查和已批准更新提醒共用的缓存周期。 */
20635
+ const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
20636
+ function isUpdateCheckCacheFresh(checkedAt, now) {
20637
+ if (typeof checkedAt !== 'string')
20638
+ return false;
20639
+ const elapsed = now.getTime() - Date.parse(checkedAt);
20640
+ return Number.isFinite(elapsed) && elapsed >= 0 && elapsed < UPDATE_CHECK_TTL_MS;
20641
+ }
20642
+
20643
+ const RELEASE_HIGHLIGHT_CACHE_VERSION = 4;
20644
+ const DEFAULT_TIMEOUT_MS$1 = 1000;
20645
+ const RELEASE_HIGHLIGHT_CACHE_FILE = 'release-highlight.json';
20646
+ const UPDATES_URL = 'https://activity.xiaoheihe.cn/u/hb-sdk/approved-notice.json';
20647
+ const paths$1 = envPaths('hb-sdk', { suffix: '' });
20648
+ async function printReleaseHighlight(options = {}) {
20649
+ try {
20650
+ const logger = options.logger ?? createCliLogger({ stderr: options.stderr });
20651
+ // 机器调用和 CI 不输出提醒,Agent 通过 Skill 读取更新日志。
20652
+ if (!logger.isInteractive) {
20653
+ return;
20654
+ }
20655
+ const notice = await getReleaseHighlight(options);
20656
+ if (notice) {
20657
+ // 展示即记录当天日期;内容缓存刷新、切换项目或中断确认都不会重复提醒。
20658
+ if (!(await recordReleaseHighlightShown(notice.version, options)))
20659
+ return;
20660
+ const useColor = (options.env ?? process.env).NO_COLOR !== '1';
20661
+ logger.raw(formatReleaseHighlight(notice, useColor, options.currentVersion ?? getCliVersion()), { stream: 'stderr' });
20662
+ const ask = options.promptDismiss ?? (() => promptDismiss(useColor));
20663
+ if ((options.promptDismiss || process.stdin.isTTY) && await ask()) {
20664
+ await dismissReleaseHighlight(notice.version, options);
20665
+ }
20666
+ }
20667
+ }
20668
+ catch (error) {
20669
+ if (error instanceof CommanderError)
20670
+ throw error;
20671
+ // 更新提醒不能影响实际执行的 hb-sdk 命令。
20672
+ }
20673
+ }
20674
+ async function getReleaseHighlight(options = {}) {
20675
+ const env = options.env ?? process.env;
20676
+ if (env.HB_SDK_NO_UPDATE_CHECK === '1' || env.CI === 'true') {
20677
+ return null;
20678
+ }
20679
+ const now = options.now?.() ?? new Date();
20680
+ const cacheFile = options.cacheFile ?? path.join(paths$1.cache, RELEASE_HIGHLIGHT_CACHE_FILE);
20681
+ let cache = await readFreshCache(cacheFile, now);
20682
+ if (!cache) {
20683
+ let release;
20684
+ try {
20685
+ release = await fetchLatestRelease(options);
20686
+ }
20687
+ catch {
20688
+ // 与原 npm 检查一致:失败也缓存本次检查时间,24 小时后再检查。
20689
+ }
20690
+ cache = {
20691
+ version: RELEASE_HIGHLIGHT_CACHE_VERSION,
20692
+ checkedAt: now.toISOString(),
20693
+ ...(release ? { release } : {}),
20694
+ };
20695
+ await writeCache(cacheFile, cache).catch(() => undefined);
20696
+ }
20697
+ const notice = createNotice(cache.release);
20698
+ if (!notice)
20699
+ return null;
20700
+ return await isReleaseHighlightSuppressed(notice.version, options) ? null : notice;
20701
+ }
20702
+ function formatReleaseHighlight(notice, useColor = false, currentVersion) {
20703
+ const label = currentVersion && semverExports.valid(currentVersion) && semverExports.valid(notice.version) && semverExports.gt(currentVersion, notice.version)
20704
+ ? '行为变更,已升级版本请核对' : '行为变更,请关注';
20705
+ const colors = pc.createColors(useColor);
20706
+ const divider = colors.yellow('─'.repeat(40));
20707
+ return [
20708
+ '',
20709
+ divider,
20710
+ colors.bold(colors.yellow(`⚠ hb-sdk ${notice.version} · ${label}`)),
20711
+ '',
20712
+ plainNoticeText(cleanTerminalText(notice.text)),
20713
+ colors.cyan(`详情:${cleanTerminalText(notice.url)}`),
20714
+ divider,
20715
+ ].join('\n');
20716
+ }
20717
+ function formatReleaseHighlightPrompt(useColor = false) {
20718
+ const colors = pc.createColors(useColor);
20719
+ return `${colors.bold(colors.green('[y + 回车]'))} 知道了,此版本公告不再提醒\n${colors.bold('[直接回车]')} 继续,今天不再提醒\n请选择:`;
20720
+ }
20721
+ function createNotice(release) {
20722
+ if (!release?.body.trim())
20723
+ return null;
20724
+ return { version: release.version, text: release.body, url: release.url };
20725
+ }
20726
+ async function fetchLatestRelease(options) {
20727
+ const fetchImpl = options.fetchImpl ?? fetch;
20728
+ const controller = new AbortController();
20729
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? DEFAULT_TIMEOUT_MS$1);
20730
+ try {
20731
+ const response = await fetchImpl(options.updatesUrl ?? UPDATES_URL, {
20732
+ headers: {
20733
+ accept: 'application/json',
20734
+ },
20735
+ signal: controller.signal,
20736
+ });
20737
+ if (response.status === 404)
20738
+ return undefined;
20739
+ if (!response.ok) {
20740
+ throw new Error(`hb-sdk updates returned ${response.status}`);
20741
+ }
20742
+ return parseLatestRelease(await response.json());
20743
+ }
20744
+ finally {
20745
+ clearTimeout(timeout);
20746
+ }
20747
+ }
20748
+ function parseLatestRelease(payload) {
20749
+ if (!isRecord(payload) || typeof payload.version !== 'string' || !/^\d+\.\d+\.\d+$/.test(payload.version) ||
20750
+ typeof payload.date !== 'string' || typeof payload.body !== 'string' || typeof payload.url !== 'string') {
20751
+ throw new Error('hb-sdk CDN notice has invalid content');
20752
+ }
20753
+ const url = new URL(payload.url);
20754
+ if (url.origin !== 'https://docs.xiaoheihe.cn' || !url.pathname.startsWith('/hb_sdk/') ||
20755
+ url.username || url.password || /[\x00-\x1f\x7f-\x9f]/.test(payload.url)) {
20756
+ throw new Error('hb-sdk CDN notice has invalid URL');
20757
+ }
20758
+ return { version: payload.version, date: payload.date, body: cleanTerminalText(payload.body), url: url.href };
20759
+ }
20760
+ async function readFreshCache(cacheFile, now) {
20761
+ try {
20762
+ const parsed = JSON.parse(await fs$2.readFile(cacheFile, 'utf8'));
20763
+ if (parsed.version !== RELEASE_HIGHLIGHT_CACHE_VERSION || !isUpdateCheckCacheFresh(parsed.checkedAt, now)) {
20764
+ return null;
20765
+ }
20766
+ return {
20767
+ ...parsed,
20768
+ ...(parsed.release ? { release: parseLatestRelease(parsed.release) } : {}),
20769
+ };
20770
+ }
20771
+ catch {
20772
+ return null;
20773
+ }
20774
+ }
20775
+ async function writeCache(cacheFile, cache) {
20776
+ await fs$2.mkdir(path.dirname(cacheFile), { recursive: true });
20777
+ await fs$2.writeFile(cacheFile, JSON.stringify(cache, null, 2), 'utf8');
20778
+ }
20779
+ function isRecord(value) {
20780
+ return typeof value === 'object' && value !== null;
20781
+ }
20782
+ function dismissalFile(options) {
20783
+ return options.dismissedFile ?? path.join(paths$1.config, 'release-highlight-dismissed.json');
20784
+ }
20785
+ async function readState(options) {
20786
+ try {
20787
+ const data = JSON.parse(await fs$2.readFile(dismissalFile(options), 'utf8'));
20788
+ if (isRecord(data) && data.version === 1 && Array.isArray(data.dismissedVersions) && isRecord(data.lastShownDates)) {
20789
+ return {
20790
+ version: 1,
20791
+ dismissedVersions: data.dismissedVersions.filter((value) => typeof value === 'string'),
20792
+ lastShownDates: Object.fromEntries(Object.entries(data.lastShownDates).filter((entry) => typeof entry[1] === 'string')),
20793
+ };
20794
+ }
20795
+ }
20796
+ catch {
20797
+ // 配置缺失或损坏时按首次提醒处理,不影响主命令。
20798
+ }
20799
+ return { version: 1, dismissedVersions: [], lastShownDates: {} };
20800
+ }
20801
+ async function dismissReleaseHighlight(version, options = {}) {
20802
+ await updateState(options, (state) => {
20803
+ state.dismissedVersions = [...new Set([...state.dismissedVersions, version])];
20804
+ });
20805
+ }
20806
+ async function recordReleaseHighlightShown(version, options) {
20807
+ try {
20808
+ return await updateState(options, (state) => {
20809
+ const date = localDate(options.now?.() ?? new Date());
20810
+ if (state.dismissedVersions.includes(version) || state.lastShownDates[version] === date)
20811
+ return false;
20812
+ state.lastShownDates[version] = date;
20813
+ return true;
20814
+ });
20815
+ }
20816
+ catch {
20817
+ // 无法记录时仍允许展示;主命令不依赖本机配置可写。
20818
+ return true;
20819
+ }
20820
+ }
20821
+ async function updateState(options, update) {
20822
+ const deadline = Date.now() + 2000;
20823
+ let lock;
20824
+ while (true) {
20825
+ try {
20826
+ lock = await acquireLocalFileLock(dismissalFile(options));
20827
+ break;
20828
+ }
20829
+ catch (error) {
20830
+ if (!(error instanceof DeployLockConflictError) || Date.now() >= deadline)
20831
+ throw error;
20832
+ await promises$1.setTimeout(20);
20833
+ }
20834
+ }
20835
+ try {
20836
+ const state = await readState(options);
20837
+ const result = update(state);
20838
+ await writeState(state, options);
20839
+ return result;
20840
+ }
20841
+ finally {
20842
+ await lock.release().catch(() => undefined);
20843
+ }
20844
+ }
20845
+ function localDate(date) {
20846
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
20847
+ }
20848
+ async function writeState(state, options) {
20849
+ const file = dismissalFile(options);
20850
+ await fs$2.mkdir(path.dirname(file), { recursive: true });
20851
+ const temporary = `${file}.${process.pid}.${node_crypto.randomUUID()}.tmp`;
20852
+ try {
20853
+ await fs$2.writeFile(temporary, JSON.stringify(state), 'utf8');
20854
+ await fs$2.rename(temporary, file);
20855
+ }
20856
+ finally {
20857
+ await fs$2.unlink(temporary).catch(() => undefined);
20858
+ }
20859
+ }
20860
+ async function promptDismiss(useColor) {
20861
+ const prompt = promises.createInterface({ input: process.stdin, output: process.stderr });
20862
+ const controller = new AbortController();
20863
+ const cancel = () => controller.abort();
20864
+ prompt.once('SIGINT', cancel);
20865
+ prompt.once('close', cancel);
20866
+ process.once('SIGINT', cancel);
20867
+ try {
20868
+ const answer = await prompt.question(formatReleaseHighlightPrompt(useColor), { signal: controller.signal });
20869
+ return answer.trim().toLowerCase() === 'y';
20870
+ }
20871
+ catch (error) {
20872
+ if (controller.signal.aborted)
20873
+ throw new CommanderError(130, 'hb-sdk.cancelled', '已取消');
20874
+ throw error;
20875
+ }
20876
+ finally {
20877
+ process.removeListener('SIGINT', cancel);
20878
+ prompt.removeListener('SIGINT', cancel);
20879
+ prompt.removeListener('close', cancel);
20880
+ prompt.close();
20881
+ }
20882
+ }
20883
+ function cleanTerminalText(text) {
20884
+ // 去除 ANSI/OSC 序列及其他终端控制字符;换行和制表符保留给摘要折叠。
20885
+ return text.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, '')
20886
+ .replace(/(?:\x1b\[|\x9b)[0-?]*[ -/]*[@-~]/g, '')
20887
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, '');
20888
+ }
20889
+ /** 终端不渲染 Markdown:去掉标记、链接保留地址;篇幅由 notices 撰写者控制,这里不截断。 */
20890
+ function plainNoticeText(markdown) {
20891
+ return markdown
20892
+ .replace(/^[ \t]*(```|~~~).*\n?/gm, '')
20893
+ .replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, '$1($2)')
20894
+ .replace(/`([^`]+)`/g, '$1')
20895
+ .replace(/\*\*([^*]+)\*\*/g, '$1')
20896
+ .replace(/^#{1,6}[ \t]+/gm, '')
20897
+ .trim();
20898
+ }
20899
+ /** 已确认或当天已经展示的重点公告不重复输出。 */
20900
+ async function isReleaseHighlightSuppressed(version, options = {}) {
20901
+ const state = await readState(options);
20902
+ return state.dismissedVersions.includes(version) || state.lastShownDates[version] === localDate(options.now?.() ?? new Date());
20903
+ }
20904
+ /** 普通升级提示仅按当天已展示的公告去重,确认公告不影响后续升级提醒。 */
20905
+ async function isReleaseHighlightShownToday(version, options = {}) {
20906
+ return (await readState(options)).lastShownDates[version] === localDate(options.now?.() ?? new Date());
20907
+ }
20908
+
20452
20909
  const HB_SDK_PACKAGE_NAME = '@heybox/hb-sdk';
20453
20910
  const HB_SDK_SKILL_NAME = 'hb-sdk';
20454
20911
  /**
@@ -20470,13 +20927,12 @@ function createSkillContentHash(fileEntries) {
20470
20927
  }
20471
20928
 
20472
20929
  const UPDATE_CHECK_CACHE_VERSION = 1;
20473
- const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
20474
20930
  const DEFAULT_TIMEOUT_MS = 1500;
20475
20931
  const UPDATE_CHECK_CACHE_FILE = 'update-check.json';
20476
20932
  const NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(HB_SDK_PACKAGE_NAME)}`;
20477
20933
  const PUBLIC_CHANGELOG_URL = 'https://docs.xiaoheihe.cn/hb_sdk/changelog/';
20478
20934
  const paths = envPaths('hb-sdk', { suffix: '' });
20479
- const PACKAGE_JSON_CANDIDATES$1 = [
20935
+ const PACKAGE_JSON_CANDIDATES = [
20480
20936
  path.resolve(__dirname, '..', 'package.json'),
20481
20937
  path.resolve(__dirname, '..', '..', 'package.json'),
20482
20938
  path.resolve(__dirname, '..', '..', '..', 'package.json'),
@@ -20484,7 +20940,7 @@ const PACKAGE_JSON_CANDIDATES$1 = [
20484
20940
  async function printUpdateReminder(options = {}) {
20485
20941
  try {
20486
20942
  const reminder = await getUpdateReminder(options);
20487
- if (!reminder) {
20943
+ if (!reminder || await isReleaseHighlightShownToday(reminder.latestVersion, { dismissedFile: options.dismissedFile, now: options.now })) {
20488
20944
  return;
20489
20945
  }
20490
20946
  const logger = options.logger ??
@@ -20538,7 +20994,7 @@ async function getUpdateReminder(options = {}) {
20538
20994
  return null;
20539
20995
  }
20540
20996
  const now = options.now?.() ?? new Date();
20541
- const currentVersion = options.currentVersion ?? (await readCurrentSdkVersion$1(options.packageJsonFiles));
20997
+ const currentVersion = options.currentVersion ?? (await readCurrentSdkVersion(options.packageJsonFiles));
20542
20998
  const cached = options.forceRefresh ? null : await readFreshUpdateCheckCache(getUpdateCheckCacheFilePath(options), now);
20543
20999
  if (cached) {
20544
21000
  return createUpdateReminder(currentVersion, cached.latestVersion);
@@ -20596,14 +21052,13 @@ async function readFreshUpdateCheckCache(cacheFile, now) {
20596
21052
  if (!cache) {
20597
21053
  return null;
20598
21054
  }
20599
- const checkedAt = Date.parse(cache.checkedAt);
20600
- if (!Number.isFinite(checkedAt) || now.getTime() - checkedAt >= UPDATE_CHECK_TTL_MS) {
21055
+ if (!isUpdateCheckCacheFresh(cache.checkedAt, now)) {
20601
21056
  return null;
20602
21057
  }
20603
21058
  return cache;
20604
21059
  }
20605
21060
  async function readUpdateCheckCache(cacheFile) {
20606
- if (!(await pathExists$1(cacheFile))) {
21061
+ if (!(await pathExists(cacheFile))) {
20607
21062
  return null;
20608
21063
  }
20609
21064
  try {
@@ -20651,9 +21106,9 @@ async function fetchLatestVersion(options) {
20651
21106
  clearTimeout(timeout);
20652
21107
  }
20653
21108
  }
20654
- async function readCurrentSdkVersion$1(packageJsonCandidates = PACKAGE_JSON_CANDIDATES$1) {
21109
+ async function readCurrentSdkVersion(packageJsonCandidates = PACKAGE_JSON_CANDIDATES) {
20655
21110
  for (const candidate of packageJsonCandidates) {
20656
- if (!(await pathExists$1(candidate))) {
21111
+ if (!(await pathExists(candidate))) {
20657
21112
  continue;
20658
21113
  }
20659
21114
  const packageJson = JSON.parse(await fs$2.readFile(candidate, 'utf8'));
@@ -20739,7 +21194,7 @@ function comparePrereleaseIdentifier(left, right) {
20739
21194
  function isNumericPrereleaseIdentifier(value) {
20740
21195
  return /^\d+$/.test(value);
20741
21196
  }
20742
- async function pathExists$1(filePath) {
21197
+ async function pathExists(filePath) {
20743
21198
  try {
20744
21199
  await fs$2.access(filePath, fs$3.constants.F_OK);
20745
21200
  return true;
@@ -20899,41 +21354,6 @@ function readEnvNameArgFromArgv(argv) {
20899
21354
  return undefined;
20900
21355
  }
20901
21356
 
20902
- const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
20903
- const BUILT_CLI_VERSION = '0.9.5-alpha.0';
20904
- const PACKAGE_JSON_CANDIDATES = [
20905
- path.resolve(__dirname, '..', '..', 'package.json'),
20906
- path.resolve(__dirname, '..', 'package.json'),
20907
- path.resolve(__dirname, '..', '..', '..', 'package.json'),
20908
- ];
20909
- function getCliVersion(packageJsonCandidates = PACKAGE_JSON_CANDIDATES) {
20910
- if (BUILT_CLI_VERSION !== CLI_VERSION_PLACEHOLDER) {
20911
- return BUILT_CLI_VERSION;
20912
- }
20913
- return readCurrentSdkVersion(packageJsonCandidates);
20914
- }
20915
- function readCurrentSdkVersion(packageJsonCandidates) {
20916
- for (const candidate of packageJsonCandidates) {
20917
- if (!pathExists(candidate)) {
20918
- continue;
20919
- }
20920
- const packageJson = JSON.parse(fs$3.readFileSync(candidate, 'utf8'));
20921
- if (typeof packageJson.version === 'string' && packageJson.version) {
20922
- return packageJson.version;
20923
- }
20924
- }
20925
- throw new Error('未能读取 @heybox/hb-sdk 当前版本号');
20926
- }
20927
- function pathExists(filePath) {
20928
- try {
20929
- fs$3.accessSync(filePath, fs$3.constants.F_OK);
20930
- return true;
20931
- }
20932
- catch {
20933
- return false;
20934
- }
20935
- }
20936
-
20937
21357
  async function runCli(options = {}) {
20938
21358
  const processLike = options.process ?? process;
20939
21359
  const argv = options.argv ?? process.argv;
@@ -20960,6 +21380,7 @@ function createCliProgram(overrides = {}) {
20960
21380
  clearLoginStatus: defaultClearLoginStatus,
20961
21381
  loginToHeybox: defaultLoginToHeybox,
20962
21382
  printLoginStatus: defaultPrintLoginStatus,
21383
+ printReleaseHighlight: printReleaseHighlight,
20963
21384
  printUpdateReminder: printUpdateReminder,
20964
21385
  runBuildCommand: defaultRunBuildCommand,
20965
21386
  runCreateCommand: defaultRunCreateCommand,
@@ -20982,6 +21403,18 @@ function createCliProgram(overrides = {}) {
20982
21403
  .showHelpAfterError()
20983
21404
  .exitOverride();
20984
21405
  installVersionUpdateReminder(program, handlers.printUpdateReminder, resolveLogger);
21406
+ program.hook('preAction', async (_program, command) => {
21407
+ if (readCommandOptionsWithAncestors(command).json)
21408
+ return;
21409
+ try {
21410
+ await handlers.printReleaseHighlight({ logger: resolveLogger(command) });
21411
+ }
21412
+ catch (error) {
21413
+ if (error instanceof CommanderError)
21414
+ throw error;
21415
+ // 公告获取或展示失败不能阻断命令;交互环境判断由展示模块统一执行。
21416
+ }
21417
+ });
20985
21418
  addVerboseOption(program.command('create').description('创建外部小程序项目开发模板').argument('<project-name>', '项目目录名,例如 my-miniapp')).action(withUpdateReminder(async (projectName, _options, command) => {
20986
21419
  const logger = resolveLogger(command);
20987
21420
  await handlers.runCreateCommand(projectName, { logger });
@@ -21284,39 +21717,39 @@ function createCommandLoggerResolver(options) {
21284
21717
  };
21285
21718
  }
21286
21719
  const defaultClearLoginStatus = async (...args) => {
21287
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-DqP3MO5K.cjs'); });
21720
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-Bk3T3PMe.cjs'); });
21288
21721
  return clearLoginStatus(...args);
21289
21722
  };
21290
21723
  const defaultLoginToHeybox = async (...args) => {
21291
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-DqP3MO5K.cjs'); });
21724
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-Bk3T3PMe.cjs'); });
21292
21725
  return loginToHeybox(...args);
21293
21726
  };
21294
21727
  const defaultPrintLoginStatus = async (...args) => {
21295
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-DqP3MO5K.cjs'); });
21728
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-Bk3T3PMe.cjs'); });
21296
21729
  return printLoginStatus(...args);
21297
21730
  };
21298
21731
  const defaultRunBuildCommand = async (...args) => {
21299
- const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-D7fJ6BEA.cjs'); });
21732
+ const { runBuildCommand } = await Promise.resolve().then(function () { return require('./build-D6tP7Uje.cjs'); });
21300
21733
  return runBuildCommand(...args);
21301
21734
  };
21302
21735
  const defaultRunCreateCommand = async (...args) => {
21303
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-B-Jsz3ik.cjs'); });
21736
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-BBXC3wLI.cjs'); });
21304
21737
  return runCreateCommand(...args);
21305
21738
  };
21306
21739
  const defaultRunDevCommand = async (...args) => {
21307
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-y8113QN9.cjs'); }).then(function (n) { return n.dev; });
21740
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-XoWrqt1g.cjs'); }).then(function (n) { return n.dev; });
21308
21741
  return runDevCommand(...args);
21309
21742
  };
21310
21743
  const defaultRunDoctorCommand = async (...args) => {
21311
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-BhKqJsAC.cjs'); });
21744
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-Cuc3EQQ8.cjs'); });
21312
21745
  return runDoctorCommand(...args);
21313
21746
  };
21314
21747
  const defaultRunSkillInstallCommand = async (...args) => {
21315
- const { runSkillInstallCommand } = await Promise.resolve().then(function () { return require('./skill-Fhveb4OH.cjs'); });
21748
+ const { runSkillInstallCommand } = await Promise.resolve().then(function () { return require('./skill-BGxlDR-g.cjs'); });
21316
21749
  return runSkillInstallCommand(...args);
21317
21750
  };
21318
21751
  const defaultRunRemoteCommand = async (...args) => {
21319
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-Bx-Pz3E9.cjs'); });
21752
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-Dfg2HLIt.cjs'); });
21320
21753
  return runRemoteCommand(...args);
21321
21754
  };
21322
21755
  function resolveStandaloneLogger(options, verbose) {
@@ -21408,13 +21841,15 @@ function parseNonNegativeInteger(value) {
21408
21841
  return parsed;
21409
21842
  }
21410
21843
  const defaultRunGameSearchCommand = async (...args) => {
21411
- const { runGameSearchCommand } = await Promise.resolve().then(function () { return require('./games-DQx46pWD.cjs'); });
21844
+ const { runGameSearchCommand } = await Promise.resolve().then(function () { return require('./games-CoddgAux.cjs'); });
21412
21845
  return runGameSearchCommand(...args);
21413
21846
  };
21414
21847
 
21415
21848
  exports.CliError = CliError;
21849
+ exports.DEPLOY_LOCKED_MESSAGE = DEPLOY_LOCKED_MESSAGE;
21416
21850
  exports.HB_SDK_PACKAGE_NAME = HB_SDK_PACKAGE_NAME;
21417
21851
  exports.HB_SDK_SKILL_NAME = HB_SDK_SKILL_NAME;
21852
+ exports.acquireDeployLock = acquireDeployLock;
21418
21853
  exports.applyMiniProgramServiceTagIfNeeded = applyMiniProgramServiceTagIfNeeded;
21419
21854
  exports.clearHeyboxAuthSession = clearHeyboxAuthSession;
21420
21855
  exports.commonjsGlobal = commonjsGlobal;
@@ -21451,4 +21886,5 @@ exports.resolveHeyboxOpenPlatformBaseUrl = resolveHeyboxOpenPlatformBaseUrl;
21451
21886
  exports.runCli = runCli;
21452
21887
  exports.semverExports = semverExports;
21453
21888
  exports.setSelectedDeveloperEntitySnapshot = setSelectedDeveloperEntitySnapshot;
21889
+ exports.withDeployLock = withDeployLock;
21454
21890
  exports.writeHeyboxAuthSession = writeHeyboxAuthSession;