intention-coding 0.5.9 → 0.6.1

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.
Files changed (51) hide show
  1. package/dist/index.cjs +1466 -782
  2. package/dist/services/change-summarizer/index.d.ts +2 -2
  3. package/dist/services/export-excel/index.d.ts +4 -4
  4. package/dist/services/image-analysis/analyzer.d.ts +2 -11
  5. package/dist/services/image-analysis/analyzer.d.ts.map +1 -1
  6. package/dist/services/image-analysis/index.d.ts +10 -10
  7. package/dist/services/image-analysis/index.d.ts.map +1 -1
  8. package/dist/services/image-recognition-agent/analyzer.d.ts +15 -1
  9. package/dist/services/image-recognition-agent/analyzer.d.ts.map +1 -1
  10. package/dist/services/image-recognition-agent/index.d.ts +2 -1
  11. package/dist/services/image-recognition-agent/index.d.ts.map +1 -1
  12. package/dist/services/image-recognition-agent/processor.d.ts +36 -8
  13. package/dist/services/image-recognition-agent/processor.d.ts.map +1 -1
  14. package/dist/services/image-recognition-agent/types.d.ts +3 -0
  15. package/dist/services/image-recognition-agent/types.d.ts.map +1 -1
  16. package/dist/services/index.d.ts.map +1 -1
  17. package/dist/services/read-excel/index.d.ts +2 -2
  18. package/dist/services/requirement-analyzer/core/document-generator.d.ts +4 -2
  19. package/dist/services/requirement-analyzer/core/document-generator.d.ts.map +1 -1
  20. package/dist/services/requirement-analyzer/core/requirement-analyzer-service.d.ts +1 -0
  21. package/dist/services/requirement-analyzer/core/requirement-analyzer-service.d.ts.map +1 -1
  22. package/dist/services/requirement-analyzer/core/template-selector.d.ts.map +1 -1
  23. package/dist/services/requirement-analyzer/core/types.d.ts +4 -1
  24. package/dist/services/requirement-analyzer/core/types.d.ts.map +1 -1
  25. package/dist/services/requirement-analyzer/index.d.ts +6 -1
  26. package/dist/services/requirement-analyzer/index.d.ts.map +1 -1
  27. package/dist/services/requirement-analyzer/prompt/html-page-template.d.ts +6 -0
  28. package/dist/services/requirement-analyzer/prompt/html-page-template.d.ts.map +1 -0
  29. package/dist/services/requirement-analyzer/prompt/intelligent-requirement-analysis.d.ts +1 -1
  30. package/dist/services/requirement-analyzer/prompt/intelligent-requirement-analysis.d.ts.map +1 -1
  31. package/dist/services/tech-spec-generator/doc-renderer.d.ts +13 -0
  32. package/dist/services/tech-spec-generator/doc-renderer.d.ts.map +1 -0
  33. package/dist/services/tech-spec-generator/index.d.ts +380 -0
  34. package/dist/services/tech-spec-generator/index.d.ts.map +1 -0
  35. package/dist/services/tech-spec-generator/types.d.ts +122 -0
  36. package/dist/services/tech-spec-generator/types.d.ts.map +1 -0
  37. package/dist/services/world2md/index.d.ts +1 -1
  38. package/dist/utils/dify.d.ts.map +1 -1
  39. package/dist/utils/logger.d.ts +1 -1
  40. package/dist/utils/logger.d.ts.map +1 -1
  41. package/dist/utils/openai.d.ts +18 -2
  42. package/dist/utils/openai.d.ts.map +1 -1
  43. package/dist//346/212/200/346/234/257/350/247/204/346/240/274/350/257/264/346/230/216/344/271/246/346/250/241/346/235/277.docx +0 -0
  44. package/package.json +4 -2
  45. package/bin/intention-coding.cjs +0 -4
  46. package/dist/services/requirement-analyzer/prompt/app-template.d.ts +0 -2
  47. package/dist/services/requirement-analyzer/prompt/app-template.d.ts.map +0 -1
  48. package/dist/services/requirement-analyzer/prompt/pc-page-template.d.ts +0 -2
  49. package/dist/services/requirement-analyzer/prompt/pc-page-template.d.ts.map +0 -1
  50. package/dist/services/requirement-analyzer/prompt/sdk-template.d.ts +0 -2
  51. package/dist/services/requirement-analyzer/prompt/sdk-template.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,5 +1,18 @@
1
1
  "use strict";
