feihong-code 7.0.0 → 7.2.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 (236) hide show
  1. package/.github/workflows/release.yml +173 -0
  2. package/CHANGELOG.md +50 -0
  3. package/dist/agent/browser-agent.js +354 -0
  4. package/dist/agent/browser-agent.js.map +1 -0
  5. package/dist/agent/change-manager.js +433 -0
  6. package/dist/agent/change-manager.js.map +1 -0
  7. package/dist/agent/code-rag.js +293 -0
  8. package/dist/agent/code-rag.js.map +1 -0
  9. package/dist/agent/code-writer.js +13 -1
  10. package/dist/agent/code-writer.js.map +1 -1
  11. package/dist/agent/completion-engine.js +522 -0
  12. package/dist/agent/completion-engine.js.map +1 -0
  13. package/dist/agent/context-compactor.js +188 -10
  14. package/dist/agent/context-compactor.js.map +1 -1
  15. package/dist/agent/custom-agent.js +368 -0
  16. package/dist/agent/custom-agent.js.map +1 -0
  17. package/dist/agent/design-to-code.js +218 -0
  18. package/dist/agent/design-to-code.js.map +1 -0
  19. package/dist/agent/event-driven-agent.js +359 -0
  20. package/dist/agent/event-driven-agent.js.map +1 -0
  21. package/dist/agent/git-integration.js +324 -0
  22. package/dist/agent/git-integration.js.map +1 -0
  23. package/dist/agent/layered-memory.js +329 -0
  24. package/dist/agent/layered-memory.js.map +1 -0
  25. package/dist/agent/multi-agent.js +359 -0
  26. package/dist/agent/multi-agent.js.map +1 -0
  27. package/dist/agent/orchestrator.js +127 -16
  28. package/dist/agent/orchestrator.js.map +1 -1
  29. package/dist/agent/quality-gate.js +139 -0
  30. package/dist/agent/quality-gate.js.map +1 -1
  31. package/dist/agent/self-correction.js +274 -0
  32. package/dist/agent/self-correction.js.map +1 -0
  33. package/dist/agent/self-heal.js +40 -10
  34. package/dist/agent/self-heal.js.map +1 -1
  35. package/dist/agent/solo-agent.js +321 -0
  36. package/dist/agent/solo-agent.js.map +1 -0
  37. package/dist/agent/symbol-index.js +258 -28
  38. package/dist/agent/symbol-index.js.map +1 -1
  39. package/dist/agent/team-collaboration.js +252 -0
  40. package/dist/agent/team-collaboration.js.map +1 -0
  41. package/dist/agent/type-checker.js +229 -0
  42. package/dist/agent/type-checker.js.map +1 -0
  43. package/dist/cli/run.js +1 -0
  44. package/dist/cli/run.js.map +1 -1
  45. package/dist/integrations/collaboration.js +219 -0
  46. package/dist/integrations/collaboration.js.map +1 -0
  47. package/dist/integrations/figma.js +307 -0
  48. package/dist/integrations/figma.js.map +1 -0
  49. package/dist/integrations/sso.js +327 -0
  50. package/dist/integrations/sso.js.map +1 -0
  51. package/dist/knowledge/library.js +301 -0
  52. package/dist/knowledge/library.js.map +1 -0
  53. package/dist/plugins/manager.js +332 -0
  54. package/dist/plugins/manager.js.map +1 -0
  55. package/dist/runtime/event-log.js.map +1 -1
  56. package/dist/tools/browser/browser.tool.js +217 -0
  57. package/dist/tools/browser/browser.tool.js.map +1 -0
  58. package/dist/tools/index.js +2 -0
  59. package/dist/tools/index.js.map +1 -1
  60. package/dist/tools/shell/exec.js +50 -10
  61. package/dist/tools/shell/exec.js.map +1 -1
  62. package/dist/tools/shell/run-shell.tool.js +8 -2
  63. package/dist/tools/shell/run-shell.tool.js.map +1 -1
  64. package/dist/training/completion-evaluator.js +213 -0
  65. package/dist/training/completion-evaluator.js.map +1 -0
  66. package/dist/training/fim-data.js +248 -0
  67. package/dist/training/fim-data.js.map +1 -0
  68. package/dist/voice/voice-programming.js +223 -0
  69. package/dist/voice/voice-programming.js.map +1 -0
  70. package/dist/web/public/css/style.css +58 -0
  71. package/dist/web/public/index.html +210 -0
  72. package/dist/web/public/js/api.js +115 -1
  73. package/dist/web/public/js/mock-api.js +234 -0
  74. package/dist/web/public/js/monaco-editor.js +203 -0
  75. package/dist/web/public/js/ui.js +926 -4
  76. package/dist/web/public/manifest.json +59 -0
  77. package/dist/web/public/service-worker.js +173 -0
  78. package/dist/web/public/vendor/monaco/vs/abap-D-t0cyap.js +1 -0
  79. package/dist/web/public/vendor/monaco/vs/apex-CcIm7xu6.js +1 -0
  80. package/dist/web/public/vendor/monaco/vs/assets/css.worker-URu8fCFR.js +97 -0
  81. package/dist/web/public/vendor/monaco/vs/assets/editor.worker-lj3bdIIn.js +30 -0
  82. package/dist/web/public/vendor/monaco/vs/assets/editorWebWorkerMain-CA_vMoUU.js +30 -0
  83. package/dist/web/public/vendor/monaco/vs/assets/html.worker-D1SL3iM8.js +474 -0
  84. package/dist/web/public/vendor/monaco/vs/assets/json.worker-CoJx_OPf.js +62 -0
  85. package/dist/web/public/vendor/monaco/vs/assets/ts.worker-BWKtMYOk.js +67722 -0
  86. package/dist/web/public/vendor/monaco/vs/azcli-BA0tQDCg.js +1 -0
  87. package/dist/web/public/vendor/monaco/vs/basic-languages/monaco.contribution.js +1 -0
  88. package/dist/web/public/vendor/monaco/vs/bat-C397hTD6.js +1 -0
  89. package/dist/web/public/vendor/monaco/vs/bicep-DF5aW17k.js +2 -0
  90. package/dist/web/public/vendor/monaco/vs/cameligo-plsz8qhj.js +1 -0
  91. package/dist/web/public/vendor/monaco/vs/clojure-Y2auQMzK.js +1 -0
  92. package/dist/web/public/vendor/monaco/vs/coffee-Bu45yuWE.js +1 -0
  93. package/dist/web/public/vendor/monaco/vs/cpp-CkKPQIni.js +1 -0
  94. package/dist/web/public/vendor/monaco/vs/csharp-CX28MZyh.js +1 -0
  95. package/dist/web/public/vendor/monaco/vs/csp-D8uWnyxW.js +1 -0
  96. package/dist/web/public/vendor/monaco/vs/css-CaeNmE3S.js +3 -0
  97. package/dist/web/public/vendor/monaco/vs/css.worker-CyhWkhHo.js +1 -0
  98. package/dist/web/public/vendor/monaco/vs/cssMode-CV6Ay48H.js +1 -0
  99. package/dist/web/public/vendor/monaco/vs/cypher-DVThT8BS.js +1 -0
  100. package/dist/web/public/vendor/monaco/vs/dart-CmGfCvrO.js +1 -0
  101. package/dist/web/public/vendor/monaco/vs/dockerfile-CZqqYdch.js +1 -0
  102. package/dist/web/public/vendor/monaco/vs/ecl-30fUercY.js +1 -0
  103. package/dist/web/public/vendor/monaco/vs/editor/editor.main.css +1 -0
  104. package/dist/web/public/vendor/monaco/vs/editor/editor.main.js +1 -0
  105. package/dist/web/public/vendor/monaco/vs/editor/editor.worker.js +1 -0
  106. package/dist/web/public/vendor/monaco/vs/editor-KLE6jdfb.js +831 -0
  107. package/dist/web/public/vendor/monaco/vs/editor.js +1 -0
  108. package/dist/web/public/vendor/monaco/vs/editorWorkerHost-fVE1cjcC.js +35 -0
  109. package/dist/web/public/vendor/monaco/vs/elixir-xjPaIfzF.js +1 -0
  110. package/dist/web/public/vendor/monaco/vs/flow9-DqtmStfK.js +1 -0
  111. package/dist/web/public/vendor/monaco/vs/freemarker2-FWreY7v7.js +3 -0
  112. package/dist/web/public/vendor/monaco/vs/fsharp-BOMdg4U1.js +1 -0
  113. package/dist/web/public/vendor/monaco/vs/go-D_hbi-Jt.js +1 -0
  114. package/dist/web/public/vendor/monaco/vs/graphql-CKUU4kLG.js +1 -0
  115. package/dist/web/public/vendor/monaco/vs/handlebars-CZi4pHCH.js +1 -0
  116. package/dist/web/public/vendor/monaco/vs/hcl-DTaboeZW.js +1 -0
  117. package/dist/web/public/vendor/monaco/vs/html-j_7ZTNRU.js +1 -0
  118. package/dist/web/public/vendor/monaco/vs/html.worker-CA3iAimZ.js +1 -0
  119. package/dist/web/public/vendor/monaco/vs/htmlMode-27by_KM4.js +1 -0
  120. package/dist/web/public/vendor/monaco/vs/index-049xrXrp.js +1 -0
  121. package/dist/web/public/vendor/monaco/vs/index-CBVt3dzv.js +5 -0
  122. package/dist/web/public/vendor/monaco/vs/index.js +1 -0
  123. package/dist/web/public/vendor/monaco/vs/ini-CsNwO04R.js +1 -0
  124. package/dist/web/public/vendor/monaco/vs/initialize-DL0l1TGY.js +1 -0
  125. package/dist/web/public/vendor/monaco/vs/java-CI4ZMsH9.js +1 -0
  126. package/dist/web/public/vendor/monaco/vs/javascript-DTJl4Jn1.js +1 -0
  127. package/dist/web/public/vendor/monaco/vs/json.worker-BizpAl9O.js +1 -0
  128. package/dist/web/public/vendor/monaco/vs/jsonMode-DLUiMUrI.js +1 -0
  129. package/dist/web/public/vendor/monaco/vs/julia-BwzEvaQw.js +1 -0
  130. package/dist/web/public/vendor/monaco/vs/kotlin-IUYPiTV8.js +1 -0
  131. package/dist/web/public/vendor/monaco/vs/language/css/css.worker.js +66 -0
  132. package/dist/web/public/vendor/monaco/vs/language/css/monaco.contribution.js +1 -0
  133. package/dist/web/public/vendor/monaco/vs/language/html/html.worker.js +443 -0
  134. package/dist/web/public/vendor/monaco/vs/language/html/monaco.contribution.js +1 -0
  135. package/dist/web/public/vendor/monaco/vs/language/json/json.worker.js +17 -0
  136. package/dist/web/public/vendor/monaco/vs/language/json/monaco.contribution.js +1 -0
  137. package/dist/web/public/vendor/monaco/vs/language/typescript/monaco.contribution.js +1 -0
  138. package/dist/web/public/vendor/monaco/vs/language/typescript/ts.worker.js +67693 -0
  139. package/dist/web/public/vendor/monaco/vs/less-C0eDYdqa.js +2 -0
  140. package/dist/web/public/vendor/monaco/vs/lexon-iON-Kj97.js +1 -0
  141. package/dist/web/public/vendor/monaco/vs/liquid-CLJYelW6.js +1 -0
  142. package/dist/web/public/vendor/monaco/vs/loader.js +1368 -0
  143. package/dist/web/public/vendor/monaco/vs/lspLanguageFeatures-BIkJOWLw.js +2 -0
  144. package/dist/web/public/vendor/monaco/vs/lua-DtygF91M.js +1 -0
  145. package/dist/web/public/vendor/monaco/vs/m3-CsR4AuFi.js +1 -0
  146. package/dist/web/public/vendor/monaco/vs/main-BEx-Fmlo.js +15 -0
  147. package/dist/web/public/vendor/monaco/vs/main-DsK8pnKg.js +3 -0
  148. package/dist/web/public/vendor/monaco/vs/markdown-C_rD0bIw.js +1 -0
  149. package/dist/web/public/vendor/monaco/vs/mdx-CpzZIPHF.js +1 -0
  150. package/dist/web/public/vendor/monaco/vs/mips-CiYP61RB.js +1 -0
  151. package/dist/web/public/vendor/monaco/vs/monaco.contribution-9cKT3C7t.js +1 -0
  152. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BE88ZNGY.js +1 -0
  153. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BPhsneLd.js +1 -0
  154. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BgRy6xDf.js +1 -0
  155. package/dist/web/public/vendor/monaco/vs/msdax-C38-sJlp.js +1 -0
  156. package/dist/web/public/vendor/monaco/vs/mysql-CdtbpvbG.js +1 -0
  157. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.d.ts +1 -0
  158. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.js +9 -0
  159. package/dist/web/public/vendor/monaco/vs/nls/lang/de.d.ts +1 -0
  160. package/dist/web/public/vendor/monaco/vs/nls/lang/de.js +9 -0
  161. package/dist/web/public/vendor/monaco/vs/nls/lang/es.d.ts +1 -0
  162. package/dist/web/public/vendor/monaco/vs/nls/lang/es.js +9 -0
  163. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.d.ts +1 -0
  164. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.js +9 -0
  165. package/dist/web/public/vendor/monaco/vs/nls/lang/it.d.ts +1 -0
  166. package/dist/web/public/vendor/monaco/vs/nls/lang/it.js +9 -0
  167. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.d.ts +1 -0
  168. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.js +9 -0
  169. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.d.ts +1 -0
  170. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.js +9 -0
  171. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.d.ts +1 -0
  172. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.js +9 -0
  173. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.d.ts +1 -0
  174. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.js +9 -0
  175. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.d.ts +1 -0
  176. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.js +9 -0
  177. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.d.ts +1 -0
  178. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.js +9 -0
  179. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.d.ts +1 -0
  180. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.js +9 -0
  181. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.d.ts +1 -0
  182. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.js +9 -0
  183. package/dist/web/public/vendor/monaco/vs/nls.messages-loader.js +1 -0
  184. package/dist/web/public/vendor/monaco/vs/objective-c-CntZFaHX.js +1 -0
  185. package/dist/web/public/vendor/monaco/vs/pascal-r6kuqfl_.js +1 -0
  186. package/dist/web/public/vendor/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
  187. package/dist/web/public/vendor/monaco/vs/perl-DABw_TcH.js +1 -0
  188. package/dist/web/public/vendor/monaco/vs/pgsql-me_jFXeX.js +1 -0
  189. package/dist/web/public/vendor/monaco/vs/php-D_kh-9LK.js +1 -0
  190. package/dist/web/public/vendor/monaco/vs/pla-VfZjczW0.js +1 -0
  191. package/dist/web/public/vendor/monaco/vs/postiats-BBSzz8Pk.js +1 -0
  192. package/dist/web/public/vendor/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
  193. package/dist/web/public/vendor/monaco/vs/powershell-B-7ap1zc.js +1 -0
  194. package/dist/web/public/vendor/monaco/vs/protobuf-BmtuEB1A.js +2 -0
  195. package/dist/web/public/vendor/monaco/vs/pug-BRpRNeEb.js +1 -0
  196. package/dist/web/public/vendor/monaco/vs/python-CqWUUgfu.js +1 -0
  197. package/dist/web/public/vendor/monaco/vs/qsharp-BzsFaUU9.js +1 -0
  198. package/dist/web/public/vendor/monaco/vs/r-f8dDdrp4.js +1 -0
  199. package/dist/web/public/vendor/monaco/vs/razor-hok5y9Km.js +1 -0
  200. package/dist/web/public/vendor/monaco/vs/redis-fvZQY4PI.js +1 -0
  201. package/dist/web/public/vendor/monaco/vs/redshift-45Et0LQi.js +1 -0
  202. package/dist/web/public/vendor/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
  203. package/dist/web/public/vendor/monaco/vs/ruby-CZO8zYTz.js +1 -0
  204. package/dist/web/public/vendor/monaco/vs/rust-Bfetafyc.js +1 -0
  205. package/dist/web/public/vendor/monaco/vs/sb-3GYllVck.js +1 -0
  206. package/dist/web/public/vendor/monaco/vs/scala-foMgrKo1.js +1 -0
  207. package/dist/web/public/vendor/monaco/vs/scheme-CHdMtr7p.js +1 -0
  208. package/dist/web/public/vendor/monaco/vs/scss-C1cmLt9V.js +3 -0
  209. package/dist/web/public/vendor/monaco/vs/shell-ClXCKCEW.js +1 -0
  210. package/dist/web/public/vendor/monaco/vs/solidity-MZ6ExpPy.js +1 -0
  211. package/dist/web/public/vendor/monaco/vs/sophia-DWkuSsPQ.js +1 -0
  212. package/dist/web/public/vendor/monaco/vs/sparql-AUGFYSyk.js +1 -0
  213. package/dist/web/public/vendor/monaco/vs/sql-32GpJSV2.js +1 -0
  214. package/dist/web/public/vendor/monaco/vs/st-CuDFIVZ_.js +1 -0
  215. package/dist/web/public/vendor/monaco/vs/swift-t-PfMj7W.js +1 -0
  216. package/dist/web/public/vendor/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
  217. package/dist/web/public/vendor/monaco/vs/tcl-D74tq1nH.js +1 -0
  218. package/dist/web/public/vendor/monaco/vs/toggleHighContrast-qGX7E9o7.js +61 -0
  219. package/dist/web/public/vendor/monaco/vs/ts.worker-2QLmBukE.js +1 -0
  220. package/dist/web/public/vendor/monaco/vs/tsMode-B0S_kp2q.js +11 -0
  221. package/dist/web/public/vendor/monaco/vs/twig-C6taOxMV.js +1 -0
  222. package/dist/web/public/vendor/monaco/vs/typescript-_2t_511t.js +1 -0
  223. package/dist/web/public/vendor/monaco/vs/typespec-8OfoLt6R.js +1 -0
  224. package/dist/web/public/vendor/monaco/vs/vb-Dyb2648j.js +1 -0
  225. package/dist/web/public/vendor/monaco/vs/wgsl-BhLXMOR0.js +298 -0
  226. package/dist/web/public/vendor/monaco/vs/workers-BBttULjf.js +1 -0
  227. package/dist/web/public/vendor/monaco/vs/xml-cZjNDqDT.js +1 -0
  228. package/dist/web/public/vendor/monaco/vs/yaml-A1fOIdH6.js +1 -0
  229. package/dist/web/server.js +1019 -0
  230. package/dist/web/server.js.map +1 -1
  231. package/dist/web/task-queue.js +22 -2
  232. package/dist/web/task-queue.js.map +1 -1
  233. package/docs/DEPLOYMENT.md +382 -0
  234. package/docs/MODEL_FINETUNING.md +405 -0
  235. package/electron/main.js +202 -4
  236. package/package.json +6 -1
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -29,6 +62,19 @@ const version_1 = require("../cli/version");
29
62
  const i18n_1 = require("../shared/i18n");
