feihong-code 7.5.0 → 7.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 (347) hide show
  1. package/.github/workflows/ci.yml +193 -180
  2. package/.github/workflows/release.yml +203 -200
  3. package/.github/workflows/swebench-real.yml +84 -0
  4. package/CHANGELOG.md +117 -94
  5. package/CONTRIBUTING.md +9 -2
  6. package/README.md +636 -609
  7. package/README.self-evolve.md +279 -274
  8. package/dist/agent/change-manager.js +1 -1
  9. package/dist/agent/code-rag.js +1 -1
  10. package/dist/agent/code-review.js +1 -1
  11. package/dist/agent/code-writer.js +1 -1
  12. package/dist/agent/completion-postprocess.js +1 -1
  13. package/dist/agent/context-compactor.js +11 -0
  14. package/dist/agent/context-compactor.js.map +1 -1
  15. package/dist/agent/custom-agent.js +52 -52
  16. package/dist/agent/design-to-code.js +40 -40
  17. package/dist/agent/experience.js +1 -1
  18. package/dist/agent/layered-memory.js +1 -1
  19. package/dist/agent/lint.js +1 -1
  20. package/dist/agent/multi-agent.js +44 -44
  21. package/dist/agent/orchestrator.js +93 -18
  22. package/dist/agent/orchestrator.js.map +1 -1
  23. package/dist/agent/parallel-orchestrator.js +1 -1
  24. package/dist/agent/planner.js +8 -3
  25. package/dist/agent/planner.js.map +1 -1
  26. package/dist/agent/prompts.js +2 -2
  27. package/dist/agent/quality-gate.js +1 -1
  28. package/dist/agent/repo-context.js +1 -1
  29. package/dist/agent/repo-reader.js +1 -1
  30. package/dist/agent/repo-underwriter.js +1 -1
  31. package/dist/agent/self-correction.js +1 -1
  32. package/dist/agent/self-heal.js +5 -0
  33. package/dist/agent/self-heal.js.map +1 -1
  34. package/dist/agent/self-improver.js +1 -1
  35. package/dist/agent/subagent-summary.js +1 -1
  36. package/dist/agent/subagent.js +1 -1
  37. package/dist/agent/swe-agent.js +1 -1
  38. package/dist/agent/swe-verifier.js +1 -1
  39. package/dist/agent/symbol-index.js +1 -1
  40. package/dist/agent/team.js +1 -1
  41. package/dist/agent/type-checker.js +1 -1
  42. package/dist/cli/commands.js +7 -0
  43. package/dist/cli/commands.js.map +1 -1
  44. package/dist/cli/index.js +57 -2
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/cli/repl.js +1 -1
  47. package/dist/cli/run.js +40 -3
  48. package/dist/cli/run.js.map +1 -1
  49. package/dist/cli/self-evolve-cli.js +168 -0
  50. package/dist/cli/tui-run.js +1 -1
  51. package/dist/cli/tui.js +1 -1
  52. package/dist/cli/version.js +3 -3
  53. package/dist/cli/version.js.map +1 -1
  54. package/dist/enterprise/audit.js +1 -1
  55. package/dist/enterprise/index.js +1 -1
  56. package/dist/enterprise/policy.js +1 -1
  57. package/dist/enterprise/quota.js +1 -1
  58. package/dist/enterprise/tenant.js +1 -1
  59. package/dist/harness/executor.js +1 -1
  60. package/dist/harness/index.js +1 -1
  61. package/dist/harness/loader.js +1 -1
  62. package/dist/harness/types.js +1 -1
  63. package/dist/harness/verifier.js +52 -12
  64. package/dist/harness/verifier.js.map +1 -1
  65. package/dist/hello.js +14 -0
  66. package/dist/hello.js.map +1 -0
  67. package/dist/integrations/feishu-bridge.js +348 -0
  68. package/dist/integrations/feishu-bridge.js.map +1 -0
  69. package/dist/integrations/github-mcp.js +137 -0
  70. package/dist/integrations/github-mcp.js.map +1 -0
  71. package/dist/integrations/wechat-bridge.js +499 -0
  72. package/dist/integrations/wechat-bridge.js.map +1 -0
  73. package/dist/integrations/yuanbao-bridge.js +326 -0
  74. package/dist/integrations/yuanbao-bridge.js.map +1 -0
  75. package/dist/lsp/lsp-client.js +1 -1
  76. package/dist/models/model-router.js +1 -1
  77. package/dist/models/model.dto.js +1 -1
  78. package/dist/models/providers/ollama.provider.js +1 -1
  79. package/dist/models/providers/openai-compatible.provider.js +1 -1
  80. package/dist/plugins/plugin-loader.js +1 -1
  81. package/dist/runtime/event-log.js +1 -1
  82. package/dist/runtime/git.js +1 -1
  83. package/dist/runtime/hooks.js +71 -4
  84. package/dist/runtime/hooks.js.map +1 -1
  85. package/dist/runtime/session-persist.js +1 -1
  86. package/dist/runtime/worktree.js +1 -1
  87. package/dist/self-evolve/hook.ts +80 -0
  88. package/dist/self-evolve/manager.d.ts +8 -0
  89. package/dist/self-evolve/manager.js +517 -401
  90. package/dist/self-evolve/self-heal-scheduler.js +160 -0
  91. package/dist/self-evolve/self-heal-scheduler.js.map +1 -0
  92. package/dist/shared/concurrency.js +1 -1
  93. package/dist/shared/config.js +4 -2
  94. package/dist/shared/config.js.map +1 -1
  95. package/dist/shared/errors.js +1 -1
  96. package/dist/shared/i18n.js +1 -1
  97. package/dist/shared/i18n.js.map +1 -1
  98. package/dist/shared/secure-store.js +12 -5
  99. package/dist/shared/secure-store.js.map +1 -1
  100. package/dist/shared/types.js +1 -1
  101. package/dist/skills/goal.js +1 -1
  102. package/dist/skills/grill.js +1 -1
  103. package/dist/skills/plan.js +1 -1
  104. package/dist/skills/pua-hooks.js +273 -0
  105. package/dist/skills/pua-hooks.js.map +1 -0
  106. package/dist/skills/self-heal.js +9 -3
  107. package/dist/skills/self-heal.js.map +1 -1
  108. package/dist/skills/skill-loader.js +1 -1
  109. package/dist/skills/skill-market.js +84 -8
  110. package/dist/skills/skill-market.js.map +1 -1
  111. package/dist/tools/analysis/code-analyzer.js +1 -1
  112. package/dist/tools/file/edit.tool.js +18 -3
  113. package/dist/tools/file/edit.tool.js.map +1 -1
  114. package/dist/tools/file/list.tool.js +1 -1
  115. package/dist/tools/file/read.tool.js +1 -1
  116. package/dist/tools/file/write.tool.js +1 -1
  117. package/dist/tools/generator/code-generator.js +1 -1
  118. package/dist/tools/generator/test-generator.js +1 -1
  119. package/dist/tools/index.js +1 -1
  120. package/dist/tools/mcp/index.js +1 -1
  121. package/dist/tools/mcp/mcp-client.js +1 -1
  122. package/dist/tools/safe-path.js +1 -1
  123. package/dist/tools/search/grep.tool.js +1 -1
  124. package/dist/tools/shell/exec.js +1 -1
  125. package/dist/tools/shell/run-shell.tool.js +1 -1
  126. package/dist/tools/skills/load-skill.tool.js +1 -1
  127. package/dist/tools/tool.registry.js +10 -1
  128. package/dist/tools/tool.registry.js.map +1 -1
  129. package/dist/tools/verify/build-check.tool.js +1 -1
  130. package/dist/tools/verify/test-run.tool.js +1 -1
  131. package/dist/tools/web/web.tool.js +1 -1
  132. package/dist/voice/voice-programming.js +32 -6
  133. package/dist/voice/voice-programming.js.map +1 -1
  134. package/dist/web/auth.js +34 -2
  135. package/dist/web/auth.js.map +1 -1
  136. package/dist/web/channels.js +1 -1
  137. package/dist/web/public/css/style.css +1751 -1724
  138. package/dist/web/public/index.html +1243 -1242
  139. package/dist/web/public/js/api.js +558 -555
  140. package/dist/web/public/js/app.js +2233 -2210
  141. package/dist/web/public/js/mock-api.js +259 -234
  142. package/dist/web/public/js/monaco-editor.js +363 -363
  143. package/dist/web/public/js/ui.js +2217 -2251
  144. package/dist/web/public/js/utils.js +214 -214
  145. package/dist/web/public/manifest.json +59 -59
  146. package/dist/web/public/service-worker.js +149 -173
  147. package/dist/web/public/vendor/monaco/vs/abap-D-t0cyap.js +1 -0
  148. package/dist/web/public/vendor/monaco/vs/apex-CcIm7xu6.js +1 -0
  149. package/dist/web/public/vendor/monaco/vs/assets/css.worker-URu8fCFR.js +97 -0
  150. package/dist/web/public/vendor/monaco/vs/assets/editor.worker-lj3bdIIn.js +30 -0
  151. package/dist/web/public/vendor/monaco/vs/assets/editorWebWorkerMain-CA_vMoUU.js +30 -0
  152. package/dist/web/public/vendor/monaco/vs/assets/html.worker-D1SL3iM8.js +474 -0
  153. package/dist/web/public/vendor/monaco/vs/assets/json.worker-CoJx_OPf.js +62 -0
  154. package/dist/web/public/vendor/monaco/vs/assets/ts.worker-BWKtMYOk.js +67722 -0
  155. package/dist/web/public/vendor/monaco/vs/azcli-BA0tQDCg.js +1 -0
  156. package/dist/web/public/vendor/monaco/vs/basic-languages/monaco.contribution.js +1 -0
  157. package/dist/web/public/vendor/monaco/vs/bat-C397hTD6.js +1 -0
  158. package/dist/web/public/vendor/monaco/vs/bicep-DF5aW17k.js +2 -0
  159. package/dist/web/public/vendor/monaco/vs/cameligo-plsz8qhj.js +1 -0
  160. package/dist/web/public/vendor/monaco/vs/clojure-Y2auQMzK.js +1 -0
  161. package/dist/web/public/vendor/monaco/vs/coffee-Bu45yuWE.js +1 -0
  162. package/dist/web/public/vendor/monaco/vs/cpp-CkKPQIni.js +1 -0
  163. package/dist/web/public/vendor/monaco/vs/csharp-CX28MZyh.js +1 -0
  164. package/dist/web/public/vendor/monaco/vs/csp-D8uWnyxW.js +1 -0
  165. package/dist/web/public/vendor/monaco/vs/css-CaeNmE3S.js +3 -0
  166. package/dist/web/public/vendor/monaco/vs/css.worker-CyhWkhHo.js +1 -0
  167. package/dist/web/public/vendor/monaco/vs/cssMode-CV6Ay48H.js +1 -0
  168. package/dist/web/public/vendor/monaco/vs/cypher-DVThT8BS.js +1 -0
  169. package/dist/web/public/vendor/monaco/vs/dart-CmGfCvrO.js +1 -0
  170. package/dist/web/public/vendor/monaco/vs/dockerfile-CZqqYdch.js +1 -0
  171. package/dist/web/public/vendor/monaco/vs/ecl-30fUercY.js +1 -0
  172. package/dist/web/public/vendor/monaco/vs/editor/editor.main.css +1 -0
  173. package/dist/web/public/vendor/monaco/vs/editor/editor.main.js +1 -0
  174. package/dist/web/public/vendor/monaco/vs/editor/editor.worker.js +1 -0
  175. package/dist/web/public/vendor/monaco/vs/editor-KLE6jdfb.js +831 -0
  176. package/dist/web/public/vendor/monaco/vs/editor.js +1 -0
  177. package/dist/web/public/vendor/monaco/vs/editorWorkerHost-fVE1cjcC.js +35 -0
  178. package/dist/web/public/vendor/monaco/vs/elixir-xjPaIfzF.js +1 -0
  179. package/dist/web/public/vendor/monaco/vs/flow9-DqtmStfK.js +1 -0
  180. package/dist/web/public/vendor/monaco/vs/freemarker2-FWreY7v7.js +3 -0
  181. package/dist/web/public/vendor/monaco/vs/fsharp-BOMdg4U1.js +1 -0
  182. package/dist/web/public/vendor/monaco/vs/go-D_hbi-Jt.js +1 -0
  183. package/dist/web/public/vendor/monaco/vs/graphql-CKUU4kLG.js +1 -0
  184. package/dist/web/public/vendor/monaco/vs/handlebars-CZi4pHCH.js +1 -0
  185. package/dist/web/public/vendor/monaco/vs/hcl-DTaboeZW.js +1 -0
  186. package/dist/web/public/vendor/monaco/vs/html-j_7ZTNRU.js +1 -0
  187. package/dist/web/public/vendor/monaco/vs/html.worker-CA3iAimZ.js +1 -0
  188. package/dist/web/public/vendor/monaco/vs/htmlMode-27by_KM4.js +1 -0
  189. package/dist/web/public/vendor/monaco/vs/index-049xrXrp.js +1 -0
  190. package/dist/web/public/vendor/monaco/vs/index-CBVt3dzv.js +5 -0
  191. package/dist/web/public/vendor/monaco/vs/index.js +1 -0
  192. package/dist/web/public/vendor/monaco/vs/ini-CsNwO04R.js +1 -0
  193. package/dist/web/public/vendor/monaco/vs/initialize-DL0l1TGY.js +1 -0
  194. package/dist/web/public/vendor/monaco/vs/java-CI4ZMsH9.js +1 -0
  195. package/dist/web/public/vendor/monaco/vs/javascript-DTJl4Jn1.js +1 -0
  196. package/dist/web/public/vendor/monaco/vs/json.worker-BizpAl9O.js +1 -0
  197. package/dist/web/public/vendor/monaco/vs/jsonMode-DLUiMUrI.js +1 -0
  198. package/dist/web/public/vendor/monaco/vs/julia-BwzEvaQw.js +1 -0
  199. package/dist/web/public/vendor/monaco/vs/kotlin-IUYPiTV8.js +1 -0
  200. package/dist/web/public/vendor/monaco/vs/language/css/css.worker.js +66 -0
  201. package/dist/web/public/vendor/monaco/vs/language/css/monaco.contribution.js +1 -0
  202. package/dist/web/public/vendor/monaco/vs/language/html/html.worker.js +443 -0
  203. package/dist/web/public/vendor/monaco/vs/language/html/monaco.contribution.js +1 -0
  204. package/dist/web/public/vendor/monaco/vs/language/json/json.worker.js +17 -0
  205. package/dist/web/public/vendor/monaco/vs/language/json/monaco.contribution.js +1 -0
  206. package/dist/web/public/vendor/monaco/vs/language/typescript/monaco.contribution.js +1 -0
  207. package/dist/web/public/vendor/monaco/vs/language/typescript/ts.worker.js +67693 -0
  208. package/dist/web/public/vendor/monaco/vs/less-C0eDYdqa.js +2 -0
  209. package/dist/web/public/vendor/monaco/vs/lexon-iON-Kj97.js +1 -0
  210. package/dist/web/public/vendor/monaco/vs/liquid-CLJYelW6.js +1 -0
  211. package/dist/web/public/vendor/monaco/vs/loader.js +1368 -0
  212. package/dist/web/public/vendor/monaco/vs/lspLanguageFeatures-BIkJOWLw.js +2 -0
  213. package/dist/web/public/vendor/monaco/vs/lua-DtygF91M.js +1 -0
  214. package/dist/web/public/vendor/monaco/vs/m3-CsR4AuFi.js +1 -0
  215. package/dist/web/public/vendor/monaco/vs/main-BEx-Fmlo.js +15 -0
  216. package/dist/web/public/vendor/monaco/vs/main-DsK8pnKg.js +3 -0
  217. package/dist/web/public/vendor/monaco/vs/markdown-C_rD0bIw.js +1 -0
  218. package/dist/web/public/vendor/monaco/vs/mdx-CpzZIPHF.js +1 -0
  219. package/dist/web/public/vendor/monaco/vs/mips-CiYP61RB.js +1 -0
  220. package/dist/web/public/vendor/monaco/vs/monaco.contribution-9cKT3C7t.js +1 -0
  221. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BE88ZNGY.js +1 -0
  222. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BPhsneLd.js +1 -0
  223. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BgRy6xDf.js +1 -0
  224. package/dist/web/public/vendor/monaco/vs/msdax-C38-sJlp.js +1 -0
  225. package/dist/web/public/vendor/monaco/vs/mysql-CdtbpvbG.js +1 -0
  226. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.d.ts +1 -0
  227. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.js +9 -0
  228. package/dist/web/public/vendor/monaco/vs/nls/lang/de.d.ts +1 -0
  229. package/dist/web/public/vendor/monaco/vs/nls/lang/de.js +9 -0
  230. package/dist/web/public/vendor/monaco/vs/nls/lang/es.d.ts +1 -0
  231. package/dist/web/public/vendor/monaco/vs/nls/lang/es.js +9 -0
  232. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.d.ts +1 -0
  233. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.js +9 -0
  234. package/dist/web/public/vendor/monaco/vs/nls/lang/it.d.ts +1 -0
  235. package/dist/web/public/vendor/monaco/vs/nls/lang/it.js +9 -0
  236. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.d.ts +1 -0
  237. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.js +9 -0
  238. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.d.ts +1 -0
  239. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.js +9 -0
  240. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.d.ts +1 -0
  241. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.js +9 -0
  242. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.d.ts +1 -0
  243. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.js +9 -0
  244. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.d.ts +1 -0
  245. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.js +9 -0
  246. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.d.ts +1 -0
  247. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.js +9 -0
  248. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.d.ts +1 -0
  249. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.js +9 -0
  250. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.d.ts +1 -0
  251. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.js +9 -0
  252. package/dist/web/public/vendor/monaco/vs/nls.messages-loader.js +1 -0
  253. package/dist/web/public/vendor/monaco/vs/objective-c-CntZFaHX.js +1 -0
  254. package/dist/web/public/vendor/monaco/vs/pascal-r6kuqfl_.js +1 -0
  255. package/dist/web/public/vendor/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
  256. package/dist/web/public/vendor/monaco/vs/perl-DABw_TcH.js +1 -0
  257. package/dist/web/public/vendor/monaco/vs/pgsql-me_jFXeX.js +1 -0
  258. package/dist/web/public/vendor/monaco/vs/php-D_kh-9LK.js +1 -0
  259. package/dist/web/public/vendor/monaco/vs/pla-VfZjczW0.js +1 -0
  260. package/dist/web/public/vendor/monaco/vs/postiats-BBSzz8Pk.js +1 -0
  261. package/dist/web/public/vendor/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
  262. package/dist/web/public/vendor/monaco/vs/powershell-B-7ap1zc.js +1 -0
  263. package/dist/web/public/vendor/monaco/vs/protobuf-BmtuEB1A.js +2 -0
  264. package/dist/web/public/vendor/monaco/vs/pug-BRpRNeEb.js +1 -0
  265. package/dist/web/public/vendor/monaco/vs/python-CqWUUgfu.js +1 -0
  266. package/dist/web/public/vendor/monaco/vs/qsharp-BzsFaUU9.js +1 -0
  267. package/dist/web/public/vendor/monaco/vs/r-f8dDdrp4.js +1 -0
  268. package/dist/web/public/vendor/monaco/vs/razor-hok5y9Km.js +1 -0
  269. package/dist/web/public/vendor/monaco/vs/redis-fvZQY4PI.js +1 -0
  270. package/dist/web/public/vendor/monaco/vs/redshift-45Et0LQi.js +1 -0
  271. package/dist/web/public/vendor/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
  272. package/dist/web/public/vendor/monaco/vs/ruby-CZO8zYTz.js +1 -0
  273. package/dist/web/public/vendor/monaco/vs/rust-Bfetafyc.js +1 -0
  274. package/dist/web/public/vendor/monaco/vs/sb-3GYllVck.js +1 -0
  275. package/dist/web/public/vendor/monaco/vs/scala-foMgrKo1.js +1 -0
  276. package/dist/web/public/vendor/monaco/vs/scheme-CHdMtr7p.js +1 -0
  277. package/dist/web/public/vendor/monaco/vs/scss-C1cmLt9V.js +3 -0
  278. package/dist/web/public/vendor/monaco/vs/shell-ClXCKCEW.js +1 -0
  279. package/dist/web/public/vendor/monaco/vs/solidity-MZ6ExpPy.js +1 -0
  280. package/dist/web/public/vendor/monaco/vs/sophia-DWkuSsPQ.js +1 -0
  281. package/dist/web/public/vendor/monaco/vs/sparql-AUGFYSyk.js +1 -0
  282. package/dist/web/public/vendor/monaco/vs/sql-32GpJSV2.js +1 -0
  283. package/dist/web/public/vendor/monaco/vs/st-CuDFIVZ_.js +1 -0
  284. package/dist/web/public/vendor/monaco/vs/swift-t-PfMj7W.js +1 -0
  285. package/dist/web/public/vendor/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
  286. package/dist/web/public/vendor/monaco/vs/tcl-D74tq1nH.js +1 -0
  287. package/dist/web/public/vendor/monaco/vs/toggleHighContrast-qGX7E9o7.js +61 -0
  288. package/dist/web/public/vendor/monaco/vs/ts.worker-2QLmBukE.js +1 -0
  289. package/dist/web/public/vendor/monaco/vs/tsMode-B0S_kp2q.js +11 -0
  290. package/dist/web/public/vendor/monaco/vs/twig-C6taOxMV.js +1 -0
  291. package/dist/web/public/vendor/monaco/vs/typescript-_2t_511t.js +1 -0
  292. package/dist/web/public/vendor/monaco/vs/typespec-8OfoLt6R.js +1 -0
  293. package/dist/web/public/vendor/monaco/vs/vb-Dyb2648j.js +1 -0
  294. package/dist/web/public/vendor/monaco/vs/wgsl-BhLXMOR0.js +298 -0
  295. package/dist/web/public/vendor/monaco/vs/workers-BBttULjf.js +1 -0
  296. package/dist/web/public/vendor/monaco/vs/xml-cZjNDqDT.js +1 -0
  297. package/dist/web/public/vendor/monaco/vs/yaml-A1fOIdH6.js +1 -0
  298. package/dist/web/server.js +81 -16
  299. package/dist/web/server.js.map +1 -1
  300. package/dist/web/task-queue.js +6 -21
  301. package/dist/web/task-queue.js.map +1 -1
  302. package/dist/web/web-config.js +143 -0
  303. package/dist/web/web-config.js.map +1 -0
  304. package/docs/App/344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +1 -1
  305. package/docs/App/346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +1 -1
  306. package/docs/BENCHMARK_REPORT_en.md +386 -386
  307. package/docs/BENCHMARK_REPORT_zh.md +386 -386
  308. package/docs/DPA.md +65 -63
  309. package/docs/DPA/346/225/260/346/215/256/345/244/204/347/220/206/345/215/217/350/256/256/346/250/241/346/235/277_v1.0.md +69 -67
  310. package/docs/Deployment_Guide_EN.md +1 -1
  311. package/docs/SECURITY_WHITEPAPER.md +2 -2
  312. package/docs/SELF-EVOLVE-GUIDE.md +1 -1
  313. package/docs/SWE_BENCH_REPORT.md +73 -55
  314. package/docs/TECHNICAL_SPEC_en.md +292 -292
  315. package/docs/TECHNICAL_SPEC_zh.md +292 -292
  316. package/docs/Technical_Manual_EN.md +1 -1
  317. package/docs/UPDATE_NOTES_en.md +159 -159
  318. package/docs/UPDATE_NOTES_zh.md +159 -159
  319. package/docs/UPGRADE_7.2.0.md +309 -309
  320. package/docs/UPGRADE_GUIDE_7_5.md +86 -86
  321. package/docs/UPGRADE_GUIDE_7_6.md +153 -0
  322. package/docs/User_Manual_EN.md +1 -1
  323. package/docs/VOLTAGENT_SKILLS_CATALOG.md +95 -0
  324. package/docs/error-codes.md +1 -1
  325. package/docs/geo-feihong-code.html +391 -391
  326. package/docs//344/272/247/345/223/201/345/274/200/345/217/221/346/226/207/346/241/243.md +5 -3
  327. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +140 -231
  328. package/docs//345/205/250/351/235/242/345/244/215/347/233/230_50/350/275/256/346/267/261/345/272/246/345/256/241/350/256/241_v7.2.0.md +208 -208
  329. package/docs//345/205/250/351/235/242/345/244/215/347/233/230_6/351/241/271/351/207/215/347/202/271/346/240/270/346/237/245_v7.2.0.md +152 -152
  330. package/docs//345/205/250/351/235/242/345/244/215/347/233/230_/350/277/220/350/241/214/346/227/266/345/256/236/346/265/213/347/211/210_v7.2.0.md +271 -271
  331. package/docs//345/220/210/350/247/204/350/256/244/350/257/201/345/207/206/345/244/207/346/270/205/345/215/225_v7.2.0.md +59 -59
  332. package/docs//345/256/211/345/205/250/347/231/275/347/232/256/344/271/246_v7.2.0.md +84 -82
  333. package/docs//346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +240 -149
  334. package/docs//351/203/250/347/275/262/350/257/264/346/230/216/344/271/246.md +2 -2
  335. package/electron/main.js +404 -404
  336. package/package.json +12 -5
  337. package/templates/skills/api-design/SKILL.md +1 -1
  338. package/templates/skills/code-review/SKILL.md +1 -1
  339. package/templates/skills/dependency-upgrade/SKILL.md +1 -1
  340. package/templates/skills/doc-gen/SKILL.md +1 -1
  341. package/templates/skills/git-flow/SKILL.md +1 -1
  342. package/templates/skills/onboarding/SKILL.md +1 -1
  343. package/templates/skills/performance/SKILL.md +1 -1
  344. package/templates/skills/refactor/SKILL.md +1 -1
  345. package/templates/skills/security-audit/SKILL.md +1 -1
  346. package/templates/skills/test-gen/SKILL.md +1 -1
  347. package/tool-schema.json +197 -197
