@hongmaple0820/scale-engine 0.40.0 → 0.40.1

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/dist/api/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // SCALE Engine — CLI 入口 (W6 完整实现)
3
3
  // 所有 Hook 调用入口: session/gate/create/list/transition/context
4
4
  import { defineCommand, runMain } from 'citty';
5
+ import { createInterface } from 'node:readline';
5
6
  import { EventBus } from '../core/eventBus.js';
6
7
  import { SQLiteArtifactStore } from '../artifact/sqliteStore.js';
7
8
  import { FSM } from '../artifact/fsm.js';
@@ -2848,6 +2849,7 @@ const setup = defineCommand({
2848
2849
  scaleDir: SCALE_DIR,
2849
2850
  packIds: explicitPacks.length > 0 ? uniqueStrings([...recommendedPacks, ...explicitPacks]) : recommendedPacks,
2850
2851
  includeIds: parseCommaList(args.include),
2852
+ promptPacks: explicitPacks.length === 0 && recommendedPacks.length === 0 && !args.include,
2851
2853
  apply: isTruthyFlag(args.apply),
2852
2854
  yes: isTruthyFlag(args.yes),
2853
2855
  interactive: isTruthyFlag(args.interactive) && !isTruthyFlag(args.json),
@@ -2859,30 +2861,33 @@ const setup = defineCommand({
2859
2861
  allowExternalWrite: isTruthyFlag(args['allow-external-write']) ? true : undefined,
2860
2862
  promptLanguage: isTruthyFlag(args.interactive) && !args.lang,
2861
2863
  });
2864
+ if (!args.json) {
2865
+ console.log(lang === 'zh' ? '\nSCALE 交互式安装' : '\nSCALE Interactive Setup');
2866
+ console.log(lang === 'zh'
2867
+ ? ` 已执行安装: ${report.applied ? '是' : '否'}`
2868
+ : ` Applied: ${report.applied}`);
2869
+ if (report.memoryProviderSwitch) {
2870
+ const switched = report.memoryProviderSwitch;
2871
+ console.log(lang === 'zh' ? ' 记忆供应商:' : ' Memory provider:');
2872
+ console.log(` provider=${switched.provider}; mode=${switched.mode}; config=${switched.path}`);
2873
+ console.log(` order=${switched.previousOrder.join(' -> ')} => ${switched.nextOrder.join(' -> ')}`);
2874
+ if (switched.providerStatus) {
2875
+ console.log(` status=${switched.providerStatus.available ? 'available' : 'not-ready'}; reason=${switched.providerStatus.reason}`);
2876
+ }
2877
+ for (const warning of switched.warnings)
2878
+ console.log(lang === 'zh' ? ` [警告] ${warning}` : ` [WARN] ${warning}`);
2879
+ }
2880
+ console.log(renderDependencyBootstrapReport(report.final, lang));
2881
+ if (!report.ok)
2882
+ process.exitCode = 1;
2883
+ return;
2884
+ }
2862
2885
  if (args.json) {
2863
2886
  console.log(JSON.stringify(report, null, 2));
2864
2887
  if (!report.ok)
2865
2888
  process.exitCode = 1;
2866
2889
  return;
2867
2890
  }
2868
- console.log(lang === 'zh' ? '\nSCALE 交互式安装' : '\nSCALE Interactive Setup');
2869
- console.log(lang === 'zh'
2870
- ? ` 已执行安装: ${report.applied ? '是' : '否'}`
2871
- : ` Applied: ${report.applied}`);
2872
- if (report.memoryProviderSwitch) {
2873
- const switched = report.memoryProviderSwitch;
2874
- console.log(lang === 'zh' ? ' 记忆供应商:' : ' Memory provider:');
2875
- console.log(` provider=${switched.provider}; mode=${switched.mode}; config=${switched.path}`);
2876
- console.log(` order=${switched.previousOrder.join(' -> ')} => ${switched.nextOrder.join(' -> ')}`);
2877
- if (switched.providerStatus) {
2878
- console.log(` status=${switched.providerStatus.available ? 'available' : 'not-ready'}; reason=${switched.providerStatus.reason}`);
2879
- }
2880
- for (const warning of switched.warnings)
2881
- console.log(lang === 'zh' ? ` [警告] ${warning}` : ` [WARN] ${warning}`);
2882
- }
2883
- console.log(renderDependencyBootstrapReport(report.final, lang));
2884
- if (!report.ok)
2885
- process.exitCode = 1;
2886
2891
  },
2887
2892
  });
2888
2893
  // config command — Configuration profile management
