intention-coding 0.5.9 → 0.6.0

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 (43) hide show
  1. package/dist/index.cjs +1069 -751
  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/read-excel/index.d.ts +2 -2
  17. package/dist/services/requirement-analyzer/core/document-generator.d.ts +4 -2
  18. package/dist/services/requirement-analyzer/core/document-generator.d.ts.map +1 -1
  19. package/dist/services/requirement-analyzer/core/requirement-analyzer-service.d.ts +1 -0
  20. package/dist/services/requirement-analyzer/core/requirement-analyzer-service.d.ts.map +1 -1
  21. package/dist/services/requirement-analyzer/core/template-selector.d.ts.map +1 -1
  22. package/dist/services/requirement-analyzer/core/types.d.ts +2 -1
  23. package/dist/services/requirement-analyzer/core/types.d.ts.map +1 -1
  24. package/dist/services/requirement-analyzer/index.d.ts +6 -1
  25. package/dist/services/requirement-analyzer/index.d.ts.map +1 -1
  26. package/dist/services/requirement-analyzer/prompt/html-page-template.d.ts +6 -0
  27. package/dist/services/requirement-analyzer/prompt/html-page-template.d.ts.map +1 -0
  28. package/dist/services/requirement-analyzer/prompt/intelligent-requirement-analysis.d.ts +1 -1
  29. package/dist/services/requirement-analyzer/prompt/intelligent-requirement-analysis.d.ts.map +1 -1
  30. package/dist/services/world2md/index.d.ts +1 -1
  31. package/dist/utils/dify.d.ts.map +1 -1
  32. package/dist/utils/logger.d.ts +1 -1
  33. package/dist/utils/logger.d.ts.map +1 -1
  34. package/dist/utils/openai.d.ts +18 -2
  35. package/dist/utils/openai.d.ts.map +1 -1
  36. package/package.json +1 -2
  37. package/bin/intention-coding.cjs +0 -4
  38. package/dist/services/requirement-analyzer/prompt/app-template.d.ts +0 -2
  39. package/dist/services/requirement-analyzer/prompt/app-template.d.ts.map +0 -1
  40. package/dist/services/requirement-analyzer/prompt/pc-page-template.d.ts +0 -2
  41. package/dist/services/requirement-analyzer/prompt/pc-page-template.d.ts.map +0 -1
  42. package/dist/services/requirement-analyzer/prompt/sdk-template.d.ts +0 -2
  43. package/dist/services/requirement-analyzer/prompt/sdk-template.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,5 +1,15 @@
1
1
  "use strict";
2
2
  var __webpack_modules__ = {
3
+ "fs/promises": function(module) {
4
+ module.exports = import("fs/promises").then(function(module) {
5
+ return module;
6
+ });
7
+ },
8
+ path: function(module) {
9
+ module.exports = import("path").then(function(module) {
10
+ return module;
11
+ });
12
+ },
3
13
  "pdf-parse/lib/pdf-parse.js": function(module) {
4
14
  module.exports = import("pdf-parse/lib/pdf-parse.js").then(function(module) {
5
15
  return module;
@@ -60,18 +70,15 @@ var __webpack_exports__ = {};
60
70
  var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
61
71
  const external_winston_namespaceObject = require("winston");
62
72
  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;
73
+ const external_os_namespaceObject = require("os");
74
+ var external_os_default = /*#__PURE__*/ __webpack_require__.n(external_os_namespaceObject);
75
+ const isProduction = "production" === process.env.NODE_ENV || !process.env.npm_lifecycle_event;
76
+ const logDir = external_path_default().join(external_os_default().homedir(), ".aico", "logs");
66
77
  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
- }
78
+ external_fs_default().mkdirSync(logDir, {
79
+ recursive: true
80
+ });
81
+ } catch {}
75
82
  const levels = {
76
83
  error: 0,
77
84
  warn: 1,
@@ -79,20 +86,6 @@ var __webpack_exports__ = {};
79
86
  debug: 3,
80
87
  verbose: 4
81
88
  };
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
89
  const fileFormat = external_winston_default().format.combine(external_winston_default().format.timestamp(), external_winston_default().format.errors({
97
90
  stack: true
98
91
  }), external_winston_default().format.json());
@@ -103,11 +96,11 @@ var __webpack_exports__ = {};
103
96
  const error = meta.error || meta;
104
97
  const errorInfo = {
105
98
  timestamp,
106
- level: level || 'error',
107
- message: message || 'Uncaught Exception',
108
- stack: stack || error && error.stack || 'No stack trace available',
99
+ level: level || "error",
100
+ message: message || "Uncaught Exception",
101
+ stack: stack || error && error.stack || "No stack trace available",
109
102
  error: {
110
- name: error && error.name || 'Error',
103
+ name: error && error.name || "Error",
111
104
  message: error && error.message || String(error || message),
112
105
  code: error && error.code || meta.code,
113
106
  ...meta
@@ -115,50 +108,48 @@ var __webpack_exports__ = {};
115
108
  };
116
109
  return JSON.stringify(errorInfo, null, 2);
117
110
  }));
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',
111
+ const transports = [];
112
+ transports.push(new (external_winston_default()).transports.File({
113
+ filename: external_path_default().join(logDir, "error.log"),
114
+ level: "error",
130
115
  format: fileFormat,
131
- level: 'info'
116
+ maxsize: 5242880,
117
+ maxFiles: 1,
118
+ tailable: true
119
+ }));
120
+ if (!isProduction) transports.push(new (external_winston_default()).transports.File({
121
+ filename: external_path_default().join(logDir, "app.log"),
122
+ level: "info",
123
+ format: fileFormat,
124
+ maxsize: 5242880,
125
+ maxFiles: 1,
126
+ tailable: true
132
127
  }));
133
128
  const logger = external_winston_default().createLogger({
134
- level: 'debug',
129
+ level: isProduction ? "error" : "debug",
135
130
  levels,
136
131
  format: external_winston_default().format.combine(external_winston_default().format.errors({
137
132
  stack: true
138
133
  }), external_winston_default().format.splat()),
139
134
  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
135
+ exceptionHandlers: [
136
+ new (external_winston_default()).transports.File({
137
+ filename: external_path_default().join(logDir, "error.log"),
138
+ format: exceptionFormat,
139
+ maxsize: 5242880,
140
+ maxFiles: 1
148
141
  })
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
142
+ ],
143
+ rejectionHandlers: [
144
+ new (external_winston_default()).transports.File({
145
+ filename: external_path_default().join(logDir, "error.log"),
146
+ format: exceptionFormat,
147
+ maxsize: 5242880,
148
+ maxFiles: 1
158
149
  })
159
- ] : []
150
+ ]
160
151
  });
