@icyfenix-dmla/cli 2026.5.2-2022 → 2026.5.2-2114

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icyfenix-dmla/cli",
3
- "version": "2026.5.2-2022",
3
+ "version": "2026.5.2-2114",
4
4
  "description": "DMLA 沙箱服务命令行工具",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -49,6 +49,16 @@ const DATASETS = [
49
49
  }
50
50
  ]
51
51
 
52
+ /**
53
+ * 检查是否是用户取消操作(ESC 或 Ctrl+C)
54
+ * enquirer 可能抛出空字符串错误或包含 'cancel' 的消息
55
+ */
56
+ function isUserCancel(error) {
57
+ return !error.message ||
58
+ error.message === '' ||
59
+ error.message.includes('cancel')
60
+ }
61
+
52
62
  /**
53
63
  * 显示 Banner
54
64
  */
@@ -401,19 +411,16 @@ async function downloadDatasets() {
401
411
  // 构建选项列表
402
412
  const choices = DATASETS.map((dataset, index) => {
403
413
  const downloaded = isDatasetDownloaded(dataPath, dataset.id)
404
- const isMnist = dataset.id === 'mnist'
405
414
 
406
415
  let message = `${dataset.name} (${dataset.size})`
407
416
  if (downloaded) {
408
417
  message += ' [已下载]'
409
- } else if (isMnist) {
410
- message += ' [训练时自动下载]'
411
418
  }
412
419
 
413
420
  return {
414
421
  name: index.toString(),
415
422
  message,
416
- disabled: downloaded || isMnist
423
+ disabled: downloaded
417
424
  }
418
425
  })
419
426
 
@@ -428,7 +435,7 @@ async function downloadDatasets() {
428
435
  message: '选择要下载的数据集',
429
436
  choices,
430
437
  hint: '空格选择,回车确认下载',
431
- warn: '已下载或自动下载类型'
438
+ warn: '已下载'
432
439
  })
433
440
 
434
441
  if (!selected || selected.length === 0) {
@@ -444,12 +451,6 @@ async function downloadDatasets() {
444
451
  console.log()
445
452
  console.log(chalk.cyan(`────────────────────────────────────`))
446
453
 
447
- // MNIST 特殊处理
448
- if (dataset.id === 'mnist') {
449
- console.log(chalk.yellow('MNIST 数据集将在训练时通过 torchvision 自动下载'))
450
- continue
451
- }
452
-
453
454
  // 检查是否已下载
454
455
  if (isDatasetDownloaded(dataPath, dataset.id)) {
455
456
  console.log(chalk.yellow(`${dataset.name} 已下载,跳过`))
@@ -464,7 +465,7 @@ async function downloadDatasets() {
464
465
  console.log(chalk.green('所有选中的数据集已处理完成'))
465
466
  } catch (error) {
466
467
  // 用户按 ESC 或 Ctrl+C 取消
467
- if (error.message && error.message.includes('cancel')) {
468
+ if (isUserCancel(error)) {
468
469
  console.log(chalk.gray('返回上一级'))
469
470
  return
470
471
  }
@@ -624,49 +625,101 @@ export async function runDataTUI() {
624
625
  console.log(chalk.yellow(`数据目录不存在: ${dataPath}`))
625
626
  console.log()
626
627
 
627
- const { create } = await prompt({
628
- type: 'confirm',
629
- name: 'create',
630
- message: '是否创建数据目录?',
631
- initial: true
632
- })
628
+ try {
629
+ const { create } = await prompt({
630
+ type: 'confirm',
631
+ name: 'create',
632
+ message: '是否创建数据目录?',
633
+ initial: true
634
+ })
633
635
 
634
- if (create) {
635
- ensureDataDirStructure(dataPath)
636
- console.log(chalk.green(`数据目录已创建: ${dataPath}`))
636
+ if (create) {
637
+ ensureDataDirStructure(dataPath)
638
+ console.log(chalk.green(`数据目录已创建: ${dataPath}`))
639
+ }
640
+ } catch (error) {
641
+ if (isUserCancel(error)) {
642
+ console.log(chalk.gray('已退出数据管理'))
643
+ console.log()
644
+ return
645
+ }
646
+ throw error
637
647
  }
638
648
  }
639
649
 
640
650
  // 主循环
641
651
  while (true) {
642
652
  console.log()
643
- const action = await showMainMenu(dataPath)
644
-
645
- switch (action) {
646
- case 1:
647
- await mountPath()
648
- break
649
- case 2:
650
- await downloadDatasets()
651
- break
652
- case 3:
653
- listDatasets()
654
- break
655
- case 4:
656
- await clearData()
657
- break
658
- case 5:
659
- await removeData()
660
- break
661
- case 6:
653
+ try {
654
+ const action = await showMainMenu(dataPath)
655
+
656
+ switch (action) {
657
+ case 1:
658
+ try {
659
+ await mountPath()
660
+ } catch (error) {
661
+ if (isUserCancel(error)) {
662
+ console.log(chalk.gray('返回主菜单'))
663
+ } else {
664
+ throw error
665
+ }
666
+ }
667
+ break
668
+ case 2:
669
+ try {
670
+ await downloadDatasets()
671
+ } catch (error) {
672
+ if (isUserCancel(error)) {
673
+ console.log(chalk.gray('返回主菜单'))
674
+ } else {
675
+ throw error
676
+ }
677
+ }
678
+ break
679
+ case 3:
680
+ listDatasets()
681
+ break
682
+ case 4:
683
+ try {
684
+ await clearData()
685
+ } catch (error) {
686
+ if (isUserCancel(error)) {
687
+ console.log(chalk.gray('返回主菜单'))
688
+ } else {
689
+ throw error
690
+ }
691
+ }
692
+ break
693
+ case 5:
694
+ try {
695
+ await removeData()
696
+ } catch (error) {
697
+ if (isUserCancel(error)) {
698
+ console.log(chalk.gray('返回主菜单'))
699
+ } else {
700
+ throw error
701
+ }
702
+ }
703
+ break
704
+ case 6:
705
+ console.log()
706
+ console.log(chalk.gray('已退出数据管理'))
707
+ console.log()
708
+ return
709
+ }
710
+
711
+ // 刷新路径(可能在操作中修改了)
712
+ dataPath = getDataVolumePath()
713
+ } catch (error) {
714
+ // 主菜单按 ESC 取消 -> 退出程序
715
+ if (isUserCancel(error)) {
662
716
  console.log()
663
717
  console.log(chalk.gray('已退出数据管理'))
664
718
  console.log()
665
719
  return
720
+ }
721
+ throw error
666
722
  }
667
-
668
- // 刷新路径(可能在操作中修改了)
669
- dataPath = getDataVolumePath()
670
723
  }
671
724
  }
672
725