@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/cli/index.js CHANGED
@@ -3,11 +3,11 @@
3
3
 
4
4
  var commander = require('commander');
5
5
  var chalk9 = require('chalk');
6
+ var fsSync = require('fs');
7
+ var path6 = require('path');
6
8
  var readline = require('readline');
7
- var path5 = require('path');
8
- var fs5 = require('fs/promises');
9
+ var fs6 = require('fs/promises');
9
10
  var enquirer = require('enquirer');
10
- var fsSync = require('fs');
11
11
  var crypto = require('crypto');
12
12
  var os = require('os');
13
13
  var tiktoken = require('tiktoken');
@@ -37,10 +37,10 @@ function _interopNamespace(e) {
37
37
  }
38
38
 
39
39
  var chalk9__default = /*#__PURE__*/_interopDefault(chalk9);
40
- var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
41
- var path5__namespace = /*#__PURE__*/_interopNamespace(path5);
42
- var fs5__namespace = /*#__PURE__*/_interopNamespace(fs5);
43
40
  var fsSync__namespace = /*#__PURE__*/_interopNamespace(fsSync);
41
+ var path6__namespace = /*#__PURE__*/_interopNamespace(path6);
42
+ var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
43
+ var fs6__namespace = /*#__PURE__*/_interopNamespace(fs6);
44
44
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
45
45
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
46
46
 
@@ -125,8 +125,8 @@ var CommandParser = class {
125
125
  };
126
126
  }