161
- process.on('SIGINT', ()=>{
152
+ process.on("SIGINT", ()=>{
162
153
  logger.end(()=>{
163
154
  logger.info("\u65E5\u5FD7\u5DF2\u5173\u95ED");
164
155
  process.exit(0);
@@ -316,7 +307,6 @@ var __webpack_exports__ = {};
316
307
  var external_mammoth_default = /*#__PURE__*/ __webpack_require__.n(external_mammoth_namespaceObject);
317
308
  const external_html_to_md_namespaceObject = require("html-to-md");
318
309
  var external_html_to_md_default = /*#__PURE__*/ __webpack_require__.n(external_html_to_md_namespaceObject);
319
- const external_os_namespaceObject = require("os");
320
310
  const sanitizeFileName = (input)=>input.replace(/[\\/:*?"<>|\n\r#%&]/g, '').trim().replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_+|_+$/g, '');
321
311
  function normalizePath(filePath) {
322
312
  if (!filePath || 'string' != typeof filePath) throw new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
@@ -4199,6 +4189,207 @@ var __webpack_exports__ = {};
4199
4189
  ErrorCodes["UNSUPPORTED_REQUIREMENT_TYPE"] = "UNSUPPORTED_REQUIREMENT_TYPE";
4200
4190
  return ErrorCodes;
4201
4191
  }({});
4192
+ async function invokeFlow(params, streamCb) {
4193
+ const { appid = "app-ESTcrkOPOmkxdrO0120mE4s1", data, timeout = 1800000 } = params;
4194
+ const controller = new AbortController();
4195
+ const signal = controller.signal;
4196
+ if ("undefined" == typeof ReadableStream) throw new Error("ReadableStream is not supported in this environment");
4197
+ const fetchData = async (retryCount = 0)=>{
4198
+ try {
4199
+ const fetchOptions = {
4200
+ method: "POST",
4201
+ headers: {
4202
+ Authorization: `Bearer ${appid}`,
4203
+ "Content-Type": "application/json"
4204
+ },
4205
+ body: JSON.stringify({
4206
+ inputs: data,
4207
+ response_mode: "streaming",
4208
+ user: "aico-mcp"
4209
+ }),
4210
+ signal
4211
+ };
4212
+ const res = await fetch("http://11.0.166.20:9199/v1/workflows/run", fetchOptions);
4213
+ if (!res.ok) {
4214
+ if (retryCount < 3) {
4215
+ await new Promise((resolve)=>setTimeout(resolve, 1000));
4216
+ return fetchData(retryCount + 1);
4217
+ }
4218
+ const errorResponse = await res.text();
4219
+ throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
4220
+ }
4221
+ if (res.ok) if (res.body) {
4222
+ const reader = res.body.getReader();
4223
+ const decoder = new TextDecoder("utf-8");
4224
+ if (streamCb) return void new ReadableStream({
4225
+ start (controller) {
4226
+ let buffer = "";
4227
+ function push() {
4228
+ reader.read().then(({ done, value })=>{
4229
+ if (done) {
4230
+ const lines = buffer.split("\n");
4231
+ for (const line of lines)handleLine(line, controller);
4232
+ if (streamCb) streamCb({
4233
+ isEnd: true
4234
+ });
4235
+ controller.close();
4236
+ return;
4237
+ }
4238
+ const chunkText = decoder.decode(value, {
4239
+ stream: true
4240
+ });
4241
+ buffer += chunkText;
4242
+ const lines = buffer.split("\n");
4243
+ for(let i = 0; i < lines.length - 1; i++)handleLine(lines[i], controller);
4244
+ buffer = lines[lines.length - 1];
4245
+ push();
4246
+ });
4247
+ }
4248
+ function handleLine(line, controller) {
4249
+ line = line.trim();
4250
+ if (line.startsWith("data:")) {
4251
+ const dataStr = line.slice(5).trim();
4252
+ if ("" === dataStr) return;
4253
+ try {
4254
+ const jsonData = JSON.parse(dataStr);
4255
+ if (jsonData.data?.text) {
4256
+ const wrappedData = {
4257
+ content: jsonData.data.text.toString(),
4258
+ controller
4259
+ };
4260
+ if (streamCb) streamCb(wrappedData);
4261
+ }
4262
+ } catch (e) {
4263
+ console.error("\u89E3\u6790JSON\u5931\u8D25:", e);
4264
+ }
4265
+ }
4266
+ }
4267
+ push();
4268
+ }
4269
+ });
4270
+ {
4271
+ let buffer = "";
4272
+ let accumulatedText = "";
4273
+ let isResponseEnded = false;
4274
+ const readAll = async ()=>{
4275
+ const { done, value } = await reader.read();
4276
+ if (done) {
4277
+ if (!isResponseEnded) throw new Error("\u54CD\u5E94\u63D0\u524D\u7ED3\u675F");
4278
+ return accumulatedText;
4279
+ }
4280
+ const chunkText = decoder.decode(value, {
4281
+ stream: true
4282
+ });
4283
+ buffer += chunkText;
4284
+ const lines = buffer.split("\n");
4285
+ for(let i = 0; i < lines.length - 1; i++){
4286
+ const line = lines[i].trim();
4287
+ if (!line.startsWith("data:")) continue;
4288
+ const dataStr = line.slice(5).trim();
4289
+ if ("" !== dataStr) try {
4290
+ const jsonData = JSON.parse(dataStr);
4291
+ switch(jsonData.event){
4292
+ case "message":
4293
+ case "agent_message":
4294
+ case "text_chunk":
4295
+ {
4296
+ const content = "text_chunk" === jsonData.event ? jsonData.data.text : jsonData.answer;
4297
+ accumulatedText += content;
4298
+ break;
4299
+ }
4300
+ case "workflow_finished":
4301
+ if (jsonData.data?.outputs?.text) accumulatedText = jsonData.data.outputs.text;
4302
+ else if (jsonData.data?.outputs) {
4303
+ const outputs = jsonData.data.outputs;
4304
+ const textValue = Object.values(outputs).find((v)=>"string" == typeof v && v.length > 0);
4305
+ if (textValue) accumulatedText = textValue;
4306
+ }
4307
+ isResponseEnded = true;
4308
+ break;
4309
+ case "message_end":
4310
+ isResponseEnded = true;
4311
+ break;
4312
+ case "error":
4313
+ throw new Error(`\u{670D}\u{52A1}\u{5668}\u{9519}\u{8BEF}: ${jsonData.code}, ${jsonData.message}`);
4314
+ default:
4315
+ break;
4316
+ }
4317
+ } catch (e) {
4318
+ throw new Error("\u89E3\u6790JSON\u5931\u8D25: " + e.message);
4319
+ }
4320
+ }
4321
+ buffer = lines[lines.length - 1];
4322
+ return readAll();
4323
+ };
4324
+ return readAll();
4325
+ }
4326
+ } else throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
4327
+ {
4328
+ const errorResponse = await res.text();
4329
+ throw new Error(`\u{7F51}\u{7EDC}\u{54CD}\u{5E94}\u{5F02}\u{5E38}: ${res.status} ${res.statusText} - ${errorResponse}`);
4330
+ }
4331
+ } catch (error) {
4332
+ if ("AbortError" === error.name) throw new Error("\u8BF7\u6C42\u5DF2\u88AB\u4E2D\u6B62\uFF0C\u8D85\u65F6");
4333
+ throw error;
4334
+ }
4335
+ };
4336
+ try {
4337
+ const result = await Promise.race([
4338
+ fetchData(),
4339
+ new Promise((_, reject)=>{
4340
+ setTimeout(()=>{
4341
+ controller.abort();
4342
+ reject(new Error("\u8BF7\u6C42\u8D85\u65F6"));
4343
+ }, timeout);
4344
+ })
4345
+ ]);
4346
+ if (streamCb) return;
4347
+ return result;
4348
+ } catch (error) {
4349
+ controller.abort();
4350
+ throw error;
4351
+ }
4352
+ }
4353
+ async function uploadFile(params) {
4354
+ const { appid, filePath, user = "aico-mcp" } = params;
4355
+ try {
4356
+ const fileBuffer = await external_fs_default().promises.readFile(filePath);
4357
+ const fileName = external_path_default().basename(filePath);
4358
+ const fileExtension = external_path_default().extname(filePath).toLowerCase().slice(1);
4359
+ const mimeTypes = {
4360
+ png: "image/png",
4361
+ jpeg: "image/jpeg",
4362
+ jpg: "image/jpeg",
4363
+ webp: "image/webp",
4364
+ gif: "image/gif"
4365
+ };
4366
+ const mimeType = mimeTypes[fileExtension] || "application/octet-stream";
4367
+ const formData = new FormData();
4368
+ formData.append("file", new Blob([
4369
+ fileBuffer.buffer
4370
+ ], {
4371
+ type: mimeType
4372
+ }), fileName);
4373
+ formData.append("user", user);
4374
+ const response = await fetch("http://11.0.166.20:9199/v1/files/upload", {
4375
+ method: "POST",
4376
+ headers: {
4377
+ Authorization: `Bearer ${appid}`
4378
+ },
4379
+ body: formData
4380
+ });
4381
+ if (!response.ok) {
4382
+ const errorText = await response.text();
4383
+ throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${response.status} ${response.statusText} - ${errorText}`);
4384
+ }
4385
+ const result = await response.json();
4386
+ if (!result.id || !result.name) throw new Error("\u65E0\u6548\u7684\u6587\u4EF6\u4E0A\u4F20\u54CD\u5E94\u683C\u5F0F");
4387
+ return result;
4388
+ } catch (error) {
4389
+ if (error instanceof Error) throw new Error(`\u{6587}\u{4EF6}\u{4E0A}\u{4F20}\u{5931}\u{8D25}: ${error.message}`);
4390
+ throw new Error("\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: \u672A\u77E5\u9519\u8BEF");
4391
+ }
4392
+ }
4202
4393
  class OpenAIService {
4203
4394
  qwenConfig = {
4204
4395
  apiKey: "sk-95b0bc60b7464bbbafd64edc2f5bab14",
@@ -4220,6 +4411,10 @@ var __webpack_exports__ = {};
4220
4411
  baseUrl: "https://api.lkeap.cloud.tencent.com/v1/chat/completions",
4221
4412
  model: "deepseek-v3.1-terminus"
4222
4413
  };
4414
+ difyConfig = {
4415
+ apiKey: "app-AvlLh0nfN4l9oz1MSW4sEAQ6",
4416
+ baseUrl: "http://11.0.166.20:9199/v1"
4417
+ };
4223
4418
  constructor(){}
4224
4419
  async generateText(params) {
4225
4420
  const { prompt, temperature, system_prompt } = params;
@@ -4576,23 +4771,115 @@ var __webpack_exports__ = {};
4576
4771
  }
4577
4772
  }
4578
4773
  }
4774
+ async analyzeImageWithPath(params) {
4775
+ const { prompt, image_path, system_prompt } = params;
4776
+ logger.info("[OpenAI] analyzeImageWithPath \u88AB\u8C03\u7528", {
4777
+ image_path,
4778
+ prompt_length: prompt.length
4779
+ });
4780
+ try {
4781
+ logger.info("[OpenAI] \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6\u5230 Dify", {
4782
+ image_path
4783
+ });
4784
+ const uploadResult = await uploadFile({
4785
+ appid: this.difyConfig.apiKey,
4786
+ filePath: image_path,
4787
+ user: "aico-mcp"
4788
+ });
4789
+ logger.info("[OpenAI] \u6587\u4EF6\u4E0A\u4F20\u6210\u529F", {
4790
+ upload_file_id: uploadResult.id
4791
+ });
4792
+ const workflowData = {
4793
+ imagePath: {
4794
+ type: "image",
4795
+ transfer_method: "local_file",
4796
+ upload_file_id: uploadResult.id
4797
+ },
4798
+ context: prompt
4799
+ };
4800
+ logger.info("[OpenAI] \u5F00\u59CB\u8C03\u7528 Dify \u5DE5\u4F5C\u6D41");
4801
+ const workflowResponse = await invokeFlow({
4802
+ appid: this.difyConfig.apiKey,
4803
+ data: workflowData,
4804
+ timeout: 120000
4805
+ });
4806
+ logger.info("[OpenAI] Dify \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F", {
4807
+ response_type: typeof workflowResponse,
4808
+ response_preview: "string" == typeof workflowResponse ? workflowResponse.substring(0, 200) : JSON.stringify(workflowResponse).substring(0, 500)
4809
+ });
4810
+ let summary = "";
4811
+ if ("string" == typeof workflowResponse && workflowResponse.length > 0) summary = workflowResponse;
4812
+ else if (workflowResponse?.outputs?.text) summary = workflowResponse.outputs.text;
4813
+ else if (workflowResponse?.data?.outputs?.text) summary = workflowResponse.data.outputs.text;
4814
+ else if (workflowResponse?.data?.text) summary = workflowResponse.data.text;
4815
+ else if (workflowResponse?.answer) summary = workflowResponse.answer;
4816
+ 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"}`);
4817
+ if (!summary || 0 === summary.length) {
4818
+ logger.error("[OpenAI] Dify \u54CD\u5E94\u89E3\u6790\u5931\u8D25\uFF0C\u65E0\u6CD5\u63D0\u53D6\u6587\u672C\u5185\u5BB9", {
4819
+ response: JSON.stringify(workflowResponse)
4820
+ });
4821
+ throw new Error("Dify\u5DE5\u4F5C\u6D41\u54CD\u5E94\u4E2D\u672A\u627E\u5230\u6709\u6548\u6587\u672C\u5185\u5BB9");
4822
+ }
4823
+ logger.info("[OpenAI] Dify \u5206\u6790\u5B8C\u6210", {
4824
+ summary_length: summary.length
4825
+ });
4826
+ return summary;
4827
+ } catch (difyError) {
4828
+ logger.error("[OpenAI] Dify \u8C03\u7528\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u5176\u4ED6\u670D\u52A1", {
4829
+ error: difyError instanceof Error ? difyError.message : String(difyError)
4830
+ });
4831
+ const fs = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "fs/promises"));
4832
+ const path = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "path"));
4833
+ const imageBuffer = await fs.readFile(image_path);
4834
+ const base64 = imageBuffer.toString("base64");
4835
+ const ext = path.extname(image_path).toLowerCase();
4836
+ let mimeType = "image/jpeg";
4837
+ switch(ext){
4838
+ case ".png":
4839
+ mimeType = "image/png";
4840
+ break;
4841
+ case ".gif":
4842
+ mimeType = "image/gif";
4843
+ break;
4844
+ case ".webp":
4845
+ mimeType = "image/webp";
4846
+ break;
4847
+ case ".jpg":
4848
+ case ".jpeg":
4849
+ mimeType = "image/jpeg";
4850
+ break;
4851
+ }
4852
+ const image_base64 = `data:${mimeType};base64,${base64}`;
4853
+ return this.analyzeImage({
4854
+ prompt,
4855
+ image_base64,
4856
+ system_prompt
4857
+ });
4858
+ }
4859
+ }
4579
4860
  async analyzeImage(params) {
4580
4861
  const { prompt, image_base64, system_prompt } = params;
4581
- let lastError = null;
4582
4862
  try {
4583
- const response = await fetch(this.glm4vConfig.baseUrl, {
4863
+ const controller = new AbortController();
4864
+ const timeoutId = setTimeout(()=>controller.abort(), 20000);
4865
+ const response = await fetch(this.kimiConfig.baseUrl, {
4584
4866
  method: "POST",
4585
4867
  headers: {
4586
4868
  "Content-Type": "application/json",
4587
- Authorization: `Bearer ${this.glm4vConfig.apiKey}`
4869
+ Authorization: `Bearer ${this.kimiConfig.apiKey}`
4588
4870
  },
4589
4871
  body: JSON.stringify({
4590
- model: this.glm4vConfig.model,
4872
+ model: this.kimiConfig.model,
4591
4873
  messages: [
4592
4874
  ...system_prompt ? [
4593
4875
  {
4594
4876
  role: "system",
4595
- content: system_prompt
4877
+ content: [
4878
+ {
4879
+ type: "text",
4880
+ text: system_prompt
4881
+ }
4882
+ ]
4596
4883
  }
4597
4884
  ] : [],
4598
4885
  {
@@ -4612,36 +4899,34 @@ var __webpack_exports__ = {};
4612
4899
  }
4613
4900
  ],
4614
4901
  stream: false
4615
- })
4902
+ }),
4903
+ signal: controller.signal
4616
4904
  });
4905
+ clearTimeout(timeoutId);
4617
4906
  if (!response.ok) {
4618
4907
  const errorText = await response.text();
4619
- throw new Error(`GLM-4V API error: ${response.status} ${response.statusText} - ${errorText}`);
4908
+ throw new Error(`Kimi Vision API error: ${response.status} ${response.statusText} - ${errorText}`);
4620
4909
  }
4621
4910
  const data = await response.json();
4622
- if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from GLM-4V API");
4911
+ if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Kimi Vision API");
4623
4912
  return data.choices[0].message.content;
4624
- } catch (error) {
4625
- lastError = error;
4913
+ } catch (kimiError) {
4626
4914
  try {
4627
- const response = await fetch(this.kimiConfig.baseUrl, {
4915
+ const controller = new AbortController();
4916
+ const timeoutId = setTimeout(()=>controller.abort(), 15000);
4917
+ const response = await fetch(this.glm4vConfig.baseUrl, {
4628
4918
  method: "POST",
4629
4919
  headers: {
4630
4920
  "Content-Type": "application/json",
4631
- Authorization: `Bearer ${this.kimiConfig.apiKey}`
4921
+ Authorization: `Bearer ${this.glm4vConfig.apiKey}`
4632
4922
  },
4633
4923
  body: JSON.stringify({
4634
- model: this.kimiConfig.model,
4924
+ model: this.glm4vConfig.model,
4635
4925
  messages: [
4636
4926
  ...system_prompt ? [
4637
4927
  {
4638
4928
  role: "system",
4639
- content: [
4640
- {
4641
- type: "text",
4642
- text: system_prompt
4643
- }
4644
- ]
4929
+ content: system_prompt
4645
4930
  }
4646
4931
  ] : [],
4647
4932
  {
@@ -4661,41 +4946,57 @@ var __webpack_exports__ = {};
4661
4946
  }
4662
4947
  ],
4663
4948
  stream: false
4664
- })
4949
+ }),
4950
+ signal: controller.signal
4665
4951
  });
4952
+ clearTimeout(timeoutId);
4666
4953
  if (!response.ok) {
4667
4954
  const errorText = await response.text();
4668
- throw new Error(`Kimi Vision API error: ${response.status} ${response.statusText} - ${errorText}`);
4955
+ throw new Error(`GLM-4V API error: ${response.status} ${response.statusText} - ${errorText}`);
4669
4956
  }
4670
4957
  const data = await response.json();
4671
- if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from Kimi Vision API");
4958
+ if (!data.choices || 0 === data.choices.length) throw new Error("No choices returned from GLM-4V API");
4672
4959
  return data.choices[0].message.content;
4673
- } catch (kimiError) {
4674
- throw lastError;
4960
+ } catch (glmError) {
4961
+ 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
4962
  }
4676
4963
  }
4677
4964
  }
4678
4965
  }
4679
4966
  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}
4967
+ 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
4968
 
4682
4969
  **\u{8F93}\u{5165}\u{5185}\u{5BB9}**:
4683
4970
  {inputContent}
4684
4971
 
4685
- ## \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{8BC6}\u{522B}
4972
+ ## \u{5206}\u{6790}\u{4EFB}\u{52A1}
4973
+
4974
+ \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
4975
 
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}
4976
+ ### 1. \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{8BC6}\u{522B}
4692
4977
 
4693
- ## \u{529F}\u{80FD}\u{70B9}\u{63D0}\u{53D6}\u{539F}\u{5219}
4978
+ \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}
4979
+ - **\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}
4980
+ - **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}
4981
+ - **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}
4982
+ - **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
4983
 
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}
4984
+ ### 2. \u{6DF1}\u{5EA6}\u{9700}\u{6C42}\u{5206}\u{6790}
4985
+
4986
+ \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}
4987
+ - **\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}
4988
+ - **\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}
4989
+ - **\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}
4990
+ - **\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}
4991
+ - **\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}
4992
+
4993
+ ### 3. \u{6280}\u{672F}\u{4E0A}\u{4E0B}\u{6587}\u{63D0}\u{53D6}
4994
+
4995
+ \u{4ECE}\u{9879}\u{76EE}\u{4FE1}\u{606F}\u{4E2D}\u{63D0}\u{53D6}\u{FF1A}
4996
+ - \u{6280}\u{672F}\u{6808}\u{548C}\u{6846}\u{67B6}
4997
+ - \u{73B0}\u{6709}\u{7684}\u{4EE3}\u{7801}\u{7ED3}\u{6784}
4998
+ - \u{4F9D}\u{8D56}\u{5173}\u{7CFB}
4999
+ - \u{8BBE}\u{8BA1}\u{89C4}\u{8303}
4699
5000
 
