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/db/tech-spec-storage.d.ts +139 -0
- package/dist/db/tech-spec-storage.d.ts.map +1 -0
- package/dist/index.cjs +1977 -0
- package/dist/services/tech-spec-generator/chapter-processor.d.ts +95 -0
- package/dist/services/tech-spec-generator/chapter-processor.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/code-analyzer.d.ts +19 -0
- package/dist/services/tech-spec-generator/code-analyzer.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/document-merger.d.ts +50 -0
- package/dist/services/tech-spec-generator/document-merger.d.ts.map +1 -0
- package/dist/services/tech-spec-generator/index.d.ts +172 -22
- package/dist/services/tech-spec-generator/index.d.ts.map +1 -1
- package/dist/services/tech-spec-generator/project-analyzer.d.ts +58 -0
- package/dist/services/tech-spec-generator/project-analyzer.d.ts.map +1 -0
- package/package.json +2 -2
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,
|