@nick848/sf-cli 1.0.0 → 1.0.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/index.mjs CHANGED
@@ -10,6 +10,7 @@ import chalk9 from 'chalk';
10
10
  import { v4 } from 'uuid';
11
11
  import { prompt } from 'enquirer';
12
12
  import { spawn } from 'child_process';
13
+ import { createRequire } from 'module';
13
14
 
14
15
  // src/services/config.ts
15
16
  var DEFAULT_CONFIG = {
@@ -6622,15 +6623,32 @@ var MAX_FILE_SIZE2 = 1024 * 1024;
6622
6623
  var COMPLEXITY_THRESHOLD = 6;
6623
6624
  async function handleNew(args, ctx) {
6624
6625
  const workingDir = ctx.options.workingDirectory;
6626
+ const workflowEngine = ctx.workflowEngine;
6627
+ if (workflowEngine) {
6628
+ const existingState = workflowEngine.getState();
6629
+ if (existingState && existingState.status === "running") {
6630
+ return {
6631
+ output: chalk9.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9.gray(`
6632
+
6633
+ \u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9.gray(`
6634
+ \u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9.gray(`
6635
+
6636
+ \u9009\u9879:`) + chalk9.gray(`
6637
+ 1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:${existingState.currentStep}`) + chalk9.gray(`
6638
+ 2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel`) + chalk9.gray(`
6639
+ 3. \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001: /opsx:status`)
6640
+ };
6641
+ }
6642
+ }
6625
6643
  const { requirement, forceComplexity } = parseArgs(args);
6626
6644
  if (!requirement) {
6627
6645
  return {
6628
6646
  output: chalk9.red("\u8BF7\u8F93\u5165\u9700\u6C42\u63CF\u8FF0") + chalk9.gray("\n\u7528\u6CD5: /new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray("\n\u9009\u9879:") + chalk9.gray("\n --simple \u5F3A\u5236\u4F7F\u7528\u7B80\u5355\u6D41\u7A0B") + chalk9.gray("\n --complex \u5F3A\u5236\u4F7F\u7528\u590D\u6742\u6D41\u7A0B")
6629
6647
  };
6630
6648
  }
6631
- return newFeature({ requirement, forceComplexity }, workingDir);
6649
+ return newFeature({ requirement, forceComplexity }, workingDir, workflowEngine);
6632
6650
  }
6633
- async function newFeature(options, workingDir) {
6651
+ async function newFeature(options, workingDir, workflowEngine) {
6634
6652
  const cwd = workingDir || process.cwd();
6635
6653
  const { requirement, forceComplexity } = options;
6636
6654
  try {
@@ -6648,8 +6666,10 @@ async function newFeature(options, workingDir) {
6648
6666
  try {
6649
6667
  const context = await readProjectContext(cwd);
6650
6668
  const analysis = forceComplexity ? createForcedAnalysis(forceComplexity) : analyzeComplexity(requirement, context);
6651
- const workflow = new WorkflowEngine();
6652
- await workflow.initialize(cwd);
6669
+ const workflow = workflowEngine || new WorkflowEngine();
6670
+ if (!workflowEngine) {
6671
+ await workflow.initialize(cwd);
6672
+ }
6653
6673
  const state = await workflow.start(requirement, analysis.score, {
6654
6674
  title: extractTitle(requirement)
6655
6675
  });
@@ -7203,8 +7223,9 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9.cyan(`
7203
7223
  throw e;
7204
7224
  }
7205
7225
  }
7206
-
7207
- // src/commands/runner.ts
7226
+ var require2 = createRequire(import.meta.url);
7227
+ var packageJson = require2("../../package.json");
7228
+ var VERSION2 = packageJson.version;
7208
7229
  async function runSlashCommand(command, args, ctx) {
7209
7230
  const normalizedCommand = normalizeCommand(command);
7210
7231
  switch (normalizedCommand) {
@@ -7232,6 +7253,11 @@ async function runSlashCommand(command, args, ctx) {
7232
7253
  case "new":
7233
7254
  case "n":
7234
7255
  return handleNew(args, ctx);
7256
+ case "version":
7257
+ case "v":
7258
+ return {
7259
+ output: chalk9.cyan(`sf-cli v${VERSION2}`)
7260
+ };
7235
7261
  default:
7236
7262
  if (normalizedCommand.startsWith("opsx:")) {
7237
7263
  return handleOpsx(normalizedCommand, args, ctx);
@@ -7342,12 +7368,75 @@ async function handleNaturalLanguage(input, ctx) {
7342
7368
  }
7343
7369
 
7344
7370
  // src/cli/executor.ts
7371
+ var ALLOWED_COMMANDS_WITHOUT_WORKFLOW = [
7372
+ "help",
7373
+ "h",
7374
+ "?",
7375
+ "init",
7376
+ "i",
7377
+ "model",
7378
+ "m",
7379
+ "new",
7380
+ "n",
7381
+ "exit",
7382
+ "e",
7383
+ "q",
7384
+ "quit",
7385
+ "clear",
7386
+ "c",
7387
+ "update",
7388
+ "u",
7389
+ "version",
7390
+ "v"
7391
+ ];
7392
+ var STAGE_PERMISSIONS = {
7393
+ "explore": {
7394
+ canRead: true,
7395
+ canWrite: false,
7396
+ canRunShell: false,
7397
+ allowedAgents: ["architect"]
7398
+ },
7399
+ "new": {
7400
+ canRead: true,
7401
+ canWrite: true,
7402
+ canRunShell: false,
7403
+ allowedAgents: ["frontend-dev", "architect"]
7404
+ },
7405
+ "continue": {
7406
+ canRead: true,
7407
+ canWrite: true,
7408
+ canRunShell: true,
7409
+ allowedAgents: ["frontend-dev", "tester"]
7410
+ },
7411
+ "propose": {
7412
+ canRead: true,
7413
+ canWrite: true,
7414
+ canRunShell: true,
7415
+ allowedAgents: ["frontend-dev"]
7416
+ },
7417
+ "apply": {
7418
+ canRead: true,
7419
+ canWrite: true,
7420
+ canRunShell: true,
7421
+ allowedAgents: ["code-reviewer"]
7422
+ },
7423
+ "archive": {
7424
+ canRead: true,
7425
+ canWrite: false,
7426
+ canRunShell: false,
7427
+ allowedAgents: []
7428
+ }
7429
+ };
7345
7430
  var CommandExecutor = class {
7346
7431
  async execute(parseResult, ctx) {
7347
7432
  if (!parseResult.success || !parseResult.command) {
7348
7433
  return { output: chalk9.red(`\u9519\u8BEF: ${parseResult.error}`) };
7349
7434
  }
7350
7435
  const { command } = parseResult;
7436
+ const workflowCheck = this.checkWorkflowPermission(command, ctx);
7437
+ if (!workflowCheck.allowed) {
7438
+ return { output: workflowCheck.message };
7439
+ }
7351
7440
  switch (command.type) {
7352
7441
  case "slash" /* SLASH */:
7353
7442
  return this.executeSlashCommand(command, ctx);
@@ -7365,13 +7454,75 @@ var CommandExecutor = class {
7365
7454
  return { output: chalk9.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
7366
7455
  }
7367
7456
  }
7457
+ /**
7458
+ * 检查工作流权限
7459
+ */
7460
+ checkWorkflowPermission(command, ctx) {
7461
+ const workflowEngine = ctx.workflowEngine;
7462
+ const workflowState = workflowEngine?.getState();
7463
+ if (!workflowState) {
7464
+ if (command.type === "slash" /* SLASH */) {
7465
+ const cmd = command.command?.toLowerCase();
7466
+ if (!ALLOWED_COMMANDS_WITHOUT_WORKFLOW.includes(cmd)) {
7467
+ return {
7468
+ allowed: false,
7469
+ message: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7470
+ };
7471
+ }
7472
+ }
7473
+ if (command.type === "natural" /* NATURAL */) {
7474
+ return {
7475
+ allowed: false,
7476
+ message: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7477
+ };
7478
+ }
7479
+ if (command.type === "dollar" /* DOLLAR */) {
7480
+ return {
7481
+ allowed: false,
7482
+ message: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u8C03\u7528 Agent") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7483
+ };
7484
+ }
7485
+ if (command.type === "shell" /* SHELL */) {
7486
+ return {
7487
+ allowed: false,
7488
+ message: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u6267\u884C Shell \u547D\u4EE4") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7489
+ };
7490
+ }
7491
+ return { allowed: true };
7492
+ }
7493
+ const currentStep = workflowState.currentStep;
7494
+ const permissions = STAGE_PERMISSIONS[currentStep];
7495
+ if (command.type === "at" /* AT */ && !permissions.canRead) {
7496
+ return {
7497
+ allowed: false,
7498
+ message: chalk9.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8BFB\u53D6\u6587\u4EF6`)
7499
+ };
7500
+ }
7501
+ if (command.type === "dollar" /* DOLLAR */) {
7502
+ const agentId = command.agent?.toLowerCase().replace("$", "");
7503
+ if (!permissions.allowedAgents.includes(agentId)) {
7504
+ return {
7505
+ allowed: false,
7506
+ message: chalk9.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8C03\u7528 $${agentId} Agent`) + chalk9.gray(`
7507
+ \u5F53\u524D\u9636\u6BB5\u5141\u8BB8\u7684 Agent: ${permissions.allowedAgents.map((a) => `$${a}`).join(", ") || "\u65E0"}`)
7508
+ };
7509
+ }
7510
+ }
7511
+ if (command.type === "shell" /* SHELL */ && !permissions.canRunShell) {
7512
+ return {
7513
+ allowed: false,
7514
+ message: chalk9.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u6267\u884C Shell \u547D\u4EE4`)
7515
+ };
7516
+ }
7517
+ return { allowed: true };
7518
+ }
7368
7519
  async executeSlashCommand(command, ctx) {
7369
7520
  const result = await runSlashCommand(
7370
7521
  command.command,
7371
7522
  command.args || [],
7372
7523
  ctx
7373
7524
  );
7374
- return { output: result.output };
7525
+ return { output: result.output, exit: result.exit };
7375
7526
  }
7376
7527
  async executeFileReference(command, ctx) {
7377
7528
  const result = await handleFileReference(command.path, ctx);