UNPKG

taskflow-ai

Version:

TaskFlow AI - 智能PRD文档解析与任务管理助手,支持多模型AI协同、MCP编辑器集成,专为开发团队设计的CLI工具

1 lines 79.9 kB
"use strict";var t=require("fs-extra"),e=require("path"),s=require("markdown-it"),r=require("fs"),n=require("os"),i=require("winston"),a=require("axios"),o=require("crypto");function c(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,r.get?r:{enumerable:!0,get:function(){return t[s]}})}}),e.default=t,Object.freeze(e)}var u,h,l,p,d,m,y,f,w,g,v,$,x,k=c(t),b=c(e),T=c(r),D=c(n),P=c(o);exports.MessageRole=void 0,(u=exports.MessageRole||(exports.MessageRole={})).USER="user",u.ASSISTANT="assistant",u.SYSTEM="system",exports.FileType=void 0,(h=exports.FileType||(exports.FileType={})).MARKDOWN="markdown",h.PDF="pdf",h.WORD="word",h.TEXT="text",h.JSON="json",h.UNKNOWN="unknown",function(t){t.MARKDOWN="markdown",t.TEXT="text",t.JSON="json",t.HTML="html",t.WORD="word",t.PDF="pdf"}(l||(l={})),function(t){t.OVERVIEW="overview",t.REQUIREMENTS="requirements",t.FEATURES="features",t.TECHNICAL="technical",t.TIMELINE="timeline",t.RESOURCES="resources",t.APPENDIX="appendix",t.OTHER="other"}(p||(p={}));class S{constructor(t){this.logger=t,this.markdownParser=new s({html:!0,linkify:!0,typographer:!0})}async processDocument(t,e={}){try{if(this.logger.info(`开始处理文档: ${t}`),!await k.pathExists(t))throw new Error(`文件不存在: ${t}`);const s=await k.stat(t),r=this.detectDocumentType(t),n=await this.readFileContent(t,r),i={fileName:b.basename(t),fileSize:s.size,createdAt:s.birthtime,modifiedAt:s.mtime,documentType:r,language:e.detectLanguage?this.detectLanguage(n):"zh-CN",wordCount:this.countWords(n),estimatedReadTime:Math.ceil(this.countWords(n)/200)},a=await this.parseDocumentStructure(n,r,e),o={title:this.extractTitle(n,r)||i.fileName,sections:a,metadata:i};return this.logger.info(`文档处理完成: ${a.length} 个章节`),o}catch(t){throw this.logger.error(`文档处理失败: ${t.message}`),t}}detectDocumentType(t){switch(b.extname(t).toLowerCase()){case".md":case".markdown":return l.MARKDOWN;case".txt":default:return l.TEXT;case".json":return l.JSON;case".html":case".htm":return l.HTML;case".docx":case".doc":return l.WORD;case".pdf":return l.PDF}}async readFileContent(t,e){switch(e){case l.MARKDOWN:case l.TEXT:case l.HTML:case l.JSON:return await k.readFile(t,"utf-8");case l.WORD:return this.logger.warn("Word文档解析暂未实现,将作为文本处理"),await k.readFile(t,"utf-8");case l.PDF:return this.logger.warn("PDF文档解析暂未实现,将作为文本处理"),await k.readFile(t,"utf-8");default:return await k.readFile(t,"utf-8")}}async parseDocumentStructure(t,e,s){switch(e){case l.MARKDOWN:return this.parseMarkdownStructure(t,s);case l.TEXT:return this.parseTextStructure(t,s);case l.JSON:return this.parseJsonStructure(t,s);case l.HTML:return this.parseHtmlStructure(t,s);default:return this.parseTextStructure(t,s)}}parseMarkdownStructure(t,e){const s=[],r=t.split("\n");let n=null,i=0;for(let t=0;t<r.length;t++){const a=r[t].trim(),o=a.match(/^(#{1,6})\s+(.+)$/);if(o){const t=o[1].length,r=o[2].trim();n&&s.push(n),n={id:"section-"+ ++i,title:r,content:"",level:t,subsections:[],type:this.classifySectionType(r),keywords:e.extractKeywords?this.extractKeywords(r):[],importance:e.calculateImportance?this.calculateImportance(r,""):.5}}else n&&a&&(n.content+=a+"\n")}return n&&s.push(n),(e.calculateImportance||e.extractKeywords)&&s.forEach(t=>{e.extractKeywords&&(t.keywords=this.extractKeywords(t.title+" "+t.content)),e.calculateImportance&&(t.importance=this.calculateImportance(t.title,t.content))}),this.buildSectionHierarchy(s)}parseTextStructure(t,e){const s=[];return t.split(/\n\s*\n/).filter(t=>t.trim()).forEach((t,r)=>{const n=t.trim().split("\n"),i=n[0].trim(),a=n.slice(1).join("\n").trim();s.push({id:`section-${r+1}`,title:i||`段落 ${r+1}`,content:a,level:1,subsections:[],type:this.classifySectionType(i),keywords:e.extractKeywords?this.extractKeywords(t):[],importance:e.calculateImportance?this.calculateImportance(i,a):.5})}),s}parseJsonStructure(t,e){try{const e=JSON.parse(t),s=[];return Array.isArray(e)?e.forEach((t,e)=>{s.push(this.createSectionFromObject(t,`item-${e}`,1))}):"object"==typeof e&&Object.entries(e).forEach(([t,e],r)=>{s.push(this.createSectionFromObject({[t]:e},`section-${r+1}`,1))}),s}catch(t){return this.logger.error(`JSON解析失败: ${t.message}`),[]}}parseHtmlStructure(t,e){const s=[],r=/<h([1-6])[^>]*>(.*?)<\/h[1-6]>/gi;let n,i=0;for(;null!==(n=r.exec(t));){const t=parseInt(n[1]),r=n[2].replace(/<[^>]*>/g,"").trim();s.push({id:"section-"+ ++i,title:r,content:"",level:t,subsections:[],type:this.classifySectionType(r),keywords:e.extractKeywords?this.extractKeywords(r):[],importance:e.calculateImportance?this.calculateImportance(r,""):.5})}return this.buildSectionHierarchy(s)}createSectionFromObject(t,e,s){const r="object"==typeof t&&null!==t?Object.keys(t)[0]||e:String(t),n="object"==typeof t&&null!==t?JSON.stringify(t,null,2):String(t);return{id:e,title:r,content:n,level:s,subsections:[],type:this.classifySectionType(r),keywords:this.extractKeywords(n),importance:this.calculateImportance(r,n)}}buildSectionHierarchy(t){const e=[],s=[];for(const r of t){for(;s.length>0&&s[s.length-1].level>=r.level;)s.pop();0===s.length?e.push(r):s[s.length-1].subsections.push(r),s.push(r)}return e}classifySectionType(t){const e=t.toLowerCase();return e.includes("概述")||e.includes("overview")||e.includes("简介")?p.OVERVIEW:e.includes("需求")||e.includes("requirement")?p.REQUIREMENTS:e.includes("功能")||e.includes("feature")?p.FEATURES:e.includes("技术")||e.includes("technical")||e.includes("架构")?p.TECHNICAL:e.includes("时间")||e.includes("timeline")||e.includes("计划")?p.TIMELINE:e.includes("资源")||e.includes("resource")?p.RESOURCES:e.includes("附录")||e.includes("appendix")?p.APPENDIX:p.OTHER}extractKeywords(t){const e=t.toLowerCase().replace(/[^\u4e00-\u9fa5a-zA-Z0-9\s]/g," ").split(/\s+/).filter(t=>t.length>1),s=new Map;return e.forEach(t=>{s.set(t,(s.get(t)||0)+1)}),Array.from(s.entries()).sort((t,e)=>e[1]-t[1]).slice(0,10).map(([t])=>t)}calculateImportance(t,e){let s=.5;const r=t.toLowerCase();["核心","关键","重要","必须","主要","core","key","important","critical","main"].forEach(t=>{r.includes(t)&&(s+=.1)});const n=e.length;switch(n>1e3&&(s+=.1),n>2e3&&(s+=.1),this.classifySectionType(t)){case p.REQUIREMENTS:case p.FEATURES:s+=.2;break;case p.TECHNICAL:s+=.15;break;case p.OVERVIEW:s+=.1}return Math.min(1,s)}extractTitle(t,e){switch(e){case l.MARKDOWN:{const e=t.match(/^#\s+(.+)$/m);return e?e[1].trim():null}case l.HTML:{const e=t.match(/<h1[^>]*>(.*?)<\/h1>/i);return e?e[1].replace(/<[^>]*>/g,"").trim():null}default:{const e=t.split("\n")[0].trim();return e.length>0&&e.length<100?e:null}}}detectLanguage(t){const e=t.match(/[\u4e00-\u9fa5]/g),s=t.replace(/\s/g,"").length;return e&&e.length/s>.3?"zh-CN":"en-US"}countWords(t){const e=t.match(/[\u4e00-\u9fa5]/g),s=t.match(/[a-zA-Z]+/g);return(e?e.length:0)+(s?s.length:0)}}exports.TaskStatus=void 0,(d=exports.TaskStatus||(exports.TaskStatus={})).NOT_STARTED="not_started",d.PENDING="pending",d.IN_PROGRESS="in_progress",d.RUNNING="running",d.COMPLETED="completed",d.DONE="done",d.CANCELLED="cancelled",d.FAILED="failed",d.BLOCKED="blocked",d.ON_HOLD="on_hold",d.REVIEW="review",d.TODO="todo",exports.TaskPriority=void 0,(m=exports.TaskPriority||(exports.TaskPriority={})).LOW="low",m.MEDIUM="medium",m.HIGH="high",m.CRITICAL="critical",exports.TaskType=void 0,(y=exports.TaskType||(exports.TaskType={})).FEATURE="feature",y.BUG_FIX="bug_fix",y.REFACTOR="refactor",y.TEST="test",y.DOCUMENT="document",y.ANALYSIS="analysis",y.DESIGN="design",y.DEPLOYMENT="deployment",y.RESEARCH="research",function(t){t.FUNCTIONAL="functional",t.NON_FUNCTIONAL="non_functional",t.BUSINESS="business",t.TECHNICAL="technical",t.USER_STORY="user_story",t.CONSTRAINT="constraint",t.ASSUMPTION="assumption"}(f||(f={}));class A{constructor(t){this.requirementPatterns={functional:[/系统(应该|必须|需要|能够)(.+)/gi,/用户(可以|能够|应该)(.+)/gi,/应用程序(应该|必须|需要)(.+)/gi,/(实现|支持|提供)(.+)功能/gi,/the system (should|must|shall|will)(.+)/gi,/users (can|should|must|will be able to)(.+)/gi],nonFunctional:[/(性能|响应时间|吞吐量)(.+)/gi,/(安全|权限|认证)(.+)/gi,/(可用性|稳定性|可靠性)(.+)/gi,/(兼容性|扩展性|可维护性)(.+)/gi,/(performance|security|usability|reliability)(.+)/gi],userStory:[/作为(.+?),我希望(.+?),以便(.+)/gi,/As a (.+?), I want (.+?) so that (.+)/gi,/Given (.+?) when (.+?) then (.+)/gi],constraint:[/(限制|约束|不能|禁止)(.+)/gi,/(constraint|limitation|restriction)(.+)/gi]},this.priorityKeywords={critical:["关键","核心","重要","必须","critical","essential","must","key"],high:["高","优先","重点","high","priority","important"],medium:["中等","一般","普通","medium","normal","standard"],low:["低","次要","可选","low","optional","nice to have"]},this.complexityKeywords={high:["复杂","困难","挑战","集成","算法","complex","difficult","challenging","integration"],medium:["中等","标准","常规","medium","standard","typical"],low:["简单","基础","直接","simple","basic","straightforward"]},this.logger=t}async extractRequirements(t,e={}){try{this.logger.info("开始提取需求");const s=[],r=[],n=[];for(const r of t.sections){const t=await this.extractFromSection(r,e);s.push(...t)}e.detectDependencies&&this.detectDependencies(s);const i=this.generateSummary(s);return n.push(...this.generateSuggestions(s,i)),r.push(...this.validateRequirements(s)),this.logger.info(`需求提取完成: ${s.length} 个需求`),{requirements:s,summary:i,warnings:r,suggestions:n}}catch(t){throw this.logger.error(`需求提取失败: ${t.message}`),t}}async extractFromSection(t,e){const s=[],r=t.title+"\n"+t.content;switch(t.type){case p.REQUIREMENTS:s.push(...this.extractFunctionalRequirements(t,r)),s.push(...this.extractNonFunctionalRequirements(t,r));break;case p.FEATURES:s.push(...this.extractFeatureRequirements(t,r)),e.includeUserStories&&s.push(...this.extractUserStories(t,r));break;case p.TECHNICAL:s.push(...this.extractTechnicalRequirements(t,r));break;default:s.push(...this.extractGeneralRequirements(t,r))}for(const r of t.subsections){const t=await this.extractFromSection(r,e);s.push(...t)}return s}extractFunctionalRequirements(t,e){const s=[];let r=1;return this.requirementPatterns.functional.forEach(n=>{let i;for(;null!==(i=n.exec(e));){const n=i[0].trim();n.length>10&&s.push(this.createRequirement(`${t.id}-func-${r++}`,this.extractTitle(n),n,f.FUNCTIONAL,t,e))}}),s}extractNonFunctionalRequirements(t,e){const s=[];let r=1;return this.requirementPatterns.nonFunctional.forEach(n=>{let i;for(;null!==(i=n.exec(e));){const n=i[0].trim();n.length>10&&s.push(this.createRequirement(`${t.id}-nonfunc-${r++}`,this.extractTitle(n),n,f.NON_FUNCTIONAL,t,e))}}),s}extractFeatureRequirements(t,e){const s=[],r=e.split("\n").filter(t=>t.trim());let n=1;return r.forEach(r=>{const i=r.trim();this.isFunctionDescription(i)&&s.push(this.createRequirement(`${t.id}-feature-${n++}`,this.extractTitle(i),i,f.FUNCTIONAL,t,e))}),s}extractUserStories(t,e){const s=[];let r=1;return this.requirementPatterns.userStory.forEach(n=>{let i;for(;null!==(i=n.exec(e));){const n=i[0].trim();s.push(this.createRequirement(`${t.id}-story-${r++}`,`用户故事 ${r}`,n,f.USER_STORY,t,e))}}),s}extractTechnicalRequirements(t,e){const s=[],r=["技术栈","架构","数据库","框架","接口","API","服务","组件"],n=e.split("\n").filter(t=>t.trim());let i=1;return n.forEach(n=>{const a=n.trim();r.some(t=>a.includes(t))&&a.length>10&&s.push(this.createRequirement(`${t.id}-tech-${i++}`,this.extractTitle(a),a,f.TECHNICAL,t,e))}),s}extractGeneralRequirements(t,e){const s=[],r=e.split("\n").filter(t=>t.trim());let n=1;return r.forEach(r=>{const i=r.trim();this.isRequirementLike(i)&&s.push(this.createRequirement(`${t.id}-req-${n++}`,this.extractTitle(i),i,f.BUSINESS,t,e))}),s}createRequirement(t,e,s,r,n,i){return{id:t,title:e,description:s,type:r,priority:this.analyzePriority(s),category:n.title,source:n.id,dependencies:[],acceptanceCriteria:this.extractAcceptanceCriteria(s),estimatedEffort:this.estimateEffort(s,r),complexity:this.analyzeComplexity(s),tags:this.extractTags(s),stakeholders:this.extractStakeholders(s),businessValue:this.calculateBusinessValue(s,r),technicalRisk:this.calculateTechnicalRisk(s,r),metadata:{extractedAt:new Date,confidence:this.calculateConfidence(s,r),extractionMethod:"pattern_matching",keywords:n.keywords,relatedSections:[n.id]}}}analyzePriority(t){const e=t.toLowerCase();for(const[t,s]of Object.entries(this.priorityKeywords))if(s.some(t=>e.includes(t)))return t;return exports.TaskPriority.MEDIUM}analyzeComplexity(t){const e=t.toLowerCase();for(const[t,s]of Object.entries(this.complexityKeywords))if(s.some(t=>e.includes(t)))return t;return t.length>200?"high":t.length>100?"medium":"low"}estimateEffort(t,e){let s=8;switch(e){case f.TECHNICAL:s=16;break;case f.NON_FUNCTIONAL:s=12;break;case f.USER_STORY:s=6}switch(this.analyzeComplexity(t)){case"high":s*=2;break;case"low":s*=.5}return Math.round(s)}calculateBusinessValue(t,e){let s=5;const r=t.toLowerCase();return["收入","用户","体验","效率","成本","revenue","user","experience","efficiency"].forEach(t=>{r.includes(t)&&(s+=1)}),e===f.BUSINESS&&(s+=2),e===f.USER_STORY&&(s+=1),Math.min(10,s)}calculateTechnicalRisk(t,e){let s=3;const r=t.toLowerCase();return["集成","新技术","算法","性能","安全","integration","new","algorithm","performance","security"].forEach(t=>{r.includes(t)&&(s+=1)}),e===f.TECHNICAL&&(s+=2),e===f.NON_FUNCTIONAL&&(s+=1),Math.min(10,s)}calculateConfidence(t,e){let s=.5;return this.requirementPatterns.functional.some(e=>e.test(t))&&(s+=.3),t.length>20&&t.length<500&&(s+=.2),Math.min(1,s)}extractAcceptanceCriteria(t){const e=[];return[/验收标准[::]\s*(.+)/gi,/acceptance criteria[::]\s*(.+)/gi,/given (.+?) when (.+?) then (.+)/gi].forEach(s=>{let r;for(;null!==(r=s.exec(t));)e.push(r[1]||r[0])}),e}extractTags(t){const e=[],s=t.toLowerCase();return Object.entries({UI:["界面","页面","按钮","UI","interface","page","button"],API:["接口","API","service","服务"],Database:["数据库","存储","database","storage"],Security:["安全","权限","security","permission","auth"],Performance:["性能","速度","performance","speed"]}).forEach(([t,r])=>{r.some(t=>s.includes(t))&&e.push(t)}),e}extractStakeholders(t){const e=[];return[/用户/g,/管理员/g,/开发者/g,/测试人员/g,/user/gi,/admin/gi,/developer/gi,/tester/gi].forEach(s=>{const r=t.match(s);r&&e.push(...r)}),[...new Set(e)]}detectDependencies(t){t.forEach(e=>{t.forEach(t=>{e.id!==t.id&&this.hasDependencyRelation(e.description,t.description)&&e.dependencies.push(t.id)})})}hasDependencyRelation(t,e){return["基于","依赖","需要","使用","based on","depends on","requires","uses"].some(s=>t.toLowerCase().includes(s)&&e.toLowerCase().includes(s))}generateSummary(t){const e=t.filter(t=>t.type===f.FUNCTIONAL).length,s=t.filter(t=>t.type===f.NON_FUNCTIONAL).length,r=t.filter(t=>t.type===f.USER_STORY).length,n=t.filter(t=>t.priority===exports.TaskPriority.HIGH||t.priority===exports.TaskPriority.CRITICAL).length,i=t.reduce((t,e)=>t+e.estimatedEffort,0),a=t.map(t=>{switch(t.complexity){case"high":return 3;case"medium":default:return 2;case"low":return 1}}),o=a.reduce((t,e)=>t+e,0)/a.length,c=o>2.5?"high":o>1.5?"medium":"low",u=t.reduce((t,e)=>t+e.metadata.confidence,0)/t.length,h=Math.min(1,u*(t.length/10));return{totalRequirements:t.length,functionalRequirements:e,nonFunctionalRequirements:s,userStories:r,highPriorityRequirements:n,estimatedTotalEffort:i,averageComplexity:c,coverageScore:h}}generateSuggestions(t,e){const s=[];return e.totalRequirements<5&&s.push("需求数量较少,建议检查是否遗漏了重要需求"),0===e.nonFunctionalRequirements&&s.push("未发现非功能需求,建议补充性能、安全、可用性等方面的需求"),e.highPriorityRequirements/e.totalRequirements>.8&&s.push("高优先级需求比例过高,建议重新评估需求优先级"),e.coverageScore<.6&&s.push("需求覆盖度较低,建议补充更详细的需求描述"),e.estimatedTotalEffort/e.totalRequirements>20&&s.push("平均工作量较高,建议将复杂需求拆分为更小的任务"),s}validateRequirements(t){const e=[];return t.forEach(t=>{t.description.length<10&&e.push(`需求 ${t.id} 描述过于简短`),t.metadata.confidence<.3&&e.push(`需求 ${t.id} 提取置信度较低`),0===t.acceptanceCriteria.length&&e.push(`需求 ${t.id} 缺少验收标准`)}),e}isFunctionDescription(t){return[/^[-*+]\s+/,/^\d+\.\s+/,/^[a-zA-Z0-9]+[.)]\s+/,/功能|特性|能力/].some(e=>e.test(t))&&t.length>10}isRequirementLike(t){return["需要","应该","必须","能够","支持","实现","提供","need","should","must","shall","support","implement","provide"].some(e=>t.toLowerCase().includes(e))&&t.length>15}extractTitle(t){const e=t.substring(0,50).trim();return e.endsWith("...")?e:e+(t.length>50?"...":"")}}class _{constructor(t,e){this.modelCoordinator=t,this.logger=e,this.documentProcessor=new S(e),this.requirementExtractor=new A(e)}async parseFromFile(t,e){var s,r;try{if(this.logger.info(`开始解析PRD文件:${t}`),!await k.pathExists(t))throw new Error(`文件不存在:${t}`);const n={extractTables:!0,extractImages:!1,detectLanguage:!0,analyzeStructure:!0,extractKeywords:!0,calculateImportance:!0},i=await this.documentProcessor.processDocument(t,n),a={includeUserStories:null===(s=null==e?void 0:e.extractFeatures)||void 0===s||s,detectDependencies:!0,estimateEffort:!0,analyzePriority:null===(r=null==e?void 0:e.prioritize)||void 0===r||r,extractAcceptanceCriteria:!0,detectStakeholders:!0},o=await this.requirementExtractor.extractRequirements(i,a);return this.convertToParseResult(i,o)}catch(t){throw this.logger.error(`解析PRD文件失败:${t.message}`),t}}async parseContent(t,e=exports.FileType.MARKDOWN,s){try{const r=this.preprocessContent(t,e),n=await this.modelCoordinator.parsePRD(r,s);try{const t=JSON.parse(n.content);return this.validateParseResult(t),this.logger.info("PRD解析成功"),t}catch(t){throw this.logger.error(`解析模型返回结果失败:${t.message}`),new Error(`无法解析模型返回的JSON结果:${t.message}`)}}catch(t){throw this.logger.error(`解析PRD内容失败:${t.message}`),t}}preprocessContent(t,e){switch(e){case exports.FileType.MARKDOWN:return t;case exports.FileType.JSON:try{const e=JSON.parse(t);return JSON.stringify(e,null,2)}catch{return t}default:return t}}detectFileType(t){switch(b.extname(t).toLowerCase()){case".md":case".markdown":return exports.FileType.MARKDOWN;case".pdf":return exports.FileType.PDF;case".docx":case".doc":return exports.FileType.WORD;case".txt":return exports.FileType.TEXT;case".json":return exports.FileType.JSON;default:return exports.FileType.UNKNOWN}}validateParseResult(t){if(t.title||this.logger.warn("解析结果缺少标题"),t.description||this.logger.warn("解析结果缺少描述"),!Array.isArray(t.sections)||0===t.sections.length)throw new Error("解析结果必须包含至少一个章节");t.sections.forEach((t,e)=>{t.title||this.logger.warn(`第${e+1}个章节缺少标题`),Array.isArray(t.features)||(this.logger.warn(`第${e+1}个章节的features字段不是数组`),t.features=[])})}convertToParseResult(t,e){const s=e.requirements.map(t=>({id:t.id,name:t.title,description:t.description,priority:t.priority,type:t.type,dependencies:t.dependencies,estimatedHours:t.estimatedEffort,tags:t.tags,acceptanceCriteria:t.acceptanceCriteria,complexity:t.complexity,businessValue:t.businessValue,technicalRisk:t.technicalRisk,stakeholders:t.stakeholders,category:t.category,status:exports.TaskStatus.NOT_STARTED,createdAt:t.metadata.extractedAt,updatedAt:t.metadata.extractedAt}));return{id:`prd-${Date.now()}`,title:t.title,description:this.extractDescription(t),sections:[],metadata:{version:"1.0.0",features:s,fileName:t.metadata.fileName,fileSize:t.metadata.fileSize,parsedAt:new Date,language:t.metadata.language,wordCount:t.metadata.wordCount,estimatedReadTime:t.metadata.estimatedReadTime,extractionSummary:e.summary,warnings:e.warnings,suggestions:e.suggestions,documentStructure:{sectionsCount:t.sections.length,maxDepth:this.calculateMaxDepth(this.convertToPRDSections(t.sections)),hasTableOfContents:this.hasTableOfContents(t),primaryLanguage:t.metadata.language},createdAt:new Date,updatedAt:new Date}}}extractDescription(t){const e=t.sections.find(t=>"overview"===t.type||t.title.toLowerCase().includes("概述")||t.title.toLowerCase().includes("简介")||t.title.toLowerCase().includes("overview"));return e?e.content.substring(0,500).trim():t.sections.length>0?t.sections[0].content.substring(0,500).trim():"从PRD文档自动提取的产品需求"}convertToPRDSections(t){return t.map(t=>({title:t.title,content:t.content,level:t.level,features:[],subsections:t.subsections?this.convertToPRDSections(t.subsections):void 0}))}calculateMaxDepth(t){let e=0;const s=(t,r=1)=>{e=Math.max(e,r),t.forEach(t=>{t.subsections&&t.subsections.length>0&&s(t.subsections,r+1)})};return s(t),e}hasTableOfContents(t){return t.sections.some(t=>t.title.toLowerCase().includes("目录")||t.title.toLowerCase().includes("contents")||t.title.toLowerCase().includes("toc"))}}class R{constructor(t,e){this.modelCoordinator=t,this.logger=e}async generateTaskPlan(t,e){try{this.logger.info("开始生成任务计划");const s=await this.modelCoordinator.planTasks(t,e);try{const t=JSON.parse(s.content);return this.validateTaskPlan(t),this.postProcessTaskPlan(t),this.logger.info(`任务计划生成成功,共 ${t.tasks.length} 个任务`),t}catch(t){throw this.logger.error(`解析模型返回的任务计划失败:${t.message}`),new Error(`无法解析模型返回的JSON结果:${t.message}`)}}catch(t){throw this.logger.error(`生成任务计划失败:${t.message}`),t}}async optimizeTaskPlan(t,e){try{return this.logger.info("开始优化任务计划"),this.optimizeDependencies(t),this.optimizePriorities(t,e),this.identifyParallelTasks(t,e),this.balanceWorkload(t,e),this.logger.info("任务计划优化完成"),t}catch(t){throw this.logger.error(`优化任务计划失败:${t.message}`),t}}async saveTaskPlan(t,e){try{await k.ensureDir(b.dirname(e)),await k.writeFile(e,JSON.stringify(t,null,2),"utf-8"),this.logger.info(`任务计划已保存至 ${e}`)}catch(t){throw this.logger.error(`保存任务计划失败:${t.message}`),t}}validateTaskPlan(t){if(t.name||this.logger.warn("任务计划缺少名称"),t.description||this.logger.warn("任务计划缺少描述"),!Array.isArray(t.tasks))throw new Error("任务计划必须包含tasks数组");t.tasks.forEach((t,e)=>{if(!t.id)throw new Error(`第${e+1}个任务缺少ID`);t.title||this.logger.warn(`任务 ${t.id} 缺少标题`),t.priority||(this.logger.warn(`任务 ${t.id} 缺少优先级,设置为默认值'medium'`),t.priority=exports.TaskPriority.MEDIUM),t.type||(this.logger.warn(`任务 ${t.id} 缺少类型,设置为默认值'feature'`),t.type=exports.TaskType.FEATURE),Array.isArray(t.dependencies)||(this.logger.warn(`任务 ${t.id} 的dependencies字段不是数组,设置为空数组`),t.dependencies=[]),t.status||(t.status=exports.TaskStatus.NOT_STARTED)})}postProcessTaskPlan(t){const e=new Set;t.tasks.forEach(t=>{if(e.has(t.id)){const s=this.generateUniqueId(t.id,e);this.logger.warn(`发现重复的任务ID: ${t.id},自动更新为: ${s}`),t.id=s}e.add(t.id),t.dependencies=t.dependencies.filter(s=>e.has(s)||s===t.id?s!==t.id||(this.logger.warn(`任务 ${t.id} 不能依赖自身,已移除此依赖`),!1):(this.logger.warn(`任务 ${t.id} 依赖的任务 ${s} 不存在,已移除此依赖`),!1))}),this.checkCircularDependencies(t)}generateUniqueId(t,e){let s=1,r=`${t}_${s}`;for(;e.has(r);)s++,r=`${t}_${s}`;return r}checkCircularDependencies(t){const e=new Map;t.tasks.forEach(t=>{e.set(t.id,[...t.dependencies])});const s=new Set,r=new Set;t.tasks.forEach(t=>{this.detectCycle(t.id,e,s,r)})}detectCycle(t,e,s,r){if(r.has(t))return this.logger.warn(`检测到循环依赖,包含任务: ${t}`),!0;if(s.has(t))return!1;s.add(t),r.add(t);const n=e.get(t)||[];for(const i of n)if(this.detectCycle(i,e,s,r)){const s=e.get(t)||[];e.set(t,s.filter(t=>t!==i)),this.logger.warn(`移除循环依赖: ${t} -> ${i}`)}return r.delete(t),!1}optimizeDependencies(t){this.logger.info("优化任务依赖关系"),t.tasks.forEach(e=>{const s=this.removeRedundantDependencies(e.dependencies,t);e.dependencies=s}),this.checkCircularDependencies(t)}removeRedundantDependencies(t,e){if(t.length<=1)return t;const s=new Map;e.tasks.forEach(t=>s.set(t.id,t));const r=[];for(const e of t){if(!s.get(e))continue;let n=!1;for(const r of t)if(r!==e&&this.hasTransitiveDependency(r,e,s)){n=!0;break}n||r.push(e)}return r}hasTransitiveDependency(t,e,s){const r=new Set,n=[t];for(;n.length>0;){const t=n.shift();if(r.has(t))continue;r.add(t);const i=s.get(t);if(i)for(const t of i.dependencies){if(t===e)return!0;r.has(t)||n.push(t)}}return!1}optimizePriorities(t,e){this.logger.info("优化任务优先级"),t.tasks.forEach(e=>{const s=this.findDependentTasks(e.id,t);s.length>=3?e.priority=exports.TaskPriority.HIGH:s.length>=2&&(e.priority=exports.TaskPriority.MEDIUM),this.isOnCriticalPath(e.id,t)&&(e.priority=exports.TaskPriority.CRITICAL)})}findDependentTasks(t,e){return e.tasks.filter(e=>e.dependencies.includes(t))}isOnCriticalPath(t,e){return!!e.tasks.find(e=>e.id===t)&&this.calculateDependencyDepth(t,e)>1.5*this.calculateAverageDependencyDepth(e)}calculateDependencyDepth(t,e){const s=new Set,r=t=>{if(s.has(t))return 0;s.add(t);const n=e.tasks.find(e=>e.id===t);if(!n||0===n.dependencies.length)return 1;let i=0;for(const t of n.dependencies)i=Math.max(i,r(t));return i+1};return r(t)}calculateAverageDependencyDepth(t){const e=t.tasks.map(e=>this.calculateDependencyDepth(e.id,t));return e.reduce((t,e)=>t+e,0)/e.length}identifyParallelTasks(t,e){this.logger.info("识别并行任务"),this.findParallelGroups(t,3).forEach((t,e)=>{t.forEach(t=>{t.tags||(t.tags=[]),t.tags.push(`parallel-group-${e+1}`)})})}findParallelGroups(t,e){const s=[],r=new Set;return t.tasks.forEach(n=>{if(r.has(n.id))return;const i=this.findParallelTasks(n,t,r);i.length>1&&i.length<=e&&(s.push(i),i.forEach(t=>r.add(t.id)))}),s}findParallelTasks(t,e,s){const r=[t];return e.tasks.forEach(n=>{n.id===t.id||s.has(n.id)||this.canRunInParallel(t,n,e)&&r.push(n)}),r}canRunInParallel(t,e,s){return!(t.dependencies.includes(e.id)||e.dependencies.includes(t.id)||this.hasIndirectDependency(t.id,e.id,s)||this.hasIndirectDependency(e.id,t.id,s)||t.type===e.type&&(t.type===exports.TaskType.DEPLOYMENT||t.type===exports.TaskType.TEST))}hasIndirectDependency(t,e,s){const r=new Map;return s.tasks.forEach(t=>r.set(t.id,t)),this.hasTransitiveDependency(t,e,r)}balanceWorkload(t,e){this.logger.info("平衡工作量");const s=(null==e?void 0:e.considerTeamSize)||3,r=t.tasks.reduce((t,e)=>t+(e.estimatedHours||8),0)/s;t.tasks.forEach(t=>{const e=t.estimatedHours||8;e>.5*r&&(t.tags||(t.tags=[]),t.tags.push("consider-splitting"),t.notes||(t.notes=""),t.notes+=`\n建议拆分:预计工作量 ${e} 小时,超过平均值的50%`)})}}class j{constructor(t,e){this.taskPlan=null,this.autoSaveInterval=null,this.logger=t,this.configManager=e;const s=this.configManager.get("taskSettings",{outputDir:"./tasks",autoSave:!0,saveInterval:300});this.taskFilePath=b.join(s.outputDir,"tasks.json"),s.autoSave&&this.startAutoSave(1e3*s.saveInterval)}async loadTaskPlan(t){const e=t||this.taskFilePath;try{if(!k.existsSync(e))throw new Error(`任务计划文件不存在:${e}`);const t=await k.readFile(e,"utf-8");return this.taskPlan=JSON.parse(t),this.logger.info(`成功加载任务计划,共 ${this.taskPlan.tasks.length} 个任务`),this.taskPlan}catch(t){throw this.logger.error(`加载任务计划失败:${t.message}`),t}}async saveTaskPlan(t){const e=t||this.taskFilePath;if(!this.taskPlan)throw new Error("没有任务计划可保存,请先加载或创建任务计划");try{await k.ensureDir(b.dirname(e)),await k.writeFile(e,JSON.stringify(this.taskPlan,null,2),"utf-8"),this.logger.info(`任务计划已保存至 ${e}`)}catch(t){throw this.logger.error(`保存任务计划失败:${t.message}`),t}}setTaskPlan(t){this.taskPlan=t,this.logger.info(`设置任务计划成功,共 ${t.tasks.length} 个任务`)}getTaskPlan(){return this.taskPlan}getAllTasks(){if(!this.taskPlan)throw new Error("没有加载任务计划");return[...this.taskPlan.tasks]}getTaskById(t){if(!this.taskPlan)throw new Error("没有加载任务计划");if(t.includes(".")){const[e,s]=t.split("."),r=this.taskPlan.tasks.find(t=>t.id===e);if(!r||!r.subtasks)return null;const n=`${e}.${s}`,i=r.subtasks.find(t=>t.id===n);return i?{id:i.id,name:i.name,title:i.name,description:i.description,status:i.status,priority:exports.TaskPriority.MEDIUM,type:exports.TaskType.FEATURE,dependencies:[],createdAt:new Date,updatedAt:new Date,tags:[],subtasks:[]}:null}return this.taskPlan.tasks.find(e=>e.id===t)||null}filterTasks(t){if(!this.taskPlan)throw new Error("没有加载任务计划");return this.taskPlan.tasks.filter(e=>{if(t.status)if(Array.isArray(t.status)){if(!t.status.includes(e.status))return!1}else if(e.status!==t.status)return!1;if(t.type)if(Array.isArray(t.type)){if(!t.type.includes(e.type))return!1}else if(e.type!==t.type)return!1;if(t.assignee&&e.assignee!==t.assignee)return!1;if(t.priority)if(Array.isArray(t.priority)){if(!t.priority.includes(e.priority))return!1}else if(e.priority!==t.priority)return!1;return!0})}addTask(t){if(!this.taskPlan)throw new Error("没有加载任务计划");if(this.taskPlan.tasks.find(e=>e.id===t.id))throw new Error(`任务ID ${t.id} 已存在`);return this.taskPlan.tasks.push(t),this.logger.info(`添加新任务 ${t.id}: ${t.name}`),t}updateTask(t,e){if(!this.taskPlan)throw new Error("没有加载任务计划");if(t.includes(".")){const[s]=t.split("."),r=this.taskPlan.tasks.findIndex(t=>t.id===s);if(r<0||!this.taskPlan.tasks[r].subtasks)return null;const n=t,i=this.taskPlan.tasks[r].subtasks.findIndex(t=>t.id===n);if(i<0)return null;const a=this.taskPlan.tasks[r].subtasks[i];return e.name&&(a.name=e.name),e.description&&(a.description=e.description),e.status&&(a.status=e.status),this.logger.info(`更新子任务 ${t}: ${a.name}`),{id:a.id,name:a.name,title:a.name,description:a.description,status:a.status,priority:exports.TaskPriority.MEDIUM,type:exports.TaskType.FEATURE,dependencies:[],subtasks:[],createdAt:new Date,updatedAt:new Date,tags:[]}}const s=this.taskPlan.tasks.findIndex(e=>e.id===t);if(s<0)return null;const r=this.taskPlan.tasks[s];return e.name&&(r.name=e.name),e.description&&(r.description=e.description),e.status&&(r.status=e.status),e.priority&&(r.priority=e.priority),e.assignee&&(r.assignee=e.assignee),this.logger.info(`更新任务 ${t}: ${r.name}`),r}removeTask(t){if(!this.taskPlan)throw new Error("没有加载任务计划");if(t.includes(".")){const[e]=t.split("."),s=this.taskPlan.tasks.findIndex(t=>t.id===e);if(s<0||!this.taskPlan.tasks[s].subtasks)return!1;const r=t,n=this.taskPlan.tasks[s].subtasks.findIndex(t=>t.id===r);return!(n<0||(this.taskPlan.tasks[s].subtasks.splice(n,1),this.logger.info(`删除子任务 ${t}`),0))}const e=this.taskPlan.tasks.findIndex(e=>e.id===t);return!(e<0||(this.taskPlan.tasks.splice(e,1),this.taskPlan.tasks.forEach(e=>{e.dependencies=e.dependencies.filter(e=>e!==t)}),this.logger.info(`删除任务 ${t}`),0))}addSubtask(t,e){if(!this.taskPlan)throw new Error("没有加载任务计划");const s=this.taskPlan.tasks.find(e=>e.id===t);if(!s)throw new Error(`父任务 ${t} 不存在`);return Array.isArray(s.subtasks)||(s.subtasks=[]),e.id||(e.id=`${t}.${s.subtasks.length+1}`),e.status||(e.status=exports.TaskStatus.TODO),s.subtasks.push(e),this.logger.info(`为任务 ${t} 添加子任务 ${e.id}: ${e.name}`),e}getNextTasks(){if(!this.taskPlan)throw new Error("没有加载任务计划");return this.taskPlan.tasks.filter(t=>t.status!==exports.TaskStatus.DONE&&t.status!==exports.TaskStatus.REVIEW).filter(t=>!t.dependencies||0===t.dependencies.length||t.dependencies.every(t=>{const e=this.getTaskById(t);return e&&e.status===exports.TaskStatus.DONE}))}addDependency(t,e){if(!this.taskPlan)throw new Error("没有加载任务计划");const s=this.getTaskById(t);if(!s)throw new Error(`任务 ${t} 不存在`);if(!this.getTaskById(e))throw new Error(`依赖的任务 ${e} 不存在`);if(t===e)throw new Error("任务不能依赖自身");if(this.checkCircularDependency(e,t))throw new Error("添加此依赖会导致循环依赖");return Array.isArray(s.dependencies)||(s.dependencies=[]),!s.dependencies.includes(e)&&(s.dependencies.push(e),this.logger.info(`为任务 ${t} 添加依赖: ${e}`),!0)}removeDependency(t,e){if(!this.taskPlan)throw new Error("没有加载任务计划");const s=this.getTaskById(t);if(!s||!Array.isArray(s.dependencies))return!1;const r=s.dependencies.indexOf(e);return!(r<0||(s.dependencies.splice(r,1),this.logger.info(`从任务 ${t} 移除依赖: ${e}`),0))}checkCircularDependency(t,e){if(!this.taskPlan)return!1;const s=new Map;this.taskPlan.tasks.forEach(t=>{s.set(t.id,[...t.dependencies||[]])});const r=s.get(t)||[];r.push(e),s.set(t,r);const n=new Set,i=new Set,a=t=>{if(i.has(t))return!0;if(n.has(t))return!1;n.add(t),i.add(t);const e=s.get(t)||[];for(const t of e)if(a(t))return!0;return i.delete(t),!1};return a(t)}startAutoSave(t){this.autoSaveInterval&&clearInterval(this.autoSaveInterval),this.autoSaveInterval=setInterval(async()=>{if(this.taskPlan)try{await this.saveTaskPlan()}catch(t){this.logger.error(`自动保存任务计划失败:${t.message}`)}},t),this.logger.info(`启动自动保存,间隔: ${t/1e3} 秒`)}stopAutoSave(){this.autoSaveInterval&&(clearInterval(this.autoSaveInterval),this.autoSaveInterval=null,this.logger.info("停止自动保存"))}destroy(){this.stopAutoSave()}}exports.VisualizationType=void 0,(w=exports.VisualizationType||(exports.VisualizationType={})).GANTT="gantt",w.DEPENDENCY="dependency",w.KANBAN="kanban",w.TIMELINE="timeline",w.PROGRESS="progress",exports.ModelType=void 0,(g=exports.ModelType||(exports.ModelType={})).BAIDU="baidu",g.XUNFEI="xunfei",g.ZHIPU="zhipu",g.DEEPSEEK="deepseek",g.QWEN="qwen",g.SPARK="spark",g.MOONSHOT="moonshot",exports.LogLevel=void 0,(v=exports.LogLevel||(exports.LogLevel={})).ERROR="error",v.WARN="warn",v.INFO="info",v.DEBUG="debug",function(t){t.TYPESCRIPT="typescript",t.JAVASCRIPT="javascript",t.PYTHON="python",t.JAVA="java",t.GO="go",t.RUST="rust",t.CPP="cpp",t.CSHARP="csharp"}($||($={})),function(t){t.WEB_APP="web-app",t.API="api",t.MOBILE_APP="mobile-app",t.DESKTOP_APP="desktop-app",t.LIBRARY="library",t.CLI_TOOL="cli-tool"}(x||(x={}));class E{constructor(){this.configPath=b.join(D.homedir(),".taskflow-ai","config.json"),this.config=this.loadConfig()}loadConfig(){try{if(T.existsSync(this.configPath)){const t=T.readFileSync(this.configPath,"utf8");return JSON.parse(t)}}catch(t){}return{models:{default:exports.ModelType.DEEPSEEK,apiKeys:{},endpoints:{}},ui:{theme:"light",language:"zh-CN"},features:{autoSave:!0,notifications:!0}}}saveConfig(){try{const t=b.dirname(this.configPath);T.existsSync(t)||T.mkdirSync(t,{recursive:!0}),T.writeFileSync(this.configPath,JSON.stringify(this.config,null,2))}catch(t){}}get(t,e){const s=t.split(".");let r=this.config;for(const t of s){if(!r||"object"!=typeof r||null===r||!(t in r))return e;r=r[t]}return r}set(t,e){const s=t.split(".");let r=this.config;for(let t=0;t<s.length-1;t++){const e=s[t];r[e]&&"object"==typeof r[e]||(r[e]={}),r=r[e]}r[s[s.length-1]]=e,this.saveConfig()}getAll(){return{...this.config}}update(t){this.config={...this.config,...t},this.saveConfig()}reset(){this.config=this.loadConfig()}getConfig(){return this.getAll()}updateConfig(t,e=!1){this.update(t)}getDefaultModelType(){return this.get("models.default",exports.ModelType.DEEPSEEK)}}class I{constructor(s){const r=e.join(process.env.HOME||process.env.USERPROFILE||".",".config","mcp","logs");t.ensureDirSync(r);const n=s.file||e.join(r,"mcp.log"),a=i.format.combine(i.format.colorize(),i.format.timestamp(),i.format.printf(({timestamp:t,level:e,message:s})=>`${t} ${e}: ${s}`)),o=i.format.combine(i.format.timestamp(),i.format.json()),c=[];"console"!==s.output&&"both"!==s.output||c.push(new i.transports.Console({format:a,level:s.level})),"file"!==s.output&&"both"!==s.output||c.push(new i.transports.File({filename:n,format:o,level:s.level,maxsize:5242880,maxFiles:5})),this.logger=i.createLogger({level:s.level,levels:i.config.npm.levels,defaultMeta:{service:"mcp"},transports:c})}static getInstance(t){return I.instance||(I.instance=new I(t)),I.instance}updateConfig(t){I.instance=new I(t)}error(t,e){this.logger.error(t,e)}warn(t,e){this.logger.warn(t,e)}info(t,e){this.logger.info(t,e)}debug(t,e){this.logger.debug(t,e)}log(t,e,s){this.logger.log(t,e,s)}}class q{constructor(t){this.modelType=t}getModelType(){return this.modelType}handleRequestError(t){if(t&&"object"==typeof t&&"response"in t){const e=t.response,s=null==e?void 0:e.status,r=null==e?void 0:e.data;let n=`HTTP Error ${s}`;throw r&&"object"==typeof r&&(n+=`: ${JSON.stringify(r)}`),401===s||403===s?new Error(`认证失败:${n},请检查API密钥是否正确`):429===s?new Error(`请求速率限制:${n},请稍后重试`):new Error(`API调用失败:${n}`)}if(t&&"object"==typeof t&&"request"in t){const e=t.message||"网络错误";throw new Error(`请求超时或网络错误:${e}`)}{const e=(null==t?void 0:t.message)||"未知错误";throw new Error(`请求配置错误:${e}`)}}}class C extends q{constructor(t){super(exports.ModelType.BAIDU),this.accessToken=null,this.tokenExpireTime=0;const e=t.get(`models.${exports.ModelType.BAIDU}`,{apiKey:"",secretKey:"",endpoint:"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/",modelVersion:"ernie-bot-4"});if(this.apiKey=e.apiKey,this.secretKey=e.secretKey,this.endpoint=e.endpoint||"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/",this.modelVersion=e.modelVersion||"ernie-bot-4",!this.apiKey||!this.secretKey)throw new Error("百度文心API密钥未配置,请使用 mcp config 命令设置 model.baidu.apiKey 和 model.baidu.secretKey")}async chat(t,e){try{await this.ensureAccessToken();const s=this.buildRequestBody(t,e),r=`${this.endpoint}${this.modelVersion}?access_token=${this.accessToken}`,n=await a.post(r,s,{headers:{"Content-Type":"application/json"},timeout:(null==e?void 0:e.timeout)||3e4});return this.processResponse(n.data)}catch(t){return this.handleRequestError(t)}}async chatStream(t,e,s){try{await this.ensureAccessToken();const r=this.buildRequestBody(t,{...s,stream:!0}),n=`${this.endpoint}${this.modelVersion}?access_token=${this.accessToken}`,i=(await a.post(n,r,{headers:{"Content-Type":"application/json"},responseType:"stream",timeout:(null==s?void 0:s.timeout)||6e4})).data;return new Promise((t,s)=>{let r="";i.on("data",t=>{const s=t.toString();r+=s;const n=r.split("\n");r=n.pop()||"";for(const t of n)if(t.startsWith("data: ")){const s=t.substring(6);try{const t=JSON.parse(s);e(t.result,t.is_end||!1)}catch{}}}),i.on("end",()=>{e("",!0),t()}),i.on("error",t=>{s(t)})})}catch(t){return this.handleRequestError(t)}}async validateApiKey(){try{return await this.ensureAccessToken(),!!this.accessToken}catch{return!1}}buildRequestBody(t,e){var s,r,n,i;return{messages:t.messages.map(t=>({role:this.mapRole(t.role),content:t.content})),temperature:null!==(r=null!==(s=null==e?void 0:e.temperature)&&void 0!==s?s:t.temperature)&&void 0!==r?r:.7,top_p:null!==(n=t.topP)&&void 0!==n?n:.8,stream:null!==(i=null==e?void 0:e.stream)&&void 0!==i&&i,user_id:"mcp-user"}}processResponse(t){return{content:t.result,finishReason:t.is_end?"stop":void 0,usage:t.usage?{promptTokens:t.usage.prompt_tokens,completionTokens:t.usage.completion_tokens,totalTokens:t.usage.total_tokens}:void 0}}mapRole(t){switch(t){case exports.MessageRole.USER:return"user";case exports.MessageRole.ASSISTANT:return"assistant";case exports.MessageRole.SYSTEM:return"system";default:return"user"}}async ensureAccessToken(){const t=Date.now();if(!(this.accessToken&&t<this.tokenExpireTime))try{const e=`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${this.apiKey}&client_secret=${this.secretKey}`,s=await a.post(e);if(!s.data||!s.data.access_token)throw new Error("获取访问令牌失败:响应中没有access_token字段");this.accessToken=s.data.access_token,this.tokenExpireTime=t+1e3*(s.data.expires_in||2592e3)-864e5}catch(t){throw this.accessToken=null,this.tokenExpireTime=0,new Error(`获取百度文心访问令牌失败:${t.message}`)}}}class O extends q{constructor(t){super(exports.ModelType.DEEPSEEK);const e=t.get(`models.${exports.ModelType.DEEPSEEK}`,{apiKey:"",endpoint:"https://api.deepseek.com/v1/chat/completions",modelVersion:"deepseek-chat"});if(this.apiKey=e.apiKey,this.endpoint=e.endpoint||"https://api.deepseek.com/v1/chat/completions",this.modelVersion=e.modelVersion||"deepseek-chat",!this.apiKey)throw new Error("DeepSeek API密钥未配置,请使用 mcp config 命令设置 model.deepseek.apiKey")}async chat(t,e){try{const s=this.buildRequestBody(t,e),r=await a.post(this.endpoint,s,{headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},timeout:(null==e?void 0:e.timeout)||3e4});return this.processResponse(r.data)}catch(t){return this.handleRequestError(t)}}async chatStream(t,e,s){try{const r=this.buildRequestBody(t,{...s,stream:!0}),n=(await a.post(this.endpoint,r,{headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},responseType:"stream",timeout:(null==s?void 0:s.timeout)||6e4})).data;return new Promise((t,s)=>{let r="";n.on("data",t=>{var s;const n=t.toString();r+=n;const i=r.split("\n");r=i.pop()||"";for(const t of i)if(t.startsWith("data: ")){const r=t.substring(6);if("[DONE]"===r){e("",!0);continue}try{const t=JSON.parse(r);if(t.choices&&t.choices.length>0){const r=(null===(s=t.choices[0].message)||void 0===s?void 0:s.content)||"",n="stop"===t.choices[0].finish_reason;e(r,n)}}catch{}}}),n.on("end",()=>{e("",!0),t()}),n.on("error",t=>{s(t)})})}catch(t){return this.handleRequestError(t)}}async validateApiKey(){try{return await this.chat({messages:[{role:exports.MessageRole.USER,content:"Hello"}],maxTokens:5},{temperature:.1}),!0}catch{return!1}}buildRequestBody(t,e){var s,r,n,i,a,o;const c=t.messages.map(t=>({role:this.mapRole(t.role),content:t.content}));return{model:this.modelVersion,messages:c,temperature:null!==(r=null!==(s=null==e?void 0:e.temperature)&&void 0!==s?s:t.temperature)&&void 0!==r?r:.7,top_p:null!==(n=t.topP)&&void 0!==n?n:.8,max_tokens:null!==(a=null!==(i=null==e?void 0:e.maxTokens)&&void 0!==i?i:t.maxTokens)&&void 0!==a?a:1024,stream:null!==(o=null==e?void 0:e.stream)&&void 0!==o&&o}}processResponse(t){var e;if(!t.choices||0===t.choices.length)throw new Error("无效的响应格式:没有返回choices字段");const s=t.choices[0];return{content:(null===(e=s.message)||void 0===e?void 0:e.content)||"",finishReason:s.finish_reason,usage:t.usage?{promptTokens:t.usage.prompt_tokens,completionTokens:t.usage.completion_tokens,totalTokens:t.usage.total_tokens}:void 0}}mapRole(t){switch(t){case exports.MessageRole.USER:return"user";case exports.MessageRole.ASSISTANT:return"assistant";case exports.MessageRole.SYSTEM:return"system";default:return"user"}}}class N extends q{constructor(t){super(exports.ModelType.ZHIPU);const e=t.get(`models.${exports.ModelType.ZHIPU}`,{apiKey:"",endpoint:"https://open.bigmodel.cn/api/paas/v4/chat/completions",modelVersion:"glm-4"});if(this.apiKey=e.apiKey,this.endpoint=e.endpoint||"https://open.bigmodel.cn/api/paas/v4/chat/completions",this.modelVersion=e.modelVersion||"glm-4",!this.apiKey)throw new Error("智谱AI API密钥未配置,请使用 yasi config 命令设置 model.zhipu.apiKey")}async chat(t,e){try{const s=this.buildRequestBody(t,e),r=this.generateAuthHeaders(),n=await a.post(this.endpoint,s,{headers:{"Content-Type":"application/json",Authorization:r.Authorization,Date:r.Date},timeout:(null==e?void 0:e.timeout)||3e4});return this.processResponse(n.data)}catch(t){return this.handleRequestError(t)}}async chatStream(t,e,s){try{const r=this.buildRequestBody(t,{...s,stream:!0}),n=this.generateAuthHeaders(),i=(await a.post(this.endpoint,r,{headers:{"Content-Type":"application/json",Authorization:n.Authorization,Date:n.Date,Accept:"text/event-stream"},responseType:"stream",timeout:(null==s?void 0:s.timeout)||6e4})).data;return new Promise((t,s)=>{let r="";i.on("data",t=>{var s;const n=t.toString();r+=n;const i=r.split("\n");r=i.pop()||"";for(const t of i)if(t.startsWith("data: ")){const r=t.substring(6);if("[DONE]"===r){e("",!0);continue}try{const t=JSON.parse(r);if(t.choices&&t.choices.length>0){const r=(null===(s=t.choices[0].delta)||void 0===s?void 0:s.content)||"",n="stop"===t.choices[0].finish_reason;e(r,n)}}catch{}}}),i.on("end",()=>{e("",!0),t()}),i.on("error",t=>{s(t)})})}catch(t){return this.handleRequestError(t)}}async validateApiKey(){try{return await this.chat({messages:[{role:exports.MessageRole.USER,content:"Hello"}],maxTokens:5},{temperature:.1}),!0}catch{return!1}}buildRequestBody(t,e){var s,r,n,i,a,o;const c=t.messages.map(t=>({role:this.mapRole(t.role),content:t.content}));return{model:this.modelVersion,messages:c,temperature:null!==(r=null!==(s=null==e?void 0:e.temperature)&&void 0!==s?s:t.temperature)&&void 0!==r?r:.7,top_p:null!==(n=t.topP)&&void 0!==n?n:.8,max_tokens:null!==(a=null!==(i=null==e?void 0:e.maxTokens)&&void 0!==i?i:t.maxTokens)&&void 0!==a?a:1024,stream:null!==(o=null==e?void 0:e.stream)&&void 0!==o&&o}}processResponse(t){var e;if(!t.choices||0===t.choices.length)throw new Error("无效的响应格式:没有返回choices字段");const s=t.choices[0];return{content:(null===(e=s.message)||void 0===e?void 0:e.content)||"",finishReason:s.finish_reason,usage:t.usage?{promptTokens:t.usage.prompt_tokens,completionTokens:t.usage.completion_tokens,totalTokens:t.usage.total_tokens}:void 0}}mapRole(t){switch(t){case exports.MessageRole.USER:return"user";case exports.MessageRole.ASSISTANT:return"assistant";case exports.MessageRole.SYSTEM:return"system";default:return"user"}}generateAuthHeaders(){if(!this.apiKey.startsWith("zhipu-"))throw new Error('智谱AI API密钥格式不正确,应以"zhipu-"开头');const[t,e]=this.apiKey.substring(6).split(".");if(!t||!e)throw new Error("智谱AI API密钥格式不正确,无法提取id和secret");const s=(new Date).toUTCString(),r=`date: ${s}\nPOST /api/paas/v4/chat/completions HTTP/1.1`;return{Authorization:`hmac username="${t}", algorithm="hmac-sha256", headers="date request-line", signature="${P.createHmac("sha256",e).update(r).digest("base64")}"`,Date:s}}}class M extends q{constructor(t){super(exports.ModelType.QWEN);const e=t.get(`models.${exports.ModelType.QWEN}`);if(!e)throw new Error("Qwen模型配置未找到");this.apiKey=e.apiKey,this.endpoint=e.endpoint||"https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",this.modelVersion=e.modelVersion||"qwen-turbo",this.client=a.create({baseURL:this.endpoint,headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json","X-DashScope-SSE":"disable"},timeout:3e4})}async chat(t,e){var s,r,n;try{const e=this.buildRequestData(t),i=await this.client.post("",e);if(i.data.output&&i.data.output.text)return{content:i.data.output.text,usage:{promptTokens:(null===(s=i.data.usage)||void 0===s?void 0:s.input_tokens)||0,completionTokens:(null===(r=i.data.usage)||void 0===r?void 0:r.output_tokens)||0,totalTokens:(null===(n=i.data.usage)||void 0===n?void 0:n.total_tokens)||0},finishReason:i.data.output.finish_reason||"stop"};throw new Error("Invalid response format from Qwen API")}catch(t){this.handleRequestError(t)}}async chatStream(t,e,s){try{const s={...this.buildRequestData(t),parameters:{...this.buildRequestData(t).parameters,incremental_output:!0}},r=await this.client.post("",s,{headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json","X-DashScope-SSE":"enable",Accept:"text/event-stream"},responseType:"stream"});let n="";r.data.on("data",t=>{n+=t.toString();const s=n.split("\n");n=s.pop()||"";for(const t of s)if(t.startsWith("data: ")){const s=t.slice(6);if("[DONE]"===s)return void e("",!0);try{const t=JSON.parse(s);t.output&&t.output.text&&e(t.output.text,!1)}catch{}}}),r.data.on("end",()=>{e("",!0)})}catch(t){this.handleRequestError(t)}}async validateApiKey(){try{const t={messages:[{role:exports.MessageRole.USER,content:"Hello"}],maxTokens:10};return await this.chat(t),!0}catch{return!1}}buildRequestData(t){const e=t.messages.map(t=>({role:t.role,content:t.content}));return{model:this.modelVersion,input:{messages:e},parameters:{max_tokens:t.maxTokens||2e3,temperature:t.temperature||.7,top_p:t.topP||.9,repetition_penalty:1.1,result_format:"text"}}}}class z{constructor(t){this.modelCache=new Map,this.configManager=t}createModelAdapter(t){const e=t||this.configManager.getDefaultModelType(),s=this.modelCache.get(e);if(s)return s;let r;switch(e){case exports.ModelType.BAIDU:r=new C(this.configManager);break;case exports.ModelType.DEEPSEEK:r=new O(this.configManager);break;case exports.ModelType.ZHIPU:r=new N(this.configManager);break;case exports.ModelType.QWEN:r=new M(this.configManager);break;default:throw new Error(`不支持的模型类型: ${e}`)}return this.modelCache.set(e,r),r}clearCache(t){t?this.modelCache.delete(t):this.modelCache.clear()}getAvailableModelTypes(){return[exports.ModelType.BAIDU,exports.ModelType.DEEPSEEK,exports.ModelType.ZHIPU]}async validateModelApiKey(t){try{const e=this.createModelAdapter(t);return await e.validateApiKey()}catch{return!1}}}class F{constructor(t){this.configManager=t,this.modelFactory=new z(t)}async chat(t,e,s){const r=this.modelFactory.createModelAdapter(e);return await r.chat({messages:t},s)}async chatStream(t,e,s,r){const n=this.modelFactory.createModelAdapter(s);return await n.chatStream({messages:t},e,r)}async parsePRD(t,e){const s=(null==e?void 0:e.modelType)||this.configManager.getDefaultModelType(),r=`以下是需要解析的PRD文档内容:\n\n${t}\n\n请解析这份文档,按照要求的JSON格式返回结果。`,n=[{role:exports.MessageRole.SYSTEM,content:'你是一位专业的PRD需求分析师,请帮我解析以下PRD文档,提取其中的关键信息。\n请按照以下JSON格式输出结果:\n{\n "title": "文档标题",\n "description": "文档整体描述",\n "sections": [\n {\n "title": "章节标题",\n "content": "章节内容概述",\n "level": 章节层级,\n "features": [\n {\n "name": "功能名称",\n "description": "功能描述",\n "priority": "优先级" // high, medium, low\n }\n ]\n }\n ]\n}\n只返回JSON格式内容,不要有其他解释。'},{role:exports.MessageRole.USER,content:r}];return await this.chat(n,s)}async planTasks(t,e){const s=(null==e?void 0:e.modelType)||this.configManager.getDefaultModelType(),r=`你是一位专业的项目规划师,请根据解析后的PRD内容,生成详细的任务计划。\n请按照以下要求拆分任务:\n1. 将大的功能需求拆分为更小的可执行子任务\n2. 为每个任务分配合理的优先级和类型标签\n3. 确定任务之间的依赖关系\n4. ${(null==e?void 0:e.estimateDuration)?"估算每个任务的完成时间(以小时为单位)":""}\n5. ${(null==e?void 0:e.assignTasks)?"为每个任务分配合适的角色":""}\n\n请按照以下JSON格式输出结果:\n{\n "name": "项目名称",\n "description": "项目描述",\n "tasks": [\n {\n "id": "唯一ID",\n "name": "任务名称",\n "description": "任务描述",\n "priority": "优先级", // high, medium, low\n "type": "任务类型", // feature, bug_fix, refactor, test, document\n "dependencies": ["依赖任务ID"],\n ${(null==e?void 0:e.estimateDuration)?'"estimatedDuration": 预计耗时(小时),':""}\n ${(null==e?void 0:e.assignTasks)?'"assignee": "负责角色",':""}\n "subtasks": [\n // 子任务,结构与父任务相同\n ]\n }\n ]\n}\n只返回JSON格式内容,不要有其他解释。`,n=`以下是解析后的PRD内容:\n\n${JSON.stringify(t,null,2)}\n\n${(null==e?void 0:e.taskTemplate)?`请参考以下任务模板进行规划:\n${e.taskTemplate}`:""}\n\n请生成详细的任务计划,按照要求的JSON格式返回结果。`,i=[{role:exports.MessageRole.SYSTEM,content:r},{role:exports.MessageRole.USER,content:n}];return await this.chat(i,s)}async generateTests(t,e){const s=(null==e?void 0:e.modelType)||this.configManager.getDefaultModelType(),r=`你是一位专业的测试工程师,请根据任务描述,生成详细的测试用例。\n请使用 ${(null==e?void 0:e.framework)||this.configManager.get("testSettings.framework","jest")} 测试框架编写测试代码。\n要求:\n1. 测试需要覆盖正常功能路径\n2. ${(null==e?void 0:e.includeEdgeCases)?"测试需要覆盖边界条件和异常情况":""}\n3. ${(null==e?void 0:e.mockDependencies)?"使用mock/stub处理外部依赖":""}\n4. 测试代码应该清晰可读,包含必要的注释\n5. 遵循测试框架的最佳实践\n\n请输出完整可执行的测试代码。`,n=`以下是需要编写测试用例的任务描述:\n\n${t}\n\n请为此任务生成测试用例。`,i=[{role:exports.MessageRole.SYSTEM,content:r},{role:exports.MessageRole.USER,content:n}];return await this.chat(i,s)}getAvailableModelTypes(){return this.modelFactory.getAvailableModelType