feihong-code 7.2.0 → 7.5.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 (249) hide show
  1. package/.github/workflows/ci.yml +180 -140
  2. package/.github/workflows/release.yml +200 -173
  3. package/CHANGELOG.md +94 -115
  4. package/README.md +609 -586
  5. package/dist/agent/completion-engine.js +76 -45
  6. package/dist/agent/completion-engine.js.map +1 -1
  7. package/dist/agent/completion-postprocess.js +109 -0
  8. package/dist/agent/completion-postprocess.js.map +1 -0
  9. package/dist/agent/context-budget.js +121 -0
  10. package/dist/agent/context-budget.js.map +1 -0
  11. package/dist/agent/context-compactor.js +47 -0
  12. package/dist/agent/context-compactor.js.map +1 -1
  13. package/dist/agent/custom-agent.js +52 -52
  14. package/dist/agent/design-to-code.js +40 -40
  15. package/dist/agent/lint.js +121 -0
  16. package/dist/agent/lint.js.map +1 -0
  17. package/dist/agent/multi-agent.js +44 -44
  18. package/dist/agent/orchestrator.js +20 -20
  19. package/dist/agent/prompts.js +54 -54
  20. package/dist/agent/self-correction.js +24 -24
  21. package/dist/agent/self-heal.js +27 -27
  22. package/dist/cli/commands.js +9 -0
  23. package/dist/cli/commands.js.map +1 -1
  24. package/dist/cli/index.js +9 -0
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/multi-pane-tui.js +217 -0
  27. package/dist/cli/multi-pane-tui.js.map +1 -0
  28. package/dist/cli/run.js +129 -40
  29. package/dist/cli/run.js.map +1 -1
  30. package/dist/cli/tui-run.js +79 -0
  31. package/dist/cli/tui-run.js.map +1 -0
  32. package/dist/cli/tui.js.map +1 -1
  33. package/dist/cli/version.js +1 -1
  34. package/dist/lsp/lsp-client.js +183 -0
  35. package/dist/lsp/lsp-client.js.map +1 -0
  36. package/dist/lsp/lsp-service.js +159 -0
  37. package/dist/lsp/lsp-service.js.map +1 -0
  38. package/dist/plugins/manager.js +50 -2
  39. package/dist/plugins/manager.js.map +1 -1
  40. package/dist/shared/i18n.js +108 -100
  41. package/dist/shared/i18n.js.map +1 -1
  42. package/dist/tools/generator/code-generator.js +40 -40
  43. package/dist/tools/generator/test-generator.js +9 -9
  44. package/dist/tools/shell/exec.js +23 -1
  45. package/dist/tools/shell/exec.js.map +1 -1
  46. package/dist/web/extra-apis.js +440 -0
  47. package/dist/web/extra-apis.js.map +1 -0
  48. package/dist/web/public/css/style.css +1715 -1715
  49. package/dist/web/public/index.html +1242 -1200
  50. package/dist/web/public/js/api.js +555 -496
  51. package/dist/web/public/js/app.js +2210 -2210
  52. package/dist/web/public/js/mock-api.js +234 -234
  53. package/dist/web/public/js/monaco-editor.js +363 -203
  54. package/dist/web/public/js/ui.js +2251 -1981
  55. package/dist/web/public/js/utils.js +214 -214
  56. package/dist/web/public/manifest.json +59 -59
  57. package/dist/web/public/service-worker.js +173 -173
  58. package/dist/web/server.js +97 -45
  59. package/dist/web/server.js.map +1 -1
  60. package/docs/BENCHMARK_REPORT_en.md +386 -329
  61. package/docs/BENCHMARK_REPORT_zh.md +386 -329
  62. package/docs/DPA.md +63 -0
  63. 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 +67 -0
  64. package/docs/SECURITY_WHITEPAPER.md +74 -0
  65. package/docs/SWE_BENCH_REPORT.md +55 -0
  66. package/docs/TECHNICAL_SPEC_en.md +292 -292
  67. package/docs/TECHNICAL_SPEC_zh.md +292 -292
  68. package/docs/UPDATE_NOTES_en.md +159 -159
  69. package/docs/UPDATE_NOTES_zh.md +159 -159
  70. package/docs/UPGRADE_7.2.0.md +309 -0
  71. package/docs/UPGRADE_GUIDE_7_5.md +86 -0
  72. package/docs/geo-feihong-code.html +391 -0
  73. 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 -0
  74. 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 -0
  75. 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 -0
  76. 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 -0
  77. package/docs//345/256/211/345/205/250/347/231/275/347/232/256/344/271/246_v7.2.0.md +82 -0
  78. package/electron/main.js +404 -602
  79. package/package.json +175 -172
  80. package/templates/skills/api-design/SKILL.md +27 -0
  81. package/templates/skills/code-review/SKILL.md +35 -0
  82. package/templates/skills/dependency-upgrade/SKILL.md +29 -0
  83. package/templates/skills/doc-gen/SKILL.md +29 -0
  84. package/templates/skills/git-flow/SKILL.md +26 -0
  85. package/templates/skills/onboarding/SKILL.md +27 -0
  86. package/templates/skills/performance/SKILL.md +29 -0
  87. package/templates/skills/refactor/SKILL.md +28 -0
  88. package/templates/skills/security-audit/SKILL.md +28 -0
  89. package/templates/skills/test-gen/SKILL.md +30 -0
  90. package/tool-schema.json +197 -197
  91. package/dist/hello.js +0 -14
  92. package/dist/hello.js.map +0 -1
  93. package/dist/self-evolve/hook.ts +0 -80
  94. package/dist/self-evolve/manager.d.ts +0 -8
  95. package/dist/web/public/vendor/monaco/vs/abap-D-t0cyap.js +0 -1
  96. package/dist/web/public/vendor/monaco/vs/apex-CcIm7xu6.js +0 -1
  97. package/dist/web/public/vendor/monaco/vs/assets/css.worker-URu8fCFR.js +0 -97
  98. package/dist/web/public/vendor/monaco/vs/assets/editor.worker-lj3bdIIn.js +0 -30
  99. package/dist/web/public/vendor/monaco/vs/assets/editorWebWorkerMain-CA_vMoUU.js +0 -30
  100. package/dist/web/public/vendor/monaco/vs/assets/html.worker-D1SL3iM8.js +0 -474
  101. package/dist/web/public/vendor/monaco/vs/assets/json.worker-CoJx_OPf.js +0 -62
  102. package/dist/web/public/vendor/monaco/vs/assets/ts.worker-BWKtMYOk.js +0 -67722
  103. package/dist/web/public/vendor/monaco/vs/azcli-BA0tQDCg.js +0 -1
  104. package/dist/web/public/vendor/monaco/vs/basic-languages/monaco.contribution.js +0 -1
  105. package/dist/web/public/vendor/monaco/vs/bat-C397hTD6.js +0 -1
  106. package/dist/web/public/vendor/monaco/vs/bicep-DF5aW17k.js +0 -2
  107. package/dist/web/public/vendor/monaco/vs/cameligo-plsz8qhj.js +0 -1
  108. package/dist/web/public/vendor/monaco/vs/clojure-Y2auQMzK.js +0 -1
  109. package/dist/web/public/vendor/monaco/vs/coffee-Bu45yuWE.js +0 -1
  110. package/dist/web/public/vendor/monaco/vs/cpp-CkKPQIni.js +0 -1
  111. package/dist/web/public/vendor/monaco/vs/csharp-CX28MZyh.js +0 -1
  112. package/dist/web/public/vendor/monaco/vs/csp-D8uWnyxW.js +0 -1
  113. package/dist/web/public/vendor/monaco/vs/css-CaeNmE3S.js +0 -3
  114. package/dist/web/public/vendor/monaco/vs/css.worker-CyhWkhHo.js +0 -1
  115. package/dist/web/public/vendor/monaco/vs/cssMode-CV6Ay48H.js +0 -1
  116. package/dist/web/public/vendor/monaco/vs/cypher-DVThT8BS.js +0 -1
  117. package/dist/web/public/vendor/monaco/vs/dart-CmGfCvrO.js +0 -1
  118. package/dist/web/public/vendor/monaco/vs/dockerfile-CZqqYdch.js +0 -1
  119. package/dist/web/public/vendor/monaco/vs/ecl-30fUercY.js +0 -1
  120. package/dist/web/public/vendor/monaco/vs/editor/editor.main.css +0 -1
  121. package/dist/web/public/vendor/monaco/vs/editor/editor.main.js +0 -1
  122. package/dist/web/public/vendor/monaco/vs/editor/editor.worker.js +0 -1
  123. package/dist/web/public/vendor/monaco/vs/editor-KLE6jdfb.js +0 -831
  124. package/dist/web/public/vendor/monaco/vs/editor.js +0 -1
  125. package/dist/web/public/vendor/monaco/vs/editorWorkerHost-fVE1cjcC.js +0 -35
  126. package/dist/web/public/vendor/monaco/vs/elixir-xjPaIfzF.js +0 -1
  127. package/dist/web/public/vendor/monaco/vs/flow9-DqtmStfK.js +0 -1
  128. package/dist/web/public/vendor/monaco/vs/freemarker2-FWreY7v7.js +0 -3
  129. package/dist/web/public/vendor/monaco/vs/fsharp-BOMdg4U1.js +0 -1
  130. package/dist/web/public/vendor/monaco/vs/go-D_hbi-Jt.js +0 -1
  131. package/dist/web/public/vendor/monaco/vs/graphql-CKUU4kLG.js +0 -1
  132. package/dist/web/public/vendor/monaco/vs/handlebars-CZi4pHCH.js +0 -1
  133. package/dist/web/public/vendor/monaco/vs/hcl-DTaboeZW.js +0 -1
  134. package/dist/web/public/vendor/monaco/vs/html-j_7ZTNRU.js +0 -1
  135. package/dist/web/public/vendor/monaco/vs/html.worker-CA3iAimZ.js +0 -1
  136. package/dist/web/public/vendor/monaco/vs/htmlMode-27by_KM4.js +0 -1
  137. package/dist/web/public/vendor/monaco/vs/index-049xrXrp.js +0 -1
  138. package/dist/web/public/vendor/monaco/vs/index-CBVt3dzv.js +0 -5
  139. package/dist/web/public/vendor/monaco/vs/index.js +0 -1
  140. package/dist/web/public/vendor/monaco/vs/ini-CsNwO04R.js +0 -1
  141. package/dist/web/public/vendor/monaco/vs/initialize-DL0l1TGY.js +0 -1
  142. package/dist/web/public/vendor/monaco/vs/java-CI4ZMsH9.js +0 -1
  143. package/dist/web/public/vendor/monaco/vs/javascript-DTJl4Jn1.js +0 -1
  144. package/dist/web/public/vendor/monaco/vs/json.worker-BizpAl9O.js +0 -1
  145. package/dist/web/public/vendor/monaco/vs/jsonMode-DLUiMUrI.js +0 -1
  146. package/dist/web/public/vendor/monaco/vs/julia-BwzEvaQw.js +0 -1
  147. package/dist/web/public/vendor/monaco/vs/kotlin-IUYPiTV8.js +0 -1
  148. package/dist/web/public/vendor/monaco/vs/language/css/css.worker.js +0 -66
  149. package/dist/web/public/vendor/monaco/vs/language/css/monaco.contribution.js +0 -1
  150. package/dist/web/public/vendor/monaco/vs/language/html/html.worker.js +0 -443
  151. package/dist/web/public/vendor/monaco/vs/language/html/monaco.contribution.js +0 -1
  152. package/dist/web/public/vendor/monaco/vs/language/json/json.worker.js +0 -17
  153. package/dist/web/public/vendor/monaco/vs/language/json/monaco.contribution.js +0 -1
  154. package/dist/web/public/vendor/monaco/vs/language/typescript/monaco.contribution.js +0 -1
  155. package/dist/web/public/vendor/monaco/vs/language/typescript/ts.worker.js +0 -67693
  156. package/dist/web/public/vendor/monaco/vs/less-C0eDYdqa.js +0 -2
  157. package/dist/web/public/vendor/monaco/vs/lexon-iON-Kj97.js +0 -1
  158. package/dist/web/public/vendor/monaco/vs/liquid-CLJYelW6.js +0 -1
  159. package/dist/web/public/vendor/monaco/vs/loader.js +0 -1368
  160. package/dist/web/public/vendor/monaco/vs/lspLanguageFeatures-BIkJOWLw.js +0 -2
  161. package/dist/web/public/vendor/monaco/vs/lua-DtygF91M.js +0 -1
  162. package/dist/web/public/vendor/monaco/vs/m3-CsR4AuFi.js +0 -1
  163. package/dist/web/public/vendor/monaco/vs/main-BEx-Fmlo.js +0 -15
  164. package/dist/web/public/vendor/monaco/vs/main-DsK8pnKg.js +0 -3
  165. package/dist/web/public/vendor/monaco/vs/markdown-C_rD0bIw.js +0 -1
  166. package/dist/web/public/vendor/monaco/vs/mdx-CpzZIPHF.js +0 -1
  167. package/dist/web/public/vendor/monaco/vs/mips-CiYP61RB.js +0 -1
  168. package/dist/web/public/vendor/monaco/vs/monaco.contribution-9cKT3C7t.js +0 -1
  169. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BE88ZNGY.js +0 -1
  170. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BPhsneLd.js +0 -1
  171. package/dist/web/public/vendor/monaco/vs/monaco.contribution-BgRy6xDf.js +0 -1
  172. package/dist/web/public/vendor/monaco/vs/msdax-C38-sJlp.js +0 -1
  173. package/dist/web/public/vendor/monaco/vs/mysql-CdtbpvbG.js +0 -1
  174. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.d.ts +0 -1
  175. package/dist/web/public/vendor/monaco/vs/nls/lang/cs.js +0 -9
  176. package/dist/web/public/vendor/monaco/vs/nls/lang/de.d.ts +0 -1
  177. package/dist/web/public/vendor/monaco/vs/nls/lang/de.js +0 -9
  178. package/dist/web/public/vendor/monaco/vs/nls/lang/es.d.ts +0 -1
  179. package/dist/web/public/vendor/monaco/vs/nls/lang/es.js +0 -9
  180. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.d.ts +0 -1
  181. package/dist/web/public/vendor/monaco/vs/nls/lang/fr.js +0 -9
  182. package/dist/web/public/vendor/monaco/vs/nls/lang/it.d.ts +0 -1
  183. package/dist/web/public/vendor/monaco/vs/nls/lang/it.js +0 -9
  184. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.d.ts +0 -1
  185. package/dist/web/public/vendor/monaco/vs/nls/lang/ja.js +0 -9
  186. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.d.ts +0 -1
  187. package/dist/web/public/vendor/monaco/vs/nls/lang/ko.js +0 -9
  188. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.d.ts +0 -1
  189. package/dist/web/public/vendor/monaco/vs/nls/lang/pl.js +0 -9
  190. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.d.ts +0 -1
  191. package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.js +0 -9
  192. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.d.ts +0 -1
  193. package/dist/web/public/vendor/monaco/vs/nls/lang/ru.js +0 -9
  194. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.d.ts +0 -1
  195. package/dist/web/public/vendor/monaco/vs/nls/lang/tr.js +0 -9
  196. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.d.ts +0 -1
  197. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.js +0 -9
  198. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.d.ts +0 -1
  199. package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.js +0 -9
  200. package/dist/web/public/vendor/monaco/vs/nls.messages-loader.js +0 -1
  201. package/dist/web/public/vendor/monaco/vs/objective-c-CntZFaHX.js +0 -1
  202. package/dist/web/public/vendor/monaco/vs/pascal-r6kuqfl_.js +0 -1
  203. package/dist/web/public/vendor/monaco/vs/pascaligo-BiXoTmXh.js +0 -1
  204. package/dist/web/public/vendor/monaco/vs/perl-DABw_TcH.js +0 -1
  205. package/dist/web/public/vendor/monaco/vs/pgsql-me_jFXeX.js +0 -1
  206. package/dist/web/public/vendor/monaco/vs/php-D_kh-9LK.js +0 -1
  207. package/dist/web/public/vendor/monaco/vs/pla-VfZjczW0.js +0 -1
  208. package/dist/web/public/vendor/monaco/vs/postiats-BBSzz8Pk.js +0 -1
  209. package/dist/web/public/vendor/monaco/vs/powerquery-Dt-g_2cc.js +0 -1
  210. package/dist/web/public/vendor/monaco/vs/powershell-B-7ap1zc.js +0 -1
  211. package/dist/web/public/vendor/monaco/vs/protobuf-BmtuEB1A.js +0 -2
  212. package/dist/web/public/vendor/monaco/vs/pug-BRpRNeEb.js +0 -1
  213. package/dist/web/public/vendor/monaco/vs/python-CqWUUgfu.js +0 -1
  214. package/dist/web/public/vendor/monaco/vs/qsharp-BzsFaUU9.js +0 -1
  215. package/dist/web/public/vendor/monaco/vs/r-f8dDdrp4.js +0 -1
  216. package/dist/web/public/vendor/monaco/vs/razor-hok5y9Km.js +0 -1
  217. package/dist/web/public/vendor/monaco/vs/redis-fvZQY4PI.js +0 -1
  218. package/dist/web/public/vendor/monaco/vs/redshift-45Et0LQi.js +0 -1
  219. package/dist/web/public/vendor/monaco/vs/restructuredtext-C7UUFKFD.js +0 -1
  220. package/dist/web/public/vendor/monaco/vs/ruby-CZO8zYTz.js +0 -1
  221. package/dist/web/public/vendor/monaco/vs/rust-Bfetafyc.js +0 -1
  222. package/dist/web/public/vendor/monaco/vs/sb-3GYllVck.js +0 -1
  223. package/dist/web/public/vendor/monaco/vs/scala-foMgrKo1.js +0 -1
  224. package/dist/web/public/vendor/monaco/vs/scheme-CHdMtr7p.js +0 -1
  225. package/dist/web/public/vendor/monaco/vs/scss-C1cmLt9V.js +0 -3
  226. package/dist/web/public/vendor/monaco/vs/shell-ClXCKCEW.js +0 -1
  227. package/dist/web/public/vendor/monaco/vs/solidity-MZ6ExpPy.js +0 -1
  228. package/dist/web/public/vendor/monaco/vs/sophia-DWkuSsPQ.js +0 -1
  229. package/dist/web/public/vendor/monaco/vs/sparql-AUGFYSyk.js +0 -1
  230. package/dist/web/public/vendor/monaco/vs/sql-32GpJSV2.js +0 -1
  231. package/dist/web/public/vendor/monaco/vs/st-CuDFIVZ_.js +0 -1
  232. package/dist/web/public/vendor/monaco/vs/swift-t-PfMj7W.js +0 -1
  233. package/dist/web/public/vendor/monaco/vs/systemverilog-Ch4vA8Yt.js +0 -1
  234. package/dist/web/public/vendor/monaco/vs/tcl-D74tq1nH.js +0 -1
  235. package/dist/web/public/vendor/monaco/vs/toggleHighContrast-qGX7E9o7.js +0 -61
  236. package/dist/web/public/vendor/monaco/vs/ts.worker-2QLmBukE.js +0 -1
  237. package/dist/web/public/vendor/monaco/vs/tsMode-B0S_kp2q.js +0 -11
  238. package/dist/web/public/vendor/monaco/vs/twig-C6taOxMV.js +0 -1
  239. package/dist/web/public/vendor/monaco/vs/typescript-_2t_511t.js +0 -1
  240. package/dist/web/public/vendor/monaco/vs/typespec-8OfoLt6R.js +0 -1
  241. package/dist/web/public/vendor/monaco/vs/vb-Dyb2648j.js +0 -1
  242. package/dist/web/public/vendor/monaco/vs/wgsl-BhLXMOR0.js +0 -298
  243. package/dist/web/public/vendor/monaco/vs/workers-BBttULjf.js +0 -1
  244. package/dist/web/public/vendor/monaco/vs/xml-cZjNDqDT.js +0 -1
  245. package/dist/web/public/vendor/monaco/vs/yaml-A1fOIdH6.js +0 -1
  246. package/dist/web/web-config.js +0 -143
  247. package/dist/web/web-config.js.map +0 -1
  248. package/docs/DEPLOYMENT.md +0 -382
  249. package/docs/MODEL_FINETUNING.md +0 -405