30
63
  const enterprise_1 = require("../enterprise");
31
64
  const config_1 = require("../shared/config");
65
+ const model_router_1 = require("../models/model-router");
66
+ const openai_compatible_provider_1 = require("../models/providers/openai-compatible.provider");
67
+ const completion_engine_1 = require("../agent/completion-engine");
68
+ const symbol_index_1 = require("../agent/symbol-index");
69
+ const change_manager_1 = require("../agent/change-manager");
70
+ const design_to_code_1 = require("../agent/design-to-code");
71
+ const git_integration_1 = require("../agent/git-integration");
72
+ const team_collaboration_1 = require("../agent/team-collaboration");
73
+ const solo_agent_1 = require("../agent/solo-agent");
74
+ const multi_agent_1 = require("../agent/multi-agent");
75
+ const event_driven_agent_1 = require("../agent/event-driven-agent");
76
+ const custom_agent_1 = require("../agent/custom-agent");
77
+ const mcp_client_1 = require("../tools/mcp/mcp-client");
32
78
  const memory_1 = require("../memory");
33
79
  const auto_summarize_1 = require("../memory/auto-summarize");
34
80
  const secure_store_1 = require("../shared/secure-store");
@@ -58,6 +104,22 @@ function startWebServer(opts = {}) {
58
104
  const sessions = new auth_1.SessionStore();
59
105
  // 当前 Web 控制台工作区,任务提交缺省时使用
60
106
  let serverWorkspaceDir = (0, path_1.resolve)(process.cwd());
107
+ // P3: 多文件变更管理器(AI 生成的修改先暂存,用户审批后才写入磁盘)
108
+ const changeManager = new change_manager_1.ChangeManager({ cwd: serverWorkspaceDir });
109
+ // P2-2: Git 集成管理器
110
+ let gitIntegration = (0, git_integration_1.createGitIntegration)(serverWorkspaceDir);
111
+ // P2-3: 团队协作管理器
112
+ const teamManager = (0, team_collaboration_1.createTeamCollaborationManager)();
113
+ // 阶段二-2: 事件驱动 Agent 管理器
114
+ const eventDrivenManager = (0, event_driven_agent_1.createEventDrivenAgentManager)(serverWorkspaceDir, async (event) => {
115
+ console.log('[event-driven] processing:', { eventId: event.id, type: event.type });
116
+ // 实际处理逻辑:根据事件类型触发对应的 Agent 任务
117
+ // 这里简化处理,实际应集成到 orchestrator
118
+ });
119
+ // 阶段二-3: 自定义 Agent 管理器
120
+ const customAgentManager = (0, custom_agent_1.createCustomAgentManager)(serverWorkspaceDir);
121
+ // P3-2: SOLO 全自主编程任务存储
122
+ const soloTasks = new Map();
61
123
  // 任务队列(进程内;服务端静默执行)— 需在登录接口前初始化
62
124
  const persistDir = process.env.FH_TASK_PERSIST_DIR?.trim() ||
63
125
  (0, path_1.join)(process.env.FH_HOME?.trim() || (0, path_1.join)(require('os').homedir(), '.feihong-code'), 'tasks');
@@ -65,6 +127,13 @@ function startWebServer(opts = {}) {
65
127
  concurrency: Number(process.env.FH_TASK_CONCURRENCY ?? 2),
66
128
  webhookUrl: process.env.FH_TASK_WEBHOOK_URL,
67
129
  persistDir,
130
+ // P3-1: AI 生成的文件修改自动暂存到变更面板
131
+ stageChange: (path, content) => {
132
+ try {
133
+ changeManager.stageChange(path, content);
134
+ }
135
+ catch (e) { /* 暂存失败不影响任务执行 */ }
136
+ },
68
137
  });
