feihong-code 7.5.0 → 8.0.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 (367) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +36 -22
  2. package/.github/ISSUE_TEMPLATE/config.yml +10 -13
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +38 -13
  4. package/.github/PULL_REQUEST_TEMPLATE.md +65 -30
  5. package/.github/workflows/ci.yml +193 -180
  6. package/.github/workflows/release.yml +203 -200
  7. package/.github/workflows/swebench-real.yml +84 -0
  8. package/CHANGELOG.md +117 -94
  9. package/CONTRIBUTING.md +61 -5
  10. package/README.md +636 -609
  11. package/README.self-evolve.md +279 -274
  12. package/dist/agent/change-manager.js +1 -1
  13. package/dist/agent/code-rag.js +1 -1
  14. package/dist/agent/code-review.js +1 -1
  15. package/dist/agent/code-writer.js +1 -1
  16. package/dist/agent/completion-postprocess.js +1 -1
  17. package/dist/agent/context-compactor.js +11 -0
  18. package/dist/agent/context-compactor.js.map +1 -1
  19. package/dist/agent/custom-agent.js +52 -52
  20. package/dist/agent/design-to-code.js +40 -40
  21. package/dist/agent/experience.js +1 -1
  22. package/dist/agent/layered-memory.js +1 -1
  23. package/dist/agent/lint.js +1 -1
  24. package/dist/agent/multi-agent.js +44 -44
  25. package/dist/agent/orchestrator.js +93 -18
  26. package/dist/agent/orchestrator.js.map +1 -1
  27. package/dist/agent/parallel-orchestrator.js +1 -1
  28. package/dist/agent/planner.js +8 -3
  29. package/dist/agent/planner.js.map +1 -1
  30. package/dist/agent/prompts.js +2 -2
  31. package/dist/agent/quality-gate.js +1 -1
  32. package/dist/agent/repo-context.js +1 -1
  33. package/dist/agent/repo-reader.js +1 -1
  34. package/dist/agent/repo-underwriter.js +1 -1
  35. package/dist/agent/self-correction.js +1 -1
  36. package/dist/agent/self-heal.js +5 -0
  37. package/dist/agent/self-heal.js.map +1 -1
  38. package/dist/agent/self-improver.js +1 -1
  39. package/dist/agent/subagent-summary.js +1 -1
  40. package/dist/agent/subagent.js +1 -1
  41. package/dist/agent/swe-agent.js +1 -1
  42. package/dist/agent/swe-verifier.js +1 -1
  43. package/dist/agent/symbol-index.js +1 -1
  44. package/dist/agent/team.js +1 -1
  45. package/dist/agent/type-checker.js +1 -1
  46. package/dist/cli/commands.js +7 -0
  47. package/dist/cli/commands.js.map +1 -1
  48. package/dist/cli/index.js +57 -2
  49. package/dist/cli/index.js.map +1 -1
  50. package/dist/cli/repl.js +1 -1
  51. package/dist/cli/run.js +40 -3
  52. package/dist/cli/run.js.map +1 -1
  53. package/dist/cli/self-evolve-cli.js +168 -0
  54. package/dist/cli/tui-run.js +1 -1
  55. package/dist/cli/tui.js +1 -1
  56. package/dist/cli/version.js +3 -3
  57. package/dist/cli/version.js.map +1 -1
  58. package/dist/enterprise/audit.js +1 -1
  59. package/dist/enterprise/index.js +1 -1
  60. package/dist/enterprise/policy.js +1 -1
  61. package/dist/enterprise/quota.js +1 -1
  62. package/dist/enterprise/tenant.js +1 -1
  63. package/dist/harness/executor.js +1 -1
  64. package/dist/harness/index.js +1 -1
  65. package/dist/harness/loader.js +1 -1
  66. package/dist/harness/types.js +1 -1
  67. package/dist/harness/verifier.js +52 -12
  68. package/dist/harness/verifier.js.map +1 -1
  69. package/dist/hello.js +14 -0
  70. package/dist/hello.js.map +1 -0
  71. package/dist/integrations/feishu-bridge.js +348 -0
  72. package/dist/integrations/feishu-bridge.js.map +1 -0
  73. package/dist/integrations/github-mcp.js +137 -0
  74. package/dist/integrations/github-mcp.js.map +1 -0
  75. package/dist/integrations/wechat-bridge.js +499 -0
  76. package/dist/integrations/wechat-bridge.js.map +1 -0
  77. package/dist/integrations/yuanbao-bridge.js +326 -0
  78. package/dist/integrations/yuanbao-bridge.js.map +1 -0
  79. package/dist/lsp/lsp-client.js +1 -1
  80. package/dist/memory/honcho-store.js +231 -0
  81. package/dist/memory/honcho-store.js.map +1 -0
  82. package/dist/models/model-router.js +1 -1
  83. package/dist/models/model.dto.js +1 -1
  84. package/dist/models/providers/ollama.provider.js +1 -1
  85. package/dist/models/providers/openai-compatible.provider.js +1 -1
  86. package/dist/plugins/plugin-loader.js +1 -1
  87. package/dist/runtime/event-log.js +1 -1
  88. package/dist/runtime/git.js +1 -1
  89. package/dist/runtime/hooks.js +71 -4
  90. package/dist/runtime/hooks.js.map +1 -1
  91. package/dist/runtime/session-persist.js +1 -1
  92. package/dist/runtime/worktree.js +1 -1
  93. package/dist/self-evolve/hook.ts +80 -0
  94. package/dist/self-evolve/manager.d.ts +8 -0
  95. package/dist/self-evolve/manager.js +517 -401
  96. package/dist/self-evolve/self-heal-scheduler.js +160 -0
  97. package/dist/self-evolve/self-heal-scheduler.js.map +1 -0
  98. package/dist/shared/concurrency.js +1 -1
  99. package/dist/shared/config.js +4 -2
  100. package/dist/shared/config.js.map +1 -1
  101. package/dist/shared/errors.js +1 -1
  102. package/dist/shared/i18n.js +1 -1
  103. package/dist/shared/i18n.js.map +1 -1
  104. package/dist/shared/log-rotator.js +238 -0
  105. package/dist/shared/log-rotator.js.map +1 -0
  106. package/dist/shared/secure-store.js +12 -5
  107. package/dist/shared/secure-store.js.map +1 -1
  108. package/dist/shared/sqlite-store.js +512 -0
  109. package/dist/shared/sqlite-store.js.map +1 -0
  110. package/dist/shared/types.js +1 -1
  111. package/dist/skills/goal.js +1 -1
  112. package/dist/skills/grill.js +1 -1
  113. package/dist/skills/plan.js +1 -1
  114. package/dist/skills/pua-hooks.js +273 -0
  115. package/dist/skills/pua-hooks.js.map +1 -0
  116. package/dist/skills/self-heal.js +9 -3
  117. package/dist/skills/self-heal.js.map +1 -1
  118. package/dist/skills/skill-loader.js +1 -1
  119. package/dist/skills/skill-market.js +84 -8
  120. package/dist/skills/skill-market.js.map +1 -1
  121. package/dist/tools/analysis/code-analyzer.js +1 -1
  122. package/dist/tools/docker-sandbox.js +212 -0
  123. package/dist/tools/docker-sandbox.js.map +1 -0
  124. package/dist/tools/file/edit.tool.js +18 -3
  125. package/dist/tools/file/edit.tool.js.map +1 -1
  126. package/dist/tools/file/list.tool.js +1 -1
  127. package/dist/tools/file/read.tool.js +1 -1
  128. package/dist/tools/file/write.tool.js +1 -1
  129. package/dist/tools/generator/code-generator.js +1 -1
  130. package/dist/tools/generator/test-generator.js +1 -1
  131. package/dist/tools/index.js +1 -1
  132. package/dist/tools/mcp/index.js +1 -1
  133. package/dist/tools/mcp/mcp-client.js +1 -1
  134. package/dist/tools/safe-path.js +1 -1
  135. package/dist/tools/search/grep.tool.js +1 -1
  136. package/dist/tools/shell/exec.js +1 -1
  137. package/dist/tools/shell/run-shell.tool.js +1 -1
  138. package/dist/tools/skills/load-skill.tool.js +1 -1
  139. package/dist/tools/tool.registry.js +10 -1
  140. package/dist/tools/tool.registry.js.map +1 -1
  141. package/dist/tools/verify/build-check.tool.js +1 -1
  142. package/dist/tools/verify/test-run.tool.js +1 -1
  143. package/dist/tools/web/web.tool.js +1 -1
  144. package/dist/voice/voice-programming.js +32 -6
  145. package/dist/voice/voice-programming.js.map +1 -1
  146. package/dist/web/auth.js +34 -2
  147. package/dist/web/auth.js.map +1 -1
  148. package/dist/web/channels.js +1 -1
  149. package/dist/web/public/css/style.css +1751 -1724
  150. package/dist/web/public/favicon.svg +11 -0
  151. package/dist/web/public/index.html +1246 -1242
  152. package/dist/web/public/js/api.js +558 -555
  153. package/dist/web/public/js/app.js +2233 -2210
  154. package/dist/web/public/js/mock-api.js +259 -234
  155. package/dist/web/public/js/monaco-editor.js +363 -363
  156. package/dist/web/public/js/ui.js +2217 -2251
  157. package/dist/web/public/js/utils.js +214 -214
  158. package/dist/web/public/manifest.json +59 -59
  159. package/dist/web/public/robots.txt +14 -0
  160. package/dist/web/public/service-worker.js +149 -173
  161. package/dist/web/public/vendor/monaco/vs/abap-D-t0cyap.js +1 -0
  162. package/dist/web/public/vendor/monaco/vs/apex-CcIm7xu6.js +1 -0
  163. package/dist/web/public/vendor/monaco/vs/assets/css.worker-URu8fCFR.js +97 -0
  164. package/dist/web/public/vendor/monaco/vs/assets/editor.worker-lj3bdIIn.js +30 -0
  165. package/dist/web/public/vendor/monaco/vs/assets/editorWebWorkerMain-CA_vMoUU.js +30 -0
  166. package/dist/web/public/vendor/monaco/vs/assets/html.worker-D1SL3iM8.js +474 -0
  167. package/dist/web/public/vendor/monaco/vs/assets/json.worker-CoJx_OPf.js +62 -0
  168. package/dist/web/public/vendor/monaco/vs/assets/ts.worker-BWKtMYOk.js +67722 -0
  169. package/dist/web/public/vendor/monaco/vs/azcli-BA0tQDCg.js +1 -0
  170. package/dist/web/public/vendor/monaco/vs/basic-languages/monaco.contribution.js +1 -0
  171. package/dist/web/public/vendor/monaco/vs/bat-C397hTD6.js +1 -0
  172. package/dist/web/public/vendor/monaco/vs/bicep-DF5aW17k.js +2 -0
  173. package/dist/web/public/vendor/monaco/vs/cameligo-plsz8qhj.js +1 -0
  174. package/dist/web/public/vendor/monaco/vs/clojure-Y2auQMzK.js +1 -0
  175. package/dist/web/public/vendor/monaco/vs/coffee-Bu45yuWE.js +1 -0
  176. package/dist/web/public/vendor/monaco/vs/cpp-CkKPQIni.js +1 -0
  177. package/dist/web/public/vendor/monaco/vs/csharp-CX28MZyh.js +1 -0
  178. package/dist/web/public/vendor/monaco/vs/csp-D8uWnyxW.js +1 -0
  179. package/dist/web/public/vendor/monaco/vs/css-CaeNmE3S.js +3 -0
  180. package/dist/web/public/vendor/monaco/vs/css.worker-CyhWkhHo.js +1 -0
  181. package/dist/web/public/vendor/monaco/vs/cssMode-CV6Ay48H.js +1 -0
  182. package/dist/web/public/vendor/monaco/vs/cypher-DVThT8BS.js +1 -0
  183. package/dist/web/public/vendor/monaco/vs/dart-CmGfCvrO.js +1 -0
  184. package/dist/web/public/vendor/monaco/vs/dockerfile-CZqqYdch.js +1 -0
  185. package/dist/web/public/vendor/monaco/vs/ecl-30fUercY.js +1 -0
  186. package/dist/web/public/vendor/monaco/vs/editor/editor.main.css +1 -0
  187. package/dist/web/public/vendor/monaco/vs/editor/editor.main.js +1 -0
  188. package/dist/web/public/vendor/monaco/vs/editor/editor.worker.js +1 -0
  189. package/dist/web/public/vendor/monaco/vs/editor-KLE6jdfb.js +831 -0
  190. package/dist/web/public/vendor/monaco/vs/editor.js +1 -0
  191. package/dist/web/public/vendor/monaco/vs/editorWorkerHost-fVE1cjcC.js +35 -0
  192. package/dist/web/public/vendor/monaco/vs/elixir-xjPaIfzF.js +1 -0
  193. package/dist/web/public/vendor/monaco/vs/flow9-DqtmStfK.js +1 -0
  194. package/dist/web/public/vendor/monaco/vs/freemarker2-FWreY7v7.js +3 -0
  195. package/dist/web/public/vendor/monaco/vs/fsharp-BOMdg4U1.js +1 -0
  196. package/dist/web/public/vendor/monaco/vs/go-D_hbi-Jt.js +1 -0
  197. package/dist/web/public/vendor/monaco/vs/graphql-CKUU4kLG.js +1 -0
  198. package/dist/web/public/vendor/monaco/vs/handlebars-CZi4pHCH.js +1 -0
  199. package/dist/web/public/vendor/monaco/vs/hcl-DTaboeZW.js +1 -0
  200. package/dist/web/public/vendor/monaco/vs/html-j_7ZTNRU.js +1 -0
  201. package/dist/web/public/vendor/monaco/vs/html.worker-CA3iAimZ.js +1 -0
  202. package/dist/web/public/vendor/monaco/vs/htmlMode-27by_KM4.js +1 -0
  203. package/dist/web/public/vendor/monaco/vs/index-049xrXrp.js +1 -0
  204. package/dist/web/public/vendor/monaco/vs/index-CBVt3dzv.js +5 -0
  205. package/dist/web/public/vendor/monaco/vs/index.js +1 -0
  206. package/dist/web/public/vendor/monaco/vs/ini-CsNwO04R.js +1 -0
  207. package/dist/web/public/vendor/monaco/vs/initialize-DL0l1TGY.js +1 -0
  208. package/dist/web/public/vendor/monaco/vs/java-CI4ZMsH9.js +1 -0
  209. package/dist/web/public/vendor/monaco/vs/javascript-DTJl4Jn1.js +1 -0
  210. package/dist/web/public/vendor/monaco/vs/json.worker-BizpAl9O.js +1 -0
  211. package/dist/web/public/vendor/monaco/vs/jsonMode-DLUiMUrI.js +1 -0
  212. package/dist/web/public/vendor/monaco/vs/julia-BwzEvaQw.js +1 -0
  213. package/dist/web/public/vendor/monaco/vs/kotlin-IUYPiTV8.js +1 -0
  214. package/dist/web/public/vendor/monaco/vs/language/css/css.worker.js +66 -0
  215. package/dist/web/public/vendor/monaco/vs/language/css/monaco.contribution.js +1 -0
  216. package/dist/web/public/vendor/monaco/vs/language/html/html.worker.js +443 -0
  217. package/dist/web/public/vendor/monaco/vs/language/html/monaco.contribution.js +1 -0
  218. package/dist/web/public/vendor/monaco/vs/language/json/json.worker.js +17 -0
  219. package/dist/web/public/vendor/monaco/vs/language/json/monaco.contribution.js +1 -0
  220. package/dist/web/public/vendor/monaco/vs/language/typescript/monaco.contribution.js +1 -0
  221. package/dist/web/public/vendor/monaco/vs/language/typescript/ts.worker.js +67693 -0
  222. package/dist/web/public/vendor/monaco/vs/less-C0eDYdqa.js +2 -0
  223. package/dist/web/public/vendor/monaco/vs/lexon-iON-Kj97.js +1 -0
  224. package/dist/web/public/vendor/monaco/vs/liquid-CLJYelW6.js +1 -0
  225. package/dist/web/public/vendor/monaco/vs/loader.js +1368 -0
  226. package/dist/web/public/vendor/monaco/vs/lspLanguageFeatures-BIkJOWLw.js +2 -0
  227. package/dist/web/public/vendor/monaco/vs/lua-DtygF91M.js +1 -0
  228. package/dist/web/public/vendor/monaco/vs/m3-CsR4AuFi.js +1 -0
  229. package/dist/web/public/vendor/monaco/vs/main-BEx-Fmlo.js +15 -0
  230. package/dist/web/public/vendor/monaco/vs/main-DsK8pnKg.js +3 -0
  231. package/dist/web/public/vendor/monaco/vs/markdown-C_rD0bIw.js +1 -0
  232. package/dist/web/public/vendor/monaco/vs/mdx-CpzZIPHF.js +1 -0
  233. package/dist/web/public/vendor/monaco/vs/mips-CiYP61RB.js +1 -0
  234. package/dist/web/public/vendor/monaco/vs/monaco.contribution-9cKT3C7t.js +1 -0
  235. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BE88ZNGY.js +1 -0
  236. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BPhsneLd.js +1 -0
  237. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BgRy6xDf.js +1 -0
  238. package/dist/web/public/vendor/monaco/vs/msdax-C38-sJlp.js +1 -0
  239. package/dist/web/public/vendor/monaco/vs/mysql-CdtbpvbG.js +1 -0
  240. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.d.ts +1 -0
  241. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.js +9 -0
  242. package/dist/web/public/vendor/monaco/vs/nls/lang/de.d.ts +1 -0
  243. package/dist/web/public/vendor/monaco/vs/nls/lang/de.js +9 -0
  244. package/dist/web/public/vendor/monaco/vs/nls/lang/es.d.ts +1 -0
  245. package/dist/web/public/vendor/monaco/vs/nls/lang/es.js +9 -0
  246. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.d.ts +1 -0
  247. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.js +9 -0
  248. package/dist/web/public/vendor/monaco/vs/nls/lang/it.d.ts +1 -0
  249. package/dist/web/public/vendor/monaco/vs/nls/lang/it.js +9 -0
  250. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.d.ts +1 -0
  251. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.js +9 -0
  252. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.d.ts +1 -0
  253. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.js +9 -0
  254. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.d.ts +1 -0
  255. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.js +9 -0
  256. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.d.ts +1 -0
  257. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.js +9 -0
  258. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.d.ts +1 -0
  259. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.js +9 -0
  260. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.d.ts +1 -0
  261. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.js +9 -0
  262. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.d.ts +1 -0
  263. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.js +9 -0
  264. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.d.ts +1 -0
  265. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.js +9 -0
  266. package/dist/web/public/vendor/monaco/vs/nls.messages-loader.js +1 -0
  267. package/dist/web/public/vendor/monaco/vs/objective-c-CntZFaHX.js +1 -0
  268. package/dist/web/public/vendor/monaco/vs/pascal-r6kuqfl_.js +1 -0
  269. package/dist/web/public/vendor/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
  270. package/dist/web/public/vendor/monaco/vs/perl-DABw_TcH.js +1 -0
  271. package/dist/web/public/vendor/monaco/vs/pgsql-me_jFXeX.js +1 -0
  272. package/dist/web/public/vendor/monaco/vs/php-D_kh-9LK.js +1 -0
  273. package/dist/web/public/vendor/monaco/vs/pla-VfZjczW0.js +1 -0
  274. package/dist/web/public/vendor/monaco/vs/postiats-BBSzz8Pk.js +1 -0
  275. package/dist/web/public/vendor/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
  276. package/dist/web/public/vendor/monaco/vs/powershell-B-7ap1zc.js +1 -0
  277. package/dist/web/public/vendor/monaco/vs/protobuf-BmtuEB1A.js +2 -0
  278. package/dist/web/public/vendor/monaco/vs/pug-BRpRNeEb.js +1 -0
  279. package/dist/web/public/vendor/monaco/vs/python-CqWUUgfu.js +1 -0
  280. package/dist/web/public/vendor/monaco/vs/qsharp-BzsFaUU9.js +1 -0
  281. package/dist/web/public/vendor/monaco/vs/r-f8dDdrp4.js +1 -0
  282. package/dist/web/public/vendor/monaco/vs/razor-hok5y9Km.js +1 -0
  283. package/dist/web/public/vendor/monaco/vs/redis-fvZQY4PI.js +1 -0
  284. package/dist/web/public/vendor/monaco/vs/redshift-45Et0LQi.js +1 -0
  285. package/dist/web/public/vendor/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
  286. package/dist/web/public/vendor/monaco/vs/ruby-CZO8zYTz.js +1 -0
  287. package/dist/web/public/vendor/monaco/vs/rust-Bfetafyc.js +1 -0
  288. package/dist/web/public/vendor/monaco/vs/sb-3GYllVck.js +1 -0
  289. package/dist/web/public/vendor/monaco/vs/scala-foMgrKo1.js +1 -0
  290. package/dist/web/public/vendor/monaco/vs/scheme-CHdMtr7p.js +1 -0
  291. package/dist/web/public/vendor/monaco/vs/scss-C1cmLt9V.js +3 -0
  292. package/dist/web/public/vendor/monaco/vs/shell-ClXCKCEW.js +1 -0
  293. package/dist/web/public/vendor/monaco/vs/solidity-MZ6ExpPy.js +1 -0
  294. package/dist/web/public/vendor/monaco/vs/sophia-DWkuSsPQ.js +1 -0
  295. package/dist/web/public/vendor/monaco/vs/sparql-AUGFYSyk.js +1 -0
  296. package/dist/web/public/vendor/monaco/vs/sql-32GpJSV2.js +1 -0
  297. package/dist/web/public/vendor/monaco/vs/st-CuDFIVZ_.js +1 -0
  298. package/dist/web/public/vendor/monaco/vs/swift-t-PfMj7W.js +1 -0
  299. package/dist/web/public/vendor/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
  300. package/dist/web/public/vendor/monaco/vs/tcl-D74tq1nH.js +1 -0
  301. package/dist/web/public/vendor/monaco/vs/toggleHighContrast-qGX7E9o7.js +61 -0
  302. package/dist/web/public/vendor/monaco/vs/ts.worker-2QLmBukE.js +1 -0
  303. package/dist/web/public/vendor/monaco/vs/tsMode-B0S_kp2q.js +11 -0
  304. package/dist/web/public/vendor/monaco/vs/twig-C6taOxMV.js +1 -0
  305. package/dist/web/public/vendor/monaco/vs/typescript-_2t_511t.js +1 -0
  306. package/dist/web/public/vendor/monaco/vs/typespec-8OfoLt6R.js +1 -0
  307. package/dist/web/public/vendor/monaco/vs/vb-Dyb2648j.js +1 -0
  308. package/dist/web/public/vendor/monaco/vs/wgsl-BhLXMOR0.js +298 -0
  309. package/dist/web/public/vendor/monaco/vs/workers-BBttULjf.js +1 -0
  310. package/dist/web/public/vendor/monaco/vs/xml-cZjNDqDT.js +1 -0
  311. package/dist/web/public/vendor/monaco/vs/yaml-A1fOIdH6.js +1 -0
  312. package/dist/web/server.js +151 -16
  313. package/dist/web/server.js.map +1 -1
  314. package/dist/web/task-queue.js +6 -21
  315. package/dist/web/task-queue.js.map +1 -1
  316. package/dist/web/web-config.js +143 -0
  317. package/dist/web/web-config.js.map +1 -0
  318. package/docs/API.md +827 -0
  319. package/docs/App/344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +1 -1
  320. package/docs/App/346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +1 -1
  321. package/docs/BENCHMARK_REPORT_en.md +386 -386
  322. package/docs/BENCHMARK_REPORT_zh.md +386 -386
  323. package/docs/DPA.md +65 -63
  324. 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
  325. package/docs/Deployment_Guide_EN.md +1 -1
  326. package/docs/PROJECT-ANALYSIS-AND-TEST.md +721 -0
  327. package/docs/SECURITY_WHITEPAPER.md +2 -2
  328. package/docs/SELF-EVOLVE-GUIDE.md +1 -1
  329. package/docs/SWE_BENCH_REPORT.md +73 -55
  330. package/docs/TECHNICAL-SPECIFICATION.md +746 -0
  331. package/docs/TECHNICAL_SPEC_en.md +292 -292
  332. package/docs/TECHNICAL_SPEC_zh.md +292 -292
  333. package/docs/Technical_Manual_EN.md +1 -1
  334. package/docs/UPDATE_NOTES_en.md +159 -159
  335. package/docs/UPDATE_NOTES_zh.md +159 -159
  336. package/docs/UPGRADE-v7.9.0.md +291 -0
  337. package/docs/UPGRADE-v8.0.0.md +237 -0
  338. package/docs/UPGRADE_7.2.0.md +309 -309
  339. package/docs/UPGRADE_GUIDE_7_5.md +86 -86
  340. package/docs/UPGRADE_GUIDE_7_6.md +153 -0
  341. package/docs/User_Manual_EN.md +1 -1
  342. package/docs/VOLTAGENT_SKILLS_CATALOG.md +95 -0
  343. package/docs/error-codes.md +1 -1
  344. package/docs/geo-feihong-code.html +391 -391
  345. package/docs//344/272/247/345/223/201/345/274/200/345/217/221/346/226/207/346/241/243.md +5 -3
  346. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246-v8.0.0.md +922 -0
  347. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +140 -231
  348. 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
  349. 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
  350. 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
  351. 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
  352. package/docs//345/256/211/345/205/250/347/231/275/347/232/256/344/271/246_v7.2.0.md +84 -82
  353. package/docs//346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +240 -149
  354. package/docs//351/203/250/347/275/262/350/257/264/346/230/216/344/271/246.md +2 -2
  355. package/electron/main.js +404 -404
  356. package/package.json +12 -5
  357. package/templates/skills/api-design/SKILL.md +1 -1
  358. package/templates/skills/code-review/SKILL.md +1 -1
  359. package/templates/skills/dependency-upgrade/SKILL.md +1 -1
  360. package/templates/skills/doc-gen/SKILL.md +1 -1
  361. package/templates/skills/git-flow/SKILL.md +1 -1
  362. package/templates/skills/onboarding/SKILL.md +1 -1
  363. package/templates/skills/performance/SKILL.md +1 -1
  364. package/templates/skills/refactor/SKILL.md +1 -1
  365. package/templates/skills/security-audit/SKILL.md +1 -1
  366. package/templates/skills/test-gen/SKILL.md +1 -1
  367. package/tool-schema.json +197 -197