@@ -3635,9 +3640,125 @@ const upgradeRollback = defineCommand({
3635
3640
  },
3636
3641
  });
3637
3642
  const upgrade = defineCommand({
3638
- meta: { name: 'upgrade', description: 'SCALE 工作流、模板、skills、MCP、CLI 工具的安全升级规划 / Safe update planning for workflow assets' },
3643
+ meta: { name: 'upgrade', description: 'SCALE 工作流、模板、skills、MCP、CLI 工具的安全升级向导 / Safe update wizard for workflow assets' },
3644
+ args: {
3645
+ dir: { type: 'string', default: PROJECT_DIR, description: '项目目录 / Project directory' },
3646
+ 'target-version': { type: 'string', description: '目标 SCALE Engine 版本,默认使用当前 CLI 版本 / Target SCALE Engine version' },
3647
+ apply: { type: 'boolean', default: false, description: '直接应用安全升级计划 / Apply safe upgrade plan' },
3648
+ yes: { type: 'boolean', default: false, description: '非交互确认 / Confirm without prompting' },
3649
+ html: { type: 'boolean', default: true, description: '写入 HTML 升级计划 / Write HTML plan' },
3650
+ interactive: { type: 'boolean', default: true, description: '启用升级向导交互 / Enable upgrade wizard prompts' },
3651
+ lang: { type: 'string', default: 'zh', description: '输出语言 zh/en / Output language' },
3652
+ json: { type: 'boolean', default: false, description: '输出 JSON / Print JSON output' },
3653
+ },
3639
3654
  subCommands: { check: upgradeCheck, plan: upgradePlan, apply: upgradeApply, rollback: upgradeRollback },
3655
+ async run({ args }) {
3656
+ if (isUpgradeSubcommandInvocation(process.argv))
3657
+ return;
3658
+ const lang = normalizeLangArg(args.lang);
3659
+ const projectDir = resolve(String(args.dir ?? PROJECT_DIR));
3660
+ const scaleDir = resolveScaleDirForProject(projectDir);
3661
+ const targetScaleVersion = args['target-version'] ? String(args['target-version']) : undefined;
3662
+ const plan = createUpgradePlanReport({ projectDir, scaleDir, targetScaleVersion });
3663
+ const htmlPath = args.html ? writeUpgradePlanHtml(plan, undefined, lang) : undefined;
3664
+ const canApply = plan.applyMode === 'safe' && plan.blockers.length === 0;
3665
+ const interactive = isTruthyFlag(args.interactive) && !args.json && Boolean(process.stdin.isTTY) && !isTruthyFlag(args.yes);
3666
+ let apply = isTruthyFlag(args.apply) || isTruthyFlag(args.yes);
3667
+ let cancelled = false;
3668
+ if (interactive && canApply && !apply) {
3669
+ const answer = await askUpgradeWizardQuestion(lang === 'zh'
3670
+ ? '发现可安全应用的升级计划。现在应用吗?1=仅生成计划 2=应用 3=取消,默认 1: '
3671
+ : 'Safe upgrade plan found. Apply now? 1=plan only 2=apply 3=cancel, default 1: ');
3672
+ const normalized = answer.trim().toLowerCase();
3673
+ apply = normalized === '2' || normalized === 'apply' || normalized === 'yes' || normalized === 'y';
3674
+ cancelled = normalized === '3' || normalized === 'cancel' || normalized === 'c';
3675
+ }
3676
+ const applyResult = apply && !cancelled
3677
+ ? applyUpgradePlan({ projectDir, scaleDir, confirm: true })
3678
+ : undefined;
3679
+ const ok = !cancelled && (!applyResult || applyResult.ok);
3680
+ const report = { ok, cancelled, htmlPath, plan, applyResult };
3681
+ if (args.json) {
3682
+ console.log(JSON.stringify(report, null, 2));
3683
+ if (!ok)
3684
+ process.exitCode = 1;
3685
+ return;
3686
+ }
3687
+ renderUpgradeWizardReport(report, lang);
3688
+ if (!ok)
3689
+ process.exitCode = 1;
3690
+ },
3640
3691
  });