69
138
  // 公开健康检查(仅暴露版本/状态等观测信息,无敏感数据)
70
139
  app.get('/api/health', (_req, res) => {
@@ -536,6 +605,908 @@ function startWebServer(opts = {}) {
536
605
  res.status(500).json({ ok: false, error: '读取失败: ' + e.message });
537
606
  }
538
607
  });
608
+ /* ========== P3: 多文件变更管理(暂存/审批/原子提交) ========== */
609
+ // 暂存变更(AI 生成的文件内容先暂存,不直接写入)
610
+ app.post('/api/changes/stage', (req, res) => {
611
+ const body = (req.body ?? {});
612
+ const path = typeof body?.path === 'string' ? body.path.trim() : '';
613
+ const content = typeof body?.content === 'string' ? body.content : '';
614
+ if (!path) {
615
+ res.status(400).json({ ok: false, error: '缺少 path 字段' });
616
+ return;
617
+ }
618
+ const change = changeManager.stageChange(path, content);
619
+ if (!change) {
620
+ res.status(400).json({ ok: false, error: '内容未变化或暂存区已满' });
621
+ return;
622
+ }
623
+ res.json({ ok: true, change: { path: change.path, type: change.type, additions: change.additions, deletions: change.deletions, status: change.status, hunks: change.hunks } });
624
+ });
625
+ // 获取所有暂存变更(变更面板数据)
626
+ app.get('/api/changes', (_req, res) => {
627
+ res.json({ ok: true, ...changeManager.toPanelData() });
628
+ });
629
+ // 接受整个文件的变更
630
+ app.post('/api/changes/accept', (req, res) => {
631
+ const body = (req.body ?? {});
632
+ const path = typeof body?.path === 'string' ? body.path.trim() : '';
633
+ if (!path) {
634
+ res.status(400).json({ ok: false, error: '缺少 path 字段' });
635
+ return;
636
+ }
637
+ const ok = changeManager.acceptFile(path);
638
+ res.json({ ok, ...(ok ? {} : { error: '文件不存在' }) });
639
+ });
640
+ // 拒绝整个文件的变更
641
+ app.post('/api/changes/reject', (req, res) => {
642
+ const body = (req.body ?? {});
643
+ const path = typeof body?.path === 'string' ? body.path.trim() : '';
644
+ if (!path) {
645
+ res.status(400).json({ ok: false, error: '缺少 path 字段' });
646
+ return;
647
+ }
648
+ const ok = changeManager.rejectFile(path);
649
+ res.json({ ok, ...(ok ? {} : { error: '文件不存在' }) });
650
+ });
651
+ // 接受单个 Hunk
652
+ app.post('/api/changes/hunk/accept', (req, res) => {
653
+ const body = (req.body ?? {});
654
+ const path = typeof body?.path === 'string' ? body.path.trim() : '';
655
+ const hunkIndex = typeof body?.hunkIndex === 'number' ? body.hunkIndex : -1;
656
+ if (!path || hunkIndex < 0) {
657
+ res.status(400).json({ ok: false, error: '缺少 path 或 hunkIndex' });
658
+ return;
659
+ }
660
+ const ok = changeManager.acceptHunk(path, hunkIndex);
661
+ res.json({ ok, ...(ok ? {} : { error: '文件或 Hunk 不存在' }) });
662
+ });
663
+ // 拒绝单个 Hunk
664
+ app.post('/api/changes/hunk/reject', (req, res) => {
665
+ const body = (req.body ?? {});
666
+ const path = typeof body?.path === 'string' ? body.path.trim() : '';
667
+ const hunkIndex = typeof body?.hunkIndex === 'number' ? body.hunkIndex : -1;
668
+ if (!path || hunkIndex < 0) {
669
+ res.status(400).json({ ok: false, error: '缺少 path 或 hunkIndex' });
670
+ return;
671
+ }
672
+ const ok = changeManager.rejectHunk(path, hunkIndex);
673
+ res.json({ ok, ...(ok ? {} : { error: '文件或 Hunk 不存在' }) });
674
+ });
675
+ // 原子化提交(写入所有已接受的变更,失败自动回滚)
676
+ app.post('/api/changes/commit', (_req, res) => {
677
+ const result = changeManager.commit();
678
+ res.json({ ok: result.success, ...result });
679
+ });
680
+ // 丢弃所有暂存变更
681
+ app.post('/api/changes/discard', (_req, res) => {
682
+ changeManager.discardAll();
683
+ res.json({ ok: true });
684
+ });
685
+ // 检测冲突
686
+ app.post('/api/changes/detect-conflicts', (_req, res) => {
687
+ const conflicts = changeManager.detectConflicts();
688
+ res.json({ ok: true, conflicts });
689
+ });
690
+ /* ========== P1-2: MCP 协议管理 API ========== */
691
+ // 获取当前 MCP 服务器配置
692
+ app.get('/api/mcp/config', (_req, res) => {
693
+ try {
694
+ const cfg = (0, config_1.loadConfig)();
695
+ const servers = (cfg.mcp?.servers ?? []).map((s) => ({
696
+ name: s.name,
697
+ command: s.command,
698
+ args: s.args ?? [],
699
+ env: s.env ? Object.keys(s.env) : [], // 只暴露环境变量名,不暴露值
700
+ }));
701
+ res.json({ ok: true, servers, count: servers.length });
702
+ }
703
+ catch (e) {
704
+ res.status(500).json({ ok: false, error: `读取配置失败: ${e instanceof Error ? e.message : String(e)}` });
705
+ }
706
+ });
707
+ // 测试指定 MCP 服务器连接(临时连接,列出工具后关闭)
708
+ app.post('/api/mcp/test', async (req, res) => {
709
+ const body = (req.body ?? {});
710
+ const name = typeof body?.name === 'string' ? body.name.trim() : '';
711
+ if (!name) {
712
+ res.status(400).json({ ok: false, error: '缺少 name 字段' });
713
+ return;
714
+ }
715
+ try {
716
+ const cfg = (0, config_1.loadConfig)();
717
+ const serverCfg = (cfg.mcp?.servers ?? []).find((s) => s.name === name);
718
+ if (!serverCfg) {
719
+ res.status(404).json({ ok: false, error: `未找到 MCP 服务器: ${name}` });
720
+ return;
721
+ }
722
+ const startTime = Date.now();
723
+ const client = await (0, mcp_client_1.connectMcp)(serverCfg);
724
+ const tools = await client.listTools();
725
+ const latencyMs = Date.now() - startTime;
726
+ await client.close().catch(() => undefined);
727
+ res.json({
728
+ ok: true,
729
+ name,
730
+ connected: true,
731
+ latencyMs,
732
+ toolCount: tools.length,
733
+ tools: tools.map((t) => ({
734
+ name: t.name,
735
+ description: (t.description || '').slice(0, 100),
736
+ })),
737
+ });
738
+ }
739
+ catch (e) {
740
+ res.json({
741
+ ok: false,
742
+ name,
743
+ connected: false,
744
+ error: `连接失败: ${e instanceof Error ? e.message : String(e)}`,
745
+ });
746
+ }
747
+ });
748
+ // 列出所有 MCP 服务器的工具(逐个连接测试,返回汇总)
749
+ app.get('/api/mcp/tools', async (_req, res) => {
750
+ try {
751
+ const cfg = (0, config_1.loadConfig)();
752
+ const servers = cfg.mcp?.servers ?? [];
753
+ const results = [];
754
+ for (const s of servers) {
755
+ try {
756
+ const client = await (0, mcp_client_1.connectMcp)(s);
757
+ const tools = await client.listTools();
758
+ await client.close().catch(() => undefined);
759
+ results.push({ name: s.name, ok: true, toolCount: tools.length });
760
+ }
761
+ catch (e) {
762
+ results.push({ name: s.name, ok: false, toolCount: 0, error: e instanceof Error ? e.message : String(e) });
763
+ }
764
+ }
765
+ res.json({ ok: true, servers: results, totalServers: servers.length });
766
+ }
767
+ catch (e) {
768
+ res.status(500).json({ ok: false, error: `获取 MCP 工具失败: ${e instanceof Error ? e.message : String(e)}` });
769
+ }
770
+ });
771
+ /* ========== P2: 代码补全 API(真实接入 CompletionEngine) ========== */
772
+ app.post('/api/completion', async (req, res) => {
773
+ const body = (req.body ?? {});
774
+ const filePath = typeof body?.filePath === 'string' ? body.filePath.trim() : '';
775
+ const fileContent = typeof body?.fileContent === 'string' ? body.fileContent : '';
776
+ const cursorOffset = typeof body?.cursorOffset === 'number' ? body.cursorOffset : fileContent.length;
777
+ const mode = body?.mode === 'full' ? 'full' : 'quick';
778
+ const language = typeof body?.language === 'string' ? body.language : undefined;
779
+ if (!filePath || !fileContent) {
780
+ res.status(400).json({ ok: false, error: '缺少 filePath 或 fileContent' });
781
+ return;
782
+ }
783
+ if (!completionEngine) {
784
+ res.json({ ok: true, suggestions: [], latencyMs: 0, model: '', cached: false, note: '未配置模型,补全不可用' });
785
+ return;
786
+ }
787
+ try {
788
+ const result = await completionEngine.complete({
789
+ filePath,
790
+ fileContent,
791
+ cursorOffset,
792
+ mode,
793
+ language,
794
+ });
795
+ res.json({ ok: true, ...result });
796
+ }
797
+ catch (e) {
798
+ res.status(500).json({ ok: false, error: '补全失败: ' + e.message, suggestions: [] });
799
+ }
800
+ });
801
+ /* ========== 阶段一-2:补全 Pro API ========== */
802
+ // 记录用户接受的补全(用于连续推荐)
803
+ app.post('/api/completion/accept', (req, res) => {
804
+ const body = (req.body ?? {});
805
+ const filePath = typeof body?.filePath === 'string' ? body.filePath.trim() : '';
806
+ const cursorOffset = typeof body?.cursorOffset === 'number' ? body.cursorOffset : 0;
807
+ const text = typeof body?.text === 'string' ? body.text : '';
808
+ if (!filePath || !text) {
809
+ res.status(400).json({ ok: false, error: '缺少 filePath 或 text' });
810
+ return;
811
+ }
812
+ if (!completionEngine) {
813
+ res.json({ ok: false, error: '补全引擎未初始化' });
814
+ return;
815
+ }
816
+ try {
817
+ completionEngine.recordAcceptance(filePath, cursorOffset, text);
818
+ res.json({ ok: true });
819
+ }
820
+ catch (e) {
821
+ res.status(500).json({ ok: false, error: e.message });
822
+ }
823
+ });
824
+ // 推荐下一个改动点(补全 Pro 连续推荐)
825
+ app.post('/api/completion/suggest-next', (req, res) => {
826
+ const body = (req.body ?? {});
827
+ const filePath = typeof body?.filePath === 'string' ? body.filePath.trim() : '';
828
+ const fileContent = typeof body?.fileContent === 'string' ? body.fileContent : '';
829
+ const cursorOffset = typeof body?.cursorOffset === 'number' ? body.cursorOffset : fileContent.length;
830
+ if (!filePath || !fileContent) {
831
+ res.status(400).json({ ok: false, error: '缺少 filePath 或 fileContent' });
832
+ return;
833
+ }
834
+ if (!completionEngine) {
835
+ res.json({ ok: true, suggested: false });
836
+ return;
837
+ }
838
+ try {
839
+ const suggestion = completionEngine.suggestNext(filePath, fileContent, cursorOffset);
840
+ res.json({ ok: true, ...suggestion });
841
+ }
842
+ catch (e) {
843
+ res.status(500).json({ ok: false, error: e.message });
844
+ }
845
+ });
846
+ /* ========== P2-1: 设计稿转代码 API(多模态,图片→代码) ========== */
847
+ app.post('/api/design-to-code', async (req, res) => {
848
+ const body = (req.body ?? {});
849
+ const image = typeof body?.image === 'string' ? body.image.trim() : '';
850
+ const framework = body?.framework || 'html';
851
+ const instructions = typeof body?.instructions === 'string' ? body.instructions : undefined;
852
+ const previousCode = typeof body?.previousCode === 'string' ? body.previousCode : undefined;
853
+ const feedback = typeof body?.feedback === 'string' ? body.feedback : undefined;
854
+ if (!image) {
855
+ res.status(400).json({ ok: false, error: '缺少 image 字段(base64 或 URL)' });
856
+ return;
857
+ }
858
+ if (!designToCodeEngine) {
859
+ res.status(503).json({ ok: false, error: '未配置多模态模型。请在模型设置中添加支持 vision 能力的模型(如 GPT-4V、Claude 3、通义千问 VL 等)。' });
860
+ return;
861
+ }
862
+ try {
863
+ const result = await designToCodeEngine.generate({
864
+ image,
865
+ framework,
866
+ instructions,
867
+ previousCode,
868
+ feedback,
869
+ });
870
+ res.json({ ok: true, ...result });
871
+ }
872
+ catch (e) {
873
+ res.status(500).json({ ok: false, error: e.message });
874
+ }
875
+ });
876
+ /* ========== P2-2: Git 集成 API ========== */
877
+ // 获取 Git 状态
878
+ app.get('/api/git/status', async (_req, res) => {
879
+ try {
880
+ const status = await gitIntegration.status();
881
+ res.json({ ok: true, ...status });
882
+ }
883
+ catch (e) {
884
+ res.status(500).json({ ok: false, error: e.message });
885
+ }
886
+ });
887
+ // 获取文件 diff
888
+ app.post('/api/git/diff', async (req, res) => {
889
+ const body = (req.body ?? {});
890
+ const path = typeof body?.path === 'string' ? body.path : undefined;
891
+ const staged = body?.staged === true;
892
+ try {
893
+ const diffs = await gitIntegration.diff(path, staged);
894
+ res.json({ ok: true, diffs });
895
+ }
896
+ catch (e) {
897
+ res.status(500).json({ ok: false, error: e.message });
898
+ }
899
+ });
900
+ // 暂存文件
901
+ app.post('/api/git/add', async (req, res) => {
902
+ const body = (req.body ?? {});
903
+ const paths = Array.isArray(body?.paths) ? body.paths.filter((p) => typeof p === 'string') : [];
904
+ if (!paths.length) {
905
+ res.status(400).json({ ok: false, error: '缺少 paths 字段' });
906
+ return;
907
+ }
908
+ try {
909
+ const result = await gitIntegration.add(paths);
910
+ res.json({ ok: result.success, message: result.message });
911
+ }
912
+ catch (e) {
913
+ res.status(500).json({ ok: false, error: e.message });
914
+ }
915
+ });
916
+ // 取消暂存
917
+ app.post('/api/git/reset', async (req, res) => {
918
+ const body = (req.body ?? {});
919
+ const paths = Array.isArray(body?.paths) ? body.paths.filter((p) => typeof p === 'string') : [];
920
+ if (!paths.length) {
921
+ res.status(400).json({ ok: false, error: '缺少 paths 字段' });
922
+ return;
923
+ }
924
+ try {
925
+ const result = await gitIntegration.reset(paths);
926
+ res.json({ ok: result.success, message: result.message });
927
+ }
928
+ catch (e) {
929
+ res.status(500).json({ ok: false, error: e.message });
930
+ }
931
+ });
932
+ // 提交
933
+ app.post('/api/git/commit', async (req, res) => {
934
+ const body = (req.body ?? {});
935
+ const message = typeof body?.message === 'string' ? body.message.trim() : '';
936
+ const paths = Array.isArray(body?.paths) ? body.paths.filter((p) => typeof p === 'string') : undefined;
937
+ if (!message) {
938
+ res.status(400).json({ ok: false, error: '提交信息不能为空' });
939
+ return;
940
+ }
941
+ try {
942
+ const result = await gitIntegration.commit(message, paths);
943
+ res.json({ ok: result.success, hash: result.hash, message: result.message });
944
+ }
945
+ catch (e) {
946
+ res.status(500).json({ ok: false, error: e.message });
947
+ }
948
+ });
949
+ // 获取分支列表
950
+ app.get('/api/git/branches', async (_req, res) => {
951
+ try {
952
+ const branches = await gitIntegration.branches();
953
+ res.json({ ok: true, branches });
954
+ }
955
+ catch (e) {
956
+ res.status(500).json({ ok: false, error: e.message });
957
+ }
958
+ });
959
+ // 切换分支
960
+ app.post('/api/git/checkout', async (req, res) => {
961
+ const body = (req.body ?? {});
962
+ const branch = typeof body?.branch === 'string' ? body.branch.trim() : '';
963
+ const createNew = body?.createNew === true;
964
+ if (!branch) {
965
+ res.status(400).json({ ok: false, error: '缺少 branch 字段' });
966
+ return;
967
+ }
968
+ try {
969
+ const result = await gitIntegration.checkout(branch, createNew);
970
+ res.json({ ok: result.success, message: result.message });
971
+ }
972
+ catch (e) {
973
+ res.status(500).json({ ok: false, error: e.message });
974
+ }
975
+ });
976
+ // 获取提交历史
977
+ app.get('/api/git/log', async (req, res) => {
978
+ const count = typeof req.query?.count === 'string' ? parseInt(req.query.count) : 20;
979
+ try {
980
+ const commits = await gitIntegration.log(Math.min(Math.max(count, 1), 100));
981
+ res.json({ ok: true, commits });
982
+ }
983
+ catch (e) {
984
+ res.status(500).json({ ok: false, error: e.message });
985
+ }
986
+ });
987
+ // 推送
988
+ app.post('/api/git/push', async (req, res) => {
989
+ const body = (req.body ?? {});
990
+ const remote = typeof body?.remote === 'string' ? body.remote : 'origin';
991
+ const branch = typeof body?.branch === 'string' ? body.branch : undefined;
992
+ const force = body?.force === true;
993
+ try {
994
+ const result = await gitIntegration.push(remote, branch, force);
995
+ res.json({ ok: result.success, message: result.message });
996
+ }
997
+ catch (e) {
998
+ res.status(500).json({ ok: false, error: e.message });
999
+ }
1000
+ });
1001
+ // 拉取
1002
+ app.post('/api/git/pull', async (req, res) => {
1003
+ const body = (req.body ?? {});
1004
+ const remote = typeof body?.remote === 'string' ? body.remote : 'origin';
1005
+ const branch = typeof body?.branch === 'string' ? body.branch : undefined;
1006
+ try {
1007
+ const result = await gitIntegration.pull(remote, branch);
1008
+ res.json({ ok: result.success, message: result.message });
1009
+ }
1010
+ catch (e) {
1011
+ res.status(500).json({ ok: false, error: e.message });
1012
+ }
1013
+ });
1014
+ // 初始化仓库
1015
+ app.post('/api/git/init', async (_req, res) => {
1016
+ try {
1017
+ const result = await gitIntegration.init();
1018
+ res.json({ ok: result.success, message: result.message });
1019
+ }
1020
+ catch (e) {
1021
+ res.status(500).json({ ok: false, error: e.message });
1022
+ }
1023
+ });
1024
+ /* ========== P2-3: 团队协作 API ========== */
1025
+ app.get('/api/team', (_req, res) => {
1026
+ try {
1027
+ const team = teamManager.getTeam();
1028
+ const stats = teamManager.getStats();
1029
+ res.json({ ok: true, team, stats });
1030
+ }
1031
+ catch (e) {
1032
+ res.status(500).json({ ok: false, error: e.message });
1033
+ }
1034
+ });
1035
+ app.put('/api/team/config', (req, res) => {
1036
+ try {
1037
+ const config = teamManager.updateConfig(req.body || {});
1038
+ res.json({ ok: true, config });
1039
+ }
1040
+ catch (e) {
1041
+ res.status(500).json({ ok: false, error: e.message });
1042
+ }
1043
+ });
1044
+ app.get('/api/team/members', (_req, res) => {
1045
+ try {
1046
+ res.json({ ok: true, members: teamManager.getMembers() });
1047
+ }
1048
+ catch (e) {
1049
+ res.status(500).json({ ok: false, error: e.message });
1050
+ }
1051
+ });
1052
+ app.post('/api/team/members/invite', (req, res) => {
1053
+ const body = (req.body ?? {});
1054
+ const name = typeof body?.name === 'string' ? body.name.trim() : '';
1055
+ const email = typeof body?.email === 'string' ? body.email.trim() : '';
1056
+ const role = body?.role || 'developer';
1057
+ if (!name || !email) {
1058
+ res.status(400).json({ ok: false, error: '缺少 name 或 email' });
1059
+ return;
1060
+ }
1061
+ try {
1062
+ const member = teamManager.inviteMember(name, email, role);
1063
+ res.json({ ok: true, member });
1064
+ }
1065
+ catch (e) {
1066
+ res.status(400).json({ ok: false, error: e.message });
1067
+ }
1068
+ });
1069
+ app.put('/api/team/members/:id/role', (req, res) => {
1070
+ try {
1071
+ const role = (req.body ?? {}).role;
1072
+ const member = teamManager.updateMemberRole(req.params.id, role);
1073
+ res.json({ ok: true, member });
1074
+ }
1075
+ catch (e) {
1076
+ res.status(400).json({ ok: false, error: e.message });
1077
+ }
1078
+ });
1079
+ app.delete('/api/team/members/:id', (req, res) => {
1080
+ try {
1081
+ teamManager.removeMember(req.params.id);
1082
+ res.json({ ok: true });
1083
+ }
1084
+ catch (e) {
1085
+ res.status(400).json({ ok: false, error: e.message });
1086
+ }
1087
+ });
1088
+ app.get('/api/team/tasks', (req, res) => {
1089
+ try {
1090
+ const status = typeof req.query?.status === 'string' ? req.query.status : undefined;
1091
+ res.json({ ok: true, tasks: teamManager.getTasks(status) });
1092
+ }
1093
+ catch (e) {
1094
+ res.status(500).json({ ok: false, error: e.message });
1095
+ }
1096
+ });
1097
+ app.post('/api/team/tasks', (req, res) => {
1098
+ const body = (req.body ?? {});
1099
+ const title = typeof body?.title === 'string' ? body.title.trim() : '';
1100
+ if (!title) {
1101
+ res.status(400).json({ ok: false, error: '缺少 title' });
1102
+ return;
1103
+ }
1104
+ try {
1105
+ const task = teamManager.createTask(title, body.createdBy || 'system', body);
1106
+ res.json({ ok: true, task });
1107
+ }
1108
+ catch (e) {
1109
+ res.status(500).json({ ok: false, error: e.message });
1110
+ }
1111
+ });
1112
+ app.put('/api/team/tasks/:id', (req, res) => {
1113
+ try {
1114
+ res.json({ ok: true, task: teamManager.updateTask(req.params.id, req.body || {}) });
1115
+ }
1116
+ catch (e) {
1117
+ res.status(400).json({ ok: false, error: e.message });
1118
+ }
1119
+ });
1120
+ app.delete('/api/team/tasks/:id', (req, res) => {
1121
+ try {
1122
+ teamManager.deleteTask(req.params.id);
1123
+ res.json({ ok: true });
1124
+ }
1125
+ catch (e) {
1126
+ res.status(400).json({ ok: false, error: e.message });
1127
+ }
1128
+ });
1129
+ app.post('/api/team/tasks/:id/comments', (req, res) => {
1130
+ const body = (req.body ?? {});
1131
+ const content = typeof body?.content === 'string' ? body.content.trim() : '';
1132
+ if (!content) {
1133
+ res.status(400).json({ ok: false, error: '缺少 content' });
1134
+ return;
1135
+ }
1136
+ try {
1137
+ const task = teamManager.addComment(req.params.id, body.author || 'anonymous', content);
1138
+ res.json({ ok: true, task });
1139
+ }
1140
+ catch (e) {
1141
+ res.status(400).json({ ok: false, error: e.message });
1142
+ }
1143
+ });
1144
+ app.get('/api/team/stats', (_req, res) => {
1145
+ try {
1146
+ res.json({ ok: true, stats: teamManager.getStats() });
1147
+ }
1148
+ catch (e) {
1149
+ res.status(500).json({ ok: false, error: e.message });
1150
+ }
1151
+ });
1152
+ /* ========== P3-2: SOLO 全自主编程 API ========== */
1153
+ // 启动 SOLO 任务
1154
+ app.post('/api/solo/run', async (req, res) => {
1155
+ const body = (req.body ?? {});
1156
+ const goal = typeof body?.goal === 'string' ? body.goal.trim() : '';
1157
+ if (!goal) {
1158
+ res.status(400).json({ ok: false, error: '缺少 goal' });
1159
+ return;
1160
+ }
1161
+ const taskId = `solo-${Date.now()}`;
1162
+ const config = {
1163
+ cwd: serverWorkspaceDir,
1164
+ goal,
1165
+ maxTasks: body.maxTasks || 8,
1166
+ maxRetries: body.maxRetries || 3,
1167
+ parallel: body.parallel || false,
1168
+ maxParallel: body.maxParallel || 2,
1169
+ planOnly: body.planOnly || false,
1170
+ verifyOnly: body.verifyOnly || false,
1171
+ autoCorrect: body.autoCorrect !== false,
1172
+ };
1173
+ // 创建子任务执行器(简化版,实际应委托给 orchestrator)
1174
+ const executor = async (focusedGoal) => {
1175
+ try {
1176
+ // 简化执行:返回成功,实际应调用 orchestrator
1177
+ return { ok: true, output: `已执行: ${focusedGoal}`, touchedFiles: [], iterations: 1 };
1178
+ }
1179
+ catch (e) {
1180
+ return { ok: false, output: e.message, touchedFiles: [], iterations: 0 };
1181
+ }
1182
+ };
1183
+ const agent = new solo_agent_1.SoloAgent(config, executor);
1184
+ soloTasks.set(taskId, { agent, status: 'running' });
1185
+ // 异步执行
1186
+ (async () => {
1187
+ try {
1188
+ const report = await agent.run();
1189
+ const task = soloTasks.get(taskId);
1190
+ if (task) {
1191
+ task.report = report;
1192
+ task.status = report.overall === 'failed' ? 'failed' : 'completed';
1193
+ }
1194
+ }
1195
+ catch (e) {
1196
+ const task = soloTasks.get(taskId);
1197
+ if (task) {
1198
+ task.status = 'failed';
1199
+ task.report = {
1200
+ goal, cwd: serverWorkspaceDir, overall: 'failed', phase: 'failed',
1201
+ startedAt: new Date().toISOString(), completedAt: new Date().toISOString(),
1202
+ totalTasks: 0, completedTasks: 0, failedTasks: 0, skippedTasks: 0,
1203
+ tasks: [], summary: `执行失败: ${e.message}`, events: [],
1204
+ };
1205
+ }
1206
+ }
1207
+ })();
1208
+ res.json({ ok: true, taskId, message: 'SOLO 任务已启动' });
1209
+ });
1210
+ // 获取 SOLO 任务状态
1211
+ app.get('/api/solo/status/:id', (req, res) => {
1212
+ const task = soloTasks.get(req.params.id);
1213
+ if (!task) {
1214
+ res.status(404).json({ ok: false, error: '任务不存在' });
1215
+ return;
1216
+ }
1217
+ const status = task.agent.getStatus();
1218
+ res.json({ ok: true, taskId: req.params.id, status: task.status, ...status });
1219
+ });
1220
+ // 获取 SOLO 任务报告
1221
+ app.get('/api/solo/report/:id', (req, res) => {
1222
+ const task = soloTasks.get(req.params.id);
1223
+ if (!task) {
1224
+ res.status(404).json({ ok: false, error: '任务不存在' });
1225
+ return;
1226
+ }
1227
+ if (!task.report) {
1228
+ res.status(202).json({ ok: false, error: '任务尚未完成', status: task.status });
1229
+ return;
1230
+ }
1231
+ res.json({ ok: true, report: task.report });
1232
+ });
1233
+ // 取消 SOLO 任务
1234
+ app.post('/api/solo/cancel/:id', (req, res) => {
1235
+ const task = soloTasks.get(req.params.id);
1236
+ if (!task) {
1237
+ res.status(404).json({ ok: false, error: '任务不存在' });
1238
+ return;
1239
+ }
1240
+ if (task.status === 'running') {
1241
+ task.status = 'failed';
1242
+ res.json({ ok: true, message: '任务已取消' });
1243
+ }
1244
+ else {
1245
+ res.json({ ok: false, error: '任务已结束,无法取消' });
1246
+ }
1247
+ });
1248
+ // 列出所有 SOLO 任务
1249
+ app.get('/api/solo/list', (_req, res) => {
1250
+ const tasks = Array.from(soloTasks.entries()).map(([id, task]) => ({
1251
+ id,
1252
+ status: task.status,
1253
+ goal: task.report?.goal || '',
1254
+ startedAt: task.report?.startedAt,
1255
+ completedAt: task.report?.completedAt,
1256
+ }));
1257
+ res.json({ ok: true, tasks });
1258
+ });
1259
+ /* ========== 阶段二-1:多智能体协同 API ========== */
1260
+ // 运行多智能体协同(架构师/开发/测试/评审)
1261
+ app.post('/api/multi-agent/run', async (req, res) => {
1262
+ const body = (req.body ?? {});
1263
+ const goal = typeof body?.goal === 'string' ? body.goal.trim() : '';
1264
+ if (!goal) {
1265
+ res.status(400).json({ ok: false, error: '缺少 goal' });
1266
+ return;
1267
+ }
1268
+ if (!sharedModelRouter) {
1269
+ res.status(500).json({ ok: false, error: '模型未配置' });
1270
+ return;
1271
+ }
1272
+ const config = {
1273
+ roles: body.roles || ['architect', 'developer', 'tester', 'reviewer'],
1274
+ maxRounds: body.maxRounds || 3,
1275
+ enableReviewLoop: body.enableReviewLoop !== false,
1276
+ };
1277
+ try {
1278
+ const result = await (0, multi_agent_1.runMultiAgent)(sharedModelRouter, goal, config, body.context);
1279
+ res.json({ ok: true, ...result });
1280
+ }
1281
+ catch (e) {
1282
+ res.status(500).json({ ok: false, error: '多智能体协同失败: ' + e.message });
1283
+ }
1284
+ });
1285
+ // 获取角色配置
1286
+ app.get('/api/multi-agent/roles', (_req, res) => {
1287
+ try {
1288
+ Promise.resolve().then(() => __importStar(require('../agent/multi-agent'))).then(({ AGENT_ROLES }) => {
1289
+ const roles = Object.values(AGENT_ROLES).map((r) => ({
1290
+ role: r.role,
1291
+ name: r.name,
1292
+ description: r.description,
1293
+ capabilities: r.capabilities,
1294
+ }));
1295
+ res.json({ ok: true, roles });
1296
+ });
1297
+ }
1298
+ catch (e) {
1299
+ res.status(500).json({ ok: false, error: e.message });
1300
+ }
1301
+ });
1302
+ /* ========== 阶段二-2:事件驱动 Agent API ========== */
1303
+ // 获取事件驱动配置
1304
+ app.get('/api/event-driven/config', (_req, res) => {
1305
+ try {
1306
+ res.json({ ok: true, config: eventDrivenManager.getConfig() });
1307
+ }
1308
+ catch (e) {
1309
+ res.status(500).json({ ok: false, error: e.message });
1310
+ }
1311
+ });
1312
+ // 获取事件历史
1313
+ app.get('/api/event-driven/events', (req, res) => {
1314
+ try {
1315
+ const limit = typeof req.query?.limit === 'string' ? parseInt(req.query.limit, 10) : 50;
1316
+ res.json({ ok: true, events: eventDrivenManager.getEvents(limit) });
1317
+ }
1318
+ catch (e) {
1319
+ res.status(500).json({ ok: false, error: e.message });
1320
+ }
1321
+ });
1322
+ // 手动触发事件
1323
+ app.post('/api/event-driven/trigger', (req, res) => {
1324
+ const body = (req.body ?? {});
1325
+ if (!body.type || !body.title) {
1326
+ res.status(400).json({ ok: false, error: '缺少 type 或 title' });
1327
+ return;
1328
+ }
1329
+ eventDrivenManager.triggerEvent({
1330
+ type: body.type,
1331
+ severity: body.severity || 'info',
1332
+ title: body.title,
1333
+ description: body.description || '',
1334
+ source: body.source || 'manual',
1335
+ payload: body.payload,
1336
+ }).then((event) => res.json({ ok: true, event }))
1337
+ .catch((e) => res.status(500).json({ ok: false, error: e.message }));
1338
+ });
1339
+ // Cron 任务 CRUD
1340
+ app.post('/api/event-driven/cron', (req, res) => {
1341
+ const body = (req.body ?? {});
1342
+ if (!body.name || !body.cron || !body.task) {
1343
+ res.status(400).json({ ok: false, error: '缺少 name/cron/task' });
1344
+ return;
1345
+ }
1346
+ try {
1347
+ const task = eventDrivenManager.addCronTask({
1348
+ name: body.name,
1349
+ cron: body.cron,
1350
+ task: body.task,
1351
+ enabled: body.enabled !== false,
1352
+ debounceMs: body.debounceMs || 0,
1353
+ });
1354
+ res.json({ ok: true, task });
1355
+ }
1356
+ catch (e) {
1357
+ res.status(500).json({ ok: false, error: e.message });
1358
+ }
1359
+ });
1360
+ app.put('/api/event-driven/cron/:id', (req, res) => {
1361
+ try {
1362
+ const task = eventDrivenManager.updateCronTask(req.params.id, (req.body ?? {}));
1363
+ if (!task) {
1364
+ res.status(404).json({ ok: false, error: '任务不存在' });
1365
+ return;
1366
+ }
1367
+ res.json({ ok: true, task });
1368
+ }
1369
+ catch (e) {
1370
+ res.status(500).json({ ok: false, error: e.message });
1371
+ }
1372
+ });
1373
+ app.delete('/api/event-driven/cron/:id', (req, res) => {
1374
+ try {
1375
+ const ok = eventDrivenManager.removeCronTask(req.params.id);
1376
+ res.json({ ok, message: ok ? '已删除' : '任务不存在' });
1377
+ }
1378
+ catch (e) {
1379
+ res.status(500).json({ ok: false, error: e.message });
1380
+ }
1381
+ });
1382
+ // Webhook 接收
1383
+ app.post('/api/event-driven/webhook/:path', (req, res) => {
1384
+ const path = `/webhook/${req.params.path}`;
1385
+ eventDrivenManager.handleWebhook(path, (req.body || {}), req.headers)
1386
+ .then((result) => res.json(result))
1387
+ .catch((e) => res.status(500).json({ ok: false, error: e.message }));
1388
+ });
1389
+ /* ========== 阶段二-3:自定义 Agent API ========== */
1390
+ // 获取所有自定义 Agent
1391
+ app.get('/api/custom-agents', (req, res) => {
1392
+ try {
1393
+ const category = typeof req.query?.category === 'string' ? req.query.category : undefined;
1394
+ res.json({ ok: true, agents: customAgentManager.getAllAgents(category) });
1395
+ }
1396
+ catch (e) {
1397
+ res.status(500).json({ ok: false, error: e.message });
1398
+ }
1399
+ });
1400
+ // 获取 Agent 分类
1401
+ app.get('/api/custom-agents/categories', (_req, res) => {
1402
+ try {
1403
+ res.json({ ok: true, categories: customAgentManager.getCategories() });
1404
+ }
1405
+ catch (e) {
1406
+ res.status(500).json({ ok: false, error: e.message });
1407
+ }
1408
+ });
1409
+ // 匹配推荐 Agent
1410
+ app.post('/api/custom-agents/match', (req, res) => {
1411
+ const body = (req.body ?? {});
1412
+ const input = typeof body?.input === 'string' ? body.input : '';
1413
+ if (!input) {
1414
+ res.status(400).json({ ok: false, error: '缺少 input' });
1415
+ return;
1416
+ }
1417
+ try {
1418
+ const limit = typeof body?.limit === 'number' ? body.limit : 3;
1419
+ res.json({ ok: true, agents: customAgentManager.matchAgents(input, limit) });
1420
+ }
1421
+ catch (e) {
1422
+ res.status(500).json({ ok: false, error: e.message });
1423
+ }
1424
+ });
1425
+ // 获取单个 Agent
1426
+ app.get('/api/custom-agents/:id', (req, res) => {
1427
+ try {
1428
+ const agent = customAgentManager.getAgent(req.params.id);
1429
+ if (!agent) {
1430
+ res.status(404).json({ ok: false, error: 'Agent 不存在' });
1431
+ return;
1432
+ }
1433
+ res.json({ ok: true, agent });
1434
+ }
1435
+ catch (e) {
1436
+ res.status(500).json({ ok: false, error: e.message });
1437
+ }
1438
+ });
1439
+ // 创建自定义 Agent
1440
+ app.post('/api/custom-agents', (req, res) => {
1441
+ const body = (req.body ?? {});
1442
+ if (!body.name || !body.systemPrompt) {
1443
+ res.status(400).json({ ok: false, error: '缺少 name 或 systemPrompt' });
1444
+ return;
1445
+ }
1446
+ try {
1447
+ const agent = customAgentManager.createAgent({
1448
+ name: body.name,
1449
+ description: body.description || '',
1450
+ systemPrompt: body.systemPrompt,
1451
+ tools: body.tools || [],
1452
+ modelConfig: body.modelConfig || { temperature: 0.3, maxTokens: 2000, timeoutMs: 30000 },
1453
+ triggers: body.triggers || [],
1454
+ icon: body.icon || '🤖',
1455
+ category: body.category || 'custom',
1456
+ enabled: body.enabled !== false,
1457
+ author: body.author,
1458
+ version: body.version || '1.0.0',
1459
+ });
1460
+ res.json({ ok: true, agent });
1461
+ }
1462
+ catch (e) {
1463
+ res.status(500).json({ ok: false, error: e.message });
1464
+ }
1465
+ });
1466
+ // 更新自定义 Agent
1467
+ app.put('/api/custom-agents/:id', (req, res) => {
1468
+ try {
1469
+ const agent = customAgentManager.updateAgent(req.params.id, (req.body ?? {}));
1470
+ if (!agent) {
1471
+ res.status(404).json({ ok: false, error: 'Agent 不存在' });
1472
+ return;
1473
+ }
1474
+ res.json({ ok: true, agent });
1475
+ }
1476
+ catch (e) {
1477
+ res.status(500).json({ ok: false, error: e.message });
1478
+ }
1479
+ });
1480
+ // 删除自定义 Agent
1481
+ app.delete('/api/custom-agents/:id', (req, res) => {
1482
+ try {
1483
+ const ok = customAgentManager.deleteAgent(req.params.id);
1484
+ res.json({ ok, message: ok ? '已删除' : 'Agent 不存在或为内置 Agent' });
1485
+ }
1486
+ catch (e) {
1487
+ res.status(500).json({ ok: false, error: e.message });
1488
+ }
1489
+ });
1490
+ // 执行自定义 Agent
1491
+ app.post('/api/custom-agents/:id/execute', async (req, res) => {
1492
+ const body = (req.body ?? {});
1493
+ const input = typeof body?.input === 'string' ? body.input : '';
1494
+ if (!input) {
1495
+ res.status(400).json({ ok: false, error: '缺少 input' });
1496
+ return;
1497
+ }
1498
+ if (!sharedModelRouter) {
1499
+ res.status(500).json({ ok: false, error: '模型未配置' });
1500
+ return;
1501
+ }
1502
+ try {
1503
+ const result = await customAgentManager.executeAgent(req.params.id, input, sharedModelRouter, body?.context);
1504
+ res.json({ ok: result.success, ...result });
1505
+ }
1506
+ catch (e) {
1507
+ res.status(500).json({ ok: false, error: e.message });
1508
+ }
1509
+ });
539
1510
  /* ========== 打开本地文件夹/浏览器 ========== */