@@ -1,363 +1,363 @@
1
- /**
2
- * 飞虹 Code - Monaco Editor 封装模块
3
- * VSCode 同款编辑器内核,提供语法高亮、智能补全、内联 ghost text 等能力
4
- *
5
- * 依赖:index.html 中已加载 vendor/monaco/vs/loader.js(AMD loader)
6
- */
7
- (function (global) {
8
- 'use strict';
9
-
10
- let monacoInstance = null;
11
- let initPromise = null;
12
- const editors = new Map(); // containerId -> editor instance
13
- let activeEditor = null; // 最近创建的编辑器(供 lint/诊断反馈定位)
14
- let inlineCompletionProvider = null;
15
- let completionItemProvider = null;
16
-
17
- /** 获取当前活跃编辑器(P6-1 lint 反馈定位) */
18
- function getActiveEditor() {
19
- return activeEditor;
20
- }
21
-
22
- /** 根据文件扩展名推断 Monaco language id */
23
- function detectLanguage(filePath) {
24
- const ext = filePath.split('.').pop().toLowerCase();
25
- const map = {
26
- ts: 'typescript', tsx: 'typescript', js: 'javascript', jsx: 'javascript',
27
- json: 'json', md: 'markdown', html: 'html', css: 'css', scss: 'scss',
28
- less: 'less', py: 'python', java: 'java', c: 'c', cpp: 'cpp', h: 'cpp',
29
- cs: 'csharp', go: 'go', rs: 'rust', php: 'php', rb: 'ruby', swift: 'swift',
30
- kt: 'kotlin', scala: 'scala', sh: 'shell', bash: 'shell', zsh: 'shell',
31
- sql: 'sql', yaml: 'yaml', yml: 'yaml', xml: 'xml', vue: 'html', svelte: 'html',
32
- proto: 'protobuf', dockerfile: 'dockerfile', toml: 'ini', ini: 'ini',
33
- };
34
- if (filePath.toLowerCase().endsWith('dockerfile')) return 'dockerfile';
35
- return map[ext] || 'plaintext';
36
- }
37
-
38
- /** 初始化 Monaco(只执行一次,返回 Promise) */
39
- function initMonaco() {
40
- if (monacoInstance) return Promise.resolve(monacoInstance);
41
- if (initPromise) return initPromise;
42
-
43
- initPromise = new Promise((resolve, reject) => {
44
- if (typeof global.require === 'undefined') {
45
- reject(new Error('Monaco loader.js 未加载,请检查 vendor/monaco/vs/loader.js'));
46
- return;
47
- }
48
- global.require.config({ paths: { vs: 'vendor/monaco/vs' } });
49
- global.require(['vs/editor/editor.main'], function () {
50
- monacoInstance = global.monaco;
51
- // 配置默认主题(跟随系统深色/浅色)
52
- const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
53
- monacoInstance.editor.setTheme(isDark ? 'vs-dark' : 'vs');
54
- resolve(monacoInstance);
55
- }, reject);
56
- });
57
- return initPromise;
58
- }
59
-
60
- /**
61
- * 在指定容器中创建 Monaco 编辑器
62
- * @param {HTMLElement|string} container - 容器元素或 ID
63
- * @param {string} value - 初始内容
64
- * @param {string} filePath - 文件路径(用于推断语言)
65
- * @param {object} options - 额外选项
66
- * @returns {Promise<monaco.editor.IStandaloneCodeEditor>}
67
- */
68
- async function createEditor(container, value, filePath, options = {}) {
69
- const monaco = await initMonaco();
70
- const el = typeof container === 'string' ? document.getElementById(container) : container;
71
- if (!el) throw new Error('编辑器容器不存在: ' + container);
72
-
73
- // 如果该容器已有编辑器,先销毁
74
- const existing = editors.get(el.id || container);
75
- if (existing) {
76
- existing.dispose();
77
- editors.delete(el.id || container);
78
- }
79
-
80
- const language = detectLanguage(filePath);
81
- const editor = monaco.editor.create(el, {
82
- value: value || '',
83
- language: language,
84
- theme: undefined, // 使用全局主题
85
- automaticLayout: true,
86
- fontSize: 13,
87
- lineNumbers: 'on',
88
- minimap: { enabled: true },
89
- scrollBeyondLastLine: false,
90
- wordWrap: 'on',
91
- bracketPairColorization: { enabled: true },
92
- guides: { bracketPairs: true, indentation: true },
93
- tabSize: 2,
94
- renderWhitespace: 'selection',
95
- smoothScrolling: true,
96
- cursorBlinking: 'smooth',
97
- // P0-1: 启用内联补全(ghost text,Tab 接受)
98
- inlineSuggest: { enabled: true, showToolbar: 'always' },
99
- // 启用快速建议(输入时自动触发补全弹窗)
100
- quickSuggestions: { other: true, comments: false, strings: true },
101
- quickSuggestionsDelay: 200,
102
- ...options,
103
- });
104
-
105
- const key = el.id || container;
106
- editors.set(key, editor);
107
- activeEditor = editor; // P6-1: 记录最近活跃编辑器供 lint 反馈定位
108
- return editor;
109
- }
110
-
111
- /** 获取编辑器实例 */
112
- function getEditor(container) {
113
- const key = typeof container === 'string' ? container : container.id;
114
- return editors.get(key);
115
- }
116
-
117
- /** 销毁编辑器 */
118
- function disposeEditor(container) {
119
- const key = typeof container === 'string' ? container : container.id;
120
- const editor = editors.get(key);
121
- if (editor) {
122
- editor.dispose();
123
- editors.delete(key);
124
- }
125
- }
126
-
127
- /**
128
- * 注册内联补全 Provider(ghost text,Tab 接受)
129
- * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset},返回 {text: string}
130
- */
131
- /**
132
- * 注册行内补全 Provider(ghost text)
133
- * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset, token},返回 {text} 或 null
134
- * @param {{getActiveEditor?:function, onAccept?:function}} [opts] - P6-1: getActiveEditor 取当前编辑器;onAccept 在补全被接受(插入)时回调插入文本
135
- */
136
- function registerInlineCompletions(fetchFn, opts) {
137
- const o = opts || {};
138
- initMonaco().then((monaco) => {
139
- if (inlineCompletionProvider) {
140
- inlineCompletionProvider.dispose();
141
- }
142
- let lastText = '';
143
- inlineCompletionProvider = monaco.languages.registerInlineCompletionsProvider('*', {
144
- provideInlineCompletions: async function (model, position, context, token) {
145
- try {
146
- const filePath = model.uri.path || 'untitled';
147
- const content = model.getValue();
148
- const offset = model.getOffsetAt(position);
149
- const result = await fetchFn({ filePath, content, offset, token });
150
- if (!result || !result.text) return { items: [] };
151
- const item = {
152
- range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
153
- insertText: result.text,
154
- filterText: result.text.slice(0, 20),
155
- };
156
- lastText = result.text;
157
- return { items: [item] };
158
- } catch (e) {
159
- return { items: [] };
160
- }
161
- },
162
- freeInlineCompletions: function () {},
163
- });
164
-
165
- // P6-1: accept 检测——编辑器内容变化且插入文本匹配最近补全 → onAccept(插入文本)
166
- const bindAccept = function () {
167
- const editor = typeof o.getActiveEditor === 'function' ? o.getActiveEditor() : null;
168
- if (!editor || editor.__fhInlineAcceptBound) return;
169
- editor.__fhInlineAcceptBound = true;
170
- editor.onDidChangeModelContent((e) => {
171
- if (!lastText) return;
172
- for (const ch of e.changes || []) {
173
- const ins = ch.text || '';
174
- if (ins && (ins.startsWith(lastText) || lastText.startsWith(ins))) {
175
- const accepted = ins.length >= lastText.length ? ins : lastText;
176
- if (typeof o.onAccept === 'function') {
177
- try { o.onAccept(accepted); } catch { /* lint 回调失败不阻塞编辑 */ }
178
- }
179
- lastText = '';
180
- break;
181
- }
182
- }
183
- });
184
- };
185
- bindAccept();
186
- });
187
- }
188
-
189
- /**
190
- * 注册补全项 Provider(Ctrl+Space 触发弹窗,↑↓选择,Enter接受)
191
- * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset, prefix},返回数组 [{label, kind, insertText, detail}]
192
- */
193
- function registerCompletionItems(fetchFn) {
194
- initMonaco().then((monaco) => {
195
- if (completionItemProvider) {
196
- completionItemProvider.dispose();
197
- }
198
- completionItemProvider = monaco.languages.registerCompletionItemProvider('*', {
199
- triggerCharacters: ['.', '(', ',', ' '],
200
- provideCompletionItems: async function (model, position, context, token) {
201
- try {
202
- const filePath = model.uri.path || 'untitled';
203
- const content = model.getValue();
204
- const offset = model.getOffsetAt(position);
205
- const word = model.getWordUntilPosition(position);
206
- const prefix = word.word || '';
207
- const suggestions = await fetchFn({ filePath, content, offset, prefix, token });
208
- if (!Array.isArray(suggestions) || !suggestions.length) return { suggestions: [] };
209
- const range = new monaco.Range(
210
- position.lineNumber, word.startColumn,
211
- position.lineNumber, position.column
212
- );
213
- return {
214
- suggestions: suggestions.map((s) => ({
215
- label: s.label || s.insertText || '',
216
- kind: monaco.languages.CompletionItemKind[s.kind] || monaco.languages.CompletionItemKind.Text,
217
- insertText: s.insertText || '',
218
- detail: s.detail || '',
219
- range: range,
220
- })),
221
- };
222
- } catch (e) {
223
- return { suggestions: [] };
224
- }
225
- },
226
- });
227
- });
228
- }
229
-
230
- /**
231
- * 注册语义诊断 Provider(P4-2:编辑时错误波浪线)
232
- * @param {function} fetchFn - 异步诊断函数,参数 {filePath, content},返回 [{line, column, endLine, endColumn, message, severity}]
233
- * @param {function} [getEditor] - 获取当前编辑器实例(默认遍历已注册编辑器)
234
- */
235
- function registerDiagnostics(fetchFn, getActiveEditor) {
236
- initMonaco().then((monaco) => {
237
- // P5-2: 诊断 hover 提示——hover 到有 marker 的行时展示错误/警告详情
238
- const langSet = [
239
- 'typescript', 'javascript', 'json', 'markdown', 'html', 'css', 'scss', 'less',
240
- 'python', 'java', 'c', 'cpp', 'csharp', 'go', 'rust', 'php', 'ruby', 'swift',
241
- 'kotlin', 'scala', 'shell', 'sql', 'yaml', 'xml', 'protobuf', 'dockerfile',
242
- 'ini', 'plaintext',
243
- ];
244
- const hoverDisp = monaco.languages.registerHoverProvider(langSet, {
245
- provideHover(model, position) {
246
- let editor;
247
- try { editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null; } catch { editor = null; }
248
- if (!editor || editor.isDisposed?.()) return null;
249
- const cur = editor.getModel();
250
- if (!cur || model.uri.toString() !== cur.uri.toString()) return null;
251
- const markers = monaco.editor.getModelMarkers({ resource: model.uri })
252
- .filter((x) => x.startLineNumber <= position.lineNumber && position.lineNumber <= x.endLineNumber);
253
- if (markers.length === 0) return null;
254
- const md = markers.map((x) => {
255
- const sevName = x.severity === monaco.MarkerSeverity.Error ? '错误' : x.severity === monaco.MarkerSeverity.Warning ? '警告' : '提示';
256
- const icon = x.severity === monaco.MarkerSeverity.Error ? '⛔' : x.severity === monaco.MarkerSeverity.Warning ? '⚠️' : 'ℹ️';
257
- return '**' + icon + ' ' + sevName + '** (L' + x.startLineNumber + ':' + x.startColumn + ') \n' + x.message;
258
- }).join('\n\n---\n\n');
259
- return {
260
- contents: [{ value: '#### 飞虹 Code 诊断\n\n' + md, isTrusted: true }],
261
- range: new monaco.Range(position.lineNumber, 1, position.lineNumber, 1),
262
- };
263
- },
264
- });
265
- hoverDisp; // 引用保持存活(Monaco 内部维护)
266
-
267
- // 防抖 + 单飞,避免编辑时高频请求
268
- let timer = null;
269
- let inflight = false;
270
- let queued = false;
271
- const run = async function () {
272
- if (inflight) { queued = true; return; }
273
- const editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null;
274
- if (!editor || editor.isDisposed?.()) return;
275
- const model = editor.getModel();
276
- if (!model) return;
277
- inflight = true;
278
- try {
279
- const filePath = model.uri.path || 'untitled';
280
- const content = model.getValue();
281
- const result = await fetchFn({ filePath, content });
282
- if (!result || !Array.isArray(result.diagnostics)) {
283
- monaco.editor.setModelMarkers(model, 'fhcode', []);
284
- return;
285
- }
286
- const markers = result.diagnostics.map((d) => {
287
- const sev = d.severity === 1 || d.severity === 'error'
288
- ? monaco.MarkerSeverity.Error
289
- : d.severity === 2 || d.severity === 'warning'
290
- ? monaco.MarkerSeverity.Warning
291
- : monaco.MarkerSeverity.Info;
292
- return {
293
- severity: sev,
294
- message: d.message || '',
295
- startLineNumber: d.line ?? 1,
296
- startColumn: d.column ?? 1,
297
- endLineNumber: d.endLine ?? (d.line ?? 1),
298
- endColumn: d.endColumn ?? (d.column ?? 1) + (d.message?.length || 8),
299
- };
300
- });
301
- monaco.editor.setModelMarkers(model, 'fhcode', markers);
302
- } catch {
303
- /* 诊断失败静默(不阻塞编辑) */
304
- } finally {
305
- inflight = false;
306
- if (queued) { queued = false; timer = setTimeout(run, 200); }
307
- }
308
- };
309
- const schedule = function () {
310
- clearTimeout(timer);
311
- timer = setTimeout(run, 350);
312
- };
313
- // 绑定现有编辑器(createEditor 后由 ui 层调用 attachDiagnostics 触发监听)
314
- const editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null;
315
- if (editor && !editor.__fhDiagnosticsBound) {
316
- editor.__fhDiagnosticsBound = true;
317
- editor.onDidChangeModelContent(schedule);
318
- editor.onDidChangeModel(() => schedule());
319
- }
320
- return { run, schedule };
321
- });
322
- }
323
-
324
- /**
325
- * P6-1: 补全接受后的 lint 反馈——把 /api/lint 结果追加为编辑器波浪线(owner: fhcode-lint)
326
- * @param {Array} issues - [{severity, line, column, message}]
327
- */
328
- function showLintFeedback(issues) {
329
- initMonaco().then((monaco) => {
330
- const editor = activeEditor;
331
- if (!editor || editor.isDisposed?.()) return;
332
- const model = editor.getModel();
333
- if (!model) return;
334
- if (!Array.isArray(issues) || issues.length === 0) {
335
- monaco.editor.setModelMarkers(model, 'fhcode-lint', []);
336
- return;
337
- }
338
- const markers = issues.map((d) => ({
339
- severity: d.severity === 1 ? monaco.MarkerSeverity.Error : d.severity === 2 ? monaco.MarkerSeverity.Warning : monaco.MarkerSeverity.Info,
340
- message: '补全校验:' + (d.message || ''),
341
- startLineNumber: d.line ?? 1,
342
- startColumn: d.column ?? 1,
343
- endLineNumber: d.line ?? 1,
344
- endColumn: (d.column ?? 1) + (d.message?.length || 20),
345
- }));
346
- monaco.editor.setModelMarkers(model, 'fhcode-lint', markers);
347
- });
348
- }
349
-
350
- /** 暴露全局 API */
351
- global.FHMonaco = {
352
- init: initMonaco,
353
- createEditor: createEditor,
354
- getEditor: getEditor,
355
- disposeEditor: disposeEditor,
356
- detectLanguage: detectLanguage,
357
- getActiveEditor: getActiveEditor,
358
- registerInlineCompletions: registerInlineCompletions,
359
- registerCompletionItems: registerCompletionItems,
360
- registerDiagnostics: registerDiagnostics,
361
- showLintFeedback: showLintFeedback,
362
- };
363
- })(window);
1
+ /**
2
+ * 飞虹 Code - Monaco Editor 封装模块
3
+ * VSCode 同款编辑器内核,提供语法高亮、智能补全、内联 ghost text 等能力
4
+ *
5
+ * 依赖:index.html 中已加载 vendor/monaco/vs/loader.js(AMD loader)
6
+ */
7
+ (function (global) {
8
+ 'use strict';
9
+
10
+ let monacoInstance = null;
11
+ let initPromise = null;
12
+ const editors = new Map(); // containerId -> editor instance
13
+ let activeEditor = null; // 最近创建的编辑器(供 lint/诊断反馈定位)
14
+ let inlineCompletionProvider = null;
15
+ let completionItemProvider = null;
16
+
17
+ /** 获取当前活跃编辑器(P6-1 lint 反馈定位) */
18
+ function getActiveEditor() {
19
+ return activeEditor;
20
+ }
21
+
22
+ /** 根据文件扩展名推断 Monaco language id */
23
+ function detectLanguage(filePath) {
24
+ const ext = filePath.split('.').pop().toLowerCase();
25
+ const map = {
26
+ ts: 'typescript', tsx: 'typescript', js: 'javascript', jsx: 'javascript',
27
+ json: 'json', md: 'markdown', html: 'html', css: 'css', scss: 'scss',
28
+ less: 'less', py: 'python', java: 'java', c: 'c', cpp: 'cpp', h: 'cpp',
29
+ cs: 'csharp', go: 'go', rs: 'rust', php: 'php', rb: 'ruby', swift: 'swift',
30
+ kt: 'kotlin', scala: 'scala', sh: 'shell', bash: 'shell', zsh: 'shell',
31
+ sql: 'sql', yaml: 'yaml', yml: 'yaml', xml: 'xml', vue: 'html', svelte: 'html',
32
+ proto: 'protobuf', dockerfile: 'dockerfile', toml: 'ini', ini: 'ini',
33
+ };
34
+ if (filePath.toLowerCase().endsWith('dockerfile')) return 'dockerfile';
35
+ return map[ext] || 'plaintext';
36
+ }
37
+
38
+ /** 初始化 Monaco(只执行一次,返回 Promise) */
39
+ function initMonaco() {
40
+ if (monacoInstance) return Promise.resolve(monacoInstance);
41
+ if (initPromise) return initPromise;
42
+
43
+ initPromise = new Promise((resolve, reject) => {
44
+ if (typeof global.require === 'undefined') {
45
+ reject(new Error('Monaco loader.js 未加载,请检查 vendor/monaco/vs/loader.js'));
46
+ return;
47
+ }
48
+ global.require.config({ paths: { vs: 'vendor/monaco/vs' } });
49
+ global.require(['vs/editor/editor.main'], function () {
50
+ monacoInstance = global.monaco;
51
+ // 配置默认主题(跟随系统深色/浅色)
52
+ const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
53
+ monacoInstance.editor.setTheme(isDark ? 'vs-dark' : 'vs');
54
+ resolve(monacoInstance);
55
+ }, reject);
56
+ });
57
+ return initPromise;
58
+ }
59
+
60
+ /**
61
+ * 在指定容器中创建 Monaco 编辑器
62
+ * @param {HTMLElement|string} container - 容器元素或 ID
63
+ * @param {string} value - 初始内容
64
+ * @param {string} filePath - 文件路径(用于推断语言)
65
+ * @param {object} options - 额外选项
66
+ * @returns {Promise<monaco.editor.IStandaloneCodeEditor>}
67
+ */
68
+ async function createEditor(container, value, filePath, options = {}) {
69
+ const monaco = await initMonaco();
70
+ const el = typeof container === 'string' ? document.getElementById(container) : container;
71
+ if (!el) throw new Error('编辑器容器不存在: ' + container);
72
+
73
+ // 如果该容器已有编辑器,先销毁
74
+ const existing = editors.get(el.id || container);
75
+ if (existing) {
76
+ existing.dispose();
77
+ editors.delete(el.id || container);
78
+ }
79
+
80
+ const language = detectLanguage(filePath);
81
+ const editor = monaco.editor.create(el, {
82
+ value: value || '',
83
+ language: language,
84
+ theme: undefined, // 使用全局主题
85
+ automaticLayout: true,
86
+ fontSize: 13,
87
+ lineNumbers: 'on',
88
+ minimap: { enabled: true },
89
+ scrollBeyondLastLine: false,
90
+ wordWrap: 'on',
91
+ bracketPairColorization: { enabled: true },
92
+ guides: { bracketPairs: true, indentation: true },
93
+ tabSize: 2,
94
+ renderWhitespace: 'selection',
95
+ smoothScrolling: true,
96
+ cursorBlinking: 'smooth',
97
+ // P0-1: 启用内联补全(ghost text,Tab 接受)
98
+ inlineSuggest: { enabled: true, showToolbar: 'always' },
99
+ // 启用快速建议(输入时自动触发补全弹窗)
100
+ quickSuggestions: { other: true, comments: false, strings: true },
101
+ quickSuggestionsDelay: 200,
102
+ ...options,
103
+ });
104
+
105
+ const key = el.id || container;
106
+ editors.set(key, editor);
107
+ activeEditor = editor; // P6-1: 记录最近活跃编辑器供 lint 反馈定位
108
+ return editor;
109
+ }
110
+
111
+ /** 获取编辑器实例 */
112
+ function getEditor(container) {
113
+ const key = typeof container === 'string' ? container : container.id;
114
+ return editors.get(key);
115
+ }
116
+
117
+ /** 销毁编辑器 */
118
+ function disposeEditor(container) {
119
+ const key = typeof container === 'string' ? container : container.id;
120
+ const editor = editors.get(key);
121
+ if (editor) {
122
+ editor.dispose();
123
+ editors.delete(key);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * 注册内联补全 Provider(ghost text,Tab 接受)
129
+ * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset},返回 {text: string}
130
+ */
131
+ /**
132
+ * 注册行内补全 Provider(ghost text)
133
+ * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset, token},返回 {text} 或 null
134
+ * @param {{getActiveEditor?:function, onAccept?:function}} [opts] - P6-1: getActiveEditor 取当前编辑器;onAccept 在补全被接受(插入)时回调插入文本
135
+ */
136
+ function registerInlineCompletions(fetchFn, opts) {
137
+ const o = opts || {};
138
+ initMonaco().then((monaco) => {
139
+ if (inlineCompletionProvider) {
140
+ inlineCompletionProvider.dispose();
141
+ }
142
+ let lastText = '';
143
+ inlineCompletionProvider = monaco.languages.registerInlineCompletionsProvider('*', {
144
+ provideInlineCompletions: async function (model, position, context, token) {
145
+ try {
146
+ const filePath = model.uri.path || 'untitled';
147
+ const content = model.getValue();
148
+ const offset = model.getOffsetAt(position);
149
+ const result = await fetchFn({ filePath, content, offset, token });
150
+ if (!result || !result.text) return { items: [] };
151
+ const item = {
152
+ range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
153
+ insertText: result.text,
154
+ filterText: result.text.slice(0, 20),
155
+ };
156
+ lastText = result.text;
157
+ return { items: [item] };
158
+ } catch (e) {
159
+ return { items: [] };
160
+ }
161
+ },
162
+ freeInlineCompletions: function () {},
163
+ });
164
+
165
+ // P6-1: accept 检测——编辑器内容变化且插入文本匹配最近补全 → onAccept(插入文本)
166
+ const bindAccept = function () {
167
+ const editor = typeof o.getActiveEditor === 'function' ? o.getActiveEditor() : null;
168
+ if (!editor || editor.__fhInlineAcceptBound) return;
169
+ editor.__fhInlineAcceptBound = true;
170
+ editor.onDidChangeModelContent((e) => {
171
+ if (!lastText) return;
172
+ for (const ch of e.changes || []) {
173
+ const ins = ch.text || '';
174
+ if (ins && (ins.startsWith(lastText) || lastText.startsWith(ins))) {
175
+ const accepted = ins.length >= lastText.length ? ins : lastText;
176
+ if (typeof o.onAccept === 'function') {
177
+ try { o.onAccept(accepted); } catch { /* lint 回调失败不阻塞编辑 */ }
178
+ }
179
+ lastText = '';
180
+ break;
181
+ }
182
+ }
183
+ });
184
+ };
185
+ bindAccept();
186
+ });
187
+ }
188
+
189
+ /**
190
+ * 注册补全项 Provider(Ctrl+Space 触发弹窗,↑↓选择,Enter接受)
191
+ * @param {function} fetchFn - 异步补全函数,参数 {filePath, content, offset, prefix},返回数组 [{label, kind, insertText, detail}]
192
+ */
193
+ function registerCompletionItems(fetchFn) {
194
+ initMonaco().then((monaco) => {
195
+ if (completionItemProvider) {
196
+ completionItemProvider.dispose();
197
+ }
198
+ completionItemProvider = monaco.languages.registerCompletionItemProvider('*', {
199
+ triggerCharacters: ['.', '(', ',', ' '],
200
+ provideCompletionItems: async function (model, position, context, token) {
201
+ try {
202
+ const filePath = model.uri.path || 'untitled';
203
+ const content = model.getValue();
204
+ const offset = model.getOffsetAt(position);
205
+ const word = model.getWordUntilPosition(position);
206
+ const prefix = word.word || '';
207
+ const suggestions = await fetchFn({ filePath, content, offset, prefix, token });
208
+ if (!Array.isArray(suggestions) || !suggestions.length) return { suggestions: [] };
209
+ const range = new monaco.Range(
210
+ position.lineNumber, word.startColumn,
211
+ position.lineNumber, position.column
212
+ );
213
+ return {
214
+ suggestions: suggestions.map((s) => ({
215
+ label: s.label || s.insertText || '',
216
+ kind: monaco.languages.CompletionItemKind[s.kind] || monaco.languages.CompletionItemKind.Text,
217
+ insertText: s.insertText || '',
218
+ detail: s.detail || '',
219
+ range: range,
220
+ })),
221
+ };
222
+ } catch (e) {
223
+ return { suggestions: [] };
224
+ }
225
+ },
226
+ });
227
+ });
228
+ }
229
+
230
+ /**
231
+ * 注册语义诊断 Provider(P4-2:编辑时错误波浪线)
232
+ * @param {function} fetchFn - 异步诊断函数,参数 {filePath, content},返回 [{line, column, endLine, endColumn, message, severity}]
233
+ * @param {function} [getEditor] - 获取当前编辑器实例(默认遍历已注册编辑器)
234
+ */
235
+ function registerDiagnostics(fetchFn, getActiveEditor) {
236
+ initMonaco().then((monaco) => {
237
+ // P5-2: 诊断 hover 提示——hover 到有 marker 的行时展示错误/警告详情
238
+ const langSet = [
239
+ 'typescript', 'javascript', 'json', 'markdown', 'html', 'css', 'scss', 'less',
240
+ 'python', 'java', 'c', 'cpp', 'csharp', 'go', 'rust', 'php', 'ruby', 'swift',
241
+ 'kotlin', 'scala', 'shell', 'sql', 'yaml', 'xml', 'protobuf', 'dockerfile',
242
+ 'ini', 'plaintext',
243
+ ];
244
+ const hoverDisp = monaco.languages.registerHoverProvider(langSet, {
245
+ provideHover(model, position) {
246
+ let editor;
247
+ try { editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null; } catch { editor = null; }
248
+ if (!editor || editor.isDisposed?.()) return null;
249
+ const cur = editor.getModel();
250
+ if (!cur || model.uri.toString() !== cur.uri.toString()) return null;
251
+ const markers = monaco.editor.getModelMarkers({ resource: model.uri })
252
+ .filter((x) => x.startLineNumber <= position.lineNumber && position.lineNumber <= x.endLineNumber);
253
+ if (markers.length === 0) return null;
254
+ const md = markers.map((x) => {
255
+ const sevName = x.severity === monaco.MarkerSeverity.Error ? '错误' : x.severity === monaco.MarkerSeverity.Warning ? '警告' : '提示';
256
+ const icon = x.severity === monaco.MarkerSeverity.Error ? '⛔' : x.severity === monaco.MarkerSeverity.Warning ? '⚠️' : 'ℹ️';
257
+ return '**' + icon + ' ' + sevName + '** (L' + x.startLineNumber + ':' + x.startColumn + ') \n' + x.message;
258
+ }).join('\n\n---\n\n');
259
+ return {
260
+ contents: [{ value: '#### 飞虹 Code 诊断\n\n' + md, isTrusted: true }],
261
+ range: new monaco.Range(position.lineNumber, 1, position.lineNumber, 1),
262
+ };
263
+ },
264
+ });
265
+ hoverDisp; // 引用保持存活(Monaco 内部维护)
266
+
267
+ // 防抖 + 单飞,避免编辑时高频请求
268
+ let timer = null;
269
+ let inflight = false;
270
+ let queued = false;
271
+ const run = async function () {
272
+ if (inflight) { queued = true; return; }
273
+ const editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null;
274
+ if (!editor || editor.isDisposed?.()) return;
275
+ const model = editor.getModel();
276
+ if (!model) return;
277
+ inflight = true;
278
+ try {
279
+ const filePath = model.uri.path || 'untitled';
280
+ const content = model.getValue();
281
+ const result = await fetchFn({ filePath, content });
282
+ if (!result || !Array.isArray(result.diagnostics)) {
283
+ monaco.editor.setModelMarkers(model, 'fhcode', []);
284
+ return;
285
+ }
286
+ const markers = result.diagnostics.map((d) => {
287
+ const sev = d.severity === 1 || d.severity === 'error'
288
+ ? monaco.MarkerSeverity.Error
289
+ : d.severity === 2 || d.severity === 'warning'
290
+ ? monaco.MarkerSeverity.Warning
291
+ : monaco.MarkerSeverity.Info;
292
+ return {
293
+ severity: sev,
294
+ message: d.message || '',
295
+ startLineNumber: d.line ?? 1,
296
+ startColumn: d.column ?? 1,
297
+ endLineNumber: d.endLine ?? (d.line ?? 1),
298
+ endColumn: d.endColumn ?? (d.column ?? 1) + (d.message?.length || 8),
299
+ };
300
+ });
301
+ monaco.editor.setModelMarkers(model, 'fhcode', markers);
302
+ } catch {
303
+ /* 诊断失败静默(不阻塞编辑) */
304
+ } finally {
305
+ inflight = false;
306
+ if (queued) { queued = false; timer = setTimeout(run, 200); }
307
+ }
308
+ };
309
+ const schedule = function () {
310
+ clearTimeout(timer);
311
+ timer = setTimeout(run, 350);
312
+ };
313
+ // 绑定现有编辑器(createEditor 后由 ui 层调用 attachDiagnostics 触发监听)
314
+ const editor = typeof getActiveEditor === 'function' ? getActiveEditor() : null;
315
+ if (editor && !editor.__fhDiagnosticsBound) {
316
+ editor.__fhDiagnosticsBound = true;
317
+ editor.onDidChangeModelContent(schedule);
318
+ editor.onDidChangeModel(() => schedule());
319
+ }
320
+ return { run, schedule };
321
+ });
322
+ }
323
+
324
+ /**
325
+ * P6-1: 补全接受后的 lint 反馈——把 /api/lint 结果追加为编辑器波浪线(owner: fhcode-lint)
326
+ * @param {Array} issues - [{severity, line, column, message}]
327
+ */
328
+ function showLintFeedback(issues) {
329
+ initMonaco().then((monaco) => {
330
+ const editor = activeEditor;
331
+ if (!editor || editor.isDisposed?.()) return;
332
+ const model = editor.getModel();
333
+ if (!model) return;
334
+ if (!Array.isArray(issues) || issues.length === 0) {
335
+ monaco.editor.setModelMarkers(model, 'fhcode-lint', []);
336
+ return;
337
+ }
338
+ const markers = issues.map((d) => ({
339
+ severity: d.severity === 1 ? monaco.MarkerSeverity.Error : d.severity === 2 ? monaco.MarkerSeverity.Warning : monaco.MarkerSeverity.Info,
340
+ message: '补全校验:' + (d.message || ''),
341
+ startLineNumber: d.line ?? 1,
342
+ startColumn: d.column ?? 1,
343
+ endLineNumber: d.line ?? 1,
344
+ endColumn: (d.column ?? 1) + (d.message?.length || 20),
345
+ }));
346
+ monaco.editor.setModelMarkers(model, 'fhcode-lint', markers);
347
+ });
348
+ }
349
+
350
+ /** 暴露全局 API */
351
+ global.FHMonaco = {
352
+ init: initMonaco,
353
+ createEditor: createEditor,
354
+ getEditor: getEditor,
355
+ disposeEditor: disposeEditor,
356
+ detectLanguage: detectLanguage,
357
+ getActiveEditor: getActiveEditor,
358
+ registerInlineCompletions: registerInlineCompletions,
359
+ registerCompletionItems: registerCompletionItems,
360
+ registerDiagnostics: registerDiagnostics,
361
+ showLintFeedback: showLintFeedback,
362
+ };
363
+ })(window);