3692
+ async function askUpgradeWizardQuestion(question) {
3693
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3694
+ try {
3695
+ return await new Promise(resolve => rl.question(question, resolve));
3696
+ }
3697
+ finally {
3698
+ rl.close();
3699
+ }
3700
+ }
3701
+ function isUpgradeSubcommandInvocation(argv) {
3702
+ const upgradeIndex = argv.findIndex((value, index) => index > 1 && value === 'upgrade');
3703
+ if (upgradeIndex < 0)
3704
+ return false;
3705
+ const positional = argv.slice(upgradeIndex + 1).find(value => !value.startsWith('-') && !value.includes('='));
3706
+ return positional === 'check' || positional === 'plan' || positional === 'apply' || positional === 'rollback';
3707
+ }
3708
+ function renderUpgradeWizardReport(report, lang) {
3709
+ const plan = report.plan;
3710
+ if (lang === 'zh') {
3711
+ console.log('\nSCALE 升级向导');
3712
+ console.log(` 项目: ${plan.projectDir}`);
3713
+ console.log(` 状态: ${plan.status}`);
3714
+ console.log(` 应用模式: ${plan.applyMode}`);
3715
+ console.log(` 阻塞项: ${plan.blockers.length}`);
3716
+ console.log(` 步骤数: ${plan.steps.length}`);
3717
+ if (report.htmlPath)
3718
+ console.log(` HTML 计划: ${report.htmlPath}`);
3719
+ if (report.cancelled)
3720
+ console.log(' 结果: 已取消');
3721
+ else if (report.applyResult) {
3722
+ console.log(` 结果: ${report.applyResult.applied ? '已应用' : '未应用'}`);
3723
+ console.log(` 原因: ${formatUpgradeApplyReason(report.applyResult.reason, lang)}`);
3724
+ for (const path of report.applyResult.changedFiles)
3725
+ console.log(` 已变更: ${path}`);
3726
+ }
3727
+ else {
3728
+ console.log(' 结果: 已生成计划,未应用变更');
3729
+ }
3730
+ console.log(' 下一步:');
3731
+ for (const command of plan.check.recommendedCommands.slice(0, 5))
3732
+ console.log(` ${formatUpgradeCommand(command, lang)}`);
3733
+ if (plan.blockers.length > 0)
3734
+ console.log(' 先解决阻塞项后再执行 scale upgrade apply --confirm');
3735
+ return;
3736
+ }
3737
+ console.log('\nSCALE Upgrade Wizard');
3738
+ console.log(` Project: ${plan.projectDir}`);
3739
+ console.log(` Status: ${plan.status}`);
3740
+ console.log(` Apply mode: ${plan.applyMode}`);
3741
+ console.log(` Blockers: ${plan.blockers.length}`);
3742
+ console.log(` Steps: ${plan.steps.length}`);
3743
+ if (report.htmlPath)
3744
+ console.log(` HTML plan: ${report.htmlPath}`);
3745
+ if (report.cancelled)
3746
+ console.log(' Result: cancelled');
3747
+ else if (report.applyResult) {
3748
+ console.log(` Result: ${report.applyResult.applied ? 'applied' : 'not applied'}`);
3749
+ console.log(` Reason: ${report.applyResult.reason}`);
3750
+ for (const path of report.applyResult.changedFiles)
3751
+ console.log(` changed: ${path}`);
3752
+ }
3753
+ else {
3754
+ console.log(' Result: plan generated; no changes applied');
3755
+ }
3756
+ console.log(' Next:');
3757
+ for (const command of plan.check.recommendedCommands.slice(0, 5))
3758
+ console.log(` ${formatUpgradeCommand(command, lang)}`);
3759
+ if (plan.blockers.length > 0)
3760
+ console.log(' Resolve blockers before running scale upgrade apply --confirm');
3761
+ }
3641
3762
  function formatUpgradeBlockerMessage(code, fallback, lang) {
3642
3763
  if (lang !== 'zh')
3643
3764
  return fallback;
@@ -6169,5 +6290,19 @@ const main = defineCommand({
6169
6290
  config,
6170
6291
  },
6171
6292
  });
6293
+ normalizeUpgradeRootOptionValues(process.argv);
6172
6294
  runMain(main);
6295
+ function normalizeUpgradeRootOptionValues(argv) {
6296
+ const upgradeIndex = argv.findIndex((value, index) => index > 1 && value === 'upgrade');
6297
+ if (upgradeIndex < 0)
6298
+ return;
6299
+ for (let index = upgradeIndex + 1; index < argv.length - 1; index += 1) {
6300
+ if (!['--dir', '--target-version', '--lang'].includes(argv[index]))
6301
+ continue;
6302
+ const value = argv[index + 1];
6303
+ if (!value || value.startsWith('--'))
6304
+ continue;
6305
+ argv.splice(index, 2, `${argv[index]}=${value}`);
6306
+ }
6307
+ }
6173
6308
  //# sourceMappingURL=cli.js.map