@nick848/sf-cli 1.0.22 → 1.0.23

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
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk9 = require('chalk');
4
- var fs4 = require('fs/promises');
4
+ var fs9 = require('fs/promises');
5
5
  var path4 = require('path');
6
6
  var fs10 = require('fs');
7
7
  var crypto = require('crypto');
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
34
34
  }
35
35
 
36
36
  var chalk9__default = /*#__PURE__*/_interopDefault(chalk9);
37
- var fs4__namespace = /*#__PURE__*/_interopNamespace(fs4);
37
+ var fs9__namespace = /*#__PURE__*/_interopNamespace(fs9);
38
38
  var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
39
39
  var fs10__namespace = /*#__PURE__*/_interopNamespace(fs10);
40
40
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
@@ -667,24 +667,13 @@ async function executeDevelopment(ctx, session) {
667
667
  loader.start();
668
668
  try {
669
669
  const taskPrompt = buildTaskPrompt(session, item, i);
670
+ const structureInfo = session.context?.projectStructure;
671
+ const structureGuide = buildStructureGuide(structureInfo);
672
+ const systemPrompt = buildCodeGenerationSystemPrompt(session, structureGuide);
670
673
  const messages = [
671
674
  {
672
675
  role: "system",
673
- content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u4EFB\u52A1\u63CF\u8FF0\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002
674
-
675
- \u26A0\uFE0F \u91CD\u8981\u89C4\u5219\uFF1A
676
- 1. \u53EA\u751F\u6210\u5F53\u524D\u4EFB\u52A1\u76F8\u5173\u7684\u4EE3\u7801\uFF0C\u4E0D\u8981\u751F\u6210\u5176\u4ED6\u4EFB\u52A1\u7684\u4EE3\u7801
677
- 2. \u6280\u672F\u5B9E\u73B0\u5FC5\u987B\u4E25\u683C\u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u5F00\u53D1\u89C4\u8303
678
- 3. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
679
- 4. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
680
-
681
- \u9879\u76EE\u4FE1\u606F\uFF1A
682
- - \u540D\u79F0: ${session.context?.name}
683
- - \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
684
- - \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
685
-
686
- ${session.context?.devStandards ? `\u3010\u5F00\u53D1\u89C4\u8303\u3011
687
- ${session.context.devStandards.slice(0, 2e3)}` : ""}`
676
+ content: systemPrompt
688
677
  },
689
678
  {
690
679
  role: "user",
@@ -704,17 +693,17 @@ ${session.context.devStandards.slice(0, 2e3)}` : ""}`
704
693
  for (const block of codeBlocks) {
705
694
  const filePath = path4__namespace.join(workingDir, block.filename);
706
695
  const dir = path4__namespace.dirname(filePath);
707
- await fs4__namespace.mkdir(dir, { recursive: true });
708
- await fs4__namespace.writeFile(filePath, block.code, "utf-8");
696
+ await fs9__namespace.mkdir(dir, { recursive: true });
697
+ await fs9__namespace.writeFile(filePath, block.code, "utf-8");
709
698
  files.push(block.filename);
710
699
  }
711
700
  loader.stop(chalk9__default.default.green(`${prefix} \u2713 ${item.title.slice(0, 25)} (${codeBlocks.length} \u4E2A\u6587\u4EF6)`));
712
701
  } else {
713
702
  const implDir = path4__namespace.join(workingDir, "src");
714
- await fs4__namespace.mkdir(implDir, { recursive: true });
703
+ await fs9__namespace.mkdir(implDir, { recursive: true });
715
704
  const fileName = `${item.title.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_")}.ts`;
716
705
  const filePath = path4__namespace.join(implDir, fileName);
717
- await fs4__namespace.writeFile(filePath, `// TODO: ${item.title}
706
+ await fs9__namespace.writeFile(filePath, `// TODO: ${item.title}
718
707
  // ${item.description}
719
708
  `, "utf-8");
720
709
  files.push(`src/${fileName}`);
@@ -737,6 +726,91 @@ ${session.context.devStandards.slice(0, 2e3)}` : ""}`
737
726
  };
738
727
  }
739
728
  }
729
+ function buildStructureGuide(structure) {
730
+ if (!structure) {
731
+ return `## \u9879\u76EE\u7ED3\u6784
732
+ - \u7EC4\u4EF6\u653E\u5728 src/components/
733
+ - \u9875\u9762\u653E\u5728 src/pages/
734
+ - \u5DE5\u5177\u51FD\u6570\u653E\u5728 src/utils/`;
735
+ }
736
+ const lines = ["## \u9879\u76EE\u7ED3\u6784\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09"];
737
+ if (structure.hasSrc) {
738
+ lines.push(`- \u6E90\u7801\u76EE\u5F55: ${structure.srcDir}/`);
739
+ }
740
+ if (structure.hasPages) {
741
+ lines.push(`- \u9875\u9762\u76EE\u5F55: ${structure.pagesDir}/ \uFF08\u9875\u9762\u7EC4\u4EF6\u653E\u8FD9\u91CC\uFF09`);
742
+ } else {
743
+ lines.push(`- \u9875\u9762\u76EE\u5F55: src/pages/ \uFF08\u9875\u9762\u7EC4\u4EF6\u653E\u8FD9\u91CC\uFF09`);
744
+ }
745
+ if (structure.hasComponents) {
746
+ lines.push(`- \u7EC4\u4EF6\u76EE\u5F55: ${structure.componentsDir}/ \uFF08\u901A\u7528\u7EC4\u4EF6\u653E\u8FD9\u91CC\uFF09`);
747
+ } else {
748
+ lines.push(`- \u7EC4\u4EF6\u76EE\u5F55: src/components/ \uFF08\u901A\u7528\u7EC4\u4EF6\u653E\u8FD9\u91CC\uFF09`);
749
+ }
750
+ if (structure.hasApi) {
751
+ lines.push(`- API \u76EE\u5F55: src/api/ \u6216 src/services/`);
752
+ }
753
+ if (structure.hasHooks) {
754
+ lines.push(`- Hooks \u76EE\u5F55: src/hooks/`);
755
+ }
756
+ if (structure.hasStore) {
757
+ lines.push(`- \u72B6\u6001\u7BA1\u7406\u76EE\u5F55: src/store/`);
758
+ }
759
+ if (structure.hasUtils) {
760
+ lines.push(`- \u5DE5\u5177\u51FD\u6570\u76EE\u5F55: src/utils/`);
761
+ }
762
+ lines.push("");
763
+ lines.push("\u26A0\uFE0F \u6587\u4EF6\u5FC5\u987B\u653E\u5728\u4E0A\u8FF0\u5BF9\u5E94\u76EE\u5F55\u4E2D\uFF0C\u4E0D\u8981\u968F\u610F\u521B\u5EFA\u65B0\u76EE\u5F55");
764
+ return lines.join("\n");
765
+ }
766
+ function buildCodeGenerationSystemPrompt(session, structureGuide) {
767
+ const framework = session.context?.framework || "React";
768
+ const techStack = session.context?.techStack?.join(", ") || "TypeScript";
769
+ const devStandards = session.context?.devStandards || "";
770
+ const standardsText = devStandards.slice(0, 6e3);
771
+ return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u4EFB\u52A1\u63CF\u8FF0\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002
772
+
773
+ ## \u26A0\uFE0F \u6838\u5FC3\u89C4\u5219\uFF08\u5FC5\u987B\u9075\u5B88\uFF09
774
+
775
+ 1. **\u8BED\u8A00**: \u5FC5\u987B\u4F7F\u7528 TypeScript (.tsx/.ts \u6587\u4EF6)
776
+ 2. **\u6846\u67B6**: ${framework}
777
+ 3. **\u53EA\u751F\u6210\u5F53\u524D\u4EFB\u52A1\u76F8\u5173\u7684\u4EE3\u7801**\uFF0C\u4E0D\u8981\u751F\u6210\u5176\u4ED6\u4EFB\u52A1\u7684\u4EE3\u7801
778
+ 4. **\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u6B63\u786E**\uFF1A\u4E25\u683C\u6309\u7167\u9879\u76EE\u7ED3\u6784\u653E\u7F6E\u6587\u4EF6
779
+ 5. **\u5FC5\u987B\u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801**\uFF0C\u4E0D\u8981\u5199 TODO \u6216\u5360\u4F4D\u7B26
780
+ 6. **\u5982\u679C\u4EFB\u52A1\u6D89\u53CA\u9875\u9762**\uFF0C\u5FC5\u987B\u751F\u6210\u9875\u9762\u7EC4\u4EF6
781
+ 7. **\u5982\u679C\u4EFB\u52A1\u6D89\u53CA UI**\uFF0C\u5FC5\u987B\u751F\u6210\u5BF9\u5E94\u7684\u7EC4\u4EF6\u548C\u6837\u5F0F
782
+
783
+ ${structureGuide}
784
+
785
+ ## \u9879\u76EE\u4FE1\u606F
786
+
787
+ - \u540D\u79F0: ${session.context?.name || "\u672A\u547D\u540D\u9879\u76EE"}
788
+ - \u6846\u67B6: ${framework}
789
+ - \u6280\u672F\u6808: ${techStack}
790
+
791
+ ## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
792
+
793
+ ${standardsText || `### \u9ED8\u8BA4\u89C4\u8303
794
+ - \u4F7F\u7528\u51FD\u6570\u5F0F\u7EC4\u4EF6
795
+ - \u4F7F\u7528 TypeScript \u7C7B\u578B\u5B9A\u4E49
796
+ - \u4F7F\u7528 async/await \u5904\u7406\u5F02\u6B65
797
+ - \u53D8\u91CF\u4F7F\u7528 camelCase\uFF0C\u7EC4\u4EF6\u4F7F\u7528 PascalCase
798
+ - \u5BFC\u51FA\u4F7F\u7528 export default \u6216 export const`}
799
+
800
+ ## \u8F93\u51FA\u683C\u5F0F
801
+
802
+ \u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u5305\u88F9\uFF0C\u4F8B\u5982\uFF1A
803
+
804
+ \`\`\`src/pages/HomePage.tsx
805
+ // \u4EE3\u7801\u5185\u5BB9
806
+ \`\`\`
807
+
808
+ \`\`\`src/components/Button/Button.tsx
809
+ // \u4EE3\u7801\u5185\u5BB9
810
+ \`\`\`
811
+
812
+ \u73B0\u5728\u8BF7\u6839\u636E\u4EFB\u52A1\u8981\u6C42\u751F\u6210\u4EE3\u7801\u3002`;
813
+ }
740
814
  function buildTaskPrompt(session, item, index) {
741
815
  const lines = [];
742
816
  lines.push(`## \u5F53\u524D\u4EFB\u52A1 (#${index + 1})`);
@@ -791,7 +865,7 @@ async function executeReview(ctx, session) {
791
865
  const codeContents = [];
792
866
  for (const file of session.implFiles) {
793
867
  try {
794
- const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
868
+ const content = await fs9__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
795
869
  codeContents.push(`// ${file}
796
870
  ${content}`);
797
871
  } catch {
@@ -800,7 +874,7 @@ ${content}`);
800
874
  const testContents = [];
801
875
  for (const file of session.testFiles) {
802
876
  try {
803
- const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
877
+ const content = await fs9__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
804
878
  testContents.push(`// ${file}
805
879
  ${content}`);
806
880
  } catch {
@@ -894,9 +968,9 @@ async function readProjectContext(workingDir) {
894
968
  };
895
969
  const agentsPath = path4__namespace.join(workingDir, "AGENTS.md");
896
970
  try {
897
- const stats = await fs4__namespace.stat(agentsPath);
971
+ const stats = await fs9__namespace.stat(agentsPath);
898
972
  if (stats.size <= MAX_FILE_SIZE2) {
899
- context.agentsMd = await fs4__namespace.readFile(agentsPath, "utf-8");
973
+ context.agentsMd = await fs9__namespace.readFile(agentsPath, "utf-8");
900
974
  const nameMatch = context.agentsMd.match(/\|\s*项目名称\s*\|\s*([^\s|]+)/);
901
975
  if (nameMatch) context.name = nameMatch[1];
902
976
  const typeMatch = context.agentsMd.match(/\|\s*项目类型\s*\|\s*([^\s|]+)/);
@@ -910,9 +984,9 @@ async function readProjectContext(workingDir) {
910
984
  }
911
985
  const configPath = path4__namespace.join(workingDir, "openspec", "config.yaml");
912
986
  try {
913
- const stats = await fs4__namespace.stat(configPath);
987
+ const stats = await fs9__namespace.stat(configPath);
914
988
  if (stats.size <= MAX_FILE_SIZE2) {
915
- context.configYaml = await fs4__namespace.readFile(configPath, "utf-8");
989
+ context.configYaml = await fs9__namespace.readFile(configPath, "utf-8");
916
990
  const nameMatch = context.configYaml.match(/name:\s*(.+)/);
917
991
  if (nameMatch) context.name = nameMatch[1].trim();
918
992
  const typeMatch = context.configYaml.match(/type:\s*(.+)/);
@@ -933,14 +1007,173 @@ async function readProjectContext(workingDir) {
933
1007
  }
934
1008
  const devStandardsPath = path4__namespace.join(workingDir, ".sf-cli", "norms", "devstanded.md");
935
1009
  try {
936
- const stats = await fs4__namespace.stat(devStandardsPath);
1010
+ const stats = await fs9__namespace.stat(devStandardsPath);
937
1011
  if (stats.size <= MAX_FILE_SIZE2) {
938
- context.devStandards = await fs4__namespace.readFile(devStandardsPath, "utf-8");
1012
+ context.devStandards = await fs9__namespace.readFile(devStandardsPath, "utf-8");
939
1013
  }
940
1014
  } catch {
941
1015
  }
1016
+ if (!context.framework) {
1017
+ const detectedFramework = await detectFramework2(workingDir);
1018
+ if (detectedFramework) {
1019
+ context.framework = detectedFramework;
1020
+ context.techStack = [detectedFramework, ...context.techStack.filter((t) => t !== detectedFramework)];
1021
+ }
1022
+ }
1023
+ if (!context.devStandards) {
1024
+ context.devStandards = await analyzeProjectForStandards(workingDir, context);
1025
+ }
1026
+ context.projectStructure = await analyzeProjectStructure(workingDir);
942
1027
  return context;
943
1028
  }
1029
+ async function detectFramework2(workingDir) {
1030
+ try {
1031
+ const pkgPath = path4__namespace.join(workingDir, "package.json");
1032
+ const pkgContent = await fs9__namespace.readFile(pkgPath, "utf-8");
1033
+ const pkg = JSON.parse(pkgContent);
1034
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1035
+ if (deps["react"] || deps["next"]) return "React";
1036
+ if (deps["vue"] || deps["nuxt"]) return "Vue";
1037
+ if (deps["angular"] || deps["@angular/core"]) return "Angular";
1038
+ if (deps["svelte"]) return "Svelte";
1039
+ if (deps["solid-js"]) return "Solid";
1040
+ if (deps["vite"] || deps["webpack"]) return "JavaScript";
1041
+ if (deps["typescript"]) return "TypeScript";
1042
+ return null;
1043
+ } catch {
1044
+ return null;
1045
+ }
1046
+ }
1047
+ async function analyzeProjectForStandards(workingDir, context) {
1048
+ const standards = [];
1049
+ standards.push(`# \u9879\u76EE\u5F00\u53D1\u89C4\u8303\uFF08\u81EA\u52A8\u751F\u6210\uFF09
1050
+ > \u9879\u76EE\u540D\u79F0: ${context.name}
1051
+ > \u6846\u67B6: ${context.framework || "\u672A\u68C0\u6D4B\u5230"}
1052
+ > \u6280\u672F\u6808: ${context.techStack.join(", ") || "\u672A\u68C0\u6D4B\u5230"}
1053
+ `);
1054
+ try {
1055
+ const tsConfigPath = path4__namespace.join(workingDir, "tsconfig.json");
1056
+ await fs9__namespace.access(tsConfigPath);
1057
+ standards.push("\n## \u8BED\u8A00\n- \u4F7F\u7528 TypeScript");
1058
+ } catch {
1059
+ standards.push("\n## \u8BED\u8A00\n- \u4F7F\u7528 JavaScript");
1060
+ }
1061
+ try {
1062
+ const srcDir = path4__namespace.join(workingDir, "src");
1063
+ const files = await listFilesDeep(srcDir);
1064
+ const hasCss = files.some((f) => f.endsWith(".css"));
1065
+ const hasScss = files.some((f) => f.endsWith(".scss") || f.endsWith(".sass"));
1066
+ const hasLess = files.some((f) => f.endsWith(".less"));
1067
+ const hasStyled = files.some((f) => f.includes(".styled.") || f.includes("styled-components"));
1068
+ if (hasScss) standards.push("\n## \u6837\u5F0F\n- \u4F7F\u7528 SCSS/Sass");
1069
+ else if (hasLess) standards.push("\n## \u6837\u5F0F\n- \u4F7F\u7528 Less");
1070
+ else if (hasStyled) standards.push("\n## \u6837\u5F0F\n- \u4F7F\u7528 styled-components");
1071
+ else if (hasCss) standards.push("\n## \u6837\u5F0F\n- \u4F7F\u7528 CSS");
1072
+ } catch {
1073
+ }
1074
+ try {
1075
+ const srcDir = path4__namespace.join(workingDir, "src");
1076
+ const entries = await fs9__namespace.readdir(srcDir, { withFileTypes: true });
1077
+ const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
1078
+ if (dirs.includes("components")) standards.push("\n## \u76EE\u5F55\u7ED3\u6784\n- \u7EC4\u4EF6\u653E\u5728 src/components/");
1079
+ if (dirs.includes("pages") || dirs.includes("views")) standards.push("- \u9875\u9762\u653E\u5728 src/pages/ \u6216 src/views/");
1080
+ if (dirs.includes("hooks")) standards.push("- Hooks \u653E\u5728 src/hooks/");
1081
+ if (dirs.includes("utils")) standards.push("- \u5DE5\u5177\u51FD\u6570\u653E\u5728 src/utils/");
1082
+ if (dirs.includes("api") || dirs.includes("services")) standards.push("- API \u8C03\u7528\u653E\u5728 src/api/ \u6216 src/services/");
1083
+ if (dirs.includes("store") || dirs.includes("stores")) standards.push("- \u72B6\u6001\u7BA1\u7406\u653E\u5728 src/store/");
1084
+ } catch {
1085
+ }
1086
+ standards.push("\n## \u4EE3\u7801\u89C4\u8303");
1087
+ standards.push("- \u4F7F\u7528 ES6+ \u8BED\u6CD5");
1088
+ standards.push("- \u7EC4\u4EF6\u4F7F\u7528\u51FD\u6570\u5F0F\u5199\u6CD5");
1089
+ standards.push("- \u4F7F\u7528 async/await \u5904\u7406\u5F02\u6B65");
1090
+ standards.push("- \u53D8\u91CF\u4F7F\u7528 camelCase\uFF0C\u7EC4\u4EF6\u4F7F\u7528 PascalCase");
1091
+ standards.push("- \u5E38\u91CF\u4F7F\u7528 UPPER_SNAKE_CASE");
1092
+ return standards.join("\n");
1093
+ }
1094
+ async function listFilesDeep(dir, maxDepth = 3) {
1095
+ const files = [];
1096
+ async function scan(currentDir, depth) {
1097
+ if (depth > maxDepth) return;
1098
+ try {
1099
+ const entries = await fs9__namespace.readdir(currentDir, { withFileTypes: true });
1100
+ for (const entry of entries) {
1101
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
1102
+ const fullPath = path4__namespace.join(currentDir, entry.name);
1103
+ if (entry.isDirectory()) {
1104
+ await scan(fullPath, depth + 1);
1105
+ } else {
1106
+ files.push(fullPath);
1107
+ }
1108
+ }
1109
+ } catch {
1110
+ }
1111
+ }
1112
+ await scan(dir, 0);
1113
+ return files;
1114
+ }
1115
+ async function analyzeProjectStructure(workingDir) {
1116
+ const structure = {
1117
+ hasSrc: false,
1118
+ hasPages: false,
1119
+ hasComponents: false,
1120
+ hasApi: false,
1121
+ hasHooks: false,
1122
+ hasStore: false,
1123
+ hasUtils: false,
1124
+ srcDir: "src",
1125
+ pagesDir: "",
1126
+ componentsDir: ""
1127
+ };
1128
+ try {
1129
+ const srcDir = path4__namespace.join(workingDir, "src");
1130
+ try {
1131
+ const srcStat = await fs9__namespace.stat(srcDir);
1132
+ if (srcStat.isDirectory()) {
1133
+ structure.hasSrc = true;
1134
+ structure.srcDir = "src";
1135
+ const srcEntries = await fs9__namespace.readdir(srcDir, { withFileTypes: true });
1136
+ const srcDirs = srcEntries.filter((e) => e.isDirectory()).map((e) => e.name);
1137
+ if (srcDirs.includes("pages")) {
1138
+ structure.hasPages = true;
1139
+ structure.pagesDir = "src/pages";
1140
+ } else if (srcDirs.includes("views")) {
1141
+ structure.hasPages = true;
1142
+ structure.pagesDir = "src/views";
1143
+ }
1144
+ if (srcDirs.includes("components")) {
1145
+ structure.hasComponents = true;
1146
+ structure.componentsDir = "src/components";
1147
+ }
1148
+ if (srcDirs.includes("api") || srcDirs.includes("services")) {
1149
+ structure.hasApi = true;
1150
+ }
1151
+ if (srcDirs.includes("hooks")) {
1152
+ structure.hasHooks = true;
1153
+ }
1154
+ if (srcDirs.includes("store") || srcDirs.includes("stores")) {
1155
+ structure.hasStore = true;
1156
+ }
1157
+ if (srcDirs.includes("utils")) {
1158
+ structure.hasUtils = true;
1159
+ }
1160
+ }
1161
+ } catch {
1162
+ const rootEntries = await fs9__namespace.readdir(workingDir, { withFileTypes: true });
1163
+ const rootDirs = rootEntries.filter((e) => e.isDirectory()).map((e) => e.name);
1164
+ if (rootDirs.includes("pages")) {
1165
+ structure.hasPages = true;
1166
+ structure.pagesDir = "pages";
1167
+ }
1168
+ if (rootDirs.includes("components")) {
1169
+ structure.hasComponents = true;
1170
+ structure.componentsDir = "components";
1171
+ }
1172
+ }
1173
+ } catch {
1174
+ }
1175
+ return structure;
1176
+ }
944
1177
  function analyzeComplexity(requirement, context) {
945
1178
  let score = 3;
946
1179
  if (requirement.length > 100) score += 1;
@@ -1429,10 +1662,10 @@ ${feedbacks.map((f, i) => `${i + 1}. ${f}`).join("\n")}
1429
1662
  }
1430
1663
  async function saveSpecFile(workingDir, session) {
1431
1664
  const specDir = path4__namespace.join(workingDir, "openspec", "changes");
1432
- await fs4__namespace.mkdir(specDir, { recursive: true });
1665
+ await fs9__namespace.mkdir(specDir, { recursive: true });
1433
1666
  const specPath = path4__namespace.join(specDir, `${session.id}-spec.md`);
1434
1667
  const content = formatSpecFile(session);
1435
- await fs4__namespace.writeFile(specPath, content, "utf-8");
1668
+ await fs9__namespace.writeFile(specPath, content, "utf-8");
1436
1669
  return specPath;
1437
1670
  }
1438
1671
  function formatSpecFile(session) {
@@ -1517,7 +1750,7 @@ function formatSpecFile(session) {
1517
1750
  }
1518
1751
  async function generateTests(workingDir, session, ctx) {
1519
1752
  const testDir = path4__namespace.join(workingDir, "tests");
1520
- await fs4__namespace.mkdir(testDir, { recursive: true });
1753
+ await fs9__namespace.mkdir(testDir, { recursive: true });
1521
1754
  const testFiles = [];
1522
1755
  if (ctx?.modelService) {
1523
1756
  for (const scenario of session.bddScenarios) {
@@ -1527,12 +1760,12 @@ async function generateTests(workingDir, session, ctx) {
1527
1760
  loader.start();
1528
1761
  try {
1529
1762
  const content = await generateTestFileWithAI(scenario, session, ctx);
1530
- await fs4__namespace.writeFile(testPath, content, "utf-8");
1763
+ await fs9__namespace.writeFile(testPath, content, "utf-8");
1531
1764
  testFiles.push(`tests/${testName}.test.ts`);
1532
1765
  loader.stop(chalk9__default.default.green(` \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210`));
1533
1766
  } catch {
1534
1767
  const content = generateTestFile(scenario, session);
1535
- await fs4__namespace.writeFile(testPath, content, "utf-8");
1768
+ await fs9__namespace.writeFile(testPath, content, "utf-8");
1536
1769
  testFiles.push(`tests/${testName}.test.ts`);
1537
1770
  loader.stop(chalk9__default.default.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u6D4B\u8BD5\u6A21\u677F"));
1538
1771
  }
@@ -1542,7 +1775,7 @@ async function generateTests(workingDir, session, ctx) {
1542
1775
  const testName = scenario.feature.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_");
1543
1776
  const testPath = path4__namespace.join(testDir, `${testName}.test.ts`);
1544
1777
  const content = generateTestFile(scenario, session);
1545
- await fs4__namespace.writeFile(testPath, content, "utf-8");
1778
+ await fs9__namespace.writeFile(testPath, content, "utf-8");
1546
1779
  testFiles.push(`tests/${testName}.test.ts`);
1547
1780
  }
1548
1781
  }
@@ -1636,7 +1869,7 @@ function generateTestFile(scenario, session) {
1636
1869
  async function archiveWorkflow(workingDir) {
1637
1870
  if (!activeSession) return;
1638
1871
  const archiveDir = path4__namespace.join(workingDir, "openspec", "spec");
1639
- await fs4__namespace.mkdir(archiveDir, { recursive: true });
1872
+ await fs9__namespace.mkdir(archiveDir, { recursive: true });
1640
1873
  const archivePath = path4__namespace.join(archiveDir, `${activeSession.id}.md`);
1641
1874
  const content = `# \u5F52\u6863: ${activeSession.requirement.slice(0, 50)}
1642
1875
 
@@ -1663,7 +1896,7 @@ ${activeSession.refinedRequirement}
1663
1896
 
1664
1897
  ${activeSession.testFiles.map((f) => `- ${f}`).join("\n") || "\u65E0"}
1665
1898
  `;
1666
- await fs4__namespace.writeFile(archivePath, content, "utf-8");
1899
+ await fs9__namespace.writeFile(archivePath, content, "utf-8");
1667
1900
  }
1668
1901
  function generateSessionId() {
1669
1902
  const timestamp = Date.now().toString(36);
@@ -1939,7 +2172,7 @@ var ConfigManager = class {
1939
2172
  this.projectPath = projectPath;
1940
2173
  this.configPath = path4__namespace.join(projectPath, ".sf-cli", "config.json");
1941
2174
  try {
1942
- const content = await fs4__namespace.readFile(this.configPath, "utf-8");
2175
+ const content = await fs9__namespace.readFile(this.configPath, "utf-8");
1943
2176
  const loaded = JSON.parse(content);
1944
2177
  if (loaded.apiKey && loaded.apiKeyEncrypted) {
1945
2178
  loaded.apiKey = this.decrypt(loaded.apiKey);
@@ -1958,8 +2191,8 @@ var ConfigManager = class {
1958
2191
  configToSave.apiKey = encrypted;
1959
2192
  configToSave.apiKeyEncrypted = true;
1960
2193
  }
1961
- await fs4__namespace.mkdir(path4__namespace.dirname(this.configPath), { recursive: true });
1962
- await fs4__namespace.writeFile(
2194
+ await fs9__namespace.mkdir(path4__namespace.dirname(this.configPath), { recursive: true });
2195
+ await fs9__namespace.writeFile(
1963
2196
  this.configPath,
1964
2197
  JSON.stringify(configToSave, null, 2),
1965
2198
  "utf-8"
@@ -3057,8 +3290,8 @@ var ModelService = class {
3057
3290
  const dailyPath = path4__namespace.join(this.statsPath, "daily.json");
3058
3291
  const totalPath = path4__namespace.join(this.statsPath, "total.json");
3059
3292
  const [daily, total] = await Promise.all([
3060
- fs4__namespace.readFile(dailyPath, "utf-8").catch(() => "{}"),
3061
- fs4__namespace.readFile(totalPath, "utf-8").catch(() => '{"totalInput":0,"totalOutput":0}')
3293
+ fs9__namespace.readFile(dailyPath, "utf-8").catch(() => "{}"),
3294
+ fs9__namespace.readFile(totalPath, "utf-8").catch(() => '{"totalInput":0,"totalOutput":0}')
3062
3295
  ]);
3063
3296
  const dailyData = JSON.parse(daily);
3064
3297
  const totalData = JSON.parse(total);
@@ -3071,12 +3304,12 @@ var ModelService = class {
3071
3304
  async saveStats() {
3072
3305
  if (!this.statsPath) return;
3073
3306
  try {
3074
- await fs4__namespace.mkdir(this.statsPath, { recursive: true });
3307
+ await fs9__namespace.mkdir(this.statsPath, { recursive: true });
3075
3308
  const dailyPath = path4__namespace.join(this.statsPath, "daily.json");
3076
3309
  const totalPath = path4__namespace.join(this.statsPath, "total.json");
3077
3310
  await Promise.all([
3078
- fs4__namespace.writeFile(dailyPath, JSON.stringify(this.stats.byDate, null, 2)),
3079
- fs4__namespace.writeFile(totalPath, JSON.stringify({
3311
+ fs9__namespace.writeFile(dailyPath, JSON.stringify(this.stats.byDate, null, 2)),
3312
+ fs9__namespace.writeFile(totalPath, JSON.stringify({
3080
3313
  totalInput: this.stats.totalInput,
3081
3314
  totalOutput: this.stats.totalOutput
3082
3315
  }))
@@ -4785,15 +5018,15 @@ async function loadProjectContext(workingDirectory) {
4785
5018
  devStandards: ""
4786
5019
  };
4787
5020
  try {
4788
- context.agentsMd = await fs4__namespace.readFile(path4__namespace.join(workingDirectory, "AGENTS.md"), "utf-8");
5021
+ context.agentsMd = await fs9__namespace.readFile(path4__namespace.join(workingDirectory, "AGENTS.md"), "utf-8");
4789
5022
  } catch {
4790
5023
  }
4791
5024
  try {
4792
- context.configYaml = await fs4__namespace.readFile(path4__namespace.join(workingDirectory, "openspec", "config.yaml"), "utf-8");
5025
+ context.configYaml = await fs9__namespace.readFile(path4__namespace.join(workingDirectory, "openspec", "config.yaml"), "utf-8");
4793
5026
  } catch {
4794
5027
  }
4795
5028
  try {
4796
- context.devStandards = await fs4__namespace.readFile(path4__namespace.join(workingDirectory, ".sf-cli", "norms", "devstanded.md"), "utf-8");
5029
+ context.devStandards = await fs9__namespace.readFile(path4__namespace.join(workingDirectory, ".sf-cli", "norms", "devstanded.md"), "utf-8");
4797
5030
  } catch {
4798
5031
  }
4799
5032
  return context;
@@ -5756,19 +5989,19 @@ var WorkflowEngine = class {
5756
5989
  async loadProjectContext() {
5757
5990
  const agentsMdPath = path4__namespace.join(this.projectPath, "AGENTS.md");
5758
5991
  try {
5759
- this.projectContext = await fs4__namespace.readFile(agentsMdPath, "utf-8");
5992
+ this.projectContext = await fs9__namespace.readFile(agentsMdPath, "utf-8");
5760
5993
  } catch {
5761
5994
  this.projectContext = "";
5762
5995
  }
5763
5996
  const configPath = path4__namespace.join(this.openspecPath, "config.yaml");
5764
5997
  try {
5765
- this.projectConfig = await fs4__namespace.readFile(configPath, "utf-8");
5998
+ this.projectConfig = await fs9__namespace.readFile(configPath, "utf-8");
5766
5999
  } catch {
5767
6000
  this.projectConfig = "";
5768
6001
  }
5769
6002
  const devstandedPath = path4__namespace.join(this.projectPath, ".sf-cli", "norms", "devstanded.md");
5770
6003
  try {
5771
- this.devStandards = await fs4__namespace.readFile(devstandedPath, "utf-8");
6004
+ this.devStandards = await fs9__namespace.readFile(devstandedPath, "utf-8");
5772
6005
  } catch {
5773
6006
  this.devStandards = "";
5774
6007
  }
@@ -5797,7 +6030,7 @@ var WorkflowEngine = class {
5797
6030
  const specPath = this.getSpecFilePath();
5798
6031
  if (!specPath) return false;
5799
6032
  try {
5800
- await fs4__namespace.access(specPath);
6033
+ await fs9__namespace.access(specPath);
5801
6034
  return true;
5802
6035
  } catch {
5803
6036
  return false;
@@ -6031,11 +6264,11 @@ var WorkflowEngine = class {
6031
6264
  const workflows = [];
6032
6265
  const changesDir = path4__namespace.join(this.openspecPath, "changes");
6033
6266
  try {
6034
- const files = await fs4__namespace.readdir(changesDir);
6267
+ const files = await fs9__namespace.readdir(changesDir);
6035
6268
  for (const file of files) {
6036
6269
  if (!file.endsWith(".md") || file.includes("-spec.md")) continue;
6037
6270
  const filePath = path4__namespace.join(changesDir, file);
6038
- const content = await fs4__namespace.readFile(filePath, "utf-8");
6271
+ const content = await fs9__namespace.readFile(filePath, "utf-8");
6039
6272
  const state = this.parseChangeRecord(content);
6040
6273
  if (state && state.status === "running") {
6041
6274
  workflows.push(state);
@@ -6086,7 +6319,7 @@ var WorkflowEngine = class {
6086
6319
  }
6087
6320
  const statePath = path4__namespace.join(this.openspecPath, ".workflow-states", `${changeId}.json`);
6088
6321
  try {
6089
- const content = await fs4__namespace.readFile(statePath, "utf-8");
6322
+ const content = await fs9__namespace.readFile(statePath, "utf-8");
6090
6323
  this.state = JSON.parse(content, (key, value) => {
6091
6324
  if (key.endsWith("At") && typeof value === "string") {
6092
6325
  return new Date(value);
@@ -6099,7 +6332,7 @@ var WorkflowEngine = class {
6099
6332
  const changesDir = path4__namespace.join(this.openspecPath, "changes");
6100
6333
  const changeFile = path4__namespace.join(changesDir, `${changeId}.md`);
6101
6334
  try {
6102
- const content = await fs4__namespace.readFile(changeFile, "utf-8");
6335
+ const content = await fs9__namespace.readFile(changeFile, "utf-8");
6103
6336
  const parsed = this.parseChangeRecord(content);
6104
6337
  if (parsed && parsed.status === "running") {
6105
6338
  this.state = parsed;
@@ -6164,8 +6397,8 @@ var WorkflowEngine = class {
6164
6397
  const archiveDir = path4__namespace.join(changesDir, "archive");
6165
6398
  const changeFile = path4__namespace.join(changesDir, `${changeId}.md`);
6166
6399
  const archiveFile = path4__namespace.join(archiveDir, `${changeId}.md`);
6167
- await fs4__namespace.mkdir(archiveDir, { recursive: true });
6168
- await fs4__namespace.rename(changeFile, archiveFile).catch(() => {
6400
+ await fs9__namespace.mkdir(archiveDir, { recursive: true });
6401
+ await fs9__namespace.rename(changeFile, archiveFile).catch(() => {
6169
6402
  });
6170
6403
  this.state = null;
6171
6404
  this.snapshots.clear();
@@ -6191,15 +6424,15 @@ var WorkflowEngine = class {
6191
6424
  const archiveDir = path4__namespace.join(changesDir, "archive");
6192
6425
  const specDir = path4__namespace.join(this.openspecPath, "spec");
6193
6426
  const statesDir = path4__namespace.join(this.openspecPath, ".workflow-states");
6194
- await fs4__namespace.mkdir(archiveDir, { recursive: true });
6195
- await fs4__namespace.mkdir(specDir, { recursive: true });
6196
- await fs4__namespace.mkdir(statesDir, { recursive: true });
6427
+ await fs9__namespace.mkdir(archiveDir, { recursive: true });
6428
+ await fs9__namespace.mkdir(specDir, { recursive: true });
6429
+ await fs9__namespace.mkdir(statesDir, { recursive: true });
6197
6430
  }
6198
6431
  async restoreState() {
6199
6432
  const activePath = path4__namespace.join(this.openspecPath, ".workflow-active.json");
6200
6433
  let activeId = null;
6201
6434
  try {
6202
- const activeContent = await fs4__namespace.readFile(activePath, "utf-8");
6435
+ const activeContent = await fs9__namespace.readFile(activePath, "utf-8");
6203
6436
  const activeData = JSON.parse(activeContent);
6204
6437
  activeId = activeData.activeId;
6205
6438
  } catch {
@@ -6207,7 +6440,7 @@ var WorkflowEngine = class {
6207
6440
  if (activeId) {
6208
6441
  const statePath = path4__namespace.join(this.openspecPath, ".workflow-states", `${activeId}.json`);
6209
6442
  try {
6210
- const content = await fs4__namespace.readFile(statePath, "utf-8");
6443
+ const content = await fs9__namespace.readFile(statePath, "utf-8");
6211
6444
  this.state = JSON.parse(content, (key, value) => {
6212
6445
  if (key.endsWith("At") && typeof value === "string") {
6213
6446
  return new Date(value);
@@ -6220,7 +6453,7 @@ var WorkflowEngine = class {
6220
6453
  }
6221
6454
  const oldStatePath = path4__namespace.join(this.openspecPath, ".workflow-state.json");
6222
6455
  try {
6223
- const content = await fs4__namespace.readFile(oldStatePath, "utf-8");
6456
+ const content = await fs9__namespace.readFile(oldStatePath, "utf-8");
6224
6457
  this.state = JSON.parse(content, (key, value) => {
6225
6458
  if (key.endsWith("At") && typeof value === "string") {
6226
6459
  return new Date(value);
@@ -6229,7 +6462,7 @@ var WorkflowEngine = class {
6229
6462
  });
6230
6463
  if (this.state) {
6231
6464
  await this.saveState();
6232
- await fs4__namespace.unlink(oldStatePath).catch(() => {
6465
+ await fs9__namespace.unlink(oldStatePath).catch(() => {
6233
6466
  });
6234
6467
  }
6235
6468
  } catch (e) {
@@ -6243,16 +6476,16 @@ var WorkflowEngine = class {
6243
6476
  async saveState() {
6244
6477
  if (!this.state) return;
6245
6478
  const statesDir = path4__namespace.join(this.openspecPath, ".workflow-states");
6246
- await fs4__namespace.mkdir(statesDir, { recursive: true });
6479
+ await fs9__namespace.mkdir(statesDir, { recursive: true });
6247
6480
  const statePath = path4__namespace.join(statesDir, `${this.state.id}.json`);
6248
- await fs4__namespace.writeFile(statePath, JSON.stringify(this.state, null, 2));
6481
+ await fs9__namespace.writeFile(statePath, JSON.stringify(this.state, null, 2));
6249
6482
  const activePath = path4__namespace.join(this.openspecPath, ".workflow-active.json");
6250
- await fs4__namespace.writeFile(activePath, JSON.stringify({ activeId: this.state.id }, null, 2));
6483
+ await fs9__namespace.writeFile(activePath, JSON.stringify({ activeId: this.state.id }, null, 2));
6251
6484
  }
6252
6485
  async restoreSnapshots() {
6253
6486
  const snapshotsPath = path4__namespace.join(this.openspecPath, ".workflow-snapshots.json");
6254
6487
  try {
6255
- const content = await fs4__namespace.readFile(snapshotsPath, "utf-8");
6488
+ const content = await fs9__namespace.readFile(snapshotsPath, "utf-8");
6256
6489
  const data = JSON.parse(content, (key, value) => {
6257
6490
  if (key === "timestamp" && typeof value === "string") {
6258
6491
  return new Date(value);
@@ -6269,7 +6502,7 @@ var WorkflowEngine = class {
6269
6502
  async saveSnapshots() {
6270
6503
  const snapshotsPath = path4__namespace.join(this.openspecPath, ".workflow-snapshots.json");
6271
6504
  const data = Array.from(this.snapshots.values());
6272
- await fs4__namespace.writeFile(snapshotsPath, JSON.stringify(data, null, 2));
6505
+ await fs9__namespace.writeFile(snapshotsPath, JSON.stringify(data, null, 2));
6273
6506
  }
6274
6507
  async createSnapshot() {
6275
6508
  if (!this.state) return;
@@ -6290,7 +6523,7 @@ var WorkflowEngine = class {
6290
6523
  async createChangeRecord() {
6291
6524
  if (!this.state) return;
6292
6525
  const changePath = path4__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
6293
- await fs4__namespace.writeFile(changePath, this.formatChangeRecord());
6526
+ await fs9__namespace.writeFile(changePath, this.formatChangeRecord());
6294
6527
  }
6295
6528
  async updateChangeRecord(status) {
6296
6529
  if (!this.state) return;
@@ -6298,7 +6531,7 @@ var WorkflowEngine = class {
6298
6531
  this.state.status = status;
6299
6532
  }
6300
6533
  const changePath = path4__namespace.join(this.openspecPath, "changes", `${this.state.id}.md`);
6301
- await fs4__namespace.writeFile(changePath, this.formatChangeRecord());
6534
+ await fs9__namespace.writeFile(changePath, this.formatChangeRecord());
6302
6535
  }
6303
6536
  formatChangeRecord() {
6304
6537
  if (!this.state) return "";
@@ -6362,7 +6595,7 @@ ${this.state.steps.map((s) => `- [${s.status === "completed" ? "x" : " "}] ${s.s
6362
6595
 
6363
6596
  ${this.state.artifacts.map((a) => `- ${a}`).join("\n") || "\u6682\u65E0"}
6364
6597
  `;
6365
- await fs4__namespace.writeFile(specPath, content);
6598
+ await fs9__namespace.writeFile(specPath, content);
6366
6599
  }
6367
6600
  };
6368
6601
  var ConfirmationRequiredError = class extends Error {
@@ -6411,11 +6644,11 @@ var NormsManager = class {
6411
6644
  const files = await this.collectProjectFiles(projectPath);
6412
6645
  for (const filePath of files.slice(0, MAX_FILES_TO_SCAN)) {
6413
6646
  try {
6414
- const stats = await fs4__namespace.stat(filePath);
6647
+ const stats = await fs9__namespace.stat(filePath);
6415
6648
  if (stats.size > MAX_FILE_SIZE) {
6416
6649
  continue;
6417
6650
  }
6418
- const content = await fs4__namespace.readFile(filePath, "utf-8");
6651
+ const content = await fs9__namespace.readFile(filePath, "utf-8");
6419
6652
  const patterns = await this.learnFromFile(filePath, content);
6420
6653
  result.patternsFound += patterns.length;
6421
6654
  result.filesScanned++;
@@ -7041,7 +7274,7 @@ ${response}`;
7041
7274
  const files = [];
7042
7275
  async function scan(dir) {
7043
7276
  try {
7044
- const entries = await fs4__namespace.readdir(dir, { withFileTypes: true });
7277
+ const entries = await fs9__namespace.readdir(dir, { withFileTypes: true });
7045
7278
  for (const entry of entries) {
7046
7279
  if (entry.isDirectory()) {
7047
7280
  if (!IGNORED_DIRS.includes(entry.name)) {
@@ -7084,8 +7317,8 @@ ${response}`;
7084
7317
  * 确保规范目录存在
7085
7318
  */
7086
7319
  async ensureNormsDir() {
7087
- await fs4__namespace.mkdir(this.config.normsDir, { recursive: true });
7088
- await fs4__namespace.mkdir(path4__namespace.join(this.config.normsDir, "weekly"), { recursive: true });
7320
+ await fs9__namespace.mkdir(this.config.normsDir, { recursive: true });
7321
+ await fs9__namespace.mkdir(path4__namespace.join(this.config.normsDir, "weekly"), { recursive: true });
7089
7322
  }
7090
7323
  /**
7091
7324
  * 加载已有规范
@@ -7093,7 +7326,7 @@ ${response}`;
7093
7326
  async loadStandards() {
7094
7327
  const standardsPath = path4__namespace.join(this.config.normsDir, "patterns.json");
7095
7328
  try {
7096
- const content = await fs4__namespace.readFile(standardsPath, "utf-8");
7329
+ const content = await fs9__namespace.readFile(standardsPath, "utf-8");
7097
7330
  const data = JSON.parse(content);
7098
7331
  for (const standard of data) {
7099
7332
  this.standards.set(standard.id, {
@@ -7111,7 +7344,7 @@ ${response}`;
7111
7344
  async loadWeights() {
7112
7345
  const weightsPath = path4__namespace.join(this.config.normsDir, "weights.json");
7113
7346
  try {
7114
- const content = await fs4__namespace.readFile(weightsPath, "utf-8");
7347
+ const content = await fs9__namespace.readFile(weightsPath, "utf-8");
7115
7348
  const data = JSON.parse(content);
7116
7349
  for (const weight of data) {
7117
7350
  this.weights.set(weight.standardId, {
@@ -7127,7 +7360,7 @@ ${response}`;
7127
7360
  */
7128
7361
  async saveStandards() {
7129
7362
  const standardsPath = path4__namespace.join(this.config.normsDir, "patterns.json");
7130
- await fs4__namespace.writeFile(
7363
+ await fs9__namespace.writeFile(
7131
7364
  standardsPath,
7132
7365
  JSON.stringify(Array.from(this.standards.values()), null, 2),
7133
7366
  "utf-8"
@@ -7138,7 +7371,7 @@ ${response}`;
7138
7371
  */
7139
7372
  async saveWeights() {
7140
7373
  const weightsPath = path4__namespace.join(this.config.normsDir, "weights.json");
7141
- await fs4__namespace.writeFile(
7374
+ await fs9__namespace.writeFile(
7142
7375
  weightsPath,
7143
7376
  JSON.stringify(Array.from(this.weights.values()), null, 2),
7144
7377
  "utf-8"
@@ -7166,7 +7399,7 @@ ${response}`;
7166
7399
  */
7167
7400
  async saveWeeklyReport(weekId, report) {
7168
7401
  const reportPath = path4__namespace.join(this.config.normsDir, "weekly", `${weekId}.json`);
7169
- await fs4__namespace.writeFile(reportPath, JSON.stringify(report, null, 2), "utf-8");
7402
+ await fs9__namespace.writeFile(reportPath, JSON.stringify(report, null, 2), "utf-8");
7170
7403
  }
7171
7404
  /**
7172
7405
  * 更新 devstanded.md
@@ -7175,7 +7408,7 @@ ${response}`;
7175
7408
  const standards = this.getEffectiveStandards();
7176
7409
  const content = this.generateDevStandedMd(standards);
7177
7410
  const mdPath = path4__namespace.join(this.config.normsDir, "devstanded.md");
7178
- await fs4__namespace.writeFile(mdPath, content, "utf-8");
7411
+ await fs9__namespace.writeFile(mdPath, content, "utf-8");
7179
7412
  }
7180
7413
  /**
7181
7414
  * 生成 devstanded.md 内容
@@ -7567,14 +7800,14 @@ ${summary}`,
7567
7800
  async persist() {
7568
7801
  if (!this.persistPath) return;
7569
7802
  const dir = path4__namespace.dirname(this.persistPath);
7570
- await fs4__namespace.mkdir(dir, { recursive: true });
7803
+ await fs9__namespace.mkdir(dir, { recursive: true });
7571
7804
  const data = {
7572
7805
  messages: this.state.messages,
7573
7806
  totalTokens: this.state.totalTokens,
7574
7807
  limit: this.state.limit,
7575
7808
  savedAt: (/* @__PURE__ */ new Date()).toISOString()
7576
7809
  };
7577
- await fs4__namespace.writeFile(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
7810
+ await fs9__namespace.writeFile(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
7578
7811
  }
7579
7812
  /**
7580
7813
  * 加载持久化的上下文
@@ -7582,7 +7815,7 @@ ${summary}`,
7582
7815
  async loadPersistedContext() {
7583
7816
  if (!this.persistPath) return;
7584
7817
  try {
7585
- const content = await fs4__namespace.readFile(this.persistPath, "utf-8");
7818
+ const content = await fs9__namespace.readFile(this.persistPath, "utf-8");
7586
7819
  const data = JSON.parse(content);
7587
7820
  this.state.messages = data.messages || [];
7588
7821
  this.state.totalTokens = data.totalTokens || 0;
@@ -7799,7 +8032,7 @@ async function handleInit(args, ctx) {
7799
8032
  async function initProject(options = {}, workingDir) {
7800
8033
  const cwd = workingDir || process.cwd();
7801
8034
  try {
7802
- const stats = await fs4__namespace.stat(cwd);
8035
+ const stats = await fs9__namespace.stat(cwd);
7803
8036
  if (!stats.isDirectory()) {
7804
8037
  return {
7805
8038
  output: chalk9__default.default.red(`\u9519\u8BEF: ${cwd} \u4E0D\u662F\u6709\u6548\u76EE\u5F55`)
@@ -7831,7 +8064,7 @@ async function initProject(options = {}, workingDir) {
7831
8064
  await normsManager.initialize();
7832
8065
  const scanResult = await normsManager.scanProject(cwd);
7833
8066
  const agentsContent = generateAgentsMd(projectInfo, scanResult);
7834
- await fs4__namespace.writeFile(agentsMdPath, agentsContent, "utf-8");
8067
+ await fs9__namespace.writeFile(agentsMdPath, agentsContent, "utf-8");
7835
8068
  await generateOpenSpecConfig(openspecDir, projectInfo);
7836
8069
  return {
7837
8070
  output: chalk9__default.default.green("\u2713 \u9879\u76EE\u521D\u59CB\u5316\u5B8C\u6210\n") + chalk9__default.default.gray(` \u9879\u76EE\u7C7B\u578B: ${projectInfo.type}
@@ -7872,7 +8105,7 @@ async function createSfCliDirectory(basePath) {
7872
8105
  "logs"
7873
8106
  ];
7874
8107
  for (const dir of dirs) {
7875
- await fs4__namespace.mkdir(path4__namespace.join(basePath, dir), { recursive: true });
8108
+ await fs9__namespace.mkdir(path4__namespace.join(basePath, dir), { recursive: true });
7876
8109
  }
7877
8110
  const config = {
7878
8111
  version: "1.0.0",
@@ -7880,22 +8113,22 @@ async function createSfCliDirectory(basePath) {
7880
8113
  yolo: false,
7881
8114
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
7882
8115
  };
7883
- await fs4__namespace.writeFile(
8116
+ await fs9__namespace.writeFile(
7884
8117
  path4__namespace.join(basePath, "config.json"),
7885
8118
  JSON.stringify(config, null, 2),
7886
8119
  "utf-8"
7887
8120
  );
7888
- await fs4__namespace.writeFile(
8121
+ await fs9__namespace.writeFile(
7889
8122
  path4__namespace.join(basePath, "agents", "registry.json"),
7890
8123
  JSON.stringify({ version: "1.0.0", agents: {} }, null, 2),
7891
8124
  "utf-8"
7892
8125
  );
7893
- await fs4__namespace.writeFile(
8126
+ await fs9__namespace.writeFile(
7894
8127
  path4__namespace.join(basePath, "skills", "registry.json"),
7895
8128
  JSON.stringify({ version: "1.0.0", skills: {} }, null, 2),
7896
8129
  "utf-8"
7897
8130
  );
7898
- await fs4__namespace.writeFile(
8131
+ await fs9__namespace.writeFile(
7899
8132
  path4__namespace.join(basePath, "health", "health.md"),
7900
8133
  generateHealthTemplate(),
7901
8134
  "utf-8"
@@ -7905,8 +8138,8 @@ async function createOpenSpecDirectory(basePath) {
7905
8138
  const changesDir = path4__namespace.join(basePath, "changes");
7906
8139
  const archiveDir = path4__namespace.join(changesDir, "archive");
7907
8140
  const specDir = path4__namespace.join(basePath, "spec");
7908
- await fs4__namespace.mkdir(archiveDir, { recursive: true });
7909
- await fs4__namespace.mkdir(specDir, { recursive: true });
8141
+ await fs9__namespace.mkdir(archiveDir, { recursive: true });
8142
+ await fs9__namespace.mkdir(specDir, { recursive: true });
7910
8143
  }
7911
8144
  async function analyzeProject(cwd) {
7912
8145
  const result = {
@@ -7931,7 +8164,7 @@ async function analyzeProject(cwd) {
7931
8164
  };
7932
8165
  const pkgPath = path4__namespace.join(cwd, "package.json");
7933
8166
  try {
7934
- const pkgContent = await fs4__namespace.readFile(pkgPath, "utf-8");
8167
+ const pkgContent = await fs9__namespace.readFile(pkgPath, "utf-8");
7935
8168
  const pkg = JSON.parse(pkgContent);
7936
8169
  result.name = pkg.name || result.name;
7937
8170
  result.dependencies = pkg.dependencies || {};
@@ -8014,7 +8247,7 @@ async function analyzeDirectoryStructure(cwd) {
8014
8247
  others: []
8015
8248
  };
8016
8249
  try {
8017
- const entries = await fs4__namespace.readdir(cwd, { withFileTypes: true });
8250
+ const entries = await fs9__namespace.readdir(cwd, { withFileTypes: true });
8018
8251
  for (const entry of entries) {
8019
8252
  if (!entry.isDirectory()) continue;
8020
8253
  const name = entry.name;
@@ -8059,7 +8292,7 @@ async function findEntryPoints(cwd) {
8059
8292
  }
8060
8293
  async function saveProjectAnalysis(sfCliDir, analysis) {
8061
8294
  const analysisPath = path4__namespace.join(sfCliDir, "cache", "analysis", "project-analysis.json");
8062
- await fs4__namespace.writeFile(
8295
+ await fs9__namespace.writeFile(
8063
8296
  analysisPath,
8064
8297
  JSON.stringify(analysis, null, 2),
8065
8298
  "utf-8"
@@ -8100,7 +8333,7 @@ architecture:
8100
8333
  # \u5F00\u53D1\u89C4\u8303 (\u4ECE\u4EE3\u7801\u4E2D\u5B66\u4E60)
8101
8334
  standards: []
8102
8335
  `;
8103
- await fs4__namespace.writeFile(configPath, content, "utf-8");
8336
+ await fs9__namespace.writeFile(configPath, content, "utf-8");
8104
8337
  }
8105
8338
  function generateAgentsMd(info, scanResult) {
8106
8339
  const techStackList = info.techStack.length > 0 ? info.techStack.map((t) => `| ${t} | \u2713 |`).join("\n") : "| \u5F85\u8BC6\u522B | - |";
@@ -8222,7 +8455,7 @@ function generateHealthTemplate() {
8222
8455
  }
8223
8456
  async function fileExists(filePath) {
8224
8457
  try {
8225
- await fs4__namespace.access(filePath);
8458
+ await fs9__namespace.access(filePath);
8226
8459
  return true;
8227
8460
  } catch {
8228
8461
  return false;
@@ -9657,9 +9890,9 @@ async function handleFileReference(filePath, ctx) {
9657
9890
  const cwd = ctx.options.workingDirectory;
9658
9891
  const absolutePath = path4__namespace.isAbsolute(filePath) ? filePath : path4__namespace.join(cwd, filePath);
9659
9892
  try {
9660
- const stats = await fs4__namespace.stat(absolutePath);
9893
+ const stats = await fs9__namespace.stat(absolutePath);
9661
9894
  if (stats.isDirectory()) {
9662
- const files = await fs4__namespace.readdir(absolutePath);
9895
+ const files = await fs9__namespace.readdir(absolutePath);
9663
9896
  return {
9664
9897
  output: chalk9__default.default.cyan(`\u{1F4C1} ${filePath}/`) + chalk9__default.default.gray(`
9665
9898
  ${files.slice(0, 20).join("\n")}`) + (files.length > 20 ? chalk9__default.default.gray(`
@@ -9667,7 +9900,7 @@ ${files.slice(0, 20).join("\n")}`) + (files.length > 20 ? chalk9__default.defaul
9667
9900
  contextUsed: 0
9668
9901
  };
9669
9902
  }
9670
- const content = await fs4__namespace.readFile(absolutePath, "utf-8");
9903
+ const content = await fs9__namespace.readFile(absolutePath, "utf-8");
9671
9904
  const lines = content.split("\n");
9672
9905
  ctx.contextManager.addMessage({
9673
9906
  role: "user",
@@ -10096,7 +10329,7 @@ var Completer = class {
10096
10329
  prefix = filePath.slice(lastSlash + 1);
10097
10330
  }
10098
10331
  try {
10099
- const entries = await fs4__namespace.readdir(dirPath, { withFileTypes: true });
10332
+ const entries = await fs9__namespace.readdir(dirPath, { withFileTypes: true });
10100
10333
  const matches = [];
10101
10334
  for (const entry of entries) {
10102
10335
  if (entry.name.startsWith(prefix)) {