requirements-analysis
Version:
简化的需求分析MCP服务 - 基于AI软件工程(优化版)6步流程
141 lines (118 loc) • 3.98 kB
text/typescript
/**
* 文档引用管理器
* 负责管理步骤间的文档引用和内容传递
*/
import { promises as fs } from 'fs';
import { join } from 'path';
import { Logger } from './logger';
export class DocumentReferenceManager {
private projectDir: string;
private logger = new Logger();
constructor(projectName: string) {
this.projectDir = join('outputs', projectName);
}
/**
* 获取指定步骤的文档内容
*/
async getStepDocument(stepNumber: number): Promise<string> {
try {
const files = await fs.readdir(this.projectDir);
const stepFile = files.find(f => f.startsWith(`step${stepNumber}-`));
if (!stepFile) {
throw new Error(`Step ${stepNumber} document not found in ${this.projectDir}`);
}
const filePath = join(this.projectDir, stepFile);
const content = await fs.readFile(filePath, 'utf-8');
this.logger.info(`Successfully loaded step ${stepNumber} document: ${stepFile}`);
return content;
} catch (error) {
this.logger.error(`Failed to load step ${stepNumber} document:`, undefined, undefined, error);
throw error;
}
}
/**
* 获取多个步骤的文档内容
*/
async getMultipleStepDocuments(stepNumbers: number[]): Promise<Map<number, string>> {
const results = new Map<number, string>();
for (const stepNumber of stepNumbers) {
try {
const content = await this.getStepDocument(stepNumber);
results.set(stepNumber, content);
} catch (error) {
this.logger.warn(`Failed to load step ${stepNumber} document, using empty content`);
results.set(stepNumber, ''); // 空内容作为降级
}
}
return results;
}
/**
* 检查步骤文档是否存在
*/
async isStepDocumentReady(stepNumber: number): Promise<boolean> {
try {
await this.getStepDocument(stepNumber);
return true;
} catch {
return false;
}
}
/**
* 获取项目目录下所有可用的步骤文档
*/
async getAvailableStepDocuments(): Promise<number[]> {
try {
const files = await fs.readdir(this.projectDir);
const stepFiles = files.filter(f => f.match(/^step\d+-.*\.md$/));
const stepNumbers = stepFiles.map(f => {
const match = f.match(/^step(\d+)-/);
return match ? parseInt(match[1]) : 0;
}).filter(n => n > 0);
return stepNumbers.sort((a, b) => a - b);
} catch (error) {
this.logger.warn('Failed to scan available step documents:', undefined, undefined, error);
return [];
}
}
/**
* 等待指定步骤的文档就绪
*/
async waitForStepDocument(stepNumber: number, maxWaitTime: number = 30000): Promise<boolean> {
const startTime = Date.now();
const checkInterval = 1000; // 1秒检查一次
while (Date.now() - startTime < maxWaitTime) {
if (await this.isStepDocumentReady(stepNumber)) {
return true;
}
await new Promise(resolve => setTimeout(resolve, checkInterval));
}
this.logger.warn(`Timeout waiting for step ${stepNumber} document after ${maxWaitTime}ms`);
return false;
}
/**
* 获取文档的基本信息
*/
async getDocumentInfo(stepNumber: number): Promise<{
fileName: string;
size: number;
lastModified: Date;
} | null> {
try {
const files = await fs.readdir(this.projectDir);
const stepFile = files.find(f => f.startsWith(`step${stepNumber}-`));
if (!stepFile) {
return null;
}
const filePath = join(this.projectDir, stepFile);
const stats = await fs.stat(filePath);
return {
fileName: stepFile,
size: stats.size,
lastModified: stats.mtime
};
} catch (error) {
this.logger.error(`Failed to get document info for step ${stepNumber}:`, undefined, undefined, error);
return null;
}
}
}