4700
5001
  ## \u{8F93}\u{51FA}\u{683C}\u{5F0F}
4701
5002
 
@@ -4707,14 +5008,36 @@ var __webpack_exports__ = {};
4707
5008
  "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
5009
  "primaryTechnology": "\u{4E3B}\u{8981}\u{6280}\u{672F}\u{6808}\u{63CF}\u{8FF0}",
4709
5010
  "confidence": "high|medium|low",
5011
+ "businessContext": {
5012
+ "background": "\u{4E1A}\u{52A1}\u{80CC}\u{666F}\u{63CF}\u{8FF0}",
5013
+ "objectives": ["\u{4E1A}\u{52A1}\u{76EE}\u{6807}1", "\u{4E1A}\u{52A1}\u{76EE}\u{6807}2"],
5014
+ "stakeholders": ["\u{6D89}\u{53CA}\u{7684}\u{89D2}\u{8272}1", "\u{6D89}\u{53CA}\u{7684}\u{89D2}\u{8272}2"]
5015
+ },
4710
5016
  "requirements": [
4711
5017
  {
4712
5018
  "id": "req_001",
4713
5019
  "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}",
5020
+ "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
5021
  "priority": "high|medium|low",
4716
5022
  "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}"
5023
+ "type": "\u{63A5}\u{53E3}|PC\u{9875}\u{9762}|APP|SDK\u{96C6}\u{6210}",
5024
+ "businessFlow": {
5025
+ "preconditions": ["\u{524D}\u{7F6E}\u{6761}\u{4EF6}1"],
5026
+ "mainFlow": ["\u{6B65}\u{9AA4}1", "\u{6B65}\u{9AA4}2", "\u{6B65}\u{9AA4}3"],
5027
+ "alternativeFlows": ["\u{66FF}\u{4EE3}\u{6D41}\u{7A0B}1"],
5028
+ "exceptionFlows": ["\u{5F02}\u{5E38}\u{5904}\u{7406}1"]
5029
+ },
5030
+ "dataEntities": [
5031
+ {
5032
+ "name": "\u{5B9E}\u{4F53}\u{540D}\u{79F0}",
5033
+ "fields": [
5034
+ {"name": "\u{5B57}\u{6BB5}\u{540D}", "type": "\u{7C7B}\u{578B}", "required": true, "description": "\u{8BF4}\u{660E}"}
5035
+ ]
5036
+ }
5037
+ ],
5038
+ "interactions": [
5039
+ {"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}"}
5040
+ ]
4718
5041
  }
4719
5042
  ],
4720
5043
  "templateRecommendation": {
@@ -4722,13 +5045,29 @@ var __webpack_exports__ = {};
4722
5045
  "reason": "\u{9009}\u{62E9}\u{8BE5}\u{6A21}\u{677F}\u{7684}\u{539F}\u{56E0}",
4723
5046
  "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
5047
  },
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}"
5048
+ "technicalContext": {
5049
+ "suggestedTechStack": ["\u{5EFA}\u{8BAE}\u{7684}\u{6280}\u{672F}\u{6808}"],
5050
+ "integrationPoints": ["\u{9700}\u{8981}\u{96C6}\u{6210}\u{7684}\u{7CFB}\u{7EDF}\u{6216}\u{670D}\u{52A1}"],
5051
+ "securityRequirements": ["\u{5B89}\u{5168}\u{8981}\u{6C42}"],
5052
+ "performanceRequirements": ["\u{6027}\u{80FD}\u{8981}\u{6C42}"]
5053
+ },
5054
+ "documentationHints": {
5055
+ "keySequenceDiagrams": ["\u{9700}\u{8981}\u{7ED8}\u{5236}\u{7684}\u{65F6}\u{5E8F}\u{56FE}\u{573A}\u{666F}"],
5056
+ "keyERDiagrams": ["\u{9700}\u{8981}\u{7ED8}\u{5236}\u{7684}ER\u{56FE}\u{5B9E}\u{4F53}"],
5057
+ "keyTables": ["\u{9700}\u{8981}\u{8BE6}\u{7EC6}\u{8BF4}\u{660E}\u{7684}\u{8868}\u{683C}"]
5058
+ }
4726
5059
  }