package/electron/main.js CHANGED
@@ -1,404 +1,404 @@
1
- /**
2
- * 飞虹 Code Electron 桌面版主进程(简化稳定版)
3
- * 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
4
- */
5
-
6
- const { app, BrowserWindow, shell, Tray, Menu, ipcMain, dialog, clipboard, Notification, session, desktopCapturer, screen } = require('electron');
7
- const { spawn } = require('child_process');
8
- const { existsSync } = require('fs');
9
- const { join } = require('path');
10
- const http = require('http');
11
-
12
- // 禁用安全警告
13
- process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
14
-
15
- // 配置
16
- const PORT = parseInt(process.env.FH_WEB_PORT || '8081');
17
- const isDev = !app.isPackaged;
18
-
19
- // 全局变量
20
- let mainWindow = null;
21
- let serverProcess = null;
22
- let tray = null;
23
-
24
- // 获取应用根目录
25
- function getAppPath() {
26
- if (isDev) return join(__dirname, '..');
27
- return process.resourcesPath ? join(process.resourcesPath, 'app') : app.getAppPath();
28
- }
29
- const APP_PATH = getAppPath();
30
-
31
- /**
32
- * 等待服务器就绪
33
- */
34
- function waitForServer(port, timeoutMs) {
35
- return new Promise((resolve, reject) => {
36
- const startTime = Date.now();
37
- const check = () => {
38
- const req = http.get(`http://127.0.0.1:${port}/api/health`, (res) => {
39
- if (res.statusCode === 200) {
40
- resolve();
41
- } else {
42
- res.resume();
43
- retry();
44
- }
45
- });
46
- req.on('error', () => retry());
47
- req.setTimeout(2000, () => { req.destroy(); retry(); });
48
- };
49
- const retry = () => {
50
- if (Date.now() - startTime > timeoutMs) {
51
- reject(new Error('服务器启动超时'));
52
- } else {
53
- setTimeout(check, 500);
54
- }
55
- };
56
- check();
57
- });
58
- }
59
-
60
- /**
61
- * 启动内置 Web 服务器
62
- */
63
- function startServer() {
64
- return new Promise((resolve, reject) => {
65
- const serverEntry = join(APP_PATH, 'dist', 'cli', 'index.js');
66
- if (!existsSync(serverEntry)) {
67
- reject(new Error('未找到服务器入口文件,请先运行 npm run build'));
68
- return;
69
- }
70
-
71
- console.log('[Electron] 启动服务器,端口: ' + PORT);
72
-
73
- let serverLog = '';
74
- let started = false;
75
-
76
- serverProcess = spawn('node', [serverEntry, 'serve'], {
77
- cwd: APP_PATH,
78
- env: { ...process.env, FH_WEB_PORT: String(PORT) },
79
- stdio: ['ignore', 'pipe', 'pipe']
80
- });
81
-
82
- serverProcess.stdout.on('data', (data) => {
83
- const text = data.toString();
84
- serverLog += text;
85
- console.log('[Server] ' + text.trim());
86
- });
87
-
88
- serverProcess.stderr.on('data', (data) => {
89
- const text = data.toString();
90
- serverLog += text;
91
- console.error('[Server Error] ' + text.trim());
92
- });
93
-
94
- serverProcess.on('error', (err) => {
95
- if (!started) reject(new Error('启动服务器失败: ' + err.message));
96
- });
97
-
98
- serverProcess.on('exit', (code) => {
99
- console.log('[Electron] 服务器退出,代码: ' + code);
100
- serverProcess = null;
101
- if (!started) {
102
- reject(new Error('服务器启动失败,退出代码: ' + code + '\n\n日志:\n' + serverLog.slice(-2000)));
103
- }
104
- });
105
-
106
- // 等待服务器就绪
107
- waitForServer(PORT, 60000).then(() => {
108
- started = true;
109
- console.log('[Electron] 服务器已就绪');
110
- resolve();
111
- }).catch((err) => {
112
- if (!started) reject(new Error(err.message + '\n\n服务器日志:\n' + serverLog.slice(-2000)));
113
- });
114
- });
115
- }
116
-
117
- /**
118
- * 创建主窗口
119
- */
120
- function createWindow() {
121
- mainWindow = new BrowserWindow({
122
- width: 1400,
123
- height: 900,
124
- minWidth: 1024,
125
- minHeight: 680,
126
- title: '飞虹 Code',
127
- webPreferences: {
128
- preload: join(__dirname, 'preload.js'),
129
- contextIsolation: true,
130
- nodeIntegration: false
131
- },
132
- show: false,
133
- backgroundColor: '#1a1a2e'
134
- });
135
-
136
- const url = `http://127.0.0.1:${PORT}/`;
137
- console.log('[Electron] 加载页面: ' + url);
138
- mainWindow.loadURL(url);
139
-
140
- mainWindow.once('ready-to-show', () => {
141
- mainWindow.show();
142
- });
143
-
144
- // 外部链接用系统浏览器打开
145
- mainWindow.webContents.setWindowOpenHandler(({ url }) => {
146
- shell.openExternal(url);
147
- return { action: 'deny' };
148
- });
149
-
150
- // 关闭时最小化到托盘
151
- mainWindow.on('close', (e) => {
152
- if (!app.isQuitting) {
153
- e.preventDefault();
154
- mainWindow.hide();
155
- }
156
- });
157
-
158
- mainWindow.on('closed', () => {
159
- mainWindow = null;
160
- });
161
- }
162
-
163
- /**
164
- * 创建系统托盘
165
- */
166
- function createTray() {
167
- try {
168
- const iconPath = join(__dirname, 'icon.png');
169
- let trayIcon;
170
- if (existsSync(iconPath)) {
171
- trayIcon = require('electron').nativeImage.createFromPath(iconPath);
172
- } else {
173
- trayIcon = require('electron').nativeImage.createEmpty();
174
- }
175
-
176
- tray = new Tray(trayIcon);
177
- tray.setToolTip('飞虹 Code');
178
-
179
- const contextMenu = Menu.buildFromTemplate([
180
- { label: '显示主窗口', click: () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } } },
181
- { type: 'separator' },
182
- { label: '退出', click: () => { app.isQuitting = true; app.quit(); } }
183
- ]);
184
- tray.setContextMenu(contextMenu);
185
-
186
- tray.on('click', () => {
187
- if (mainWindow) {
188
- if (mainWindow.isVisible()) mainWindow.hide();
189
- else { mainWindow.show(); mainWindow.focus(); }
190
- }
191
- });
192
- } catch (e) {
193
- console.warn('[Electron] 创建托盘失败: ' + e.message);
194
- }
195
- }
196
-
197
- /**
198
- * 创建应用菜单(关键:没有菜单会导致复制粘贴等快捷键失效)
199
- */
200
- function createMenu() {
201
- const template = [
202
- {
203
- label: '文件',
204
- submenu: [
205
- { label: '刷新', role: 'reload' },
206
- { label: '强制刷新', role: 'forceReload' },
207
- { type: 'separator' },
208
- { label: '退出', role: 'quit' }
209
- ]
210
- },
211
- {
212
- label: '编辑',
213
- submenu: [
214
- { label: '撤销', role: 'undo' },
215
- { label: '重做', role: 'redo' },
216
- { type: 'separator' },
217
- { label: '剪切', role: 'cut' },
218
- { label: '复制', role: 'copy' },
219
- { label: '粘贴', role: 'paste' },
220
- { label: '全选', role: 'selectAll' }
221
- ]
222
- },
223
- {
224
- label: '视图',
225
- submenu: [
226
- { label: '放大', role: 'zoomIn' },
227
- { label: '缩小', role: 'zoomOut' },
228
- { label: '重置缩放', role: 'resetZoom' },
229
- { type: 'separator' },
230
- { label: '全屏', role: 'togglefullscreen' },
231
- { label: '开发者工具', role: 'toggleDevTools' }
232
- ]
233
- },
234
- {
235
- label: '窗口',
236
- submenu: [
237
- { label: '最小化', role: 'minimize' },
238
- { label: '关闭', role: 'close' }
239
- ]
240
- },
241
- {
242
- label: '帮助',
243
- submenu: [
244
- { label: '关于飞虹 Code', click: () => {
245
- dialog.showMessageBox(mainWindow, {
246
- type: 'info',
247
- title: '关于飞虹 Code',
248
- message: '飞虹 Code v0.6.1',
249
- detail: '终端 AI 编程智能体\n晋江市飞虹智科技企业管理有限公司'
250
- });
251
- }}
252
- ]
253
- }
254
- ];
255
- const menu = Menu.buildFromTemplate(template);
256
- Menu.setApplicationMenu(menu);
257
- }
258
-
259
- /**
260
- * 设置权限(麦克风、摄像头、屏幕捕获)
261
- */
262
- function setupPermissions() {
263
- // 允许所有权限请求(语音输入、视频通话、截图等)
264
- session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
265
- console.log('[Electron] 权限请求: ' + permission);
266
- // 允许所有权限
267
- callback(true);
268
- });
269
-
270
- // 屏幕捕获:自动选择主屏幕,不需要每次都请求权限
271
- session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
272
- console.log('[Electron] 屏幕捕获请求,自动选择主屏幕');
273
- desktopCapturer.getSources({ types: ['screen'] }).then(sources => {
274
- if (sources.length > 0) {
275
- // 自动选择第一个屏幕(主屏幕)
276
- callback({ video: sources[0] });
277
- } else {
278
- callback({});
279
- }
280
- }).catch(err => {
281
- console.error('[Electron] 获取屏幕源失败:', err.message);
282
- callback({});
283
- });
284
- });
285
- }
286
-
287
- /**
288
- * 设置 IPC
289
- */
290
- function setupIpc() {
291
- ipcMain.on('window:minimize', () => { if (mainWindow) mainWindow.minimize(); });
292
- ipcMain.on('window:maximize', () => { if (mainWindow) mainWindow.maximize(); });
293
- ipcMain.on('window:unmaximize', () => { if (mainWindow) mainWindow.unmaximize(); });
294
- ipcMain.on('window:close', () => { if (mainWindow) mainWindow.close(); });
295
- ipcMain.handle('window:isMaximized', () => mainWindow ? mainWindow.isMaximized() : false);
296
-
297
- ipcMain.on('app:quit', () => { app.isQuitting = true; app.quit(); });
298
- ipcMain.on('app:restart', () => { app.relaunch(); app.exit(0); });
299
- ipcMain.handle('app:getPath', (_, name) => { try { return app.getPath(name); } catch { return null; } });
300
-
301
- ipcMain.handle('shell:openExternal', (_, url) => shell.openExternal(url));
302
- ipcMain.handle('shell:openPath', (_, path) => shell.openPath(path));
303
-
304
- ipcMain.handle('dialog:showOpen', (_, options) => dialog.showOpenDialog(mainWindow, options));
305
- ipcMain.handle('dialog:showSave', (_, options) => dialog.showSaveDialog(mainWindow, options));
306
- ipcMain.handle('dialog:showMessage', (_, options) => dialog.showMessageBox(mainWindow, options));
307
-
308
- ipcMain.handle('clipboard:writeText', (_, text) => { clipboard.writeText(text); return true; });
309
- ipcMain.handle('clipboard:readText', () => clipboard.readText());
310
-
311
- ipcMain.handle('notification:show', (_, { title, body }) => {
312
- if (Notification.isSupported()) { new Notification({ title, body }).show(); return true; }
313
- return false;
314
- });
315
-
316
- // 截图功能:截取主屏幕,返回 dataURL
317
- ipcMain.handle('screenshot:capture', async () => {
318
- try {
319
- const primaryDisplay = screen.getPrimaryDisplay();
320
- const { width, height } = primaryDisplay.size;
321
- const sources = await desktopCapturer.getSources({
322
- types: ['screen'],
323
- thumbnailSize: { width, height }
324
- });
325
- const primarySource = sources.find(s => s.display_id === String(primaryDisplay.id)) || sources[0];
326
- if (!primarySource) throw new Error('未找到屏幕源');
327
- return {
328
- success: true,
329
- dataUrl: primarySource.thumbnail.toDataURL(),
330
- width: width,
331
- height: height
332
- };
333
- } catch (err) {
334
- return { success: false, error: err.message };
335
- }
336
- });
337
- }
338
-
339
- // App 就绪
340
- app.whenReady().then(async () => {
341
- console.log('[Electron] App 已就绪');
342
- console.log('[Electron] 应用路径: ' + APP_PATH);
343
-
344
- try {
345
- setupIpc();
346
- setupPermissions();
347
- createMenu();
348
- await startServer();
349
- createWindow();
350
- createTray();
351
-
352
- app.on('activate', () => {
353
- if (BrowserWindow.getAllWindows().length === 0) createWindow();
354
- });
355
- } catch (err) {
356
- console.error('[Electron] 启动失败: ' + err.message);
357
-
358
- // 显示错误窗口
359
- const errorWin = new BrowserWindow({
360
- width: 700,
361
- height: 500,
362
- title: '启动失败',
363
- webPreferences: { nodeIntegration: true, contextIsolation: false }
364
- });
365
-
366
- const errorHtml = `
367
- <html><body style="font-family:Microsoft YaHei,sans-serif;padding:30px;background:#1a1a2e;color:#fff;margin:0;">
368
- <h2 style="color:#ff6b6b;">飞虹 Code 启动失败</h2>
369
- <p style="color:#aaa;">错误详情:</p>
370
- <pre style="background:#0d1117;padding:15px;border-radius:8px;overflow:auto;white-space:pre-wrap;font-size:12px;max-height:300px;">${String(err.message).replace(/</g, '&lt;')}</pre>
371
- <p style="color:#888;margin-top:20px;">请检查:1) 是否已运行 npm run build 2) 端口 ${PORT} 是否被占用 3) Node.js 版本是否 >= 18</p>
372
- <p style="color:#666;margin-top:20px;font-size:12px;">关闭此窗口后退出</p>
373
- </body></html>
374
- `;
375
- errorWin.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(errorHtml));
376
- errorWin.on('closed', () => app.quit());
377
- }
378
- });
379
-
380
- // 所有窗口关闭时不退出(保持托盘运行)
381
- app.on('window-all-closed', () => {});
382
-
383
- // 退出前停止服务器
384
- app.on('before-quit', () => {
385
- app.isQuitting = true;
386
- if (serverProcess) {
387
- serverProcess.kill();
388
- serverProcess = null;
389
- }
390
- });
391
-
392
- // 防止多开
393
- const gotLock = app.requestSingleInstanceLock();
394
- if (!gotLock) {
395
- app.quit();
396
- } else {
397
- app.on('second-instance', () => {
398
- if (mainWindow) {
399
- if (mainWindow.isMinimized()) mainWindow.restore();
400
- mainWindow.show();
401
- mainWindow.focus();
402
- }
403
- });
404
- }
1
+ /**
2
+ * 飞虹 Code Electron 桌面版主进程(简化稳定版)
3
+ * 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
4
+ */
5
+
6
+ const { app, BrowserWindow, shell, Tray, Menu, ipcMain, dialog, clipboard, Notification, session, desktopCapturer, screen } = require('electron');
7
+ const { spawn } = require('child_process');
8
+ const { existsSync } = require('fs');
9
+ const { join } = require('path');
10
+ const http = require('http');
11
+
12
+ // 禁用安全警告
13
+ process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
14
+
15
+ // 配置
16
+ const PORT = parseInt(process.env.FH_WEB_PORT || '8081');
17
+ const isDev = !app.isPackaged;
18
+
19
+ // 全局变量
20
+ let mainWindow = null;
21
+ let serverProcess = null;
22
+ let tray = null;
23
+
24
+ // 获取应用根目录
25
+ function getAppPath() {
26
+ if (isDev) return join(__dirname, '..');
27
+ return process.resourcesPath ? join(process.resourcesPath, 'app') : app.getAppPath();
28
+ }
29
+ const APP_PATH = getAppPath();
30
+
31
+ /**
32
+ * 等待服务器就绪
33
+ */
34
+ function waitForServer(port, timeoutMs) {
35
+ return new Promise((resolve, reject) => {
36
+ const startTime = Date.now();
37
+ const check = () => {
38
+ const req = http.get(`http://127.0.0.1:${port}/api/health`, (res) => {
39
+ if (res.statusCode === 200) {
40
+ resolve();
41
+ } else {
42
+ res.resume();
43
+ retry();
44
+ }
45
+ });
46
+ req.on('error', () => retry());
47
+ req.setTimeout(2000, () => { req.destroy(); retry(); });
48
+ };
49
+ const retry = () => {
50
+ if (Date.now() - startTime > timeoutMs) {
51
+ reject(new Error('服务器启动超时'));
52
+ } else {
53
+ setTimeout(check, 500);
54
+ }
55
+ };
56
+ check();
57
+ });
58
+ }
59
+
60
+ /**
61
+ * 启动内置 Web 服务器
62
+ */
63
+ function startServer() {
64
+ return new Promise((resolve, reject) => {
65
+ const serverEntry = join(APP_PATH, 'dist', 'cli', 'index.js');
66
+ if (!existsSync(serverEntry)) {
67
+ reject(new Error('未找到服务器入口文件,请先运行 npm run build'));
68
+ return;
69
+ }
70
+
71
+ console.log('[Electron] 启动服务器,端口: ' + PORT);
72
+
73
+ let serverLog = '';
74
+ let started = false;
75
+
76
+ serverProcess = spawn('node', [serverEntry, 'serve'], {
77
+ cwd: APP_PATH,
78
+ env: { ...process.env, FH_WEB_PORT: String(PORT) },
79
+ stdio: ['ignore', 'pipe', 'pipe']
80
+ });
81
+
82
+ serverProcess.stdout.on('data', (data) => {
83
+ const text = data.toString();
84
+ serverLog += text;
85
+ console.log('[Server] ' + text.trim());
86
+ });
87
+
88
+ serverProcess.stderr.on('data', (data) => {
89
+ const text = data.toString();
90
+ serverLog += text;
91
+ console.error('[Server Error] ' + text.trim());
92
+ });
93
+
94
+ serverProcess.on('error', (err) => {
95
+ if (!started) reject(new Error('启动服务器失败: ' + err.message));
96
+ });
97
+
98
+ serverProcess.on('exit', (code) => {
99
+ console.log('[Electron] 服务器退出,代码: ' + code);
100
+ serverProcess = null;
101
+ if (!started) {
102
+ reject(new Error('服务器启动失败,退出代码: ' + code + '\n\n日志:\n' + serverLog.slice(-2000)));
103
+ }
104
+ });
105
+
106
+ // 等待服务器就绪
107
+ waitForServer(PORT, 60000).then(() => {
108
+ started = true;
109
+ console.log('[Electron] 服务器已就绪');
110
+ resolve();
111
+ }).catch((err) => {
112
+ if (!started) reject(new Error(err.message + '\n\n服务器日志:\n' + serverLog.slice(-2000)));
113
+ });
114
+ });
115
+ }
116
+
117
+ /**
118
+ * 创建主窗口
119
+ */
120
+ function createWindow() {
121
+ mainWindow = new BrowserWindow({
122
+ width: 1400,
123
+ height: 900,
124
+ minWidth: 1024,
125
+ minHeight: 680,
126
+ title: '飞虹 Code',
127
+ webPreferences: {
128
+ preload: join(__dirname, 'preload.js'),
129
+ contextIsolation: true,
130
+ nodeIntegration: false
131
+ },
132
+ show: false,
133
+ backgroundColor: '#1a1a2e'
134
+ });
135
+
136
+ const url = `http://127.0.0.1:${PORT}/`;
137
+ console.log('[Electron] 加载页面: ' + url);
138
+ mainWindow.loadURL(url);
139
+
140
+ mainWindow.once('ready-to-show', () => {
141
+ mainWindow.show();
142
+ });
143
+
144
+ // 外部链接用系统浏览器打开
145
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
146
+ shell.openExternal(url);
147
+ return { action: 'deny' };
148
+ });
149
+
150
+ // 关闭时最小化到托盘
151
+ mainWindow.on('close', (e) => {
152
+ if (!app.isQuitting) {
153
+ e.preventDefault();
154
+ mainWindow.hide();
155
+ }
156
+ });
157
+
158
+ mainWindow.on('closed', () => {
159
+ mainWindow = null;
160
+ });
161
+ }
162
+
163
+ /**
164
+ * 创建系统托盘
165
+ */
166
+ function createTray() {
167
+ try {
168
+ const iconPath = join(__dirname, 'icon.png');
169
+ let trayIcon;
170
+ if (existsSync(iconPath)) {
171
+ trayIcon = require('electron').nativeImage.createFromPath(iconPath);
172
+ } else {
173
+ trayIcon = require('electron').nativeImage.createEmpty();
174
+ }
175
+
176
+ tray = new Tray(trayIcon);
177
+ tray.setToolTip('飞虹 Code');
178
+
179
+ const contextMenu = Menu.buildFromTemplate([
180
+ { label: '显示主窗口', click: () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } } },
181
+ { type: 'separator' },
182
+ { label: '退出', click: () => { app.isQuitting = true; app.quit(); } }
183
+ ]);
184
+ tray.setContextMenu(contextMenu);
185
+
186
+ tray.on('click', () => {
187
+ if (mainWindow) {
188
+ if (mainWindow.isVisible()) mainWindow.hide();
189
+ else { mainWindow.show(); mainWindow.focus(); }
190
+ }
191
+ });
192
+ } catch (e) {
193
+ console.warn('[Electron] 创建托盘失败: ' + e.message);
194
+ }
195
+ }
196
+
197
+ /**
198
+ * 创建应用菜单(关键:没有菜单会导致复制粘贴等快捷键失效)
199
+ */
200
+ function createMenu() {
201
+ const template = [
202
+ {
203
+ label: '文件',
204
+ submenu: [
205
+ { label: '刷新', role: 'reload' },
206
+ { label: '强制刷新', role: 'forceReload' },
207
+ { type: 'separator' },
208
+ { label: '退出', role: 'quit' }
209
+ ]
210
+ },
211
+ {
212
+ label: '编辑',
213
+ submenu: [
214
+ { label: '撤销', role: 'undo' },
215
+ { label: '重做', role: 'redo' },
216
+ { type: 'separator' },
217
+ { label: '剪切', role: 'cut' },
218
+ { label: '复制', role: 'copy' },
219
+ { label: '粘贴', role: 'paste' },
220
+ { label: '全选', role: 'selectAll' }
221
+ ]
222
+ },
223
+ {
224
+ label: '视图',
225
+ submenu: [
226
+ { label: '放大', role: 'zoomIn' },
227
+ { label: '缩小', role: 'zoomOut' },
228
+ { label: '重置缩放', role: 'resetZoom' },
229
+ { type: 'separator' },
230
+ { label: '全屏', role: 'togglefullscreen' },
231
+ { label: '开发者工具', role: 'toggleDevTools' }
232
+ ]
233
+ },
234
+ {
235
+ label: '窗口',
236
+ submenu: [
237
+ { label: '最小化', role: 'minimize' },
238
+ { label: '关闭', role: 'close' }
239
+ ]
240
+ },
241
+ {
242
+ label: '帮助',
243
+ submenu: [
244
+ { label: '关于飞虹 Code', click: () => {
245
+ dialog.showMessageBox(mainWindow, {
246
+ type: 'info',
247
+ title: '关于飞虹 Code',
248
+ message: '飞虹 Code v0.6.1',
249
+ detail: '终端 AI 编程智能体\n晋江市飞虹智科技企业管理有限公司'
250
+ });
251
+ }}
252
+ ]
253
+ }
254
+ ];
255
+ const menu = Menu.buildFromTemplate(template);
256
+ Menu.setApplicationMenu(menu);
257
+ }
258
+
259
+ /**
260
+ * 设置权限(麦克风、摄像头、屏幕捕获)
261
+ */
262
+ function setupPermissions() {
263
+ // 允许所有权限请求(语音输入、视频通话、截图等)
264
+ session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
265
+ console.log('[Electron] 权限请求: ' + permission);
266
+ // 允许所有权限
267
+ callback(true);
268
+ });
269
+
270
+ // 屏幕捕获:自动选择主屏幕,不需要每次都请求权限
271
+ session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
272
+ console.log('[Electron] 屏幕捕获请求,自动选择主屏幕');
273
+ desktopCapturer.getSources({ types: ['screen'] }).then(sources => {
274
+ if (sources.length > 0) {
275
+ // 自动选择第一个屏幕(主屏幕)
276
+ callback({ video: sources[0] });
277
+ } else {
278
+ callback({});
279
+ }
280
+ }).catch(err => {
281
+ console.error('[Electron] 获取屏幕源失败:', err.message);
282
+ callback({});
283
+ });
284
+ });
285
+ }
286
+
287
+ /**
288
+ * 设置 IPC
289
+ */
290
+ function setupIpc() {
291
+ ipcMain.on('window:minimize', () => { if (mainWindow) mainWindow.minimize(); });
292
+ ipcMain.on('window:maximize', () => { if (mainWindow) mainWindow.maximize(); });
293
+ ipcMain.on('window:unmaximize', () => { if (mainWindow) mainWindow.unmaximize(); });
294
+ ipcMain.on('window:close', () => { if (mainWindow) mainWindow.close(); });
295
+ ipcMain.handle('window:isMaximized', () => mainWindow ? mainWindow.isMaximized() : false);
296
+
297
+ ipcMain.on('app:quit', () => { app.isQuitting = true; app.quit(); });
298
+ ipcMain.on('app:restart', () => { app.relaunch(); app.exit(0); });
299
+ ipcMain.handle('app:getPath', (_, name) => { try { return app.getPath(name); } catch { return null; } });
300
+
301
+ ipcMain.handle('shell:openExternal', (_, url) => shell.openExternal(url));
302
+ ipcMain.handle('shell:openPath', (_, path) => shell.openPath(path));
303
+
304
+ ipcMain.handle('dialog:showOpen', (_, options) => dialog.showOpenDialog(mainWindow, options));
305
+ ipcMain.handle('dialog:showSave', (_, options) => dialog.showSaveDialog(mainWindow, options));
306
+ ipcMain.handle('dialog:showMessage', (_, options) => dialog.showMessageBox(mainWindow, options));
307
+
308
+ ipcMain.handle('clipboard:writeText', (_, text) => { clipboard.writeText(text); return true; });
309
+ ipcMain.handle('clipboard:readText', () => clipboard.readText());
310
+
311
+ ipcMain.handle('notification:show', (_, { title, body }) => {
312
+ if (Notification.isSupported()) { new Notification({ title, body }).show(); return true; }
313
+ return false;
314
+ });
315
+
316
+ // 截图功能:截取主屏幕,返回 dataURL
317
+ ipcMain.handle('screenshot:capture', async () => {
318
+ try {
319
+ const primaryDisplay = screen.getPrimaryDisplay();
320
+ const { width, height } = primaryDisplay.size;
321
+ const sources = await desktopCapturer.getSources({
322
+ types: ['screen'],
323
+ thumbnailSize: { width, height }
324
+ });
325
+ const primarySource = sources.find(s => s.display_id === String(primaryDisplay.id)) || sources[0];
326
+ if (!primarySource) throw new Error('未找到屏幕源');
327
+ return {
328
+ success: true,
329
+ dataUrl: primarySource.thumbnail.toDataURL(),
330
+ width: width,
331
+ height: height
332
+ };
333
+ } catch (err) {
334
+ return { success: false, error: err.message };
335
+ }
336
+ });
337
+ }
338
+
339
+ // App 就绪
340
+ app.whenReady().then(async () => {
341
+ console.log('[Electron] App 已就绪');
342
+ console.log('[Electron] 应用路径: ' + APP_PATH);
343
+
344
+ try {
345
+ setupIpc();
346
+ setupPermissions();
347
+ createMenu();
348
+ await startServer();
349
+ createWindow();
350
+ createTray();
351
+
352
+ app.on('activate', () => {
353
+ if (BrowserWindow.getAllWindows().length === 0) createWindow();
354
+ });
355
+ } catch (err) {
356
+ console.error('[Electron] 启动失败: ' + err.message);
357
+
358
+ // 显示错误窗口
359
+ const errorWin = new BrowserWindow({
360
+ width: 700,
361
+ height: 500,
362
+ title: '启动失败',
363
+ webPreferences: { nodeIntegration: true, contextIsolation: false }
364
+ });
365
+
366
+ const errorHtml = `
367
+ <html><body style="font-family:Microsoft YaHei,sans-serif;padding:30px;background:#1a1a2e;color:#fff;margin:0;">
368
+ <h2 style="color:#ff6b6b;">飞虹 Code 启动失败</h2>
369
+ <p style="color:#aaa;">错误详情:</p>
370
+ <pre style="background:#0d1117;padding:15px;border-radius:8px;overflow:auto;white-space:pre-wrap;font-size:12px;max-height:300px;">${String(err.message).replace(/</g, '&lt;')}</pre>
371
+ <p style="color:#888;margin-top:20px;">请检查:1) 是否已运行 npm run build 2) 端口 ${PORT} 是否被占用 3) Node.js 版本是否 >= 18</p>
372
+ <p style="color:#666;margin-top:20px;font-size:12px;">关闭此窗口后退出</p>
373
+ </body></html>
374
+ `;
375
+ errorWin.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(errorHtml));
376
+ errorWin.on('closed', () => app.quit());
377
+ }
378
+ });
379
+
380
+ // 所有窗口关闭时不退出(保持托盘运行)
381
+ app.on('window-all-closed', () => {});
382
+
383
+ // 退出前停止服务器
384
+ app.on('before-quit', () => {
385
+ app.isQuitting = true;
386
+ if (serverProcess) {
387
+ serverProcess.kill();
388
+ serverProcess = null;
389
+ }
390
+ });
391
+
392
+ // 防止多开
393
+ const gotLock = app.requestSingleInstanceLock();
394
+ if (!gotLock) {
395
+ app.quit();
396
+ } else {
397
+ app.on('second-instance', () => {
398
+ if (mainWindow) {
399
+ if (mainWindow.isMinimized()) mainWindow.restore();
400
+ mainWindow.show();
401
+ mainWindow.focus();
402
+ }
403
+ });
404
+ }