540
1511
  app.post('/api/open/folder', (req, res) => {
541
1512
  const body = (req.body ?? {});
@@ -1700,6 +2671,8 @@ function startWebServer(opts = {}) {
1700
2671
  apiKey: resolveApiKey(m),
1701
2672
  model: m.name,
1702
2673
  })));
2674
+ // P2: 同步更新补全引擎
2675
+ rebuildCompletionEngine(encList);
1703
2676
  return ok;
1704
2677
  }
1705
2678
  // 初始化模型提供列表,并注册到任务队列
@@ -1711,6 +2684,52 @@ function startWebServer(opts = {}) {
1711
2684
  apiKey: resolveApiKey(m),
1712
2685
  model: m.name,
1713
2686
  })));
2687
+ /* ========== P2: 共享 ModelRouter + CompletionEngine(供 /api/completion 使用) ========== */
2688
+ let sharedModelRouter = null;
2689
+ let completionEngine = null;
2690
+ // P2-1: 设计稿转代码引擎(多模态)
2691
+ let designToCodeEngine = null;
2692
+ function rebuildCompletionEngine(models) {
2693
+ try {
2694
+ const providers = models
2695
+ .filter((m) => m.apiBase && m.name)
2696
+ .map((m) => new openai_compatible_provider_1.OpenAICompatibleProvider({
2697
+ id: m.id,
2698
+ type: 'openai-compatible',
2699
+ baseURL: m.apiBase,
2700
+ apiKey: resolveApiKey(m),
2701
+ model: m.name,
2702
+ tags: ['code-gen', 'cheap'],
2703
+ }));
2704
+ if (!providers.length) {
2705
+ sharedModelRouter = null;
2706
+ completionEngine = null;
2707
+ designToCodeEngine = null;
2708
+ return;
2709
+ }
2710
+ sharedModelRouter = new model_router_1.ModelRouter(providers, 'capability', 1.0);
2711
+ // 阶段一-1:构建代码图谱,用于跨文件上下文注入
2712
+ const codeGraph = (0, symbol_index_1.buildCodeGraph)(serverWorkspaceDir, { maxFiles: 500 });
2713
+ completionEngine = (0, completion_engine_1.createCompletionEngine)(sharedModelRouter, {
2714
+ maxPrefixChars: 1500,
2715
+ maxSuffixChars: 500,
2716
+ quickMaxTokens: 64,
2717
+ fullMaxTokens: 256,
2718
+ cacheTtlMs: 10000,
2719
+ enableSyntaxCheck: true,
2720
+ }, codeGraph);
2721
+ // P2-1: 更新设计稿转代码引擎的模型提供者
2722
+ designToCodeEngine = (0, design_to_code_1.createDesignToCodeEngine)(providers);
2723
+ }
2724
+ catch (e) {
2725
+ console.error('[completion] rebuild failed:', e);
2726
+ sharedModelRouter = null;
2727
+ completionEngine = null;
2728
+ designToCodeEngine = null;
2729
+ }
2730
+ }
2731
+ // 初始化时构建
2732
+ rebuildCompletionEngine(initialModels);
1714
2733
  // 第二重(通信层):向客户端下发 RSA 公钥,用于加密敏感参数(如模型 API Key)传输
1715
2734
  app.get('/api/security/public-key', (_req, res) => {
1716
2735
  res.json({ ok: true, publicKey: rsaKeys.publicKey, algorithm: 'RSA-OAEP-2048-SHA256' });