4727
5060
  \`\`\`
4728
5061
 
5062
+ ## \u{5206}\u{6790}\u{539F}\u{5219}
4729
5063
 
5064
+ 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}
5065
+ 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}
5066
+ 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}
5067
+ 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}
5068
+ 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
5069
 
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}`;
5070
+ **\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
5071
  class IntelligentAnalyzer {
4733
5072
  async analyzeRequirements(inputContent, projectInfo, customPrompt) {
4734
5073
  try {
@@ -5490,9 +5829,9 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5490
5829
 
5491
5830
  **\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
5831
  `;
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}
5832
+ 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
5833
 
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}
5834
+ **\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
5835
 
5497
5836
  **\u{539F}\u{59CB}\u{9700}\u{6C42}**:
5498
5837
  \`\`\`
@@ -5502,11 +5841,12 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5502
5841
  ## \u{6587}\u{6863}\u{7ED3}\u{6784}\u{8981}\u{6C42}
5503
5842
  \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
5843
 
5505
- # {featureName} - PC\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5844
+ # {featureName} - HTML\u{9875}\u{9762}\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
5506
5845
 
5507
5846
  > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: {currentTime}
5508
5847
  > **\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}
5848
+ > **\u{9875}\u{9762}\u{7C7B}\u{578B}**: {pageType}\u{FF08}pc/mobile/responsive\u{FF09}
5849
+ > **\u{9875}\u{9762}\u{98CE}\u{683C}**: TailwindCSS \u{7B80}\u{7EA6}\u{98CE}\u{683C}
5510
5850
 
5511
5851
  ---
5512
5852
 
@@ -5518,6 +5858,8 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5518
5858
 
5519
5859
  **\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
5860
 
5861
+ **\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}]
5862
+
5521
5863
  ## 2. {featureName}\u{529F}\u{80FD}\u{8BBE}\u{8BA1}\u{8BF4}\u{660E}
5522
5864
 
5523
5865
  | | | | | |
@@ -5527,14 +5869,17 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5527
5869
  |**\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
5870
  |**\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
5871
  |**\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}]|
5872
+ |**\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
5873
  |**\u{529F}\u{80FD}\u{63CF}\u{8FF0}**|[\u{8BE6}\u{7EC6}\u{7684}\u{529F}\u{80FD}\u{63CF}\u{8FF0}]|
5532
5874
  |**\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
5875
 
5534
5876
  ## 3. \u{9875}\u{9762}\u{5E03}\u{5C40}\u{8BBE}\u{8BA1}
5535
5877
 
5536
5878
  ### 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}]
5879
+ [\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}]
5880
+ - **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}]
5881
+ - **\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}]
5882
+ - **\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
5883
 
5539
5884
  ### 3.2 \u{9875}\u{9762}\u{533A}\u{57DF}\u{5212}\u{5206}
5540
5885
  [\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 +5887,34 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5542
5887
  ### 3.3 \u{9875}\u{9762}\u{6D41}\u{7EBF}\u{8BBE}\u{8BA1}
5543
5888
  [\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
5889
 
5890
+ ### 3.4 \u{54CD}\u{5E94}\u{5F0F}\u{9002}\u{914D}\u{7B56}\u{7565}
5891
+ [\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}]
5892
+ - **\u{65AD}\u{70B9}\u{8BBE}\u{7F6E}**: sm(640px), md(768px), lg(1024px), xl(1280px)
5893
+ - **\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}]
5894
+ - **\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}]
5895
+
5545
5896
  ## 4. \u{6837}\u{5F0F}\u{89C4}\u{8303}\u{8BF4}\u{660E}
5546
5897
 
5547
5898
  ### 4.1 \u{8272}\u{5F69}\u{89C4}\u{8303}
5548
5899
  [\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}]
5900
+ \`\`\`css
5901
+ :root {
5902
+ --bg: #ffffff;
5903
+ --bg-secondary: #f8f9fa;
5904
+ --border: #e5e5e5;
5905
+ --text: #111111;
5906
+ --text-muted: #666666;
5907
+ --accent: #000000;
5908
+ }
5909
+ \`\`\`
5910
+
5911
+ ### 4.2 \u{5B57}\u{4F53}\u{89C4}\u{8303}
5912
+ [\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
5913
 
5914
+ ### 4.3 \u{95F4}\u{8DDD}\u{89C4}\u{8303}
5915
+ [\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
5916
 
5551
- ### 4.2 \u{54C1}\u{724C}\u{89C6}\u{89C9}\u{89C4}\u{8303}
5917
+ ### 4.4 \u{54C1}\u{724C}\u{89C6}\u{89C9}\u{89C4}\u{8303}
5552
5918
  [\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
5919
 
5554
5920
  ## 5. \u{4EA4}\u{4E92}\u{903B}\u{8F91}\u{8BF4}\u{660E}
@@ -5565,11 +5931,14 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5565
5931
  ### 5.4 \u{8868}\u{5355}\u{9A8C}\u{8BC1}\u{89C4}\u{5219}
5566
5932
  [\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
5933
 
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}]
5934
+ ### 5.5 \u{89E6}\u{6478}/\u{624B}\u{52BF}\u{4EA4}\u{4E92}
5935
+ [\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}]
5936
+ - **\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}]
5937
+ - **\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}]
5938
+ - **\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
5939
 
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}]
5940
+ ### 5.6 \u{4E8B}\u{4EF6}\u{5904}\u{7406}\u{673A}\u{5236}
5941
+ [\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
5942
 
5574
5943
  ### 5.7 \u{9519}\u{8BEF}\u{5904}\u{7406}\u{4E0E}\u{6062}\u{590D}
5575
5944
  [\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 +5948,10 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5579
5948
  ### 6.1 \u{4E3B}\u{8981}\u{6570}\u{636E}\u{5B9E}\u{4F53}
5580
5949
  [\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
5950
 
5582
- \u{5B9E}\u{4F53}\u{4E00}
5583
- | | | | | |
5951
+ | **\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
5952
  |---|---|---|---|---|
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
5953
  |[\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
5954
  |[\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
5955
 
5590
5956
  ### 6.2 \u{8868}\u{5355}\u{5B57}\u{6BB5}\u{8BF4}\u{660E}
5591
5957
  [\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 +5961,10 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5595
5961
 
5596
5962
  ## 7. \u{754C}\u{9762}\u{64CD}\u{4F5C}\u{8BF4}\u{660E}
5597
5963
 
5598
- | | | |
5964
+ | **\u{5E8F}\u{53F7}** | **\u{4E1A}\u{52A1}\u{64CD}\u{4F5C}** | **\u{8BF4}\u{660E}** |
5599
5965
  |---|---|---|
5600
- |**\u{5E8F}\u{53F7}**|**\u{4E1A}\u{52A1}\u{64CD}\u{4F5C}**|**\u{8BF4}\u{660E}**|
5601
5966
  |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
5967
  |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
5968
 
5605
5969
  ## 8. \u{7EC4}\u{4EF6}\u{7ED3}\u{6784}\u{8BBE}\u{8BA1}
5606
5970
 
@@ -5622,21 +5986,32 @@ Scenario Outline: UI\u{7EC4}\u{4EF6}\u{4EA4}\u{4E92}\u{5904}\u{7406}\u{6D41}\u{7
5622
5986
 
5623
5987
  \`\`\`mermaid
5624
5988
  sequenceDiagram
5989
+ participant User as \u{7528}\u{6237}
5990
+ participant Page as \u{9875}\u{9762}
5991
+ participant API as \u{540E}\u{7AEF}API
5992
+ User->>Page: \u{8BBF}\u{95EE}\u{9875}\u{9762}
5993
+ Page->>API: \u{8BF7}\u{6C42}\u{6570}\u{636E}
5994
+ API-->>Page: \u{8FD4}\u{56DE}\u{6570}\u{636E}
5995
+ Page-->>User: \u{5C55}\u{793A}\u{5185}\u{5BB9}
5625
5996
  \`\`\`
5626
5997
 
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}
5998
+ ### 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
5999
 
5629
- #### 9.2.1 \u{6027}\u{80FD}\u{4F18}\u{5316}\u{8981}\u{6C42}
5630
6000
  \`\`\`mermaid
5631
6001
  sequenceDiagram
6002
+ participant User as \u{7528}\u{6237}
6003
+ participant Page as \u{9875}\u{9762}
6004
+ participant API as \u{540E}\u{7AEF}API
6005
+ User->>Page: \u{63D0}\u{4EA4}\u{8868}\u{5355}
6006
+ Page->>API: \u{53D1}\u{9001}\u{8BF7}\u{6C42}
6007
+ API-->>Page: \u{8FD4}\u{56DE}\u{9519}\u{8BEF}
6008
+ Page-->>User: \u{663E}\u{793A}\u{9519}\u{8BEF}\u{63D0}\u{793A}
5632
6009
  \`\`\`
5633
6010
 
5634
-
5635
6011
  ## 10. \u{4E1A}\u{52A1}\u{72B6}\u{6001}\u{63CF}\u{8FF0}
5636
6012
 
5637
- | | | |
6013
+ | **\u{72B6}\u{6001}\u{7F16}\u{53F7}** | **\u{72B6}\u{6001}\u{540D}\u{79F0}** | **\u{63CF}\u{8FF0}** |
5638
6014
  |---|---|---|
5639
- |**\u{72B6}\u{6001}\u{7F16}\u{53F7}**|**\u{72B6}\u{6001}\u{540D}\u{79F0}**|**\u{63CF}\u{8FF0}**|
5640
6015
  |01|\u{5F85}\u{52A0}\u{8F7D}|\u{9875}\u{9762}\u{521D}\u{59CB}\u{5316}\u{72B6}\u{6001}|
5641
6016
  |02|\u{52A0}\u{8F7D}\u{4E2D}|\u{6570}\u{636E}\u{52A0}\u{8F7D}\u{72B6}\u{6001}|
5642
6017
  |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 +6022,19 @@ sequenceDiagram
5647
6022
  |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
6023
  |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
6024
  |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
6025
 
5652
6026
  ## 11. \u{7528}\u{6237}\u{6545}\u{4E8B}
5653
6027
 
5654
6028
  ### 11.1 \u{6545}\u{4E8B}1
5655
6029
  [\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}]
6030
+
5656
6031
  ### 11.2 \u{6545}\u{4E8B}2
5657
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}]
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
-
5664
- ---
5665
-
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
6033
 
5685
6034
  ---
5686
6035
 
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}
6036
+ **\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}`;
6037
+ 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
6038
 
5819
6039
  **\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
6040
 
@@ -6007,36 +6227,28 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6007
6227
  class TemplateSelector {
6008
6228
  templateMap = new Map([
6009
6229
  [
6010
- "PC\u9875\u9762",
6011
- pcPageTemplatePrompt
6012
- ],
6013
- [
6014
- "APP",
6015
- appTemplatePrompt
6230
+ "HTML",
6231
+ htmlPageTemplatePrompt
6016
6232
  ],
6017
6233
  [
6018
- "SDK\u96C6\u6210",
6019
- sdkTemplatePrompt
6234
+ "html",
6235
+ htmlPageTemplatePrompt
6020
6236
  ],
6021
6237
  [
6022
- "\u63A5\u53E3",
6023
- apiTemplatePrompt
6238
+ "API",
6239
+ api_template_apiTemplatePrompt
6024
6240
  ],
6025
6241
  [
6026
6242
  "api",
6027
- apiTemplatePrompt
6243
+ api_template_apiTemplatePrompt
6028
6244
  ],
6029
6245
  [
6030
- "pc",
6031
- pcPageTemplatePrompt
6032
- ],
6033
- [
6034
- "app",
6035
- appTemplatePrompt
6246
+ "\u63A5\u53E3",
6247
+ api_template_apiTemplatePrompt
6036
6248
  ],
6037
6249
  [
6038
- "sdk",
6039
- sdkTemplatePrompt
6250
+ "\u9875\u9762",
6251
+ htmlPageTemplatePrompt
6040
6252
  ]
6041
6253
  ]);
6042
6254
  selectTemplate(requirementType) {
@@ -6081,33 +6293,18 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6081
6293
  "ui",
6082
6294
  "\u7F51\u9875",
6083
6295
  "\u6D4F\u89C8\u5668",
6084
- "\u524D\u7AEF"
6085
- ])) return {
6086
- type: "PC\u9875\u9762",
6087
- template: pcPageTemplatePrompt
6088
- };
6089
- if (this.containsAny(lowerType, [
6296
+ "\u524D\u7AEF",
6297
+ "html",
6090
6298
  "app",
6091
6299
  "\u79FB\u52A8",
6092
6300
  "ios",
6093
6301
  "android",
6094
6302
  "\u5C0F\u7A0B\u5E8F",
6095
- "\u79FB\u52A8\u7AEF"
6096
- ])) 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"
6303
+ "\u79FB\u52A8\u7AEF",
6304
+ "\u54CD\u5E94\u5F0F"
6108
6305
  ])) return {
6109
- type: "SDK\u96C6\u6210",
6110
- template: sdkTemplatePrompt
6306
+ type: "HTML",
6307
+ template: htmlPageTemplatePrompt
6111
6308
  };
6112
6309
  if (this.containsAny(lowerType, [
6113
6310
  "\u63A5\u53E3",
@@ -6119,7 +6316,7 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6119
6316
  "\u670D\u52A1\u7AEF"
6120
6317
  ])) return {
6121
6318
  type: "\u63A5\u53E3",
6122
- template: apiTemplatePrompt
6319
+ template: api_template_apiTemplatePrompt
6123
6320
  };
6124
6321
  return null;
6125
6322
  }
@@ -6195,7 +6392,7 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6195
6392
  cleanedCount
6196
6393
  });
6197
6394
  }
