@nick848/sf-cli 1.0.0 → 1.0.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.
package/dist/index.js CHANGED
@@ -374,7 +374,7 @@ var BaseAdapter = class {
374
374
  * 延迟工具函数
375
375
  */
376
376
  delay(ms) {
377
- return new Promise((resolve2) => setTimeout(resolve2, ms));
377
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
378
378
  }
379
379
  };
380
380
 
@@ -5618,8 +5618,8 @@ var CommandParser = class {
5618
5618
  };
5619
5619
  }
5620
5620
  parseAtPath(input) {
5621
- const path11 = input.slice(1).trim();
5622
- if (!path11) {
5621
+ const path13 = input.slice(1).trim();
5622
+ if (!path13) {
5623
5623
  return { success: false, error: "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84" };
5624
5624
  }
5625
5625
  return {
@@ -5627,7 +5627,7 @@ var CommandParser = class {
5627
5627
  command: {
5628
5628
  type: "at" /* AT */,
5629
5629
  raw: input,
5630
- path: path11
5630
+ path: path13
5631
5631
  }
5632
5632
  };
5633
5633
  }
@@ -6471,8 +6471,10 @@ function createSpinner(message) {
6471
6471
  stop: () => process.stdout.write(" ".repeat(message.length + 10) + "\r")
6472
6472
  };
6473
6473
  }
6474
- var CURRENT_VERSION = "1.0.0";
6475
- var PACKAGE_NAME = "sf-cli";
6474
+ var packageJsonPath = path4__namespace.resolve(__dirname, "../../package.json");
6475
+ var packageJson = JSON.parse(fsSync__namespace.readFileSync(packageJsonPath, "utf-8"));
6476
+ var CURRENT_VERSION = packageJson.version;
6477
+ var PACKAGE_NAME = packageJson.name;
6476
6478
  async function handleUpdate(args, ctx) {
6477
6479
  const options = {
6478
6480
  check: args.includes("--check") || args.includes("-c"),
@@ -6499,6 +6501,9 @@ async function checkForUpdates() {
6499
6501
  const latestVersion = await getLatestVersion();
6500
6502
  if (!latestVersion) {
6501
6503
  lines.push(chalk9__default.default.yellow("\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\u4FE1\u606F"));
6504
+ lines.push(chalk9__default.default.gray("\u53EF\u80FD\u539F\u56E0:"));
6505
+ lines.push(chalk9__default.default.gray(" 1. \u5305\u5C1A\u672A\u53D1\u5E03\u5230 npm"));
6506
+ lines.push(chalk9__default.default.gray(" 2. \u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898"));
6502
6507
  return { output: lines.join("\n") };
6503
6508
  }
6504
6509
  lines.push(chalk9__default.default.gray(` \u5F53\u524D\u7248\u672C: v${CURRENT_VERSION}`));
@@ -6517,43 +6522,70 @@ async function checkForUpdates() {
6517
6522
  async function performUpdate(targetVersion) {
6518
6523
  const lines = [];
6519
6524
  lines.push(chalk9__default.default.cyan("\u6B63\u5728\u66F4\u65B0 sf-cli..."));
6525
+ lines.push(chalk9__default.default.gray(` \u5305\u540D: ${PACKAGE_NAME}`));
6526
+ lines.push(chalk9__default.default.gray(` \u5F53\u524D\u7248\u672C: v${CURRENT_VERSION}`));
6520
6527
  try {
6521
6528
  const latestVersion = await getLatestVersion();
6529
+ if (!latestVersion && !targetVersion) {
6530
+ lines.push(chalk9__default.default.yellow("\n\u26A0 \u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\u4FE1\u606F"));
6531
+ lines.push(chalk9__default.default.gray("\n\u53EF\u80FD\u539F\u56E0:"));
6532
+ lines.push(chalk9__default.default.gray(" 1. \u5305\u5C1A\u672A\u53D1\u5E03\u5230 npm"));
6533
+ lines.push(chalk9__default.default.gray(" 2. \u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898"));
6534
+ lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
6535
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
6536
+ return { output: lines.join("\n") };
6537
+ }
6522
6538
  if (latestVersion === CURRENT_VERSION && !targetVersion) {
6523
- lines.push(chalk9__default.default.green("\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0"));
6539
+ lines.push(chalk9__default.default.green("\n\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0"));
6524
6540
  return { output: lines.join("\n") };
6525
6541
  }
6526
6542
  const packageSpec = targetVersion ? `${PACKAGE_NAME}@${targetVersion}` : `${PACKAGE_NAME}@latest`;
6527
6543
  lines.push(chalk9__default.default.gray(` \u5B89\u88C5: ${packageSpec}`));
6528
- await new Promise((resolve2, reject) => {
6544
+ const installResult = await new Promise((resolve4) => {
6529
6545
  const proc = child_process.spawn("npm", ["install", "-g", packageSpec], {
6530
6546
  stdio: "pipe",
6531
6547
  shell: true
6532
6548
  });
6549
+ let output = "";
6550
+ proc.stdout?.on("data", (data) => {
6551
+ output += data.toString();
6552
+ });
6553
+ proc.stderr?.on("data", (data) => {
6554
+ output += data.toString();
6555
+ });
6533
6556
  proc.on("close", (code) => {
6534
- if (code === 0) {
6535
- resolve2();
6536
- } else {
6537
- reject(new Error(`npm install exited with code ${code}`));
6538
- }
6557
+ resolve4({
6558
+ success: code === 0,
6559
+ output
6560
+ });
6539
6561
  });
6540
6562
  proc.on("error", (err) => {
6541
- reject(err);
6563
+ resolve4({
6564
+ success: false,
6565
+ output: err.message
6566
+ });
6542
6567
  });
6543
6568
  });
6544
- lines.push(chalk9__default.default.green("\u2713 \u66F4\u65B0\u5B8C\u6210!"));
6569
+ if (!installResult.success) {
6570
+ lines.push(chalk9__default.default.red("\n\u2717 \u66F4\u65B0\u5931\u8D25"));
6571
+ lines.push(chalk9__default.default.gray(installResult.output));
6572
+ lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
6573
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
6574
+ return { output: lines.join("\n") };
6575
+ }
6576
+ lines.push(chalk9__default.default.green("\n\u2713 \u66F4\u65B0\u5B8C\u6210!"));
6545
6577
  lines.push(chalk9__default.default.gray(` \u65B0\u7248\u672C: v${targetVersion || latestVersion}`));
6546
6578
  lines.push(chalk9__default.default.gray("\n\u8BF7\u91CD\u542F CLI \u4EE5\u4F7F\u7528\u65B0\u7248\u672C"));
6547
6579
  } catch (error) {
6548
6580
  lines.push(chalk9__default.default.red("\u66F4\u65B0\u5931\u8D25: " + error.message));
6549
6581
  lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
6550
- lines.push(chalk9__default.default.gray(" npm install -g sf-cli@latest"));
6582
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
6551
6583
  }
6552
6584
  return { output: lines.join("\n") };
6553
6585
  }
6554
6586
  async function getLatestVersion() {
6555
6587
  try {
6556
- const result = await new Promise((resolve2, reject) => {
6588
+ const result = await new Promise((resolve4, reject) => {
6557
6589
  const proc = child_process.spawn("npm", ["view", PACKAGE_NAME, "version"], {
6558
6590
  stdio: "pipe",
6559
6591
  shell: true
@@ -6563,13 +6595,17 @@ async function getLatestVersion() {
6563
6595
  output += data.toString();
6564
6596
  });
6565
6597
  proc.on("close", (code) => {
6566
- if (code === 0) {
6567
- resolve2(output.trim());
6598
+ if (code === 0 && output.trim()) {
6599
+ resolve4(output.trim());
6568
6600
  } else {
6569
6601
  reject(new Error("Failed to get version"));
6570
6602
  }
6571
6603
  });
6572
6604
  proc.on("error", reject);
6605
+ setTimeout(() => {
6606
+ proc.kill();
6607
+ reject(new Error("Timeout"));
6608
+ }, 1e4);
6573
6609
  });
6574
6610
  return result || null;
6575
6611
  } catch {
@@ -6651,15 +6687,32 @@ var MAX_FILE_SIZE2 = 1024 * 1024;
6651
6687
  var COMPLEXITY_THRESHOLD = 6;
6652
6688
  async function handleNew(args, ctx) {
6653
6689
  const workingDir = ctx.options.workingDirectory;
6690
+ const workflowEngine = ctx.workflowEngine;
6691
+ if (workflowEngine) {
6692
+ const existingState = workflowEngine.getState();
6693
+ if (existingState && existingState.status === "running") {
6694
+ return {
6695
+ output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray(`
6696
+
6697
+ \u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
6698
+ \u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9__default.default.gray(`
6699
+
6700
+ \u9009\u9879:`) + chalk9__default.default.gray(`
6701
+ 1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:${existingState.currentStep}`) + chalk9__default.default.gray(`
6702
+ 2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel`) + chalk9__default.default.gray(`
6703
+ 3. \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001: /opsx:status`)
6704
+ };
6705
+ }
6706
+ }
6654
6707
  const { requirement, forceComplexity } = parseArgs(args);
6655
6708
  if (!requirement) {
6656
6709
  return {
6657
6710
  output: chalk9__default.default.red("\u8BF7\u8F93\u5165\u9700\u6C42\u63CF\u8FF0") + chalk9__default.default.gray("\n\u7528\u6CD5: /new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray("\n\u9009\u9879:") + chalk9__default.default.gray("\n --simple \u5F3A\u5236\u4F7F\u7528\u7B80\u5355\u6D41\u7A0B") + chalk9__default.default.gray("\n --complex \u5F3A\u5236\u4F7F\u7528\u590D\u6742\u6D41\u7A0B")
6658
6711
  };
6659
6712
  }
6660
- return newFeature({ requirement, forceComplexity }, workingDir);
6713
+ return newFeature({ requirement, forceComplexity }, workingDir, workflowEngine);
6661
6714
  }
6662
- async function newFeature(options, workingDir) {
6715
+ async function newFeature(options, workingDir, workflowEngine) {
6663
6716
  const cwd = workingDir || process.cwd();
6664
6717
  const { requirement, forceComplexity } = options;
6665
6718
  try {
@@ -6677,8 +6730,10 @@ async function newFeature(options, workingDir) {
6677
6730
  try {
6678
6731
  const context = await readProjectContext(cwd);
6679
6732
  const analysis = forceComplexity ? createForcedAnalysis(forceComplexity) : analyzeComplexity(requirement, context);
6680
- const workflow = new WorkflowEngine();
6681
- await workflow.initialize(cwd);
6733
+ const workflow = workflowEngine || new WorkflowEngine();
6734
+ if (!workflowEngine) {
6735
+ await workflow.initialize(cwd);
6736
+ }
6682
6737
  const state = await workflow.start(requirement, analysis.score, {
6683
6738
  title: extractTitle(requirement)
6684
6739
  });
@@ -7234,6 +7289,9 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
7234
7289
  }
7235
7290
 
7236
7291
  // src/commands/runner.ts
7292
+ var packageJsonPath2 = path4__namespace.resolve(__dirname, "../../package.json");
7293
+ var packageJson2 = JSON.parse(fsSync__namespace.readFileSync(packageJsonPath2, "utf-8"));
7294
+ var VERSION2 = packageJson2.version;
7237
7295
  async function runSlashCommand(command, args, ctx) {
7238
7296
  const normalizedCommand = normalizeCommand(command);
7239
7297
  switch (normalizedCommand) {
@@ -7261,6 +7319,11 @@ async function runSlashCommand(command, args, ctx) {
7261
7319
  case "new":
7262
7320
  case "n":
7263
7321
  return handleNew(args, ctx);
7322
+ case "version":
7323
+ case "v":
7324
+ return {
7325
+ output: chalk9__default.default.cyan(`sf-cli v${VERSION2}`)
7326
+ };
7264
7327
  default:
7265
7328
  if (normalizedCommand.startsWith("opsx:")) {
7266
7329
  return handleOpsx(normalizedCommand, args, ctx);
@@ -7323,7 +7386,7 @@ async function executeShell(command, ctx) {
7323
7386
  \u547D\u4EE4 "${command}" \u53EF\u80FD\u4F1A\u5220\u9664\u91CD\u8981\u6587\u4EF6`) + chalk9__default.default.gray("\n\u4F7F\u7528 yolo \u6A21\u5F0F\u5F3A\u5236\u6267\u884C")
7324
7387
  };
7325
7388
  }
7326
- return new Promise((resolve2) => {
7389
+ return new Promise((resolve4) => {
7327
7390
  const shell = child_process.spawn(command, [], {
7328
7391
  shell: true,
7329
7392
  cwd: ctx.options.workingDirectory
@@ -7348,11 +7411,11 @@ async function executeShell(command, ctx) {
7348
7411
  output += chalk9__default.default.red(`
7349
7412
  \u9000\u51FA\u7801: ${code}`);
7350
7413
  }
7351
- resolve2({ output: output || chalk9__default.default.gray("(\u65E0\u8F93\u51FA)") });
7414
+ resolve4({ output: output || chalk9__default.default.gray("(\u65E0\u8F93\u51FA)") });
7352
7415
  });
7353
7416
  setTimeout(() => {
7354
7417
  shell.kill();
7355
- resolve2({
7418
+ resolve4({
7356
7419
  output: chalk9__default.default.yellow("\u547D\u4EE4\u6267\u884C\u8D85\u65F6\uFF0C\u5DF2\u7EC8\u6B62")
7357
7420
  });
7358
7421
  }, 6e4);
@@ -7371,12 +7434,75 @@ async function handleNaturalLanguage(input, ctx) {
7371
7434
  }
7372
7435
 
7373
7436
  // src/cli/executor.ts
7437
+ var ALLOWED_COMMANDS_WITHOUT_WORKFLOW = [
7438
+ "help",
7439
+ "h",
7440
+ "?",
7441
+ "init",
7442
+ "i",
7443
+ "model",
7444
+ "m",
7445
+ "new",
7446
+ "n",
7447
+ "exit",
7448
+ "e",
7449
+ "q",
7450
+ "quit",
7451
+ "clear",
7452
+ "c",
7453
+ "update",
7454
+ "u",
7455
+ "version",
7456
+ "v"
7457
+ ];
7458
+ var STAGE_PERMISSIONS = {
7459
+ "explore": {
7460
+ canRead: true,
7461
+ canWrite: false,
7462
+ canRunShell: false,
7463
+ allowedAgents: ["architect"]
7464
+ },
7465
+ "new": {
7466
+ canRead: true,
7467
+ canWrite: true,
7468
+ canRunShell: false,
7469
+ allowedAgents: ["frontend-dev", "architect"]
7470
+ },
7471
+ "continue": {
7472
+ canRead: true,
7473
+ canWrite: true,
7474
+ canRunShell: true,
7475
+ allowedAgents: ["frontend-dev", "tester"]
7476
+ },
7477
+ "propose": {
7478
+ canRead: true,
7479
+ canWrite: true,
7480
+ canRunShell: true,
7481
+ allowedAgents: ["frontend-dev"]
7482
+ },
7483
+ "apply": {
7484
+ canRead: true,
7485
+ canWrite: true,
7486
+ canRunShell: true,
7487
+ allowedAgents: ["code-reviewer"]
7488
+ },
7489
+ "archive": {
7490
+ canRead: true,
7491
+ canWrite: false,
7492
+ canRunShell: false,
7493
+ allowedAgents: []
7494
+ }
7495
+ };
7374
7496
  var CommandExecutor = class {
7375
7497
  async execute(parseResult, ctx) {
7376
7498
  if (!parseResult.success || !parseResult.command) {
7377
7499
  return { output: chalk9__default.default.red(`\u9519\u8BEF: ${parseResult.error}`) };
7378
7500
  }
7379
7501
  const { command } = parseResult;
7502
+ const workflowCheck = this.checkWorkflowPermission(command, ctx);
7503
+ if (!workflowCheck.allowed) {
7504
+ return { output: workflowCheck.message };
7505
+ }
7380
7506
  switch (command.type) {
7381
7507
  case "slash" /* SLASH */:
7382
7508
  return this.executeSlashCommand(command, ctx);
@@ -7394,13 +7520,75 @@ var CommandExecutor = class {
7394
7520
  return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
7395
7521
  }
7396
7522
  }
7523
+ /**
7524
+ * 检查工作流权限
7525
+ */
7526
+ checkWorkflowPermission(command, ctx) {
7527
+ const workflowEngine = ctx.workflowEngine;
7528
+ const workflowState = workflowEngine?.getState();
7529
+ if (!workflowState) {
7530
+ if (command.type === "slash" /* SLASH */) {
7531
+ const cmd = command.command?.toLowerCase();
7532
+ if (!ALLOWED_COMMANDS_WITHOUT_WORKFLOW.includes(cmd)) {
7533
+ return {
7534
+ allowed: false,
7535
+ message: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7536
+ };
7537
+ }
7538
+ }
7539
+ if (command.type === "natural" /* NATURAL */) {
7540
+ return {
7541
+ allowed: false,
7542
+ message: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7543
+ };
7544
+ }
7545
+ if (command.type === "dollar" /* DOLLAR */) {
7546
+ return {
7547
+ allowed: false,
7548
+ message: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u8C03\u7528 Agent") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7549
+ };
7550
+ }
7551
+ if (command.type === "shell" /* SHELL */) {
7552
+ return {
7553
+ allowed: false,
7554
+ message: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u6267\u884C Shell \u547D\u4EE4") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7555
+ };
7556
+ }
7557
+ return { allowed: true };
7558
+ }
7559
+ const currentStep = workflowState.currentStep;
7560
+ const permissions = STAGE_PERMISSIONS[currentStep];
7561
+ if (command.type === "at" /* AT */ && !permissions.canRead) {
7562
+ return {
7563
+ allowed: false,
7564
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8BFB\u53D6\u6587\u4EF6`)
7565
+ };
7566
+ }
7567
+ if (command.type === "dollar" /* DOLLAR */) {
7568
+ const agentId = command.agent?.toLowerCase().replace("$", "");
7569
+ if (!permissions.allowedAgents.includes(agentId)) {
7570
+ return {
7571
+ allowed: false,
7572
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8C03\u7528 $${agentId} Agent`) + chalk9__default.default.gray(`
7573
+ \u5F53\u524D\u9636\u6BB5\u5141\u8BB8\u7684 Agent: ${permissions.allowedAgents.map((a) => `$${a}`).join(", ") || "\u65E0"}`)
7574
+ };
7575
+ }
7576
+ }
7577
+ if (command.type === "shell" /* SHELL */ && !permissions.canRunShell) {
7578
+ return {
7579
+ allowed: false,
7580
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u6267\u884C Shell \u547D\u4EE4`)
7581
+ };
7582
+ }
7583
+ return { allowed: true };
7584
+ }
7397
7585
  async executeSlashCommand(command, ctx) {
7398
7586
  const result = await runSlashCommand(
7399
7587
  command.command,
7400
7588
  command.args || [],
7401
7589
  ctx
7402
7590
  );
7403
- return { output: result.output };
7591
+ return { output: result.output, exit: result.exit };
7404
7592
  }
7405
7593
  async executeFileReference(command, ctx) {
7406
7594
  const result = await handleFileReference(command.path, ctx);