2
+ const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
+ return 'undefined' == typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
4
+ }();
2
5
  var __webpack_modules__ = {
6
+ "fs/promises": function(module) {
7
+ module.exports = import("fs/promises").then(function(module) {
8
+ return module;
9
+ });
10
+ },
11
+ path: function(module) {
12
+ module.exports = import("path").then(function(module) {
13
+ return module;
14
+ });
15
+ },
3
16
  "pdf-parse/lib/pdf-parse.js": function(module) {
4
17
  module.exports = import("pdf-parse/lib/pdf-parse.js").then(function(module) {
5
18
  return module;
@@ -60,18 +73,15 @@ var __webpack_exports__ = {};
60
73
  var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
61
74
  const external_winston_namespaceObject = require("winston");
62
75
  var external_winston_default = /*#__PURE__*/ __webpack_require__.n(external_winston_namespaceObject);
63
- const external_winston_daily_rotate_file_namespaceObject = require("winston-daily-rotate-file");
64
- var external_winston_daily_rotate_file_default = /*#__PURE__*/ __webpack_require__.n(external_winston_daily_rotate_file_namespaceObject);
65
- let logDir;
76
+ const external_os_namespaceObject = require("os");
77
+ var external_os_default = /*#__PURE__*/ __webpack_require__.n(external_os_namespaceObject);
78
+ const isProduction = "production" === process.env.NODE_ENV || !process.env.npm_lifecycle_event;
79
+ const logDir = external_path_default().join(external_os_default().homedir(), ".aico", "logs");
66
80
  try {
67
- if (process.env.LOG_DIR) logDir = process.env.LOG_DIR;
68
- else {
69
- const storageDir = getStorageDir();
70
- logDir = storageDir ? storageDir + '/logs' : './.aico/logs';
71
- }
72
- } catch (error) {
73
- logDir = process.env.TMPDIR || "/tmp/aico-logs";
74
- }
81
+ external_fs_default().mkdirSync(logDir, {
82
+ recursive: true
83
+ });
84
+ } catch {}
75
85
  const levels = {
76
86
  error: 0,
77
87
  warn: 1,
@@ -79,20 +89,6 @@ var __webpack_exports__ = {};
79
89
  debug: 3,
80
90
  verbose: 4
81
91
  };
82
- const colors = {
83
- error: 'red',
84
- warn: 'yellow',
85
- info: 'green',
86
- debug: 'blue',
87
- verbose: 'cyan'
88
- };
89
- external_winston_default().addColors(colors);
90
- const consoleFormat = external_winston_default().format.combine(external_winston_default().format.timestamp({
91
- format: 'YYYY-MM-DD HH:mm:ss'
92
- }), external_winston_default().format.colorize(), external_winston_default().format.printf(({ timestamp, level, message, ...meta })=>{
93
- const metaStr = Object.keys(meta).length ? JSON.stringify(meta, null, 2) : '';
94
- return `${timestamp} [${level}]: ${message} ${metaStr}`;
95
- }));
96
92
  const fileFormat = external_winston_default().format.combine(external_winston_default().format.timestamp(), external_winston_default().format.errors({
97
93
  stack: true
98
94
  }), external_winston_default().format.json());
@@ -103,11 +99,11 @@ var __webpack_exports__ = {};
103
99
  const error = meta.error || meta;
104
100
  const errorInfo = {
105
101
  timestamp,
106
- level: level || 'error',
107
- message: message || 'Uncaught Exception',
108
- stack: stack || error && error.stack || 'No stack trace available',
102
+ level: level || "error",
103
+ message: message || "Uncaught Exception",
104
+ stack: stack || error && error.stack || "No stack trace available",
109
105
  error: {
110
- name: error && error.name || 'Error',
106
+ name: error && error.name || "Error",
111
107
  message: error && error.message || String(error || message),
112
108
  code: error && error.code || meta.code,
113
109
  ...meta
@@ -115,50 +111,48 @@ var __webpack_exports__ = {};
115
111
  };
116
112
  return JSON.stringify(errorInfo, null, 2);
117
113
  }));
118
- const transports = [
119
- new (external_winston_default()).transports.Console({
120
- format: consoleFormat,
121
- level: 'verbose'
122
- })
123
- ];
124
- if (logDir) transports.push(new (external_winston_daily_rotate_file_default())({
125
- filename: external_path_default().join(logDir, 'application-%DATE%.log'),
126
- datePattern: 'YYYY-MM-DD',
127
- zippedArchive: true,
128
- maxSize: '2m',
129
- maxFiles: '1d',
114
+ const transports = [];
115
+ transports.push(new (external_winston_default()).transports.File({
116
+ filename: external_path_default().join(logDir, "error.log"),
117
+ level: "error",
130
118
  format: fileFormat,
131
- level: 'info'
119
+ maxsize: 5242880,
120
+ maxFiles: 1,
121
+ tailable: true
122
+ }));
123
+ if (!isProduction) transports.push(new (external_winston_default()).transports.File({
124
+ filename: external_path_default().join(logDir, "app.log"),
125
+ level: "info",
126
+ format: fileFormat,
127
+ maxsize: 5242880,
128
+ maxFiles: 1,
129
+ tailable: true
132
130
  }));
133
131
  const logger = external_winston_default().createLogger({
134
- level: 'debug',
132
+ level: isProduction ? "error" : "debug",
135
133
  levels,
136
134
  format: external_winston_default().format.combine(external_winston_default().format.errors({
137
135
  stack: true
138
136
  }), external_winston_default().format.splat()),
139
137
  transports,
140
- exceptionHandlers: logDir ? [
141
- new (external_winston_daily_rotate_file_default())({
142
- filename: external_path_default().join(logDir, 'exceptions-%DATE%.log'),
143
- datePattern: 'YYYY-MM-DD',
144
- zippedArchive: true,
145
- maxSize: '1m',
146
- maxFiles: '1d',
147
- format: exceptionFormat
138
+ exceptionHandlers: [
139
+ new (external_winston_default()).transports.File({
140
+ filename: external_path_default().join(logDir, "error.log"),
141
+ format: exceptionFormat,
142
+ maxsize: 5242880,
143
+ maxFiles: 1
148
144
  })
149
- ] : [],
150
- rejectionHandlers: logDir ? [
151
- new (external_winston_daily_rotate_file_default())({
152
- filename: external_path_default().join(logDir, 'rejections-%DATE%.log'),
153
- datePattern: 'YYYY-MM-DD',
154
- zippedArchive: true,
155
- maxSize: '1m',
156
- maxFiles: '1d',
157
- format: exceptionFormat
145
+ ],
146
+ rejectionHandlers: [
147
+ new (external_winston_default()).transports.File({
148
+ filename: external_path_default().join(logDir, "error.log"),
149
+ format: exceptionFormat,
150
+ maxsize: 5242880,
151
+ maxFiles: 1
158
152
  })
159
- ] : []
153
+ ]
160
154
  });
161
- process.on('SIGINT', ()=>{
155
+ process.on("SIGINT", ()=>{
162
156
  logger.end(()=>{
163
157
  logger.info("\u65E5\u5FD7\u5DF2\u5173\u95ED");
164
158
  process.exit(0);
@@ -316,7 +310,6 @@ var __webpack_exports__ = {};
316
310
  var external_mammoth_default = /*#__PURE__*/ __webpack_require__.n(external_mammoth_namespaceObject);
317
311
  const external_html_to_md_namespaceObject = require("html-to-md");
318
312
  var external_html_to_md_default = /*#__PURE__*/ __webpack_require__.n(external_html_to_md_namespaceObject);
319
- const external_os_namespaceObject = require("os");
320
313
  const sanitizeFileName = (input)=>input.replace(/[\\/:*?"<>|\n\r#%&]/g, '').trim().replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_+|_+$/g, '');
321
314
  function normalizePath(filePath) {
322
315
  if (!filePath || 'string' != typeof filePath) throw new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
@@ -4199,6 +4192,207 @@ var __webpack_exports__ = {};
4199
4192
  ErrorCodes["UNSUPPORTED_REQUIREMENT_TYPE"] = "UNSUPPORTED_REQUIREMENT_TYPE";
4200
4193
  return ErrorCodes;
4201
4194
  }({});
4195
+ async function invokeFlow(params, streamCb) {
4196
+ const { appid = "app-ESTcrkOPOmkxdrO0120mE4s1", data, timeout = 1800000 } = params;
4197
+ const controller = new AbortController();
4198
+ const signal = controller.signal;
4199
+ if ("undefined" == typeof ReadableStream) throw new Error("ReadableStream is not supported in this environment");
4200
+ const fetchData = async (retryCount = 0)=>{
4201
+ try {
4202
+ const fetchOptions = {
4203
+ method: "POST",
4204
+ headers: {
4205
+ Authorization: `Bearer ${appid}`,
4206
+ "Content-Type": "application/json"
4207
+ },
4208
+ body: JSON.stringify({
4209
+ inputs: data,
4210
+ response_mode: "streaming",
4211
+ user: "aico-mcp"
4212
+ }),
4213
+ signal
4214
+ };
4215
+ const res = await fetch("http://11.0.166.20:9199/v1/workflows/run", fetchOptions);
4216
+ if (!res.ok) {
4217
+ if (retryCount < 3) {
4218
+ await new Promise((resolve)=>setTimeout(resolve, 1000));
4219
+ return fetchData(retryCount + 1);
4220
+ }
4221
+ const errorResponse = await res.text();
4222
+ throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
4223
+ }
4224
+ if (res.ok) if (res.body) {
4225
+ const reader = res.body.getReader();
4226
+ const decoder = new TextDecoder("utf-8");
4227
+ if (streamCb) return void new ReadableStream({
4228
+ start (controller) {
4229
+ let buffer = "";
4230
+ function push() {
4231
+ reader.read().then(({ done, value })=>{
4232
+ if (done) {
4233
+ const lines = buffer.split("\n");
4234
+ for (const line of lines)handleLine(line, controller);
4235
+ if (streamCb) streamCb({
4236
+ isEnd: true
4237
+ });
4238
+ controller.close();
4239
+ return;
4240
+ }
4241
+ const chunkText = decoder.decode(value, {
4242
+ stream: true
4243
+ });
4244
+ buffer += chunkText;
4245
+ const lines = buffer.split("\n");
4246
+ for(let i = 0; i < lines.length - 1; i++)handleLine(lines[i], controller);
4247
+ buffer = lines[lines.length - 1];
4248
+ push();
4249
+ });
4250
+ }
4251
+ function handleLine(line, controller) {
4252
+ line = line.trim();
4253
+ if (line.startsWith("data:")) {
4254
+ const dataStr = line.slice(5).trim();
4255
+ if ("" === dataStr) return;
4256
+ try {
4257
+ const jsonData = JSON.parse(dataStr);
4258
+ if (jsonData.data?.text) {
4259
+ const wrappedData = {
4260
+ content: jsonData.data.text.toString(),
4261
+ controller
4262
+ };
4263
+ if (streamCb) streamCb(wrappedData);
4264
+ }
4265
+ } catch (e) {
4266
+ console.error("\u89E3\u6790JSON\u5931\u8D25:", e);
4267
+ }
4268
+ }
4269
+ }
4270
+ push();
4271
+ }
4272
+ });
4273
+ {
4274
+ let buffer = "";
4275
+ let accumulatedText = "";
4276
+ let isResponseEnded = false;
4277
+ const readAll = async ()=>{
4278
+ const { done, value } = await reader.read();
4279
+ if (done) {
4280
+ if (!isResponseEnded) throw new Error("\u54CD\u5E94\u63D0\u524D\u7ED3\u675F");
4281
+ return accumulatedText;
4282
+ }
4283
+ const chunkText = decoder.decode(value, {
4284
+ stream: true
4285
+ });
4286
+ buffer += chunkText;
4287
+ const lines = buffer.split("\n");
4288
+ for(let i = 0; i < lines.length - 1; i++){
4289
+ const line = lines[i].trim();
4290
+ if (!line.startsWith("data:")) continue;
4291
+ const dataStr = line.slice(5).trim();
4292
+ if ("" !== dataStr) try {
4293
+ const jsonData = JSON.parse(dataStr);
4294
+ switch(jsonData.event){
4295
+ case "message":
4296
+ case "agent_message":
4297
+ case "text_chunk":
4298
+ {
4299
+ const content = "text_chunk" === jsonData.event ? jsonData.data.text : jsonData.answer;
4300
+ accumulatedText += content;
4301
+ break;
4302
+ }
4303
+ case "workflow_finished":
4304
+ if (jsonData.data?.outputs?.text) accumulatedText = jsonData.data.outputs.text;
4305
+ else if (jsonData.data?.outputs) {
4306
+ const outputs = jsonData.data.outputs;
4307
+ const textValue = Object.values(outputs).find((v)=>"string" == typeof v && v.length > 0);
4308
+ if (textValue) accumulatedText = textValue;
4309
+ }
4310
+ isResponseEnded = true;
4311
+ break;
4312
+ case "message_end":
4313
+ isResponseEnded = true;
4314
+ break;
4315
+ case "error":
4316
+ throw new Error(`\u{670D}\u{52A1}\u{5668}\u{9519}\u{8BEF}: ${jsonData.code}, ${jsonData.message}`);
4317
+ default:
4318
+ break;
4319
+ }
4320
+ } catch (e) {
4321
+ throw new Error("\u89E3\u6790JSON\u5931\u8D25: " + e.message);
4322
+ }
4323
+ }
4324
+ buffer = lines[lines.length - 1];
4325
+ return readAll();
4326
+ };
4327
+ return readAll();
4328
+ }
4329
+ } else throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
4330
+ {
4331
+ const errorResponse = await res.text();
4332
+ throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
4333
+ }
4334
+ } catch (error) {
4335
+ if ("AbortError" === error.name) throw new Error("\u8BF7\u6C42\u5DF2\u88AB\u4E2D\u6B62\uFF0C\u8D85\u65F6");
4336
+ throw error;
4337
+ }
4338
+ };
4339
+ try {
4340
+ const result = await Promise.race([
4341
+ fetchData(),
4342
+ new Promise((_, reject)=>{
4343
+ setTimeout(()=>{
4344
+ controller.abort();
4345
+ reject(new Error("\u8BF7\u6C42\u8D85\u65F6"));
4346
+ }, timeout);
4347
+ })
4348
+ ]);
4349
+ if (streamCb) return;
4350
+ return result;
4351
+ } catch (error) {
4352
+ controller.abort();
4353
+ throw error;
4354
+ }
4355
+ }
4356
+ async function uploadFile(params) {
4357
+ const { appid, filePath, user = "aico-mcp" } = params;
4358
+ try {
4359
+ const fileBuffer = await external_fs_default().promises.readFile(filePath);
4360
+ const fileName = external_path_default().basename(filePath);
4361
+ const fileExtension = external_path_default().extname(filePath).toLowerCase().slice(1);
4362
+ const mimeTypes = {
4363
+ png: "image/png",
4364
+ jpeg: "image/jpeg",
4365
+ jpg: "image/jpeg",
4366
+ webp: "image/webp",
4367
+ gif: "image/gif"
4368
+ };
4369
+ const mimeType = mimeTypes[fileExtension] || "application/octet-stream";
4370
+ const formData = new FormData();
4371
+ formData.append("file", new Blob([
4372
+ fileBuffer.buffer
4373
+ ], {
4374
+ type: mimeType
4375
+ }), fileName);
4376
+ formData.append("user", user);
4377
+ const response = await fetch("http://11.0.166.20:9199/v1/files/upload", {
4378
+ method: "POST",
4379
+ headers: {
4380
+ Authorization: `Bearer ${appid}`
4381
+ },
4382
+ body: formData
4383
+ });
4384
+ if (!response.ok) {
4385
+ const errorText = await response.text();
4386
+ throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${response.status} ${response.statusText} - ${errorText}`);
4387
+ }
4388
+ const result = await response.json();
4389
+ if (!result.id || !result.name) throw new Error("\u65E0\u6548\u7684\u6587\u4EF6\u4E0A\u4F20\u54CD\u5E94\u683C\u5F0F");
4390
+ return result;
4391
+ } catch (error) {
4392
+ if (error instanceof Error) throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${error.message}`);
4393
+ throw new Error("\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: \u672A\u77E5\u9519\u8BEF");
4394
+ }
4395
+ }
4202
4396
  class OpenAIService {
4203
4397
  qwenConfig = {
4204
4398
  apiKey: "sk-95b0bc60b7464bbbafd64edc2f5bab14",
@@ -4220,6 +4414,10 @@ var __webpack_exports__ = {};
4220
4414
  baseUrl: "https://api.lkeap.cloud.tencent.com/v1/chat/completions",
4221
4415
  model: "deepseek-v3.1-terminus"
4222
4416
  };
4417
+ difyConfig = {
4418
+ apiKey: "app-AvlLh0nfN4l9oz1MSW4sEAQ6",
4419
+ baseUrl: "http://11.0.166.20:9199/v1"
4420
+ };
4223
4421
  constructor(){}
4224
4422
  async generateText(params) {
4225
4423
  const { prompt, temperature, system_prompt } = params;
@@ -4576,23 +4774,115 @@ var __webpack_exports__ = {};
4576
4774
  }
4577
4775
  }
4578
4776
  }
4777
+ async analyzeImageWithPath(params) {
4778
+ const { prompt, image_path, system_prompt } = params;
4779
+ logger.info("[OpenAI] analyzeImageWithPath \u88AB\u8C03\u7528", {
4780
+ image_path,
4781
+ prompt_length: prompt.length
4782
+ });
4783
+ try {
4784
+ logger.info("[OpenAI] \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6\u5230 Dify", {
4785
+ image_path
4786
+ });
4787
+ const uploadResult = await uploadFile({
4788
+ appid: this.difyConfig.apiKey,
4789
+ filePath: image_path,
4790
+ user: "aico-mcp"
4791
+ });
4792
+ logger.info("[OpenAI] \u6587\u4EF6\u4E0A\u4F20\u6210\u529F", {
4793
+ upload_file_id: uploadResult.id
4794
+ });
4795
+ const workflowData = {
4796
+ imagePath: {
4797
+ type: "image",
4798
+ transfer_method: "local_file",
4799
+ upload_file_id: uploadResult.id
4800
+ },
4801
+ context: prompt
4802
+ };
4803
+ logger.info("[OpenAI] \u5F00\u59CB\u8C03\u7528 Dify \u5DE5\u4F5C\u6D41");
4804
+ const workflowResponse = await invokeFlow({
4805
+ appid: this.difyConfig.apiKey,
4806
+ data: workflowData,
4807
+ timeout: 120000
4808
+ });
4809
+ logger.info("[OpenAI] Dify \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F", {
4810
+ response_type: typeof workflowResponse,
4811
+ response_preview: "string" == typeof workflowResponse ? workflowResponse.substring(0, 200) : JSON.stringify(workflowResponse).substring(0, 500)
4812
+ });
4813
+ let summary = "";
4814
+ if ("string" == typeof workflowResponse && workflowResponse.length > 0) summary = workflowResponse;
4815
+ else if (workflowResponse?.outputs?.text) summary = workflowResponse.outputs.text;
4816
+ else if (workflowResponse?.data?.outputs?.text) summary = workflowResponse.data.outputs.text;
4817
+ else if (workflowResponse?.data?.text) summary = workflowResponse.data.text;
4818
+ else if (workflowResponse?.answer) summary = workflowResponse.answer;
4819
+ else if (workflowResponse?.status === "failed") throw new Error(`Dify\u{5DE5}\u{4F5C}\u{6D41}\u{6267}\u{884C}\u{5931}\u{8D25}: ${workflowResponse.error || "\u672A\u77E5\u9519\u8BEF"}`);
4820
+ if (!summary || 0 === summary.length) {
4821
+ logger.error("[OpenAI] Dify \u54CD\u5E94\u89E3\u6790\u5931\u8D25\uFF0C\u65E0\u6CD5\u63D0\u53D6\u6587\u672C\u5185\u5BB9", {
4822
+ response: JSON.stringify(workflowResponse)
4823
+ });
4824
+ throw new Error("Dify\u5DE5\u4F5C\u6D41\u54CD\u5E94\u4E2D\u672A\u627E\u5230\u6709\u6548\u6587\u672C\u5185\u5BB9");
4825
+ }
4826
+ logger.info("[OpenAI] Dify \u5206\u6790\u5B8C\u6210", {
4827
+ summary_length: summary.length
4828
+ });
4829
+ return summary;
4830
+ } catch (difyError) {
4831
+ logger.error("[OpenAI] Dify \u8C03\u7528\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u5176\u4ED6\u670D\u52A1", {
4832
+ error: difyError instanceof Error ? difyError.message : String(difyError)
4833
+ });
4834
+ const fs = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "fs/promises"));
4835
+ const path = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "path"));
4836
+ const imageBuffer = await fs.readFile(image_path);
4837
+ const base64 = imageBuffer.toString("base64");
4838
+ const ext = path.extname(image_path).toLowerCase();
4839
+ let mimeType = "image/jpeg";
4840
+ switch(ext){
4841
+ case ".png":
4842
+ mimeType = "image/png";
4843
+ break;
4844
+ case ".gif":
4845
+ mimeType = "image/gif";
4846
+ break;
4847
+ case ".webp":
4848
+ mimeType = "image/webp";
4849
+ break;
4850
+ case ".jpg":
4851
+ case ".jpeg":
4852
+ mimeType = "image/jpeg";
4853
+ break;
4854
+ }
4855
+ const image_base64 = `data:${mimeType};base64,${base64}`;
4856
+ return this.analyzeImage({
4857
+ prompt,
4858
+ image_base64,
4859
+ system_prompt
4860
+ });
4861
+ }
4862
+ }
4579
4863
  async analyzeImage(params) {
4580
4864
  const { prompt, image_base64, system_prompt } = params;
4581
- let lastError = null;
4582
4865
  try {
4583
- const response = await fetch(this.glm4vConfig.baseUrl, {
4866
+ const controller = new AbortController();
4867
+ const timeoutId = setTimeout(()=>controller.abort(), 20000);
4868
+ const response = await fetch(this.kimiConfig.baseUrl, {
4584
4869
  method: "POST",
4585
4870
  headers: {
4586
4871
  "Content-Type": "application/json",
4587
- Authorization: `Bearer ${this.glm4vConfig.apiKey}`
4872
+ Authorization: `Bearer ${this.kimiConfig.apiKey}`
4588
4873
  },
4589
4874
  body: JSON.stringify({
4590
- model: this.glm4vConfig.model,
4875
+ model: this.kimiConfig.model,
4591
4876
  messages: [
4592
4877
  ...system_prompt ? [
4593
4878
  {
4594
4879
  role: "system",
4595
- content: system_prompt
4880
+ content: [
4881
+ {
4882
+ type: "text",
4883
+ text: system_prompt
4884
+ }
4885
+ ]
4596
4886
  }
4597
4887
  ] : [],
4598
4888
  {
@@ -4612,36 +4902,34 @@ var __webpack_exports__ = {};
4612
4902
  }
4613
4903
  ],
4614
4904
  stream: false
4615
- })
4905
+ }),
4906
+ signal: controller.signal
4616
4907
  });
4908
+ clearTimeout(timeoutId);
4617
4909
  if (!response.ok) {
4618
4910
  const errorText = await response.text();
4619
- throw new Error(`GLM-4V API error: ${response.status} ${response.statusText} - ${errorText}`);
4911
+ throw new Error(`Kimi Vision API error: ${response.status} ${response.statusText} - ${errorText}`);
4620
4912
  }
4621
4913
  const data = await response.json();
4622
- if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from GLM-4V API");
4914
+ if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Kimi Vision API");
4623
4915
  return data.choices[0].message.content;
4624
- } catch (error) {
4625
- lastError = error;
4916
+ } catch (kimiError) {
4626
4917
  try {
4627
- const response = await fetch(this.kimiConfig.baseUrl, {
4918
+ const controller = new AbortController();
4919
+ const timeoutId = setTimeout(()=>controller.abort(), 15000);
4920
+ const response = await fetch(this.glm4vConfig.baseUrl, {
4628
4921
  method: "POST",
4629
4922
  headers: {
4630
4923
  "Content-Type": "application/json",
4631
- Authorization: `Bearer ${this.kimiConfig.apiKey}`
4924
+ Authorization: `Bearer ${this.glm4vConfig.apiKey}`
4632
4925
  },
4633
4926
  body: JSON.stringify({
4634
- model: this.kimiConfig.model,
4927
+ model: this.glm4vConfig.model,
4635
4928
  messages: [
4636
4929
  ...system_prompt ? [
4637
4930
  {
4638
4931
  role: "system",
4639
- content: [
4640
- {
4641
- type: "text",
4642
- text: system_prompt
4643
- }
4644
- ]
4932
+ content: system_prompt
4645
4933
  }
4646
4934
  ] : [],
4647
4935
  {
@@ -4661,41 +4949,57 @@ var __webpack_exports__ = {};
4661
4949
  }
4662
4950
  ],
4663
4951
  stream: false
4664
- })
4952
+ }),
4953
+ signal: controller.signal
4665
4954
  });
4955
+ clearTimeout(timeoutId);
4666
4956
  if (!response.ok) {
4667
4957
  const errorText = await response.text();
4668
- throw new Error(`Kimi Vision API error: ${response.status} ${response.statusText} - ${errorText}`);
4958
+ throw new Error(`GLM-4V API error: ${response.status} ${response.statusText} - ${errorText}`);
4669
4959
  }
4670
4960
  const data = await response.json();
4671
- if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Kimi Vision API");
4961
+ if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from GLM-4V API");
4672
4962
  return data.choices[0].message.content;
4673
- } catch (kimiError) {
4674
- throw lastError;
4963
+ } catch (glmError) {
4964
+ throw new Error(`All vision services failed. Kimi: ${kimiError instanceof Error ? kimiError.message : String(kimiError)}, GLM-4V: ${glmError instanceof Error ? glmError.message : String(glmError)}`);
4675
4965
  }
4676
4966
  }
4677
4967
  }
4678
4968
  }
4679
4969
  const openAIService = new OpenAIService();
4680
- const intelligentRequirementAnalysisPrompt = `\u{4F60}\u{662F}\u{8F6F}\u{4EF6}\u{9700}\u{6C42}\u{5206}\u{6790}\u{5E08}\u{FF0C}\u{5FEB}\u{901F}\u{8BC6}\u{522B}\u{9700}\u{6C42}\u{7C7B}\u{578B}\u{5E76}\u{7CBE}\u{786E}\u{63D0}\u{53D6}2-5\u{4E2A}\u{6838}\u{5FC3}\u{529F}\u{80FD}\u{70B9}\u{3002}
4970
+ const intelligentRequirementAnalysisPrompt = `\u{4F60}\u{662F}\u{8D44}\u{6DF1}\u{8F6F}\u{4EF6}\u{9700}\u{6C42}\u{5206}\u{6790}\u{5E08}\u{FF0C}\u{8D1F}\u{8D23}\u{6DF1}\u{5EA6}\u{5206}\u{6790}\u{7528}\u{6237}\u{9700}\u{6C42}\u{5E76}\u{63D0}\u{53D6}\u{7ED3}\u{6784}\u{5316}\u{4FE1}\u{606F}\u{FF0C}\u{4E3A}\u{540E}\u{7EED}\u{6587}\u{6863}\u{751F}\u{6210}\u{63D0}\u{4F9B}\u{5B8C}\u{6574}\u{7684}\u{4E0A}\u{4E0B}\u{6587}\u{3002}
4681
4971
 
4682
4972
  **\u{8F93}\u{5165}\u{5185}\u{5BB9}**:
4683
4973
  {inputContent}
4684
4974
 
4685
- ## \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{8BC6}\u{522B}
4975
+ ## \u{5206}\u{6790}\u{4EFB}\u{52A1}
4976
+
4977
+ \u{4F60}\u{9700}\u{8981}\u{5B8C}\u{6210}\u{4EE5}\u{4E0B}\u{5206}\u{6790}\u{4EFB}\u{52A1}\u{FF0C}\u{4E3A}MCP\u{5BA2}\u{6237}\u{7AEF}\u{751F}\u{6210}\u{6280}\u{672F}\u{6587}\u{6863}\u{63D0}\u{4F9B}\u{5145}\u{5206}\u{7684}\u{4E0A}\u{4E0B}\u{6587}\u{FF1A}
4686
4978
 
4687
- **\u{63A5}\u{53E3}**: API\u{3001}REST\u{3001}GraphQL\u{3001}\u{5FAE}\u{670D}\u{52A1}\u{3001}\u{540E}\u{7AEF}\u{670D}\u{52A1} \u{2192} \u{6570}\u{636E}\u{4EA4}\u{4E92}\u{3001}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{3001}\u{7CFB}\u{7EDF}\u{96C6}\u{6210}
4688
- **PC\u{9875}\u{9762}**: \u{9875}\u{9762}\u{3001}UI\u{3001}\u{7F51}\u{9875}\u{3001}\u{524D}\u{7AEF}\u{3001}\u{7BA1}\u{7406}\u{540E}\u{53F0} \u{2192} \u{7528}\u{6237}\u{754C}\u{9762}\u{3001}\u{8868}\u{5355}\u{64CD}\u{4F5C}\u{3001}\u{6570}\u{636E}\u{5C55}\u{793A}
4689
- **APP**: \u{79FB}\u{52A8}\u{5E94}\u{7528}\u{3001}iOS\u{3001}Android\u{3001}\u{5C0F}\u{7A0B}\u{5E8F} \u{2192} \u{79FB}\u{52A8}\u{7AEF}\u{529F}\u{80FD}\u{3001}\u{624B}\u{52BF}\u{64CD}\u{4F5C}\u{3001}\u{8BBE}\u{5907}\u{7279}\u{6027}
4690
- **SDK\u{96C6}\u{6210}**: \u{7B2C}\u{4E09}\u{65B9}\u{3001}\u{5BF9}\u{63A5}\u{3001}\u{652F}\u{4ED8}\u{3001}\u{5730}\u{56FE}\u{3001}\u{63A8}\u{9001} \u{2192} \u{5916}\u{90E8}\u{670D}\u{52A1}\u{5BF9}\u{63A5}\u{3001}\u{914D}\u{7F6E}\u{53C2}\u{6570}\u{3001}\u{56DE}\u{8C03}\u{5904}\u{7406}
4691
- **\u{6DF7}\u{5408}**: \u{5305}\u{542B}\u{591A}\u{79CD}\u{7C7B}\u{578B}\u{7279}\u{5F81}
4979
+ ### 1. \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{8BC6}\u{522B}
4692
4980
 
4693
- ## \u{529F}\u{80FD}\u{70B9}\u{63D0}\u{53D6}\u{539F}\u{5219}
4981
+ \u{6839}\u{636E}\u{5173}\u{952E}\u{8BCD}\u{548C}\u{4E1A}\u{52A1}\u{573A}\u{666F}\u{8BC6}\u{522B}\u{9700}\u{6C42}\u{7C7B}\u{578B}\u{FF1A}
4982
+ - **\u{63A5}\u{53E3}(API)**: API\u{3001}REST\u{3001}GraphQL\u{3001}\u{5FAE}\u{670D}\u{52A1}\u{3001}\u{540E}\u{7AEF}\u{670D}\u{52A1}\u{3001}\u{6570}\u{636E}\u{63A5}\u{53E3}
4983
+ - **PC\u{9875}\u{9762}**: \u{9875}\u{9762}\u{3001}UI\u{3001}\u{7F51}\u{9875}\u{3001}\u{524D}\u{7AEF}\u{3001}\u{7BA1}\u{7406}\u{540E}\u{53F0}\u{3001}Web\u{7AEF}
4984
+ - **APP**: \u{79FB}\u{52A8}\u{5E94}\u{7528}\u{3001}iOS\u{3001}Android\u{3001}\u{5C0F}\u{7A0B}\u{5E8F}\u{3001}\u{79FB}\u{52A8}\u{7AEF}
4985
+ - **SDK\u{96C6}\u{6210}**: \u{7B2C}\u{4E09}\u{65B9}\u{3001}\u{5BF9}\u{63A5}\u{3001}\u{652F}\u{4ED8}\u{3001}\u{5730}\u{56FE}\u{3001}\u{63A8}\u{9001}\u{3001}SDK
4694
4986
 
4695
- 1. \u{7CBE}\u{786E}\u{6027}\u{FF1A}\u{53EA}\u{63D0}\u{53D6}\u{6838}\u{5FC3}\u{72EC}\u{7ACB}\u{529F}\u{80FD}\u{70B9}\u{FF08}2-5\u{4E2A}\u{FF09}
4696
- 2. \u{4E1A}\u{52A1}\u{4EF7}\u{503C}\u{FF1A}\u{6BCF}\u{4E2A}\u{529F}\u{80FD}\u{70B9}\u{6709}\u{660E}\u{786E}\u{4E1A}\u{52A1}\u{4EF7}\u{503C}
4697
- 3. \u{6280}\u{672F}\u{5339}\u{914D}\u{FF1A}\u{529F}\u{80FD}\u{70B9}\u{4E0E}\u{9700}\u{6C42}\u{7C7B}\u{578B}\u{9AD8}\u{5EA6}\u{5339}\u{914D}
4698
- 4. \u{907F}\u{514D}\u{8FC7}\u{5EA6}\u{62C6}\u{5206}\u{FF1A}\u{4FDD}\u{6301}\u{529F}\u{80FD}\u{5B8C}\u{6574}\u{6027}
4987
+ ### 2. \u{6DF1}\u{5EA6}\u{9700}\u{6C42}\u{5206}\u{6790}
4988
+
4989
+ \u{5BF9}\u{6BCF}\u{4E2A}\u{529F}\u{80FD}\u{70B9}\u{8FDB}\u{884C}\u{6DF1}\u{5EA6}\u{5206}\u{6790}\u{FF0C}\u{63D0}\u{53D6}\u{FF1A}
4990
+ - **\u{4E1A}\u{52A1}\u{80CC}\u{666F}**: \u{4E3A}\u{4EC0}\u{4E48}\u{9700}\u{8981}\u{8FD9}\u{4E2A}\u{529F}\u{80FD}
4991
+ - **\u{6838}\u{5FC3}\u{6D41}\u{7A0B}**: \u{4E3B}\u{8981}\u{7684}\u{4E1A}\u{52A1}\u{6D41}\u{7A0B}\u{6B65}\u{9AA4}
4992
+ - **\u{6570}\u{636E}\u{5B9E}\u{4F53}**: \u{6D89}\u{53CA}\u{7684}\u{6570}\u{636E}\u{5BF9}\u{8C61}\u{548C}\u{5B57}\u{6BB5}
4993
+ - **\u{4EA4}\u{4E92}\u{903B}\u{8F91}**: \u{7528}\u{6237}\u{64CD}\u{4F5C}\u{548C}\u{7CFB}\u{7EDF}\u{54CD}\u{5E94}
4994
+ - **\u{5F02}\u{5E38}\u{573A}\u{666F}**: \u{53EF}\u{80FD}\u{7684}\u{9519}\u{8BEF}\u{60C5}\u{51B5}\u{548C}\u{5904}\u{7406}\u{65B9}\u{5F0F}
4995
+
4996
+ ### 3. \u{6280}\u{672F}\u{4E0A}\u{4E0B}\u{6587}\u{63D0}\u{53D6}
4997
+
4998
+ \u{4ECE}\u{9879}\u{76EE}\u{4FE1}\u{606F}\u{4E2D}\u{63D0}\u{53D6}\u{FF1A}
4999
+ - \u{6280}\u{672F}\u{6808}\u{548C}\u{6846}\u{67B6}
5000
+ - \u{73B0}\u{6709}\u{7684}\u{4EE3}\u{7801}\u{7ED3}\u{6784}
5001
+ - \u{4F9D}\u{8D56}\u{5173}\u{7CFB}
5002
+ - \u{8BBE}\u{8BA1}\u{89C4}\u{8303}
4699
5003
 
4700
5004
  ## \u{8F93}\u{51FA}\u{683C}\u{5F0F}
4701
5005
 
@@ -4707,14 +5011,36 @@ var __webpack_exports__ = {};
4707
5011
  "requirementType": "\u{63A5}\u{53E3}|PC\u{9875}\u{9762}|APP|SDK\u{96C6}\u{6210}|\u{6DF7}\u{5408}\u{7C7B}\u{578B}",
4708
5012
  "primaryTechnology": "\u{4E3B}\u{8981}\u{6280}\u{672F}\u{6808}\u{63CF}\u{8FF0}",
4709
5013
  "confidence": "high|medium|low",
5014
+ "businessContext": {
5015
+ "background": "\u{4E1A}\u{52A1}\u{80CC}\u{666F}\u{63CF}\u{8FF0}",
5016
+ "objectives": ["\u{4E1A}\u{52A1}\u{76EE}\u{6807}1", "\u{4E1A}\u{52A1}\u{76EE}\u{6807}2"],
5017
+ "stakeholders": ["\u{6D89}\u{53CA}\u{7684}\u{89D2}\u{8272}1", "\u{6D89}\u{53CA}\u{7684}\u{89D2}\u{8272}2"]
5018
+ },
4710
5019
  "requirements": [
4711
5020
  {
4712
5021
  "id": "req_001",
4713
5022
  "title": "\u{529F}\u{80FD}\u{70B9}\u{540D}\u{79F0}",
4714
- "fullContent": "\u{529F}\u{80FD}\u{70B9}\u{7684}\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}",
5023
+ "fullContent": "\u{529F}\u{80FD}\u{70B9}\u{7684}\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{FF0C}\u{5305}\u{542B}\u{5B8C}\u{6574}\u{7684}\u{4E1A}\u{52A1}\u{903B}\u{8F91}",
4715
5024
  "priority": "high|medium|low",
4716
5025
  "complexity": "\u{7B80}\u{5355}|\u{4E2D}\u{7B49}|\u{590D}\u{6742}",
4717
- "type": "\u{63A5}\u{53E3}|PC\u{9875}\u{9762}|APP|SDK\u{96C6}\u{6210}"
5026
+ "type": "\u{63A5}\u{53E3}|PC\u{9875}\u{9762}|APP|SDK\u{96C6}\u{6210}",
5027
+ "businessFlow": {
5028
+ "preconditions": ["\u{524D}\u{7F6E}\u{6761}\u{4EF6}1"],
5029
+ "mainFlow": ["\u{6B65}\u{9AA4}1", "\u{6B65}\u{9AA4}2", "\u{6B65}\u{9AA4}3"],
5030
+ "alternativeFlows": ["\u{66FF}\u{4EE3}\u{6D41}\u{7A0B}1"],
5031
+ "exceptionFlows": ["\u{5F02}\u{5E38}\u{5904}\u{7406}1"]
5032
+ },
5033
+ "dataEntities": [
5034
+ {
5035
+ "name": "\u{5B9E}\u{4F53}\u{540D}\u{79F0}",
5036
+ "fields": [
5037
+ {"name": "\u{5B57}\u{6BB5}\u{540D}", "type": "\u{7C7B}\u{578B}", "required": true, "description": "\u{8BF4}\u{660E}"}
5038
+ ]
5039
+ }
5040
+ ],
5041
+ "interactions": [
5042
+ {"trigger": "\u{89E6}\u{53D1}\u{6761}\u{4EF6}", "action": "\u{7CFB}\u{7EDF}\u{52A8}\u{4F5C}", "response": "\u{54CD}\u{5E94}\u{7ED3}\u{679C}"}
5043
+ ]
4718
5044
  }
4719
5045
  ],
4720
5046
  "templateRecommendation": {
@@ -4722,13 +5048,29 @@ var __webpack_exports__ = {};
4722
5048
  "reason": "\u{9009}\u{62E9}\u{8BE5}\u{6A21}\u{677F}\u{7684}\u{539F}\u{56E0}",
4723
5049
  "additionalTemplates": ["\u{5982}\u{679C}\u{662F}\u{6DF7}\u{5408}\u{7C7B}\u{578B}\u{FF0C}\u{5217}\u{51FA}\u{9700}\u{8981}\u{7684}\u{5176}\u{4ED6}\u{6A21}\u{677F}"]
4724
5050
  },
4725
- "optimizationSuggestion": "\u{9488}\u{5BF9}\u{529F}\u{80FD}\u{70B9}\u{6570}\u{91CF}\u{548C}\u{7C7B}\u{578B}\u{7684}\u{4F18}\u{5316}\u{5EFA}\u{8BAE}"
5051
+ "technicalContext": {
5052
+ "suggestedTechStack": ["\u{5EFA}\u{8BAE}\u{7684}\u{6280}\u{672F}\u{6808}"],
5053
+ "integrationPoints": ["\u{9700}\u{8981}\u{96C6}\u{6210}\u{7684}\u{7CFB}\u{7EDF}\u{6216}\u{670D}\u{52A1}"],
5054
+ "securityRequirements": ["\u{5B89}\u{5168}\u{8981}\u{6C42}"],
5055
+ "performanceRequirements": ["\u{6027}\u{80FD}\u{8981}\u{6C42}"]
5056
+ },
5057
+ "documentationHints": {
5058
+ "keySequenceDiagrams": ["\u{9700}\u{8981}\u{7ED8}\u{5236}\u{7684}\u{65F6}\u{5E8F}\u{56FE}\u{573A}\u{666F}"],
5059
+ "keyERDiagrams": ["\u{9700}\u{8981}\u{7ED8}\u{5236}\u{7684}ER\u{56FE}\u{5B9E}\u{4F53}"],
5060
+ "keyTables": ["\u{9700}\u{8981}\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}\u{7684}\u{8868}\u{683C}"]
5061
+ }
4726
5062
  }
4727
5063
  \`\`\`
4728
5064
 
5065
+ ## \u{5206}\u{6790}\u{539F}\u{5219}
4729
5066
 
5067
+ 1. **\u{6DF1}\u{5EA6}\u{4F18}\u{4E8E}\u{5E7F}\u{5EA6}**: \u{5BF9}\u{6BCF}\u{4E2A}\u{529F}\u{80FD}\u{70B9}\u{8FDB}\u{884C}\u{6DF1}\u{5165}\u{5206}\u{6790}\u{FF0C}\u{800C}\u{4E0D}\u{662F}\u{7B80}\u{5355}\u{7F57}\u{5217}
5068
+ 2. **\u{4E1A}\u{52A1}\u{9A71}\u{52A8}**: \u{4ECE}\u{4E1A}\u{52A1}\u{4EF7}\u{503C}\u{89D2}\u{5EA6}\u{7406}\u{89E3}\u{9700}\u{6C42}\u{FF0C}\u{800C}\u{4E0D}\u{4EC5}\u{662F}\u{6280}\u{672F}\u{5B9E}\u{73B0}
5069
+ 3. **\u{4E0A}\u{4E0B}\u{6587}\u{5B8C}\u{6574}**: \u{63D0}\u{4F9B}\u{8DB3}\u{591F}\u{7684}\u{4E0A}\u{4E0B}\u{6587}\u{4FE1}\u{606F}\u{FF0C}\u{8BA9}\u{540E}\u{7EED}\u{6587}\u{6863}\u{751F}\u{6210}\u{6709}\u{636E}\u{53EF}\u{4F9D}
5070
+ 4. **\u{7ED3}\u{6784}\u{5316}\u{8F93}\u{51FA}**: \u{6240}\u{6709}\u{4FE1}\u{606F}\u{90FD}\u{4EE5}\u{7ED3}\u{6784}\u{5316}\u{65B9}\u{5F0F}\u{8F93}\u{51FA}\u{FF0C}\u{4FBF}\u{4E8E}\u{6A21}\u{677F}\u{586B}\u{5145}
5071
+ 5. **\u{63A7}\u{5236}\u{6570}\u{91CF}**: \u{6838}\u{5FC3}\u{529F}\u{80FD}\u{70B9}\u{63A7}\u{5236}\u{5728}2-5\u{4E2A}\u{FF0C}\u{907F}\u{514D}\u{8FC7}\u{5EA6}\u{62C6}\u{5206}
4730
5072
 
4731
- **\u{8981}\u{6C42}**: \u{907F}\u{514D}\u{8FC7}\u{5EA6}\u{62C6}\u{5206}\u{FF0C}\u{7CBE}\u{786E}\u{5339}\u{914D}\u{9700}\u{6C42}\u{7C7B}\u{578B}\u{FF0C}\u{63A7}\u{5236}2-5\u{4E2A}\u{6838}\u{5FC3}\u{529F}\u{80FD}\u{70B9}\u{FF0C}\u{4F18}\u{5148}\u{5355}\u{4E00}\u{6280}\u{672F}\u{6A21}\u{677F}\u{3002}`;
5073
+ **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5FC5}\u{987B}\u{662F}\u{6709}\u{6548}\u{7684}JSON\u{683C}\u{5F0F}\u{FF0C}\u{6BCF}\u{4E2A}\u{5B57}\u{6BB5}\u{90FD}\u{8981}\u{6709}\u{5B9E}\u{9645}\u{5185}\u{5BB9}\u{FF0C}\u{4E0D}\u{8981}\u{4F7F}\u{7528}\u{5360}\u{4F4D}\u{7B26}\u{3002}`;
4732
5074
  class IntelligentAnalyzer {
4733
5075
  async analyzeRequirements(inputContent, projectInfo, customPrompt) {
4734
5076
  try {
@@ -5490,9 +5832,9 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5490
5832
 
5491
5833
  **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{7AE0}\u{8282}\u{6709}\u{5B9E}\u{8D28}\u{5185}\u{5BB9}\u{FF0C}\u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}\u{FF0C}\u{57FA}\u{4E8E}\u{539F}\u{59CB}\u{5185}\u{5BB9}\u{5177}\u{4F53}\u{5206}\u{6790}\u{3002}\`;
5492
5834
  `;
5493
- const pcPageTemplatePrompt = `\u{4F60}\u{662F}\u{524D}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}PC\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}3000\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
5835
+ const htmlPageTemplatePrompt = `\u{4F60}\u{662F}\u{524D}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}HTML\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}3000\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
5494
5836
 
5495
- **\u{8F93}\u{5165}**: \u{529F}\u{80FD}\u{540D}\u{79F0}={featureName}, \u{4E1A}\u{52A1}\u{9886}\u{57DF}={businessDomain}, \u{751F}\u{6210}\u{65F6}\u{5E8F}\u{56FE}={generateSequenceDiagram}
5837
+ **\u{8F93}\u{5165}**: \u{529F}\u{80FD}\u{540D}\u{79F0}={featureName}, \u{4E1A}\u{52A1}\u{9886}\u{57DF}={businessDomain}, \u{9875}\u{9762}\u{7C7B}\u{578B}={pageType}, \u{9875}\u{9762}\u{98CE}\u{683C}={pageStyle}
5496
5838
 
5497
5839
  **\u{539F}\u{59CB}\u{9700}\u{6C42}**:
5498
5840
  \`\`\`
@@ -5502,11 +5844,12 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5502
5844
  ## \u{6587}\u{6863}\u{7ED3}\u{6784}\u{8981}\u{6C42}
5503
5845
  \u{8BF7}\u{4E25}\u{683C}\u{6309}\u{7167}\u{4EE5}\u{4E0B}\u{7ED3}\u{6784}\u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{7684}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{4E2A}\u{7AE0}\u{8282}\u{90FD}\u{8981}\u{6709}\u{8BE6}\u{5B9E}\u{7684}\u{5185}\u{5BB9}\u{FF1A}
5504
5846
 
5505
- # {featureName} - PC\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5847
+ # {featureName} - HTML\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5506
5848
 
5507
5849
  > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: {currentTime}
5508
5850
  > **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: {businessDomain}
5509
- > **\u{9875}\u{9762}\u{7C7B}\u{578B}**: PC\u{7AEF}Web\u{9875}\u{9762}
5851
+ > **\u{9875}\u{9762}\u{7C7B}\u{578B}**: {pageType}\u{FF08}pc/mobile/responsive\u{FF09}
5852
+ > **\u{9875}\u{9762}\u{98CE}\u{683C}**: TailwindCSS \u{7B80}\u{7EA6}\u{98CE}\u{683C}
5510
5853
 
5511
5854
  ---
5512
5855
 
@@ -5518,6 +5861,8 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5518
5861
 
5519
5862
  **\u{6D89}\u{53CA}\u{89D2}\u{8272}**: [\u{5217}\u{51FA}\u{6240}\u{6709}\u{76F8}\u{5173}\u{7528}\u{6237}\u{89D2}\u{8272}]
5520
5863
 
5864
+ **\u{76EE}\u{6807}\u{8BBE}\u{5907}**: [\u{6839}\u{636E}pageType\u{63CF}\u{8FF0}\u{76EE}\u{6807}\u{8BBE}\u{5907}\u{FF0C}\u{5982}PC\u{6D4F}\u{89C8}\u{5668}\u{3001}\u{79FB}\u{52A8}\u{7AEF}\u{6D4F}\u{89C8}\u{5668}\u{3001}\u{6216}\u{4E24}\u{8005}\u{517C}\u{987E}]
5865
+
5521
5866
  ## 2. {featureName}\u{529F}\u{80FD}\u{8BBE}\u{8BA1}\u{8BF4}\u{660E}
5522
5867
 
5523
5868
  | | | | | |
@@ -5527,14 +5872,17 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5527
5872
  |**\u{529F}\u{80FD}\u{8BBE}\u{8BA1}\u{7F16}\u{53F7}**|FD001|**\u{7CFB}\u{7EDF}\u{529F}\u{80FD}\u{540D}\u{79F0}**|{featureName}|
5528
5873
  |**\u{524D}\u{7F6E}\u{6761}\u{4EF6}**|[\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{8BBF}\u{95EE}\u{7684}\u{524D}\u{7F6E}\u{6761}\u{4EF6}]|
5529
5874
  |**\u{89D2}\u{8272}\u{FF08}\u{5C97}\u{4F4D}\u{FF09}**|[\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{7528}\u{6237}\u{89D2}\u{8272}\u{53CA}\u{5176}\u{6743}\u{9650}]|
5530
- |**\u{5165}\u{53E3}\u{6E20}\u{9053}**|[\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{8BBF}\u{95EE}\u{5165}\u{53E3}\u{FF0C}\u{5982}\u{83DC}\u{5355}\u{3001}\u{94FE}\u{63A5}\u{7B49}]|
5875
+ |**\u{5165}\u{53E3}\u{6E20}\u{9053}**|[\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{8BBF}\u{95EE}\u{5165}\u{53E3}\u{FF0C}\u{5982}\u{83DC}\u{5355}\u{3001}\u{94FE}\u{63A5}\u{3001}APP\u{5185}\u{5D4C}\u{7B49}]|
5531
5876
  |**\u{529F}\u{80FD}\u{63CF}\u{8FF0}**|[\u{8BE6}\u{7EC6}\u{7684}\u{529F}\u{80FD}\u{63CF}\u{8FF0}]|
5532
5877
  |**\u{8C03}\u{7528}\u{80FD}\u{529B}\u{57DF}/\u{4E2D}\u{5FC3}**|[\u{5982}\u{9002}\u{7528}\u{7684}\u{540E}\u{7AEF}API\u{63A5}\u{53E3}]|
5533
5878
 
5534
5879
  ## 3. \u{9875}\u{9762}\u{5E03}\u{5C40}\u{8BBE}\u{8BA1}
5535
5880
 
5536
5881
  ### 3.1 \u{6574}\u{4F53}\u{5E03}\u{5C40}\u{7ED3}\u{6784}
5537
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{7684}\u{6574}\u{4F53}\u{5E03}\u{5C40}\u{7ED3}\u{6784}\u{FF0C}\u{5305}\u{62EC}\u{5934}\u{90E8}\u{3001}\u{4E3B}\u{4F53}\u{3001}\u{4FA7}\u{8FB9}\u{680F}\u{3001}\u{5E95}\u{90E8}\u{7B49}\u{533A}\u{57DF}\u{7684}\u{5212}\u{5206}\u{548C}\u{529F}\u{80FD}]
5882
+ [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{7684}\u{6574}\u{4F53}\u{5E03}\u{5C40}\u{7ED3}\u{6784}]
5883
+ - **PC\u{7AEF}\u{5E03}\u{5C40}**: [\u{5982}\u{9002}\u{7528}\u{FF0C}\u{63CF}\u{8FF0}PC\u{7AEF}\u{7684}\u{5934}\u{90E8}\u{3001}\u{4E3B}\u{4F53}\u{3001}\u{4FA7}\u{8FB9}\u{680F}\u{3001}\u{5E95}\u{90E8}\u{7B49}\u{533A}\u{57DF}]
5884
+ - **\u{79FB}\u{52A8}\u{7AEF}\u{5E03}\u{5C40}**: [\u{5982}\u{9002}\u{7528}\u{FF0C}\u{63CF}\u{8FF0}\u{79FB}\u{52A8}\u{7AEF}\u{7684}\u{9876}\u{90E8}\u{5BFC}\u{822A}\u{3001}\u{5185}\u{5BB9}\u{533A}\u{3001}\u{5E95}\u{90E8}\u{5BFC}\u{822A}\u{7B49}\u{533A}\u{57DF}]
5885
+ - **\u{54CD}\u{5E94}\u{5F0F}\u{65AD}\u{70B9}**: [\u{5982}\u{9002}\u{7528}\u{FF0C}\u{63CF}\u{8FF0}\u{4E0D}\u{540C}\u{5C4F}\u{5E55}\u{5C3A}\u{5BF8}\u{4E0B}\u{7684}\u{5E03}\u{5C40}\u{53D8}\u{5316}]
5538
5886
 
5539
5887
  ### 3.2 \u{9875}\u{9762}\u{533A}\u{57DF}\u{5212}\u{5206}
5540
5888
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{5404}\u{4E2A}\u{529F}\u{80FD}\u{533A}\u{57DF}\u{7684}\u{5E03}\u{5C40}\u{FF0C}\u{4F7F}\u{7528}\u{6587}\u{5B57}\u{6216}ASCII\u{56FE}\u{793A}\u{63CF}\u{8FF0}\u{533A}\u{57DF}\u{4F4D}\u{7F6E}\u{5173}\u{7CFB}]
@@ -5542,13 +5890,34 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5542
5890
  ### 3.3 \u{9875}\u{9762}\u{6D41}\u{7EBF}\u{8BBE}\u{8BA1}
5543
5891
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{7528}\u{6237}\u{5728}\u{9875}\u{9762}\u{4E2D}\u{7684}\u{89C6}\u{89C9}\u{6D41}\u{7EBF}\u{548C}\u{64CD}\u{4F5C}\u{8DEF}\u{5F84}\u{8BBE}\u{8BA1}]
5544
5892
 
5893
+ ### 3.4 \u{54CD}\u{5E94}\u{5F0F}\u{9002}\u{914D}\u{7B56}\u{7565}
5894
+ [\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{5728}\u{4E0D}\u{540C}\u{8BBE}\u{5907}\u{4E0A}\u{7684}\u{9002}\u{914D}\u{7B56}\u{7565}]
5895
+ - **\u{65AD}\u{70B9}\u{8BBE}\u{7F6E}**: sm(640px), md(768px), lg(1024px), xl(1280px)
5896
+ - **\u{5E03}\u{5C40}\u{53D8}\u{5316}**: [\u{63CF}\u{8FF0}\u{5404}\u{65AD}\u{70B9}\u{4E0B}\u{7684}\u{5E03}\u{5C40}\u{8C03}\u{6574}]
5897
+ - **\u{5143}\u{7D20}\u{9690}\u{85CF}/\u{663E}\u{793A}**: [\u{63CF}\u{8FF0}\u{54EA}\u{4E9B}\u{5143}\u{7D20}\u{5728}\u{4E0D}\u{540C}\u{8BBE}\u{5907}\u{4E0A}\u{663E}\u{793A}\u{6216}\u{9690}\u{85CF}]
5898
+
5545
5899
  ## 4. \u{6837}\u{5F0F}\u{89C4}\u{8303}\u{8BF4}\u{660E}
5546
5900
 
5547
5901
  ### 4.1 \u{8272}\u{5F69}\u{89C4}\u{8303}
5548
5902
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4F7F}\u{7528}\u{7684}\u{4E3B}\u{8272}\u{8C03}\u{3001}\u{8F85}\u{52A9}\u{8272}\u{3001}\u{72B6}\u{6001}\u{8272}\u{7B49}\u{914D}\u{8272}\u{65B9}\u{6848}]
5903
+ \`\`\`css
5904
+ :root {
5905
+ --bg: #ffffff;
5906
+ --bg-secondary: #f8f9fa;
5907
+ --border: #e5e5e5;
5908
+ --text: #111111;
5909
+ --text-muted: #666666;
5910
+ --accent: #000000;
5911
+ }
5912
+ \`\`\`
5913
+
5914
+ ### 4.2 \u{5B57}\u{4F53}\u{89C4}\u{8303}
5915
+ [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{5B57}\u{4F53}\u{65CF}\u{3001}\u{5B57}\u{53F7}\u{3001}\u{884C}\u{9AD8}\u{7B49}\u{6392}\u{7248}\u{89C4}\u{8303}]
5549
5916
 
5917
+ ### 4.3 \u{95F4}\u{8DDD}\u{89C4}\u{8303}
5918
+ [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{5143}\u{7D20}\u{7684}\u{95F4}\u{8DDD}\u{89C4}\u{8303}\u{FF0C}\u{4F7F}\u{7528}TailwindCSS\u{7684}\u{95F4}\u{8DDD}\u{7CFB}\u{7EDF}]
5550
5919
 
5551
- ### 4.2 \u{54C1}\u{724C}\u{89C6}\u{89C9}\u{89C4}\u{8303}
5920
+ ### 4.4 \u{54C1}\u{724C}\u{89C6}\u{89C9}\u{89C4}\u{8303}
5552
5921
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{54C1}\u{724C}\u{89C6}\u{89C9}\u{5143}\u{7D20}\u{5728}\u{9875}\u{9762}\u{4E2D}\u{7684}\u{5E94}\u{7528}\u{89C4}\u{8303}\u{FF0C}\u{5982}Logo\u{3001}\u{56FE}\u{6807}\u{7B49}]
5553
5922
 
5554
5923
  ## 5. \u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{8BF4}\u{660E}
@@ -5565,11 +5934,14 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5565
5934
  ### 5.4 \u{8868}\u{5355}\u{9A8C}\u{8BC1}\u{89C4}\u{5219}
5566
5935
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4E2D}\u{8868}\u{5355}\u{5143}\u{7D20}\u{7684}\u{9A8C}\u{8BC1}\u{89C4}\u{5219}\u{548C}\u{9519}\u{8BEF}\u{63D0}\u{793A}]
5567
5936
 
5568
- ### 5.5 \u{4E8B}\u{4EF6}\u{5904}\u{7406}\u{673A}\u{5236}
5569
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4E2D}\u{5404}\u{79CD}\u{7528}\u{6237}\u{4E8B}\u{4EF6}\u{7684}\u{5904}\u{7406}\u{673A}\u{5236}\u{FF0C}\u{5982}\u{70B9}\u{51FB}\u{3001}\u{60AC}\u{505C}\u{3001}\u{952E}\u{76D8}\u{64CD}\u{4F5C}\u{7B49}]
5937
+ ### 5.5 \u{89E6}\u{6478}/\u{624B}\u{52BF}\u{4EA4}\u{4E92}
5938
+ [\u{5982}\u{9002}\u{7528}\u{4E8E}\u{79FB}\u{52A8}\u{7AEF}\u{FF0C}\u{63CF}\u{8FF0}\u{89E6}\u{6478}\u{548C}\u{624B}\u{52BF}\u{4EA4}\u{4E92}\u{8BBE}\u{8BA1}]
5939
+ - **\u{6ED1}\u{52A8}\u{64CD}\u{4F5C}**: [\u{63CF}\u{8FF0}\u{6ED1}\u{52A8}\u{76F8}\u{5173}\u{7684}\u{4EA4}\u{4E92}]
5940
+ - **\u{957F}\u{6309}\u{64CD}\u{4F5C}**: [\u{63CF}\u{8FF0}\u{957F}\u{6309}\u{76F8}\u{5173}\u{7684}\u{4EA4}\u{4E92}]
5941
+ - **\u{4E0B}\u{62C9}\u{5237}\u{65B0}**: [\u{63CF}\u{8FF0}\u{4E0B}\u{62C9}\u{5237}\u{65B0}\u{7684}\u{4EA4}\u{4E92}]
5570
5942
 
5571
- ### 5.6 \u{6570}\u{636E}\u{66F4}\u{65B0}\u{673A}\u{5236}
5572
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4E2D}\u{6570}\u{636E}\u{66F4}\u{65B0}\u{7684}\u{89E6}\u{53D1}\u{6761}\u{4EF6}\u{548C}\u{5904}\u{7406}\u{903B}\u{8F91}]
5943
+ ### 5.6 \u{4E8B}\u{4EF6}\u{5904}\u{7406}\u{673A}\u{5236}
5944
+ [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4E2D}\u{5404}\u{79CD}\u{7528}\u{6237}\u{4E8B}\u{4EF6}\u{7684}\u{5904}\u{7406}\u{673A}\u{5236}]
5573
5945
 
5574
5946
  ### 5.7 \u{9519}\u{8BEF}\u{5904}\u{7406}\u{4E0E}\u{6062}\u{590D}
5575
5947
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{4E2D}\u{9519}\u{8BEF}\u{60C5}\u{51B5}\u{7684}\u{5904}\u{7406}\u{548C}\u{7528}\u{6237}\u{5F15}\u{5BFC}\u{6062}\u{590D}\u{673A}\u{5236}]
@@ -5579,13 +5951,10 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5579
5951
  ### 6.1 \u{4E3B}\u{8981}\u{6570}\u{636E}\u{5B9E}\u{4F53}
5580
5952
  [\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{6D89}\u{53CA}\u{7684}\u{4E3B}\u{8981}\u{6570}\u{636E}\u{5B9E}\u{4F53}]
5581
5953
 
5582
- \u{5B9E}\u{4F53}\u{4E00}
5583
- | | | | | |
5954
+ | **\u{5B57}\u{6BB5}\u{540D}\u{79F0}** | **\u{6570}\u{636E}\u{7C7B}\u{578B}** | **\u{957F}\u{5EA6}** | **\u{5FC5}\u{586B}** | **\u{8BF4}\u{660E}** |
5584
5955
  |---|---|---|---|---|
5585
- |**\u{5B57}\u{6BB5}\u{540D}\u{79F0}**|**\u{6570}\u{636E}\u{7C7B}\u{578B}**|**\u{957F}\u{5EA6}**|**\u{5FC5}\u{586B}**|**\u{8BF4}\u{660E}**|
5586
5956
  |[\u{5B57}\u{6BB5}1]|[\u{7C7B}\u{578B}]|[\u{957F}\u{5EA6}]|[\u{662F}/\u{5426}]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}]|
5587
5957
  |[\u{5B57}\u{6BB5}2]|[\u{7C7B}\u{578B}]|[\u{957F}\u{5EA6}]|[\u{662F}/\u{5426}]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}]|
5588
- |[\u{6DFB}\u{52A0}\u{66F4}\u{591A}\u{76F8}\u{5173}\u{5B57}\u{6BB5}...]|||
5589
5958
 
5590
5959
  ### 6.2 \u{8868}\u{5355}\u{5B57}\u{6BB5}\u{8BF4}\u{660E}
5591
5960
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{9875}\u{9762}\u{8868}\u{5355}\u{4E2D}\u{5404}\u{5B57}\u{6BB5}\u{7684}\u{542B}\u{4E49}\u{3001}\u{683C}\u{5F0F}\u{8981}\u{6C42}\u{3001}\u{9A8C}\u{8BC1}\u{89C4}\u{5219}\u{7B49}]
@@ -5595,12 +5964,10 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5595
5964
 
5596
5965
  ## 7. \u{754C}\u{9762}\u{64CD}\u{4F5C}\u{8BF4}\u{660E}
5597
5966
 
5598
- | | | |
5967
+ | **\u{5E8F}\u{53F7}** | **\u{4E1A}\u{52A1}\u{64CD}\u{4F5C}** | **\u{8BF4}\u{660E}** |
5599
5968
  |---|---|---|
5600
- |**\u{5E8F}\u{53F7}**|**\u{4E1A}\u{52A1}\u{64CD}\u{4F5C}**|**\u{8BF4}\u{660E}**|
5601
5969
  |1|[\u{64CD}\u{4F5C}1]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}\u{64CD}\u{4F5C}\u{89E6}\u{53D1}\u{6761}\u{4EF6}\u{3001}\u{6267}\u{884C}\u{8FC7}\u{7A0B}\u{548C}\u{7ED3}\u{679C}]|
5602
5970
  |2|[\u{64CD}\u{4F5C}2]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}\u{64CD}\u{4F5C}\u{89E6}\u{53D1}\u{6761}\u{4EF6}\u{3001}\u{6267}\u{884C}\u{8FC7}\u{7A0B}\u{548C}\u{7ED3}\u{679C}]|
5603
- |[\u{6DFB}\u{52A0}\u{66F4}\u{591A}\u{64CD}\u{4F5C}...]|
5604
5971
 
5605
5972
  ## 8. \u{7EC4}\u{4EF6}\u{7ED3}\u{6784}\u{8BBE}\u{8BA1}
5606
5973
 
@@ -5622,21 +5989,32 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5622
5989
 
5623
5990
  \`\`\`mermaid
5624
5991
  sequenceDiagram
5992
+ participant User as \u{7528}\u{6237}
5993
+ participant Page as \u{9875}\u{9762}
5994
+ participant API as \u{540E}\u{7AEF}API
5995
+ User->>Page: \u{8BBF}\u{95EE}\u{9875}\u{9762}
5996
+ Page->>API: \u{8BF7}\u{6C42}\u{6570}\u{636E}
5997
+ API-->>Page: \u{8FD4}\u{56DE}\u{6570}\u{636E}
5998
+ Page-->>User: \u{5C55}\u{793A}\u{5185}\u{5BB9}
5625
5999
  \`\`\`
5626
6000
 
5627
- ### 9.2 \u{8FB9}\u{7F18}\u{60C5}\u{51B5}\u{6D41}\u{7A0B}\u{FF08}\u{5E76}\u{53D1}\u{3001}\u{8D85}\u{65F6}\u{7B49}\u{FF09}
6001
+ ### 9.2 \u{8FB9}\u{7F18}\u{60C5}\u{51B5}\u{6D41}\u{7A0B}\u{FF08}\u{9519}\u{8BEF}\u{5904}\u{7406}\u{3001}\u{8D85}\u{65F6}\u{7B49}\u{FF09}
5628
6002
 
5629
- #### 9.2.1 \u{6027}\u{80FD}\u{4F18}\u{5316}\u{8981}\u{6C42}
5630
6003
  \`\`\`mermaid
5631
6004
  sequenceDiagram
6005
+ participant User as \u{7528}\u{6237}
6006
+ participant Page as \u{9875}\u{9762}
6007
+ participant API as \u{540E}\u{7AEF}API
6008
+ User->>Page: \u{63D0}\u{4EA4}\u{8868}\u{5355}
6009
+ Page->>API: \u{53D1}\u{9001}\u{8BF7}\u{6C42}
6010
+ API-->>Page: \u{8FD4}\u{56DE}\u{9519}\u{8BEF}
6011
+ Page-->>User: \u{663E}\u{793A}\u{9519}\u{8BEF}\u{63D0}\u{793A}
5632
6012
  \`\`\`
5633
6013
 
5634
-
5635
6014
  ## 10. \u{4E1A}\u{52A1}\u{72B6}\u{6001}\u{63CF}\u{8FF0}
5636
6015
 
5637
- | | | |
6016
+ | **\u{72B6}\u{6001}\u{7F16}\u{53F7}** | **\u{72B6}\u{6001}\u{540D}\u{79F0}** | **\u{63CF}\u{8FF0}** |
5638
6017
  |---|---|---|
5639
- |**\u{72B6}\u{6001}\u{7F16}\u{53F7}**|**\u{72B6}\u{6001}\u{540D}\u{79F0}**|**\u{63CF}\u{8FF0}**|
5640
6018
  |01|\u{5F85}\u{52A0}\u{8F7D}|\u{9875}\u{9762}\u{521D}\u{59CB}\u{5316}\u{72B6}\u{6001}|
5641
6019
  |02|\u{52A0}\u{8F7D}\u{4E2D}|\u{6570}\u{636E}\u{52A0}\u{8F7D}\u{72B6}\u{6001}|
5642
6020
  |03|\u{6B63}\u{5E38}\u{663E}\u{793A}|\u{9875}\u{9762}\u{6B63}\u{5E38}\u{663E}\u{793A}\u{72B6}\u{6001}|
@@ -5647,174 +6025,19 @@ sequenceDiagram
5647
6025
  |08|\u{63D0}\u{4EA4}\u{4E2D}|\u{8868}\u{5355}\u{63D0}\u{4EA4}\u{5904}\u{7406}\u{4E2D}\u{72B6}\u{6001}|
5648
6026
  |09|\u{63D0}\u{4EA4}\u{6210}\u{529F}|\u{8868}\u{5355}\u{63D0}\u{4EA4}\u{6210}\u{529F}\u{72B6}\u{6001}|
5649
6027
  |10|\u{63D0}\u{4EA4}\u{5931}\u{8D25}|\u{8868}\u{5355}\u{63D0}\u{4EA4}\u{5931}\u{8D25}\u{72B6}\u{6001}|
5650
- |[\u{6DFB}\u{52A0}\u{66F4}\u{591A}\u{72B6}\u{6001}...]||
5651
6028
 
5652
6029
  ## 11. \u{7528}\u{6237}\u{6545}\u{4E8B}
5653
6030
 
5654
6031
  ### 11.1 \u{6545}\u{4E8B}1
5655
6032
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{6545}\u{4E8B}\u{7684}\u{5185}\u{5BB9}\u{FF0C}\u{5305}\u{62EC}\u{4EFB}\u{52A1}\u{5B9A}\u{4E49}\u{3001}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{63CF}\u{8FF0}\u{3001}\u{6280}\u{672F}\u{65B9}\u{6848}\u{5B9E}\u{73B0}\u{7B49}]
6033
+
5656
6034
  ### 11.2 \u{6545}\u{4E8B}2
5657
6035
  [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{6545}\u{4E8B}\u{7684}\u{5185}\u{5BB9}\u{FF0C}\u{5305}\u{62EC}\u{4EFB}\u{52A1}\u{5B9A}\u{4E49}\u{3001}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{63CF}\u{8FF0}\u{3001}\u{6280}\u{672F}\u{65B9}\u{6848}\u{5B9E}\u{73B0}\u{7B49}]
5658
- ...
5659
- ### 11.3 \u{66F4}\u{591A}\u{6545}\u{4E8B}
5660
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}\u{66F4}\u{591A}\u{6545}\u{4E8B}\u{7684}\u{5185}\u{5BB9}\u{FF0C}\u{5305}\u{62EC}\u{4EFB}\u{52A1}\u{5B9A}\u{4E49}\u{3001}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{63CF}\u{8FF0}\u{3001}\u{6280}\u{672F}\u{65B9}\u{6848}\u{5B9E}\u{73B0}\u{7B49}]
5661
- >
5662
-
5663
6036
 
5664
6037
  ---
5665
6038
 
5666
- **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{7AE0}\u{8282}\u{6709}\u{5B9E}\u{8D28}\u{5185}\u{5BB9}\u{FF0C}\u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}\u{FF0C}\u{91CD}\u{70B9}\u{5173}\u{6CE8}\u{9875}\u{9762}\u{5E03}\u{5C40}\u{3001}\u{6837}\u{5F0F}\u{3001}\u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{3002}`;
5667
- const appTemplatePrompt = `\u{4F60}\u{662F}\u{79FB}\u{52A8}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}APP\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}1500\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
5668
-
5669
- **\u{8F93}\u{5165}**: \u{529F}\u{80FD}\u{540D}\u{79F0}={featureName}, \u{4E1A}\u{52A1}\u{9886}\u{57DF}={businessDomain}
5670
-
5671
- **\u{539F}\u{59CB}\u{9700}\u{6C42}**:
5672
- \`\`\`
5673
- {inputContent}
5674
- \`\`\`
5675
-
5676
- ## \u{6587}\u{6863}\u{7ED3}\u{6784}\u{8981}\u{6C42}
5677
- \u{8BF7}\u{4E25}\u{683C}\u{6309}\u{7167}\u{4EE5}\u{4E0B}\u{7ED3}\u{6784}\u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{7684}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{4E2A}\u{7AE0}\u{8282}\u{90FD}\u{8981}\u{6709}\u{8BE6}\u{5B9E}\u{7684}\u{5185}\u{5BB9}\u{FF1A}
5678
-
5679
- # {featureName} - APP\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5680
-
5681
- > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: {currentTime}
5682
- > **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: {businessDomain}
5683
- > **\u{5E94}\u{7528}\u{7C7B}\u{578B}**: \u{79FB}\u{52A8}\u{7AEF}\u{5E94}\u{7528}\u{7A0B}\u{5E8F}
5684
-
5685
- ---
5686
-
5687
- ## 1. \u{9700}\u{6C42}\u{6982}\u{8FF0}
5688
-
5689
- **\u{4E1A}\u{52A1}\u{80CC}\u{666F}**: [\u{63CF}\u{8FF0}APP\u{529F}\u{80FD}\u{80CC}\u{666F}\u{3001}\u{4E1A}\u{52A1}\u{9700}\u{6C42}\u{548C}\u{76EE}\u{6807}]
5690
-
5691
- **\u{6838}\u{5FC3}\u{529F}\u{80FD}**: [\u{5217}\u{51FA}APP\u{7684}\u{4E3B}\u{8981}\u{529F}\u{80FD}\u{70B9}]
5692
-
5693
- ## 2. \u{754C}\u{9762}\u{8BBE}\u{8BA1}
5694
-
5695
- ### 2.1 \u{9875}\u{9762}\u{5E03}\u{5C40}
5696
- [\u{63CF}\u{8FF0}\u{4E3B}\u{8981}\u{9875}\u{9762}\u{7684}\u{5E03}\u{5C40}\u{7ED3}\u{6784}\u{548C}\u{754C}\u{9762}\u{5143}\u{7D20}]
5697
-
5698
- ### 2.2 \u{7528}\u{6237}\u{754C}\u{9762}
5699
- [\u{63CF}\u{8FF0}APP\u{7684}\u{7528}\u{6237}\u{754C}\u{9762}\u{8BBE}\u{8BA1}\u{548C}\u{4EA4}\u{4E92}\u{5143}\u{7D20}]
5700
-
5701
- ## 3. \u{4EA4}\u{4E92}\u{903B}\u{8F91}
5702
-
5703
- ### 3.1 \u{7528}\u{6237}\u{64CD}\u{4F5C}\u{6D41}\u{7A0B}
5704
- [\u{63CF}\u{8FF0}\u{4E3B}\u{8981}\u{7684}\u{7528}\u{6237}\u{64CD}\u{4F5C}\u{6D41}\u{7A0B}\u{548C}\u{5BFC}\u{822A}\u{8DEF}\u{5F84}]
5705
-
5706
- ### 3.2 \u{4EA4}\u{4E92}\u{89C4}\u{5219}
5707
- [\u{63CF}\u{8FF0}APP\u{4E2D}\u{7684}\u{4E3B}\u{8981}\u{4EA4}\u{4E92}\u{89C4}\u{5219}\u{548C}\u{54CD}\u{5E94}\u{673A}\u{5236}]
5708
-
5709
- ## 4. \u{6570}\u{636E}\u{5904}\u{7406}
5710
-
5711
- ### 4.1 \u{6570}\u{636E}\u{5C55}\u{793A}
5712
- [\u{63CF}\u{8FF0}APP\u{4E2D}\u{6570}\u{636E}\u{7684}\u{5C55}\u{793A}\u{65B9}\u{5F0F}\u{548C}\u{683C}\u{5F0F}]
5713
-
5714
- ### 4.2 \u{6570}\u{636E}\u{4EA4}\u{4E92}
5715
- [\u{63CF}\u{8FF0}APP\u{4E0E}\u{540E}\u{7AEF}\u{7684}\u{6570}\u{636E}\u{4EA4}\u{4E92}\u{65B9}\u{5F0F}]
5716
-
5717
- ## 5. \u{529F}\u{80FD}\u{6A21}\u{5757}
5718
-
5719
- ### 5.1 \u{6838}\u{5FC3}\u{6A21}\u{5757}
5720
- [\u{63CF}\u{8FF0}APP\u{7684}\u{6838}\u{5FC3}\u{529F}\u{80FD}\u{6A21}\u{5757}]
5721
-
5722
- ### 5.2 \u{4E1A}\u{52A1}\u{903B}\u{8F91}
5723
- [\u{63CF}\u{8FF0}\u{5404}\u{6A21}\u{5757}\u{7684}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{548C}\u{5904}\u{7406}\u{6D41}\u{7A0B}]
5724
-
5725
- ## 6. \u{4E1A}\u{52A1}\u{6D41}\u{7A0B}
5726
-
5727
- [\u{4F7F}\u{7528}\u{7B80}\u{5355}\u{7684}mermaid\u{6D41}\u{7A0B}\u{56FE}\u{63CF}\u{8FF0}\u{4E3B}\u{8981}\u{4E1A}\u{52A1}\u{6D41}\u{7A0B}]
5728
-
5729
- \`\`\`mermaid
5730
- graph TD
5731
- A[\u{5F00}\u{59CB}] --> B[\u{5904}\u{7406}]
5732
- B --> C[\u{7ED3}\u{675F}]
5733
- \`\`\`
5734
-
5735
- ---
5736
-
5737
- **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{7AE0}\u{8282}\u{6709}\u{5B9E}\u{8D28}\u{5185}\u{5BB9}\u{FF0C}\u{91CD}\u{70B9}\u{5173}\u{6CE8}\u{754C}\u{9762}\u{8BBE}\u{8BA1}\u{3001}\u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{548C}\u{6570}\u{636E}\u{5904}\u{7406}\u{3002}`;
5738
- const sdkTemplatePrompt = `\u{4F60}\u{662F}\u{540E}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}\u{4E09}\u{65B9}SDK\u{96C6}\u{6210}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}1500\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
5739
-
5740
- **\u{8F93}\u{5165}**: \u{529F}\u{80FD}\u{540D}\u{79F0}={featureName}, \u{4E1A}\u{52A1}\u{9886}\u{57DF}={businessDomain}
5741
-
5742
- **\u{539F}\u{59CB}\u{9700}\u{6C42}**:
5743
- \`\`\`
5744
- {inputContent}
5745
- \`\`\`
5746
-
5747
- ## \u{6587}\u{6863}\u{7ED3}\u{6784}\u{8981}\u{6C42}
5748
- \u{8BF7}\u{4E25}\u{683C}\u{6309}\u{7167}\u{4EE5}\u{4E0B}\u{7ED3}\u{6784}\u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{7684}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{4E2A}\u{7AE0}\u{8282}\u{90FD}\u{8981}\u{6709}\u{8BE6}\u{5B9E}\u{7684}\u{5185}\u{5BB9}\u{FF1A}
5749
-
5750
- # {featureName} - \u{4E09}\u{65B9}SDK\u{96C6}\u{6210}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5751
-
5752
- > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: {currentTime}
5753
- > **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: {businessDomain}
5754
- > **\u{96C6}\u{6210}\u{7C7B}\u{578B}**: \u{4E09}\u{65B9}SDK\u{96C6}\u{6210}
5755
-
5756
- ---
5757
-
5758
- ## 1. \u{9700}\u{6C42}\u{6982}\u{8FF0}
5759
-
5760
- **\u{4E1A}\u{52A1}\u{80CC}\u{666F}**: [\u{63CF}\u{8FF0}SDK\u{96C6}\u{6210}\u{7684}\u{80CC}\u{666F}\u{3001}\u{4E1A}\u{52A1}\u{9700}\u{6C42}\u{548C}\u{76EE}\u{6807}]
5761
-
5762
- **\u{6838}\u{5FC3}\u{529F}\u{80FD}**: [\u{5217}\u{51FA}SDK\u{96C6}\u{6210}\u{7684}\u{4E3B}\u{8981}\u{529F}\u{80FD}\u{70B9}]
5763
-
5764
- ## 2. SDK\u{96C6}\u{6210}\u{8BBE}\u{8BA1}
5765
-
5766
- ### 2.1 \u{63A5}\u{5165}\u{6D41}\u{7A0B}
5767
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}SDK\u{63A5}\u{5165}\u{7684}\u{51C6}\u{5907}\u{5DE5}\u{4F5C}\u{548C}\u{914D}\u{7F6E}\u{6D41}\u{7A0B}]
5768
-
5769
- ### 2.2 \u{521D}\u{59CB}\u{5316}\u{914D}\u{7F6E}
5770
- [\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}SDK\u{7684}\u{521D}\u{59CB}\u{5316}\u{914D}\u{7F6E}\u{8FC7}\u{7A0B}]
5771
-
5772
- ## 3. \u{63A5}\u{53E3}\u{8C03}\u{7528}\u{8BF4}\u{660E}
5773
-
5774
- ### 3.1 \u{4E3B}\u{8981}API\u{63A5}\u{53E3}
5775
- [\u{5217}\u{51FA}SDK\u{63D0}\u{4F9B}\u{7684}\u{4E3B}\u{8981}API\u{63A5}\u{53E3}]
5776
-
5777
- ### 3.2 \u{63A5}\u{53E3}\u{8C03}\u{7528}\u{793A}\u{4F8B}
5778
- [\u{63D0}\u{4F9B}\u{8BE6}\u{7EC6}\u{7684}\u{63A5}\u{53E3}\u{8C03}\u{7528}\u{793A}\u{4F8B}\u{4EE3}\u{7801}]
5779
-
5780
- ### 3.3 \u{53C2}\u{6570}\u{8BF4}\u{660E}
5781
- [\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}\u{5404}\u{63A5}\u{53E3}\u{7684}\u{8BF7}\u{6C42}\u{53C2}\u{6570}\u{548C}\u{54CD}\u{5E94}\u{6570}\u{636E}\u{7ED3}\u{6784}]
5782
-
5783
- |\u{53C2}\u{6570}\u{540D}\u{79F0}|\u{7C7B}\u{578B}|\u{662F}\u{5426}\u{5FC5}\u{586B}|\u{8BF4}\u{660E}|
5784
- |------|------|------|------|
5785
- |[\u{53C2}\u{6570}1]|[string/number\u{7B49}]|[\u{662F}/\u{5426}]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}]|
5786
- |[\u{53C2}\u{6570}2]|[string/number\u{7B49}]|[\u{662F}/\u{5426}]|[\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}]|
5787
-
5788
- ## 4. \u{4EA4}\u{4E92}\u{903B}\u{8F91}
5789
-
5790
- ### 4.1 \u{8C03}\u{7528}\u{65F6}\u{5E8F}
5791
- [\u{63CF}\u{8FF0}SDK\u{8C03}\u{7528}\u{7684}\u{65F6}\u{5E8F}\u{903B}\u{8F91}]
5792
-
5793
- ### 4.2 \u{9519}\u{8BEF}\u{5904}\u{7406}
5794
- [\u{63CF}\u{8FF0}SDK\u{8C03}\u{7528}\u{5F02}\u{5E38}\u{7684}\u{5904}\u{7406}\u{903B}\u{8F91}]
5795
-
5796
- ## 5. \u{5B89}\u{5168}\u{4E0E}\u{6027}\u{80FD}
5797
-
5798
- ### 5.1 \u{5B89}\u{5168}\u{6027}\u{8003}\u{8651}
5799
- [\u{63CF}\u{8FF0}\u{6570}\u{636E}\u{52A0}\u{5BC6}\u{3001}\u{8BBF}\u{95EE}\u{63A7}\u{5236}\u{7B49}\u{5B89}\u{5168}\u{8981}\u{6C42}]
5800
-
5801
- ### 5.2 \u{6027}\u{80FD}\u{4F18}\u{5316}
5802
- [\u{63CF}\u{8FF0}SDK\u{8C03}\u{7528}\u{7684}\u{6027}\u{80FD}\u{8981}\u{6C42}\u{548C}\u{4F18}\u{5316}\u{7B56}\u{7565}]
5803
-
5804
- ## 6. \u{4E1A}\u{52A1}\u{6D41}\u{7A0B}
5805
-
5806
- [\u{4F7F}\u{7528}\u{7B80}\u{5355}\u{7684}mermaid\u{6D41}\u{7A0B}\u{56FE}\u{63CF}\u{8FF0}\u{4E3B}\u{8981}\u{4E1A}\u{52A1}\u{6D41}\u{7A0B}]
5807
-
5808
- \`\`\`mermaid
5809
- graph TD
5810
- A[\u{5F00}\u{59CB}] --> B[\u{5904}\u{7406}]
5811
- B --> C[\u{7ED3}\u{675F}]
5812
- \`\`\`
5813
-
5814
- ---
5815
-
5816
- **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{7AE0}\u{8282}\u{6709}\u{5B9E}\u{8D28}\u{5185}\u{5BB9}\u{FF0C}\u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}\u{FF0C}\u{91CD}\u{70B9}\u{5173}\u{6CE8}SDK\u{63A5}\u{5165}\u{6D41}\u{7A0B}\u{3001}\u{63A5}\u{53E3}\u{8C03}\u{7528}\u{548C}\u{6570}\u{636E}\u{7ED3}\u{6784}\u{3002}`;
5817
- const apiTemplatePrompt = `\u{4F60}\u{662F}\u{540E}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}API\u{63A5}\u{53E3}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}3000\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
6039
+ **\u{8981}\u{6C42}**: \u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{6587}\u{6863}\u{FF0C}\u{6BCF}\u{7AE0}\u{8282}\u{6709}\u{5B9E}\u{8D28}\u{5185}\u{5BB9}\u{FF0C}\u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}\u{FF0C}\u{91CD}\u{70B9}\u{5173}\u{6CE8}\u{9875}\u{9762}\u{5E03}\u{5C40}\u{3001}\u{6837}\u{5F0F}\u{3001}\u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{3002}\u{6839}\u{636E}pageType\u{8C03}\u{6574}\u{5185}\u{5BB9}\u{4FA7}\u{91CD}\u{70B9}\u{3002}`;
6040
+ const api_template_apiTemplatePrompt = `\u{4F60}\u{662F}\u{540E}\u{7AEF}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{57FA}\u{4E8E}\u{8F93}\u{5165}\u{5185}\u{5BB9}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}API\u{63A5}\u{53E3}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF08}Markdown\u{683C}\u{5F0F}\u{FF0C}3000\u{5B57}\u{4EE5}\u{4E0A}\u{FF09}\u{3002}
5818
6041
 
5819
6042
  **\u{8F93}\u{5165}**: \u{529F}\u{80FD}\u{540D}\u{79F0}={featureName}, \u{4E1A}\u{52A1}\u{9886}\u{57DF}={businessDomain}, \u{751F}\u{6210}\u{65F6}\u{5E8F}\u{56FE}={generateSequenceDiagram}
5820
6043
 
@@ -6007,36 +6230,28 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6007
6230
  class TemplateSelector {
6008
6231
  templateMap = new Map([
6009
6232
  [
6010
- "PC\u9875\u9762",
6011
- pcPageTemplatePrompt
6012
- ],
6013
- [
6014
- "APP",
6015
- appTemplatePrompt
6233
+ "HTML",
6234
+ htmlPageTemplatePrompt
6016
6235
  ],
6017
6236
  [
6018
- "SDK\u96C6\u6210",
6019
- sdkTemplatePrompt
6237
+ "html",
6238
+ htmlPageTemplatePrompt
6020
6239
  ],
6021
6240
  [
6022
- "\u63A5\u53E3",
6023
- apiTemplatePrompt
6241
+ "API",
6242
+ api_template_apiTemplatePrompt
6024
6243
  ],
6025
6244
  [
6026
6245
  "api",
6027
- apiTemplatePrompt
6028
- ],
6029
- [
6030
- "pc",
6031
- pcPageTemplatePrompt
6246
+ api_template_apiTemplatePrompt
6032
6247
  ],
6033
6248
  [
6034
- "app",
6035
- appTemplatePrompt
6249
+ "\u63A5\u53E3",
6250
+ api_template_apiTemplatePrompt
6036
6251
  ],
6037
6252
  [
6038
- "sdk",
6039
- sdkTemplatePrompt
6253
+ "\u9875\u9762",
6254
+ htmlPageTemplatePrompt
6040
6255
  ]
6041
6256
  ]);
6042
6257
  selectTemplate(requirementType) {
@@ -6081,33 +6296,18 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6081
6296
  "ui",
6082
6297
  "\u7F51\u9875",
6083
6298
  "\u6D4F\u89C8\u5668",
6084
- "\u524D\u7AEF"
6085
- ])) return {
6086
- type: "PC\u9875\u9762",
6087
- template: pcPageTemplatePrompt
6088
- };
6089
- if (this.containsAny(lowerType, [
6299
+ "\u524D\u7AEF",
6300
+ "html",
6090
6301
  "app",
6091
6302
  "\u79FB\u52A8",
6092
6303
  "ios",
6093
6304
  "android",
6094
6305
  "\u5C0F\u7A0B\u5E8F",
6095
- "\u79FB\u52A8\u7AEF"
6306
+ "\u79FB\u52A8\u7AEF",
6307
+ "\u54CD\u5E94\u5F0F"
6096
6308
  ])) return {
6097
- type: "APP",
6098
- template: appTemplatePrompt
6099
- };
6100
- if (this.containsAny(lowerType, [
6101
- "sdk",
6102
- "\u7B2C\u4E09\u65B9",
6103
- "\u96C6\u6210",
6104
- "\u5BF9\u63A5",
6105
- "\u652F\u4ED8",
6106
- "\u5730\u56FE",
6107
- "\u63A8\u9001"
6108
- ])) return {
6109
- type: "SDK\u96C6\u6210",
6110
- template: sdkTemplatePrompt
6309
+ type: "HTML",
6310
+ template: htmlPageTemplatePrompt
6111
6311
  };
6112
6312
  if (this.containsAny(lowerType, [
6113
6313
  "\u63A5\u53E3",
@@ -6119,7 +6319,7 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6119
6319
  "\u670D\u52A1\u7AEF"
6120
6320
  ])) return {
6121
6321
  type: "\u63A5\u53E3",
6122
- template: apiTemplatePrompt
6322
+ template: api_template_apiTemplatePrompt
6123
6323
  };
6124
6324
  return null;
6125
6325
  }
@@ -6175,9 +6375,9 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6175
6375
  }
6176
6376
  return null;
6177
6377
  }
6178
- saveToCache(cacheKey, document) {
6378
+ saveToCache(cacheKey, document1) {
6179
6379
  DocumentGenerator.cache.set(cacheKey, {
6180
- document,
6380
+ document: document1,
6181
6381
  timestamp: Date.now()
6182
6382
  });
6183
6383
  logger.info("\u6587\u6863\u5DF2\u4FDD\u5B58\u5230\u7F13\u5B58", {
@@ -6195,7 +6395,7 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6195
6395
  cleanedCount
6196
6396
  });
6197
6397
  }
6198
- async generateUnifiedDocument(analysis, projectInfo, featureName, sourceInfo, customPrompt, currentProjectPath) {
6398
+ async generateUnifiedDocument(analysis, projectInfo, featureName, sourceInfo, customPrompt, currentProjectPath, pageStyle, pageType) {
6199
6399
  try {
6200
6400
  logger.info("\u51C6\u5907\u751F\u6210\u7EDF\u4E00\u6280\u672F\u6587\u6863\u4EFB\u52A1", {
6201
6401
  featureName,
@@ -6203,7 +6403,10 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6203
6403
  featureCount: analysis.requirements.length,
6204
6404
  currentProjectPath
6205
6405
  });
6206
- const requirementTypes = this.parseRequirementTypes(analysis.requirementType);
6406
+ const requirementTypes = [
6407
+ "API",
6408
+ "HTML"
6409
+ ];
6207
6410
  const generationTasks = await Promise.all(requirementTypes.map(async (reqType)=>{
6208
6411
  logger.info("\u51C6\u5907\u62A5\u544A\u751F\u6210\u4EFB\u52A1", {
6209
6412
  requirementType: reqType,
@@ -6227,13 +6430,19 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6227
6430
  prompt: promptData.prompt,
6228
6431
  systemPrompt: promptData.systemPrompt,
6229
6432
  templateContent: promptData.templateContent,
6230
- templateVariables: "templateVariables" in promptData ? promptData.templateVariables : {
6433
+ templateVariables: "templateVariables" in promptData ? {
6434
+ ...promptData.templateVariables,
6435
+ pageStyle,
6436
+ pageType: pageType || "responsive"
6437
+ } : {
6231
6438
  featureName: featureName,
6232
6439
  inputContent: this.buildUnifiedContent(analysis, projectInfo, featureName, sourceInfo),
6233
6440
  currentTime: new Date().toISOString(),
6234
6441
  businessDomain: this.mapRequirementTypeToBusinessDomain(reqType),
6235
6442
  generateSequenceDiagram: "true",
6236
- customPrompt
6443
+ customPrompt,
6444
+ pageStyle,
6445
+ pageType: pageType || "responsive"
6237
6446
  },
6238
6447
  existingContent: "existingContent" in promptData ? promptData.existingContent : void 0
6239
6448
  };
@@ -6306,18 +6515,72 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6306
6515
  }
6307
6516
  buildUnifiedContent(analysis, projectInfo, featureName, sourceInfo) {
6308
6517
  const featuresToProcess = analysis.featureDependencies?.mergedFeatures || analysis.requirements;
6518
+ const enrichedContext = analysis.enrichedContext || {};
6519
+ const businessContext = analysis.businessContext || {};
6520
+ const technicalContext = analysis.technicalContext || {};
6521
+ const documentationHints = analysis.documentationHints || {};
6309
6522
  const combinedFeatureContent = featuresToProcess.map((feature, index)=>{
6310
6523
  const featureTitle = "title" in feature ? feature.title : feature.featureName;
6311
6524
  const featureContent = "fullContent" in feature ? feature.fullContent : feature.description;
6312
- return `## \u{529F}\u{80FD}\u{70B9}${index + 1}\u{FF1A}${featureTitle}\n\n${featureContent}`;
6313
- }).join("\n\n");
6525
+ const businessFlow = feature.businessFlow || {};
6526
+ const dataEntities = feature.dataEntities || [];
6527
+ const interactions = feature.interactions || [];
6528
+ let content = `## \u{529F}\u{80FD}\u{70B9}${index + 1}\u{FF1A}${featureTitle}\n\n${featureContent}`;
6529
+ if (businessFlow.mainFlow?.length > 0) {
6530
+ content += `
6531
+
6532
+ ### \u{4E1A}\u{52A1}\u{6D41}\u{7A0B}
6533
+ `;
6534
+ if (businessFlow.preconditions?.length > 0) content += `**\u{524D}\u{7F6E}\u{6761}\u{4EF6}**: ${businessFlow.preconditions.join("\u3001")}\n`;
6535
+ content += `**\u{4E3B}\u{6D41}\u{7A0B}**:
6536
+ ${businessFlow.mainFlow.map((step, i)=>`${i + 1}. ${step}`).join("\n")}\n`;
6537
+ if (businessFlow.exceptionFlows?.length > 0) content += `**\u{5F02}\u{5E38}\u{5904}\u{7406}**: ${businessFlow.exceptionFlows.join("\u3001")}\n`;
6538
+ }
6539
+ if (dataEntities.length > 0) {
6540
+ content += `
6541
+
6542
+ ### \u{6570}\u{636E}\u{5B9E}\u{4F53}
6543
+ `;
6544
+ dataEntities.forEach((entity)=>{
6545
+ content += `**${entity.name}**:\n`;
6546
+ if (entity.fields?.length > 0) {
6547
+ content += `| \u{5B57}\u{6BB5}\u{540D} | \u{7C7B}\u{578B} | \u{5FC5}\u{586B} | \u{8BF4}\u{660E} |
6548
+ |---|---|---|---|
6549
+ `;
6550
+ entity.fields.forEach((field)=>{
6551
+ content += `| ${field.name} | ${field.type} | ${field.required ? "\u662F" : "\u5426"} | ${field.description} |\n`;
6552
+ });
6553
+ }
6554
+ });
6555
+ }
6556
+ if (interactions.length > 0) {
6557
+ content += `
6558
+
6559
+ ### \u{4EA4}\u{4E92}\u{903B}\u{8F91}
6560
+ `;
6561
+ interactions.forEach((interaction)=>{
6562
+ content += `- **\u{89E6}\u{53D1}**: ${interaction.trigger} \u{2192} **\u{52A8}\u{4F5C}**: ${interaction.action} \u{2192} **\u{54CD}\u{5E94}**: ${interaction.response}\n`;
6563
+ });
6564
+ }
6565
+ return content;
6566
+ }).join("\n\n---\n\n");
6314
6567
  return `# ${featureName} - \u{7EDF}\u{4E00}\u{9700}\u{6C42}\u{5206}\u{6790}
6315
6568
 
6316
6569
  ## \u{9879}\u{76EE}\u{57FA}\u{672C}\u{4FE1}\u{606F}
6317
6570
  - **\u{9879}\u{76EE}\u{7C7B}\u{578B}**: ${projectInfo?.projectType || "\u901A\u7528\u9879\u76EE"}
6318
- - **\u{4E3B}\u{8981}\u{6280}\u{672F}\u{6808}**: ${projectInfo?.techStack?.join(", ") || "\u5F85\u786E\u5B9A"}
6571
+ - **\u{4E3B}\u{8981}\u{6280}\u{672F}\u{6808}**: ${projectInfo?.techStack?.join(", ") || enrichedContext.techStack?.join(", ") || "\u5F85\u786E\u5B9A"}
6319
6572
  - **\u{5F00}\u{53D1}\u{6846}\u{67B6}**: ${projectInfo?.frameworks?.join(", ") || "\u5F85\u786E\u5B9A"}
6320
6573
  - **\u{7F16}\u{7A0B}\u{8BED}\u{8A00}**: ${projectInfo?.language || "\u5F85\u786E\u5B9A"}
6574
+ - **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: ${enrichedContext.businessDomain || "\u901A\u7528"}
6575
+
6576
+ ## \u{4E1A}\u{52A1}\u{80CC}\u{666F}
6577
+ ${businessContext.background || "\u57FA\u4E8E\u7528\u6237\u9700\u6C42\u8FDB\u884C\u529F\u80FD\u5F00\u53D1"}
6578
+
6579
+ ### \u{4E1A}\u{52A1}\u{76EE}\u{6807}
6580
+ ${businessContext.objectives?.map((obj)=>`- ${obj}`).join("\n") || "- \u6EE1\u8DB3\u7528\u6237\u9700\u6C42\n- \u63D0\u5347\u7CFB\u7EDF\u529F\u80FD"}
6581
+
6582
+ ### \u{6D89}\u{53CA}\u{89D2}\u{8272}
6583
+ ${businessContext.stakeholders?.map((role)=>`- ${role}`).join("\n") || "- \u7CFB\u7EDF\u7528\u6237\n- \u7CFB\u7EDF\u7BA1\u7406\u5458"}
6321
6584
 
6322
6585
  ## \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{5206}\u{6790}
6323
6586
  - **\u{8BC6}\u{522B}\u{7C7B}\u{578B}**: ${analysis.requirementType}
@@ -6325,6 +6588,17 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6325
6588
  - **\u{529F}\u{80FD}\u{70B9}\u{6570}\u{91CF}**: ${featuresToProcess.length}\u{4E2A}
6326
6589
  - **\u{7F6E}\u{4FE1}\u{5EA6}**: ${analysis.confidence || "medium"}
6327
6590
 
6591
+ ## \u{6280}\u{672F}\u{4E0A}\u{4E0B}\u{6587}
6592
+ - **\u{5EFA}\u{8BAE}\u{6280}\u{672F}\u{6808}**: ${technicalContext.suggestedTechStack?.join(", ") || "\u6839\u636E\u9879\u76EE\u73B0\u6709\u6280\u672F\u6808"}
6593
+ - **\u{96C6}\u{6210}\u{70B9}**: ${technicalContext.integrationPoints?.join(", ") || "\u65E0"}
6594
+ - **\u{5B89}\u{5168}\u{8981}\u{6C42}**: ${technicalContext.securityRequirements?.join(", ") || "\u6807\u51C6\u5B89\u5168\u89C4\u8303"}
6595
+ - **\u{6027}\u{80FD}\u{8981}\u{6C42}**: ${technicalContext.performanceRequirements?.join(", ") || "\u6807\u51C6\u6027\u80FD\u8981\u6C42"}
6596
+
6597
+ ## \u{6587}\u{6863}\u{751F}\u{6210}\u{63D0}\u{793A}
6598
+ - **\u{9700}\u{8981}\u{7684}\u{65F6}\u{5E8F}\u{56FE}**: ${documentationHints.keySequenceDiagrams?.join(", ") || "\u4E3B\u6D41\u7A0B\u65F6\u5E8F\u56FE"}
6599
+ - **\u{9700}\u{8981}\u{7684}ER\u{56FE}**: ${documentationHints.keyERDiagrams?.join(", ") || "\u6838\u5FC3\u6570\u636E\u5B9E\u4F53"}
6600
+ - **\u{9700}\u{8981}\u{7684}\u{8868}\u{683C}**: ${documentationHints.keyTables?.join(", ") || "\u5B57\u6BB5\u8BF4\u660E\u8868\u3001\u63A5\u53E3\u53C2\u6570\u8868"}
6601
+
6328
6602
  ## \u{529F}\u{80FD}\u{70B9}\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}
6329
6603
 
6330
6604
  ${combinedFeatureContent}
@@ -6337,19 +6611,19 @@ ${combinedFeatureContent}
6337
6611
  async generateDocument(content, title, requirementType, projectInfo, customPrompt, outputPath) {
6338
6612
  try {
6339
6613
  const cacheKey = this.generateCacheKey(content, requirementType, customPrompt);
6340
- let document = this.getCachedDocument(cacheKey);
6341
- if (document) {
6614
+ let document1 = this.getCachedDocument(cacheKey);
6615
+ if (document1) {
6342
6616
  logger.info("\u4F7F\u7528\u7F13\u5B58\u7684\u6587\u6863", {
6343
6617
  title,
6344
6618
  requirementType
6345
6619
  });
6346
- return document;
6620
+ return document1;
6347
6621
  }
6348
6622
  const template = this.templateSelector.selectTemplate(requirementType);
6349
6623
  this.templateSelector.validateTemplate(template, requirementType);
6350
6624
  const fullPrompt = this.buildDocumentPrompt(template, content, title, projectInfo, customPrompt, requirementType);
6351
6625
  if (outputPath) try {
6352
- document = await this.generateDocumentStream(fullPrompt, outputPath, title, "", {
6626
+ document1 = await this.generateDocumentStream(fullPrompt, outputPath, title, "", {
6353
6627
  realTimeMode: true
6354
6628
  });
6355
6629
  } catch (streamError) {
@@ -6357,18 +6631,18 @@ ${combinedFeatureContent}
6357
6631
  error: streamError,
6358
6632
  requirementType
6359
6633
  });
6360
- document = await openAIService.generateText({
6634
+ document1 = await openAIService.generateText({
6361
6635
  prompt: fullPrompt,
6362
6636
  system_prompt: "\u4F60\u662F\u4E00\u4F4D\u4E13\u4E1A\u7684\u6280\u672F\u6587\u6863\u7F16\u5199\u4E13\u5BB6\uFF0C\u8BF7\u751F\u6210\u5B8C\u6574\u3001\u8BE6\u7EC6\u7684\u6280\u672F\u9700\u6C42\u6587\u6863\u3002"
6363
6637
  });
6364
6638
  }
6365
- else document = await openAIService.generateText({
6639
+ else document1 = await openAIService.generateText({
6366
6640
  prompt: fullPrompt,
6367
6641
  system_prompt: "\u4F60\u662F\u4E00\u4F4D\u4E13\u4E1A\u7684\u6280\u672F\u6587\u6863\u7F16\u5199\u4E13\u5BB6\uFF0C\u8BF7\u751F\u6210\u5B8C\u6574\u3001\u8BE6\u7EC6\u7684\u6280\u672F\u9700\u6C42\u6587\u6863\u3002"
6368
6642
  });
6369
- this.validateGeneratedDocument(document, title);
6370
- this.saveToCache(cacheKey, document);
6371
- return document;
6643
+ this.validateGeneratedDocument(document1, title);
6644
+ this.saveToCache(cacheKey, document1);
6645
+ return document1;
6372
6646
  } catch (error) {
6373
6647
  logger.error("\u6280\u672F\u6587\u6863\u751F\u6210\u5931\u8D25", {
6374
6648
  error,
@@ -6656,9 +6930,9 @@ ${existingContent}
6656
6930
 
6657
6931
  \u{8BF7}\u{7EE7}\u{7EED}\u{751F}\u{6210}\u{FF1A}`;
6658
6932
  }
6659
- isDocumentComplete(document) {
6660
- const hasEnding = document.includes("## \u66F4\u65B0\u65E5\u5FD7") || document.includes("---\n\n**") || document.trim().endsWith("---") || document.trim().endsWith("\u3002") || document.trim().endsWith("\uFF09");
6661
- const hasReasonableLength = document.length >= 1000;
6933
+ isDocumentComplete(document1) {
6934
+ const hasEnding = document1.includes("## \u66F4\u65B0\u65E5\u5FD7") || document1.includes("---\n\n**") || document1.trim().endsWith("---") || document1.trim().endsWith("\u3002") || document1.trim().endsWith("\uFF09");
6935
+ const hasReasonableLength = document1.length >= 1000;
6662
6936
  return hasEnding && hasReasonableLength;
6663
6937
  }
6664
6938
  async continueDocumentGeneration(originalPrompt, existingContent, outputPath) {
@@ -6853,15 +7127,15 @@ ${customPrompt}` : ""}
6853
7127
  });
6854
7128
  }
6855
7129
  }
6856
- validateGeneratedDocument(document, title) {
6857
- if (!document || document.trim().length < 100) throw new RequirementAnalysisError("\u751F\u6210\u7684\u6280\u672F\u6587\u6863\u5185\u5BB9\u8FC7\u77ED\uFF0C\u53EF\u80FD\u5B58\u5728\u95EE\u9898", types_ErrorCodes.DOCUMENT_GENERATION_FAILED, {
7130
+ validateGeneratedDocument(document1, title) {
7131
+ if (!document1 || document1.trim().length < 100) throw new RequirementAnalysisError("\u751F\u6210\u7684\u6280\u672F\u6587\u6863\u5185\u5BB9\u8FC7\u77ED\uFF0C\u53EF\u80FD\u5B58\u5728\u95EE\u9898", types_ErrorCodes.DOCUMENT_GENERATION_FAILED, {
6858
7132
  title,
6859
- documentLength: document?.length || 0
7133
+ documentLength: document1?.length || 0
6860
7134
  });
6861
- if (!document.includes(title)) logger.warn("\u751F\u6210\u7684\u6587\u6863\u53EF\u80FD\u4E0E\u9700\u6C42\u6807\u9898\u4E0D\u5339\u914D", {
7135
+ if (!document1.includes(title)) logger.warn("\u751F\u6210\u7684\u6587\u6863\u53EF\u80FD\u4E0E\u9700\u6C42\u6807\u9898\u4E0D\u5339\u914D", {
6862
7136
  title
6863
7137
  });
6864
- if (document.includes("## 3.1 ER\u903B\u8F91\u56FE\u8BBE\u8BA1") && !document.includes("erDiagram") && !document.includes("entity")) logger.warn("\u751F\u6210\u7684\u6587\u6863\u53EF\u80FD\u7F3A\u5C11ER\u56FE\u5185\u5BB9", {
7138
+ if (document1.includes("## 3.1 ER\u903B\u8F91\u56FE\u8BBE\u8BA1") && !document1.includes("erDiagram") && !document1.includes("entity")) logger.warn("\u751F\u6210\u7684\u6587\u6863\u53EF\u80FD\u7F3A\u5C11ER\u56FE\u5185\u5BB9", {
6865
7139
  title
6866
7140
  });
6867
7141
  }
@@ -7010,14 +7284,14 @@ ${generationTasks?.map((task, i)=>`
7010
7284
  async analyzeRequirements(params) {
7011
7285
  try {
7012
7286
  logger.info("\u5F00\u59CB\u9700\u6C42\u5206\u6790\u6D41\u7A0B", {
7013
- requirementType: params.requirement_type,
7014
- projectPath: params.current_project_path
7287
+ projectPath: params.current_project_path,
7288
+ hasPageStyle: !!params.page_style
7015
7289
  });
7016
- const { requirementContent, projectInfo } = this.parseRequirementAnalysis(params.requirement_analysis);
7290
+ const { requirementContent, projectInfo, enrichedContext } = this.parseRequirementAnalysis(params.requirement_analysis);
7017
7291
  const requirementAnalysis = await this.intelligentAnalyzer.analyzeRequirements(requirementContent, projectInfo, void 0);
7018
- const finalRequirementType = params.requirement_type || requirementAnalysis.requirementType;
7019
- requirementAnalysis.requirementType = finalRequirementType;
7020
- return await this.documentGenerator.generateUnifiedDocument(requirementAnalysis, projectInfo, this.extractFeatureName(requirementContent), "requirement-identifier\u5206\u6790\u7ED3\u679C", void 0, params.current_project_path);
7292
+ requirementAnalysis.requirementType = "PC+API";
7293
+ requirementAnalysis.enrichedContext = enrichedContext;
7294
+ return await this.documentGenerator.generateUnifiedDocument(requirementAnalysis, projectInfo, this.extractFeatureName(requirementContent), "requirement-identifier\u5206\u6790\u7ED3\u679C", void 0, params.current_project_path, params.page_style, params.page_type);
7021
7295
  } catch (error) {
7022
7296
  if (error instanceof RequirementAnalysisError) throw error;
7023
7297
  logger.error("\u9700\u6C42\u5206\u6790\u6D41\u7A0B\u5931\u8D25", {
@@ -7033,15 +7307,32 @@ ${generationTasks?.map((task, i)=>`
7033
7307
  parseRequirementAnalysis(analysisResult) {
7034
7308
  try {
7035
7309
  const parsed = JSON.parse(analysisResult);
7310
+ const enrichedContext = {
7311
+ originalRequirement: parsed.requirement_description || parsed.data?.guidance || "",
7312
+ techStack: parsed.project_context?.techStack || [],
7313
+ codeStructure: parsed.project_context?.codeStructure || {},
7314
+ businessDomain: parsed.project_context?.businessDomain || "\u901A\u7528",
7315
+ relatedFiles: parsed.project_context?.relatedFiles || [],
7316
+ dependencies: parsed.project_context?.dependencies || []
7317
+ };
7036
7318
  return {
7037
7319
  requirementContent: parsed.requirement_description || parsed.data?.guidance || analysisResult,
7038
- projectInfo: parsed.project_context || this.getDefaultProjectInfo()
7320
+ projectInfo: parsed.project_context || this.getDefaultProjectInfo(),
7321
+ enrichedContext
7039
7322
  };
7040
7323
  } catch {
7041
7324
  logger.info("\u4F7F\u7528\u6587\u672C\u683C\u5F0F\u7684\u9700\u6C42\u5206\u6790\u7ED3\u679C");
7042
7325
  return {
7043
7326
  requirementContent: analysisResult,
7044
- projectInfo: this.getDefaultProjectInfo()
7327
+ projectInfo: this.getDefaultProjectInfo(),
7328
+ enrichedContext: {
7329
+ originalRequirement: analysisResult,
7330
+ techStack: [],
7331
+ codeStructure: {},
7332
+ businessDomain: "\u901A\u7528",
7333
+ relatedFiles: [],
7334
+ dependencies: []
7335
+ }
7045
7336
  };
7046
7337
  }
7047
7338
  }
@@ -7170,23 +7461,178 @@ ${generationTasks?.map((task, i)=>`
7170
7461
  };
7171
7462
  }
7172
7463
  }
7464
+ const DEFAULT_PAGE_STYLE = `<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
7465
+ <style>
7466
+ :root {
7467
+ --bg: #ffffff;
7468
+ --bg-secondary: #f8f9fa;
7469
+ --border: #e5e5e5;
7470
+ --text: #111111;
7471
+ --text-muted: #666666;
7472
+ --accent: #000000;
7473
+ }
7474
+ </style>`;
7475
+ const API_SECTIONS = [
7476
+ {
7477
+ id: "header",
7478
+ title: "\u6587\u6863\u5934\u90E8",
7479
+ prompt: "\u751F\u6210\u6587\u6863\u6807\u9898\u3001\u751F\u6210\u65F6\u95F4\u3001\u4E1A\u52A1\u9886\u57DF\u7B49\u5934\u90E8\u4FE1\u606F"
7480
+ },
7481
+ {
7482
+ id: "background",
7483
+ title: "\u9700\u6C42\u80CC\u666F",
7484
+ prompt: "\u751F\u6210\u9700\u6C42\u80CC\u666F\u3001\u5173\u952E\u529F\u80FD\u3001\u6D89\u53CA\u89D2\u8272"
7485
+ },
7486
+ {
7487
+ id: "design",
7488
+ title: "\u529F\u80FD\u8BBE\u8BA1\u8BF4\u660E",
7489
+ prompt: "\u751F\u6210\u529F\u80FD\u8BBE\u8BA1\u8BF4\u660E\u8868\u683C\uFF0C\u5305\u542B\u6D41\u7A0B\u7F16\u53F7\u3001\u524D\u7F6E\u6761\u4EF6\u3001\u89D2\u8272\u7B49"
7490
+ },
7491
+ {
7492
+ id: "dataModel",
7493
+ title: "\u6570\u636E\u5EFA\u6A21",
7494
+ prompt: "\u751F\u6210ER\u903B\u8F91\u56FE\u8BBE\u8BA1\uFF08\u4F7F\u7528mermaid erDiagram\uFF09\u548C\u6570\u636E\u8868\u5B9E\u4F53\u8BBE\u8BA1"
7495
+ },
7496
+ {
7497
+ id: "apiDesign",
7498
+ title: "API\u63A5\u53E3\u8BBE\u8BA1",
7499
+ prompt: "\u751F\u6210API\u63A5\u53E3\u5217\u8868\u3001\u8BF7\u6C42\u53C2\u6570\u3001\u54CD\u5E94\u53C2\u6570\u3001\u9519\u8BEF\u7801\u7B49"
7500
+ },
7501
+ {
7502
+ id: "sequence",
7503
+ title: "\u4E1A\u52A1\u65F6\u5E8F\u56FE",
7504
+ prompt: "\u751F\u6210\u4E1A\u52A1\u5BF9\u8C61\u65F6\u5E8F\u56FE\uFF08\u4F7F\u7528mermaid sequenceDiagram\uFF09"
7505
+ },
7506
+ {
7507
+ id: "status",
7508
+ title: "\u4E1A\u52A1\u72B6\u6001",
7509
+ prompt: "\u751F\u6210\u4E1A\u52A1\u72B6\u6001\u63CF\u8FF0\u8868\u683C"
7510
+ },
7511
+ {
7512
+ id: "pseudocode",
7513
+ title: "\u4F2A\u4EE3\u7801\u793A\u4F8B",
7514
+ prompt: "\u751F\u6210\u6838\u5FC3\u4E1A\u52A1\u903B\u8F91\u7684\u4F2A\u4EE3\u7801\u793A\u4F8B"
7515
+ }
7516
+ ];
7517
+ class ConcurrencyLimiter {
7518
+ maxConcurrent;
7519
+ running = 0;
7520
+ queue = [];
7521
+ constructor(maxConcurrent){
7522
+ this.maxConcurrent = maxConcurrent;
7523
+ }
7524
+ async run(fn) {
7525
+ while(this.running >= this.maxConcurrent)await new Promise((resolve)=>this.queue.push(resolve));
7526
+ this.running++;
7527
+ try {
7528
+ return await fn();
7529
+ } finally{
7530
+ this.running--;
7531
+ const next = this.queue.shift();
7532
+ if (next) next();
7533
+ }
7534
+ }
7535
+ }
7536
+ const apiLimiter = new ConcurrencyLimiter(18);
7537
+ const EXECUTION_TIMEOUT_MS = 40000;
7538
+ async function generateApiSection(sectionDef, templateVariables) {
7539
+ return apiLimiter.run(async ()=>{
7540
+ try {
7541
+ const prompt = `\u{4F60}\u{662F}\u{6280}\u{672F}\u{6587}\u{6863}\u{4E13}\u{5BB6}\u{3002}\u{8BF7}\u{4E3A}"${templateVariables.featureName}"\u{7684}API\u{6587}\u{6863}\u{751F}\u{6210}"${sectionDef.title}"\u{7AE0}\u{8282}\u{3002}
7542
+
7543
+ ## \u{4EFB}\u{52A1}
7544
+ ${sectionDef.prompt}
7545
+
7546
+ ## \u{9700}\u{6C42}\u{4FE1}\u{606F}
7547
+ - \u{529F}\u{80FD}\u{540D}\u{79F0}: ${templateVariables.featureName}
7548
+ - \u{4E1A}\u{52A1}\u{9886}\u{57DF}: ${templateVariables.businessDomain}
7549
+ - \u{9700}\u{6C42}\u{8BE6}\u{60C5}: ${templateVariables.inputContent?.substring(0, 1500) || ''}
7550
+
7551
+ ## \u{8981}\u{6C42}
7552
+ - \u{5185}\u{5BB9}\u{8BE6}\u{5B9E}\u{5177}\u{4F53}\u{FF0C}\u{4E0D}\u{4F7F}\u{7528}\u{5360}\u{4F4D}\u{7B26}
7553
+ - \u{4F7F}\u{7528}\u{6B63}\u{786E}\u{7684}Markdown\u{683C}\u{5F0F}
7554
+ - \u{5982}\u{9700}\u{56FE}\u{8868}\u{4F7F}\u{7528}mermaid\u{8BED}\u{6CD5}
7555
+ - \u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}
7556
+
7557
+ \u{76F4}\u{63A5}\u{8F93}\u{51FA}\u{8BE5}\u{7AE0}\u{8282}\u{7684}Markdown\u{5185}\u{5BB9}\u{FF08}\u{5305}\u{542B}\u{7AE0}\u{8282}\u{6807}\u{9898}\u{FF09}\u{3002}`;
7558
+ const content = await openAIService.generateText({
7559
+ prompt,
7560
+ system_prompt: "\u4F60\u662F\u6280\u672F\u6587\u6863\u4E13\u5BB6\uFF0C\u8F93\u51FA\u7B80\u6D01\u4E13\u4E1A\u7684\u6587\u6863\u7AE0\u8282\u3002",
7561
+ temperature: 0.7
7562
+ });
7563
+ return {
7564
+ id: sectionDef.id,
7565
+ title: sectionDef.title,
7566
+ content,
7567
+ success: true
7568
+ };
7569
+ } catch (error) {
7570
+ return {
7571
+ id: sectionDef.id,
7572
+ title: sectionDef.title,
7573
+ content: "",
7574
+ success: false,
7575
+ error: error.message
7576
+ };
7577
+ }
7578
+ });
7579
+ }
7580
+ async function generateInteractiveHtml(templateVariables) {
7581
+ const { featureName, businessDomain, pageType, pageStyle, inputContent } = templateVariables;
7582
+ const prompt = `\u{4F60}\u{662F}\u{4E00}\u{4F4D}\u{4E13}\u{4E1A}\u{7684}\u{524D}\u{7AEF}\u{5F00}\u{53D1}\u{4E13}\u{5BB6}\u{3002}\u{8BF7}\u{6839}\u{636E}\u{4EE5}\u{4E0B}\u{9700}\u{6C42}\u{751F}\u{6210}\u{4E00}\u{4E2A}\u{5B8C}\u{6574}\u{7684}\u{3001}\u{53EF}\u{4EA4}\u{4E92}\u{7684}HTML\u{9875}\u{9762}\u{3002}
7583
+
7584
+ ## \u{9700}\u{6C42}\u{4FE1}\u{606F}
7585
+ - \u{529F}\u{80FD}\u{540D}\u{79F0}: ${featureName}
7586
+ - \u{4E1A}\u{52A1}\u{9886}\u{57DF}: ${businessDomain}
7587
+ - \u{9875}\u{9762}\u{7C7B}\u{578B}: ${pageType || 'responsive'}
7588
+ - \u{9700}\u{6C42}\u{8BE6}\u{60C5}:
7589
+ ${inputContent || ''}
7590
+
7591
+ ## \u{9875}\u{9762}\u{98CE}\u{683C}\u{8981}\u{6C42}
7592
+ \u{5728}<head>\u{4E2D}\u{5305}\u{542B}\u{4EE5}\u{4E0B}\u{6837}\u{5F0F}\u{914D}\u{7F6E}\u{FF1A}
7593
+ ${pageStyle}
7594
+
7595
+ ## \u{6280}\u{672F}\u{8981}\u{6C42}
7596
+ 1. \u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}HTML\u{6587}\u{4EF6}\u{FF0C}\u{5305}\u{542B}<!DOCTYPE html>\u{3001}<html>\u{3001}<head>\u{3001}<body>
7597
+ 2. \u{4F7F}\u{7528}TailwindCSS\u{8FDB}\u{884C}\u{6837}\u{5F0F}\u{8BBE}\u{8BA1}\u{FF0C}\u{4F7F}\u{7528}CSS\u{53D8}\u{91CF}\u{5B9E}\u{73B0}\u{4E3B}\u{9898}\u{8272}
7598
+ 3. \u{9875}\u{9762}\u{5FC5}\u{987B}\u{662F}${'mobile' === pageType ? "\u79FB\u52A8\u7AEF\u4F18\u5148" : 'pc' === pageType ? "PC\u7AEF" : "\u54CD\u5E94\u5F0F"}\u{5E03}\u{5C40}
7599
+ 4. \u{5305}\u{542B}\u{5B8C}\u{6574}\u{7684}\u{8868}\u{5355}\u{9A8C}\u{8BC1}\u{548C}\u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{FF08}\u{4F7F}\u{7528}\u{539F}\u{751F}JavaScript\u{FF09}
7600
+ 5. \u{5305}\u{542B}\u{52A0}\u{8F7D}\u{72B6}\u{6001}\u{3001}\u{6210}\u{529F}/\u{5931}\u{8D25}\u{63D0}\u{793A}
7601
+ 6. \u{8868}\u{5355}\u{63D0}\u{4EA4}\u{4F7F}\u{7528}console.log\u{6A21}\u{62DF}\u{FF0C}\u{5E76}\u{663E}\u{793A}\u{63D0}\u{4EA4}\u{7ED3}\u{679C}
7602
+ 7. \u{6240}\u{6709}\u{6587}\u{672C}\u{4F7F}\u{7528}\u{4E2D}\u{6587}
7603
+ 8. \u{8BBE}\u{8BA1}\u{7F8E}\u{89C2}\u{3001}\u{73B0}\u{4EE3}\u{3001}\u{7B80}\u{6D01}
7604
+
7605
+ ## \u{8F93}\u{51FA}\u{8981}\u{6C42}
7606
+ \u{76F4}\u{63A5}\u{8F93}\u{51FA}\u{5B8C}\u{6574}\u{7684}HTML\u{4EE3}\u{7801}\u{FF0C}\u{4E0D}\u{8981}\u{5305}\u{542B}\u{4EFB}\u{4F55}\u{89E3}\u{91CA}\u{6216}markdown\u{6807}\u{8BB0}\u{3002}`;
7607
+ const html = await openAIService.generateText({
7608
+ prompt,
7609
+ system_prompt: "\u4F60\u662F\u4E00\u4F4D\u8D44\u6DF1\u7684\u524D\u7AEF\u5F00\u53D1\u4E13\u5BB6\uFF0C\u64C5\u957F\u4F7F\u7528TailwindCSS\u521B\u5EFA\u7F8E\u89C2\u3001\u53EF\u4EA4\u4E92\u7684\u9875\u9762\u3002\u53EA\u8F93\u51FAHTML\u4EE3\u7801\uFF0C\u4E0D\u8981\u5305\u542B\u4EFB\u4F55\u5176\u4ED6\u5185\u5BB9\u3002",
7610
+ temperature: 0.7
7611
+ });
7612
+ let cleanHtml = html.trim();
7613
+ if (cleanHtml.startsWith("```html")) cleanHtml = cleanHtml.slice(7);
7614
+ else if (cleanHtml.startsWith("```")) cleanHtml = cleanHtml.slice(3);
7615
+ if (cleanHtml.endsWith("```")) cleanHtml = cleanHtml.slice(0, -3);
7616
+ return cleanHtml.trim();
7617
+ }
7173
7618
  const requirementAnalyzerTool = {
7174
- name: "\u9700\u6C42\u62A5\u544A\u751F\u6210\u667A\u80FD\u4F53",
7175
- description: "\u667A\u80FD\u5206\u6790\u9700\u6C42\u5E76\u751F\u6210\u7EDF\u4E00\u7684\u6280\u672F\u6587\u6863\uFF0C\u652F\u6301\u9879\u76EE\u60C5\u51B5\u611F\u77E5\u548C\u7CBE\u786E\u6A21\u677F\u5339\u914D",
7619
+ name: "requirement-analyzer-report",
7620
+ description: `\u{667A}\u{80FD}\u{5206}\u{6790}\u{9700}\u{6C42}\u{5E76}\u{751F}\u{6210}API\u{6587}\u{6863}\u{548C}HTML\u{9875}\u{9762}\u{8BBE}\u{8BA1}\u{6587}\u{6863}\u{3002}\u{652F}\u{6301}PC\u{7AEF}\u{3001}\u{79FB}\u{52A8}\u{7AEF}\u{7B49}\u{591A}\u{79CD}\u{9875}\u{9762}\u{7C7B}\u{578B}\u{3002}`,
7176
7621
  inputSchema: {
7177
7622
  requirement_analysis: stringType().describe("requirement-identifier\u751F\u6210\u7684\u9700\u6C42\u5206\u6790\u7ED3\u679C\uFF08\u5305\u542B\u5F53\u524D\u9700\u6C42\u4E0E\u9879\u76EE\u60C5\u51B5\u7684\u5B8C\u6574\u5206\u6790\uFF09"),
7178
7623
  current_project_path: stringType().describe("\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\uFF08\u5FC5\u586B\uFF09\uFF0C\u9700\u6C42\u62A5\u544A\u5C06\u751F\u6210\u5230\u8BE5\u8DEF\u5F84\u4E0B\u7684.aico/design\u76EE\u5F55"),
7179
- requirement_type: enumType([
7180
- "PC+API",
7181
- "APP+API",
7182
- "SDK+API",
7183
- "APP+SDK",
7184
- "PC+APP+API"
7185
- ]).default("PC+API").describe("需求类型(必填):\n- PC+API: 页面+接口(会生成PC报告和API报告)\n- APP+API: 移动端+接口(会生成APP报告和API报告)\n- SDK+API: SDK集成+接口\n- APP+SDK: 移动端+SDK集成\n- PC+APP+API: 全平台(会生成PC、APP、API三份报告)\n根据需求内容选择合适的类型,如果需求提到「接口和页面」,应该使用 PC+API")
7624
+ page_style: stringType().optional().describe("HTML\u9875\u9762\u98CE\u683C\u6837\u5F0F\uFF08\u53EF\u9009\uFF09\uFF0C\u9ED8\u8BA4\u4F7F\u7528 TailwindCSS \u7B80\u7EA6\u98CE\u683C\u3002\u53EF\u81EA\u5B9A\u4E49 CSS \u53D8\u91CF\u548C\u6837\u5F0F\u3002"),
7625
+ page_type: enumType([
7626
+ "pc",
7627
+ "mobile",
7628
+ "responsive"
7629
+ ]).default("responsive").describe("页面类型(可选):\n- pc: PC端页面\n- mobile: 移动端页面\n- responsive: 响应式页面(默认,同时支持PC和移动端)")
7186
7630
  },
7187
7631
  handler: async (args)=>{
7188
7632
  try {
7189
- const { requirement_analysis, current_project_path, requirement_type } = args;
7633
+ const { requirement_analysis, current_project_path, page_style, page_type } = args;
7634
+ const finalPageStyle = page_style || DEFAULT_PAGE_STYLE;
7635
+ const finalPageType = page_type || "responsive";
7190
7636
  if (!requirement_analysis || !current_project_path) return {
7191
7637
  content: [
7192
7638
  {
@@ -7204,20 +7650,234 @@ ${generationTasks?.map((task, i)=>`
7204
7650
  const serviceResult = await service.analyzeRequirements({
7205
7651
  requirement_analysis,
7206
7652
  current_project_path,
7207
- requirement_type: requirement_type || "PC+API"
7653
+ page_style: finalPageStyle,
7654
+ page_type: finalPageType
7208
7655
  });
7209
- return {
7656
+ const generationTasks = serviceResult.generationTasks || [];
7657
+ if (0 === generationTasks.length) return {
7210
7658
  content: [
7211
7659
  {
7212
7660
  type: "text",
7213
7661
  text: JSON.stringify({
7662
+ success: false,
7663
+ message: "\u6CA1\u6709\u751F\u6210\u4EFB\u52A1",
7664
+ data: null
7665
+ })
7666
+ }
7667
+ ],
7668
+ isError: true
7669
+ };
7670
+ logger.info(`\u{5F00}\u{59CB}\u{5B8C}\u{5168}\u{5E76}\u{884C}\u{751F}\u{6210} ${generationTasks.length} \u{4EFD}\u{6587}\u{6863}\u{FF08}\u{8D85}\u{65F6}: ${EXECUTION_TIMEOUT_MS}ms\u{FF09}...`);
7671
+ const startTime = Date.now();
7672
+ const apiTask = generationTasks.find((t)=>"API" === t.requirementType);
7673
+ const htmlTask = generationTasks.find((t)=>"HTML" === t.requirementType);
7674
+ const taskStatus = new Map();
7675
+ if (apiTask) taskStatus.set("API", {
7676
+ type: "API",
7677
+ content: "",
7678
+ outputPath: apiTask.outputPath,
7679
+ success: false,
7680
+ completed: false
7681
+ });
7682
+ if (htmlTask) {
7683
+ const htmlOutputPath = htmlTask.outputPath.replace(/\.md$/, ".html");
7684
+ taskStatus.set("HTML", {
7685
+ type: "HTML",
7686
+ content: "",
7687
+ outputPath: htmlOutputPath,
7688
+ success: false,
7689
+ completed: false
7690
+ });
7691
+ }
7692
+ const parallelTasks = [];
7693
+ if (apiTask) {
7694
+ const apiPromise = (async ()=>{
7695
+ try {
7696
+ logger.info(`\u{5F00}\u{59CB}\u{5E76}\u{884C}\u{751F}\u{6210}API\u{6587}\u{6863}\u{FF08}${API_SECTIONS.length}\u{4E2A}\u{7AE0}\u{8282}\u{FF09}`);
7697
+ const sectionResults = await Promise.all(API_SECTIONS.map((section)=>generateApiSection(section, apiTask.templateVariables)));
7698
+ const successSections = sectionResults.filter((r)=>r.success);
7699
+ const header = `# ${apiTask.templateVariables.featureName} - API\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
7700
+
7701
+ > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: ${new Date().toISOString()}
7702
+ > **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: ${apiTask.templateVariables.businessDomain}
7703
+
7704
+ ---
7705
+
7706
+ `;
7707
+ const document1 = header + successSections.map((s)=>s.content).join("\n\n---\n\n");
7708
+ const outputDir = external_path_default().dirname(apiTask.outputPath);
7709
+ await promises_namespaceObject.mkdir(outputDir, {
7710
+ recursive: true
7711
+ });
7712
+ await promises_namespaceObject.writeFile(apiTask.outputPath, document1, "utf-8");
7713
+ taskStatus.set("API", {
7714
+ type: "API",
7715
+ content: document1,
7716
+ outputPath: apiTask.outputPath,
7717
+ success: true,
7718
+ completed: true
7719
+ });
7720
+ logger.info(`API\u{6587}\u{6863}\u{751F}\u{6210}\u{5B8C}\u{6210}`, {
7721
+ length: document1.length
7722
+ });
7723
+ } catch (error) {
7724
+ taskStatus.set("API", {
7725
+ type: "API",
7726
+ content: "",
7727
+ outputPath: apiTask.outputPath,
7728
+ success: false,
7729
+ error: error.message,
7730
+ completed: true
7731
+ });
7732
+ }
7733
+ })();
7734
+ parallelTasks.push(apiPromise);
7735
+ }
7736
+ if (htmlTask) {
7737
+ const htmlPromise = (async ()=>{
7738
+ try {
7739
+ logger.info(`\u{5F00}\u{59CB}\u{751F}\u{6210}\u{53EF}\u{4EA4}\u{4E92}HTML\u{9875}\u{9762}`);
7740
+ const htmlOutputPath = htmlTask.outputPath.replace(/\.md$/, ".html");
7741
+ const htmlContent = await generateInteractiveHtml(htmlTask.templateVariables);
7742
+ const outputDir = external_path_default().dirname(htmlOutputPath);
7743
+ await promises_namespaceObject.mkdir(outputDir, {
7744
+ recursive: true
7745
+ });
7746
+ await promises_namespaceObject.writeFile(htmlOutputPath, htmlContent, "utf-8");
7747
+ taskStatus.set("HTML", {
7748
+ type: "HTML",
7749
+ content: htmlContent,
7750
+ outputPath: htmlOutputPath,
7214
7751
  success: true,
7215
- message: serviceResult.message || "\u9700\u6C42\u5206\u6790\u4EFB\u52A1\u5DF2\u51C6\u5907",
7752
+ completed: true
7753
+ });
7754
+ logger.info(`HTML\u{9875}\u{9762}\u{751F}\u{6210}\u{5B8C}\u{6210}`, {
7755
+ length: htmlContent.length
7756
+ });
7757
+ } catch (error) {
7758
+ taskStatus.set("HTML", {
7759
+ type: "HTML",
7760
+ content: "",
7761
+ outputPath: htmlTask.outputPath.replace(/\.md$/, ".html"),
7762
+ success: false,
7763
+ error: error.message,
7764
+ completed: true
7765
+ });
7766
+ }
7767
+ })();
7768
+ parallelTasks.push(htmlPromise);
7769
+ }
7770
+ const timeoutPromise = new Promise((resolve)=>{
7771
+ setTimeout(()=>resolve("timeout"), EXECUTION_TIMEOUT_MS);
7772
+ });
7773
+ const raceResult = await Promise.race([
7774
+ Promise.all(parallelTasks).then(()=>"completed"),
7775
+ timeoutPromise
7776
+ ]);
7777
+ const totalDuration = Date.now() - startTime;
7778
+ const isTimeout = "timeout" === raceResult;
7779
+ const results = Array.from(taskStatus.values());
7780
+ const completedResults = results.filter((r)=>r.completed);
7781
+ const pendingResults = results.filter((r)=>!r.completed);
7782
+ const successCount = completedResults.filter((r)=>r.success).length;
7783
+ const failedCount = completedResults.filter((r)=>!r.success && r.completed).length;
7784
+ const generatedFiles = completedResults.filter((r)=>r.success).map((r)=>r.outputPath);
7785
+ logger.info(`\u{5E76}\u{884C}\u{751F}\u{6210}${isTimeout ? "\u8D85\u65F6" : "\u5B8C\u6210"}`, {
7786
+ total: results.length,
7787
+ completed: completedResults.length,
7788
+ pending: pendingResults.length,
7789
+ success: successCount,
7790
+ failed: failedCount,
7791
+ totalDuration: `${totalDuration}ms`,
7792
+ isTimeout
7793
+ });
7794
+ if (isTimeout && pendingResults.length > 0) {
7795
+ const pendingPrompts = pendingResults.map((task)=>{
7796
+ if ("API" === task.type && apiTask) return {
7797
+ type: "API",
7798
+ outputPath: task.outputPath,
7799
+ prompt: `\u{8BF7}\u{4E3A}"${apiTask.templateVariables.featureName}"\u{751F}\u{6210}API\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}\u{FF0C}\u{5305}\u{542B}\u{4EE5}\u{4E0B}\u{7AE0}\u{8282}\u{FF1A}
7800
+ 1. \u{6587}\u{6863}\u{5934}\u{90E8}\u{FF08}\u{6807}\u{9898}\u{3001}\u{751F}\u{6210}\u{65F6}\u{95F4}\u{3001}\u{4E1A}\u{52A1}\u{9886}\u{57DF}\u{FF09}
7801
+ 2. \u{9700}\u{6C42}\u{80CC}\u{666F}\u{FF08}\u{9700}\u{6C42}\u{80CC}\u{666F}\u{3001}\u{5173}\u{952E}\u{529F}\u{80FD}\u{3001}\u{6D89}\u{53CA}\u{89D2}\u{8272}\u{FF09}
7802
+ 3. \u{529F}\u{80FD}\u{8BBE}\u{8BA1}\u{8BF4}\u{660E}\u{FF08}\u{6D41}\u{7A0B}\u{7F16}\u{53F7}\u{3001}\u{524D}\u{7F6E}\u{6761}\u{4EF6}\u{3001}\u{89D2}\u{8272}\u{7B49}\u{8868}\u{683C}\u{FF09}
7803
+ 4. \u{6570}\u{636E}\u{5EFA}\u{6A21}\u{FF08}ER\u{903B}\u{8F91}\u{56FE}mermaid erDiagram + \u{6570}\u{636E}\u{8868}\u{5B9E}\u{4F53}\u{8BBE}\u{8BA1}\u{FF09}
7804
+ 5. API\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{FF08}\u{63A5}\u{53E3}\u{5217}\u{8868}\u{3001}\u{8BF7}\u{6C42}\u{53C2}\u{6570}\u{3001}\u{54CD}\u{5E94}\u{53C2}\u{6570}\u{3001}\u{9519}\u{8BEF}\u{7801}\u{FF09}
7805
+ 6. \u{4E1A}\u{52A1}\u{65F6}\u{5E8F}\u{56FE}\u{FF08}mermaid sequenceDiagram\u{FF09}
7806
+ 7. \u{4E1A}\u{52A1}\u{72B6}\u{6001}\u{FF08}\u{72B6}\u{6001}\u{63CF}\u{8FF0}\u{8868}\u{683C}\u{FF09}
7807
+ 8. \u{4F2A}\u{4EE3}\u{7801}\u{793A}\u{4F8B}\u{FF08}\u{6838}\u{5FC3}\u{4E1A}\u{52A1}\u{903B}\u{8F91}\u{FF09}
7808
+
7809
+ \u{4E1A}\u{52A1}\u{9886}\u{57DF}: ${apiTask.templateVariables.businessDomain}
7810
+ \u{9700}\u{6C42}\u{8BE6}\u{60C5}: ${apiTask.templateVariables.inputContent?.substring(0, 500) || ''}
7811
+
7812
+ \u{8BF7}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}Markdown\u{6587}\u{6863}\u{5E76}\u{4FDD}\u{5B58}\u{5230}: ${task.outputPath}`
7813
+ };
7814
+ if ("HTML" === task.type && htmlTask) return {
7815
+ type: "HTML",
7816
+ outputPath: task.outputPath,
7817
+ prompt: `\u{8BF7}\u{4E3A}"${htmlTask.templateVariables.featureName}"\u{751F}\u{6210}\u{53EF}\u{4EA4}\u{4E92}\u{7684}HTML\u{9875}\u{9762}\u{FF1A}
7818
+
7819
+ \u{6280}\u{672F}\u{8981}\u{6C42}\u{FF1A}
7820
+ 1. \u{5B8C}\u{6574}HTML\u{6587}\u{4EF6}\u{FF08}<!DOCTYPE html>\u{3001}<html>\u{3001}<head>\u{3001}<body>\u{FF09}
7821
+ 2. \u{4F7F}\u{7528}TailwindCSS\u{FF08}CDN\u{5F15}\u{5165}\u{FF09}\u{8FDB}\u{884C}\u{6837}\u{5F0F}\u{8BBE}\u{8BA1}
7822
+ 3. \u{9875}\u{9762}\u{7C7B}\u{578B}: ${htmlTask.templateVariables.pageType || 'responsive'}\u{5E03}\u{5C40}
7823
+ 4. \u{5305}\u{542B}\u{8868}\u{5355}\u{9A8C}\u{8BC1}\u{548C}\u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{FF08}\u{539F}\u{751F}JavaScript\u{FF09}
7824
+ 5. \u{5305}\u{542B}\u{52A0}\u{8F7D}\u{72B6}\u{6001}\u{3001}\u{6210}\u{529F}/\u{5931}\u{8D25}\u{63D0}\u{793A}
7825
+ 6. \u{6240}\u{6709}\u{6587}\u{672C}\u{4F7F}\u{7528}\u{4E2D}\u{6587}
7826
+
7827
+ \u{9875}\u{9762}\u{98CE}\u{683C}\u{FF1A}
7828
+ ${htmlTask.templateVariables.pageStyle || DEFAULT_PAGE_STYLE}
7829
+
7830
+ \u{9700}\u{6C42}\u{8BE6}\u{60C5}: ${htmlTask.templateVariables.inputContent?.substring(0, 500) || ''}
7831
+
7832
+ \u{8BF7}\u{751F}\u{6210}\u{5B8C}\u{6574}\u{7684}HTML\u{4EE3}\u{7801}\u{5E76}\u{4FDD}\u{5B58}\u{5230}: ${task.outputPath}`
7833
+ };
7834
+ return null;
7835
+ }).filter(Boolean);
7836
+ return {
7837
+ content: [
7838
+ {
7839
+ type: "text",
7840
+ text: JSON.stringify({
7841
+ success: successCount > 0,
7842
+ timeout: true,
7843
+ message: `\u{6267}\u{884C}\u{8D85}\u{65F6}(${EXECUTION_TIMEOUT_MS}ms)\u{FF1A}${successCount} \u{5B8C}\u{6210}\u{FF0C}${pendingResults.length} \u{5F85}\u{6267}\u{884C}\u{FF0C}\u{8BF7}\u{7EE7}\u{7EED}\u{6267}\u{884C}\u{4EE5}\u{4E0B}\u{4EFB}\u{52A1}`,
7844
+ data: {
7845
+ outputPath: serviceResult.outputPath,
7846
+ generatedFiles,
7847
+ analysisInfo: serviceResult.analysisInfo || {},
7848
+ completedResults: completedResults.map((r)=>({
7849
+ type: r.type,
7850
+ outputPath: r.outputPath,
7851
+ success: r.success,
7852
+ error: r.error,
7853
+ contentLength: r.content?.length || 0
7854
+ })),
7855
+ pendingTasks: pendingPrompts
7856
+ }
7857
+ })
7858
+ }
7859
+ ]
7860
+ };
7861
+ }
7862
+ return {
7863
+ content: [
7864
+ {
7865
+ type: "text",
7866
+ text: JSON.stringify({
7867
+ success: successCount > 0,
7868
+ timeout: false,
7869
+ message: `\u{6587}\u{6863}\u{751F}\u{6210}\u{5B8C}\u{6210}\u{FF1A}${successCount} \u{6210}\u{529F}\u{FF0C}${failedCount} \u{5931}\u{8D25}\u{FF0C}\u{603B}\u{8017}\u{65F6} ${totalDuration}ms`,
7216
7870
  data: {
7217
7871
  outputPath: serviceResult.outputPath,
7218
- generatedFiles: serviceResult.generatedFiles || [],
7872
+ generatedFiles,
7219
7873
  analysisInfo: serviceResult.analysisInfo || {},
7220
- generationTasks: serviceResult.generationTasks || []
7874
+ results: results.map((r)=>({
7875
+ type: r.type,
7876
+ outputPath: r.outputPath,
7877
+ success: r.success,
7878
+ error: r.error,
7879
+ contentLength: r.content?.length || 0
7880
+ }))
7221
7881
  }
7222
7882
  })
7223
7883
  }
@@ -7593,214 +8253,18 @@ ${requirementSection}
7593
8253
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
7594
8254
  const filename = `change-analysis-${timestamp}.${'json' === format ? 'json' : 'md'}`;
7595
8255
  const outputPath = external_path_default().join(outputDir, filename);
7596
- if ('json' === format) {
7597
- const jsonData = {
7598
- timestamp: new Date().toISOString(),
7599
- prompt,
7600
- type: 'change-analysis'
7601
- };
7602
- external_fs_default().writeFileSync(outputPath, JSON.stringify(jsonData, null, 2), 'utf-8');
7603
- } else external_fs_default().writeFileSync(outputPath, prompt, 'utf-8');
7604
- return outputPath;
7605
- }
7606
- const external_sharp_namespaceObject = require("sharp");
7607
- var external_sharp_default = /*#__PURE__*/ __webpack_require__.n(external_sharp_namespaceObject);
7608
- async function invokeFlow(params, streamCb) {
7609
- const { appid = 'app-ESTcrkOPOmkxdrO0120mE4s1', data, timeout = 1800000 } = params;
7610
- const controller = new AbortController();
7611
- const signal = controller.signal;
7612
- if ('undefined' == typeof ReadableStream) throw new Error('ReadableStream is not supported in this environment');
7613
- const fetchData = async (retryCount = 0)=>{
7614
- try {
7615
- const fetchOptions = {
7616
- method: 'POST',
7617
- headers: {
7618
- Authorization: `Bearer ${appid}`,
7619
- 'Content-Type': 'application/json'
7620
- },
7621
- body: JSON.stringify({
7622
- inputs: data,
7623
- response_mode: 'streaming',
7624
- user: "aico-mcp"
7625
- }),
7626
- signal
7627
- };
7628
- const res = await fetch('http://11.0.166.20:9199/v1/workflows/run', fetchOptions);
7629
- if (!res.ok) {
7630
- if (retryCount < 3) {
7631
- await new Promise((resolve)=>setTimeout(resolve, 1000));
7632
- return fetchData(retryCount + 1);
7633
- }
7634
- const errorResponse = await res.text();
7635
- throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
7636
- }
7637
- if (res.ok) if (res.body) {
7638
- const reader = res.body.getReader();
7639
- const decoder = new TextDecoder('utf-8');
7640
- if (streamCb) return void new ReadableStream({
7641
- start (controller) {
7642
- let buffer = '';
7643
- function push() {
7644
- reader.read().then(({ done, value })=>{
7645
- if (done) {
7646
- const lines = buffer.split('\n');
7647
- for (const line of lines)handleLine(line, controller);
7648
- if (streamCb) streamCb({
7649
- isEnd: true
7650
- });
7651
- controller.close();
7652
- return;
7653
- }
7654
- const chunkText = decoder.decode(value, {
7655
- stream: true
7656
- });
7657
- buffer += chunkText;
7658
- const lines = buffer.split('\n');
7659
- for(let i = 0; i < lines.length - 1; i++)handleLine(lines[i], controller);
7660
- buffer = lines[lines.length - 1];
7661
- push();
7662
- });
7663
- }
7664
- function handleLine(line, controller) {
7665
- line = line.trim();
7666
- if (line.startsWith('data:')) {
7667
- const dataStr = line.slice(5).trim();
7668
- if ('' === dataStr) return;
7669
- try {
7670
- const jsonData = JSON.parse(dataStr);
7671
- if (jsonData.data?.text) {
7672
- const wrappedData = {
7673
- content: jsonData.data.text.toString(),
7674
- controller
7675
- };
7676
- if (streamCb) streamCb(wrappedData);
7677
- }
7678
- } catch (e) {
7679
- console.error("\u89E3\u6790JSON\u5931\u8D25:", e);
7680
- }
7681
- }
7682
- }
7683
- push();
7684
- }
7685
- });
7686
- {
7687
- let buffer = '';
7688
- let accumulatedText = '';
7689
- let isResponseEnded = false;
7690
- const readAll = async ()=>{
7691
- const { done, value } = await reader.read();
7692
- if (done) {
7693
- if (!isResponseEnded) throw new Error("\u54CD\u5E94\u63D0\u524D\u7ED3\u675F");
7694
- return accumulatedText;
7695
- }
7696
- const chunkText = decoder.decode(value, {
7697
- stream: true
7698
- });
7699
- buffer += chunkText;
7700
- const lines = buffer.split('\n');
7701
- for(let i = 0; i < lines.length - 1; i++){
7702
- const line = lines[i].trim();
7703
- if (!line.startsWith('data:')) continue;
7704
- const dataStr = line.slice(5).trim();
7705
- if ('' !== dataStr) try {
7706
- const jsonData = JSON.parse(dataStr);
7707
- switch(jsonData.event){
7708
- case 'message':
7709
- case 'agent_message':
7710
- case 'text_chunk':
7711
- {
7712
- const content = 'text_chunk' === jsonData.event ? jsonData.data.text : jsonData.answer;
7713
- accumulatedText += content;
7714
- break;
7715
- }
7716
- case 'workflow_finished':
7717
- accumulatedText = jsonData.data;
7718
- isResponseEnded = true;
7719
- break;
7720
- case 'message_end':
7721
- isResponseEnded = true;
7722
- break;
7723
- case 'error':
7724
- throw new Error(`\u{670D}\u{52A1}\u{5668}\u{9519}\u{8BEF}: ${jsonData.code}, ${jsonData.message}`);
7725
- default:
7726
- break;
7727
- }
7728
- } catch (e) {
7729
- throw new Error("\u89E3\u6790JSON\u5931\u8D25: " + e.message);
7730
- }
7731
- }
7732
- buffer = lines[lines.length - 1];
7733
- return readAll();
7734
- };
7735
- return readAll();
7736
- }
7737
- } else throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
7738
- {
7739
- const errorResponse = await res.text();
7740
- throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
7741
- }
7742
- } catch (error) {
7743
- if ('AbortError' === error.name) throw new Error("\u8BF7\u6C42\u5DF2\u88AB\u4E2D\u6B62\uFF0C\u8D85\u65F6");
7744
- throw error;
7745
- }
7746
- };
7747
- try {
7748
- const result = await Promise.race([
7749
- fetchData(),
7750
- new Promise((_, reject)=>{
7751
- setTimeout(()=>{
7752
- controller.abort();
7753
- reject(new Error("\u8BF7\u6C42\u8D85\u65F6"));
7754
- }, timeout);
7755
- })
7756
- ]);
7757
- if (streamCb) return;
7758
- return result;
7759
- } catch (error) {
7760
- controller.abort();
7761
- throw error;
7762
- }
7763
- }
7764
- async function uploadFile(params) {
7765
- const { appid, filePath, user = 'aico-mcp' } = params;
7766
- try {
7767
- const fileBuffer = await external_fs_default().promises.readFile(filePath);
7768
- const fileName = external_path_default().basename(filePath);
7769
- const fileExtension = external_path_default().extname(filePath).toLowerCase().slice(1);
7770
- const mimeTypes = {
7771
- png: 'image/png',
7772
- jpeg: 'image/jpeg',
7773
- jpg: 'image/jpeg',
7774
- webp: 'image/webp',
7775
- gif: 'image/gif'
7776
- };
7777
- const mimeType = mimeTypes[fileExtension] || 'application/octet-stream';
7778
- const formData = new FormData();
7779
- formData.append('file', new Blob([
7780
- fileBuffer.buffer
7781
- ], {
7782
- type: mimeType
7783
- }), fileName);
7784
- formData.append('user', user);
7785
- const response = await fetch('http://11.0.166.20:9199/v1/files/upload', {
7786
- method: 'POST',
7787
- headers: {
7788
- Authorization: `Bearer ${appid}`
7789
- },
7790
- body: formData
7791
- });
7792
- if (!response.ok) {
7793
- const errorText = await response.text();
7794
- throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${response.status} ${response.statusText} - ${errorText}`);
7795
- }
7796
- const result = await response.json();
7797
- if (!result.id || !result.name) throw new Error("\u65E0\u6548\u7684\u6587\u4EF6\u4E0A\u4F20\u54CD\u5E94\u683C\u5F0F");
7798
- return result;
7799
- } catch (error) {
7800
- if (error instanceof Error) throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${error.message}`);
7801
- throw new Error("\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: \u672A\u77E5\u9519\u8BEF");
7802
- }
8256
+ if ('json' === format) {
8257
+ const jsonData = {
8258
+ timestamp: new Date().toISOString(),
8259
+ prompt,
8260
+ type: 'change-analysis'
8261
+ };
8262
+ external_fs_default().writeFileSync(outputPath, JSON.stringify(jsonData, null, 2), 'utf-8');
8263
+ } else external_fs_default().writeFileSync(outputPath, prompt, 'utf-8');
8264
+ return outputPath;
7803
8265
  }
8266
+ const external_sharp_namespaceObject = require("sharp");
8267
+ var external_sharp_default = /*#__PURE__*/ __webpack_require__.n(external_sharp_namespaceObject);
7804
8268
  class ImageAnalysisError extends Error {
7805
8269
  code;
7806
8270
  context;
@@ -7837,7 +8301,7 @@ ${requirementSection}
7837
8301
  });
7838
8302
  await this.validateParams(imagePath);
7839
8303
  const basicInfo = await this.getImageBasicInfo(imagePath);
7840
- const analysisContent = await this.performAIAnalysis(imagePath, basicInfo, context);
8304
+ const analysisContent = await this.performAIAnalysis(imagePath, context);
7841
8305
  const processingTime = Date.now() - startTime;
7842
8306
  if (!analysisContent) throw new ImageAnalysisError("AI\u5206\u6790\u8FD4\u56DE\u7A7A\u7ED3\u679C", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
7843
8307
  params: {
@@ -7864,16 +8328,15 @@ ${requirementSection}
7864
8328
  throw error;
7865
8329
  }
7866
8330
  }
7867
- async performAIAnalysis(imagePath, basicInfo, context) {
8331
+ async performAIAnalysis(imagePath, context) {
7868
8332
  try {
7869
- const imageBase64 = await this.imageToBase64(imagePath);
7870
8333
  const systemPrompt = `You must interpret and analyze images strictly according to the assigned task.
7871
8334
  When an image placeholder is provided, your role is to parse the image content only within the scope of the user's instructions.
7872
8335
  Do not ignore or deviate from the task.
7873
8336
  Always ensure that your response reflects a clear, accurate interpretation of the image aligned with the given objective.`;
7874
- const userPrompt = context || "\u8BF7\u5206\u6790\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9";
7875
- const aiResponse = await openAIService.analyzeImage({
7876
- image_base64: imageBase64,
8337
+ const userPrompt = `${context}, You must provide a complete and detailed description of all content in the image, including scenes, objects, text, colors, layout, relationships, and all other visible elements and details. Ensure the description is detailed enough so that subsequent text-based language models can fully understand the image content through text alone.Always respond in Chinese-simplified`;
8338
+ const aiResponse = await openAIService.analyzeImageWithPath({
8339
+ image_path: imagePath,
7877
8340
  prompt: userPrompt,
7878
8341
  system_prompt: systemPrompt
7879
8342
  });
@@ -7883,26 +8346,15 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7883
8346
  tags: []
7884
8347
  };
7885
8348
  } catch (error) {
7886
- logger.warn("\u4E3BAI\u5206\u6790\u5931\u8D25\uFF0C\u5C1D\u8BD5Dify\u515C\u5E95\u5206\u6790", {
8349
+ logger.error("AI\u5206\u6790\u5931\u8D25", {
7887
8350
  error,
7888
8351
  params: {
7889
8352
  image_path: imagePath
7890
8353
  }
7891
8354
  });
7892
- try {
7893
- return await this.fallbackToDifyAnalysis(imagePath, context);
7894
- } catch (fallbackError) {
7895
- logger.error("Dify\u515C\u5E95\u5206\u6790\u4E5F\u5931\u8D25", {
7896
- error: fallbackError,
7897
- params: {
7898
- image_path: imagePath
7899
- }
7900
- });
7901
- throw new ImageAnalysisError("\u8BC6\u522B\u56FE\u7247\u5931\u8D25", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
7902
- originalError: error,
7903
- fallbackError
7904
- });
7905
- }
8355
+ throw new ImageAnalysisError("\u8BC6\u522B\u56FE\u7247\u5931\u8D25", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
8356
+ originalError: error
8357
+ });
7906
8358
  }
7907
8359
  }
7908
8360
  async getImageBasicInfo(imagePath) {
@@ -7911,7 +8363,7 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7911
8363
  const stats = await promises_namespaceObject.stat(imagePath);
7912
8364
  return {
7913
8365
  path: imagePath,
7914
- format: metadata.format || 'unknown',
8366
+ format: metadata.format || "unknown",
7915
8367
  dimensions: {
7916
8368
  width: metadata.width || 0,
7917
8369
  height: metadata.height || 0
@@ -7925,37 +8377,6 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7925
8377
  });
7926
8378
  }
7927
8379
  }
7928
- async imageToBase64(imagePath) {
7929
- try {
7930
- const imageBuffer = await promises_namespaceObject.readFile(imagePath);
7931
- const base64 = imageBuffer.toString('base64');
7932
- const ext = external_path_namespaceObject.extname(imagePath).toLowerCase();
7933
- let mimeType = 'image/jpeg';
7934
- switch(ext){
7935
- case '.png':
7936
- mimeType = 'image/png';
7937
- break;
7938
- case '.gif':
7939
- mimeType = 'image/gif';
7940
- break;
7941
- case '.webp':
7942
- mimeType = 'image/webp';
7943
- break;
7944
- case '.jpg':
7945
- case '.jpeg':
7946
- mimeType = 'image/jpeg';
7947
- break;
7948
- default:
7949
- mimeType = 'image/jpeg';
7950
- }
7951
- return `data:${mimeType};base64,${base64}`;
7952
- } catch (error) {
7953
- throw new ImageAnalysisError(`\u{65E0}\u{6CD5}\u{8BFB}\u{53D6}\u{56FE}\u{7247}\u{6587}\u{4EF6}: ${imagePath}`, types_AnalysisErrorCodes.FILE_NOT_FOUND, {
7954
- imagePath,
7955
- originalError: error
7956
- });
7957
- }
7958
- }
7959
8380
  async validateParams(imagePath) {
7960
8381
  try {
7961
8382
  await promises_namespaceObject.access(imagePath);
@@ -7970,81 +8391,17 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7970
8391
  supportedFormats: SUPPORTED_IMAGE_FORMATS
7971
8392
  });
7972
8393
  }
7973
- formatFileSize(bytes) {
7974
- if (0 === bytes) return '0 B';
7975
- const k = 1024;
7976
- const sizes = [
7977
- 'B',
7978
- 'KB',
7979
- 'MB',
7980
- 'GB'
7981
- ];
7982
- const i = Math.floor(Math.log(bytes) / Math.log(k));
7983
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
7984
- }
7985
- async fallbackToDifyAnalysis(imagePath, context) {
7986
- logger.info("\u5F00\u59CBDify\u515C\u5E95\u56FE\u7247\u5206\u6790", {
7987
- imagePath: imagePath,
7988
- context: context
7989
- });
7990
- try {
7991
- const uploadResult = await uploadFile({
7992
- appid: 'app-AvlLh0nfN4l9oz1MSW4sEAQ6',
7993
- filePath: imagePath,
7994
- user: 'aico-mcp'
7995
- });
7996
- logger.info("\u6587\u4EF6\u4E0A\u4F20\u6210\u529F\uFF0C\u6587\u4EF6ID:", uploadResult.id);
7997
- const workflowData = {
7998
- imagePath: {
7999
- type: 'image',
8000
- transfer_method: 'local_file',
8001
- upload_file_id: uploadResult.id
8002
- },
8003
- context: context || "\u8BF7\u5206\u6790\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9"
8004
- };
8005
- const workflowResponse = await invokeFlow({
8006
- appid: 'app-AvlLh0nfN4l9oz1MSW4sEAQ6',
8007
- data: workflowData
8008
- });
8009
- logger.info("Dify\u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F", {
8010
- response: workflowResponse
8011
- });
8012
- let summary = "\u5206\u6790\u5B8C\u6210";
8013
- if ('string' == typeof workflowResponse) summary = workflowResponse;
8014
- else if (workflowResponse?.data?.text) summary = workflowResponse.data.text;
8015
- else if (workflowResponse?.answer) summary = workflowResponse.answer;
8016
- else if (workflowResponse?.outputs?.text) summary = workflowResponse.outputs.text;
8017
- else if (workflowResponse?.status === 'failed') throw new Error(`Dify\u{5DE5}\u{4F5C}\u{6D41}\u{6267}\u{884C}\u{5931}\u{8D25}: ${workflowResponse.error || "\u672A\u77E5\u9519\u8BEF"}`);
8018
- return {
8019
- summary: summary,
8020
- details: {
8021
- dify_response: workflowResponse,
8022
- fallback_used: true
8023
- },
8024
- tags: [
8025
- 'dify-fallback'
8026
- ]
8027
- };
8028
- } catch (error) {
8029
- logger.error("Dify\u670D\u52A1\u8C03\u7528\u5931\u8D25", {
8030
- error: error instanceof Error ? error.message : String(error),
8031
- imagePath: imagePath,
8032
- context: context
8033
- });
8034
- throw new ImageAnalysisError(`\u{56FE}\u{7247}\u{5206}\u{6790}\u{670D}\u{52A1}\u{8C03}\u{7528}\u{5931}\u{8D25}: ${error instanceof Error ? error.message : String(error)}`, types_AnalysisErrorCodes.AI_SERVICE_ERROR);
8035
- }
8036
- }
8037
8394
  }
8038
8395
  const ImageAnalysisParamsSchema = objectType({
8039
8396
  image_path: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
8040
- context: stringType().optional().describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
8397
+ context: stringType().min(1).describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
8041
8398
  });
8042
8399
  const read_imageTool = {
8043
8400
  name: "read_image",
8044
8401
  description: "\u4E13\u4E1A\u56FE\u7247\u5185\u5BB9\u5206\u6790\u5DE5\u5177\uFF0C\u63D0\u4F9B\u7CBE\u786E\u7684\u56FE\u7247\u5185\u5BB9\u8BC6\u522B\u3002\u6839\u636E\u7528\u6237\u8F93\u5165\u7684\u4E0A\u4E0B\u6587\u4FE1\u606F\u548C\u56FE\u7247\u5185\u5BB9\uFF0C\u8FDB\u884C\u4E25\u683C\u57FA\u4E8E\u4EFB\u52A1\u6307\u4EE4\u7684\u5206\u6790\uFF0C\u4E0D\u504F\u79BB\u4EFB\u52A1\u8303\u56F4\uFF0C\u8F93\u51FA\u6E05\u6670\u51C6\u786E\u7684\u5206\u6790\u7ED3\u679C\u3002",
8045
8402
  inputSchema: {
8046
8403
  image_path: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
8047
- context: stringType().optional().describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
8404
+ context: stringType().min(1).describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
8048
8405
  },
8049
8406
  handler: async (args)=>{
8050
8407
  const analyzer = new ImageAnalyzer();
@@ -8370,7 +8727,7 @@ ${error?.message || "\u672A\u77E5\u9519\u8BEF"}`;
8370
8727
  output_directory: stringType().optional().describe("\u8F93\u51FA\u76EE\u5F55\uFF0C\u4E0D\u6307\u5B9A\u5219\u5728\u539F\u6587\u4EF6\u76EE\u5F55\u751F\u6210")
8371
8728
  });
8372
8729
  const imageConverterTool = {
8373
- name: "\u56FE\u7247\u683C\u5F0F\u8F6C\u6362\u667A\u80FD\u4F53",
8730
+ name: "image-converter",
8374
8731
  description: "\u4E13\u4E1A\u56FE\u7247\u683C\u5F0F\u8F6C\u6362\u5DE5\u5177\uFF0C\u652F\u6301\u5355\u5F20\u548C\u6279\u91CF\u8F6C\u6362\uFF0C\u5305\u542B\u5C3A\u5BF8\u8C03\u6574\u548C\u8D28\u91CF\u63A7\u5236\u529F\u80FD",
8375
8732
  inputSchema: {
8376
8733
  input_paths: unionType([
@@ -8462,7 +8819,7 @@ ${results.map((r, index)=>`
8462
8819
  - **\u{8F93}\u{51FA}**: \`${r.output_path}\`
8463
8820
  - **\u{683C}\u{5F0F}**: ${r.format?.toUpperCase()}
8464
8821
  - **\u{5C3A}\u{5BF8}**: ${r.dimensions?.width} \xd7 ${r.dimensions?.height}
8465
- - **\u{6587}\u{4EF6}\u{5927}\u{5C0F}**: ${image_converter_formatFileSize(r.file_size || 0)}
8822
+ - **\u{6587}\u{4EF6}\u{5927}\u{5C0F}**: ${formatFileSize(r.file_size || 0)}
8466
8823
  `).join("")}
8467
8824
 
8468
8825
  ${args.width || args.height ? `
@@ -8498,7 +8855,7 @@ ${successResults.map((r, index)=>`
8498
8855
  ${index + 1}. **${getFileName(r.input_path)}**
8499
8856
  - \u{8F93}\u{51FA}: \`${r.output_path}\`
8500
8857
  - \u{5C3A}\u{5BF8}: ${r.dimensions?.width} \xd7 ${r.dimensions?.height}
8501
- - \u{5927}\u{5C0F}: ${image_converter_formatFileSize(r.file_size || 0)}
8858
+ - \u{5927}\u{5C0F}: ${formatFileSize(r.file_size || 0)}
8502
8859
  `).join("")}
8503
8860
 
8504
8861
  ## \u{274C} \u{8F6C}\u{6362}\u{5931}\u{8D25} (${failedResults.length}\u{5F20})
@@ -8565,7 +8922,7 @@ ${getErrorSuggestion(error.code)}
8565
8922
  function getFileName(filePath) {
8566
8923
  return filePath.split("/").pop() || filePath;
8567
8924
  }
8568
- function image_converter_formatFileSize(bytes) {
8925
+ function formatFileSize(bytes) {
8569
8926
  if (0 === bytes) return "0 B";
8570
8927
  const k = 1024;
8571
8928
  const sizes = [
@@ -8636,6 +8993,7 @@ ${getErrorSuggestion(error.code)}
8636
8993
  RETRY_DELAY_MS: 1000
8637
8994
  };
8638
8995
  const ImageRecognitionParamsSchema = objectType({
8996
+ projectPath: stringType().min(1).describe("\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\uFF0C\u8BC6\u522B\u7ED3\u679C\u5C06\u4FDD\u5B58\u5230\u8BE5\u8DEF\u5F84\u4E0B\u7684.aico/image-recognition\u76EE\u5F55"),
8639
8997
  imagePath: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
8640
8998
  context: stringType().optional().describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
8641
8999
  });
@@ -9043,8 +9401,8 @@ ${getErrorSuggestion(error.code)}
9043
9401
  }
9044
9402
  class analyzer_ImageAnalyzer {
9045
9403
  context;
9046
- async analyzeLongImage(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context) {
9047
- logger.info("ImageAnalyzer: \u5F00\u59CB\u5206\u6790\u957F\u56FE", {
9404
+ async analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context, onSegmentComplete) {
9405
+ logger.info("ImageAnalyzer: \u5F00\u59CB\u6D41\u5F0F\u5206\u6790\u957F\u56FE", {
9048
9406
  imagePath,
9049
9407
  totalSegments: segmentConfig.totalSegments,
9050
9408
  maxConcurrency: concurrencyConfig.maxConcurrency,
@@ -9054,24 +9412,36 @@ ${getErrorSuggestion(error.code)}
9054
9412
  const startTime = Date.now();
9055
9413
  const segmentResults = [];
9056
9414
  try {
9057
- if (1 === segmentConfig.totalSegments) {
9058
- const imageBuffer = await external_sharp_default()(imagePath).toBuffer();
9059
- const segmentInfo = {
9060
- index: 0,
9061
- totalSegments: 1,
9062
- position: {
9063
- x: 0,
9064
- y: 0,
9065
- width: imageInfo.width,
9066
- height: imageInfo.height
9067
- },
9068
- isFirstSegment: true,
9069
- isLastSegment: true,
9070
- hasOverlap: false
9071
- };
9072
- const result = await this.analyzeSegment(imageBuffer, segmentInfo, apiPreference);
9073
- segmentResults.push(result);
9074
- } else segmentResults.push(...await this.processSegmentsConcurrently(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference));
9415
+ const segments = await this.generateSegments(imagePath, imageInfo, segmentConfig);
9416
+ for(let i = 0; i < segments.length; i++){
9417
+ const { buffer, info } = segments[i];
9418
+ try {
9419
+ const result = await this.analyzeSegment(buffer, info, apiPreference);
9420
+ segmentResults.push(result);
9421
+ if (onSegmentComplete) await onSegmentComplete(result, {
9422
+ current: i + 1,
9423
+ total: segments.length
9424
+ });
9425
+ } catch (error) {
9426
+ logger.error(`\u{6BB5}\u{843D} ${info.index} \u{5206}\u{6790}\u{5931}\u{8D25}`, {
9427
+ error
9428
+ });
9429
+ const errorResult = {
9430
+ segmentIndex: info.index,
9431
+ textContent: '',
9432
+ imageDescription: '',
9433
+ confidence: 0,
9434
+ processingTimeMs: 0,
9435
+ apiUsed: 'none',
9436
+ error: error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"
9437
+ };
9438
+ segmentResults.push(errorResult);
9439
+ if (onSegmentComplete) await onSegmentComplete(errorResult, {
9440
+ current: i + 1,
9441
+ total: segments.length
9442
+ });
9443
+ }
9444
+ }
9075
9445
  const summary = this.generateProcessingSummary(segmentResults, startTime);
9076
9446
  const result = {
9077
9447
  imageInfo,
@@ -9080,7 +9450,7 @@ ${getErrorSuggestion(error.code)}
9080
9450
  outputPath: '',
9081
9451
  success: 0 === summary.failedSegments
9082
9452
  };
9083
- logger.info("\u957F\u56FE\u5206\u6790\u5B8C\u6210", {
9453
+ logger.info("\u957F\u56FE\u6D41\u5F0F\u5206\u6790\u5B8C\u6210", {
9084
9454
  imagePath,
9085
9455
  totalSegments: summary.totalSegments,
9086
9456
  successfulSegments: summary.successfulSegments,
@@ -9089,7 +9459,7 @@ ${getErrorSuggestion(error.code)}
9089
9459
  });
9090
9460
  return result;
9091
9461
  } catch (error) {
9092
- logger.error("\u957F\u56FE\u5206\u6790\u5931\u8D25", {
9462
+ logger.error("\u957F\u56FE\u6D41\u5F0F\u5206\u6790\u5931\u8D25", {
9093
9463
  imagePath,
9094
9464
  error
9095
9465
  });
@@ -9099,6 +9469,9 @@ ${getErrorSuggestion(error.code)}
9099
9469
  });
9100
9470
  }
9101
9471
  }
9472
+ async analyzeLongImage(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context) {
9473
+ return this.analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference, context);
9474
+ }
9102
9475
  async processSegmentsConcurrently(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference) {
9103
9476
  const results = [];
9104
9477
  const { maxConcurrency, batchSize, delayBetweenBatches } = concurrencyConfig;
@@ -9278,7 +9651,7 @@ ${getErrorSuggestion(error.code)}
9278
9651
  let prompt = '';
9279
9652
  prompt = this.context ? `${this.context}
9280
9653
 
9281
- \u{8BF7}\u{6839}\u{636E}\u{4E0A}\u{8FF0}\u{4EFB}\u{52A1}\u{8981}\u{6C42}\u{FF0C}\u{5206}\u{6790}\u{8FD9}\u{5F20}\u{56FE}\u{7247}\u{5E76}\u{63D0}\u{4F9B}\u{76F8}\u{5173}\u{7ED3}\u{679C}\u{3002}\u{53EA}\u{8F93}\u{51FA}\u{4E0E}\u{4EFB}\u{52A1}\u{76F8}\u{5173}\u{7684}\u{5185}\u{5BB9}\u{FF0C}\u{4E0D}\u{8981}\u{6DFB}\u{52A0}\u{989D}\u{5916}\u{7684}\u{89E3}\u{91CA}\u{6216}\u{63CF}\u{8FF0}\u{3002}
9654
+ You must provide a complete and detailed description of all content in the image, including scenes, objects, text, colors, layout, relationships, and all other visible elements and details. Ensure the description is detailed enough so that subsequent text-based language models can fully understand the image content through text alone.
9282
9655
 
9283
9656
  ` : `\u{8BF7}\u{5BF9}\u{8FD9}\u{5F20}\u{56FE}\u{7247}\u{8FDB}\u{884C}\u{9AD8}\u{7CBE}\u{5EA6}OCR\u{6587}\u{5B57}\u{8BC6}\u{522B}\u{FF0C}\u{53EA}\u{8F93}\u{51FA}\u{56FE}\u{7247}\u{4E2D}\u{7684}\u{539F}\u{59CB}\u{6587}\u{5B57}\u{5185}\u{5BB9}\u{3002}
9284
9657
 
@@ -9296,7 +9669,10 @@ ${getErrorSuggestion(error.code)}
9296
9669
  else prompt += `\u{8FD9}\u{662F}\u{56FE}\u{7247}\u{7684}\u{4E2D}\u{95F4}\u{90E8}\u{5206}\u{3002}`;
9297
9670
  if (segmentInfo.hasOverlap) prompt += `\u{6CE8}\u{610F}\u{FF1A}\u{8FD9}\u{4E2A}\u{6BB5}\u{843D}\u{4E0E}\u{4E0A}\u{4E00}\u{6BB5}\u{6709}\u{91CD}\u{53E0}\u{533A}\u{57DF}\u{FF0C}\u{8BF7}\u{907F}\u{514D}\u{91CD}\u{590D}\u{8BC6}\u{522B}\u{76F8}\u{540C}\u{5185}\u{5BB9}\u{3002}`;
9298
9671
  }
9299
- prompt += `
9672
+ if (this.context) prompt += `
9673
+
9674
+ Always respond in Chinese-simplified. \u{8BF7}\u{786E}\u{4FDD}\u{63CF}\u{8FF0}\u{8DB3}\u{591F}\u{8BE6}\u{7EC6}\u{FF0C}\u{4F7F}\u{540E}\u{7EED}\u{7684}\u{7EAF}\u{6587}\u{672C}\u{8BED}\u{8A00}\u{6A21}\u{578B}\u{80FD}\u{591F}\u{5B8C}\u{5168}\u{7406}\u{89E3}\u{56FE}\u{7247}\u{5185}\u{5BB9}\u{3002}`;
9675
+ else prompt += `
9300
9676
 
9301
9677
  \u{8BF7}\u{76F4}\u{63A5}\u{8F93}\u{51FA}\u{8BC6}\u{522B}\u{5230}\u{7684}\u{6587}\u{5B57}\u{5185}\u{5BB9}\u{FF0C}\u{4E0D}\u{8981}\u{6DFB}\u{52A0}\u{4EFB}\u{4F55}\u{683C}\u{5F0F}\u{6807}\u{8BB0}\u{3001}\u{8BF4}\u{660E}\u{6587}\u{5B57}\u{6216}\u{63CF}\u{8FF0}\u{6027}\u{5185}\u{5BB9}\u{3002}
9302
9678
  \u{5982}\u{679C}\u{56FE}\u{7247}\u{4E2D}\u{6CA1}\u{6709}\u{6587}\u{5B57}\u{FF0C}\u{8BF7}\u{8F93}\u{51FA}"\u{65E0}\u{6587}\u{5B57}\u{5185}\u{5BB9}"\u{3002}`;
@@ -9402,11 +9778,13 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9402
9778
  this.configCalculator = new ConfigCalculator();
9403
9779
  this.analyzer = new analyzer_ImageAnalyzer();
9404
9780
  }
9405
- async processImage(imagePath, context) {
9781
+ async processImage(imagePath, projectPath, context, callbacks) {
9406
9782
  const startTime = Date.now();
9407
9783
  logger.info("ImageRecognitionProcessor: \u5F00\u59CB\u5904\u7406\u56FE\u7247", {
9408
9784
  imagePath
9409
9785
  });
9786
+ let outputPath = '';
9787
+ const segmentResults = [];
9410
9788
  try {
9411
9789
  await this.validateImageFile(imagePath);
9412
9790
  const validation = await this.preprocessor.validateImage(imagePath);
@@ -9428,55 +9806,51 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9428
9806
  segmentHeight: segmentConfig.segmentHeight,
9429
9807
  maxConcurrency: concurrencyConfig.maxConcurrency
9430
9808
  });
9431
- const analysisResult = await this.analyzer.analyzeLongImage(imagePath, imageInfo, segmentConfig, concurrencyConfig, 'auto', context);
9432
- const outputPath = await this.generateSingleOutputFile(imageInfo, analysisResult.segmentResults, analysisResult.summary);
9433
- const totalTime = Date.now() - startTime;
9434
- logger.info("\u56FE\u7247\u5904\u7406\u5B8C\u6210", {
9809
+ outputPath = await this.initializeOutputFile(imageInfo, segmentConfig.totalSegments, projectPath);
9810
+ callbacks?.onStart?.({
9435
9811
  outputPath,
9812
+ totalSegments: segmentConfig.totalSegments,
9813
+ imageInfo
9814
+ });
9815
+ const analysisResult = await this.analyzer.analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, 'auto', context, async (result, progress)=>{
9816
+ segmentResults.push(result);
9817
+ await this.appendSegmentToFile(outputPath, result);
9818
+ callbacks?.onSegmentComplete?.(result, progress);
9819
+ });
9820
+ await this.finalizeOutputFile(outputPath, analysisResult.summary);
9821
+ const totalTime = Date.now() - startTime;
9822
+ const summary = {
9436
9823
  totalSegments: analysisResult.summary.totalSegments,
9437
9824
  successfulSegments: analysisResult.summary.successfulSegments,
9825
+ failedSegments: analysisResult.summary.failedSegments,
9826
+ successRate: analysisResult.summary.successRate,
9827
+ totalTextCharacters: analysisResult.summary.totalTextCharacters,
9828
+ totalProcessingTimeMs: totalTime,
9829
+ averageConfidence: analysisResult.summary.averageConfidence
9830
+ };
9831
+ callbacks?.onComplete?.(analysisResult.summary);
9832
+ logger.info("\u56FE\u7247\u5904\u7406\u5B8C\u6210", {
9833
+ outputPath,
9834
+ totalSegments: summary.totalSegments,
9835
+ successfulSegments: summary.successfulSegments,
9438
9836
  totalTimeMs: totalTime
9439
9837
  });
9440
9838
  return {
9441
9839
  outputPath,
9442
- summary: {
9443
- totalSegments: analysisResult.summary.totalSegments,
9444
- successfulSegments: analysisResult.summary.successfulSegments,
9445
- failedSegments: analysisResult.summary.failedSegments,
9446
- successRate: analysisResult.summary.successRate,
9447
- totalTextCharacters: analysisResult.summary.totalTextCharacters,
9448
- totalProcessingTimeMs: totalTime,
9449
- averageConfidence: analysisResult.summary.averageConfidence
9450
- }
9840
+ summary
9451
9841
  };
9452
9842
  } catch (error) {
9453
9843
  logger.error("\u56FE\u7247\u5904\u7406\u5931\u8D25", {
9454
9844
  imagePath,
9455
9845
  error
9456
9846
  });
9847
+ callbacks?.onError?.(error instanceof Error ? error : new Error(String(error)));
9457
9848
  throw error;
9458
9849
  }
9459
9850
  }
9460
- async validateImageFile(imagePath) {
9461
- try {
9462
- const stats = await external_fs_namespaceObject.promises.stat(imagePath);
9463
- if (!stats.isFile()) throw new ImageRecognitionError("\u63D0\u4F9B\u7684\u8DEF\u5F84\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6", types_ErrorTypes.FILE_NOT_FOUND, {
9464
- imagePath
9465
- });
9466
- } catch (error) {
9467
- if ('ENOENT' === error.code) throw new ImageRecognitionError("\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728", types_ErrorTypes.FILE_NOT_FOUND, {
9468
- imagePath
9469
- });
9470
- throw new ImageRecognitionError(`\u{6587}\u{4EF6}\u{8BBF}\u{95EE}\u{9519}\u{8BEF}: ${error.message}`, types_ErrorTypes.VALIDATION_ERROR, {
9471
- imagePath,
9472
- originalError: error
9473
- });
9474
- }
9475
- }
9476
- async generateSingleOutputFile(imageInfo, segmentResults, summary) {
9477
- const baseDir = getStorageDir();
9851
+ async initializeOutputFile(imageInfo, totalSegments, projectPath) {
9478
9852
  const dateDir = new Date().toISOString().split('T')[0];
9479
- const outputDirectory = external_path_namespaceObject.join(baseDir, 'image-recognition', dateDir);
9853
+ const outputDirectory = external_path_namespaceObject.join(projectPath, '.aico', 'image-recognition', dateDir);
9480
9854
  await external_fs_namespaceObject.promises.mkdir(outputDirectory, {
9481
9855
  recursive: true
9482
9856
  });
@@ -9484,39 +9858,78 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9484
9858
  const imageBaseName = external_path_namespaceObject.basename(imageInfo.fileName, external_path_namespaceObject.extname(imageInfo.fileName));
9485
9859
  const fileName = `${imageBaseName}-${timestamp}.md`;
9486
9860
  const outputPath = external_path_namespaceObject.join(outputDirectory, fileName);
9487
- const allTextContent = segmentResults.filter((result)=>result.textContent && result.textContent.trim()).map((result)=>result.textContent.trim()).join('\n\n');
9488
- const content = `# ${imageInfo.fileName} - \u{56FE}\u{7247}\u{6587}\u{5B57}\u{8BC6}\u{522B}\u{7ED3}\u{679C}
9861
+ const header = `# ${imageInfo.fileName} - \u{56FE}\u{7247}\u{6587}\u{5B57}\u{8BC6}\u{522B}\u{7ED3}\u{679C}
9489
9862
 
9490
9863
  **\u{8BC6}\u{522B}\u{65F6}\u{95F4}**: ${new Date().toLocaleString('zh-CN')}
9491
9864
  **\u{56FE}\u{7247}\u{5C3A}\u{5BF8}**: ${imageInfo.width} \xd7 ${imageInfo.height} \u{50CF}\u{7D20}
9492
- **\u{5904}\u{7406}\u{6BB5}\u{6570}**: ${summary.totalSegments}
9493
- **\u{6210}\u{529F}\u{6BB5}\u{6570}**: ${summary.successfulSegments}
9494
- **\u{6587}\u{5B57}\u{5B57}\u{7B26}\u{603B}\u{6570}**: ${summary.totalTextCharacters.toLocaleString()}
9495
- **\u{5E73}\u{5747}\u{7F6E}\u{4FE1}\u{5EA6}**: ${(100 * summary.averageConfidence).toFixed(1)}%
9865
+ **\u{9884}\u{8BA1}\u{6BB5}\u{6570}**: ${totalSegments}
9866
+ **\u{72B6}\u{6001}**: \u{1F504} \u{8BC6}\u{522B}\u{4E2D}...
9496
9867
 
9497
9868
  ---
9498
9869
 
9499
9870
  ## \u{8BC6}\u{522B}\u{7684}\u{6587}\u{5B57}\u{5185}\u{5BB9}
9500
9871
 
9501
- ${allTextContent || "\u672A\u8BC6\u522B\u5230\u6587\u5B57\u5185\u5BB9"}
9502
-
9503
- ---
9504
-
9505
- **\u{8BC6}\u{522B}\u{5B8C}\u{6210}\u{65F6}\u{95F4}**: ${new Date().toLocaleString('zh-CN')}
9506
9872
  `;
9507
- await external_fs_namespaceObject.promises.writeFile(outputPath, content, 'utf8');
9508
- logger.info("\u8F93\u51FA\u6587\u4EF6\u751F\u6210\u5B8C\u6210", {
9873
+ await external_fs_namespaceObject.promises.writeFile(outputPath, header, 'utf8');
9874
+ logger.info("\u8F93\u51FA\u6587\u4EF6\u521D\u59CB\u5316\u5B8C\u6210", {
9509
9875
  outputPath,
9510
- fileName,
9511
- contentLength: content.length
9876
+ totalSegments
9512
9877
  });
9513
9878
  return outputPath;
9514
9879
  }
9880
+ async appendSegmentToFile(outputPath, result) {
9881
+ let content = '';
9882
+ if (result.error) content = `<!-- \u{6BB5}\u{843D} ${result.segmentIndex + 1} \u{5904}\u{7406}\u{5931}\u{8D25}: ${result.error} -->\n\n`;
9883
+ else if (result.textContent && result.textContent.trim()) content = `${result.textContent.trim()}\n\n`;
9884
+ if (content) await external_fs_namespaceObject.promises.appendFile(outputPath, content, 'utf8');
9885
+ }
9886
+ async finalizeOutputFile(outputPath, summary) {
9887
+ const footer = `
9888
+ ---
9889
+
9890
+ ## \u{5904}\u{7406}\u{6458}\u{8981}
9891
+
9892
+ - **\u{603B}\u{6BB5}\u{6570}**: ${summary.totalSegments}
9893
+ - **\u{6210}\u{529F}\u{6BB5}\u{6570}**: ${summary.successfulSegments}
9894
+ - **\u{5931}\u{8D25}\u{6BB5}\u{6570}**: ${summary.failedSegments}
9895
+ - **\u{6210}\u{529F}\u{7387}**: ${(100 * summary.successRate).toFixed(1)}%
9896
+ - **\u{6587}\u{5B57}\u{5B57}\u{7B26}\u{603B}\u{6570}**: ${summary.totalTextCharacters.toLocaleString()}
9897
+ - **\u{5E73}\u{5747}\u{7F6E}\u{4FE1}\u{5EA6}**: ${(100 * summary.averageConfidence).toFixed(1)}%
9898
+ - **\u{5904}\u{7406}\u{8017}\u{65F6}**: ${(summary.totalProcessingTimeMs / 1000).toFixed(2)}\u{79D2}
9899
+
9900
+ **\u{72B6}\u{6001}**: \u{2705} \u{8BC6}\u{522B}\u{5B8C}\u{6210}
9901
+ **\u{5B8C}\u{6210}\u{65F6}\u{95F4}**: ${new Date().toLocaleString('zh-CN')}
9902
+ `;
9903
+ await external_fs_namespaceObject.promises.appendFile(outputPath, footer, 'utf8');
9904
+ const content = await external_fs_namespaceObject.promises.readFile(outputPath, 'utf8');
9905
+ const updatedContent = content.replace("**\u72B6\u6001**: \uD83D\uDD04 \u8BC6\u522B\u4E2D...", "**\u72B6\u6001**: \u2705 \u8BC6\u522B\u5B8C\u6210");
9906
+ await external_fs_namespaceObject.promises.writeFile(outputPath, updatedContent, 'utf8');
9907
+ logger.info("\u8F93\u51FA\u6587\u4EF6\u5B8C\u6210", {
9908
+ outputPath
9909
+ });
9910
+ }
9911
+ async validateImageFile(imagePath) {
9912
+ try {
9913
+ const stats = await external_fs_namespaceObject.promises.stat(imagePath);
9914
+ if (!stats.isFile()) throw new ImageRecognitionError("\u63D0\u4F9B\u7684\u8DEF\u5F84\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6", types_ErrorTypes.FILE_NOT_FOUND, {
9915
+ imagePath
9916
+ });
9917
+ } catch (error) {
9918
+ if ('ENOENT' === error.code) throw new ImageRecognitionError("\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728", types_ErrorTypes.FILE_NOT_FOUND, {
9919
+ imagePath
9920
+ });
9921
+ throw new ImageRecognitionError(`\u{6587}\u{4EF6}\u{8BBF}\u{95EE}\u{9519}\u{8BEF}: ${error.message}`, types_ErrorTypes.VALIDATION_ERROR, {
9922
+ imagePath,
9923
+ originalError: error
9924
+ });
9925
+ }
9926
+ }
9515
9927
  }
9516
9928
  const imageRecognitionAgentTool = {
9517
9929
  name: "analyzeLongImage",
9518
- description: "\u4E13\u95E8\u5904\u7406\u957F\u56FE\u7684\u5185\u5BB9\u8BC6\u522B\u667A\u80FD\u4F53\uFF0C\u652F\u6301\u5206\u6BB5\u5904\u7406\u548C\u7EFC\u5408\u5185\u5BB9\u8BC6\u522B\uFF08\u6587\u5B57+\u56FE\u50CF\u63CF\u8FF0\uFF09\uFF0C\u4EE5\u4E2D\u6587Markdown\u683C\u5F0F\u8F93\u51FA\u3002\u53EA\u9700\u63D0\u4F9B\u56FE\u7247\u8DEF\u5F84\u5373\u53EF\uFF0C\u5176\u4ED6\u53C2\u6570\u81EA\u52A8\u4F18\u5316\u3002",
9930
+ description: "\u4E13\u95E8\u5904\u7406\u957F\u56FE\u7684\u5185\u5BB9\u8BC6\u522B\u667A\u80FD\u4F53\uFF0C\u652F\u6301\u5206\u6BB5\u5904\u7406\u548C\u6D41\u5F0F\u8F93\u51FA\u3002\u8BC6\u522B\u7ED3\u679C\u5B9E\u65F6\u5199\u5165Markdown\u6587\u4EF6\uFF0C\u53EF\u8FB9\u5904\u7406\u8FB9\u67E5\u770B\u3002\u8FD4\u56DE\u7ED3\u679C\u5305\u542B\u6587\u4EF6\u8DEF\u5F84\u548C\u5B8C\u6574\u8BC6\u522B\u5185\u5BB9\u3002",
9519
9931
  inputSchema: {
9932
+ projectPath: stringType().min(1).describe("\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\uFF0C\u8BC6\u522B\u7ED3\u679C\u5C06\u4FDD\u5B58\u5230\u8BE5\u8DEF\u5F84\u4E0B\u7684.aico/image-recognition\u76EE\u5F55"),
9520
9933
  imagePath: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
9521
9934
  context: stringType().optional().describe("\u4E0A\u4E0B\u6587\u5185\u5BB9\uFF0C\u7528\u4E8E\u6307\u5BFC\u56FE\u7247\u5206\u6790\u7684\u65B9\u5411\u548C\u8303\u56F4")
9522
9935
  },
@@ -9526,13 +9939,21 @@ ${allTextContent || "\u672A\u8BC6\u522B\u5230\u6587\u5B57\u5185\u5BB9"}
9526
9939
  args
9527
9940
  });
9528
9941
  try {
9529
- const { imagePath, context } = ImageRecognitionParamsSchema.parse(args);
9942
+ const { projectPath, imagePath, context } = ImageRecognitionParamsSchema.parse(args);
9530
9943
  const processor = new ImageRecognitionProcessor();
9531
- const result = await processor.processImage(imagePath, context);
9944
+ const result = await processor.processImage(imagePath, projectPath, context);
9532
9945
  logger.info("\u56FE\u7247\u5185\u5BB9\u8BC6\u522B\u667A\u80FD\u4F53: \u5904\u7406\u5B8C\u6210", {
9533
9946
  outputPath: result.outputPath,
9534
9947
  summary: result.summary
9535
9948
  });
9949
+ let fileContent = '';
9950
+ try {
9951
+ fileContent = await external_fs_namespaceObject.promises.readFile(result.outputPath, 'utf8');
9952
+ } catch (readError) {
9953
+ logger.warn("\u8BFB\u53D6\u7ED3\u679C\u6587\u4EF6\u5931\u8D25", {
9954
+ error: readError
9955
+ });
9956
+ }
9536
9957
  return {
9537
9958
  content: [
9538
9959
  {
@@ -9547,10 +9968,14 @@ ${allTextContent || "\u672A\u8BC6\u522B\u5230\u6587\u5B57\u5185\u5BB9"}
9547
9968
  - \u{5E73}\u{5747}\u{7F6E}\u{4FE1}\u{5EA6}: ${(100 * result.summary.averageConfidence).toFixed(1)}%
9548
9969
  - \u{5904}\u{7406}\u{8017}\u{65F6}: ${(result.summary.totalProcessingTimeMs / 1000).toFixed(2)}\u{79D2}
9549
9970
 
9550
- \u{1F4C4} **\u{7ED3}\u{679C}\u{6587}\u{4EF6}**:
9971
+ \u{1F4C4} **\u{7ED3}\u{679C}\u{6587}\u{4EF6}\u{8DEF}\u{5F84}**:
9551
9972
  \`${result.outputPath}\`
9552
9973
 
9553
- \u{60A8}\u{53EF}\u{4EE5}\u{6253}\u{5F00}\u{4E0A}\u{8FF0}\u{6587}\u{4EF6}\u{67E5}\u{770B}\u{8BE6}\u{7EC6}\u{7684}\u{8BC6}\u{522B}\u{7ED3}\u{679C}\u{3002}`
9974
+ ---
9975
+
9976
+ ## \u{8BC6}\u{522B}\u{7684}\u{5B8C}\u{6574}\u{5185}\u{5BB9}
9977
+
9978
+ ${fileContent}`
9554
9979
  }
9555
9980
  ]
9556
9981
  };
@@ -10503,6 +10928,264 @@ ${requirement_description}
10503
10928
  }
10504
10929
  }
10505
10930
  };
10931
+ const external_url_namespaceObject = require("url");
10932
+ const external_docxtemplater_namespaceObject = require("docxtemplater");
10933
+ var external_docxtemplater_default = /*#__PURE__*/ __webpack_require__.n(external_docxtemplater_namespaceObject);
10934
+ const external_pizzip_namespaceObject = require("pizzip");
10935
+ var external_pizzip_default = /*#__PURE__*/ __webpack_require__.n(external_pizzip_namespaceObject);
10936
+ function getTemplatePath() {
10937
+ let currentDir;
10938
+ try {
10939
+ currentDir = external_path_namespaceObject.dirname((0, external_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
10940
+ } catch {
10941
+ currentDir = __dirname;
10942
+ }
10943
+ return external_path_namespaceObject.resolve(currentDir, "\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u6A21\u677F.docx");
10944
+ }
10945
+ async function renderTechSpecDoc(data, outputDir) {
10946
+ try {
10947
+ const templatePath = getTemplatePath();
10948
+ try {
10949
+ await promises_namespaceObject.access(templatePath);
10950
+ } catch {
10951
+ return {
10952
+ success: false,
10953
+ outputPath: null,
10954
+ error: `\u{6A21}\u{677F}\u{6587}\u{4EF6}\u{4E0D}\u{5B58}\u{5728}: ${templatePath}`
10955
+ };
10956
+ }
10957
+ const templateContent = await promises_namespaceObject.readFile(templatePath);
10958
+ const zip = new (external_pizzip_default())(templateContent);
10959
+ const doc = new (external_docxtemplater_default())(zip, {
10960
+ paragraphLoop: true,
10961
+ linebreaks: true,
10962
+ delimiters: {
10963
+ start: '{',
10964
+ end: '}'
10965
+ }
10966
+ });
10967
+ doc.render(data);
10968
+ const output = doc.getZip().generate({
10969
+ type: 'nodebuffer',
10970
+ compression: 'DEFLATE'
10971
+ });
10972
+ await promises_namespaceObject.mkdir(outputDir, {
10973
+ recursive: true
10974
+ });
10975
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
10976
+ const outputFileName = `\u{6280}\u{672F}\u{89C4}\u{683C}\u{8BF4}\u{660E}\u{4E66}_${data.projectName}_${data.moduleName}_${timestamp}.docx`;
10977
+ const outputPath = external_path_namespaceObject.join(outputDir, outputFileName);
10978
+ await promises_namespaceObject.writeFile(outputPath, output);
10979
+ logger.info("\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u6210\u529F", {
10980
+ outputPath
10981
+ });
10982
+ return {
10983
+ success: true,
10984
+ outputPath
10985
+ };
10986
+ } catch (error) {
10987
+ logger.error("\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u5931\u8D25", {
10988
+ error: error.message
10989
+ });
10990
+ if (error.properties && error.properties.errors) {
10991
+ const errorMessages = error.properties.errors.map((e)=>e.properties?.explanation || e.message).join('; ');
10992
+ return {
10993
+ success: false,
10994
+ outputPath: null,
10995
+ error: `\u{6A21}\u{677F}\u{6E32}\u{67D3}\u{9519}\u{8BEF}: ${errorMessages}`
10996
+ };
10997
+ }
10998
+ return {
10999
+ success: false,
11000
+ outputPath: null,
11001
+ error: error.message || "\u672A\u77E5\u9519\u8BEF"
11002
+ };
11003
+ }
11004
+ }
11005
+ const TableFieldDetailSchema = objectType({
11006
+ id: stringType().describe("\u5E8F\u53F7"),
11007
+ fieldName: stringType().describe("\u5B57\u6BB5\u540D"),
11008
+ fieldType: stringType().describe("\u5B57\u6BB5\u7C7B\u578B"),
11009
+ fieldDescription: stringType().describe("\u5B57\u6BB5\u63CF\u8FF0"),
11010
+ fieldLength: stringType().describe("\u5B57\u6BB5\u957F\u5EA6")
11011
+ });
11012
+ const TableInfoSchema = objectType({
11013
+ id: stringType().describe("\u5E8F\u53F7"),
11014
+ tableName: stringType().describe("\u8868\u540D\u79F0"),
11015
+ entityName: stringType().describe("\u5BF9\u5E94\u5B9E\u4F53\u540D\u79F0"),
11016
+ tableDescription: stringType().describe("\u63CF\u8FF0"),
11017
+ tableDetailList: arrayType(TableFieldDetailSchema).default([]).describe("\u8868\u5B57\u6BB5\u8BE6\u60C5\u5217\u8868")
11018
+ });
11019
+ const ParameterInfoSchema = objectType({
11020
+ id: stringType().describe("\u5E8F\u53F7"),
11021
+ propertyType: stringType().describe("\u7C7B\u578B"),
11022
+ propertyName: stringType().describe("\u5C5E\u6027\u540D"),
11023
+ required: stringType().describe("\u662F\u5426\u5FC5\u586B"),
11024
+ propertyDesc: stringType().describe("\u63CF\u8FF0")
11025
+ });
11026
+ const ReturnResultInfoSchema = objectType({
11027
+ id: stringType().describe("\u5E8F\u53F7"),
11028
+ propertyType: stringType().describe("\u7C7B\u578B"),
11029
+ propertyName: stringType().describe("\u5C5E\u6027\u540D"),
11030
+ propertyDesc: stringType().describe("\u63CF\u8FF0")
11031
+ });
11032
+ const InterfaceDesignDetailSchema = objectType({
11033
+ functionName: stringType().describe("\u529F\u80FD\u540D\u79F0"),
11034
+ interfaceDesc: stringType().describe("\u63A5\u53E3\u63CF\u8FF0"),
11035
+ className: stringType().describe("\u63A5\u53E3\u7C7B\u540D"),
11036
+ methodName: stringType().describe("\u65B9\u6CD5\u540D"),
11037
+ parameterList: arrayType(ParameterInfoSchema).default([]).describe("\u53C2\u6570\u5217\u8868"),
11038
+ returnResultList: arrayType(ReturnResultInfoSchema).default([]).describe("\u8FD4\u56DE\u7ED3\u679C\u5217\u8868"),
11039
+ implementLogic: stringType().describe("\u5B9E\u73B0\u903B\u8F91")
11040
+ });
11041
+ const DesignDetailSchema = objectType({
11042
+ serviceName: stringType().describe("\u670D\u52A1\u540D\u79F0"),
11043
+ serviceDesc: stringType().describe("\u529F\u80FD\u63CF\u8FF0"),
11044
+ interfaceDesignDetailList: arrayType(InterfaceDesignDetailSchema).default([]).describe("\u63A5\u53E3\u8BBE\u8BA1\u8BE6\u60C5\u5217\u8868")
11045
+ });
11046
+ const InterfaceDetailSchema = objectType({
11047
+ id: stringType().describe("\u5E8F\u53F7"),
11048
+ functionDescription: stringType().describe("\u529F\u80FD\u63CF\u8FF0"),
11049
+ serviceName: stringType().describe("\u670D\u52A1\u540D"),
11050
+ methodName: stringType().describe("\u65B9\u6CD5\u540D")
11051
+ });
11052
+ const ServiceInterfaceSchema = objectType({
11053
+ id: stringType().describe("\u5E8F\u53F7"),
11054
+ serviceType: stringType().describe("\u670D\u52A1\u7C7B\u578B"),
11055
+ serviceEnglishName: stringType().describe("\u670D\u52A1\u82F1\u6587\u540D\u79F0"),
11056
+ serviceChineseName: stringType().describe("\u670D\u52A1\u4E2D\u6587\u540D\u79F0"),
11057
+ serviceDescription: stringType().describe("\u670D\u52A1\u63CF\u8FF0"),
11058
+ interfaceDetailList: arrayType(InterfaceDetailSchema).default([]).describe("\u63A5\u53E3\u8BE6\u60C5\u5217\u8868")
11059
+ });
11060
+ const techSpecGeneratorTool = {
11061
+ name: 'tech-spec-generator',
11062
+ description: `\u{6280}\u{672F}\u{89C4}\u{683C}\u{8BF4}\u{660E}\u{4E66}\u{751F}\u{6210}\u{5DE5}\u{5177} - \u{6839}\u{636E}\u{6536}\u{96C6}\u{7684}\u{4EE3}\u{7801}\u{4FE1}\u{606F}\u{751F}\u{6210}\u{6280}\u{672F}\u{89C4}\u{683C}\u{8BF4}\u{660E}\u{4E66}\u{3002}
11063
+
11064
+ \u{4F7F}\u{7528}\u{6D41}\u{7A0B}\u{FF1A}
11065
+ 1. MCP\u{5BA2}\u{6237}\u{7AEF}\u{5148}\u{8BFB}\u{53D6}\u{76EE}\u{6807}\u{4EE3}\u{7801}\u{76EE}\u{5F55}\u{FF0C}\u{5206}\u{6790}\u{5E76}\u{6536}\u{96C6}\u{4EE5}\u{4E0B}\u{4FE1}\u{606F}\u{FF1A}
11066
+ - \u{6570}\u{636E}\u{8868}\u{8BBE}\u{8BA1}\u{FF08}\u{8868}\u{540D}\u{3001}\u{5B57}\u{6BB5}\u{4FE1}\u{606F}\u{7B49}\u{FF09}
11067
+ - \u{670D}\u{52A1}\u{63A5}\u{53E3}\u{8BBE}\u{8BA1}\u{FF08}\u{670D}\u{52A1}\u{540D}\u{3001}\u{63A5}\u{53E3}\u{65B9}\u{6CD5}\u{3001}\u{53C2}\u{6570}\u{3001}\u{8FD4}\u{56DE}\u{503C}\u{7B49}\u{FF09}
11068
+ - \u{529F}\u{80FD}\u{8BBE}\u{8BA1}\u{8BE6}\u{60C5}\u{FF08}\u{529F}\u{80FD}\u{540D}\u{79F0}\u{3001}\u{63CF}\u{8FF0}\u{3001}\u{5B9E}\u{73B0}\u{903B}\u{8F91}\u{7B49}\u{FF09}
11069
+ 2. \u{5C06}\u{6536}\u{96C6}\u{7684}\u{6570}\u{636E}\u{901A}\u{8FC7} techSpecData \u{53C2}\u{6570}\u{4F20}\u{9012}\u{7ED9}\u{8BE5}\u{5DE5}\u{5177}
11070
+ 3. \u{5DE5}\u{5177}\u{4F7F}\u{7528} .aico/create-tect-docs/\u{6280}\u{672F}\u{89C4}\u{683C}\u{8BF4}\u{660E}\u{4E66}\u{6A21}\u{677F}.docx \u{6A21}\u{677F}\u{6E32}\u{67D3}\u{751F}\u{6210}\u{6587}\u{6863}
11071
+ 4. \u{6587}\u{6863}\u{8F93}\u{51FA}\u{5230} projectPath/.aico/tect/ \u{76EE}\u{5F55}`,
11072
+ inputSchema: {
11073
+ projectPath: stringType().min(1).describe("\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\uFF0C\u751F\u6210\u7684\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u4FDD\u5B58\u5230\u8BE5\u8DEF\u5F84\u4E0B\u7684.aico/tect\u76EE\u5F55"),
11074
+ techSpecData: objectType({
11075
+ projectName: stringType().describe("\u9879\u76EE\u540D\u79F0"),
11076
+ moduleName: stringType().describe("\u6A21\u5757\u540D\u79F0"),
11077
+ year: stringType().optional().describe("\u5E74\u4EFD\uFF0C\u9ED8\u8BA4\u5F53\u524D\u5E74\u4EFD"),
11078
+ month: stringType().optional().describe("\u6708\u4EFD\uFF0C\u9ED8\u8BA4\u5F53\u524D\u6708\u4EFD"),
11079
+ referDoc: stringType().optional().describe("\u53C2\u8003\u6587\u6863"),
11080
+ serviceInterfaceList: arrayType(ServiceInterfaceSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u6E05\u5355"),
11081
+ designDetailList: arrayType(DesignDetailSchema).default([]).describe("\u670D\u52A1\u63A5\u53E3\u8BBE\u8BA1\u8BE6\u60C5"),
11082
+ tableInfoList: arrayType(TableInfoSchema).default([]).describe("\u6570\u636E\u5E93\u8868\u4FE1\u606F\u5217\u8868")
11083
+ }).describe("\u6280\u672F\u89C4\u683C\u6570\u636E\uFF0C\u7531MCP\u5BA2\u6237\u7AEF\u901A\u8FC7\u5206\u6790\u4EE3\u7801\u76EE\u5F55\u6536\u96C6")
11084
+ },
11085
+ handler: async (args)=>{
11086
+ try {
11087
+ const { projectPath, techSpecData } = args;
11088
+ if (!projectPath) return {
11089
+ content: [
11090
+ {
11091
+ type: 'text',
11092
+ text: JSON.stringify({
11093
+ success: false,
11094
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AprojectPath",
11095
+ data: null
11096
+ })
11097
+ }
11098
+ ],
11099
+ isError: true
11100
+ };
11101
+ if (!techSpecData) return {
11102
+ content: [
11103
+ {
11104
+ type: 'text',
11105
+ text: JSON.stringify({
11106
+ success: false,
11107
+ message: "\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570\uFF1AtechSpecData",
11108
+ data: null
11109
+ })
11110
+ }
11111
+ ],
11112
+ isError: true
11113
+ };
11114
+ const now = new Date();
11115
+ const data = {
11116
+ projectName: techSpecData.projectName || "\u672A\u547D\u540D\u9879\u76EE",
11117
+ moduleName: techSpecData.moduleName || "\u672A\u547D\u540D\u6A21\u5757",
11118
+ year: techSpecData.year || String(now.getFullYear()),
11119
+ month: techSpecData.month || String(now.getMonth() + 1).padStart(2, '0'),
11120
+ referDoc: techSpecData.referDoc || "\u65E0",
11121
+ serviceInterfaceList: techSpecData.serviceInterfaceList || [],
11122
+ designDetailList: techSpecData.designDetailList || [],
11123
+ tableInfoList: techSpecData.tableInfoList || []
11124
+ };
11125
+ const outputDir = external_path_namespaceObject.join(projectPath, '.aico', 'tect');
11126
+ logger.info("\u5F00\u59CB\u751F\u6210\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66", {
11127
+ projectPath,
11128
+ outputDir,
11129
+ projectName: data.projectName,
11130
+ moduleName: data.moduleName,
11131
+ tableCount: data.tableInfoList.length,
11132
+ serviceCount: data.serviceInterfaceList.length
11133
+ });
11134
+ const result = await renderTechSpecDoc(data, outputDir);
11135
+ if (result.success) return {
11136
+ content: [
11137
+ {
11138
+ type: 'text',
11139
+ text: JSON.stringify({
11140
+ success: true,
11141
+ message: "\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u6210\u529F",
11142
+ data: {
11143
+ outputPath: result.outputPath,
11144
+ projectName: data.projectName,
11145
+ moduleName: data.moduleName,
11146
+ statistics: {
11147
+ tableCount: data.tableInfoList.length,
11148
+ serviceCount: data.serviceInterfaceList.length,
11149
+ designCount: data.designDetailList.length
11150
+ }
11151
+ }
11152
+ })
11153
+ }
11154
+ ]
11155
+ };
11156
+ return {
11157
+ content: [
11158
+ {
11159
+ type: 'text',
11160
+ text: JSON.stringify({
11161
+ success: false,
11162
+ message: result.error || "\u6587\u6863\u751F\u6210\u5931\u8D25",
11163
+ data: null
11164
+ })
11165
+ }
11166
+ ],
11167
+ isError: true
11168
+ };
11169
+ } catch (error) {
11170
+ logger.error("\u6280\u672F\u89C4\u683C\u8BF4\u660E\u4E66\u751F\u6210\u5F02\u5E38", {
11171
+ error: error.message
11172
+ });
11173
+ return {
11174
+ content: [
11175
+ {
11176
+ type: 'text',
11177
+ text: JSON.stringify({
11178
+ success: false,
11179
+ message: error.message || "\u751F\u6210\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF",
11180
+ data: null
11181
+ })
11182
+ }
11183
+ ],
11184
+ isError: true
11185
+ };
11186
+ }
11187
+ }
11188
+ };
10506
11189
  function createMcpServer() {
10507
11190
  const server = new mcp_js_namespaceObject.McpServer({
10508
11191
  name: SERVICE_CONFIG.name,
@@ -10520,7 +11203,8 @@ ${requirement_description}
10520
11203
  exportExcelTool,
10521
11204
  requirementIdentifierTool,
10522
11205
  requirementAlignerTool,
10523
- taskExecutorTool
11206
+ taskExecutorTool,
11207
+ techSpecGeneratorTool
10524
11208
  ];
10525
11209
  tools.forEach((tool)=>{
10526
11210
  server.tool(tool.name, tool.description, tool.inputSchema, tool.handler);