intention-coding 0.6.3 → 0.6.5

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.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
4
  return 'undefined' == typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
@@ -11115,6 +11116,1559 @@ ${requirement_description}
11115
11116
  function getTechSpecOutputDir(projectPath) {
11116
11117
  return `${projectPath}/${TECH_SPEC_OUTPUT_DIR}`;
11117
11118
  }
11119
+ const FILE_TYPE_PATTERNS = {
11120
+ controller: [
11121
+ /Controller\.(ts|js|java)$/i,
11122
+ /controller\.(ts|js|java)$/i,
11123
+ /@Controller/,
11124
+ /@RestController/
11125
+ ],
11126
+ service: [
11127
+ /Service\.(ts|js|java)$/i,
11128
+ /service\.(ts|js|java)$/i,
11129
+ /@Service/,
11130
+ /ServiceImpl\.(ts|js|java)$/i
11131
+ ],
11132
+ entity: [
11133
+ /Entity\.(ts|js|java)$/i,
11134
+ /entity\.(ts|js|java)$/i,
11135
+ /Model\.(ts|js|java)$/i,
11136
+ /model\.(ts|js|java)$/i,
11137
+ /@Entity/,
11138
+ /@Table/
11139
+ ],
11140
+ dto: [
11141
+ /DTO\.(ts|js|java)$/i,
11142
+ /dto\.(ts|js|java)$/i,
11143
+ /Vo\.(ts|js|java)$/i,
11144
+ /vo\.(ts|js|java)$/i,
11145
+ /Bo\.(ts|js|java)$/i,
11146
+ /bo\.(ts|js|java)$/i,
11147
+ /Request\.(ts|js|java)$/i,
11148
+ /Response\.(ts|js|java)$/i,
11149
+ /Query\.(ts|js|java)$/i,
11150
+ /Form\.(ts|js|java)$/i
11151
+ ],
11152
+ config: [
11153
+ /Config\.(ts|js|java)$/i,
11154
+ /config\.(ts|js|java)$/i,
11155
+ /Configuration\.(ts|js|java)$/i,
11156
+ /@Configuration/
11157
+ ]
11158
+ };
11159
+ const IGNORE_PATTERNS = [
11160
+ "node_modules",
11161
+ ".git",
11162
+ ".svn",
11163
+ "target",
11164
+ "build",
11165
+ "dist",
11166
+ ".idea",
11167
+ ".vscode",
11168
+ "logs",
11169
+ "temp",
11170
+ "tmp",
11171
+ ".DS_Store",
11172
+ "Thumbs.db",
11173
+ "*.log",
11174
+ "*.tmp",
11175
+ "*.bak"
11176
+ ];
11177
+ function shouldIgnore(filePath) {
11178
+ const fileName = external_path_namespaceObject.basename(filePath);
11179
+ const dirName = external_path_namespaceObject.dirname(filePath);
11180
+ return IGNORE_PATTERNS.some((pattern)=>{
11181
+ if (pattern.includes("*")) {
11182
+ const regex = new RegExp(pattern.replace(/\*/g, ".*"));
11183
+ return regex.test(fileName);
11184
+ }
11185
+ return fileName === pattern || dirName.includes(pattern) || filePath.includes(pattern);
11186
+ });
11187
+ }
11188
+ async function identifyFileType(filePath) {
11189
+ const fileName = external_path_namespaceObject.basename(filePath);
11190
+ for (const [type, patterns] of Object.entries(FILE_TYPE_PATTERNS))for (const pattern of patterns)if (pattern instanceof RegExp) {
11191
+ if (pattern.test(fileName)) return type;
11192
+ }
11193
+ try {
11194
+ const stats = await promises_namespaceObject.stat(filePath);
11195
+ if (stats.size < 51200) {
11196
+ const content = await promises_namespaceObject.readFile(filePath, "utf-8");
11197
+ for (const [type, patterns] of Object.entries(FILE_TYPE_PATTERNS))for (const pattern of patterns)if (pattern instanceof RegExp && pattern.test(content)) return type;
11198
+ }
11199
+ } catch (error) {}
11200
+ return "other";
11201
+ }
11202
+ async function scanDirectory(dirPath, projectPath, currentModule) {
11203
+ const files = [];
11204
+ try {
11205
+ const entries = await promises_namespaceObject.readdir(dirPath, {
11206
+ withFileTypes: true
11207
+ });
11208
+ for (const entry of entries){
11209
+ const fullPath = external_path_namespaceObject.join(dirPath, entry.name);
11210
+ const relativePath = external_path_namespaceObject.relative(projectPath, fullPath);
11211
+ if (!shouldIgnore(fullPath)) {
11212
+ if (entry.isDirectory()) {
11213
+ const subFiles = await scanDirectory(fullPath, projectPath, currentModule);
11214
+ files.push(...subFiles);
11215
+ } else if (entry.isFile()) {
11216
+ const ext = external_path_namespaceObject.extname(entry.name).toLowerCase();
11217
+ if ([
11218
+ ".ts",
11219
+ ".js",
11220
+ ".java",
11221
+ ".kt",
11222
+ ".py",
11223
+ ".go",
11224
+ ".cs"
11225
+ ].includes(ext)) {
11226
+ const fileType = await identifyFileType(fullPath);
11227
+ files.push({
11228
+ path: fullPath,
11229
+ name: entry.name,
11230
+ type: fileType,
11231
+ relativePath,
11232
+ module: currentModule
11233
+ });
11234
+ }
11235
+ }
11236
+ }
11237
+ }
11238
+ } catch (error) {
11239
+ logger.warn(`\u{626B}\u{63CF}\u{76EE}\u{5F55}\u{5931}\u{8D25}: ${dirPath}`, {
11240
+ error
11241
+ });
11242
+ }
11243
+ return files;
11244
+ }
11245
+ function identifyModules(files, projectPath) {
11246
+ const moduleMap = new Map();
11247
+ for (const file of files){
11248
+ const pathParts = file.relativePath.split(external_path_namespaceObject.sep);
11249
+ let moduleName = "default";
11250
+ if (pathParts.includes("src") && pathParts.includes("main") && pathParts.includes("java")) {
11251
+ const javaIndex = pathParts.indexOf("java");
11252
+ if (javaIndex + 3 < pathParts.length) moduleName = pathParts[javaIndex + 3];
11253
+ } else if (pathParts.includes("modules") || pathParts.includes("packages")) {
11254
+ const moduleIndex = pathParts.findIndex((p)=>"modules" === p || "packages" === p);
11255
+ if (moduleIndex + 1 < pathParts.length) moduleName = pathParts[moduleIndex + 1];
11256
+ } else if (pathParts.length > 1) moduleName = pathParts[0];
11257
+ if (!moduleMap.has(moduleName)) moduleMap.set(moduleName, []);
11258
+ moduleMap.get(moduleName).push({
11259
+ ...file,
11260
+ module: moduleName
11261
+ });
11262
+ }
11263
+ const modules = [];
11264
+ for (const [moduleName, moduleFiles] of moduleMap.entries()){
11265
+ if (0 === moduleFiles.length) continue;
11266
+ const modulePaths = moduleFiles.map((f)=>external_path_namespaceObject.dirname(f.path));
11267
+ const commonPath = findCommonPath(modulePaths);
11268
+ modules.push({
11269
+ name: moduleName,
11270
+ path: commonPath,
11271
+ relativePath: external_path_namespaceObject.relative(projectPath, commonPath),
11272
+ files: moduleFiles,
11273
+ subModules: []
11274
+ });
11275
+ }
11276
+ return modules;
11277
+ }
11278
+ function findCommonPath(paths) {
11279
+ if (0 === paths.length) return "";
11280
+ if (1 === paths.length) return external_path_namespaceObject.dirname(paths[0]);
11281
+ const parts = paths[0].split(external_path_namespaceObject.sep);
11282
+ let commonLength = parts.length;
11283
+ for(let i = 1; i < paths.length; i++){
11284
+ const currentParts = paths[i].split(external_path_namespaceObject.sep);
11285
+ commonLength = Math.min(commonLength, currentParts.length);
11286
+ for(let j = 0; j < commonLength; j++)if (parts[j] !== currentParts[j]) {
11287
+ commonLength = j;
11288
+ break;
11289
+ }
11290
+ }
11291
+ return parts.slice(0, commonLength).join(external_path_namespaceObject.sep);
11292
+ }
11293
+ async function analyzeProject(projectPath) {
11294
+ logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{9879}\u{76EE}: ${projectPath}`);
11295
+ try {
11296
+ const stats = await promises_namespaceObject.stat(projectPath);
11297
+ if (!stats.isDirectory()) throw new Error(`\u{9879}\u{76EE}\u{8DEF}\u{5F84}\u{4E0D}\u{662F}\u{76EE}\u{5F55}: ${projectPath}`);
11298
+ const allFiles = await scanDirectory(projectPath, projectPath);
11299
+ const modules = identifyModules(allFiles, projectPath);
11300
+ const statistics = {
11301
+ totalFiles: allFiles.length,
11302
+ controllerFiles: allFiles.filter((f)=>"controller" === f.type).length,
11303
+ serviceFiles: allFiles.filter((f)=>"service" === f.type).length,
11304
+ entityFiles: allFiles.filter((f)=>"entity" === f.type).length,
11305
+ dtoFiles: allFiles.filter((f)=>"dto" === f.type).length,
11306
+ moduleCount: modules.length
11307
+ };
11308
+ const projectName = external_path_namespaceObject.basename(projectPath);
11309
+ const result = {
11310
+ projectName,
11311
+ projectPath,
11312
+ modules,
11313
+ allFiles,
11314
+ statistics
11315
+ };
11316
+ logger.info(`\u{9879}\u{76EE}\u{5206}\u{6790}\u{5B8C}\u{6210}`, {
11317
+ projectName,
11318
+ moduleCount: modules.length,
11319
+ totalFiles: allFiles.length
11320
+ });
11321
+ return result;
11322
+ } catch (error) {
11323
+ logger.error(`\u{9879}\u{76EE}\u{5206}\u{6790}\u{5931}\u{8D25}: ${projectPath}`, {
11324
+ error: error.message
11325
+ });
11326
+ throw error;
11327
+ }
11328
+ }
11329
+ function getModuleNames(analysis) {
11330
+ return analysis.modules.map((m)=>m.name);
11331
+ }
11332
+ function extractComments(content) {
11333
+ const comments = new Map();
11334
+ const lines = content.split("\n");
11335
+ let currentComment = "";
11336
+ let commentStartLine = -1;
11337
+ for(let i = 0; i < lines.length; i++){
11338
+ const line = lines[i].trim();
11339
+ if (line.startsWith("/**")) {
11340
+ currentComment = "";
11341
+ commentStartLine = i;
11342
+ } else if (line.startsWith("*") && commentStartLine >= 0) {
11343
+ const commentText = line.replace(/^\*\s?/, "");
11344
+ if (commentText && !commentText.startsWith("@")) currentComment += (currentComment ? " " : "") + commentText;
11345
+ } else if (line.startsWith("*/") && commentStartLine >= 0) {
11346
+ if (currentComment) comments.set(i + 1, currentComment);
11347
+ currentComment = "";
11348
+ commentStartLine = -1;
11349
+ } else if (line.startsWith("//")) {
11350
+ const commentText = line.replace(/^\/\/\s?/, "");
11351
+ if (commentText) comments.set(i + 1, commentText);
11352
+ }
11353
+ }
11354
+ return comments;
11355
+ }
11356
+ function extractAnnotations(content, lineNumber) {
11357
+ const lines = content.split("\n");
11358
+ const annotations = [];
11359
+ for(let i = Math.max(0, lineNumber - 10); i < lineNumber; i++){
11360
+ const line = lines[i]?.trim();
11361
+ if (line && line.startsWith("@")) annotations.push(line);
11362
+ }
11363
+ return annotations;
11364
+ }
11365
+ async function analyzeJavaController(file) {
11366
+ try {
11367
+ const content = await promises_namespaceObject.readFile(file.path, "utf-8");
11368
+ const comments = extractComments(content);
11369
+ const lines = content.split("\n");
11370
+ let className = "";
11371
+ let classDescription = "";
11372
+ let classLineNumber = -1;
11373
+ for(let i = 0; i < lines.length; i++){
11374
+ const line = lines[i].trim();
11375
+ if (line.includes("class ") && (line.includes("Controller") || line.includes("@RestController") || line.includes("@Controller"))) {
11376
+ const match = line.match(/class\s+(\w+)/);
11377
+ if (match) {
11378
+ className = match[1];
11379
+ classLineNumber = i;
11380
+ classDescription = comments.get(i) || className;
11381
+ break;
11382
+ }
11383
+ }
11384
+ }
11385
+ if (!className) return null;
11386
+ const methods = [];
11387
+ for(let i = 0; i < lines.length; i++){
11388
+ const line = lines[i].trim();
11389
+ const methodMatch = line.match(/public\s+(\w+(?:<[^>]+>)?)\s+(\w+)\s*\([^)]*\)/);
11390
+ if (methodMatch) {
11391
+ const returnType = methodMatch[1];
11392
+ const methodName = methodMatch[2];
11393
+ const methodDescription = comments.get(i) || methodName;
11394
+ const annotations = extractAnnotations(content, i);
11395
+ let httpMethod = "";
11396
+ let path = "";
11397
+ for (const annotation of annotations){
11398
+ if (annotation.includes("@GetMapping") || annotation.includes("@RequestMapping") && annotation.includes("GET")) httpMethod = "GET";
11399
+ else if (annotation.includes("@PostMapping") || annotation.includes("@RequestMapping") && annotation.includes("POST")) httpMethod = "POST";
11400
+ else if (annotation.includes("@PutMapping")) httpMethod = "PUT";
11401
+ else if (annotation.includes("@DeleteMapping")) httpMethod = "DELETE";
11402
+ const pathMatch = annotation.match(/["\']([^"']+)["\']/);
11403
+ if (pathMatch) path = pathMatch[1];
11404
+ }
11405
+ const parameters = [];
11406
+ const paramMatch = line.match(/\(([^)]+)\)/);
11407
+ if (paramMatch) {
11408
+ const paramStr = paramMatch[1];
11409
+ const params = paramStr.split(",").map((p)=>p.trim()).filter((p)=>p);
11410
+ params.forEach((param, index)=>{
11411
+ const parts = param.split(/\s+/);
11412
+ if (parts.length >= 2) {
11413
+ const type = parts[parts.length - 2];
11414
+ const name = parts[parts.length - 1];
11415
+ parameters.push({
11416
+ id: String(index + 1),
11417
+ propertyType: type,
11418
+ propertyName: name,
11419
+ required: "\u662F",
11420
+ propertyDesc: `${name}\u{53C2}\u{6570}`
11421
+ });
11422
+ }
11423
+ });
11424
+ }
11425
+ methods.push({
11426
+ name: methodName,
11427
+ description: methodDescription,
11428
+ parameters,
11429
+ returnType,
11430
+ returnDescription: `${methodName}\u{8FD4}\u{56DE}\u{7ED3}\u{679C}`,
11431
+ httpMethod,
11432
+ path
11433
+ });
11434
+ }
11435
+ }
11436
+ return {
11437
+ name: className,
11438
+ description: classDescription,
11439
+ type: "controller",
11440
+ methods,
11441
+ fields: [],
11442
+ annotations: extractAnnotations(content, classLineNumber)
11443
+ };
11444
+ } catch (error) {
11445
+ logger.warn(`\u{5206}\u{6790}Controller\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
11446
+ error
11447
+ });
11448
+ return null;
11449
+ }
11450
+ }
11451
+ async function analyzeJavaService(file) {
11452
+ try {
11453
+ const content = await promises_namespaceObject.readFile(file.path, "utf-8");
11454
+ const comments = extractComments(content);
11455
+ const lines = content.split("\n");
11456
+ let className = "";
11457
+ let classDescription = "";
11458
+ for(let i = 0; i < lines.length; i++){
11459
+ const line = lines[i].trim();
11460
+ if (line.includes("class ") && (line.includes("Service") || line.includes("ServiceImpl"))) {
11461
+ const match = line.match(/class\s+(\w+)/);
11462
+ if (match) {
11463
+ className = match[1];
11464
+ classDescription = comments.get(i) || className;
11465
+ break;
11466
+ }
11467
+ }
11468
+ }
11469
+ if (!className) return null;
11470
+ const methods = [];
11471
+ for(let i = 0; i < lines.length; i++){
11472
+ const line = lines[i].trim();
11473
+ const methodMatch = line.match(/public\s+(\w+(?:<[^>]+>)?)\s+(\w+)\s*\([^)]*\)/);
11474
+ if (methodMatch) {
11475
+ const returnType = methodMatch[1];
11476
+ const methodName = methodMatch[2];
11477
+ const methodDescription = comments.get(i) || methodName;
11478
+ methods.push({
11479
+ name: methodName,
11480
+ description: methodDescription,
11481
+ parameters: [],
11482
+ returnType,
11483
+ returnDescription: `${methodName}\u{8FD4}\u{56DE}\u{7ED3}\u{679C}`
11484
+ });
11485
+ }
11486
+ }
11487
+ return {
11488
+ name: className,
11489
+ description: classDescription,
11490
+ type: "service",
11491
+ methods,
11492
+ fields: [],
11493
+ annotations: []
11494
+ };
11495
+ } catch (error) {
11496
+ logger.warn(`\u{5206}\u{6790}Service\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
11497
+ error
11498
+ });
11499
+ return null;
11500
+ }
11501
+ }
11502
+ async function analyzeJavaEntity(file) {
11503
+ try {
11504
+ const content = await promises_namespaceObject.readFile(file.path, "utf-8");
11505
+ const comments = extractComments(content);
11506
+ const lines = content.split("\n");
11507
+ let className = "";
11508
+ let classDescription = "";
11509
+ for(let i = 0; i < lines.length; i++){
11510
+ const line = lines[i].trim();
11511
+ if (line.includes("@Table")) {
11512
+ const tableMatch = line.match(/name\s*=\s*["\']([^"']+)["\']/);
11513
+ if (tableMatch) tableMatch[1];
11514
+ }
11515
+ if (line.includes("class ") && (line.includes("Entity") || content.includes("@Entity"))) {
11516
+ const match = line.match(/class\s+(\w+)/);
11517
+ if (match) {
11518
+ className = match[1];
11519
+ classDescription = comments.get(i) || className;
11520
+ break;
11521
+ }
11522
+ }
11523
+ }
11524
+ if (!className) return null;
11525
+ const fields = [];
11526
+ for(let i = 0; i < lines.length; i++){
11527
+ const line = lines[i].trim();
11528
+ const fieldMatch = line.match(/private\s+(\w+(?:<[^>]+>)?)\s+(\w+);?/);
11529
+ if (fieldMatch) {
11530
+ const fieldType = fieldMatch[1];
11531
+ const fieldName = fieldMatch[2];
11532
+ const fieldDescription = comments.get(i) || fieldName;
11533
+ const annotations = extractAnnotations(content, i);
11534
+ fields.push({
11535
+ name: fieldName,
11536
+ type: fieldType,
11537
+ description: fieldDescription,
11538
+ annotations
11539
+ });
11540
+ }
11541
+ }
11542
+ return {
11543
+ name: className,
11544
+ description: classDescription,
11545
+ type: "entity",
11546
+ methods: [],
11547
+ fields,
11548
+ annotations: []
11549
+ };
11550
+ } catch (error) {
11551
+ logger.warn(`\u{5206}\u{6790}Entity\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
11552
+ error
11553
+ });
11554
+ return null;
11555
+ }
11556
+ }
11557
+ async function analyzeTypeScriptFile(file) {
11558
+ try {
11559
+ const content = await promises_namespaceObject.readFile(file.path, "utf-8");
11560
+ const comments = extractComments(content);
11561
+ const lines = content.split("\n");
11562
+ let className = "";
11563
+ let classDescription = "";
11564
+ for(let i = 0; i < lines.length; i++){
11565
+ const line = lines[i].trim();
11566
+ const classMatch = line.match(/(?:export\s+)?(?:class|interface)\s+(\w+)/);
11567
+ if (classMatch) {
11568
+ className = classMatch[1];
11569
+ classDescription = comments.get(i) || className;
11570
+ break;
11571
+ }
11572
+ }
11573
+ if (!className) return null;
11574
+ return {
11575
+ name: className,
11576
+ description: classDescription,
11577
+ type: file.type,
11578
+ methods: [],
11579
+ fields: [],
11580
+ annotations: []
11581
+ };
11582
+ } catch (error) {
11583
+ logger.warn(`\u{5206}\u{6790}TypeScript\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
11584
+ error
11585
+ });
11586
+ return null;
11587
+ }
11588
+ }
11589
+ async function analyzeCodeFile(file) {
11590
+ const supportedTypes = [
11591
+ "controller",
11592
+ "service",
11593
+ "entity",
11594
+ "dto"
11595
+ ];
11596
+ if (!supportedTypes.includes(file.type)) return null;
11597
+ const ext = external_path_namespaceObject.extname(file.path).toLowerCase();
11598
+ switch(ext){
11599
+ case ".java":
11600
+ if ("controller" === file.type) return analyzeJavaController(file);
11601
+ if ("service" === file.type) return analyzeJavaService(file);
11602
+ if ("entity" === file.type) return analyzeJavaEntity(file);
11603
+ break;
11604
+ case ".ts":
11605
+ case ".js":
11606
+ return analyzeTypeScriptFile(file);
11607
+ default:
11608
+ break;
11609
+ }
11610
+ return null;
11611
+ }
11612
+ function classInfoToServiceInterface(classInfo, index) {
11613
+ const interfaceDetailList = classInfo.methods.map((method, methodIndex)=>({
11614
+ id: String(methodIndex + 1),
11615
+ functionDescription: method.description,
11616
+ serviceName: classInfo.name,
11617
+ methodName: method.name
11618
+ }));
11619
+ return {
11620
+ id: String(index + 1),
11621
+ serviceType: "controller" === classInfo.type ? "REST" : "Service",
11622
+ serviceEnglishName: classInfo.name,
11623
+ serviceChineseName: classInfo.description,
11624
+ serviceDescription: classInfo.description,
11625
+ interfaceDetailList
11626
+ };
11627
+ }
11628
+ function classInfoToDesignDetail(classInfo) {
11629
+ const interfaceDesignDetailList = classInfo.methods.map((method)=>({
11630
+ functionName: method.name,
11631
+ interfaceDesc: method.description,
11632
+ className: classInfo.name,
11633
+ methodName: method.name,
11634
+ parameterList: method.parameters,
11635
+ returnResultList: [
11636
+ {
11637
+ id: "1",
11638
+ propertyType: method.returnType,
11639
+ propertyName: "result",
11640
+ propertyDesc: method.returnDescription
11641
+ }
11642
+ ],
11643
+ implementLogic: `${method.description}\u{7684}\u{5177}\u{4F53}\u{5B9E}\u{73B0}\u{903B}\u{8F91}`
11644
+ }));
11645
+ return {
11646
+ serviceName: classInfo.name,
11647
+ serviceDesc: classInfo.description,
11648
+ interfaceDesignDetailList
11649
+ };
11650
+ }
11651
+ function classInfoToTableInfo(classInfo, index) {
11652
+ const tableDetailList = classInfo.fields.map((field, fieldIndex)=>({
11653
+ id: String(fieldIndex + 1),
11654
+ fieldName: field.name,
11655
+ fieldType: field.type,
11656
+ fieldDescription: field.description,
11657
+ fieldLength: getFieldLength(field.type)
11658
+ }));
11659
+ return {
11660
+ id: String(index + 1),
11661
+ tableName: camelToSnakeCase(classInfo.name),
11662
+ entityName: classInfo.name,
11663
+ tableDescription: classInfo.description,
11664
+ tableDetailList
11665
+ };
11666
+ }
11667
+ function getFieldLength(fieldType) {
11668
+ const type = fieldType.toLowerCase();
11669
+ if (type.includes("string") || type.includes("varchar")) return "255";
11670
+ if (type.includes("text")) return "65535";
11671
+ if (type.includes("int") || type.includes("integer")) return "11";
11672
+ if (type.includes("long")) return "20";
11673
+ if (type.includes("decimal") || type.includes("double")) return "10,2";
11674
+ else if (type.includes("date") || type.includes("time")) return "-";
11675
+ else return "255";
11676
+ }
11677
+ function camelToSnakeCase(str) {
11678
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
11679
+ }
11680
+ async function analyzeProjectCode(analysis, options = {}) {
11681
+ logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{9879}\u{76EE}\u{4EE3}\u{7801}: ${analysis.projectName}`);
11682
+ let filesToAnalyze = analysis.allFiles;
11683
+ if (options.includeModules && options.includeModules.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>f.module && options.includeModules.includes(f.module));
11684
+ if (options.excludeModules && options.excludeModules.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>!f.module || !options.excludeModules.includes(f.module));
11685
+ if (options.includeFileTypes && options.includeFileTypes.length > 0) filesToAnalyze = filesToAnalyze.filter((f)=>options.includeFileTypes.includes(f.type));
11686
+ logger.info(`\u{9700}\u{8981}\u{5206}\u{6790}\u{7684}\u{6587}\u{4EF6}\u{6570}\u{91CF}: ${filesToAnalyze.length}`);
11687
+ const classInfoList = [];
11688
+ for (const file of filesToAnalyze)try {
11689
+ const classInfo = await analyzeCodeFile(file);
11690
+ if (classInfo) classInfoList.push(classInfo);
11691
+ } catch (error) {
11692
+ logger.warn(`\u{5206}\u{6790}\u{6587}\u{4EF6}\u{5931}\u{8D25}: ${file.path}`, {
11693
+ error
11694
+ });
11695
+ }
11696
+ logger.info(`\u{6210}\u{529F}\u{5206}\u{6790}\u{7684}\u{7C7B}\u{6570}\u{91CF}: ${classInfoList.length}`);
11697
+ const serviceInterfaceList = [];
11698
+ const designDetailList = [];
11699
+ const tableInfoList = [];
11700
+ let serviceIndex = 0;
11701
+ let tableIndex = 0;
11702
+ for (const classInfo of classInfoList)if ("controller" === classInfo.type || "service" === classInfo.type) {
11703
+ serviceInterfaceList.push(classInfoToServiceInterface(classInfo, serviceIndex++));
11704
+ designDetailList.push(classInfoToDesignDetail(classInfo));
11705
+ } else if ("entity" === classInfo.type) tableInfoList.push(classInfoToTableInfo(classInfo, tableIndex++));
11706
+ logger.info(`\u{4EE3}\u{7801}\u{5206}\u{6790}\u{5B8C}\u{6210}`, {
11707
+ serviceCount: serviceInterfaceList.length,
11708
+ designCount: designDetailList.length,
11709
+ tableCount: tableInfoList.length
11710
+ });
11711
+ return {
11712
+ serviceInterfaceList,
11713
+ designDetailList,
11714
+ tableInfoList
11715
+ };
11716
+ }
11717
+ class TechSpecStorage {
11718
+ dataDir;
11719
+ projectsFile;
11720
+ chaptersFile;
11721
+ modulesFile;
11722
+ filesFile;
11723
+ constructor(){
11724
+ try {
11725
+ const storageDir = getStorageDir();
11726
+ this.dataDir = external_path_namespaceObject.join(storageDir, "tech-spec");
11727
+ this.projectsFile = external_path_namespaceObject.join(this.dataDir, "projects.json");
11728
+ this.chaptersFile = external_path_namespaceObject.join(this.dataDir, "chapters.json");
11729
+ this.modulesFile = external_path_namespaceObject.join(this.dataDir, "modules.json");
11730
+ this.filesFile = external_path_namespaceObject.join(this.dataDir, "files.json");
11731
+ this.ensureDataDir();
11732
+ } catch (error) {
11733
+ console.warn("TechSpecStorage\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u8DEF\u5F84:", error);
11734
+ const defaultDir = external_path_namespaceObject.join(process.cwd(), ".aico");
11735
+ this.dataDir = external_path_namespaceObject.join(defaultDir, "tech-spec");
11736
+ this.projectsFile = external_path_namespaceObject.join(this.dataDir, "projects.json");
11737
+ this.chaptersFile = external_path_namespaceObject.join(this.dataDir, "chapters.json");
11738
+ this.modulesFile = external_path_namespaceObject.join(this.dataDir, "modules.json");
11739
+ this.filesFile = external_path_namespaceObject.join(this.dataDir, "files.json");
11740
+ this.ensureDataDir();
11741
+ }
11742
+ }
11743
+ ensureDataDir() {
11744
+ if (!external_fs_namespaceObject.existsSync(this.dataDir)) external_fs_namespaceObject.mkdirSync(this.dataDir, {
11745
+ recursive: true
11746
+ });
11747
+ if (!external_fs_namespaceObject.existsSync(this.projectsFile)) external_fs_namespaceObject.writeFileSync(this.projectsFile, "[]", "utf8");
11748
+ if (!external_fs_namespaceObject.existsSync(this.chaptersFile)) external_fs_namespaceObject.writeFileSync(this.chaptersFile, "[]", "utf8");
11749
+ if (!external_fs_namespaceObject.existsSync(this.modulesFile)) external_fs_namespaceObject.writeFileSync(this.modulesFile, "[]", "utf8");
11750
+ if (!external_fs_namespaceObject.existsSync(this.filesFile)) external_fs_namespaceObject.writeFileSync(this.filesFile, "[]", "utf8");
11751
+ }
11752
+ getNextId(items) {
11753
+ return items.length > 0 ? Math.max(...items.map((i)=>i.id)) + 1 : 1;
11754
+ }
11755
+ readProjects() {
11756
+ try {
11757
+ const data = external_fs_namespaceObject.readFileSync(this.projectsFile, "utf8");
11758
+ return JSON.parse(data).map((p)=>({
11759
+ ...p,
11760
+ createdAt: new Date(p.createdAt),
11761
+ updatedAt: new Date(p.updatedAt),
11762
+ completedAt: p.completedAt ? new Date(p.completedAt) : void 0
11763
+ }));
11764
+ } catch (error) {
11765
+ logger.error("Error reading tech spec projects file", error);
11766
+ return [];
11767
+ }
11768
+ }
11769
+ writeProjects(projects) {
11770
+ external_fs_namespaceObject.writeFileSync(this.projectsFile, JSON.stringify(projects, null, 2), "utf8");
11771
+ }
11772
+ async createTechSpecProject(data) {
11773
+ const projects = this.readProjects();
11774
+ const newProject = {
11775
+ id: this.getNextId(projects),
11776
+ uuid: data.uuid,
11777
+ projectName: data.projectName,
11778
+ moduleName: data.moduleName,
11779
+ projectPath: data.projectPath,
11780
+ status: "analyzing",
11781
+ totalModules: data.totalModules,
11782
+ processedModules: 0,
11783
+ totalFiles: data.totalFiles,
11784
+ processedFiles: 0,
11785
+ createdAt: new Date(),
11786
+ updatedAt: new Date()
11787
+ };
11788
+ projects.push(newProject);
11789
+ this.writeProjects(projects);
11790
+ return newProject;
11791
+ }
11792
+ async getTechSpecProject(uuid) {
11793
+ const projects = this.readProjects();
11794
+ return projects.find((p)=>p.uuid === uuid) || null;
11795
+ }
11796
+ async getAllTechSpecProjects() {
11797
+ return this.readProjects();
11798
+ }
11799
+ async updateTechSpecProject(uuid, data) {
11800
+ const projects = this.readProjects();
11801
+ const projectIndex = projects.findIndex((p)=>p.uuid === uuid);
11802
+ if (projectIndex >= 0) {
11803
+ projects[projectIndex] = {
11804
+ ...projects[projectIndex],
11805
+ ...data,
11806
+ updatedAt: new Date()
11807
+ };
11808
+ this.writeProjects(projects);
11809
+ }
11810
+ }
11811
+ readChapters() {
11812
+ try {
11813
+ const data = external_fs_namespaceObject.readFileSync(this.chaptersFile, "utf8");
11814
+ return JSON.parse(data).map((c)=>({
11815
+ ...c,
11816
+ createdAt: new Date(c.createdAt),
11817
+ updatedAt: new Date(c.updatedAt)
11818
+ }));
11819
+ } catch (error) {
11820
+ logger.error("Error reading tech spec chapters file", error);
11821
+ return [];
11822
+ }
11823
+ }
11824
+ writeChapters(chapters) {
11825
+ external_fs_namespaceObject.writeFileSync(this.chaptersFile, JSON.stringify(chapters, null, 2), "utf8");
11826
+ }
11827
+ async createTechSpecChapter(data) {
11828
+ const chapters = this.readChapters();
11829
+ const newChapter = {
11830
+ id: this.getNextId(chapters),
11831
+ uuid: data.uuid,
11832
+ projectUuid: data.projectUuid,
11833
+ chapterType: data.chapterType,
11834
+ chapterTitle: data.chapterTitle,
11835
+ chapterOrder: data.chapterOrder,
11836
+ content: data.content,
11837
+ moduleSource: data.moduleSource,
11838
+ fileCount: data.fileCount,
11839
+ status: "completed",
11840
+ createdAt: new Date(),
11841
+ updatedAt: new Date()
11842
+ };
11843
+ chapters.push(newChapter);
11844
+ this.writeChapters(chapters);
11845
+ return newChapter;
11846
+ }
11847
+ async getTechSpecChapters(projectUuid) {
11848
+ const chapters = this.readChapters();
11849
+ return chapters.filter((c)=>c.projectUuid === projectUuid).sort((a, b)=>a.chapterOrder - b.chapterOrder);
11850
+ }
11851
+ async getTechSpecChaptersByType(projectUuid, chapterType) {
11852
+ const chapters = this.readChapters();
11853
+ return chapters.filter((c)=>c.projectUuid === projectUuid && c.chapterType === chapterType).sort((a, b)=>a.chapterOrder - b.chapterOrder);
11854
+ }
11855
+ async updateTechSpecChapter(uuid, data) {
11856
+ const chapters = this.readChapters();
11857
+ const chapterIndex = chapters.findIndex((c)=>c.uuid === uuid);
11858
+ if (chapterIndex >= 0) {
11859
+ chapters[chapterIndex] = {
11860
+ ...chapters[chapterIndex],
11861
+ ...data,
11862
+ updatedAt: new Date()
11863
+ };
11864
+ this.writeChapters(chapters);
11865
+ }
11866
+ }
11867
+ readModules() {
11868
+ try {
11869
+ const data = external_fs_namespaceObject.readFileSync(this.modulesFile, "utf8");
11870
+ return JSON.parse(data).map((m)=>({
11871
+ ...m,
11872
+ createdAt: new Date(m.createdAt),
11873
+ updatedAt: new Date(m.updatedAt),
11874
+ startedAt: m.startedAt ? new Date(m.startedAt) : void 0,
11875
+ completedAt: m.completedAt ? new Date(m.completedAt) : void 0
11876
+ }));
11877
+ } catch (error) {
11878
+ logger.error("Error reading tech spec modules file", error);
11879
+ return [];
11880
+ }
11881
+ }
11882
+ writeModules(modules) {
11883
+ external_fs_namespaceObject.writeFileSync(this.modulesFile, JSON.stringify(modules, null, 2), "utf8");
11884
+ }
11885
+ async createModuleProcessStatus(data) {
11886
+ const modules = this.readModules();
11887
+ const newModule = {
11888
+ id: this.getNextId(modules),
11889
+ uuid: data.uuid,
11890
+ projectUuid: data.projectUuid,
11891
+ moduleName: data.moduleName,
11892
+ moduleType: data.moduleType,
11893
+ totalFiles: data.totalFiles,
11894
+ processedFiles: 0,
11895
+ status: "pending",
11896
+ createdAt: new Date(),
11897
+ updatedAt: new Date()
11898
+ };
11899
+ modules.push(newModule);
11900
+ this.writeModules(modules);
11901
+ return newModule;
11902
+ }
11903
+ async getModuleProcessStatuses(projectUuid) {
11904
+ const modules = this.readModules();
11905
+ return modules.filter((m)=>m.projectUuid === projectUuid);
11906
+ }
11907
+ async updateModuleProcessStatus(uuid, data) {
11908
+ const modules = this.readModules();
11909
+ const moduleIndex = modules.findIndex((m)=>m.uuid === uuid);
11910
+ if (moduleIndex >= 0) {
11911
+ modules[moduleIndex] = {
11912
+ ...modules[moduleIndex],
11913
+ ...data,
11914
+ updatedAt: new Date()
11915
+ };
11916
+ this.writeModules(modules);
11917
+ }
11918
+ }
11919
+ readFiles() {
11920
+ try {
11921
+ const data = external_fs_namespaceObject.readFileSync(this.filesFile, "utf8");
11922
+ return JSON.parse(data).map((f)=>({
11923
+ ...f,
11924
+ createdAt: new Date(f.createdAt),
11925
+ updatedAt: new Date(f.updatedAt)
11926
+ }));
11927
+ } catch (error) {
11928
+ logger.error("Error reading tech spec files file", error);
11929
+ return [];
11930
+ }
11931
+ }
11932
+ writeFiles(files) {
11933
+ external_fs_namespaceObject.writeFileSync(this.filesFile, JSON.stringify(files, null, 2), "utf8");
11934
+ }
11935
+ async createFileProcessRecord(data) {
11936
+ const files = this.readFiles();
11937
+ const newFile = {
11938
+ id: this.getNextId(files),
11939
+ uuid: data.uuid,
11940
+ projectUuid: data.projectUuid,
11941
+ moduleUuid: data.moduleUuid,
11942
+ filePath: data.filePath,
11943
+ fileName: data.fileName,
11944
+ fileType: data.fileType,
11945
+ extractedData: data.extractedData,
11946
+ status: "completed",
11947
+ processingTime: data.processingTime,
11948
+ createdAt: new Date(),
11949
+ updatedAt: new Date()
11950
+ };
11951
+ files.push(newFile);
11952
+ this.writeFiles(files);
11953
+ return newFile;
11954
+ }
11955
+ async getFileProcessRecords(projectUuid) {
11956
+ const files = this.readFiles();
11957
+ return files.filter((f)=>f.projectUuid === projectUuid);
11958
+ }
11959
+ async getFileProcessRecordsByModule(moduleUuid) {
11960
+ const files = this.readFiles();
11961
+ return files.filter((f)=>f.moduleUuid === moduleUuid);
11962
+ }
11963
+ async mergeChaptersByType(projectUuid, chapterType) {
11964
+ const chapters = await this.getTechSpecChaptersByType(projectUuid, chapterType);
11965
+ if (0 === chapters.length) return null;
11966
+ switch(chapterType){
11967
+ case "service_interface_list":
11968
+ return this.mergeServiceInterfaceChapters(chapters);
11969
+ case "interface_design":
11970
+ return this.mergeInterfaceDesignChapters(chapters);
11971
+ case "database_design":
11972
+ return this.mergeDatabaseDesignChapters(chapters);
11973
+ case "tech_solution":
11974
+ return this.mergeTechSolutionChapters(chapters);
11975
+ case "business_exception":
11976
+ return this.mergeBusinessExceptionChapters(chapters);
11977
+ case "appendix":
11978
+ return this.mergeAppendixChapters(chapters);
11979
+ default:
11980
+ return {
11981
+ content: chapters.map((c)=>JSON.parse(c.content)).join("\n\n"),
11982
+ totalModules: chapters.length,
11983
+ totalFiles: chapters.reduce((sum, c)=>sum + c.fileCount, 0)
11984
+ };
11985
+ }
11986
+ }
11987
+ mergeServiceInterfaceChapters(chapters) {
11988
+ const allInterfaces = [];
11989
+ let idCounter = 1;
11990
+ for (const chapter of chapters)try {
11991
+ const chapterData = JSON.parse(chapter.content);
11992
+ if (Array.isArray(chapterData)) {
11993
+ const interfaces = chapterData.map((item)=>({
11994
+ ...item,
11995
+ id: String(idCounter++),
11996
+ moduleSource: chapter.moduleSource
11997
+ }));
11998
+ allInterfaces.push(...interfaces);
11999
+ }
12000
+ } catch (error) {
12001
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12002
+ }
12003
+ return allInterfaces;
12004
+ }
12005
+ mergeInterfaceDesignChapters(chapters) {
12006
+ const allDesigns = [];
12007
+ for (const chapter of chapters)try {
12008
+ const chapterData = JSON.parse(chapter.content);
12009
+ if (Array.isArray(chapterData)) {
12010
+ const designs = chapterData.map((item)=>({
12011
+ ...item,
12012
+ moduleSource: chapter.moduleSource
12013
+ }));
12014
+ allDesigns.push(...designs);
12015
+ }
12016
+ } catch (error) {
12017
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12018
+ }
12019
+ return allDesigns;
12020
+ }
12021
+ mergeDatabaseDesignChapters(chapters) {
12022
+ const allTables = [];
12023
+ let idCounter = 1;
12024
+ for (const chapter of chapters)try {
12025
+ const chapterData = JSON.parse(chapter.content);
12026
+ if (Array.isArray(chapterData)) {
12027
+ const tables = chapterData.map((item)=>({
12028
+ ...item,
12029
+ id: String(idCounter++),
12030
+ moduleSource: chapter.moduleSource
12031
+ }));
12032
+ allTables.push(...tables);
12033
+ }
12034
+ } catch (error) {
12035
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12036
+ }
12037
+ return allTables;
12038
+ }
12039
+ mergeTechSolutionChapters(chapters) {
12040
+ const contents = [];
12041
+ for (const chapter of chapters)try {
12042
+ const chapterData = JSON.parse(chapter.content);
12043
+ if (chapterData.content) contents.push(`## ${chapter.moduleSource || "\u6A21\u5757"}\n${chapterData.content}`);
12044
+ } catch (error) {
12045
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12046
+ }
12047
+ return {
12048
+ content: contents.join("\n\n")
12049
+ };
12050
+ }
12051
+ mergeBusinessExceptionChapters(chapters) {
12052
+ const contents = [];
12053
+ for (const chapter of chapters)try {
12054
+ const chapterData = JSON.parse(chapter.content);
12055
+ if (chapterData.content) contents.push(`## ${chapter.moduleSource || "\u6A21\u5757"}\n${chapterData.content}`);
12056
+ } catch (error) {
12057
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12058
+ }
12059
+ return {
12060
+ content: contents.join("\n\n")
12061
+ };
12062
+ }
12063
+ mergeAppendixChapters(chapters) {
12064
+ const allExceptionCodes = [];
12065
+ const allCodeValues = [];
12066
+ let idCounter = 1;
12067
+ for (const chapter of chapters)try {
12068
+ const chapterData = JSON.parse(chapter.content);
12069
+ if (chapterData.exceptionCodeList && Array.isArray(chapterData.exceptionCodeList)) {
12070
+ const codes = chapterData.exceptionCodeList.map((item)=>({
12071
+ ...item,
12072
+ id: String(idCounter++),
12073
+ moduleSource: chapter.moduleSource
12074
+ }));
12075
+ allExceptionCodes.push(...codes);
12076
+ }
12077
+ if (chapterData.codeValueList && Array.isArray(chapterData.codeValueList)) {
12078
+ const values = chapterData.codeValueList.map((item)=>({
12079
+ ...item,
12080
+ id: String(idCounter++),
12081
+ moduleSource: chapter.moduleSource
12082
+ }));
12083
+ allCodeValues.push(...values);
12084
+ }
12085
+ } catch (error) {
12086
+ logger.warn(`\u{89E3}\u{6790}\u{7AE0}\u{8282}\u{5185}\u{5BB9}\u{5931}\u{8D25}: ${chapter.uuid}`, error);
12087
+ }
12088
+ return {
12089
+ exceptionCodeList: allExceptionCodes,
12090
+ codeValueList: allCodeValues
12091
+ };
12092
+ }
12093
+ async cleanupProject(projectUuid) {
12094
+ const chapters = this.readChapters();
12095
+ const filteredChapters = chapters.filter((c)=>c.projectUuid !== projectUuid);
12096
+ this.writeChapters(filteredChapters);
12097
+ const modules = this.readModules();
12098
+ const filteredModules = modules.filter((m)=>m.projectUuid !== projectUuid);
12099
+ this.writeModules(filteredModules);
12100
+ const files = this.readFiles();
12101
+ const filteredFiles = files.filter((f)=>f.projectUuid !== projectUuid);
12102
+ this.writeFiles(filteredFiles);
12103
+ logger.info(`\u{5DF2}\u{6E05}\u{7406}\u{9879}\u{76EE} ${projectUuid} \u{7684}\u{6240}\u{6709}\u{76F8}\u{5173}\u{6570}\u{636E}`);
12104
+ }
12105
+ async getProjectStatistics(projectUuid) {
12106
+ const chapters = await this.getTechSpecChapters(projectUuid);
12107
+ const modules = await this.getModuleProcessStatuses(projectUuid);
12108
+ const files = await this.getFileProcessRecords(projectUuid);
12109
+ const chaptersByType = {
12110
+ project_overview: 0,
12111
+ service_interface_list: 0,
12112
+ interface_design: 0,
12113
+ database_design: 0,
12114
+ tech_solution: 0,
12115
+ business_exception: 0,
12116
+ appendix: 0
12117
+ };
12118
+ chapters.forEach((chapter)=>{
12119
+ chaptersByType[chapter.chapterType]++;
12120
+ });
12121
+ return {
12122
+ totalChapters: chapters.length,
12123
+ completedChapters: chapters.filter((c)=>"completed" === c.status).length,
12124
+ totalModules: modules.length,
12125
+ completedModules: modules.filter((m)=>"completed" === m.status).length,
12126
+ totalFiles: files.length,
12127
+ completedFiles: files.filter((f)=>"completed" === f.status).length,
12128
+ chaptersByType
12129
+ };
12130
+ }
12131
+ }
12132
+ const techSpecStorage = new TechSpecStorage();
12133
+ const techSpecDbOperations = {
12134
+ createTechSpecProject: techSpecStorage.createTechSpecProject.bind(techSpecStorage),
12135
+ getTechSpecProject: techSpecStorage.getTechSpecProject.bind(techSpecStorage),
12136
+ getAllTechSpecProjects: techSpecStorage.getAllTechSpecProjects.bind(techSpecStorage),
12137
+ updateTechSpecProject: techSpecStorage.updateTechSpecProject.bind(techSpecStorage),
12138
+ createTechSpecChapter: techSpecStorage.createTechSpecChapter.bind(techSpecStorage),
12139
+ getTechSpecChapters: techSpecStorage.getTechSpecChapters.bind(techSpecStorage),
12140
+ getTechSpecChaptersByType: techSpecStorage.getTechSpecChaptersByType.bind(techSpecStorage),
12141
+ updateTechSpecChapter: techSpecStorage.updateTechSpecChapter.bind(techSpecStorage),
12142
+ createModuleProcessStatus: techSpecStorage.createModuleProcessStatus.bind(techSpecStorage),
12143
+ getModuleProcessStatuses: techSpecStorage.getModuleProcessStatuses.bind(techSpecStorage),
12144
+ updateModuleProcessStatus: techSpecStorage.updateModuleProcessStatus.bind(techSpecStorage),
12145
+ createFileProcessRecord: techSpecStorage.createFileProcessRecord.bind(techSpecStorage),
12146
+ getFileProcessRecords: techSpecStorage.getFileProcessRecords.bind(techSpecStorage),
12147
+ getFileProcessRecordsByModule: techSpecStorage.getFileProcessRecordsByModule.bind(techSpecStorage),
12148
+ mergeChaptersByType: techSpecStorage.mergeChaptersByType.bind(techSpecStorage),
12149
+ cleanupProject: techSpecStorage.cleanupProject.bind(techSpecStorage),
12150
+ getProjectStatistics: techSpecStorage.getProjectStatistics.bind(techSpecStorage)
12151
+ };
12152
+ const DEFAULT_CONFIG = {
12153
+ maxFilesPerBatch: 50,
12154
+ maxModulesPerChapter: 10,
12155
+ enableParallelProcessing: true,
12156
+ skipEmptyModules: true
12157
+ };
12158
+ class ChapterProcessor {
12159
+ config;
12160
+ constructor(config = {}){
12161
+ this.config = {
12162
+ ...DEFAULT_CONFIG,
12163
+ ...config
12164
+ };
12165
+ }
12166
+ async processFullProject(projectAnalysis, options = {}) {
12167
+ const startTime = Date.now();
12168
+ const projectUuid = (0, external_crypto_namespaceObject.randomUUID)();
12169
+ try {
12170
+ logger.info(`\u{5F00}\u{59CB}\u{5206}\u{7AE0}\u{8282}\u{5904}\u{7406}\u{9879}\u{76EE}: ${projectAnalysis.projectName}`, {
12171
+ projectUuid
12172
+ });
12173
+ const techSpecProject = await this.createProjectRecord(projectUuid, projectAnalysis, options);
12174
+ const filteredModules = this.filterModules(projectAnalysis.modules, options);
12175
+ if (0 === filteredModules.length) throw new Error("\u6CA1\u6709\u627E\u5230\u7B26\u5408\u6761\u4EF6\u7684\u6A21\u5757");
12176
+ const batches = this.createModuleBatches(filteredModules);
12177
+ logger.info(`\u{9879}\u{76EE}\u{5206}\u{4E3A} ${batches.length} \u{4E2A}\u{6279}\u{6B21}\u{5904}\u{7406}`, {
12178
+ projectUuid,
12179
+ totalModules: filteredModules.length,
12180
+ totalBatches: batches.length
12181
+ });
12182
+ let totalProcessedFiles = 0;
12183
+ let totalServiceInterfaces = 0;
12184
+ let totalDesignDetails = 0;
12185
+ let totalTableInfo = 0;
12186
+ for(let i = 0; i < batches.length; i++){
12187
+ const batch = batches[i];
12188
+ logger.info(`\u{5904}\u{7406}\u{6279}\u{6B21} ${i + 1}/${batches.length}`, {
12189
+ projectUuid,
12190
+ batchId: batch.batchId,
12191
+ moduleCount: batch.modules.length,
12192
+ fileCount: batch.totalFiles
12193
+ });
12194
+ try {
12195
+ const batchResult = await this.processBatch(projectUuid, batch);
12196
+ totalProcessedFiles += batchResult.processedFiles;
12197
+ totalServiceInterfaces += batchResult.serviceInterfaceCount;
12198
+ totalDesignDetails += batchResult.designDetailCount;
12199
+ totalTableInfo += batchResult.tableInfoCount;
12200
+ await techSpecDbOperations.updateTechSpecProject(projectUuid, {
12201
+ processedModules: (i + 1) * this.config.maxModulesPerChapter,
12202
+ processedFiles: totalProcessedFiles,
12203
+ status: "generating"
12204
+ });
12205
+ } catch (error) {
12206
+ logger.error(`\u{6279}\u{6B21}\u{5904}\u{7406}\u{5931}\u{8D25}: ${batch.batchId}`, {
12207
+ error: error.message
12208
+ });
12209
+ }
12210
+ }
12211
+ await this.generateProjectOverviewChapter(projectUuid, techSpecProject, projectAnalysis);
12212
+ await techSpecDbOperations.updateTechSpecProject(projectUuid, {
12213
+ status: "completed",
12214
+ completedAt: new Date(),
12215
+ processedModules: filteredModules.length,
12216
+ processedFiles: totalProcessedFiles
12217
+ });
12218
+ const processingTime = Date.now() - startTime;
12219
+ logger.info(`\u{9879}\u{76EE}\u{5904}\u{7406}\u{5B8C}\u{6210}`, {
12220
+ projectUuid,
12221
+ processingTime,
12222
+ totalModules: filteredModules.length,
12223
+ totalFiles: totalProcessedFiles
12224
+ });
12225
+ return {
12226
+ success: true,
12227
+ projectUuid,
12228
+ totalChapters: batches.length + 1,
12229
+ processedChapters: batches.length + 1,
12230
+ totalModules: filteredModules.length,
12231
+ processedModules: filteredModules.length,
12232
+ totalFiles: projectAnalysis.allFiles.length,
12233
+ processedFiles: totalProcessedFiles,
12234
+ statistics: {
12235
+ serviceInterfaceCount: totalServiceInterfaces,
12236
+ designDetailCount: totalDesignDetails,
12237
+ tableInfoCount: totalTableInfo,
12238
+ processingTime
12239
+ }
12240
+ };
12241
+ } catch (error) {
12242
+ logger.error(`\u{9879}\u{76EE}\u{5904}\u{7406}\u{5931}\u{8D25}: ${projectAnalysis.projectName}`, {
12243
+ error: error.message,
12244
+ projectUuid
12245
+ });
12246
+ await techSpecDbOperations.updateTechSpecProject(projectUuid, {
12247
+ status: "failed"
12248
+ });
12249
+ return {
12250
+ success: false,
12251
+ projectUuid,
12252
+ totalChapters: 0,
12253
+ processedChapters: 0,
12254
+ totalModules: 0,
12255
+ processedModules: 0,
12256
+ totalFiles: 0,
12257
+ processedFiles: 0,
12258
+ errorMessage: error.message,
12259
+ statistics: {
12260
+ serviceInterfaceCount: 0,
12261
+ designDetailCount: 0,
12262
+ tableInfoCount: 0,
12263
+ processingTime: Date.now() - startTime
12264
+ }
12265
+ };
12266
+ }
12267
+ }
12268
+ async createProjectRecord(projectUuid, projectAnalysis, options) {
12269
+ const projectName = options.projectName || projectAnalysis.projectName;
12270
+ const moduleName = options.moduleName || projectName;
12271
+ return await techSpecDbOperations.createTechSpecProject({
12272
+ uuid: projectUuid,
12273
+ projectName,
12274
+ moduleName,
12275
+ projectPath: projectAnalysis.projectPath,
12276
+ totalModules: projectAnalysis.modules.length,
12277
+ totalFiles: projectAnalysis.allFiles.length
12278
+ });
12279
+ }
12280
+ filterModules(modules, options) {
12281
+ let filteredModules = [
12282
+ ...modules
12283
+ ];
12284
+ if (options.includeModules && options.includeModules.length > 0) filteredModules = filteredModules.filter((m)=>options.includeModules.includes(m.name));
12285
+ if (options.excludeModules && options.excludeModules.length > 0) filteredModules = filteredModules.filter((m)=>!options.excludeModules.includes(m.name));
12286
+ if (this.config.skipEmptyModules) filteredModules = filteredModules.filter((m)=>m.files.length > 0);
12287
+ return filteredModules;
12288
+ }
12289
+ createModuleBatches(modules) {
12290
+ const batches = [];
12291
+ let currentBatch = [];
12292
+ let currentFileCount = 0;
12293
+ for (const module of modules){
12294
+ if (currentBatch.length >= this.config.maxModulesPerChapter || currentFileCount + module.files.length > this.config.maxFilesPerBatch) {
12295
+ if (currentBatch.length > 0) batches.push({
12296
+ batchId: (0, external_crypto_namespaceObject.randomUUID)(),
12297
+ modules: [
12298
+ ...currentBatch
12299
+ ],
12300
+ totalFiles: currentFileCount,
12301
+ chapterType: this.determineChapterType(currentBatch)
12302
+ });
12303
+ currentBatch = [];
12304
+ currentFileCount = 0;
12305
+ }
12306
+ currentBatch.push(module);
12307
+ currentFileCount += module.files.length;
12308
+ }
12309
+ if (currentBatch.length > 0) batches.push({
12310
+ batchId: (0, external_crypto_namespaceObject.randomUUID)(),
12311
+ modules: currentBatch,
12312
+ totalFiles: currentFileCount,
12313
+ chapterType: this.determineChapterType(currentBatch)
12314
+ });
12315
+ return batches;
12316
+ }
12317
+ determineChapterType(modules) {
12318
+ const fileTypes = modules.flatMap((m)=>m.files.map((f)=>f.type));
12319
+ if (fileTypes.includes("controller") || fileTypes.includes("service")) return "service_interface_list";
12320
+ if (fileTypes.includes("entity")) return "database_design";
12321
+ return "interface_design";
12322
+ }
12323
+ async processBatch(projectUuid, batch) {
12324
+ logger.info(`\u{5F00}\u{59CB}\u{5904}\u{7406}\u{6279}\u{6B21}: ${batch.batchId}`, {
12325
+ moduleCount: batch.modules.length,
12326
+ fileCount: batch.totalFiles
12327
+ });
12328
+ const moduleStatuses = [];
12329
+ for (const module of batch.modules){
12330
+ const moduleUuid = (0, external_crypto_namespaceObject.randomUUID)();
12331
+ const moduleStatus = await techSpecDbOperations.createModuleProcessStatus({
12332
+ uuid: moduleUuid,
12333
+ projectUuid,
12334
+ moduleName: module.name,
12335
+ moduleType: this.detectModuleType(module),
12336
+ totalFiles: module.files.length
12337
+ });
12338
+ moduleStatuses.push(moduleStatus);
12339
+ }
12340
+ const batchAnalysis = {
12341
+ projectName: `batch-${batch.batchId}`,
12342
+ projectPath: "",
12343
+ modules: batch.modules,
12344
+ allFiles: batch.modules.flatMap((m)=>m.files),
12345
+ statistics: {
12346
+ totalFiles: batch.totalFiles,
12347
+ controllerFiles: 0,
12348
+ serviceFiles: 0,
12349
+ entityFiles: 0,
12350
+ dtoFiles: 0,
12351
+ moduleCount: batch.modules.length
12352
+ }
12353
+ };
12354
+ const codeAnalysis = await analyzeProjectCode(batchAnalysis, {
12355
+ includeFileTypes: [
12356
+ "controller",
12357
+ "service",
12358
+ "entity",
12359
+ "dto"
12360
+ ]
12361
+ });
12362
+ await this.storeChapterContent(projectUuid, batch, codeAnalysis);
12363
+ for (const moduleStatus of moduleStatuses)await techSpecDbOperations.updateModuleProcessStatus(moduleStatus.uuid, {
12364
+ status: "completed",
12365
+ processedFiles: moduleStatus.totalFiles,
12366
+ completedAt: new Date()
12367
+ });
12368
+ return {
12369
+ processedFiles: batch.totalFiles,
12370
+ serviceInterfaceCount: codeAnalysis.serviceInterfaceList.length,
12371
+ designDetailCount: codeAnalysis.designDetailList.length,
12372
+ tableInfoCount: codeAnalysis.tableInfoList.length
12373
+ };
12374
+ }
12375
+ detectModuleType(module) {
12376
+ const javaFiles = module.files.filter((f)=>f.path.endsWith(".java"));
12377
+ const tsFiles = module.files.filter((f)=>f.path.endsWith(".ts") || f.path.endsWith(".js"));
12378
+ if (javaFiles.length > tsFiles.length) return "java";
12379
+ if (tsFiles.length > 0) return "typescript";
12380
+ return "other";
12381
+ }
12382
+ async storeChapterContent(projectUuid, batch, codeAnalysis) {
12383
+ const moduleNames = batch.modules.map((m)=>m.name).join(", ");
12384
+ if (codeAnalysis.serviceInterfaceList.length > 0) await techSpecDbOperations.createTechSpecChapter({
12385
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12386
+ projectUuid,
12387
+ chapterType: "service_interface_list",
12388
+ chapterTitle: `\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{6E05}\u{5355} - ${moduleNames}`,
12389
+ chapterOrder: this.getChapterOrder("service_interface_list"),
12390
+ content: JSON.stringify(codeAnalysis.serviceInterfaceList),
12391
+ moduleSource: moduleNames,
12392
+ fileCount: batch.totalFiles
12393
+ });
12394
+ if (codeAnalysis.designDetailList.length > 0) await techSpecDbOperations.createTechSpecChapter({
12395
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12396
+ projectUuid,
12397
+ chapterType: "interface_design",
12398
+ chapterTitle: `\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5} - ${moduleNames}`,
12399
+ chapterOrder: this.getChapterOrder("interface_design"),
12400
+ content: JSON.stringify(codeAnalysis.designDetailList),
12401
+ moduleSource: moduleNames,
12402
+ fileCount: batch.totalFiles
12403
+ });
12404
+ if (codeAnalysis.tableInfoList.length > 0) await techSpecDbOperations.createTechSpecChapter({
12405
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12406
+ projectUuid,
12407
+ chapterType: "database_design",
12408
+ chapterTitle: `\u{6570}\u{636E}\u{5E93}\u{8BBE}\u{8BA1} - ${moduleNames}`,
12409
+ chapterOrder: this.getChapterOrder("database_design"),
12410
+ content: JSON.stringify(codeAnalysis.tableInfoList),
12411
+ moduleSource: moduleNames,
12412
+ fileCount: batch.totalFiles
12413
+ });
12414
+ const techSolutionContent = this.generateTechSolutionContent(batch, codeAnalysis);
12415
+ if (techSolutionContent) await techSpecDbOperations.createTechSpecChapter({
12416
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12417
+ projectUuid,
12418
+ chapterType: "tech_solution",
12419
+ chapterTitle: `\u{6280}\u{672F}\u{65B9}\u{6848} - ${moduleNames}`,
12420
+ chapterOrder: this.getChapterOrder("tech_solution"),
12421
+ content: JSON.stringify(techSolutionContent),
12422
+ moduleSource: moduleNames,
12423
+ fileCount: batch.totalFiles
12424
+ });
12425
+ const businessExceptionContent = this.generateBusinessExceptionContent(batch, codeAnalysis);
12426
+ if (businessExceptionContent) await techSpecDbOperations.createTechSpecChapter({
12427
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12428
+ projectUuid,
12429
+ chapterType: "business_exception",
12430
+ chapterTitle: `\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{5904}\u{7406} - ${moduleNames}`,
12431
+ chapterOrder: this.getChapterOrder("business_exception"),
12432
+ content: JSON.stringify(businessExceptionContent),
12433
+ moduleSource: moduleNames,
12434
+ fileCount: batch.totalFiles
12435
+ });
12436
+ }
12437
+ getChapterOrder(chapterType) {
12438
+ const orderMap = {
12439
+ project_overview: 1,
12440
+ service_interface_list: 2,
12441
+ interface_design: 3,
12442
+ database_design: 4,
12443
+ tech_solution: 5,
12444
+ business_exception: 6,
12445
+ appendix: 7
12446
+ };
12447
+ return orderMap[chapterType] || 99;
12448
+ }
12449
+ generateTechSolutionContent(batch, codeAnalysis) {
12450
+ const moduleNames = batch.modules.map((m)=>m.name).join(", ");
12451
+ return {
12452
+ content: `
12453
+ ## ${moduleNames} \u{6A21}\u{5757}\u{6280}\u{672F}\u{65B9}\u{6848}
12454
+
12455
+ ### \u{6D41}\u{91CF}\u{4F30}\u{7B97}
12456
+ \u{6839}\u{636E} ${moduleNames} \u{6A21}\u{5757}\u{7684} ${codeAnalysis.serviceInterfaceList.length} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF0C}\u{9884}\u{4F30}\u{65E5}\u{5747}\u{8BF7}\u{6C42}\u{91CF}\u{3002}
12457
+
12458
+ ### \u{6280}\u{672F}\u{67B6}\u{6784}
12459
+ \u{6A21}\u{5757}\u{5305}\u{542B} ${codeAnalysis.tableInfoList.length} \u{4E2A}\u{6570}\u{636E}\u{8868}\u{FF0C}${codeAnalysis.designDetailList.length} \u{4E2A}\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{3002}
12460
+
12461
+ ### \u{4E2D}\u{95F4}\u{4EF6}\u{9009}\u{578B}
12462
+ \u{57FA}\u{4E8E}\u{6A21}\u{5757}\u{7279}\u{70B9}\u{FF0C}\u{5EFA}\u{8BAE}\u{4F7F}\u{7528}\u{76F8}\u{5E94}\u{7684}\u{4E2D}\u{95F4}\u{4EF6}\u{8FDB}\u{884C}\u{652F}\u{6491}\u{3002}
12463
+ `.trim()
12464
+ };
12465
+ }
12466
+ generateBusinessExceptionContent(batch, codeAnalysis) {
12467
+ const moduleNames = batch.modules.map((m)=>m.name).join(", ");
12468
+ return {
12469
+ content: `
12470
+ ## ${moduleNames} \u{6A21}\u{5757}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{5904}\u{7406}
12471
+
12472
+ ### \u{5F02}\u{5E38}\u{5206}\u{7C7B}
12473
+ \u{6A21}\u{5757}\u{4E2D}\u{7684}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{6309}\u{7167}\u{7EDF}\u{4E00}\u{7684}\u{5206}\u{7C7B}\u{6807}\u{51C6}\u{8FDB}\u{884C}\u{5904}\u{7406}\u{3002}
12474
+
12475
+ ### \u{5F02}\u{5E38}\u{5904}\u{7406}\u{7B56}\u{7565}
12476
+ \u{9488}\u{5BF9} ${codeAnalysis.serviceInterfaceList.length} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{7684}\u{5F02}\u{5E38}\u{5904}\u{7406}\u{7B56}\u{7565}\u{3002}
12477
+
12478
+ ### \u{5F02}\u{5E38}\u{7801}\u{5B9A}\u{4E49}
12479
+ \u{6A21}\u{5757}\u{76F8}\u{5173}\u{7684}\u{5F02}\u{5E38}\u{7801}\u{5B9A}\u{4E49}\u{548C}\u{5904}\u{7406}\u{89C4}\u{8303}\u{3002}
12480
+ `.trim()
12481
+ };
12482
+ }
12483
+ async generateProjectOverviewChapter(projectUuid, project, projectAnalysis) {
12484
+ const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
12485
+ const overviewContent = {
12486
+ projectName: project.projectName,
12487
+ moduleName: project.moduleName,
12488
+ projectPath: project.projectPath,
12489
+ totalModules: statistics.totalModules,
12490
+ totalFiles: statistics.totalFiles,
12491
+ summary: `
12492
+ \u{9879}\u{76EE} ${project.projectName} \u{5305}\u{542B} ${statistics.totalModules} \u{4E2A}\u{4E1A}\u{52A1}\u{6A21}\u{5757}\u{FF0C}
12493
+ \u{5171}\u{8BA1} ${statistics.totalFiles} \u{4E2A}\u{4EE3}\u{7801}\u{6587}\u{4EF6}\u{3002}
12494
+
12495
+ \u{901A}\u{8FC7}\u{81EA}\u{52A8}\u{5316}\u{5206}\u{6790}\u{FF0C}\u{751F}\u{6210}\u{4E86} ${statistics.totalChapters} \u{4E2A}\u{6280}\u{672F}\u{89C4}\u{683C}\u{7AE0}\u{8282}\u{FF0C}
12496
+ \u{5305}\u{62EC}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{6E05}\u{5355}\u{3001}\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5}\u{3001}\u{6570}\u{636E}\u{5E93}\u{8BBE}\u{8BA1}\u{7B49}\u{5B8C}\u{6574}\u{5185}\u{5BB9}\u{3002}
12497
+ `.trim(),
12498
+ moduleList: projectAnalysis.modules.map((m)=>({
12499
+ name: m.name,
12500
+ path: m.relativePath,
12501
+ fileCount: m.files.length
12502
+ }))
12503
+ };
12504
+ await techSpecDbOperations.createTechSpecChapter({
12505
+ uuid: (0, external_crypto_namespaceObject.randomUUID)(),
12506
+ projectUuid,
12507
+ chapterType: "project_overview",
12508
+ chapterTitle: "\u9879\u76EE\u6982\u8FF0",
12509
+ chapterOrder: this.getChapterOrder("project_overview"),
12510
+ content: JSON.stringify(overviewContent),
12511
+ moduleSource: "all",
12512
+ fileCount: projectAnalysis.allFiles.length
12513
+ });
12514
+ }
12515
+ }
12516
+ const DEFAULT_MERGE_CONFIG = {
12517
+ includeEmptyChapters: false,
12518
+ generateDefaultContent: true,
12519
+ maxItemsPerChapter: 1000,
12520
+ enableChapterSummary: true
12521
+ };
12522
+ class DocumentMerger {
12523
+ config;
12524
+ constructor(config = {}){
12525
+ this.config = {
12526
+ ...DEFAULT_MERGE_CONFIG,
12527
+ ...config
12528
+ };
12529
+ }
12530
+ async mergeAndRenderDocument(projectUuid, outputDir) {
12531
+ const startTime = Date.now();
12532
+ try {
12533
+ const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
12534
+ if (!project) throw new Error(`\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`);
12535
+ const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
12536
+ const techSpecData = await this.mergeAllChapters(projectUuid, project);
12537
+ const finalOutputDir = outputDir || getTechSpecOutputDir(project.projectPath);
12538
+ const renderResult = await renderTechSpecDoc(techSpecData, finalOutputDir);
12539
+ if (!renderResult.success) throw new Error(renderResult.error || "\u6587\u6863\u6E32\u67D3\u5931\u8D25");
12540
+ await techSpecDbOperations.updateTechSpecProject(projectUuid, {
12541
+ status: "completed",
12542
+ completedAt: new Date()
12543
+ });
12544
+ return {
12545
+ success: true,
12546
+ outputPath: renderResult.outputPath,
12547
+ techSpecData,
12548
+ statistics: {
12549
+ totalChapters: statistics.totalChapters,
12550
+ mergedChapters: statistics.completedChapters,
12551
+ totalServiceInterfaces: techSpecData.serviceInterfaceList.length,
12552
+ totalDesignDetails: techSpecData.designDetailList.length,
12553
+ totalTables: techSpecData.tableInfoList.length,
12554
+ processingTime: Date.now() - startTime
12555
+ }
12556
+ };
12557
+ } catch (error) {
12558
+ await techSpecDbOperations.updateTechSpecProject(projectUuid, {
12559
+ status: "failed"
12560
+ });
12561
+ return {
12562
+ success: false,
12563
+ statistics: {
12564
+ totalChapters: 0,
12565
+ mergedChapters: 0,
12566
+ totalServiceInterfaces: 0,
12567
+ totalDesignDetails: 0,
12568
+ totalTables: 0,
12569
+ processingTime: Date.now() - startTime
12570
+ },
12571
+ errorMessage: error.message
12572
+ };
12573
+ }
12574
+ }
12575
+ async mergeAllChapters(projectUuid, project) {
12576
+ const now = new Date();
12577
+ const techSpecData = {
12578
+ projectName: project.projectName,
12579
+ moduleName: project.moduleName,
12580
+ year: String(now.getFullYear()),
12581
+ month: String(now.getMonth() + 1).padStart(2, "0"),
12582
+ referDoc: "\u9879\u76EE\u4EE3\u7801\u81EA\u52A8\u5206\u6790\u751F\u6210",
12583
+ serviceInterfaceList: [],
12584
+ designDetailList: [],
12585
+ tableInfoList: []
12586
+ };
12587
+ const serviceInterfaces = await techSpecDbOperations.mergeChaptersByType(projectUuid, "service_interface_list");
12588
+ if (serviceInterfaces && Array.isArray(serviceInterfaces)) techSpecData.serviceInterfaceList = this.limitAndReindex(serviceInterfaces, this.config.maxItemsPerChapter);
12589
+ const designDetails = await techSpecDbOperations.mergeChaptersByType(projectUuid, "interface_design");
12590
+ if (designDetails && Array.isArray(designDetails)) techSpecData.designDetailList = designDetails.slice(0, this.config.maxItemsPerChapter);
12591
+ const tableInfos = await techSpecDbOperations.mergeChaptersByType(projectUuid, "database_design");
12592
+ if (tableInfos && Array.isArray(tableInfos)) techSpecData.tableInfoList = this.limitAndReindex(tableInfos, this.config.maxItemsPerChapter);
12593
+ const techSolution = await techSpecDbOperations.mergeChaptersByType(projectUuid, "tech_solution");
12594
+ if (techSolution && techSolution.content) techSpecData.techSolution = {
12595
+ content: techSolution.content
12596
+ };
12597
+ else if (this.config.generateDefaultContent) techSpecData.techSolution = this.generateDefaultTechSolution(techSpecData);
12598
+ const businessException = await techSpecDbOperations.mergeChaptersByType(projectUuid, "business_exception");
12599
+ if (businessException && businessException.content) techSpecData.businessException = {
12600
+ content: businessException.content
12601
+ };
12602
+ else if (this.config.generateDefaultContent) techSpecData.businessException = this.generateDefaultBusinessException();
12603
+ const appendix = await techSpecDbOperations.mergeChaptersByType(projectUuid, "appendix");
12604
+ if (appendix) techSpecData.appendix = {
12605
+ exceptionCodeList: appendix.exceptionCodeList || [],
12606
+ codeValueList: appendix.codeValueList || []
12607
+ };
12608
+ else if (this.config.generateDefaultContent) techSpecData.appendix = this.generateDefaultAppendix();
12609
+ return techSpecData;
12610
+ }
12611
+ limitAndReindex(items, maxItems) {
12612
+ const limitedItems = items.slice(0, maxItems);
12613
+ return limitedItems.map((item, index)=>({
12614
+ ...item,
12615
+ id: String(index + 1)
12616
+ }));
12617
+ }
12618
+ generateDefaultTechSolution(techSpecData) {
12619
+ const serviceCount = techSpecData.serviceInterfaceList.length;
12620
+ const tableCount = techSpecData.tableInfoList.length;
12621
+ return {
12622
+ content: `\u{6839}\u{636E}\u{9879}\u{76EE}\u{89C4}\u{6A21}\u{5206}\u{6790}\u{FF0C}\u{7CFB}\u{7EDF}\u{5305}\u{542B} ${serviceCount} \u{4E2A}\u{670D}\u{52A1}\u{63A5}\u{53E3}\u{FF0C}${tableCount} \u{4E2A}\u{6570}\u{636E}\u{8868}\u{3002}\u{5EFA}\u{8BAE}\u{91C7}\u{7528}\u{5FAE}\u{670D}\u{52A1}\u{67B6}\u{6784}\u{3002}`
12623
+ };
12624
+ }
12625
+ generateDefaultBusinessException() {
12626
+ return {
12627
+ content: `\u{9879}\u{76EE}\u{91C7}\u{7528}\u{7EDF}\u{4E00}\u{5F02}\u{5E38}\u{5904}\u{7406}\u{673A}\u{5236}\u{FF0C}\u{5305}\u{62EC}\u{7CFB}\u{7EDF}\u{5F02}\u{5E38}\u{548C}\u{4E1A}\u{52A1}\u{5F02}\u{5E38}\u{4E24}\u{5927}\u{7C7B}\u{3002}`
12628
+ };
12629
+ }
12630
+ generateDefaultAppendix() {
12631
+ return {
12632
+ exceptionCodeList: [
12633
+ {
12634
+ id: "1",
12635
+ exceptionCode: "SYS0001",
12636
+ exceptionDescription: "\u7CFB\u7EDF\u5185\u90E8\u9519\u8BEF"
12637
+ }
12638
+ ],
12639
+ codeValueList: [
12640
+ {
12641
+ id: "1",
12642
+ propertyName: "\u7528\u6237\u72B6\u6001",
12643
+ codeValue: "1-\u6B63\u5E38\uFF0C0-\u7981\u7528"
12644
+ }
12645
+ ]
12646
+ };
12647
+ }
12648
+ async getProjectProgress(projectUuid) {
12649
+ const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
12650
+ const statistics = await techSpecDbOperations.getProjectStatistics(projectUuid);
12651
+ if (!project) throw new Error(`\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`);
12652
+ const totalSteps = 7;
12653
+ const completedSteps = statistics.completedChapters;
12654
+ const percentage = Math.round(completedSteps / totalSteps * 100);
12655
+ let currentStep = "\u51C6\u5907\u4E2D";
12656
+ if ("analyzing" === project.status) currentStep = "\u5206\u6790\u9879\u76EE\u7ED3\u6784";
12657
+ else if ("generating" === project.status) currentStep = `\u{751F}\u{6210}\u{7AE0}\u{8282}\u{5185}\u{5BB9} (${completedSteps}/${totalSteps})`;
12658
+ else if ("completed" === project.status) currentStep = "\u5DF2\u5B8C\u6210";
12659
+ else if ("failed" === project.status) currentStep = "\u5904\u7406\u5931\u8D25";
12660
+ return {
12661
+ project,
12662
+ statistics,
12663
+ progress: {
12664
+ totalSteps,
12665
+ completedSteps,
12666
+ currentStep,
12667
+ percentage
12668
+ }
12669
+ };
12670
+ }
12671
+ }
11118
12672
  const TableFieldDetailSchema = objectType({
11119
12673
  id: stringType().describe("\u5E8F\u53F7"),
11120
12674
  fieldName: stringType().describe("\u5B57\u6BB5\u540D"),
@@ -11724,7 +13278,430 @@ ${requirement_description}
11724
13278
  }
11725
13279
  }
11726
13280
  };