@@ -1,214 +1,214 @@
1
- /**
2
- * 工具函数模块:纯函数,无状态依赖,可被任意模块调用
3
- */
4
-
5
- function formatMarkdown(text) {
6
- // 简单 Markdown 转换
7
- return text
8
- .replace(/&/g, '&')
9
- .replace(/</g, '&lt;')
10
- .replace(/>/g, '&gt;')
11
- .replace(/^### (.*$)/gm, '<h3>$1</h3>')
12
- .replace(/^## (.*$)/gm, '<h2>$1</h2>')
13
- .replace(/^# (.*$)/gm, '<h1>$1</h1>')
14
- .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
15
- .replace(/\*(.*?)\*/g, '<em>$1</em>')
16
- .replace(/`(.*?)`/g, '<code>$1</code>')
17
- .replace(/\n/g, '<br>');
18
- }
19
-
20
- function getDirectoryName(path) {
21
- if (!path || path === '' || path === '/') return '/';
22
- if (/^[A-Za-z]:$/.test(path)) return path + '\\';
23
- if (/^[A-Za-z]:\\$/.test(path)) return path;
24
- const parts = path.split(/[/\\]/).filter(Boolean);
25
- if (parts.length <= 1) {
26
- const driveMatch = parts[0].match(/^([A-Za-z]):$/);
27
- if (driveMatch) return driveMatch[1] + ':\\';
28
- return parts[0] || '/';
29
- }
30
- const parentParts = parts.slice(0, -1);
31
- if (/^[A-Za-z]:$/.test(parentParts[0])) {
32
- return parentParts[0] + '\\' + parentParts.slice(1).join('\\');
33
- }
34
- return parentParts.join('\\');
35
- }
36
-
37
- /** 渲染空状态提示,减少重复的 innerHTML 赋值代码 */
38
- function renderEmpty(el, text) {
39
- if (el) el.innerHTML = '<div class="empty">' + (text || '') + '</div>';
40
- }
41
-
42
- function extractUrl(text) {
43
- if (!text) return '';
44
- const m = text.match(/(https?:\/\/[^\s]+)/);
45
- return m ? m[1] : '';
46
- }
47
-
48
- function linkifyArtifacts(text) {
49
- let html = escapeHtml(text);
50
- // 占位符保护:先提取已识别的片段,避免后续正则把已插入的 <span> 标签二次包裹
51
- const tokens = [];
52
- const protect = (s) => { const k = '\u0000TOK' + tokens.length + '\u0000'; tokens.push(s); return k; };
53
- // 1) URL:排除结尾标点与 HTML 实体
54
- html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, (m) => protect('<span class="artifact" data-kind="url" data-path="' + m + '">' + m + '</span>'));
55
- // 2) Windows 绝对路径(支持正/反斜杠、中文、空格,排除结尾标点)
56
- html = html.replace(/([A-Za-z]:[\\\/][^\s<>"'()]+?)(?=[\s<>"',。;:、))]|$)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
57
- // 3) Unix 风格绝对路径(至少两级目录,避免误匹配 "2023/2024"、"a/b" 等相对写法)
58
- html = html.replace(/(\/(?:[A-Za-z0-9_\-.]+\/){1,}[A-Za-z0-9_\-.]*)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
59
- tokens.forEach((s, i) => { html = html.split('\u0000TOK' + i + '\u0000').join(s); });
60
- return html;
61
- }
62
-
63
- function formatSize(n) {
64
- if (!Number.isFinite(n)) return '';
65
- if (n < 1024) return n + ' B';
66
- if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
67
- return (n / 1024 / 1024).toFixed(2) + ' MB';
68
- }
69
-
70
- function estimateDataUrlSize(dataUrl) {
71
- // base64 长度 × 0.75 估算字节
72
- const b64 = (dataUrl || '').split(',')[1] || '';
73
- return Math.round(b64.length * 0.75);
74
- }
75
-
76
- function formatToolArgs(args) {
77
- if (!args || typeof args !== 'object') return '';
78
- const keys = Object.keys(args);
79
- if (!keys.length) return '';
80
- const rows = keys.map(function (k) {
81
- let v = args[k];
82
- if (v == null) v = '';
83
- else if (typeof v === 'object') v = JSON.stringify(v);
84
- return '<div><span style="color:var(--ink-2,#6b7280);">' + escapeHtml(k) + ':</span> ' + escapeHtml(String(v)) + '</div>';
85
- });
86
- return '<div class="tc-args">' + rows.join('') + '</div>';
87
- }
88
-
89
- function renderMarkdown(text) {
90
- let html = escapeHtml(text == null ? '' : text);
91
- const codeBlocks = [];
92
- html = html.replace(/```(\w*)\n?([\s\S]*?)```/g, function (_, lang, code) {
93
- const idx = codeBlocks.length;
94
- codeBlocks.push('<pre style="background:var(--bg,#f5f6fa);padding:10px;border-radius:8px;overflow-x:auto;font-size:12px;margin:6px 0;white-space:pre-wrap;word-break:break-word;"><code>' + code + '</code></pre>');
95
- return '\x00CB' + idx + '\x00';
96
- });
97
- html = html.replace(/`([^`]+)`/g, '<code style="background:var(--bg,#f5f6fa);padding:1px 5px;border-radius:4px;font-size:12px;">$1</code>');
98
- html = html.replace(/\*\*([^*]+)\*\*/g, '<b>$1</b>');
99
- html = html.replace(/^### (.*)$/gm, '<div style="font-weight:700;margin:8px 0 4px;">$1</div>');
100
- html = html.replace(/^## (.*)$/gm, '<div style="font-weight:700;font-size:15px;margin:10px 0 4px;">$1</div>');
101
- html = html.replace(/^# (.*)$/gm, '<div style="font-weight:700;font-size:16px;margin:10px 0 4px;">$1</div>');
102
- html = html.replace(/^[-*] (.*)$/gm, '<div style="padding-left:14px;">• $1</div>');
103
- html = html.replace(/^(\d+)\. (.*)$/gm, '<div style="padding-left:20px;">$1. $2</div>');
104
- html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, '<a href="$1" style="color:var(--brand,#4f6ef7);text-decoration:underline;" target="_blank">$1</a>');
105
- html = html.replace(/\n/g, '<br>');
106
- html = html.replace(/\x00CB(\d+)\x00/g, function (_, idx) { return codeBlocks[parseInt(idx)]; });
107
- return html;
108
- }
109
-
110
- // 纯文本渲染:只转义HTML、换行和链接,不转标题/列表/加粗/代码块等格式
111
- // 用于对话流展示,让输出像普通人聊天一样清爽
112
- function renderPlainText(text) {
113
- let html = escapeHtml(stripMarkdown(text == null ? '' : text));
114
- html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, '<a href="$1" style="color:var(--brand,#4f6ef7);text-decoration:underline;" target="_blank">$1</a>');
115
- html = html.replace(/\n/g, '<br>');
116
- return html;
117
- }
118
-
119
- // 把 Markdown 格式符号全部去掉,只保留纯文本内容
120
- function stripMarkdown(text) {
121
- let s = String(text);
122
- // 去掉代码块 ```...``` 里的标记,保留内容
123
- s = s.replace(/```[\w]*\n?([\s\S]*?)```/g, '$1');
124
- // 去掉行内代码 `code` 的反引号,保留内容
125
- s = s.replace(/`([^`]+)`/g, '$1');
126
- // 去掉加粗 **text** 和 __text__
127
- s = s.replace(/\*\*([^*]+)\*\*/g, '$1');
128
- s = s.replace(/__([^_]+)__/g, '$1');
129
- // 去掉斜体 *text* 和 _text_(注意不要和列表冲突)
130
- s = s.replace(/\*([^*\n]+)\*/g, '$1');
131
- s = s.replace(/_([^_\n]+)_/g, '$1');
132
- // 去掉标题 # ## ### 等,保留标题文字
133
- s = s.replace(/^#{1,6}\s+/gm, '');
134
- // 去掉无序列表符号 * - + (行首)
135
- s = s.replace(/^[\s]*[-*+]\s+/gm, '');
136
- // 去掉有序列表符号 1. 2. 等(行首)
137
- s = s.replace(/^[\s]*\d+\.\s+/gm, '');
138
- // 去掉引用符号 > (行首)
139
- s = s.replace(/^[\s]*>\s?/gm, '');
140
- // 去掉链接 [text](url) 只保留 text
141
- s = s.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
142
- // 去掉图片 ![alt](url) 只保留 alt
143
- s = s.replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1');
144
- // 去掉分割线 --- *** ___
145
- s = s.replace(/^[-*_]{3,}\s*$/gm, '');
146
- // 去掉行号引用 L123、ln 456、第789行这种
147
- s = s.replace(/\b[Ll][nN]?\s*\d+(-\d+)?/g, '');
148
- s = s.replace(/第\d+行/g, '');
149
- // 去掉多余的空行(连续3个以上换行变成2个)
150
- s = s.replace(/\n{3,}/g, '\n\n');
151
- return s.trim();
152
- }
153
-
154
- function statusBadge(s) { return '<span class="badge ' + s + '">' + s + '</span>'; }
155
-
156
- function closeModal(id) { document.getElementById(id).classList.remove('show'); }
157
-
158
- function openModal(id) { document.getElementById(id).classList.add('show'); }
159
-
160
- function toast(msg) {
161
- const el = document.getElementById('toast');
162
- el.textContent = msg; el.classList.add('show');
163
- clearTimeout(el._t); el._t = setTimeout(() => el.classList.remove('show'), 2200);
164
- }
165
-
166
- function fmtTime(iso) { try { return new Date(iso).toLocaleString(); } catch { return iso || ''; } }
167
-
168
- function escapeHtml(s) { return String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])); }
169
-
170
- function applyI18nToEl(el) {
171
- const key = el.getAttribute('data-i18n');
172
- if (!key) return;
173
- const dict = I18N[currentLang] || I18N.zh;
174
- const tag = el.tagName;
175
-
176
- // 1) 输入类控件:只处理 placeholder,用 ph.<id> 专用键;缺失则保留中文原文
177
- if (tag === 'INPUT' || tag === 'TEXTAREA') {
178
- if (el._i18nPhZh === undefined) el._i18nPhZh = el.getAttribute('placeholder') || '';
179
- const phKey = 'ph.' + (el.id || '');
180
- if (dict[phKey] != null) el.placeholder = dict[phKey];
181
- else el.placeholder = el._i18nPhZh;
182
- return;
183
- }
184
-
185
- // 2) <select>:只翻 title,内容交给 renderModelSelect 等渲染函数管理
186
- if (tag === 'SELECT') {
187
- if (el._i18nTitleZh === undefined) el._i18nTitleZh = el.getAttribute('title') || '';
188
- const tiKey = 'title.' + (el.id || '');
189
- if (dict[tiKey] != null) el.title = dict[tiKey];
190
- else el.title = el._i18nTitleZh;
191
- return;
192
- }
193
-
194
- // 3) 含元素子节点:保留子元素,只替换 title 与直接文本节点
195
- if (el.firstElementChild) {
196
- if (el.hasAttribute('title')) el.title = t(key);
197
- let done = false;
198
- el.childNodes.forEach((node) => {
199
- if (node.nodeType === 3 && node.nodeValue.trim()) {
200
- node.nodeValue = done ? '' : t(key);
201
- done = true;
202
- }
203
- });
204
- return;
205
- }
206
-
207
- // 4) 纯文本元素:直接覆盖
208
- el.textContent = t(key);
209
- }
210
-
211
- function t(key) {
212
- const dict = I18N[currentLang] || I18N.zh;
213
- return dict[key] || key;
214
- }
1
+ /**
2
+ * 工具函数模块:纯函数,无状态依赖,可被任意模块调用
3
+ */
4
+
5
+ function formatMarkdown(text) {
6
+ // 简单 Markdown 转换
7
+ return text
8
+ .replace(/&/g, '&amp;')
9
+ .replace(/</g, '&lt;')
10
+ .replace(/>/g, '&gt;')
11
+ .replace(/^### (.*$)/gm, '<h3>$1</h3>')
12
+ .replace(/^## (.*$)/gm, '<h2>$1</h2>')
13
+ .replace(/^# (.*$)/gm, '<h1>$1</h1>')
14
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
15
+ .replace(/\*(.*?)\*/g, '<em>$1</em>')
16
+ .replace(/`(.*?)`/g, '<code>$1</code>')
17
+ .replace(/\n/g, '<br>');
18
+ }
19
+
20
+ function getDirectoryName(path) {
21
+ if (!path || path === '' || path === '/') return '/';
22
+ if (/^[A-Za-z]:$/.test(path)) return path + '\\';
23
+ if (/^[A-Za-z]:\\$/.test(path)) return path;
24
+ const parts = path.split(/[/\\]/).filter(Boolean);
25
+ if (parts.length <= 1) {
26
+ const driveMatch = parts[0].match(/^([A-Za-z]):$/);
27
+ if (driveMatch) return driveMatch[1] + ':\\';
28
+ return parts[0] || '/';
29
+ }
30
+ const parentParts = parts.slice(0, -1);
31
+ if (/^[A-Za-z]:$/.test(parentParts[0])) {
32
+ return parentParts[0] + '\\' + parentParts.slice(1).join('\\');
33
+ }
34
+ return parentParts.join('\\');
35
+ }
36
+
37
+ /** 渲染空状态提示,减少重复的 innerHTML 赋值代码 */
38
+ function renderEmpty(el, text) {
39
+ if (el) el.innerHTML = '<div class="empty">' + (text || '') + '</div>';
40
+ }
41
+
42
+ function extractUrl(text) {
43
+ if (!text) return '';
44
+ const m = text.match(/(https?:\/\/[^\s]+)/);
45
+ return m ? m[1] : '';
46
+ }
47
+
48
+ function linkifyArtifacts(text) {
49
+ let html = escapeHtml(text);
50
+ // 占位符保护:先提取已识别的片段,避免后续正则把已插入的 <span> 标签二次包裹
51
+ const tokens = [];
52
+ const protect = (s) => { const k = '\u0000TOK' + tokens.length + '\u0000'; tokens.push(s); return k; };
53
+ // 1) URL:排除结尾标点与 HTML 实体
54
+ html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, (m) => protect('<span class="artifact" data-kind="url" data-path="' + m + '">' + m + '</span>'));
55
+ // 2) Windows 绝对路径(支持正/反斜杠、中文、空格,排除结尾标点)
56
+ html = html.replace(/([A-Za-z]:[\\\/][^\s<>"'()]+?)(?=[\s<>"',。;:、))]|$)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
57
+ // 3) Unix 风格绝对路径(至少两级目录,避免误匹配 "2023/2024"、"a/b" 等相对写法)
58
+ html = html.replace(/(\/(?:[A-Za-z0-9_\-.]+\/){1,}[A-Za-z0-9_\-.]*)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
59
+ tokens.forEach((s, i) => { html = html.split('\u0000TOK' + i + '\u0000').join(s); });
60
+ return html;
61
+ }
62
+
63
+ function formatSize(n) {
64
+ if (!Number.isFinite(n)) return '';
65
+ if (n < 1024) return n + ' B';
66
+ if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
67
+ return (n / 1024 / 1024).toFixed(2) + ' MB';
68
+ }
69
+
70
+ function estimateDataUrlSize(dataUrl) {
71
+ // base64 长度 × 0.75 估算字节
72
+ const b64 = (dataUrl || '').split(',')[1] || '';
73
+ return Math.round(b64.length * 0.75);
74
+ }
75
+
76
+ function formatToolArgs(args) {
77
+ if (!args || typeof args !== 'object') return '';
78
+ const keys = Object.keys(args);
79
+ if (!keys.length) return '';
80
+ const rows = keys.map(function (k) {
81
+ let v = args[k];
82
+ if (v == null) v = '';
83
+ else if (typeof v === 'object') v = JSON.stringify(v);
84
+ return '<div><span style="color:var(--ink-2,#6b7280);">' + escapeHtml(k) + ':</span> ' + escapeHtml(String(v)) + '</div>';
85
+ });
86
+ return '<div class="tc-args">' + rows.join('') + '</div>';
87
+ }
88
+
89
+ function renderMarkdown(text) {
90
+ let html = escapeHtml(text == null ? '' : text);
91
+ const codeBlocks = [];
92
+ html = html.replace(/```(\w*)\n?([\s\S]*?)```/g, function (_, lang, code) {
93
+ const idx = codeBlocks.length;
94
+ codeBlocks.push('<pre style="background:var(--bg,#f5f6fa);padding:10px;border-radius:8px;overflow-x:auto;font-size:12px;margin:6px 0;white-space:pre-wrap;word-break:break-word;"><code>' + code + '</code></pre>');
95
+ return '\x00CB' + idx + '\x00';
96
+ });
97
+ html = html.replace(/`([^`]+)`/g, '<code style="background:var(--bg,#f5f6fa);padding:1px 5px;border-radius:4px;font-size:12px;">$1</code>');
98
+ html = html.replace(/\*\*([^*]+)\*\*/g, '<b>$1</b>');
99
+ html = html.replace(/^### (.*)$/gm, '<div style="font-weight:700;margin:8px 0 4px;">$1</div>');
100
+ html = html.replace(/^## (.*)$/gm, '<div style="font-weight:700;font-size:15px;margin:10px 0 4px;">$1</div>');
101
+ html = html.replace(/^# (.*)$/gm, '<div style="font-weight:700;font-size:16px;margin:10px 0 4px;">$1</div>');
102
+ html = html.replace(/^[-*] (.*)$/gm, '<div style="padding-left:14px;">• $1</div>');
103
+ html = html.replace(/^(\d+)\. (.*)$/gm, '<div style="padding-left:20px;">$1. $2</div>');
104
+ html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, '<a href="$1" style="color:var(--brand,#4f6ef7);text-decoration:underline;" target="_blank">$1</a>');
105
+ html = html.replace(/\n/g, '<br>');
106
+ html = html.replace(/\x00CB(\d+)\x00/g, function (_, idx) { return codeBlocks[parseInt(idx)]; });
107
+ return html;
108
+ }
109
+
110
+ // 纯文本渲染:只转义HTML、换行和链接,不转标题/列表/加粗/代码块等格式
111
+ // 用于对话流展示,让输出像普通人聊天一样清爽
112
+ function renderPlainText(text) {
113
+ let html = escapeHtml(stripMarkdown(text == null ? '' : text));
114
+ html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, '<a href="$1" style="color:var(--brand,#4f6ef7);text-decoration:underline;" target="_blank">$1</a>');
115
+ html = html.replace(/\n/g, '<br>');
116
+ return html;
117
+ }
118
+
119
+ // 把 Markdown 格式符号全部去掉,只保留纯文本内容
120
+ function stripMarkdown(text) {
121
+ let s = String(text);
122
+ // 去掉代码块 ```...``` 里的标记,保留内容
123
+ s = s.replace(/```[\w]*\n?([\s\S]*?)```/g, '$1');
124
+ // 去掉行内代码 `code` 的反引号,保留内容
125
+ s = s.replace(/`([^`]+)`/g, '$1');
126
+ // 去掉加粗 **text** 和 __text__
127
+ s = s.replace(/\*\*([^*]+)\*\*/g, '$1');
128
+ s = s.replace(/__([^_]+)__/g, '$1');
129
+ // 去掉斜体 *text* 和 _text_(注意不要和列表冲突)
130
+ s = s.replace(/\*([^*\n]+)\*/g, '$1');
131
+ s = s.replace(/_([^_\n]+)_/g, '$1');
132
+ // 去掉标题 # ## ### 等,保留标题文字
133
+ s = s.replace(/^#{1,6}\s+/gm, '');
134
+ // 去掉无序列表符号 * - + (行首)
135
+ s = s.replace(/^[\s]*[-*+]\s+/gm, '');
136
+ // 去掉有序列表符号 1. 2. 等(行首)
137
+ s = s.replace(/^[\s]*\d+\.\s+/gm, '');
138
+ // 去掉引用符号 > (行首)
139
+ s = s.replace(/^[\s]*>\s?/gm, '');
140
+ // 去掉链接 [text](url) 只保留 text
141
+ s = s.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
142
+ // 去掉图片 ![alt](url) 只保留 alt
143
+ s = s.replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1');
144
+ // 去掉分割线 --- *** ___
145
+ s = s.replace(/^[-*_]{3,}\s*$/gm, '');
146
+ // 去掉行号引用 L123、ln 456、第789行这种
147
+ s = s.replace(/\b[Ll][nN]?\s*\d+(-\d+)?/g, '');
148
+ s = s.replace(/第\d+行/g, '');
149
+ // 去掉多余的空行(连续3个以上换行变成2个)
150
+ s = s.replace(/\n{3,}/g, '\n\n');
151
+ return s.trim();
152
+ }
153
+
154
+ function statusBadge(s) { return '<span class="badge ' + s + '">' + s + '</span>'; }
155
+
156
+ function closeModal(id) { document.getElementById(id).classList.remove('show'); }
157
+
158
+ function openModal(id) { document.getElementById(id).classList.add('show'); }
159
+
160
+ function toast(msg) {
161
+ const el = document.getElementById('toast');
162
+ el.textContent = msg; el.classList.add('show');
163
+ clearTimeout(el._t); el._t = setTimeout(() => el.classList.remove('show'), 2200);
164
+ }
165
+
166
+ function fmtTime(iso) { try { return new Date(iso).toLocaleString(); } catch { return iso || ''; } }
167
+
168
+ function escapeHtml(s) { return String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])); }
169
+
170
+ function applyI18nToEl(el) {
171
+ const key = el.getAttribute('data-i18n');
172
+ if (!key) return;
173
+ const dict = I18N[currentLang] || I18N.zh;
174
+ const tag = el.tagName;
175
+
176
+ // 1) 输入类控件:只处理 placeholder,用 ph.<id> 专用键;缺失则保留中文原文
177
+ if (tag === 'INPUT' || tag === 'TEXTAREA') {
178
+ if (el._i18nPhZh === undefined) el._i18nPhZh = el.getAttribute('placeholder') || '';
179
+ const phKey = 'ph.' + (el.id || '');
180
+ if (dict[phKey] != null) el.placeholder = dict[phKey];
181
+ else el.placeholder = el._i18nPhZh;
182
+ return;
183
+ }
184
+
185
+ // 2) <select>:只翻 title,内容交给 renderModelSelect 等渲染函数管理
186
+ if (tag === 'SELECT') {
187
+ if (el._i18nTitleZh === undefined) el._i18nTitleZh = el.getAttribute('title') || '';
188
+ const tiKey = 'title.' + (el.id || '');
189
+ if (dict[tiKey] != null) el.title = dict[tiKey];
190
+ else el.title = el._i18nTitleZh;
191
+ return;
192
+ }
193
+
194
+ // 3) 含元素子节点:保留子元素,只替换 title 与直接文本节点
195
+ if (el.firstElementChild) {
196
+ if (el.hasAttribute('title')) el.title = t(key);
197
+ let done = false;
198
+ el.childNodes.forEach((node) => {
199
+ if (node.nodeType === 3 && node.nodeValue.trim()) {
200
+ node.nodeValue = done ? '' : t(key);
201
+ done = true;
202
+ }
203
+ });
204
+ return;
205
+ }
206
+
207
+ // 4) 纯文本元素:直接覆盖
208
+ el.textContent = t(key);
209
+ }
210
+
211
+ function t(key) {
212
+ const dict = I18N[currentLang] || I18N.zh;
213
+ return dict[key] || key;
214
+ }
@@ -1,59 +1,59 @@
1
- {
2
- "name": "飞虹 Code",
3
- "short_name": "飞虹Code",
4
- "description": "终端 AI 编程智能体,对标 Muse Code / Cursor",
5
- "start_url": "/",
6
- "display": "standalone",
7
- "background_color": "#1a1a2e",
8
- "theme_color": "#6366f1",
9
- "orientation": "any",
10
- "scope": "/",
11
- "lang": "zh-CN",
12
- "dir": "ltr",
13
- "categories": ["developer-tools", "productivity", "utilities"],
14
- "icons": [
15
- {
16
- "src": "/icons/icon-192.png",
17
- "sizes": "192x192",
18
- "type": "image/png",
19
- "purpose": "any maskable"
20
- },
21
- {
22
- "src": "/icons/icon-512.png",
23
- "sizes": "512x512",
24
- "type": "image/png",
25
- "purpose": "any maskable"
26
- }
27
- ],
28
- "shortcuts": [
29
- {
30
- "name": "新建任务",
31
- "short_name": "新任务",
32
- "description": "创建新的 AI 编程任务",
33
- "url": "/?action=new-task",
34
- "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
35
- },
36
- {
37
- "name": "代码补全",
38
- "short_name": "补全",
39
- "description": "快速代码补全",
40
- "url": "/?action=completion",
41
- "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
42
- },
43
- {
44
- "name": "代码审查",
45
- "short_name": "审查",
46
- "description": "AI 代码审查",
47
- "url": "/?action=review",
48
- "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
49
- }
50
- ],
51
- "prefer_related_applications": false,
52
- "features": [
53
- "Cross Platform",
54
- "AI Code Completion",
55
- "Multi-agent Collaboration",
56
- "Voice Programming",
57
- "Knowledge Library"
58
- ]
59
- }
1
+ {
2
+ "name": "飞虹 Code",
3
+ "short_name": "飞虹Code",
4
+ "description": "终端 AI 编程智能体,对标 Muse Code / Cursor",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "background_color": "#1a1a2e",
8
+ "theme_color": "#6366f1",
9
+ "orientation": "any",
10
+ "scope": "/",
11
+ "lang": "zh-CN",
12
+ "dir": "ltr",
13
+ "categories": ["developer-tools", "productivity", "utilities"],
14
+ "icons": [
15
+ {
16
+ "src": "/icons/icon-192.png",
17
+ "sizes": "192x192",
18
+ "type": "image/png",
19
+ "purpose": "any maskable"
20
+ },
21
+ {
22
+ "src": "/icons/icon-512.png",
23
+ "sizes": "512x512",
24
+ "type": "image/png",
25
+ "purpose": "any maskable"
26
+ }
27
+ ],
28
+ "shortcuts": [
29
+ {
30
+ "name": "新建任务",
31
+ "short_name": "新任务",
32
+ "description": "创建新的 AI 编程任务",
33
+ "url": "/?action=new-task",
34
+ "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
35
+ },
36
+ {
37
+ "name": "代码补全",
38
+ "short_name": "补全",
39
+ "description": "快速代码补全",
40
+ "url": "/?action=completion",
41
+ "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
42
+ },
43
+ {
44
+ "name": "代码审查",
45
+ "short_name": "审查",
46
+ "description": "AI 代码审查",
47
+ "url": "/?action=review",
48
+ "icons": [{ "src": "/icons/icon-192.png", "sizes": "192x192" }]
49
+ }
50
+ ],
51
+ "prefer_related_applications": false,
52
+ "features": [
53
+ "Cross Platform",
54
+ "AI Code Completion",
55
+ "Multi-agent Collaboration",
56
+ "Voice Programming",
57
+ "Knowledge Library"
58
+ ]
59
+ }