6198
- async generateUnifiedDocument(analysis, projectInfo, featureName, sourceInfo, customPrompt, currentProjectPath) {
6395
+ async generateUnifiedDocument(analysis, projectInfo, featureName, sourceInfo, customPrompt, currentProjectPath, pageStyle, pageType) {
6199
6396
  try {
6200
6397
  logger.info("\u51C6\u5907\u751F\u6210\u7EDF\u4E00\u6280\u672F\u6587\u6863\u4EFB\u52A1", {
6201
6398
  featureName,
@@ -6203,7 +6400,10 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6203
6400
  featureCount: analysis.requirements.length,
6204
6401
  currentProjectPath
6205
6402
  });
6206
- const requirementTypes = this.parseRequirementTypes(analysis.requirementType);
6403
+ const requirementTypes = [
6404
+ "API",
6405
+ "HTML"
6406
+ ];
6207
6407
  const generationTasks = await Promise.all(requirementTypes.map(async (reqType)=>{
6208
6408
  logger.info("\u51C6\u5907\u62A5\u544A\u751F\u6210\u4EFB\u52A1", {
6209
6409
  requirementType: reqType,
@@ -6227,13 +6427,19 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6227
6427
  prompt: promptData.prompt,
6228
6428
  systemPrompt: promptData.systemPrompt,
6229
6429
  templateContent: promptData.templateContent,
6230
- templateVariables: "templateVariables" in promptData ? promptData.templateVariables : {
6430
+ templateVariables: "templateVariables" in promptData ? {
6431
+ ...promptData.templateVariables,
6432
+ pageStyle,
6433
+ pageType: pageType || "responsive"
6434
+ } : {
6231
6435
  featureName: featureName,
6232
6436
  inputContent: this.buildUnifiedContent(analysis, projectInfo, featureName, sourceInfo),
6233
6437
  currentTime: new Date().toISOString(),
6234
6438
  businessDomain: this.mapRequirementTypeToBusinessDomain(reqType),
6235
6439
  generateSequenceDiagram: "true",
6236
- customPrompt
6440
+ customPrompt,
6441
+ pageStyle,
6442
+ pageType: pageType || "responsive"
6237
6443
  },
6238
6444
  existingContent: "existingContent" in promptData ? promptData.existingContent : void 0
6239
6445
  };
@@ -6306,18 +6512,72 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6306
6512
  }
6307
6513
  buildUnifiedContent(analysis, projectInfo, featureName, sourceInfo) {
6308
6514
  const featuresToProcess = analysis.featureDependencies?.mergedFeatures || analysis.requirements;
6515
+ const enrichedContext = analysis.enrichedContext || {};
6516
+ const businessContext = analysis.businessContext || {};
6517
+ const technicalContext = analysis.technicalContext || {};
6518
+ const documentationHints = analysis.documentationHints || {};
6309
6519
  const combinedFeatureContent = featuresToProcess.map((feature, index)=>{
6310
6520
  const featureTitle = "title" in feature ? feature.title : feature.featureName;
6311
6521
  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");
6522
+ const businessFlow = feature.businessFlow || {};
6523
+ const dataEntities = feature.dataEntities || [];
6524
+ const interactions = feature.interactions || [];
6525
+ let content = `## \u{529F}\u{80FD}\u{70B9}${index + 1}\u{FF1A}${featureTitle}\n\n${featureContent}`;
6526
+ if (businessFlow.mainFlow?.length > 0) {
6527
+ content += `
6528
+
6529
+ ### \u{4E1A}\u{52A1}\u{6D41}\u{7A0B}
6530
+ `;
6531
+ if (businessFlow.preconditions?.length > 0) content += `**\u{524D}\u{7F6E}\u{6761}\u{4EF6}**: ${businessFlow.preconditions.join("\u3001")}\n`;
6532
+ content += `**\u{4E3B}\u{6D41}\u{7A0B}**:
6533
+ ${businessFlow.mainFlow.map((step, i)=>`${i + 1}. ${step}`).join("\n")}\n`;
6534
+ if (businessFlow.exceptionFlows?.length > 0) content += `**\u{5F02}\u{5E38}\u{5904}\u{7406}**: ${businessFlow.exceptionFlows.join("\u3001")}\n`;
6535
+ }
6536
+ if (dataEntities.length > 0) {
6537
+ content += `
6538
+
6539
+ ### \u{6570}\u{636E}\u{5B9E}\u{4F53}
6540
+ `;
6541
+ dataEntities.forEach((entity)=>{
6542
+ content += `**${entity.name}**:\n`;
6543
+ if (entity.fields?.length > 0) {
6544
+ content += `| \u{5B57}\u{6BB5}\u{540D} | \u{7C7B}\u{578B} | \u{5FC5}\u{586B} | \u{8BF4}\u{660E} |
6545
+ |---|---|---|---|
6546
+ `;
6547
+ entity.fields.forEach((field)=>{
6548
+ content += `| ${field.name} | ${field.type} | ${field.required ? "\u662F" : "\u5426"} | ${field.description} |\n`;
6549
+ });
6550
+ }
6551
+ });
6552
+ }
6553
+ if (interactions.length > 0) {
6554
+ content += `
6555
+
6556
+ ### \u{4EA4}\u{4E92}\u{903B}\u{8F91}
6557
+ `;
6558
+ interactions.forEach((interaction)=>{
6559
+ content += `- **\u{89E6}\u{53D1}**: ${interaction.trigger} \u{2192} **\u{52A8}\u{4F5C}**: ${interaction.action} \u{2192} **\u{54CD}\u{5E94}**: ${interaction.response}\n`;
6560
+ });
6561
+ }
6562
+ return content;
6563
+ }).join("\n\n---\n\n");
6314
6564
  return `# ${featureName} - \u{7EDF}\u{4E00}\u{9700}\u{6C42}\u{5206}\u{6790}
6315
6565
 
6316
6566
  ## \u{9879}\u{76EE}\u{57FA}\u{672C}\u{4FE1}\u{606F}
6317
6567
  - **\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"}
6568
+ - **\u{4E3B}\u{8981}\u{6280}\u{672F}\u{6808}**: ${projectInfo?.techStack?.join(", ") || enrichedContext.techStack?.join(", ") || "\u5F85\u786E\u5B9A"}
6319
6569
  - **\u{5F00}\u{53D1}\u{6846}\u{67B6}**: ${projectInfo?.frameworks?.join(", ") || "\u5F85\u786E\u5B9A"}
6320
6570
  - **\u{7F16}\u{7A0B}\u{8BED}\u{8A00}**: ${projectInfo?.language || "\u5F85\u786E\u5B9A"}
6571
+ - **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: ${enrichedContext.businessDomain || "\u901A\u7528"}
6572
+
6573
+ ## \u{4E1A}\u{52A1}\u{80CC}\u{666F}
6574
+ ${businessContext.background || "\u57FA\u4E8E\u7528\u6237\u9700\u6C42\u8FDB\u884C\u529F\u80FD\u5F00\u53D1"}
6575
+
6576
+ ### \u{4E1A}\u{52A1}\u{76EE}\u{6807}
6577
+ ${businessContext.objectives?.map((obj)=>`- ${obj}`).join("\n") || "- \u6EE1\u8DB3\u7528\u6237\u9700\u6C42\n- \u63D0\u5347\u7CFB\u7EDF\u529F\u80FD"}
6578
+
6579
+ ### \u{6D89}\u{53CA}\u{89D2}\u{8272}
6580
+ ${businessContext.stakeholders?.map((role)=>`- ${role}`).join("\n") || "- \u7CFB\u7EDF\u7528\u6237\n- \u7CFB\u7EDF\u7BA1\u7406\u5458"}
6321
6581
 
6322
6582
  ## \u{9700}\u{6C42}\u{7C7B}\u{578B}\u{5206}\u{6790}
6323
6583
  - **\u{8BC6}\u{522B}\u{7C7B}\u{578B}**: ${analysis.requirementType}
@@ -6325,6 +6585,17 @@ Scenario Outline: \u{7528}\u{6237}\u{901A}\u{8FC7}API\u{67E5}\u{8BE2}\u{8BA2}\u{
6325
6585
  - **\u{529F}\u{80FD}\u{70B9}\u{6570}\u{91CF}**: ${featuresToProcess.length}\u{4E2A}
6326
6586
  - **\u{7F6E}\u{4FE1}\u{5EA6}**: ${analysis.confidence || "medium"}
6327
6587
 
6588
+ ## \u{6280}\u{672F}\u{4E0A}\u{4E0B}\u{6587}
6589
+ - **\u{5EFA}\u{8BAE}\u{6280}\u{672F}\u{6808}**: ${technicalContext.suggestedTechStack?.join(", ") || "\u6839\u636E\u9879\u76EE\u73B0\u6709\u6280\u672F\u6808"}
6590
+ - **\u{96C6}\u{6210}\u{70B9}**: ${technicalContext.integrationPoints?.join(", ") || "\u65E0"}
6591
+ - **\u{5B89}\u{5168}\u{8981}\u{6C42}**: ${technicalContext.securityRequirements?.join(", ") || "\u6807\u51C6\u5B89\u5168\u89C4\u8303"}
6592
+ - **\u{6027}\u{80FD}\u{8981}\u{6C42}**: ${technicalContext.performanceRequirements?.join(", ") || "\u6807\u51C6\u6027\u80FD\u8981\u6C42"}
6593
+
6594
+ ## \u{6587}\u{6863}\u{751F}\u{6210}\u{63D0}\u{793A}
6595
+ - **\u{9700}\u{8981}\u{7684}\u{65F6}\u{5E8F}\u{56FE}**: ${documentationHints.keySequenceDiagrams?.join(", ") || "\u4E3B\u6D41\u7A0B\u65F6\u5E8F\u56FE"}
6596
+ - **\u{9700}\u{8981}\u{7684}ER\u{56FE}**: ${documentationHints.keyERDiagrams?.join(", ") || "\u6838\u5FC3\u6570\u636E\u5B9E\u4F53"}
6597
+ - **\u{9700}\u{8981}\u{7684}\u{8868}\u{683C}**: ${documentationHints.keyTables?.join(", ") || "\u5B57\u6BB5\u8BF4\u660E\u8868\u3001\u63A5\u53E3\u53C2\u6570\u8868"}
6598
+
6328
6599
  ## \u{529F}\u{80FD}\u{70B9}\u{8BE6}\u{7EC6}\u{63CF}\u{8FF0}
6329
6600
 
6330
6601
  ${combinedFeatureContent}
@@ -7010,14 +7281,14 @@ ${generationTasks?.map((task, i)=>`
7010
7281
  async analyzeRequirements(params) {
7011
7282
  try {
7012
7283
  logger.info("\u5F00\u59CB\u9700\u6C42\u5206\u6790\u6D41\u7A0B", {
7013
- requirementType: params.requirement_type,
7014
- projectPath: params.current_project_path
7284
+ projectPath: params.current_project_path,
7285
+ hasPageStyle: !!params.page_style
7015
7286
  });
7016
- const { requirementContent, projectInfo } = this.parseRequirementAnalysis(params.requirement_analysis);
7287
+ const { requirementContent, projectInfo, enrichedContext } = this.parseRequirementAnalysis(params.requirement_analysis);
7017
7288
  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);
7289
+ requirementAnalysis.requirementType = "PC+API";
7290
+ requirementAnalysis.enrichedContext = enrichedContext;
7291
+ 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
7292
  } catch (error) {
7022
7293
  if (error instanceof RequirementAnalysisError) throw error;
7023
7294
  logger.error("\u9700\u6C42\u5206\u6790\u6D41\u7A0B\u5931\u8D25", {
@@ -7033,15 +7304,32 @@ ${generationTasks?.map((task, i)=>`
7033
7304
  parseRequirementAnalysis(analysisResult) {
7034
7305
  try {
7035
7306
  const parsed = JSON.parse(analysisResult);
7307
+ const enrichedContext = {
7308
+ originalRequirement: parsed.requirement_description || parsed.data?.guidance || "",
7309
+ techStack: parsed.project_context?.techStack || [],
7310
+ codeStructure: parsed.project_context?.codeStructure || {},
7311
+ businessDomain: parsed.project_context?.businessDomain || "\u901A\u7528",
7312
+ relatedFiles: parsed.project_context?.relatedFiles || [],
7313
+ dependencies: parsed.project_context?.dependencies || []
7314
+ };
7036
7315
  return {
7037
7316
  requirementContent: parsed.requirement_description || parsed.data?.guidance || analysisResult,
7038
- projectInfo: parsed.project_context || this.getDefaultProjectInfo()
7317
+ projectInfo: parsed.project_context || this.getDefaultProjectInfo(),
7318
+ enrichedContext
7039
7319
  };
7040
7320
  } catch {
7041
7321
  logger.info("\u4F7F\u7528\u6587\u672C\u683C\u5F0F\u7684\u9700\u6C42\u5206\u6790\u7ED3\u679C");
7042
7322
  return {
7043
7323
  requirementContent: analysisResult,
7044
- projectInfo: this.getDefaultProjectInfo()
7324
+ projectInfo: this.getDefaultProjectInfo(),
7325
+ enrichedContext: {
7326
+ originalRequirement: analysisResult,
7327
+ techStack: [],
7328
+ codeStructure: {},
7329
+ businessDomain: "\u901A\u7528",
7330
+ relatedFiles: [],
7331
+ dependencies: []
7332
+ }
7045
7333
  };
7046
7334
  }
7047
7335
  }
@@ -7170,23 +7458,177 @@ ${generationTasks?.map((task, i)=>`
7170
7458
  };
7171
7459
  }
7172
7460
  }
7461
+ const DEFAULT_PAGE_STYLE = `<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
7462
+ <style>
7463
+ :root {
7464
+ --bg: #ffffff;
7465
+ --bg-secondary: #f8f9fa;
7466
+ --border: #e5e5e5;
7467
+ --text: #111111;
7468
+ --text-muted: #666666;
7469
+ --accent: #000000;
7470
+ }
7471
+ </style>`;
7472
+ const API_SECTIONS = [
7473
+ {
7474
+ id: "header",
7475
+ title: "\u6587\u6863\u5934\u90E8",
7476
+ prompt: "\u751F\u6210\u6587\u6863\u6807\u9898\u3001\u751F\u6210\u65F6\u95F4\u3001\u4E1A\u52A1\u9886\u57DF\u7B49\u5934\u90E8\u4FE1\u606F"
7477
+ },
7478
+ {
7479
+ id: "background",
7480
+ title: "\u9700\u6C42\u80CC\u666F",
7481
+ prompt: "\u751F\u6210\u9700\u6C42\u80CC\u666F\u3001\u5173\u952E\u529F\u80FD\u3001\u6D89\u53CA\u89D2\u8272"
7482
+ },
7483
+ {
7484
+ id: "design",
7485
+ title: "\u529F\u80FD\u8BBE\u8BA1\u8BF4\u660E",
7486
+ 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"
7487
+ },
7488
+ {
7489
+ id: "dataModel",
7490
+ title: "\u6570\u636E\u5EFA\u6A21",
7491
+ prompt: "\u751F\u6210ER\u903B\u8F91\u56FE\u8BBE\u8BA1\uFF08\u4F7F\u7528mermaid erDiagram\uFF09\u548C\u6570\u636E\u8868\u5B9E\u4F53\u8BBE\u8BA1"
7492
+ },
7493
+ {
7494
+ id: "apiDesign",
7495
+ title: "API\u63A5\u53E3\u8BBE\u8BA1",
7496
+ prompt: "\u751F\u6210API\u63A5\u53E3\u5217\u8868\u3001\u8BF7\u6C42\u53C2\u6570\u3001\u54CD\u5E94\u53C2\u6570\u3001\u9519\u8BEF\u7801\u7B49"
7497
+ },
7498
+ {
7499
+ id: "sequence",
7500
+ title: "\u4E1A\u52A1\u65F6\u5E8F\u56FE",
7501
+ prompt: "\u751F\u6210\u4E1A\u52A1\u5BF9\u8C61\u65F6\u5E8F\u56FE\uFF08\u4F7F\u7528mermaid sequenceDiagram\uFF09"
7502
+ },
7503
+ {
7504
+ id: "status",
7505
+ title: "\u4E1A\u52A1\u72B6\u6001",
7506
+ prompt: "\u751F\u6210\u4E1A\u52A1\u72B6\u6001\u63CF\u8FF0\u8868\u683C"
7507
+ },
7508
+ {
7509
+ id: "pseudocode",
7510
+ title: "\u4F2A\u4EE3\u7801\u793A\u4F8B",
7511
+ prompt: "\u751F\u6210\u6838\u5FC3\u4E1A\u52A1\u903B\u8F91\u7684\u4F2A\u4EE3\u7801\u793A\u4F8B"
7512
+ }
7513
+ ];
7514
+ class ConcurrencyLimiter {
7515
+ maxConcurrent;
7516
+ running = 0;
7517
+ queue = [];
7518
+ constructor(maxConcurrent){
7519
+ this.maxConcurrent = maxConcurrent;
7520
+ }
7521
+ async run(fn) {
7522
+ while(this.running >= this.maxConcurrent)await new Promise((resolve)=>this.queue.push(resolve));
7523
+ this.running++;
7524
+ try {
7525
+ return await fn();
7526
+ } finally{
7527
+ this.running--;
7528
+ const next = this.queue.shift();
7529
+ if (next) next();
7530
+ }
7531
+ }
7532
+ }
7533
+ const apiLimiter = new ConcurrencyLimiter(18);
7534
+ async function generateApiSection(sectionDef, templateVariables) {
7535
+ return apiLimiter.run(async ()=>{
7536
+ try {
7537
+ 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}
7538
+
7539
+ ## \u{4EFB}\u{52A1}
7540
+ ${sectionDef.prompt}
7541
+
7542
+ ## \u{9700}\u{6C42}\u{4FE1}\u{606F}
7543
+ - \u{529F}\u{80FD}\u{540D}\u{79F0}: ${templateVariables.featureName}
7544
+ - \u{4E1A}\u{52A1}\u{9886}\u{57DF}: ${templateVariables.businessDomain}
7545
+ - \u{9700}\u{6C42}\u{8BE6}\u{60C5}: ${templateVariables.inputContent?.substring(0, 1500) || ''}
7546
+
7547
+ ## \u{8981}\u{6C42}
7548
+ - \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}
7549
+ - \u{4F7F}\u{7528}\u{6B63}\u{786E}\u{7684}Markdown\u{683C}\u{5F0F}
7550
+ - \u{5982}\u{9700}\u{56FE}\u{8868}\u{4F7F}\u{7528}mermaid\u{8BED}\u{6CD5}
7551
+ - \u{8868}\u{683C}\u{586B}\u{5199}\u{5177}\u{4F53}\u{4FE1}\u{606F}
7552
+
7553
+ \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}`;
7554
+ const content = await openAIService.generateText({
7555
+ prompt,
7556
+ system_prompt: "\u4F60\u662F\u6280\u672F\u6587\u6863\u4E13\u5BB6\uFF0C\u8F93\u51FA\u7B80\u6D01\u4E13\u4E1A\u7684\u6587\u6863\u7AE0\u8282\u3002",
7557
+ temperature: 0.7
7558
+ });
7559
+ return {
7560
+ id: sectionDef.id,
7561
+ title: sectionDef.title,
7562
+ content,
7563
+ success: true
7564
+ };
7565
+ } catch (error) {
7566
+ return {
7567
+ id: sectionDef.id,
7568
+ title: sectionDef.title,
7569
+ content: "",
7570
+ success: false,
7571
+ error: error.message
7572
+ };
7573
+ }
7574
+ });
7575
+ }
7576
+ async function generateInteractiveHtml(templateVariables) {
7577
+ const { featureName, businessDomain, pageType, pageStyle, inputContent } = templateVariables;
7578
+ 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}
7579
+
7580
+ ## \u{9700}\u{6C42}\u{4FE1}\u{606F}
7581
+ - \u{529F}\u{80FD}\u{540D}\u{79F0}: ${featureName}
7582
+ - \u{4E1A}\u{52A1}\u{9886}\u{57DF}: ${businessDomain}
7583
+ - \u{9875}\u{9762}\u{7C7B}\u{578B}: ${pageType || 'responsive'}
7584
+ - \u{9700}\u{6C42}\u{8BE6}\u{60C5}:
7585
+ ${inputContent || ''}
7586
+
7587
+ ## \u{9875}\u{9762}\u{98CE}\u{683C}\u{8981}\u{6C42}
7588
+ \u{5728}<head>\u{4E2D}\u{5305}\u{542B}\u{4EE5}\u{4E0B}\u{6837}\u{5F0F}\u{914D}\u{7F6E}\u{FF1A}
7589
+ ${pageStyle}
7590
+
7591
+ ## \u{6280}\u{672F}\u{8981}\u{6C42}
7592
+ 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>
7593
+ 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}
7594
+ 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}
7595
+ 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}
7596
+ 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}
7597
+ 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}
7598
+ 7. \u{6240}\u{6709}\u{6587}\u{672C}\u{4F7F}\u{7528}\u{4E2D}\u{6587}
7599
+ 8. \u{8BBE}\u{8BA1}\u{7F8E}\u{89C2}\u{3001}\u{73B0}\u{4EE3}\u{3001}\u{7B80}\u{6D01}
7600
+
7601
+ ## \u{8F93}\u{51FA}\u{8981}\u{6C42}
7602
+ \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}`;
7603
+ const html = await openAIService.generateText({
7604
+ prompt,
7605
+ 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",
7606
+ temperature: 0.7
7607
+ });
7608
+ let cleanHtml = html.trim();
7609
+ if (cleanHtml.startsWith("```html")) cleanHtml = cleanHtml.slice(7);
7610
+ else if (cleanHtml.startsWith("```")) cleanHtml = cleanHtml.slice(3);
7611
+ if (cleanHtml.endsWith("```")) cleanHtml = cleanHtml.slice(0, -3);
7612
+ return cleanHtml.trim();
7613
+ }
7173
7614
  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",
7615
+ name: "requirement-analyzer-report",
7616
+ 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
7617
  inputSchema: {
7177
7618
  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
7619
  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")
7620
+ 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"),
7621
+ page_type: enumType([
7622
+ "pc",
7623
+ "mobile",
7624
+ "responsive"
7625
+ ]).default("responsive").describe("页面类型(可选):\n- pc: PC端页面\n- mobile: 移动端页面\n- responsive: 响应式页面(默认,同时支持PC和移动端)")
7186
7626
  },
7187
7627
  handler: async (args)=>{
7188
7628
  try {
7189
- const { requirement_analysis, current_project_path, requirement_type } = args;
7629
+ const { requirement_analysis, current_project_path, page_style, page_type } = args;
7630
+ const finalPageStyle = page_style || DEFAULT_PAGE_STYLE;
7631
+ const finalPageType = page_type || "responsive";
7190
7632
  if (!requirement_analysis || !current_project_path) return {
7191
7633
  content: [
7192
7634
  {
@@ -7204,20 +7646,131 @@ ${generationTasks?.map((task, i)=>`
7204
7646
  const serviceResult = await service.analyzeRequirements({
7205
7647
  requirement_analysis,
7206
7648
  current_project_path,
7207
- requirement_type: requirement_type || "PC+API"
7649
+ page_style: finalPageStyle,
7650
+ page_type: finalPageType
7651
+ });
7652
+ const generationTasks = serviceResult.generationTasks || [];
7653
+ if (0 === generationTasks.length) return {
7654
+ content: [
7655
+ {
7656
+ type: "text",
7657
+ text: JSON.stringify({
7658
+ success: false,
7659
+ message: "\u6CA1\u6709\u751F\u6210\u4EFB\u52A1",
7660
+ data: null
7661
+ })
7662
+ }
7663
+ ],
7664
+ isError: true
7665
+ };
7666
+ 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}...`);
7667
+ const startTime = Date.now();
7668
+ const apiTask = generationTasks.find((t)=>"API" === t.requirementType);
7669
+ const htmlTask = generationTasks.find((t)=>"HTML" === t.requirementType);
7670
+ const results = [];
7671
+ const parallelTasks = [];
7672
+ if (apiTask) {
7673
+ const apiPromise = (async ()=>{
7674
+ try {
7675
+ 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}`);
7676
+ const sectionResults = await Promise.all(API_SECTIONS.map((section)=>generateApiSection(section, apiTask.templateVariables)));
7677
+ const successSections = sectionResults.filter((r)=>r.success);
7678
+ const header = `# ${apiTask.templateVariables.featureName} - API\u{6280}\u{672F}\u{9700}\u{6C42}\u{6587}\u{6863}
7679
+
7680
+ > **\u{751F}\u{6210}\u{65F6}\u{95F4}**: ${new Date().toISOString()}
7681
+ > **\u{4E1A}\u{52A1}\u{9886}\u{57DF}**: ${apiTask.templateVariables.businessDomain}
7682
+
7683
+ ---
7684
+
7685
+ `;
7686
+ const document = header + successSections.map((s)=>s.content).join("\n\n---\n\n");
7687
+ const outputDir = external_path_default().dirname(apiTask.outputPath);
7688
+ await promises_namespaceObject.mkdir(outputDir, {
7689
+ recursive: true
7690
+ });
7691
+ await promises_namespaceObject.writeFile(apiTask.outputPath, document, "utf-8");
7692
+ results.push({
7693
+ type: "API",
7694
+ content: document,
7695
+ outputPath: apiTask.outputPath,
7696
+ success: true
7697
+ });
7698
+ logger.info(`API\u{6587}\u{6863}\u{751F}\u{6210}\u{5B8C}\u{6210}`, {
7699
+ length: document.length
7700
+ });
7701
+ } catch (error) {
7702
+ results.push({
7703
+ type: "API",
7704
+ content: "",
7705
+ outputPath: apiTask.outputPath,
7706
+ success: false,
7707
+ error: error.message
7708
+ });
7709
+ }
7710
+ })();
7711
+ parallelTasks.push(apiPromise);
7712
+ }
7713
+ if (htmlTask) {
7714
+ const htmlPromise = (async ()=>{
7715
+ try {
7716
+ logger.info(`\u{5F00}\u{59CB}\u{751F}\u{6210}\u{53EF}\u{4EA4}\u{4E92}HTML\u{9875}\u{9762}`);
7717
+ const htmlOutputPath = htmlTask.outputPath.replace(/\.md$/, ".html");
7718
+ const htmlContent = await generateInteractiveHtml(htmlTask.templateVariables);
7719
+ const outputDir = external_path_default().dirname(htmlOutputPath);
7720
+ await promises_namespaceObject.mkdir(outputDir, {
7721
+ recursive: true
7722
+ });
7723
+ await promises_namespaceObject.writeFile(htmlOutputPath, htmlContent, "utf-8");
7724
+ results.push({
7725
+ type: "HTML",
7726
+ content: htmlContent,
7727
+ outputPath: htmlOutputPath,
7728
+ success: true
7729
+ });
7730
+ logger.info(`HTML\u{9875}\u{9762}\u{751F}\u{6210}\u{5B8C}\u{6210}`, {
7731
+ length: htmlContent.length
7732
+ });
7733
+ } catch (error) {
7734
+ results.push({
7735
+ type: "HTML",
7736
+ content: "",
7737
+ outputPath: htmlTask.outputPath,
7738
+ success: false,
7739
+ error: error.message
7740
+ });
7741
+ }
7742
+ })();
7743
+ parallelTasks.push(htmlPromise);
7744
+ }
7745
+ await Promise.all(parallelTasks);
7746
+ const totalDuration = Date.now() - startTime;
7747
+ const successCount = results.filter((r)=>r.success).length;
7748
+ const failedCount = results.filter((r)=>!r.success).length;
7749
+ const generatedFiles = results.filter((r)=>r.success).map((r)=>r.outputPath);
7750
+ logger.info(`\u{5E76}\u{884C}\u{751F}\u{6210}\u{5B8C}\u{6210}`, {
7751
+ total: results.length,
7752
+ success: successCount,
7753
+ failed: failedCount,
7754
+ totalDuration: `${totalDuration}ms`
7208
7755
  });
7209
7756
  return {
7210
7757
  content: [
7211
7758
  {
7212
7759
  type: "text",
7213
7760
  text: JSON.stringify({
7214
- success: true,
7215
- message: serviceResult.message || "\u9700\u6C42\u5206\u6790\u4EFB\u52A1\u5DF2\u51C6\u5907",
7761
+ success: successCount > 0,
7762
+ 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
7763
  data: {
7217
7764
  outputPath: serviceResult.outputPath,
7218
- generatedFiles: serviceResult.generatedFiles || [],
7765
+ generatedFiles,
7219
7766
  analysisInfo: serviceResult.analysisInfo || {},
7220
- generationTasks: serviceResult.generationTasks || []
7767
+ results: results.map((r)=>({
7768
+ type: r.type,
7769
+ outputPath: r.outputPath,
7770
+ success: r.success,
7771
+ error: r.error,
7772
+ contentLength: r.content?.length || 0
7773
+ }))
7221
7774
  }
7222
7775
  })
7223
7776
  }
@@ -7605,202 +8158,6 @@ ${requirementSection}
7605
8158
  }
7606
8159
  const external_sharp_namespaceObject = require("sharp");
7607
8160
  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
- }
7803
- }
7804
8161
  class ImageAnalysisError extends Error {
7805
8162
  code;
7806
8163
  context;
@@ -7837,7 +8194,7 @@ ${requirementSection}
7837
8194
  });
7838
8195
  await this.validateParams(imagePath);
7839
8196
  const basicInfo = await this.getImageBasicInfo(imagePath);
7840
- const analysisContent = await this.performAIAnalysis(imagePath, basicInfo, context);
8197
+ const analysisContent = await this.performAIAnalysis(imagePath, context);
7841
8198
  const processingTime = Date.now() - startTime;
7842
8199
  if (!analysisContent) throw new ImageAnalysisError("AI\u5206\u6790\u8FD4\u56DE\u7A7A\u7ED3\u679C", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
7843
8200
  params: {
@@ -7864,16 +8221,15 @@ ${requirementSection}
7864
8221
  throw error;
7865
8222
  }
7866
8223
  }
7867
- async performAIAnalysis(imagePath, basicInfo, context) {
8224
+ async performAIAnalysis(imagePath, context) {
7868
8225
  try {
7869
- const imageBase64 = await this.imageToBase64(imagePath);
7870
8226
  const systemPrompt = `You must interpret and analyze images strictly according to the assigned task.
7871
8227
  When an image placeholder is provided, your role is to parse the image content only within the scope of the user's instructions.
7872
8228
  Do not ignore or deviate from the task.
7873
8229
  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,
8230
+ 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`;
8231
+ const aiResponse = await openAIService.analyzeImageWithPath({
8232
+ image_path: imagePath,
7877
8233
  prompt: userPrompt,
7878
8234
  system_prompt: systemPrompt
7879
8235
  });
@@ -7883,26 +8239,15 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7883
8239
  tags: []
7884
8240
  };
7885
8241
  } catch (error) {
7886
- logger.warn("\u4E3BAI\u5206\u6790\u5931\u8D25\uFF0C\u5C1D\u8BD5Dify\u515C\u5E95\u5206\u6790", {
8242
+ logger.error("AI\u5206\u6790\u5931\u8D25", {
7887
8243
  error,
7888
8244
  params: {
7889
8245
  image_path: imagePath
7890
8246
  }
7891
8247
  });
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
- }
8248
+ throw new ImageAnalysisError("\u8BC6\u522B\u56FE\u7247\u5931\u8D25", types_AnalysisErrorCodes.ANALYSIS_FAILED, {
8249
+ originalError: error
8250
+ });
7906
8251
  }
7907
8252
  }
7908
8253
  async getImageBasicInfo(imagePath) {
@@ -7911,7 +8256,7 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7911
8256
  const stats = await promises_namespaceObject.stat(imagePath);
7912
8257
  return {
7913
8258
  path: imagePath,
7914
- format: metadata.format || 'unknown',
8259
+ format: metadata.format || "unknown",
7915
8260
  dimensions: {
7916
8261
  width: metadata.width || 0,
7917
8262
  height: metadata.height || 0
@@ -7925,37 +8270,6 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7925
8270
  });
7926
8271
  }
7927
8272
  }
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
8273
  async validateParams(imagePath) {
7960
8274
  try {
7961
8275
  await promises_namespaceObject.access(imagePath);
@@ -7970,81 +8284,17 @@ Always ensure that your response reflects a clear, accurate interpretation of th
7970
8284
  supportedFormats: SUPPORTED_IMAGE_FORMATS
7971
8285
  });
7972
8286
  }
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
8287
  }
8038
8288
  const ImageAnalysisParamsSchema = objectType({
8039
8289
  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")
8290
+ 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
8291
  });
8042
8292
  const read_imageTool = {
8043
8293
  name: "read_image",
8044
8294
  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
8295
  inputSchema: {
8046
8296
  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")
8297
+ 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
8298
  },
8049
8299
  handler: async (args)=>{
8050
8300
  const analyzer = new ImageAnalyzer();
@@ -8370,7 +8620,7 @@ ${error?.message || "\u672A\u77E5\u9519\u8BEF"}`;
8370
8620
  output_directory: stringType().optional().describe("\u8F93\u51FA\u76EE\u5F55\uFF0C\u4E0D\u6307\u5B9A\u5219\u5728\u539F\u6587\u4EF6\u76EE\u5F55\u751F\u6210")
8371
8621
  });
8372
8622
  const imageConverterTool = {
8373
- name: "\u56FE\u7247\u683C\u5F0F\u8F6C\u6362\u667A\u80FD\u4F53",
8623
+ name: "image-converter",
8374
8624
  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
8625
  inputSchema: {
8376
8626
  input_paths: unionType([
@@ -8462,7 +8712,7 @@ ${results.map((r, index)=>`
8462
8712
  - **\u{8F93}\u{51FA}**: \`${r.output_path}\`
8463
8713
  - **\u{683C}\u{5F0F}**: ${r.format?.toUpperCase()}
8464
8714
  - **\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)}
8715
+ - **\u{6587}\u{4EF6}\u{5927}\u{5C0F}**: ${formatFileSize(r.file_size || 0)}
8466
8716
  `).join("")}
8467
8717
 
8468
8718
  ${args.width || args.height ? `
@@ -8498,7 +8748,7 @@ ${successResults.map((r, index)=>`
8498
8748
  ${index + 1}. **${getFileName(r.input_path)}**
8499
8749
  - \u{8F93}\u{51FA}: \`${r.output_path}\`
8500
8750
  - \u{5C3A}\u{5BF8}: ${r.dimensions?.width} \xd7 ${r.dimensions?.height}
8501
- - \u{5927}\u{5C0F}: ${image_converter_formatFileSize(r.file_size || 0)}
8751
+ - \u{5927}\u{5C0F}: ${formatFileSize(r.file_size || 0)}
8502
8752
  `).join("")}
8503
8753
 
8504
8754
  ## \u{274C} \u{8F6C}\u{6362}\u{5931}\u{8D25} (${failedResults.length}\u{5F20})
@@ -8565,7 +8815,7 @@ ${getErrorSuggestion(error.code)}
8565
8815
  function getFileName(filePath) {
8566
8816
  return filePath.split("/").pop() || filePath;
8567
8817
  }
8568
- function image_converter_formatFileSize(bytes) {
8818
+ function formatFileSize(bytes) {
8569
8819
  if (0 === bytes) return "0 B";
8570
8820
  const k = 1024;
8571
8821
  const sizes = [
@@ -8636,6 +8886,7 @@ ${getErrorSuggestion(error.code)}
8636
8886
  RETRY_DELAY_MS: 1000
8637
8887
  };
8638
8888
  const ImageRecognitionParamsSchema = objectType({
8889
+ 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
8890
  imagePath: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
8640
8891
  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
8892
  });
@@ -9043,8 +9294,8 @@ ${getErrorSuggestion(error.code)}
9043
9294
  }
9044
9295
  class analyzer_ImageAnalyzer {
9045
9296
  context;
9046
- async analyzeLongImage(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context) {
9047
- logger.info("ImageAnalyzer: \u5F00\u59CB\u5206\u6790\u957F\u56FE", {
9297
+ async analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context, onSegmentComplete) {
9298
+ logger.info("ImageAnalyzer: \u5F00\u59CB\u6D41\u5F0F\u5206\u6790\u957F\u56FE", {
9048
9299
  imagePath,
9049
9300
  totalSegments: segmentConfig.totalSegments,
9050
9301
  maxConcurrency: concurrencyConfig.maxConcurrency,
@@ -9054,24 +9305,36 @@ ${getErrorSuggestion(error.code)}
9054
9305
  const startTime = Date.now();
9055
9306
  const segmentResults = [];
9056
9307
  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));
9308
+ const segments = await this.generateSegments(imagePath, imageInfo, segmentConfig);
9309
+ for(let i = 0; i < segments.length; i++){
9310
+ const { buffer, info } = segments[i];
9311
+ try {
9312
+ const result = await this.analyzeSegment(buffer, info, apiPreference);
9313
+ segmentResults.push(result);
9314
+ if (onSegmentComplete) await onSegmentComplete(result, {
9315
+ current: i + 1,
9316
+ total: segments.length
9317
+ });
9318
+ } catch (error) {
9319
+ logger.error(`\u{6BB5}\u{843D} ${info.index} \u{5206}\u{6790}\u{5931}\u{8D25}`, {
9320
+ error
9321
+ });
9322
+ const errorResult = {
9323
+ segmentIndex: info.index,
9324
+ textContent: '',
9325
+ imageDescription: '',
9326
+ confidence: 0,
9327
+ processingTimeMs: 0,
9328
+ apiUsed: 'none',
9329
+ error: error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"
9330
+ };
9331
+ segmentResults.push(errorResult);
9332
+ if (onSegmentComplete) await onSegmentComplete(errorResult, {
9333
+ current: i + 1,
9334
+ total: segments.length
9335
+ });
9336
+ }
9337
+ }
9075
9338
  const summary = this.generateProcessingSummary(segmentResults, startTime);
9076
9339
  const result = {
9077
9340
  imageInfo,
@@ -9080,7 +9343,7 @@ ${getErrorSuggestion(error.code)}
9080
9343
  outputPath: '',
9081
9344
  success: 0 === summary.failedSegments
9082
9345
  };
9083
- logger.info("\u957F\u56FE\u5206\u6790\u5B8C\u6210", {
9346
+ logger.info("\u957F\u56FE\u6D41\u5F0F\u5206\u6790\u5B8C\u6210", {
9084
9347
  imagePath,
9085
9348
  totalSegments: summary.totalSegments,
9086
9349
  successfulSegments: summary.successfulSegments,
@@ -9089,7 +9352,7 @@ ${getErrorSuggestion(error.code)}
9089
9352
  });
9090
9353
  return result;
9091
9354
  } catch (error) {
9092
- logger.error("\u957F\u56FE\u5206\u6790\u5931\u8D25", {
9355
+ logger.error("\u957F\u56FE\u6D41\u5F0F\u5206\u6790\u5931\u8D25", {
9093
9356
  imagePath,
9094
9357
  error
9095
9358
  });
@@ -9099,6 +9362,9 @@ ${getErrorSuggestion(error.code)}
9099
9362
  });
9100
9363
  }
9101
9364
  }
9365
+ async analyzeLongImage(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference = 'auto', context) {
9366
+ return this.analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference, context);
9367
+ }
9102
9368
  async processSegmentsConcurrently(imagePath, imageInfo, segmentConfig, concurrencyConfig, apiPreference) {
9103
9369
  const results = [];
9104
9370
  const { maxConcurrency, batchSize, delayBetweenBatches } = concurrencyConfig;
@@ -9278,7 +9544,7 @@ ${getErrorSuggestion(error.code)}
9278
9544
  let prompt = '';
9279
9545
  prompt = this.context ? `${this.context}
9280
9546
 
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}
9547
+ 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
9548
 
9283
9549
  ` : `\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
9550
 
@@ -9296,7 +9562,10 @@ ${getErrorSuggestion(error.code)}
9296
9562
  else prompt += `\u{8FD9}\u{662F}\u{56FE}\u{7247}\u{7684}\u{4E2D}\u{95F4}\u{90E8}\u{5206}\u{3002}`;
9297
9563
  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
9564
  }
9299
- prompt += `
9565
+ if (this.context) prompt += `
9566
+
9567
+ 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}`;
9568
+ else prompt += `
9300
9569
 
9301
9570
  \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
9571
  \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 +9671,13 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9402
9671
  this.configCalculator = new ConfigCalculator();
9403
9672
  this.analyzer = new analyzer_ImageAnalyzer();
9404
9673
  }
9405
- async processImage(imagePath, context) {
9674
+ async processImage(imagePath, projectPath, context, callbacks) {
9406
9675
  const startTime = Date.now();
9407
9676
  logger.info("ImageRecognitionProcessor: \u5F00\u59CB\u5904\u7406\u56FE\u7247", {
9408
9677
  imagePath
9409
9678
  });
9679
+ let outputPath = '';
9680
+ const segmentResults = [];
9410
9681
  try {
9411
9682
  await this.validateImageFile(imagePath);
9412
9683
  const validation = await this.preprocessor.validateImage(imagePath);
@@ -9428,55 +9699,51 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9428
9699
  segmentHeight: segmentConfig.segmentHeight,
9429
9700
  maxConcurrency: concurrencyConfig.maxConcurrency
9430
9701
  });
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", {
9702
+ outputPath = await this.initializeOutputFile(imageInfo, segmentConfig.totalSegments, projectPath);
9703
+ callbacks?.onStart?.({
9435
9704
  outputPath,
9705
+ totalSegments: segmentConfig.totalSegments,
9706
+ imageInfo
9707
+ });
9708
+ const analysisResult = await this.analyzer.analyzeLongImageStreaming(imagePath, imageInfo, segmentConfig, concurrencyConfig, 'auto', context, async (result, progress)=>{
9709
+ segmentResults.push(result);
9710
+ await this.appendSegmentToFile(outputPath, result);
9711
+ callbacks?.onSegmentComplete?.(result, progress);
9712
+ });
9713
+ await this.finalizeOutputFile(outputPath, analysisResult.summary);
9714
+ const totalTime = Date.now() - startTime;
9715
+ const summary = {
9436
9716
  totalSegments: analysisResult.summary.totalSegments,
9437
9717
  successfulSegments: analysisResult.summary.successfulSegments,
9718
+ failedSegments: analysisResult.summary.failedSegments,
9719
+ successRate: analysisResult.summary.successRate,
9720
+ totalTextCharacters: analysisResult.summary.totalTextCharacters,
9721
+ totalProcessingTimeMs: totalTime,
9722
+ averageConfidence: analysisResult.summary.averageConfidence
9723
+ };
9724
+ callbacks?.onComplete?.(analysisResult.summary);
9725
+ logger.info("\u56FE\u7247\u5904\u7406\u5B8C\u6210", {
9726
+ outputPath,
9727
+ totalSegments: summary.totalSegments,
9728
+ successfulSegments: summary.successfulSegments,
9438
9729
  totalTimeMs: totalTime
9439
9730
  });
9440
9731
  return {
9441
9732
  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
- }
9733
+ summary
9451
9734
  };
9452
9735
  } catch (error) {
9453
9736
  logger.error("\u56FE\u7247\u5904\u7406\u5931\u8D25", {
9454
9737
  imagePath,
9455
9738
  error
9456
9739
  });
9740
+ callbacks?.onError?.(error instanceof Error ? error : new Error(String(error)));
9457
9741
  throw error;
9458
9742
  }
9459
9743
  }
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();
9744
+ async initializeOutputFile(imageInfo, totalSegments, projectPath) {
9478
9745
  const dateDir = new Date().toISOString().split('T')[0];
9479
- const outputDirectory = external_path_namespaceObject.join(baseDir, 'image-recognition', dateDir);
9746
+ const outputDirectory = external_path_namespaceObject.join(projectPath, '.aico', 'image-recognition', dateDir);
9480
9747
  await external_fs_namespaceObject.promises.mkdir(outputDirectory, {
9481
9748
  recursive: true
9482
9749
  });
@@ -9484,39 +9751,78 @@ Always ensure that your response reflects a clear, accurate interpretation of th
9484
9751
  const imageBaseName = external_path_namespaceObject.basename(imageInfo.fileName, external_path_namespaceObject.extname(imageInfo.fileName));
9485
9752
  const fileName = `${imageBaseName}-${timestamp}.md`;
9486
9753
  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}
9754
+ const header = `# ${imageInfo.fileName} - \u{56FE}\u{7247}\u{6587}\u{5B57}\u{8BC6}\u{522B}\u{7ED3}\u{679C}
9489
9755
 
9490
9756
  **\u{8BC6}\u{522B}\u{65F6}\u{95F4}**: ${new Date().toLocaleString('zh-CN')}
9491
9757
  **\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)}%
9758
+ **\u{9884}\u{8BA1}\u{6BB5}\u{6570}**: ${totalSegments}
9759
+ **\u{72B6}\u{6001}**: \u{1F504} \u{8BC6}\u{522B}\u{4E2D}...
9496
9760
 
9497
9761
  ---
9498
9762
 
9499
9763
  ## \u{8BC6}\u{522B}\u{7684}\u{6587}\u{5B57}\u{5185}\u{5BB9}
9500
9764
 
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
9765
  `;
9507
- await external_fs_namespaceObject.promises.writeFile(outputPath, content, 'utf8');
9508
- logger.info("\u8F93\u51FA\u6587\u4EF6\u751F\u6210\u5B8C\u6210", {
9766
+ await external_fs_namespaceObject.promises.writeFile(outputPath, header, 'utf8');
9767
+ logger.info("\u8F93\u51FA\u6587\u4EF6\u521D\u59CB\u5316\u5B8C\u6210", {
9509
9768
  outputPath,
9510
- fileName,
9511
- contentLength: content.length
9769
+ totalSegments
9512
9770
  });
9513
9771
  return outputPath;
9514
9772
  }
9773
+ async appendSegmentToFile(outputPath, result) {
9774
+ let content = '';
9775
+ if (result.error) content = `<!-- \u{6BB5}\u{843D} ${result.segmentIndex + 1} \u{5904}\u{7406}\u{5931}\u{8D25}: ${result.error} -->\n\n`;
9776
+ else if (result.textContent && result.textContent.trim()) content = `${result.textContent.trim()}\n\n`;
9777
+ if (content) await external_fs_namespaceObject.promises.appendFile(outputPath, content, 'utf8');
9778
+ }
9779
+ async finalizeOutputFile(outputPath, summary) {
9780
+ const footer = `
9781
+ ---
9782
+
9783
+ ## \u{5904}\u{7406}\u{6458}\u{8981}
9784
+
9785
+ - **\u{603B}\u{6BB5}\u{6570}**: ${summary.totalSegments}
9786
+ - **\u{6210}\u{529F}\u{6BB5}\u{6570}**: ${summary.successfulSegments}
9787
+ - **\u{5931}\u{8D25}\u{6BB5}\u{6570}**: ${summary.failedSegments}
9788
+ - **\u{6210}\u{529F}\u{7387}**: ${(100 * summary.successRate).toFixed(1)}%
9789
+ - **\u{6587}\u{5B57}\u{5B57}\u{7B26}\u{603B}\u{6570}**: ${summary.totalTextCharacters.toLocaleString()}
9790
+ - **\u{5E73}\u{5747}\u{7F6E}\u{4FE1}\u{5EA6}**: ${(100 * summary.averageConfidence).toFixed(1)}%
9791
+ - **\u{5904}\u{7406}\u{8017}\u{65F6}**: ${(summary.totalProcessingTimeMs / 1000).toFixed(2)}\u{79D2}
9792
+
9793
+ **\u{72B6}\u{6001}**: \u{2705} \u{8BC6}\u{522B}\u{5B8C}\u{6210}
9794
+ **\u{5B8C}\u{6210}\u{65F6}\u{95F4}**: ${new Date().toLocaleString('zh-CN')}
9795
+ `;
9796
+ await external_fs_namespaceObject.promises.appendFile(outputPath, footer, 'utf8');
9797
+ const content = await external_fs_namespaceObject.promises.readFile(outputPath, 'utf8');
9798
+ const updatedContent = content.replace("**\u72B6\u6001**: \uD83D\uDD04 \u8BC6\u522B\u4E2D...", "**\u72B6\u6001**: \u2705 \u8BC6\u522B\u5B8C\u6210");
9799
+ await external_fs_namespaceObject.promises.writeFile(outputPath, updatedContent, 'utf8');
9800
+ logger.info("\u8F93\u51FA\u6587\u4EF6\u5B8C\u6210", {
9801
+ outputPath
9802
+ });
9803
+ }
9804
+ async validateImageFile(imagePath) {
9805
+ try {
9806
+ const stats = await external_fs_namespaceObject.promises.stat(imagePath);
9807
+ 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, {
9808
+ imagePath
9809
+ });
9810
+ } catch (error) {
9811
+ if ('ENOENT' === error.code) throw new ImageRecognitionError("\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728", types_ErrorTypes.FILE_NOT_FOUND, {
9812
+ imagePath
9813
+ });
9814
+ throw new ImageRecognitionError(`\u{6587}\u{4EF6}\u{8BBF}\u{95EE}\u{9519}\u{8BEF}: ${error.message}`, types_ErrorTypes.VALIDATION_ERROR, {
9815
+ imagePath,
9816
+ originalError: error
9817
+ });
9818
+ }
9819
+ }
9515
9820
  }
9516
9821
  const imageRecognitionAgentTool = {
9517
9822
  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",
9823
+ 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
9824
  inputSchema: {
9825
+ 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
9826
  imagePath: stringType().min(1).describe("\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84"),
9521
9827
  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
9828
  },
@@ -9526,13 +9832,21 @@ ${allTextContent || "\u672A\u8BC6\u522B\u5230\u6587\u5B57\u5185\u5BB9"}
9526
9832
  args
9527
9833
  });
9528
9834
  try {
9529
- const { imagePath, context } = ImageRecognitionParamsSchema.parse(args);
9835
+ const { projectPath, imagePath, context } = ImageRecognitionParamsSchema.parse(args);
9530
9836
  const processor = new ImageRecognitionProcessor();
9531
- const result = await processor.processImage(imagePath, context);
9837
+ const result = await processor.processImage(imagePath, projectPath, context);
9532
9838
  logger.info("\u56FE\u7247\u5185\u5BB9\u8BC6\u522B\u667A\u80FD\u4F53: \u5904\u7406\u5B8C\u6210", {
9533
9839
  outputPath: result.outputPath,
9534
9840
  summary: result.summary
9535
9841
  });
9842
+ let fileContent = '';
9843
+ try {
9844
+ fileContent = await external_fs_namespaceObject.promises.readFile(result.outputPath, 'utf8');
9845
+ } catch (readError) {
9846
+ logger.warn("\u8BFB\u53D6\u7ED3\u679C\u6587\u4EF6\u5931\u8D25", {
9847
+ error: readError
9848
+ });
9849
+ }
9536
9850
  return {
9537
9851
  content: [
9538
9852
  {
@@ -9547,10 +9861,14 @@ ${allTextContent || "\u672A\u8BC6\u522B\u5230\u6587\u5B57\u5185\u5BB9"}
9547
9861
  - \u{5E73}\u{5747}\u{7F6E}\u{4FE1}\u{5EA6}: ${(100 * result.summary.averageConfidence).toFixed(1)}%
9548
9862
  - \u{5904}\u{7406}\u{8017}\u{65F6}: ${(result.summary.totalProcessingTimeMs / 1000).toFixed(2)}\u{79D2}
9549
9863
 
9550
- \u{1F4C4} **\u{7ED3}\u{679C}\u{6587}\u{4EF6}**:
9864
+ \u{1F4C4} **\u{7ED3}\u{679C}\u{6587}\u{4EF6}\u{8DEF}\u{5F84}**:
9551
9865
  \`${result.outputPath}\`
9552
9866
 
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}`
9867
+ ---
9868
+
9869
+ ## \u{8BC6}\u{522B}\u{7684}\u{5B8C}\u{6574}\u{5185}\u{5BB9}
9870
+
9871
+ ${fileContent}`
9554
9872
  }
9555
9873
  ]
9556
9874
  };