13281
+ const analyzeLargeProjectTool = {
13282
+ name: "analyze_large_project",
13283
+ description: "\u5206\u6790\u5927\u578B\u9879\u76EE\u5E76\u5206\u7AE0\u8282\u5B58\u50A8\u5230\u6570\u636E\u5E93\uFF0C\u652F\u6301\u5904\u7406\u5305\u542B\u6570\u767E\u4E2A\u6587\u4EF6\u7684\u5927\u578B\u9879\u76EE\u3002\u9002\u7528\u4E8E\u4F01\u4E1A\u7EA7\u9879\u76EE\u7684\u5B8C\u6574\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u3002",
13284
+ inputSchema: {
13285
+ projectPath: stringType().min(1).describe(PROJECT_PATH_DESCRIPTION),
13286
+ projectName: stringType().optional().describe("\u9879\u76EE\u540D\u79F0\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u76EE\u5F55\u540D"),
13287
+ moduleName: stringType().optional().describe("\u6A21\u5757\u540D\u79F0\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u9879\u76EE\u540D"),
13288
+ includeModules: arrayType(stringType()).optional().describe("\u8981\u5305\u542B\u7684\u6A21\u5757\u5217\u8868\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u5305\u542B\u6240\u6709\u6A21\u5757"),
13289
+ excludeModules: arrayType(stringType()).optional().describe("\u8981\u6392\u9664\u7684\u6A21\u5757\u5217\u8868"),
13290
+ maxFilesPerBatch: numberType().optional().default(50).describe("\u6BCF\u6279\u5904\u7406\u7684\u6700\u5927\u6587\u4EF6\u6570"),
13291
+ maxModulesPerChapter: numberType().optional().default(10).describe("\u6BCF\u7AE0\u8282\u7684\u6700\u5927\u6A21\u5757\u6570")
13292
+ },
13293
+ handler: async (args)=>{
13294
+ try {
13295
+ const { projectPath, projectName, moduleName, includeModules, excludeModules, maxFilesPerBatch = 50, maxModulesPerChapter = 10 } = args;
13296
+ if (!projectPath) return {
13297
+ content: [
13298
+ {
13299
+ type: "text",
13300
+ text: JSON.stringify({
13301
+ success: false,
13302
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPath"
13303
+ })
13304
+ }
13305
+ ],
13306
+ isError: true
13307
+ };
13308
+ logger.info(`\u{5F00}\u{59CB}\u{5206}\u{6790}\u{5927}\u{578B}\u{9879}\u{76EE}: ${projectPath}`);
13309
+ const projectAnalysis = await analyzeProject(projectPath);
13310
+ const chapterProcessor = new ChapterProcessor({
13311
+ maxFilesPerBatch,
13312
+ maxModulesPerChapter,
13313
+ enableParallelProcessing: true,
13314
+ skipEmptyModules: true
13315
+ });
13316
+ const result = await chapterProcessor.processFullProject(projectAnalysis, {
13317
+ projectName,
13318
+ moduleName,
13319
+ includeModules,
13320
+ excludeModules
13321
+ });
13322
+ if (result.success) return {
13323
+ content: [
13324
+ {
13325
+ type: "text",
13326
+ text: JSON.stringify({
13327
+ success: true,
13328
+ message: "\u5927\u578B\u9879\u76EE\u5206\u6790\u5B8C\u6210\uFF0C\u7AE0\u8282\u5DF2\u5B58\u50A8\u5230\u6570\u636E\u5E93",
13329
+ data: {
13330
+ projectUuid: result.projectUuid,
13331
+ projectAnalysis: {
13332
+ projectName: projectAnalysis.projectName,
13333
+ moduleCount: projectAnalysis.modules.length,
13334
+ totalFiles: projectAnalysis.statistics.totalFiles,
13335
+ modules: getModuleNames(projectAnalysis)
13336
+ },
13337
+ processingResult: {
13338
+ totalChapters: result.totalChapters,
13339
+ processedChapters: result.processedChapters,
13340
+ totalModules: result.totalModules,
13341
+ processedModules: result.processedModules,
13342
+ totalFiles: result.totalFiles,
13343
+ processedFiles: result.processedFiles
13344
+ },
13345
+ statistics: result.statistics,
13346
+ nextStep: `\u{8C03}\u{7528} render_final_document \u{5DE5}\u{5177}\u{FF0C}\u{4F7F}\u{7528} projectUuid: ${result.projectUuid} \u{751F}\u{6210}\u{6700}\u{7EC8}\u{6587}\u{6863}`
13347
+ }
13348
+ })
13349
+ }
13350
+ ]
13351
+ };
13352
+ return {
13353
+ content: [
13354
+ {
13355
+ type: "text",
13356
+ text: JSON.stringify({
13357
+ success: false,
13358
+ message: result.errorMessage || "\u5927\u578B\u9879\u76EE\u5206\u6790\u5931\u8D25",
13359
+ data: {
13360
+ projectUuid: result.projectUuid,
13361
+ statistics: result.statistics
13362
+ }
13363
+ })
13364
+ }
13365
+ ],
13366
+ isError: true
13367
+ };
13368
+ } catch (error) {
13369
+ logger.error("\u5927\u578B\u9879\u76EE\u5206\u6790\u5931\u8D25", {
13370
+ error: error.message
13371
+ });
13372
+ return {
13373
+ content: [
13374
+ {
13375
+ type: "text",
13376
+ text: JSON.stringify({
13377
+ success: false,
13378
+ message: error.message || "\u5206\u6790\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
13379
+ })
13380
+ }
13381
+ ],
13382
+ isError: true
13383
+ };
13384
+ }
13385
+ }
13386
+ };
13387
+ const renderFinalDocumentTool = {
13388
+ name: "render_final_document",
13389
+ description: "\u5C06\u6570\u636E\u5E93\u4E2D\u5B58\u50A8\u7684\u7AE0\u8282\u5408\u5E76\u5E76\u6E32\u67D3\u4E3A\u6700\u7EC8\u7684\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66Word\u6587\u6863\u3002\u7528\u4E8E\u5927\u578B\u9879\u76EE\u7684\u6700\u7EC8\u6587\u6863\u751F\u6210\u3002",
13390
+ inputSchema: {
13391
+ projectUuid: stringType().min(1).describe("\u9879\u76EEUUID\uFF0C\u7531 analyze_large_project \u5DE5\u5177\u8FD4\u56DE"),
13392
+ outputDir: stringType().optional().describe("\u8F93\u51FA\u76EE\u5F55\uFF0C\u5982\u4E0D\u63D0\u4F9B\u5219\u4F7F\u7528\u9879\u76EE\u9ED8\u8BA4\u76EE\u5F55"),
13393
+ includeEmptyChapters: booleanType().optional().default(false).describe("\u662F\u5426\u5305\u542B\u7A7A\u7AE0\u8282"),
13394
+ generateDefaultContent: booleanType().optional().default(true).describe("\u662F\u5426\u4E3A\u7A7A\u7AE0\u8282\u751F\u6210\u9ED8\u8BA4\u5185\u5BB9"),
13395
+ maxItemsPerChapter: numberType().optional().default(1000).describe("\u6BCF\u7AE0\u8282\u6700\u5927\u6761\u76EE\u6570")
13396
+ },
13397
+ handler: async (args)=>{
13398
+ try {
13399
+ const { projectUuid, outputDir, includeEmptyChapters = false, generateDefaultContent = true, maxItemsPerChapter = 1000 } = args;
13400
+ if (!projectUuid) return {
13401
+ content: [
13402
+ {
13403
+ type: "text",
13404
+ text: JSON.stringify({
13405
+ success: false,
13406
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectUuid"
13407
+ })
13408
+ }
13409
+ ],
13410
+ isError: true
13411
+ };
13412
+ logger.info(`\u{5F00}\u{59CB}\u{6E32}\u{67D3}\u{6700}\u{7EC8}\u{6587}\u{6863}: ${projectUuid}`);
13413
+ const project = await techSpecDbOperations.getTechSpecProject(projectUuid);
13414
+ if (!project) return {
13415
+ content: [
13416
+ {
13417
+ type: "text",
13418
+ text: JSON.stringify({
13419
+ success: false,
13420
+ message: `\u{9879}\u{76EE}\u{4E0D}\u{5B58}\u{5728}: ${projectUuid}`
13421
+ })
13422
+ }
13423
+ ],
13424
+ isError: true
13425
+ };
13426
+ const documentMerger = new DocumentMerger({
13427
+ includeEmptyChapters,
13428
+ generateDefaultContent,
13429
+ maxItemsPerChapter,
13430
+ enableChapterSummary: true
13431
+ });
13432
+ const result = await documentMerger.mergeAndRenderDocument(projectUuid, outputDir);
13433
+ if (result.success) return {
13434
+ content: [
13435
+ {
13436
+ type: "text",
13437
+ text: JSON.stringify({
13438
+ success: true,
13439
+ message: "\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u6210\u529F",
13440
+ data: {
13441
+ projectUuid,
13442
+ outputPath: result.outputPath,
13443
+ projectInfo: {
13444
+ projectName: project.projectName,
13445
+ moduleName: project.moduleName,
13446
+ projectPath: project.projectPath
13447
+ },
13448
+ statistics: result.statistics,
13449
+ techSpecSummary: {
13450
+ serviceInterfaceCount: result.statistics.totalServiceInterfaces,
13451
+ designDetailCount: result.statistics.totalDesignDetails,
13452
+ tableCount: result.statistics.totalTables,
13453
+ chapterCount: result.statistics.totalChapters
13454
+ }
13455
+ }
13456
+ })
13457
+ }
13458
+ ]
13459
+ };
13460
+ return {
13461
+ content: [
13462
+ {
13463
+ type: "text",
13464
+ text: JSON.stringify({
13465
+ success: false,
13466
+ message: result.errorMessage || "\u6587\u6863\u6E32\u67D3\u5931\u8D25",
13467
+ data: {
13468
+ projectUuid,
13469
+ statistics: result.statistics
13470
+ }
13471
+ })
13472
+ }
13473
+ ],
13474
+ isError: true
13475
+ };
13476
+ } catch (error) {
13477
+ logger.error("\u6587\u6863\u6E32\u67D3\u5931\u8D25", {
13478
+ error: error.message
13479
+ });
13480
+ return {
13481
+ content: [
13482
+ {
13483
+ type: "text",
13484
+ text: JSON.stringify({
13485
+ success: false,
13486
+ message: error.message || "\u6E32\u67D3\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF"
13487
+ })
13488
+ }
13489
+ ],
13490
+ isError: true
13491
+ };
13492
+ }
13493
+ }
13494
+ };
13495
+ const getProjectProgressTool = {
13496
+ name: "get_project_progress",
13497
+ description: "\u83B7\u53D6\u5927\u578B\u9879\u76EE\u5904\u7406\u8FDB\u5EA6\u548C\u72B6\u6001\u4FE1\u606F\u3002\u7528\u4E8E\u76D1\u63A7\u9879\u76EE\u5206\u6790\u548C\u6587\u6863\u751F\u6210\u7684\u8FDB\u5EA6\u3002",
13498
+ inputSchema: {
13499
+ projectUuid: stringType().min(1).describe("\u9879\u76EEUUID")
13500
+ },
13501
+ handler: async (args)=>{
13502
+ try {
13503
+ const { projectUuid } = args;
13504
+ if (!projectUuid) return {
13505
+ content: [
13506
+ {
13507
+ type: "text",
13508
+ text: JSON.stringify({
13509
+ success: false,
13510
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectUuid"
13511
+ })
13512
+ }
13513
+ ],
13514
+ isError: true
13515
+ };
13516
+ const documentMerger = new DocumentMerger();
13517
+ const progressInfo = await documentMerger.getProjectProgress(projectUuid);
13518
+ return {
13519
+ content: [
13520
+ {
13521
+ type: "text",
13522
+ text: JSON.stringify({
13523
+ success: true,
13524
+ message: "\u9879\u76EE\u8FDB\u5EA6\u83B7\u53D6\u6210\u529F",
13525
+ data: {
13526
+ projectUuid,
13527
+ project: {
13528
+ projectName: progressInfo.project.projectName,
13529
+ moduleName: progressInfo.project.moduleName,
13530
+ status: progressInfo.project.status,
13531
+ createdAt: progressInfo.project.createdAt,
13532
+ updatedAt: progressInfo.project.updatedAt,
13533
+ completedAt: progressInfo.project.completedAt
13534
+ },
13535
+ progress: progressInfo.progress,
13536
+ statistics: progressInfo.statistics,
13537
+ isCompleted: "completed" === progressInfo.project.status,
13538
+ canRender: progressInfo.statistics.completedChapters > 0
13539
+ }
13540
+ })
13541
+ }
13542
+ ]
13543
+ };
13544
+ } catch (error) {
13545
+ return {
13546
+ content: [
13547
+ {
13548
+ type: "text",
13549
+ text: JSON.stringify({
13550
+ success: false,
13551
+ message: error.message || "\u83B7\u53D6\u8FDB\u5EA6\u5931\u8D25"
13552
+ })
13553
+ }
13554
+ ],
13555
+ isError: true
13556
+ };
13557
+ }
13558
+ }
13559
+ };
13560
+ const listTechSpecProjectsTool = {
13561
+ name: "list_tech_spec_projects",
13562
+ description: "\u5217\u51FA\u6240\u6709\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u9879\u76EE\u53CA\u5176\u72B6\u6001\u3002\u7528\u4E8E\u67E5\u770B\u5386\u53F2\u9879\u76EE\u548C\u7BA1\u7406\u9879\u76EE\u3002",
13563
+ inputSchema: {
13564
+ status: stringType().optional().describe("\u8FC7\u6EE4\u72B6\u6001\uFF1Aanalyzing, generating, completed, failed"),
13565
+ limit: numberType().optional().default(20).describe("\u8FD4\u56DE\u6570\u91CF\u9650\u5236")
13566
+ },
13567
+ handler: async (args)=>{
13568
+ try {
13569
+ const { status, limit = 20 } = args;
13570
+ let projects = await techSpecDbOperations.getAllTechSpecProjects();
13571
+ if (status) projects = projects.filter((p)=>p.status === status);
13572
+ projects.sort((a, b)=>b.createdAt.getTime() - a.createdAt.getTime());
13573
+ projects = projects.slice(0, limit);
13574
+ const projectsWithStats = await Promise.all(projects.map(async (project)=>{
13575
+ try {
13576
+ const statistics = await techSpecDbOperations.getProjectStatistics(project.uuid);
13577
+ return {
13578
+ ...project,
13579
+ statistics
13580
+ };
13581
+ } catch (error) {
13582
+ return {
13583
+ ...project,
13584
+ statistics: null
13585
+ };
13586
+ }
13587
+ }));
13588
+ return {
13589
+ content: [
13590
+ {
13591
+ type: "text",
13592
+ text: JSON.stringify({
13593
+ success: true,
13594
+ message: `\u{627E}\u{5230} ${projectsWithStats.length} \u{4E2A}\u{9879}\u{76EE}`,
13595
+ data: {
13596
+ projects: projectsWithStats.map((p)=>({
13597
+ uuid: p.uuid,
13598
+ projectName: p.projectName,
13599
+ moduleName: p.moduleName,
13600
+ status: p.status,
13601
+ totalModules: p.totalModules,
13602
+ processedModules: p.processedModules,
13603
+ totalFiles: p.totalFiles,
13604
+ processedFiles: p.processedFiles,
13605
+ createdAt: p.createdAt,
13606
+ updatedAt: p.updatedAt,
13607
+ completedAt: p.completedAt,
13608
+ statistics: p.statistics
13609
+ })),
13610
+ totalCount: projectsWithStats.length
13611
+ }
13612
+ })
13613
+ }
13614
+ ]
13615
+ };
13616
+ } catch (error) {
13617
+ return {
13618
+ content: [
13619
+ {
13620
+ type: "text",
13621
+ text: JSON.stringify({
13622
+ success: false,
13623
+ message: error.message || "\u83B7\u53D6\u9879\u76EE\u5217\u8868\u5931\u8D25"
13624
+ })
13625
+ }
13626
+ ],
13627
+ isError: true
13628
+ };
13629
+ }
13630
+ }
13631
+ };
13632
+ const analyzeProjectStructureTool = {
13633
+ name: "analyze_project_structure",
13634
+ description: "\u4EC5\u5206\u6790\u9879\u76EE\u7ED3\u6784\uFF0C\u4E0D\u751F\u6210\u6587\u6863\u3002\u7528\u4E8E\u4E86\u89E3\u9879\u76EE\u7684\u6A21\u5757\u548C\u6587\u4EF6\u7EC4\u7EC7\u60C5\u51B5\u3002",
13635
+ inputSchema: {
13636
+ projectPath: stringType().min(1).describe(PROJECT_PATH_DESCRIPTION)
13637
+ },
13638
+ handler: async (args)=>{
13639
+ try {
13640
+ const { projectPath } = args;
13641
+ if (!projectPath) return {
13642
+ content: [
13643
+ {
13644
+ type: "text",
13645
+ text: JSON.stringify({
13646
+ success: false,
13647
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPath"
13648
+ })
13649
+ }
13650
+ ],
13651
+ isError: true
13652
+ };
13653
+ const analysis = await analyzeProject(projectPath);
13654
+ return {
13655
+ content: [
13656
+ {
13657
+ type: "text",
13658
+ text: JSON.stringify({
13659
+ success: true,
13660
+ message: "\u9879\u76EE\u7ED3\u6784\u5206\u6790\u5B8C\u6210",
13661
+ data: {
13662
+ projectName: analysis.projectName,
13663
+ projectPath: analysis.projectPath,
13664
+ statistics: analysis.statistics,
13665
+ modules: analysis.modules.map((m)=>({
13666
+ name: m.name,
13667
+ relativePath: m.relativePath,
13668
+ fileCount: m.files.length,
13669
+ fileTypes: {
13670
+ controller: m.files.filter((f)=>"controller" === f.type).length,
13671
+ service: m.files.filter((f)=>"service" === f.type).length,
13672
+ entity: m.files.filter((f)=>"entity" === f.type).length,
13673
+ dto: m.files.filter((f)=>"dto" === f.type).length,
13674
+ other: m.files.filter((f)=>"other" === f.type).length
13675
+ }
13676
+ })),
13677
+ availableModules: getModuleNames(analysis)
13678
+ }
13679
+ })
13680
+ }
13681
+ ]
13682
+ };
13683
+ } catch (error) {
13684
+ return {
13685
+ content: [
13686
+ {
13687
+ type: "text",
13688
+ text: JSON.stringify({
13689
+ success: false,
13690
+ message: error.message || "\u9879\u76EE\u7ED3\u6784\u5206\u6790\u5931\u8D25"
13691
+ })
13692
+ }
13693
+ ],
13694
+ isError: true
13695
+ };
13696
+ }
13697
+ }
13698
+ };
11727
13699
  const techSpecGeneratorTools = [
13700
+ analyzeLargeProjectTool,
13701
+ renderFinalDocumentTool,
13702
+ getProjectProgressTool,
13703
+ listTechSpecProjectsTool,
13704
+ analyzeProjectStructureTool,
11728
13705
  analyzeProjectContextTool,
11729
13706
  collectServiceInterfacesTool,
11730
13707
  generateInterfaceDesignsTool,