127
127
  parseAtPath(input) {
128
- const path12 = input.slice(1).trim();
129
- if (!path12) {
128
+ const path15 = input.slice(1).trim();
129
+ if (!path15) {
130
130
  return { success: false, error: "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84" };
131
131
  }
132
132
  return {
@@ -134,7 +134,7 @@ var CommandParser = class {
134
134
  command: {
135
135
  type: "at" /* AT */,
136
136
  raw: input,
137
- path: path12
137
+ path: path15
138
138
  }
139
139
  };
140
140
  }
@@ -206,11 +206,11 @@ var NormsManager = class {
206
206
  const files = await this.collectProjectFiles(projectPath);
207
207
  for (const filePath of files.slice(0, MAX_FILES_TO_SCAN)) {
208
208
  try {
209
- const stats = await fs5__namespace.stat(filePath);
209
+ const stats = await fs6__namespace.stat(filePath);
210
210
  if (stats.size > MAX_FILE_SIZE) {
211
211
  continue;
212
212
  }
213
- const content = await fs5__namespace.readFile(filePath, "utf-8");
213
+ const content = await fs6__namespace.readFile(filePath, "utf-8");
214
214
  const patterns = await this.learnFromFile(filePath, content);
215
215
  result.patternsFound += patterns.length;
216
216
  result.filesScanned++;
@@ -233,7 +233,7 @@ var NormsManager = class {
233
233
  * 从单个文件学习规范
234
234
  */
235
235
  async learnFromFile(filePath, content) {
236
- const ext = path5__namespace.extname(filePath);
236
+ const ext = path6__namespace.extname(filePath);
237
237
  const patterns = this.extractPatterns(filePath, content, ext);
238
238
  for (const pattern of patterns) {
239
239
  await this.recordOccurrence({
@@ -836,16 +836,16 @@ ${response}`;
836
836
  const files = [];
837
837
  async function scan(dir) {
838
838
  try {
839
- const entries = await fs5__namespace.readdir(dir, { withFileTypes: true });
839
+ const entries = await fs6__namespace.readdir(dir, { withFileTypes: true });
840
840
  for (const entry of entries) {
841
841
  if (entry.isDirectory()) {
842
842
  if (!IGNORED_DIRS.includes(entry.name)) {
843
- await scan(path5__namespace.join(dir, entry.name));
843
+ await scan(path6__namespace.join(dir, entry.name));
844
844
  }
845
845
  } else if (entry.isFile()) {
846
- const ext = path5__namespace.extname(entry.name);
846
+ const ext = path6__namespace.extname(entry.name);
847
847
  if (SCAN_EXTENSIONS.includes(ext)) {
848
- files.push(path5__namespace.join(dir, entry.name));
848
+ files.push(path6__namespace.join(dir, entry.name));
849
849
  }
850
850
  }
851
851
  }
@@ -879,16 +879,16 @@ ${response}`;
879
879
  * 确保规范目录存在
880
880
  */
881
881
  async ensureNormsDir() {
882
- await fs5__namespace.mkdir(this.config.normsDir, { recursive: true });
883
- await fs5__namespace.mkdir(path5__namespace.join(this.config.normsDir, "weekly"), { recursive: true });
882
+ await fs6__namespace.mkdir(this.config.normsDir, { recursive: true });
883
+ await fs6__namespace.mkdir(path6__namespace.join(this.config.normsDir, "weekly"), { recursive: true });
884
884
  }
885
885
  /**
886
886
  * 加载已有规范
887
887
  */
888
888
  async loadStandards() {
889
- const standardsPath = path5__namespace.join(this.config.normsDir, "patterns.json");
889
+ const standardsPath = path6__namespace.join(this.config.normsDir, "patterns.json");
890
890
  try {
891
- const content = await fs5__namespace.readFile(standardsPath, "utf-8");
891
+ const content = await fs6__namespace.readFile(standardsPath, "utf-8");
892
892
  const data = JSON.parse(content);
893
893
  for (const standard of data) {
894
894
  this.standards.set(standard.id, {
@@ -904,9 +904,9 @@ ${response}`;
904
904
  * 加载权重数据
905
905
  */
906
906
  async loadWeights() {
907
- const weightsPath = path5__namespace.join(this.config.normsDir, "weights.json");
907
+ const weightsPath = path6__namespace.join(this.config.normsDir, "weights.json");
908
908
  try {
909
- const content = await fs5__namespace.readFile(weightsPath, "utf-8");
909
+ const content = await fs6__namespace.readFile(weightsPath, "utf-8");
910
910
  const data = JSON.parse(content);
911
911
  for (const weight of data) {
912
912
  this.weights.set(weight.standardId, {
@@ -921,8 +921,8 @@ ${response}`;
921
921
  * 保存规范
922
922
  */
923
923
  async saveStandards() {
924
- const standardsPath = path5__namespace.join(this.config.normsDir, "patterns.json");
925
- await fs5__namespace.writeFile(
924
+ const standardsPath = path6__namespace.join(this.config.normsDir, "patterns.json");
925
+ await fs6__namespace.writeFile(
926
926
  standardsPath,
927
927
  JSON.stringify(Array.from(this.standards.values()), null, 2),
928
928
  "utf-8"
@@ -932,8 +932,8 @@ ${response}`;
932
932
  * 保存权重
933
933
  */
934
934
  async saveWeights() {
935
- const weightsPath = path5__namespace.join(this.config.normsDir, "weights.json");
936
- await fs5__namespace.writeFile(
935
+ const weightsPath = path6__namespace.join(this.config.normsDir, "weights.json");
936
+ await fs6__namespace.writeFile(
937
937
  weightsPath,
938
938
  JSON.stringify(Array.from(this.weights.values()), null, 2),
939
939
  "utf-8"
@@ -960,8 +960,8 @@ ${response}`;
960
960
  * 保存周报
961
961
  */
962
962
  async saveWeeklyReport(weekId, report) {
963
- const reportPath = path5__namespace.join(this.config.normsDir, "weekly", `${weekId}.json`);
964
- await fs5__namespace.writeFile(reportPath, JSON.stringify(report, null, 2), "utf-8");
963
+ const reportPath = path6__namespace.join(this.config.normsDir, "weekly", `${weekId}.json`);
964
+ await fs6__namespace.writeFile(reportPath, JSON.stringify(report, null, 2), "utf-8");
965
965
  }
966
966
  /**
967
967
  * 更新 devstanded.md
@@ -969,8 +969,8 @@ ${response}`;
969
969
  async updateDevStandedMd() {
970
970
  const standards = this.getEffectiveStandards();
971
971
  const content = this.generateDevStandedMd(standards);
972
- const mdPath = path5__namespace.join(this.config.normsDir, "devstanded.md");
973
- await fs5__namespace.writeFile(mdPath, content, "utf-8");
972
+ const mdPath = path6__namespace.join(this.config.normsDir, "devstanded.md");
973
+ await fs6__namespace.writeFile(mdPath, content, "utf-8");
974
974
  }
975
975
  /**
976
976
  * 生成 devstanded.md 内容
@@ -1109,7 +1109,7 @@ async function handleInit(args, ctx) {
1109
1109
  async function initProject(options = {}, workingDir) {
1110
1110
  const cwd = workingDir || process.cwd();
1111
1111
  try {
1112
- const stats = await fs5__namespace.stat(cwd);
1112
+ const stats = await fs6__namespace.stat(cwd);
1113
1113
  if (!stats.isDirectory()) {
1114
1114
  return {
1115
1115
  output: chalk9__default.default.red(`\u9519\u8BEF: ${cwd} \u4E0D\u662F\u6709\u6548\u76EE\u5F55`)
@@ -1120,9 +1120,9 @@ async function initProject(options = {}, workingDir) {
1120
1120
  output: chalk9__default.default.red(`\u9519\u8BEF: \u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6743\u9650\u8BBF\u95EE ${cwd}`)
1121
1121
  };
1122
1122
  }
1123
- const sfCliDir = path5__namespace.join(cwd, ".sf-cli");
1124
- const openspecDir = path5__namespace.join(cwd, "openspec");
1125
- const agentsMdPath = path5__namespace.join(cwd, "AGENTS.md");
1123
+ const sfCliDir = path6__namespace.join(cwd, ".sf-cli");
1124
+ const openspecDir = path6__namespace.join(cwd, "openspec");
1125
+ const agentsMdPath = path6__namespace.join(cwd, "AGENTS.md");
1126
1126
  try {
1127
1127
  const agentsExists = await fileExists(agentsMdPath);
1128
1128
  if (agentsExists && !options.force) {
@@ -1141,7 +1141,7 @@ async function initProject(options = {}, workingDir) {
1141
1141
  await normsManager.initialize();
1142
1142
  const scanResult = await normsManager.scanProject(cwd);
1143
1143
  const agentsContent = generateAgentsMd(projectInfo, scanResult);
1144
- await fs5__namespace.writeFile(agentsMdPath, agentsContent, "utf-8");
1144
+ await fs6__namespace.writeFile(agentsMdPath, agentsContent, "utf-8");
1145
1145
  await generateOpenSpecConfig(openspecDir, projectInfo);
1146
1146
  return {
1147
1147
  output: chalk9__default.default.green("\u2713 \u9879\u76EE\u521D\u59CB\u5316\u5B8C\u6210\n") + chalk9__default.default.gray(` \u9879\u76EE\u7C7B\u578B: ${projectInfo.type}
@@ -1182,7 +1182,7 @@ async function createSfCliDirectory(basePath) {
1182
1182
  "logs"
1183
1183
  ];
1184
1184
  for (const dir of dirs) {
1185
- await fs5__namespace.mkdir(path5__namespace.join(basePath, dir), { recursive: true });
1185
+ await fs6__namespace.mkdir(path6__namespace.join(basePath, dir), { recursive: true });
1186
1186
  }
1187
1187
  const config = {
1188
1188
  version: "1.0.0",
@@ -1190,37 +1190,37 @@ async function createSfCliDirectory(basePath) {
1190
1190
  yolo: false,
1191
1191
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
1192
1192
  };
1193
- await fs5__namespace.writeFile(
1194
- path5__namespace.join(basePath, "config.json"),
1193
+ await fs6__namespace.writeFile(
1194
+ path6__namespace.join(basePath, "config.json"),
1195
1195
  JSON.stringify(config, null, 2),
1196
1196
  "utf-8"
1197
1197
  );
1198
- await fs5__namespace.writeFile(
1199
- path5__namespace.join(basePath, "agents", "registry.json"),
1198
+ await fs6__namespace.writeFile(
1199
+ path6__namespace.join(basePath, "agents", "registry.json"),
1200
1200
  JSON.stringify({ version: "1.0.0", agents: {} }, null, 2),
1201
1201
  "utf-8"
1202
1202
  );
1203
- await fs5__namespace.writeFile(
1204
- path5__namespace.join(basePath, "skills", "registry.json"),
1203
+ await fs6__namespace.writeFile(
1204
+ path6__namespace.join(basePath, "skills", "registry.json"),
1205
1205
  JSON.stringify({ version: "1.0.0", skills: {} }, null, 2),
1206
1206
  "utf-8"
1207
1207
  );
1208
- await fs5__namespace.writeFile(
1209
- path5__namespace.join(basePath, "health", "health.md"),
1208
+ await fs6__namespace.writeFile(
1209
+ path6__namespace.join(basePath, "health", "health.md"),
1210
1210
  generateHealthTemplate(),
1211
1211
  "utf-8"
1212
1212
  );
1213
1213
  }
1214
1214
  async function createOpenSpecDirectory(basePath) {
1215
- const changesDir = path5__namespace.join(basePath, "changes");
1216
- const archiveDir = path5__namespace.join(changesDir, "archive");
1217
- const specDir = path5__namespace.join(basePath, "spec");
1218
- await fs5__namespace.mkdir(archiveDir, { recursive: true });
1219
- await fs5__namespace.mkdir(specDir, { recursive: true });
1215
+ const changesDir = path6__namespace.join(basePath, "changes");
1216
+ const archiveDir = path6__namespace.join(changesDir, "archive");
1217
+ const specDir = path6__namespace.join(basePath, "spec");
1218
+ await fs6__namespace.mkdir(archiveDir, { recursive: true });
1219
+ await fs6__namespace.mkdir(specDir, { recursive: true });
1220
1220
  }
1221
1221
  async function analyzeProject(cwd) {
1222
1222
  const result = {
1223
- name: path5__namespace.basename(cwd),
1223
+ name: path6__namespace.basename(cwd),
1224
1224
  type: "unknown",
1225
1225
  framework: null,
1226
1226
  techStack: [],
@@ -1239,9 +1239,9 @@ async function analyzeProject(cwd) {
1239
1239
  hasEslint: false,
1240
1240
  hasPrettier: false
1241
1241
  };
1242
- const pkgPath = path5__namespace.join(cwd, "package.json");
1242
+ const pkgPath = path6__namespace.join(cwd, "package.json");
1243
1243
  try {
1244
- const pkgContent = await fs5__namespace.readFile(pkgPath, "utf-8");
1244
+ const pkgContent = await fs6__namespace.readFile(pkgPath, "utf-8");
1245
1245
  const pkg = JSON.parse(pkgContent);
1246
1246
  result.name = pkg.name || result.name;
1247
1247
  result.dependencies = pkg.dependencies || {};
@@ -1324,7 +1324,7 @@ async function analyzeDirectoryStructure(cwd) {
1324
1324
  others: []
1325
1325
  };
1326
1326
  try {
1327
- const entries = await fs5__namespace.readdir(cwd, { withFileTypes: true });
1327
+ const entries = await fs6__namespace.readdir(cwd, { withFileTypes: true });
1328
1328
  for (const entry of entries) {
1329
1329
  if (!entry.isDirectory()) continue;
1330
1330
  const name = entry.name;
@@ -1360,7 +1360,7 @@ async function findEntryPoints(cwd) {
1360
1360
  "index.js"
1361
1361
  ];
1362
1362
  for (const entry of possibleEntries) {
1363
- const fullPath = path5__namespace.join(cwd, entry);
1363
+ const fullPath = path6__namespace.join(cwd, entry);
1364
1364
  if (await fileExists(fullPath)) {
1365
1365
  entryPoints.push(entry);
1366
1366
  }
@@ -1368,15 +1368,15 @@ async function findEntryPoints(cwd) {
1368
1368
  return entryPoints;
1369
1369
  }
1370
1370
  async function saveProjectAnalysis(sfCliDir, analysis) {
1371
- const analysisPath = path5__namespace.join(sfCliDir, "cache", "analysis", "project-analysis.json");
1372
- await fs5__namespace.writeFile(
1371
+ const analysisPath = path6__namespace.join(sfCliDir, "cache", "analysis", "project-analysis.json");
1372
+ await fs6__namespace.writeFile(
1373
1373
  analysisPath,
1374
1374
  JSON.stringify(analysis, null, 2),
1375
1375
  "utf-8"
1376
1376
  );
1377
1377
  }
1378
1378
  async function generateOpenSpecConfig(openspecDir, analysis) {
1379
- const configPath = path5__namespace.join(openspecDir, "config.yaml");
1379
+ const configPath = path6__namespace.join(openspecDir, "config.yaml");
1380
1380
  const content = `# OpenSpec \u9879\u76EE\u914D\u7F6E
1381
1381
  # \u6B64\u6587\u4EF6\u5B9A\u4E49\u9879\u76EE\u7684\u57FA\u672C\u4FE1\u606F\uFF0C\u7528\u4E8E\u6307\u5BFC AI \u7406\u89E3\u9879\u76EE\u4E0A\u4E0B\u6587
1382
1382
 
@@ -1410,7 +1410,7 @@ architecture:
1410
1410
  # \u5F00\u53D1\u89C4\u8303 (\u4ECE\u4EE3\u7801\u4E2D\u5B66\u4E60)
1411
1411
  standards: []
1412
1412
  `;
1413
- await fs5__namespace.writeFile(configPath, content, "utf-8");
1413
+ await fs6__namespace.writeFile(configPath, content, "utf-8");
1414
1414
  }
1415
1415
  function generateAgentsMd(info, scanResult) {
1416
1416
  const techStackList = info.techStack.length > 0 ? info.techStack.map((t) => `| ${t} | \u2713 |`).join("\n") : "| \u5F85\u8BC6\u522B | - |";
@@ -1532,7 +1532,7 @@ function generateHealthTemplate() {
1532
1532
  }
1533
1533
  async function fileExists(filePath) {
1534
1534
  try {
1535
- await fs5__namespace.access(filePath);
1535
+ await fs6__namespace.access(filePath);
1536
1536
  return true;
1537
1537
  } catch {
1538
1538
  return false;
@@ -1703,7 +1703,7 @@ var IV_LENGTH = 16;
1703
1703
  var KEY_DIR = ".sf-cli";
1704
1704
  var KEY_FILE = ".key";
1705
1705
  function getOrCreateEncryptionKey() {
1706
- const keyPath = path5__namespace.join(os__namespace.homedir(), KEY_DIR, KEY_FILE);
1706
+ const keyPath = path6__namespace.join(os__namespace.homedir(), KEY_DIR, KEY_FILE);
1707
1707
  try {
1708
1708
  if (fsSync__namespace.existsSync(keyPath)) {
1709
1709
  const keyBase64 = fsSync__namespace.readFileSync(keyPath, "utf-8").trim();
@@ -1713,7 +1713,7 @@ function getOrCreateEncryptionKey() {
1713
1713
  }
1714
1714
  const key = crypto__namespace.randomBytes(32);
1715
1715
  try {
1716
- const keyDir = path5__namespace.dirname(keyPath);
1716
+ const keyDir = path6__namespace.dirname(keyPath);
1717
1717
  if (!fsSync__namespace.existsSync(keyDir)) {
1718
1718
  fsSync__namespace.mkdirSync(keyDir, { recursive: true, mode: 448 });
1719
1719
  }
@@ -1744,9 +1744,9 @@ var ConfigManager = class {
1744
1744
  }
1745
1745
  async load(projectPath) {
1746
1746
  this.projectPath = projectPath;
1747
- this.configPath = path5__namespace.join(projectPath, ".sf-cli", "config.json");
1747
+ this.configPath = path6__namespace.join(projectPath, ".sf-cli", "config.json");
1748
1748
  try {
1749
- const content = await fs5__namespace.readFile(this.configPath, "utf-8");
1749
+ const content = await fs6__namespace.readFile(this.configPath, "utf-8");
1750
1750
  const loaded = JSON.parse(content);
1751
1751
  if (loaded.apiKey && loaded.apiKeyEncrypted) {
1752
1752
  loaded.apiKey = this.decrypt(loaded.apiKey);
@@ -1765,8 +1765,8 @@ var ConfigManager = class {
1765
1765
  configToSave.apiKey = encrypted;
1766
1766
  configToSave.apiKeyEncrypted = true;
1767
1767
  }
1768
- await fs5__namespace.mkdir(path5__namespace.dirname(this.configPath), { recursive: true });
1769
- await fs5__namespace.writeFile(
1768
+ await fs6__namespace.mkdir(path6__namespace.dirname(this.configPath), { recursive: true });
1769
+ await fs6__namespace.writeFile(
1770
1770
  this.configPath,
1771
1771
  JSON.stringify(configToSave, null, 2),
1772
1772
  "utf-8"
@@ -2024,7 +2024,7 @@ var BaseAdapter = class {
2024
2024
  * 延迟工具函数
2025
2025
  */
2026
2026
  delay(ms) {
2027
- return new Promise((resolve2) => setTimeout(resolve2, ms));
2027
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
2028
2028
  }
2029
2029
  };
2030
2030
 
@@ -2645,7 +2645,7 @@ var ModelService = class {
2645
2645
  * 初始化服务
2646
2646
  */
2647
2647
  async initialize(statsDir) {
2648
- this.statsPath = path5__namespace.join(statsDir, "tokens");
2648
+ this.statsPath = path6__namespace.join(statsDir, "tokens");
2649
2649
  await this.loadStats();
2650
2650
  const model = this.configManager.get("model");
2651
2651
  const apiKey = this.configManager.get("apiKey");
@@ -2818,11 +2818,11 @@ var ModelService = class {
2818
2818
  async loadStats() {
2819
2819
  if (!this.statsPath) return;
2820
2820
  try {
2821
- const dailyPath = path5__namespace.join(this.statsPath, "daily.json");
2822
- const totalPath = path5__namespace.join(this.statsPath, "total.json");
2821
+ const dailyPath = path6__namespace.join(this.statsPath, "daily.json");
2822
+ const totalPath = path6__namespace.join(this.statsPath, "total.json");
2823
2823
  const [daily, total] = await Promise.all([
2824
- fs5__namespace.readFile(dailyPath, "utf-8").catch(() => "{}"),
2825
- fs5__namespace.readFile(totalPath, "utf-8").catch(() => '{"totalInput":0,"totalOutput":0}')
2824
+ fs6__namespace.readFile(dailyPath, "utf-8").catch(() => "{}"),
2825
+ fs6__namespace.readFile(totalPath, "utf-8").catch(() => '{"totalInput":0,"totalOutput":0}')
2826
2826
  ]);
2827
2827
  const dailyData = JSON.parse(daily);
2828
2828
  const totalData = JSON.parse(total);
@@ -2835,12 +2835,12 @@ var ModelService = class {
2835
2835
  async saveStats() {
2836
2836
  if (!this.statsPath) return;
2837
2837
  try {
2838
- await fs5__namespace.mkdir(this.statsPath, { recursive: true });
2839
- const dailyPath = path5__namespace.join(this.statsPath, "daily.json");
2840
- const totalPath = path5__namespace.join(this.statsPath, "total.json");
2838
+ await fs6__namespace.mkdir(this.statsPath, { recursive: true });
2839
+ const dailyPath = path6__namespace.join(this.statsPath, "daily.json");
2840
+ const totalPath = path6__namespace.join(this.statsPath, "total.json");
2841
2841
  await Promise.all([
2842
- fs5__namespace.writeFile(dailyPath, JSON.stringify(this.stats.byDate, null, 2)),
2843
- fs5__namespace.writeFile(totalPath, JSON.stringify({
2842
+ fs6__namespace.writeFile(dailyPath, JSON.stringify(this.stats.byDate, null, 2)),
2843
+ fs6__namespace.writeFile(totalPath, JSON.stringify({
2844
2844
  totalInput: this.stats.totalInput,
2845
2845
  totalOutput: this.stats.totalOutput
2846
2846
  }))
@@ -3081,8 +3081,10 @@ function createSpinner(message) {
3081
3081
  stop: () => process.stdout.write(" ".repeat(message.length + 10) + "\r")
3082
3082
  };
3083
3083
  }
3084
- var CURRENT_VERSION = "1.0.0";
3085
- var PACKAGE_NAME = "sf-cli";
3084
+ var packageJsonPath = path6__namespace.resolve(__dirname, "../../package.json");
3085
+ var packageJson = JSON.parse(fsSync__namespace.readFileSync(packageJsonPath, "utf-8"));
3086
+ var CURRENT_VERSION = packageJson.version;
3087
+ var PACKAGE_NAME = packageJson.name;
3086
3088
  async function handleUpdate(args, ctx) {
3087
3089
  const options = {
3088
3090
  check: args.includes("--check") || args.includes("-c"),
@@ -3109,6 +3111,9 @@ async function checkForUpdates() {
3109
3111
  const latestVersion = await getLatestVersion();
3110
3112
  if (!latestVersion) {
3111
3113
  lines.push(chalk9__default.default.yellow("\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\u4FE1\u606F"));
3114
+ lines.push(chalk9__default.default.gray("\u53EF\u80FD\u539F\u56E0:"));
3115
+ lines.push(chalk9__default.default.gray(" 1. \u5305\u5C1A\u672A\u53D1\u5E03\u5230 npm"));
3116
+ lines.push(chalk9__default.default.gray(" 2. \u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898"));
3112
3117
  return { output: lines.join("\n") };
3113
3118
  }
3114
3119
  lines.push(chalk9__default.default.gray(` \u5F53\u524D\u7248\u672C: v${CURRENT_VERSION}`));
@@ -3127,43 +3132,70 @@ async function checkForUpdates() {
3127
3132
  async function performUpdate(targetVersion) {
3128
3133
  const lines = [];
3129
3134
  lines.push(chalk9__default.default.cyan("\u6B63\u5728\u66F4\u65B0 sf-cli..."));
3135
+ lines.push(chalk9__default.default.gray(` \u5305\u540D: ${PACKAGE_NAME}`));
3136
+ lines.push(chalk9__default.default.gray(` \u5F53\u524D\u7248\u672C: v${CURRENT_VERSION}`));
3130
3137
  try {
3131
3138
  const latestVersion = await getLatestVersion();
3139
+ if (!latestVersion && !targetVersion) {
3140
+ lines.push(chalk9__default.default.yellow("\n\u26A0 \u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\u4FE1\u606F"));
3141
+ lines.push(chalk9__default.default.gray("\n\u53EF\u80FD\u539F\u56E0:"));
3142
+ lines.push(chalk9__default.default.gray(" 1. \u5305\u5C1A\u672A\u53D1\u5E03\u5230 npm"));
3143
+ lines.push(chalk9__default.default.gray(" 2. \u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898"));
3144
+ lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
3145
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
3146
+ return { output: lines.join("\n") };
3147
+ }
3132
3148
  if (latestVersion === CURRENT_VERSION && !targetVersion) {
3133
- lines.push(chalk9__default.default.green("\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0"));
3149
+ lines.push(chalk9__default.default.green("\n\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0"));
3134
3150
  return { output: lines.join("\n") };
3135
3151
  }
3136
3152
  const packageSpec = targetVersion ? `${PACKAGE_NAME}@${targetVersion}` : `${PACKAGE_NAME}@latest`;
3137
3153
  lines.push(chalk9__default.default.gray(` \u5B89\u88C5: ${packageSpec}`));
3138
- await new Promise((resolve2, reject) => {
3154
+ const installResult = await new Promise((resolve5) => {
3139
3155
  const proc = child_process.spawn("npm", ["install", "-g", packageSpec], {
3140
3156
  stdio: "pipe",
3141
3157
  shell: true
3142
3158
  });
3159
+ let output = "";
3160
+ proc.stdout?.on("data", (data) => {
3161
+ output += data.toString();
3162
+ });
3163
+ proc.stderr?.on("data", (data) => {
3164
+ output += data.toString();
3165
+ });
3143
3166
  proc.on("close", (code) => {
3144
- if (code === 0) {
3145
- resolve2();
3146
- } else {
3147
- reject(new Error(`npm install exited with code ${code}`));
3148
- }
3167
+ resolve5({
3168
+ success: code === 0,
3169
+ output
3170
+ });
3149
3171
  });
3150
3172
  proc.on("error", (err) => {
3151
- reject(err);
3173
+ resolve5({
3174
+ success: false,
3175
+ output: err.message
3176
+ });
3152
3177
  });
3153
3178
  });
3154
- lines.push(chalk9__default.default.green("\u2713 \u66F4\u65B0\u5B8C\u6210!"));
3179
+ if (!installResult.success) {
3180
+ lines.push(chalk9__default.default.red("\n\u2717 \u66F4\u65B0\u5931\u8D25"));
3181
+ lines.push(chalk9__default.default.gray(installResult.output));
3182
+ lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
3183
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
3184
+ return { output: lines.join("\n") };
3185
+ }
3186
+ lines.push(chalk9__default.default.green("\n\u2713 \u66F4\u65B0\u5B8C\u6210!"));
3155
3187
  lines.push(chalk9__default.default.gray(` \u65B0\u7248\u672C: v${targetVersion || latestVersion}`));
3156
3188
  lines.push(chalk9__default.default.gray("\n\u8BF7\u91CD\u542F CLI \u4EE5\u4F7F\u7528\u65B0\u7248\u672C"));
3157
3189
  } catch (error) {
3158
3190
  lines.push(chalk9__default.default.red("\u66F4\u65B0\u5931\u8D25: " + error.message));
3159
3191
  lines.push(chalk9__default.default.gray("\n\u60A8\u53EF\u4EE5\u5C1D\u8BD5\u624B\u52A8\u66F4\u65B0:"));
3160
- lines.push(chalk9__default.default.gray(" npm install -g sf-cli@latest"));
3192
+ lines.push(chalk9__default.default.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
3161
3193
  }
3162
3194
  return { output: lines.join("\n") };
3163
3195
  }
3164
3196
  async function getLatestVersion() {
3165
3197
  try {
3166
- const result = await new Promise((resolve2, reject) => {
3198
+ const result = await new Promise((resolve5, reject) => {
3167
3199
  const proc = child_process.spawn("npm", ["view", PACKAGE_NAME, "version"], {
3168
3200
  stdio: "pipe",
3169
3201
  shell: true
@@ -3173,13 +3205,17 @@ async function getLatestVersion() {
3173
3205
  output += data.toString();
3174
3206
  });
3175
3207
  proc.on("close", (code) => {
3176
- if (code === 0) {
3177
- resolve2(output.trim());
3208
+ if (code === 0 && output.trim()) {
3209
+ resolve5(output.trim());
3178
3210
  } else {
3179
3211
  reject(new Error("Failed to get version"));
3180
3212
  }
3181
3213
  });
3182
3214
  proc.on("error", reject);
3215
+ setTimeout(() => {
3216
+ proc.kill();
3217
+ reject(new Error("Timeout"));
3218
+ }, 1e4);
3183
3219
  });
3184
3220
  return result || null;
3185
3221
  } catch {
@@ -3463,7 +3499,7 @@ var WorkflowEngine = class {
3463
3499
  */
3464
3500
  async initialize(projectPath) {
3465
3501
  this.projectPath = projectPath;
3466
- this.openspecPath = path5__namespace.join(projectPath, "openspec");
3502
+ this.openspecPath = path6__namespace.join(projectPath, "openspec");
3467
3503
  await this.ensureDirectories();
3468
3504
  await this.loadProjectContext();
3469
3505
  await this.restoreState();
@@ -3473,21 +3509,21 @@ var WorkflowEngine = class {
3473
3509
  * 加载项目上下文(AGENTS.md 和 config.yaml)
3474
3510
  */
3475
3511
  async loadProjectContext() {
3476
- const agentsMdPath = path5__namespace.join(this.projectPath, "AGENTS.md");
3512
+ const agentsMdPath = path6__namespace.join(this.projectPath, "AGENTS.md");
3477
3513
  try {
3478
- this.projectContext = await fs5__namespace.readFile(agentsMdPath, "utf-8");
3514
+ this.projectContext = await fs6__namespace.readFile(agentsMdPath, "utf-8");
3479
3515
  } catch {
3480
3516
  this.projectContext = "";
3481
3517
  }
3482
- const configPath = path5__namespace.join(this.openspecPath, "config.yaml");
3518
+ const configPath = path6__namespace.join(this.openspecPath, "config.yaml");
3483
3519
  try {
3484
- this.projectConfig = await fs5__namespace.readFile(configPath, "utf-8");
3520
+ this.projectConfig = await fs6__namespace.readFile(configPath, "utf-8");
3485
3521
  } catch {
3486
3522
  this.projectConfig = "";
3487
3523
  }
3488
- const devstandedPath = path5__namespace.join(this.projectPath, ".sf-cli", "norms", "devstanded.md");
3524
+ const devstandedPath = path6__namespace.join(this.projectPath, ".sf-cli", "norms", "devstanded.md");
3489
3525
  try {
3490
- this.devStandards = await fs5__namespace.readFile(devstandedPath, "utf-8");
3526
+ this.devStandards = await fs6__namespace.readFile(devstandedPath, "utf-8");
3491
3527
  } catch {
3492
3528
  this.devStandards = "";
3493
3529
  }
@@ -3773,12 +3809,12 @@ var WorkflowEngine = class {
3773
3809
  await this.createSpecDocument(summary);
3774
3810
  await this.updateChangeRecord("archived");
3775
3811
  await this.saveState();
3776
- const changesDir = path5__namespace.join(this.openspecPath, "changes");
3777
- const archiveDir = path5__namespace.join(changesDir, "archive");
3778
- const changeFile = path5__namespace.join(changesDir, `${changeId}.md`);
3779
- const archiveFile = path5__namespace.join(archiveDir, `${changeId}.md`);
3780
- await fs5__namespace.mkdir(archiveDir, { recursive: true });
3781
- await fs5__namespace.rename(changeFile, archiveFile).catch(() => {
3812
+ const changesDir = path6__namespace.join(this.openspecPath, "changes");
3813
+ const archiveDir = path6__namespace.join(changesDir, "archive");
3814
+ const changeFile = path6__namespace.join(changesDir, `${changeId}.md`);
3815
+ const archiveFile = path6__namespace.join(archiveDir, `${changeId}.md`);
3816
+ await fs6__namespace.mkdir(archiveDir, { recursive: true });
3817
+ await fs6__namespace.rename(changeFile, archiveFile).catch(() => {
3782
3818
  });
3783
3819
  this.state = null;
3784
3820
  this.snapshots.clear();
@@ -3800,16 +3836,16 @@ var WorkflowEngine = class {
3800
3836
  }
3801
3837
  // ==================== 私有方法 ====================
3802
3838
  async ensureDirectories() {
3803
- const changesDir = path5__namespace.join(this.openspecPath, "changes");
3804
- const archiveDir = path5__namespace.join(changesDir, "archive");
3805
- const specDir = path5__namespace.join(this.openspecPath, "spec");
3806
- await fs5__namespace.mkdir(archiveDir, { recursive: true });
3807
- await fs5__namespace.mkdir(specDir, { recursive: true });
3839
+ const changesDir = path6__namespace.join(this.openspecPath, "changes");
3840
+ const archiveDir = path6__namespace.join(changesDir, "archive");
3841
+ const specDir = path6__namespace.join(this.openspecPath, "spec");
3842
+ await fs6__namespace.mkdir(archiveDir, { recursive: true });
3843
+ await fs6__namespace.mkdir(specDir, { recursive: true });
3808
3844
  }
3809
3845
  async restoreState() {
3810
- const statePath = path5__namespace.join(this.openspecPath, ".workflow-state.json");
3846
+ const statePath = path6__namespace.join(this.openspecPath, ".workflow-state.json");
3811
3847
  try {
3812
- const content = await fs5__namespace.readFile(statePath, "utf-8");
3848
+ const content = await fs6__namespace.readFile(statePath, "utf-8");
3813
3849
  this.state = JSON.parse(content, (key, value) => {
3814
3850
  if (key.endsWith("At") && typeof value === "string") {
3815
3851
  return new Date(value);
@@ -3820,20 +3856,20 @@ var WorkflowEngine = class {
3820
3856
  const err = e;
3821
3857
  if (err.code !== "ENOENT") {
3822
3858
  console.warn("\u8B66\u544A: \u5DE5\u4F5C\u6D41\u72B6\u6001\u6587\u4EF6\u5DF2\u635F\u574F\uFF0C\u5C06\u91CD\u65B0\u5F00\u59CB");
3823
- await fs5__namespace.unlink(statePath).catch(() => {
3859
+ await fs6__namespace.unlink(statePath).catch(() => {
3824
3860
  });
3825
3861
  }
3826
3862
  this.state = null;
3827
3863
  }
3828
3864
  }
3829
3865
  async saveState() {
3830
- const statePath = path5__namespace.join(this.openspecPath, ".workflow-state.json");
3831
- await fs5__namespace.writeFile(statePath, JSON.stringify(this.state, null, 2));
3866
+ const statePath = path6__namespace.join(this.openspecPath, ".workflow-state.json");
3867
+ await fs6__namespace.writeFile(statePath, JSON.stringify(this.state, null, 2));
3832
3868
  }
3833
3869
  async restoreSnapshots() {
3834
- const snapshotsPath = path5__namespace.join(this.openspecPath, ".workflow-snapshots.json");
3870
+ const snapshotsPath = path6__namespace.join(this.openspecPath, ".workflow-snapshots.json");
3835
3871
  try {
3836
- const content = await fs5__namespace.readFile(snapshotsPath, "utf-8");
3872
+ const content = await fs6__namespace.readFile(snapshotsPath, "utf-8");
3837
3873
  const data = JSON.parse(content, (key, value) => {
3838
3874
  if (key === "timestamp" && typeof value === "string") {
3839
3875
  return new Date(value);
@@ -3848,9 +3884,9 @@ var WorkflowEngine = class {
3848
3884
  }
3849
3885
  }
3850
3886
  async saveSnapshots() {
3851
- const snapshotsPath = path5__namespace.join(this.openspecPath, ".workflow-snapshots.json");
3887
+ const snapshotsPath = path6__namespace.join(this.openspecPath, ".workflow-snapshots.json");
3852
3888
  const data = Array.from(this.snapshots.values());
3853
- await fs5__namespace.writeFile(snapshotsPath, JSON.stringify(data, null, 2));
3889
+ await fs6__namespace.writeFile(snapshotsPath, JSON.stringify(data, null, 2));
3854
3890
  }
3855
3891
  async createSnapshot() {
3856
3892
  if (!this.state) return;
@@ -3870,16 +3906,16 @@ var WorkflowEngine = class {
3870
3906
  }
3871
3907
  async createChangeRecord() {
3872
3908
  if (!this.state) return;
3873
- const changePath = path5__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
3874
- await fs5__namespace.writeFile(changePath, this.formatChangeRecord());
3909
+ const changePath = path6__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
3910
+ await fs6__namespace.writeFile(changePath, this.formatChangeRecord());
3875
3911
  }
3876
3912
  async updateChangeRecord(status) {
3877
3913
  if (!this.state) return;
3878
3914
  if (status) {
3879
3915
  this.state.status = status;
3880
3916
  }
3881
- const changePath = path5__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
3882
- await fs5__namespace.writeFile(changePath, this.formatChangeRecord());
3917
+ const changePath = path6__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
3918
+ await fs6__namespace.writeFile(changePath, this.formatChangeRecord());
3883
3919
  }
3884
3920
  formatChangeRecord() {
3885
3921
  if (!this.state) return "";
@@ -3918,7 +3954,7 @@ ${this.state.artifacts.map((a) => `- ${a}`).join("\n") || "\u6682\u65E0"}
3918
3954
  }
3919
3955
  async createSpecDocument(summary) {
3920
3956
  if (!this.state) return;
3921
- const specPath = path5__namespace.join(this.openspecPath, "spec", `${this.state.id}.md`);
3957
+ const specPath = path6__namespace.join(this.openspecPath, "spec", `${this.state.id}.md`);
3922
3958
  const content = `# Spec: ${this.state.title}
3923
3959
 
3924
3960
  > \u53D8\u66F4ID: ${this.state.id}
@@ -3943,7 +3979,7 @@ ${this.state.steps.map((s) => `- [${s.status === "completed" ? "x" : " "}] ${s.s
3943
3979
 
3944
3980
  ${this.state.artifacts.map((a) => `- ${a}`).join("\n") || "\u6682\u65E0"}
3945
3981
  `;
3946
- await fs5__namespace.writeFile(specPath, content);
3982
+ await fs6__namespace.writeFile(specPath, content);
3947
3983
  }
3948
3984
  };
3949
3985
  var ConfirmationRequiredError = class extends Error {
@@ -3959,19 +3995,36 @@ var MAX_FILE_SIZE2 = 1024 * 1024;
3959
3995
  var COMPLEXITY_THRESHOLD = 6;
3960
3996
  async function handleNew(args, ctx) {
3961
3997
  const workingDir = ctx.options.workingDirectory;
3998
+ const workflowEngine = ctx.workflowEngine;
3999
+ if (workflowEngine) {
4000
+ const existingState = workflowEngine.getState();
4001
+ if (existingState && existingState.status === "running") {
4002
+ return {
4003
+ output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray(`
4004
+
4005
+ \u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
4006
+ \u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9__default.default.gray(`
4007
+
4008
+ \u9009\u9879:`) + chalk9__default.default.gray(`
4009
+ 1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:${existingState.currentStep}`) + chalk9__default.default.gray(`
4010
+ 2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel`) + chalk9__default.default.gray(`
4011
+ 3. \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001: /opsx:status`)
4012
+ };
4013
+ }
4014
+ }
3962
4015
  const { requirement, forceComplexity } = parseArgs(args);
3963
4016
  if (!requirement) {
3964
4017
  return {
3965
4018
  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")
3966
4019
  };
3967
4020
  }
3968
- return newFeature({ requirement, forceComplexity }, workingDir);
4021
+ return newFeature({ requirement, forceComplexity }, workingDir, workflowEngine);
3969
4022
  }
3970
- async function newFeature(options, workingDir) {
4023
+ async function newFeature(options, workingDir, workflowEngine) {
3971
4024
  const cwd = workingDir || process.cwd();
3972
4025
  const { requirement, forceComplexity } = options;
3973
4026
  try {
3974
- const stats = await fs5__namespace.stat(cwd);
4027
+ const stats = await fs6__namespace.stat(cwd);
3975
4028
  if (!stats.isDirectory()) {
3976
4029
  return {
3977
4030
  output: chalk9__default.default.red(`\u9519\u8BEF: ${cwd} \u4E0D\u662F\u6709\u6548\u76EE\u5F55`)
@@ -3985,8 +4038,10 @@ async function newFeature(options, workingDir) {
3985
4038
  try {
3986
4039
  const context = await readProjectContext(cwd);
3987
4040
  const analysis = forceComplexity ? createForcedAnalysis(forceComplexity) : analyzeComplexity(requirement, context);
3988
- const workflow = new WorkflowEngine();
3989
- await workflow.initialize(cwd);
4041
+ const workflow = workflowEngine || new WorkflowEngine();
4042
+ if (!workflowEngine) {
4043
+ await workflow.initialize(cwd);
4044
+ }
3990
4045
  const state = await workflow.start(requirement, analysis.score, {
3991
4046
  title: extractTitle(requirement)
3992
4047
  });
@@ -4040,20 +4095,20 @@ function parseArgs(args) {
4040
4095
  }
4041
4096
  async function readProjectContext(cwd) {
4042
4097
  const defaultContext = {
4043
- name: path5__namespace.basename(cwd),
4098
+ name: path6__namespace.basename(cwd),
4044
4099
  type: "unknown",
4045
4100
  framework: null,
4046
4101
  techStack: [],
4047
4102
  description: ""
4048
4103
  };
4049
- const agentsPath = path5__namespace.join(cwd, "AGENTS.md");
4104
+ const agentsPath = path6__namespace.join(cwd, "AGENTS.md");
4050
4105
  try {
4051
- const stats = await fs5__namespace.stat(agentsPath);
4106
+ const stats = await fs6__namespace.stat(agentsPath);
4052
4107
  if (stats.size > MAX_FILE_SIZE2) {
4053
4108
  console.warn(`\u8B66\u544A: AGENTS.md \u6587\u4EF6\u8FC7\u5927 (${stats.size} bytes)\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
4054
4109
  return defaultContext;
4055
4110
  }
4056
- const content = await fs5__namespace.readFile(agentsPath, "utf-8");
4111
+ const content = await fs6__namespace.readFile(agentsPath, "utf-8");
4057
4112
  return parseAgentsMd(content, defaultContext);
4058
4113
  } catch (e) {
4059
4114
  const err = e;
@@ -4061,14 +4116,14 @@ async function readProjectContext(cwd) {
4061
4116
  console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 AGENTS.md - ${err.message}`);
4062
4117
  }
4063
4118
  }
4064
- const configPath = path5__namespace.join(cwd, "openspec", "config.yaml");
4119
+ const configPath = path6__namespace.join(cwd, "openspec", "config.yaml");
4065
4120
  try {
4066
- const stats = await fs5__namespace.stat(configPath);
4121
+ const stats = await fs6__namespace.stat(configPath);
4067
4122
  if (stats.size > MAX_FILE_SIZE2) {
4068
4123
  console.warn(`\u8B66\u544A: config.yaml \u6587\u4EF6\u8FC7\u5927\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
4069
4124
  return defaultContext;
4070
4125
  }
4071
- const content = await fs5__namespace.readFile(configPath, "utf-8");
4126
+ const content = await fs6__namespace.readFile(configPath, "utf-8");
4072
4127
  return parseConfigYaml(content, defaultContext);
4073
4128
  } catch (e) {
4074
4129
  const err = e;
@@ -4628,15 +4683,15 @@ async function loadProjectContext(workingDirectory) {
4628
4683
  devStandards: ""
4629
4684
  };
4630
4685
  try {
4631
- context.agentsMd = await fs5__namespace.readFile(path5__namespace.join(workingDirectory, "AGENTS.md"), "utf-8");
4686
+ context.agentsMd = await fs6__namespace.readFile(path6__namespace.join(workingDirectory, "AGENTS.md"), "utf-8");
4632
4687
  } catch {
4633
4688
  }
4634
4689
  try {
4635
- context.configYaml = await fs5__namespace.readFile(path5__namespace.join(workingDirectory, "openspec", "config.yaml"), "utf-8");
4690
+ context.configYaml = await fs6__namespace.readFile(path6__namespace.join(workingDirectory, "openspec", "config.yaml"), "utf-8");
4636
4691
  } catch {
4637
4692
  }
4638
4693
  try {
4639
- context.devStandards = await fs5__namespace.readFile(path5__namespace.join(workingDirectory, ".sf-cli", "norms", "devstanded.md"), "utf-8");
4694
+ context.devStandards = await fs6__namespace.readFile(path6__namespace.join(workingDirectory, ".sf-cli", "norms", "devstanded.md"), "utf-8");
4640
4695
  } catch {
4641
4696
  }
4642
4697
  return context;
@@ -5159,6 +5214,9 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
5159
5214
  }
5160
5215
 
5161
5216
  // src/commands/runner.ts
5217
+ var packageJsonPath2 = path6__namespace.resolve(__dirname, "../../package.json");
5218
+ var packageJson2 = JSON.parse(fsSync__namespace.readFileSync(packageJsonPath2, "utf-8"));
5219
+ var VERSION2 = packageJson2.version;
5162
5220
  async function runSlashCommand(command, args, ctx) {
5163
5221
  const normalizedCommand = normalizeCommand(command);
5164
5222
  switch (normalizedCommand) {
@@ -5186,6 +5244,11 @@ async function runSlashCommand(command, args, ctx) {
5186
5244
  case "new":
5187
5245
  case "n":
5188
5246
  return handleNew(args, ctx);
5247
+ case "version":
5248
+ case "v":
5249
+ return {
5250
+ output: chalk9__default.default.cyan(`sf-cli v${VERSION2}`)
5251
+ };
5189
5252
  default:
5190
5253
  if (normalizedCommand.startsWith("opsx:")) {
5191
5254
  return handleOpsx(normalizedCommand, args, ctx);
@@ -5200,11 +5263,11 @@ function normalizeCommand(command) {
5200
5263
  }
5201
5264
  async function handleFileReference(filePath, ctx) {
5202
5265
  const cwd = ctx.options.workingDirectory;
5203
- const absolutePath = path5__namespace.isAbsolute(filePath) ? filePath : path5__namespace.join(cwd, filePath);
5266
+ const absolutePath = path6__namespace.isAbsolute(filePath) ? filePath : path6__namespace.join(cwd, filePath);
5204
5267
  try {
5205
- const stats = await fs5__namespace.stat(absolutePath);
5268
+ const stats = await fs6__namespace.stat(absolutePath);
5206
5269
  if (stats.isDirectory()) {
5207
- const files = await fs5__namespace.readdir(absolutePath);
5270
+ const files = await fs6__namespace.readdir(absolutePath);
5208
5271
  return {
5209
5272
  output: chalk9__default.default.cyan(`\u{1F4C1} ${filePath}/`) + chalk9__default.default.gray(`
5210
5273
  ${files.slice(0, 20).join("\n")}`) + (files.length > 20 ? chalk9__default.default.gray(`
@@ -5212,7 +5275,7 @@ ${files.slice(0, 20).join("\n")}`) + (files.length > 20 ? chalk9__default.defaul
5212
5275
  contextUsed: 0
5213
5276
  };
5214
5277
  }
5215
- const content = await fs5__namespace.readFile(absolutePath, "utf-8");
5278
+ const content = await fs6__namespace.readFile(absolutePath, "utf-8");
5216
5279
  const lines = content.split("\n");
5217
5280
  ctx.contextManager.addMessage({
5218
5281
  role: "user",
@@ -5248,7 +5311,7 @@ async function executeShell(command, ctx) {
5248
5311
  \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")
5249
5312
  };
5250
5313
  }
5251
- return new Promise((resolve2) => {
5314
+ return new Promise((resolve5) => {
5252
5315
  const shell = child_process.spawn(command, [], {
5253
5316
  shell: true,
5254
5317
  cwd: ctx.options.workingDirectory
@@ -5273,11 +5336,11 @@ async function executeShell(command, ctx) {
5273
5336
  output += chalk9__default.default.red(`
5274
5337
  \u9000\u51FA\u7801: ${code}`);
5275
5338
  }
5276
- resolve2({ output: output || chalk9__default.default.gray("(\u65E0\u8F93\u51FA)") });
5339
+ resolve5({ output: output || chalk9__default.default.gray("(\u65E0\u8F93\u51FA)") });
5277
5340
  });
5278
5341
  setTimeout(() => {
5279
5342
  shell.kill();
5280
- resolve2({
5343
+ resolve5({
5281
5344
  output: chalk9__default.default.yellow("\u547D\u4EE4\u6267\u884C\u8D85\u65F6\uFF0C\u5DF2\u7EC8\u6B62")
5282
5345
  });
5283
5346
  }, 6e4);
@@ -5296,12 +5359,75 @@ async function handleNaturalLanguage(input, ctx) {
5296
5359
  }
5297
5360
 
5298
5361
  // src/cli/executor.ts
5362
+ var ALLOWED_COMMANDS_WITHOUT_WORKFLOW = [
5363
+ "help",
5364
+ "h",
5365
+ "?",
5366
+ "init",
5367
+ "i",
5368
+ "model",
5369
+ "m",
5370
+ "new",
5371
+ "n",
5372
+ "exit",
5373
+ "e",
5374
+ "q",
5375
+ "quit",
5376
+ "clear",
5377
+ "c",
5378
+ "update",
5379
+ "u",
5380
+ "version",
5381
+ "v"
5382
+ ];
5383
+ var STAGE_PERMISSIONS = {
5384
+ "explore": {
5385
+ canRead: true,
5386
+ canWrite: false,
5387
+ canRunShell: false,
5388
+ allowedAgents: ["architect"]
5389
+ },
5390
+ "new": {
5391
+ canRead: true,
5392
+ canWrite: true,
5393
+ canRunShell: false,
5394
+ allowedAgents: ["frontend-dev", "architect"]
5395
+ },
5396
+ "continue": {
5397
+ canRead: true,
5398
+ canWrite: true,
5399
+ canRunShell: true,
5400
+ allowedAgents: ["frontend-dev", "tester"]
5401
+ },
5402
+ "propose": {
5403
+ canRead: true,
5404
+ canWrite: true,
5405
+ canRunShell: true,
5406
+ allowedAgents: ["frontend-dev"]
5407
+ },
5408
+ "apply": {
5409
+ canRead: true,
5410
+ canWrite: true,
5411
+ canRunShell: true,
5412
+ allowedAgents: ["code-reviewer"]
5413
+ },
5414
+ "archive": {
5415
+ canRead: true,
5416
+ canWrite: false,
5417
+ canRunShell: false,
5418
+ allowedAgents: []
5419
+ }
5420
+ };
5299
5421
  var CommandExecutor = class {
5300
5422
  async execute(parseResult, ctx) {
5301
5423
  if (!parseResult.success || !parseResult.command) {
5302
5424
  return { output: chalk9__default.default.red(`\u9519\u8BEF: ${parseResult.error}`) };
5303
5425
  }
5304
5426
  const { command } = parseResult;
5427
+ const workflowCheck = this.checkWorkflowPermission(command, ctx);
5428
+ if (!workflowCheck.allowed) {
5429
+ return { output: workflowCheck.message };
5430
+ }
5305
5431
  switch (command.type) {
5306
5432
  case "slash" /* SLASH */:
5307
5433
  return this.executeSlashCommand(command, ctx);
@@ -5319,13 +5445,75 @@ var CommandExecutor = class {
5319
5445
  return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
5320
5446
  }
5321
5447
  }
5448
+ /**
5449
+ * 检查工作流权限
5450
+ */
5451
+ checkWorkflowPermission(command, ctx) {
5452
+ const workflowEngine = ctx.workflowEngine;
5453
+ const workflowState = workflowEngine?.getState();
5454
+ if (!workflowState) {
5455
+ if (command.type === "slash" /* SLASH */) {
5456
+ const cmd = command.command?.toLowerCase();
5457
+ if (!ALLOWED_COMMANDS_WITHOUT_WORKFLOW.includes(cmd)) {
5458
+ return {
5459
+ allowed: false,
5460
+ 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")
5461
+ };
5462
+ }
5463
+ }
5464
+ if (command.type === "natural" /* NATURAL */) {
5465
+ return {
5466
+ allowed: false,
5467
+ 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")
5468
+ };
5469
+ }
5470
+ if (command.type === "dollar" /* DOLLAR */) {
5471
+ return {
5472
+ allowed: false,
5473
+ 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")
5474
+ };
5475
+ }
5476
+ if (command.type === "shell" /* SHELL */) {
5477
+ return {
5478
+ allowed: false,
5479
+ 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")
5480
+ };
5481
+ }
5482
+ return { allowed: true };
5483
+ }
5484
+ const currentStep = workflowState.currentStep;
5485
+ const permissions = STAGE_PERMISSIONS[currentStep];
5486
+ if (command.type === "at" /* AT */ && !permissions.canRead) {
5487
+ return {
5488
+ allowed: false,
5489
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8BFB\u53D6\u6587\u4EF6`)
5490
+ };
5491
+ }
5492
+ if (command.type === "dollar" /* DOLLAR */) {
5493
+ const agentId = command.agent?.toLowerCase().replace("$", "");
5494
+ if (!permissions.allowedAgents.includes(agentId)) {
5495
+ return {
5496
+ allowed: false,
5497
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u8C03\u7528 $${agentId} Agent`) + chalk9__default.default.gray(`
5498
+ \u5F53\u524D\u9636\u6BB5\u5141\u8BB8\u7684 Agent: ${permissions.allowedAgents.map((a) => `$${a}`).join(", ") || "\u65E0"}`)
5499
+ };
5500
+ }
5501
+ }
5502
+ if (command.type === "shell" /* SHELL */ && !permissions.canRunShell) {
5503
+ return {
5504
+ allowed: false,
5505
+ message: chalk9__default.default.yellow(`\u5F53\u524D\u9636\u6BB5 [${currentStep}] \u4E0D\u5141\u8BB8\u6267\u884C Shell \u547D\u4EE4`)
5506
+ };
5507
+ }
5508
+ return { allowed: true };
5509
+ }
5322
5510
  async executeSlashCommand(command, ctx) {
5323
5511
  const result = await runSlashCommand(
5324
5512
  command.command,
5325
5513
  command.args || [],
5326
5514
  ctx
5327
5515
  );
5328
- return { output: result.output };
5516
+ return { output: result.output, exit: result.exit };
5329
5517
  }
5330
5518
  async executeFileReference(command, ctx) {
5331
5519
  const result = await handleFileReference(command.path, ctx);
@@ -5378,7 +5566,7 @@ var ContextManager = class {
5378
5566
  }
5379
5567
  async initialize(projectPath) {
5380
5568
  this.projectPath = projectPath;
5381
- this.persistPath = path5__namespace.join(projectPath, ".sf-cli", "cache", "context", "context.json");
5569
+ this.persistPath = path6__namespace.join(projectPath, ".sf-cli", "cache", "context", "context.json");
5382
5570
  await this.loadPersistedContext();
5383
5571
  }
5384
5572
  /**
@@ -5619,15 +5807,15 @@ ${summary}`,
5619
5807
  */
5620
5808
  async persist() {
5621
5809
  if (!this.persistPath) return;
5622
- const dir = path5__namespace.dirname(this.persistPath);
5623
- await fs5__namespace.mkdir(dir, { recursive: true });
5810
+ const dir = path6__namespace.dirname(this.persistPath);
5811
+ await fs6__namespace.mkdir(dir, { recursive: true });
5624
5812
  const data = {
5625
5813
  messages: this.state.messages,
5626
5814
  totalTokens: this.state.totalTokens,
5627
5815
  limit: this.state.limit,
5628
5816
  savedAt: (/* @__PURE__ */ new Date()).toISOString()
5629
5817
  };
5630
- await fs5__namespace.writeFile(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
5818
+ await fs6__namespace.writeFile(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
5631
5819
  }
5632
5820
  /**
5633
5821
  * 加载持久化的上下文
@@ -5635,7 +5823,7 @@ ${summary}`,
5635
5823
  async loadPersistedContext() {
5636
5824
  if (!this.persistPath) return;
5637
5825
  try {
5638
- const content = await fs5__namespace.readFile(this.persistPath, "utf-8");
5826
+ const content = await fs6__namespace.readFile(this.persistPath, "utf-8");
5639
5827
  const data = JSON.parse(content);
5640
5828
  this.state.messages = data.messages || [];
5641
5829
  this.state.totalTokens = data.totalTokens || 0;
@@ -5663,11 +5851,28 @@ ${summary}`,
5663
5851
  return tokens.toString();
5664
5852
  }
5665
5853
  };
5854
+ var STEP_DISPLAY_NAMES = {
5855
+ "explore": "\u63A2\u7D22",
5856
+ "new": "\u8BBE\u8BA1",
5857
+ "continue": "\u5F00\u53D1",
5858
+ "propose": "\u63D0\u6848",
5859
+ "apply": "\u5BA1\u67E5",
5860
+ "archive": "\u5F52\u6863"
5861
+ };
5862
+ var STEP_COLORS = {
5863
+ "explore": chalk9__default.default.magenta,
5864
+ "new": chalk9__default.default.blue,
5865
+ "continue": chalk9__default.default.cyan,
5866
+ "propose": chalk9__default.default.green,
5867
+ "apply": chalk9__default.default.yellow,
5868
+ "archive": chalk9__default.default.gray
5869
+ };
5666
5870
  function displayStatus(info) {
5667
5871
  const dirDisplay = info.directory.length > 30 ? "..." + info.directory.slice(-27) : info.directory;
5668
5872
  const contextKB = Math.round(info.contextLeft / 1024);
5669
5873
  const contextDisplay = contextKB > 100 ? chalk9__default.default.green(`${contextKB}KB`) : contextKB > 50 ? chalk9__default.default.yellow(`${contextKB}KB`) : chalk9__default.default.red(`${contextKB}KB`);
5670
5874
  const servicesDisplay = info.services.length > 0 ? info.services.map((s) => `${s.name}:${s.port}`).join(", ") : chalk9__default.default.gray("\u65E0");
5875
+ const workflowDisplay = info.workflowStep ? STEP_COLORS[info.workflowStep](`[${STEP_DISPLAY_NAMES[info.workflowStep]}]`) : chalk9__default.default.gray("[\u65E0\u5DE5\u4F5C\u6D41]");
5671
5876
  console.log(chalk9__default.default.gray("\u2500".repeat(60)));
5672
5877
  console.log(
5673
5878
  chalk9__default.default.cyan("\u{1F4C1}"),
@@ -5677,7 +5882,10 @@ function displayStatus(info) {
5677
5882
  chalk9__default.default.white(info.model),
5678
5883
  chalk9__default.default.cyan("\u2502"),
5679
5884
  chalk9__default.default.cyan("\u{1F4CA}"),
5680
- contextDisplay
5885
+ contextDisplay,
5886
+ chalk9__default.default.cyan("\u2502"),
5887
+ chalk9__default.default.cyan("\u{1F504}"),
5888
+ workflowDisplay
5681
5889
  );
5682
5890
  console.log(
5683
5891
  chalk9__default.default.cyan("\u{1F50C}"),
@@ -5785,17 +5993,17 @@ var Completer = class {
5785
5993
  prefix = filePath;
5786
5994
  } else {
5787
5995
  const dir = filePath.slice(0, lastSlash);
5788
- dirPath = path5__namespace.resolve(this.workingDirectory, dir);
5996
+ dirPath = path6__namespace.resolve(this.workingDirectory, dir);
5789
5997
  prefix = filePath.slice(lastSlash + 1);
5790
5998
  }
5791
5999
  try {
5792
- const entries = await fs5__namespace.readdir(dirPath, { withFileTypes: true });
6000
+ const entries = await fs6__namespace.readdir(dirPath, { withFileTypes: true });
5793
6001
  const matches = [];
5794
6002
  for (const entry of entries) {
5795
6003
  if (entry.name.startsWith(prefix)) {
5796
6004
  const isDir = entry.isDirectory();
5797
6005
  matches.push({
5798
- text: "@" + path5__namespace.relative(this.workingDirectory, path5__namespace.join(dirPath, entry.name)).replace(/\\/g, "/") + (isDir ? "/" : ""),
6006
+ text: "@" + path6__namespace.relative(this.workingDirectory, path6__namespace.join(dirPath, entry.name)).replace(/\\/g, "/") + (isDir ? "/" : ""),
5799
6007
  displayText: entry.name + (isDir ? "/" : ""),
5800
6008
  description: isDir ? "\u76EE\u5F55" : "\u6587\u4EF6",
5801
6009
  type: isDir ? "directory" : "file"
@@ -5867,10 +6075,10 @@ var Completer = class {
5867
6075
 
5868
6076
  // src/cli/repl.ts
5869
6077
  async function startInteractiveMode(options) {
5870
- const historyFile = path5__namespace.join(options.workingDirectory, ".sf-cli", "history.json");
6078
+ const historyFile = path6__namespace.join(options.workingDirectory, ".sf-cli", "history.json");
5871
6079
  let history = [];
5872
6080
  try {
5873
- const historyData = await fs5__namespace.readFile(historyFile, "utf-8");
6081
+ const historyData = await fs6__namespace.readFile(historyFile, "utf-8");
5874
6082
  history = JSON.parse(historyData);
5875
6083
  } catch {
5876
6084
  }
@@ -5901,10 +6109,17 @@ async function startInteractiveMode(options) {
5901
6109
  const contextManager = new ContextManager();
5902
6110
  const configManager = new ConfigManager();
5903
6111
  const modelService = new ModelService(configManager);
6112
+ const workflowEngine = new WorkflowEngine();
6113
+ const normsManager = new NormsManager({
6114
+ projectPath: options.workingDirectory,
6115
+ normsDir: path6__namespace.join(options.workingDirectory, ".sf-cli", "norms")
6116
+ });
5904
6117
  await configManager.load(options.workingDirectory);
5905
6118
  await contextManager.initialize(options.workingDirectory);
5906
- const statsDir = path5__namespace.join(options.workingDirectory, ".sf-cli");
6119
+ const statsDir = path6__namespace.join(options.workingDirectory, ".sf-cli");
5907
6120
  await modelService.initialize(statsDir);
6121
+ await workflowEngine.initialize(options.workingDirectory);
6122
+ await normsManager.initialize();
5908
6123
  const state = {
5909
6124
  isRunning: true,
5910
6125
  currentTask: null,
@@ -5913,16 +6128,27 @@ async function startInteractiveMode(options) {
5913
6128
  // 512K
5914
6129
  };
5915
6130
  const currentModel = modelService.getCurrentModel() || "GLM-5";
6131
+ const workflowState = workflowEngine.getState();
5916
6132
  displayStatus({
5917
6133
  directory: options.workingDirectory,
5918
6134
  model: currentModel,
5919
6135
  contextLeft: state.contextLimit - state.contextUsed,
5920
- services: []
6136
+ services: [],
6137
+ workflowStep: workflowState?.currentStep
5921
6138
  });
6139
+ if (workflowState) {
6140
+ console.log(chalk9__default.default.cyan(`
6141
+ \u{1F4CB} \u6D3B\u8DC3\u5DE5\u4F5C\u6D41: ${workflowState.title}`));
6142
+ console.log(chalk9__default.default.gray(` \u5F53\u524D\u9636\u6BB5: ${workflowState.currentStep} | \u72B6\u6001: ${workflowState.status}`));
6143
+ console.log(chalk9__default.default.gray(` \u8F93\u5165 /opsx:status \u67E5\u770B\u8BE6\u60C5
6144
+ `));
6145
+ } else {
6146
+ console.log(chalk9__default.default.gray("\n\u{1F4A1} \u4F7F\u7528 /new <\u9700\u6C42\u63CF\u8FF0> \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41\n"));
6147
+ }
5922
6148
  const saveHistory = async () => {
5923
6149
  try {
5924
- await fs5__namespace.mkdir(path5__namespace.dirname(historyFile), { recursive: true });
5925
- await fs5__namespace.writeFile(historyFile, JSON.stringify(history.slice(-500)));
6150
+ await fs6__namespace.mkdir(path6__namespace.dirname(historyFile), { recursive: true });
6151
+ await fs6__namespace.writeFile(historyFile, JSON.stringify(history.slice(-500)));
5926
6152
  } catch {
5927
6153
  }
5928
6154
  };
@@ -5963,6 +6189,8 @@ async function startInteractiveMode(options) {
5963
6189
  contextManager,
5964
6190
  configManager,
5965
6191
  modelService,
6192
+ normsManager,
6193
+ workflowEngine,
5966
6194
  state,
5967
6195
  options
5968
6196
  });
@@ -5981,23 +6209,27 @@ async function startInteractiveMode(options) {
5981
6209
  console.log(chalk9__default.default.red(`\u9519\u8BEF: ${error.message}`));
5982
6210
  }
5983
6211
  const currentModel2 = modelService.getCurrentModel() || "GLM-5";
6212
+ const workflowState2 = workflowEngine.getState();
5984
6213
  displayStatus({
5985
6214
  directory: options.workingDirectory,
5986
6215
  model: currentModel2,
5987
6216
  contextLeft: state.contextLimit - state.contextUsed,
5988
- services: []
6217
+ services: [],
6218
+ workflowStep: workflowState2?.currentStep
5989
6219
  });
5990
6220
  rl.prompt();
5991
6221
  }
5992
6222
  }
5993
6223
 
5994
6224
  // src/cli/index.ts
5995
- var VERSION2 = "1.0.0";
6225
+ var packageJsonPath3 = path6__namespace.resolve(__dirname, "../package.json");
6226
+ var packageJson3 = JSON.parse(fsSync__namespace.readFileSync(packageJsonPath3, "utf-8"));
6227
+ var VERSION3 = packageJson3.version;
5996
6228
  var NAME = "sf-cli";
5997
- commander.program.name(NAME).description("\u4E13\u4E3A\u524D\u7AEF\u5F00\u53D1\u8BBE\u8BA1\u7684AI\u9A71\u52A8CLI\u5DE5\u5177").version(VERSION2);
6229
+ commander.program.name(NAME).description("\u4E13\u4E3A\u524D\u7AEF\u5F00\u53D1\u8BBE\u8BA1\u7684AI\u9A71\u52A8CLI\u5DE5\u5177").version(VERSION3, "-v, --version", "\u663E\u793A\u7248\u672C\u53F7");
5998
6230
  commander.program.argument("[directory]", "\u5DE5\u4F5C\u76EE\u5F55", process.cwd()).option("-m, --model <model>", "\u6307\u5B9AAI\u6A21\u578B").option("-y, --yolo", "\u81EA\u52A8\u786E\u8BA4\u6240\u6709\u64CD\u4F5C").action(async (directory, options) => {
5999
6231
  console.log(chalk9__default.default.cyan.bold(`
6000
- \u{1F680} ${NAME} v${VERSION2}`));
6232
+ \u{1F680} ${NAME} v${VERSION3}`));
6001
6233
  console.log(chalk9__default.default.gray("\u4E13\u4E3A\u524D\u7AEF\u5F00\u53D1\u8BBE\u8BA1\u7684AI\u9A71\u52A8CLI\u5DE5\u5177\n"));
6002
6234
  await startInteractiveMode({
6003
6235
  workingDirectory: directory,