feihong-code 7.2.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 (204) hide show
  1. package/.github/workflows/ci.yml +54 -1
  2. package/.github/workflows/release.yml +30 -0
  3. package/.github/workflows/swebench-real.yml +84 -0
  4. package/CHANGELOG.md +41 -39
  5. package/CONTRIBUTING.md +9 -2
  6. package/README.md +56 -6
  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-engine.js +76 -45
  13. package/dist/agent/completion-engine.js.map +1 -1
  14. package/dist/agent/completion-postprocess.js +109 -0
  15. package/dist/agent/completion-postprocess.js.map +1 -0
  16. package/dist/agent/context-budget.js +121 -0
  17. package/dist/agent/context-budget.js.map +1 -0
  18. package/dist/agent/context-compactor.js +58 -0
  19. package/dist/agent/context-compactor.js.map +1 -1
  20. package/dist/agent/experience.js +1 -1
  21. package/dist/agent/layered-memory.js +1 -1
  22. package/dist/agent/lint.js +121 -0
  23. package/dist/agent/lint.js.map +1 -0
  24. package/dist/agent/orchestrator.js +106 -31
  25. package/dist/agent/orchestrator.js.map +1 -1
  26. package/dist/agent/parallel-orchestrator.js +1 -1
  27. package/dist/agent/planner.js +8 -3
  28. package/dist/agent/planner.js.map +1 -1
  29. package/dist/agent/prompts.js +55 -55
  30. package/dist/agent/quality-gate.js +1 -1
  31. package/dist/agent/repo-context.js +1 -1
  32. package/dist/agent/repo-reader.js +1 -1
  33. package/dist/agent/repo-underwriter.js +1 -1
  34. package/dist/agent/self-correction.js +25 -25
  35. package/dist/agent/self-heal.js +32 -27
  36. package/dist/agent/self-heal.js.map +1 -1
  37. package/dist/agent/self-improver.js +1 -1
  38. package/dist/agent/subagent-summary.js +1 -1
  39. package/dist/agent/subagent.js +1 -1
  40. package/dist/agent/swe-agent.js +1 -1
  41. package/dist/agent/swe-verifier.js +1 -1
  42. package/dist/agent/symbol-index.js +1 -1
  43. package/dist/agent/team.js +1 -1
  44. package/dist/agent/type-checker.js +1 -1
  45. package/dist/cli/commands.js +16 -0
  46. package/dist/cli/commands.js.map +1 -1
  47. package/dist/cli/index.js +66 -2
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/cli/multi-pane-tui.js +217 -0
  50. package/dist/cli/multi-pane-tui.js.map +1 -0
  51. package/dist/cli/repl.js +1 -1
  52. package/dist/cli/run.js +168 -42
  53. package/dist/cli/run.js.map +1 -1
  54. package/dist/cli/self-evolve-cli.js +168 -0
  55. package/dist/cli/tui-run.js +79 -0
  56. package/dist/cli/tui-run.js.map +1 -0
  57. package/dist/cli/tui.js +1 -1
  58. package/dist/cli/tui.js.map +1 -1
  59. package/dist/cli/version.js +3 -3
  60. package/dist/cli/version.js.map +1 -1
  61. package/dist/enterprise/audit.js +1 -1
  62. package/dist/enterprise/index.js +1 -1
  63. package/dist/enterprise/policy.js +1 -1
  64. package/dist/enterprise/quota.js +1 -1
  65. package/dist/enterprise/tenant.js +1 -1
  66. package/dist/harness/executor.js +1 -1
  67. package/dist/harness/index.js +1 -1
  68. package/dist/harness/loader.js +1 -1
  69. package/dist/harness/types.js +1 -1
  70. package/dist/harness/verifier.js +52 -12
  71. package/dist/harness/verifier.js.map +1 -1
  72. package/dist/integrations/feishu-bridge.js +348 -0
  73. package/dist/integrations/feishu-bridge.js.map +1 -0
  74. package/dist/integrations/github-mcp.js +137 -0
  75. package/dist/integrations/github-mcp.js.map +1 -0
  76. package/dist/integrations/wechat-bridge.js +499 -0
  77. package/dist/integrations/wechat-bridge.js.map +1 -0
  78. package/dist/integrations/yuanbao-bridge.js +326 -0
  79. package/dist/integrations/yuanbao-bridge.js.map +1 -0
  80. package/dist/lsp/lsp-client.js +183 -0
  81. package/dist/lsp/lsp-client.js.map +1 -0
  82. package/dist/lsp/lsp-service.js +159 -0
  83. package/dist/lsp/lsp-service.js.map +1 -0
  84. package/dist/models/model-router.js +1 -1
  85. package/dist/models/model.dto.js +1 -1
  86. package/dist/models/providers/ollama.provider.js +1 -1
  87. package/dist/models/providers/openai-compatible.provider.js +1 -1
  88. package/dist/plugins/manager.js +50 -2
  89. package/dist/plugins/manager.js.map +1 -1
  90. package/dist/plugins/plugin-loader.js +1 -1
  91. package/dist/runtime/event-log.js +1 -1
  92. package/dist/runtime/git.js +1 -1
  93. package/dist/runtime/hooks.js +71 -4
  94. package/dist/runtime/hooks.js.map +1 -1
  95. package/dist/runtime/session-persist.js +1 -1
  96. package/dist/runtime/worktree.js +1 -1
  97. package/dist/self-evolve/manager.js +517 -401
  98. package/dist/self-evolve/self-heal-scheduler.js +160 -0
  99. package/dist/self-evolve/self-heal-scheduler.js.map +1 -0
  100. package/dist/shared/concurrency.js +1 -1
  101. package/dist/shared/config.js +4 -2
  102. package/dist/shared/config.js.map +1 -1
  103. package/dist/shared/errors.js +1 -1
  104. package/dist/shared/i18n.js +109 -101
  105. package/dist/shared/i18n.js.map +1 -1
  106. package/dist/shared/secure-store.js +12 -5
  107. package/dist/shared/secure-store.js.map +1 -1
  108. package/dist/shared/types.js +1 -1
  109. package/dist/skills/goal.js +1 -1
  110. package/dist/skills/grill.js +1 -1
  111. package/dist/skills/plan.js +1 -1
  112. package/dist/skills/pua-hooks.js +273 -0
  113. package/dist/skills/pua-hooks.js.map +1 -0
  114. package/dist/skills/self-heal.js +9 -3
  115. package/dist/skills/self-heal.js.map +1 -1
  116. package/dist/skills/skill-loader.js +1 -1
  117. package/dist/skills/skill-market.js +84 -8
  118. package/dist/skills/skill-market.js.map +1 -1
  119. package/dist/tools/analysis/code-analyzer.js +1 -1
  120. package/dist/tools/file/edit.tool.js +18 -3
  121. package/dist/tools/file/edit.tool.js.map +1 -1
  122. package/dist/tools/file/list.tool.js +1 -1
  123. package/dist/tools/file/read.tool.js +1 -1
  124. package/dist/tools/file/write.tool.js +1 -1
  125. package/dist/tools/generator/code-generator.js +41 -41
  126. package/dist/tools/generator/test-generator.js +10 -10
  127. package/dist/tools/index.js +1 -1
  128. package/dist/tools/mcp/index.js +1 -1
  129. package/dist/tools/mcp/mcp-client.js +1 -1
  130. package/dist/tools/safe-path.js +1 -1
  131. package/dist/tools/search/grep.tool.js +1 -1
  132. package/dist/tools/shell/exec.js +24 -2
  133. package/dist/tools/shell/exec.js.map +1 -1
  134. package/dist/tools/shell/run-shell.tool.js +1 -1
  135. package/dist/tools/skills/load-skill.tool.js +1 -1
  136. package/dist/tools/tool.registry.js +10 -1
  137. package/dist/tools/tool.registry.js.map +1 -1
  138. package/dist/tools/verify/build-check.tool.js +1 -1
  139. package/dist/tools/verify/test-run.tool.js +1 -1
  140. package/dist/tools/web/web.tool.js +1 -1
  141. package/dist/voice/voice-programming.js +32 -6
  142. package/dist/voice/voice-programming.js.map +1 -1
  143. package/dist/web/auth.js +34 -2
  144. package/dist/web/auth.js.map +1 -1
  145. package/dist/web/channels.js +1 -1
  146. package/dist/web/extra-apis.js +440 -0
  147. package/dist/web/extra-apis.js.map +1 -0
  148. package/dist/web/public/css/style.css +99 -72
  149. package/dist/web/public/index.html +44 -1
  150. package/dist/web/public/js/api.js +64 -2
  151. package/dist/web/public/js/app.js +151 -128
  152. package/dist/web/public/js/mock-api.js +25 -0
  153. package/dist/web/public/js/monaco-editor.js +161 -1
  154. package/dist/web/public/js/ui.js +292 -56
  155. package/dist/web/public/service-worker.js +5 -29
  156. package/dist/web/server.js +178 -61
  157. package/dist/web/server.js.map +1 -1
  158. package/dist/web/task-queue.js +6 -21
  159. package/dist/web/task-queue.js.map +1 -1
  160. package/docs/App/344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +1 -1
  161. package/docs/App/346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +1 -1
  162. package/docs/BENCHMARK_REPORT_en.md +62 -5
  163. package/docs/BENCHMARK_REPORT_zh.md +66 -9
  164. package/docs/DPA.md +65 -0
  165. 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 -0
  166. package/docs/Deployment_Guide_EN.md +1 -1
  167. package/docs/SECURITY_WHITEPAPER.md +74 -0
  168. package/docs/SELF-EVOLVE-GUIDE.md +1 -1
  169. package/docs/SWE_BENCH_REPORT.md +73 -0
  170. package/docs/TECHNICAL_SPEC_en.md +1 -1
  171. package/docs/TECHNICAL_SPEC_zh.md +1 -1
  172. package/docs/Technical_Manual_EN.md +1 -1
  173. package/docs/UPDATE_NOTES_en.md +1 -1
  174. package/docs/UPDATE_NOTES_zh.md +1 -1
  175. package/docs/UPGRADE_7.2.0.md +309 -0
  176. package/docs/UPGRADE_GUIDE_7_5.md +86 -0
  177. package/docs/UPGRADE_GUIDE_7_6.md +153 -0
  178. package/docs/User_Manual_EN.md +1 -1
  179. package/docs/VOLTAGENT_SKILLS_CATALOG.md +95 -0
  180. package/docs/error-codes.md +1 -1
  181. package/docs/geo-feihong-code.html +391 -0
  182. package/docs//344/272/247/345/223/201/345/274/200/345/217/221/346/226/207/346/241/243.md +5 -3
  183. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +140 -231
  184. 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
  185. 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
  186. 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
  187. 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
  188. package/docs//345/256/211/345/205/250/347/231/275/347/232/256/344/271/246_v7.2.0.md +84 -0
  189. package/docs//346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +240 -149
  190. package/docs//351/203/250/347/275/262/350/257/264/346/230/216/344/271/246.md +2 -2
  191. package/electron/main.js +4 -202
  192. package/package.json +182 -172
  193. package/templates/skills/api-design/SKILL.md +27 -0
  194. package/templates/skills/code-review/SKILL.md +35 -0
  195. package/templates/skills/dependency-upgrade/SKILL.md +29 -0
  196. package/templates/skills/doc-gen/SKILL.md +29 -0
  197. package/templates/skills/git-flow/SKILL.md +26 -0
  198. package/templates/skills/onboarding/SKILL.md +27 -0
  199. package/templates/skills/performance/SKILL.md +29 -0
  200. package/templates/skills/refactor/SKILL.md +28 -0
  201. package/templates/skills/security-audit/SKILL.md +28 -0
  202. package/templates/skills/test-gen/SKILL.md +30 -0
  203. package/docs/DEPLOYMENT.md +0 -382
  204. package/docs/MODEL_FINETUNING.md +0 -405
@@ -1,4 +1,4 @@
1
- :root {
1
+ :root {
2
2
  --bg: #f5f7fa;
3
3
  --card: #ffffff;
4
4
  --ink: #1f2933;
@@ -35,7 +35,7 @@
35
35
  overflow: hidden;
36
36
  }
37
37
 
38
- /* ========== 登录遮罩 ========== */
38
+ /* ========== 鐧诲綍閬僵 ========== */
39
39
  #loginOverlay {
40
40
  position: fixed; inset: 0; background: var(--bg); z-index: 50;
41
41
  display: flex; align-items: center; justify-content: center;
@@ -58,7 +58,7 @@
58
58
  #loginOverlay .login-status { font-size: 13px; margin-top: 10px; min-height: 18px; }
59
59
  #loginOverlay .login-status.err { color: var(--err); }
60
60
 
61
- /* ========== 主布局 ========== */
61
+ /* ========== 涓诲竷灞€ ========== */
62
62
  .app-layout {
63
63
  display: flex;
64
64
  flex-direction: column;
@@ -66,11 +66,11 @@
66
66
  display: none;
67
67
  }
68
68
  .app-layout.show { display: flex; }
69
- /* 已登录状态:提前隐藏登录页,显示应用布局,避免闪烁(感觉像打开两次) */
69
+ /* 宸茬櫥褰曠姸鎬侊細鎻愬墠闅愯棌鐧诲綍椤碉紝鏄剧ず搴旂敤甯冨眬锛岄伩鍏嶉棯鐑侊紙鎰熻鍍忔墦寮€涓ゆ锛?*/
70
70
  html.logged-in #loginOverlay { display: none !important; }
71
71
  html.logged-in .app-layout { display: flex !important; }
72
72
 
73
- /* ========== 顶部导航栏 ========== */
73
+ /* ========== 椤堕儴瀵艰埅鏍?========== */
74
74
  .topbar {
75
75
  height: var(--topbar-height);
76
76
  background: var(--card);
@@ -152,9 +152,9 @@
152
152
  .lang-btn.active { background: var(--brand); color: #fff; }
153
153
  .lang-btn:hover:not(.active) { background: var(--bg); }
154
154
 
155
- /* ========== 主体内容区 ========== */
156
- /* overflow 必须为 hidden:约束内部 .messages / .sidebar 各自滚动,
157
- 原生 <select> 弹层由浏览器绘制在顶层,不受此裁剪影响。 */
155
+ /* ========== 涓讳綋鍐呭鍖?========== */
156
+ /* overflow 蹇呴』涓?hidden锛氱害鏉熷唴閮?.messages / .sidebar 鍚勮嚜婊氬姩锛?
157
+ 鍘熺敓 <select> 寮瑰眰鐢辨祻瑙堝櫒缁樺埗鍦ㄩ《灞傦紝涓嶅彈姝よ鍓奖鍝嶃€?*/
158
158
  .main-area {
159
159
  flex: 1;
160
160
  display: flex;
@@ -165,7 +165,7 @@
165
165
  width: 100%;
166
166
  }
167
167
 
168
- /* ========== 左侧侧边栏 ========== */
168
+ /* ========== 宸︿晶渚ц竟鏍?========== */
169
169
  .sidebar {
170
170
  width: 200px;
171
171
  background: var(--card);
@@ -290,7 +290,7 @@
290
290
  .task-item .task-actions .delete-btn:hover { background: #fee2e2; color: var(--err); }
291
291
  .task-pinned { color: var(--warn); }
292
292
 
293
- /* ========== 中间对话区 ========== */
293
+ /* ========== 涓棿瀵硅瘽鍖?========== */
294
294
  .chat-area {
295
295
  flex: 1;
296
296
  display: flex;
@@ -299,7 +299,7 @@
299
299
  background: var(--bg);
300
300
  }
301
301
 
302
- /* ========== 任务上下文头部 ========== */
302
+ /* ========== 浠诲姟涓婁笅鏂囧ご閮?========== */
303
303
  .task-context-header {
304
304
  display: flex;
305
305
  align-items: center;
@@ -315,7 +315,7 @@
315
315
  .tch-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
316
316
  .tch-time { font-size: 12px; color: var(--muted); }
317
317
 
318
- /* ========== 思维链路线程 ========== */
318
+ /* ========== 鎬濈淮閾捐矾绾跨▼ ========== */
319
319
  .messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 16px; padding-right: 4px; }
320
320
  .step { max-width: 92%; font-size: 13.5px; line-height: 1.6; word-break: break-word; }
321
321
  .step.created {
@@ -350,7 +350,7 @@
350
350
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--muted);
351
351
  }
352
352
  .step.note { align-self: stretch; background: var(--bg); border-radius: 8px; padding: 6px 12px; color: var(--muted); font-size: 12px; }
353
- /* 对话流与思维链路分隔标题 */
353
+ /* 瀵硅瘽娴佷笌鎬濈淮閾捐矾鍒嗛殧鏍囬 */
354
354
  .conv-divider {
355
355
  align-self: stretch; text-align: center; font-size: 11px; color: var(--muted);
356
356
  border-top: 1px solid var(--line); padding-top: 8px; margin-top: 4px;
@@ -378,7 +378,7 @@
378
378
  padding: 12px 16px; white-space: pre-wrap; word-break: break-word; max-width: 92%;
379
379
  }
380
380
 
381
- /* 对话消息区 */
381
+ /* 瀵硅瘽娑堟伅鍖?*/
382
382
  .conv {
383
383
  flex: 1;
384
384
  display: flex;
@@ -410,26 +410,31 @@
410
410
  }
411
411
  .msg-actions {
412
412
  position: absolute;
413
- top: 6px;
414
- right: 6px;
415
- display: none;
413
+ bottom: 4px;
414
+ right: 8px;
415
+ display: flex;
416
416
  gap: 4px;
417
- background: rgba(255,255,255,0.95);
417
+ background: rgba(255,255,255,0.92);
418
418
  border-radius: 6px;
419
- padding: 2px;
420
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
419
+ padding: 2px 4px;
420
+ box-shadow: 0 1px 6px rgba(0,0,0,0.08);
421
+ opacity: 0.35;
422
+ transition: opacity 0.2s ease;
423
+ user-select: none;
424
+ z-index: 2;
421
425
  }
422
426
  .msg:hover .msg-actions {
423
- display: flex;
427
+ opacity: 1;
424
428
  }
425
429
  .msg-action-btn {
426
430
  background: none;
427
431
  border: none;
428
- padding: 4px 8px;
432
+ padding: 5px 10px;
429
433
  font-size: 12px;
430
434
  cursor: pointer;
431
435
  border-radius: 4px;
432
436
  color: var(--ink-2);
437
+ white-space: nowrap;
433
438
  }
434
439
  .msg-action-btn:hover {
435
440
  background: var(--brand-soft);
@@ -444,7 +449,7 @@
444
449
  border: 1px solid var(--border);
445
450
  align-self: flex-start;
446
451
  }
447
- /* ========== 思考过程气泡(Cursor 风格) ========== */
452
+ /* ========== 鎬濊€冭繃绋嬫皵娉★紙Cursor 椋庢牸锛?========== */
448
453
  .msg.assistant.thinking-msg {
449
454
  background: var(--card);
450
455
  border: 1px solid var(--border);
@@ -554,7 +559,7 @@
554
559
  padding-top: 8px;
555
560
  border-top: 1px solid var(--line);
556
561
  }
557
- /* 思考中状态指示 */
562
+ /* 鎬濊€冧腑鐘舵€佹寚绀?*/
558
563
  .thinking-indicator {
559
564
  display: flex;
560
565
  align-items: center;
@@ -584,7 +589,7 @@
584
589
  }
585
590
  .dark .msg.sys { background: #334155; }
586
591
  .msg .artifact { color: var(--brand); text-decoration: underline; cursor: pointer; }
587
- /* 内部执行过程:默认折叠,避免"一直都在调用/验证"的噪声;点击展开查看思考与工具调用 */
592
+ /* 鍐呴儴鎵ц杩囩▼锛氶粯璁ゆ姌鍙狅紝閬垮厤"涓€鐩撮兘鍦ㄨ皟鐢?楠岃瘉"鐨勫櫔澹帮紱鐐瑰嚮灞曞紑鏌ョ湅鎬濊€冧笌宸ュ叿璋冪敤 */
588
593
  .proc-details {
589
594
  align-self: stretch; margin-top: 6px; border-top: 1px dashed var(--line);
590
595
  padding: 8px 0 2px; display: flex; flex-direction: column; gap: 8px;
@@ -600,7 +605,7 @@
600
605
  .error-msg { border-left: 3px solid var(--err); align-self: flex-start; color: var(--err); }
601
606
  .msg .artifact:hover { opacity: 0.8; }
602
607
 
603
- /* 输入栏 */
608
+ /* 杈撳叆鏍?*/
604
609
  .input-area {
605
610
  padding: 0 16px 16px;
606
611
  flex-shrink: 0;
@@ -645,7 +650,7 @@
645
650
  .pill:hover { border-color: var(--brand); }
646
651
  .voice-badge { display: inline-flex; align-items: center; gap: 6px; color: var(--err); font-size: 12px; }
647
652
 
648
- /* 工作区条 */
653
+ /* 宸ヤ綔鍖烘潯 */
649
654
  .workspace-bar {
650
655
  display: flex;
651
656
  align-items: center;
@@ -692,7 +697,7 @@
692
697
  }
693
698
  .wb-perm:hover { border-color: var(--brand); }
694
699
 
695
- /* 通话栏 */
700
+ /* 閫氳瘽鏍?*/
696
701
  .call-bar {
697
702
  display: flex;
698
703
  align-items: center;
@@ -716,7 +721,7 @@
716
721
  .call-btn.hangup { background: #fee2e2; color: var(--err); border-color: #fecaca; }
717
722
  .call-status { font-size: 12px; color: var(--muted); margin-left: auto; }
718
723
 
719
- /* 视频通话窗口 */
724
+ /* 瑙嗛閫氳瘽绐楀彛 */
720
725
  .video-call-window {
721
726
  position: fixed;
722
727
  bottom: 100px;
@@ -765,7 +770,7 @@
765
770
  background: #000;
766
771
  }
767
772
 
768
- /* 底部工具栏 */
773
+ /* 搴曢儴宸ュ叿鏍?*/
769
774
  .chat-footbar {
770
775
  display: flex;
771
776
  align-items: center;
@@ -795,7 +800,7 @@
795
800
  }
796
801
  .ghost-btn:hover { background: var(--brand-soft); }
797
802
 
798
- /* 新建任务按钮(侧边栏) */
803
+ /* 鏂板缓浠诲姟鎸夐挳锛堜晶杈规爮锛?*/
799
804
  .new-task-btn {
800
805
  border: 1px solid var(--border);
801
806
  background: var(--brand);
@@ -809,7 +814,7 @@
809
814
  }
810
815
  .new-task-btn:hover { opacity: 0.88; }
811
816
 
812
- /* 新建对话任务弹窗 */
817
+ /* 鏂板缓瀵硅瘽浠诲姟寮圭獥 */
813
818
  .nt-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
814
819
  .nt-label { font-size: 12.5px; font-weight: 600; color: var(--ink-2); display: block; margin-bottom: 4px; }
815
820
  .nt-form textarea, .nt-form select {
@@ -822,7 +827,7 @@
822
827
  .nt-row > div { flex: 1; }
823
828
  .nt-hint { font-size: 12px; color: var(--muted); }
824
829
 
825
- /* ========== 右侧面板 ========== */
830
+ /* ========== 鍙充晶闈㈡澘 ========== */
826
831
  .right-panel {
827
832
  width: 320px;
828
833
  background: var(--card);
@@ -861,7 +866,7 @@
861
866
  }
862
867
  .preview-content pre { margin: 0; white-space: pre-wrap; word-break: break-word; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
863
868
 
864
- /* 电脑操作面板 */
869
+ /* 鐢佃剳鎿嶄綔闈㈡澘 */
865
870
  .computer-controls { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
866
871
  .screen-preview {
867
872
  background: var(--bg);
@@ -891,7 +896,7 @@
891
896
  }
892
897
  .computer-actions .pill:hover { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); }
893
898
 
894
- /* 任务详情 */
899
+ /* 浠诲姟璇︽儏 */
895
900
  .detail-ops {
896
901
  display: grid;
897
902
  grid-template-columns: 1fr 1fr;
@@ -921,7 +926,7 @@
921
926
  }
922
927
  .artifact-file:hover { background: var(--brand-soft); color: var(--brand); }
923
928
 
924
- /* ========== 功能页面 ========== */
929
+ /* ========== 鍔熻兘椤甸潰 ========== */
925
930
  .page-view {
926
931
  flex: 1;
927
932
  display: none;
@@ -948,7 +953,7 @@
948
953
  .tile .desc { color: var(--muted); font-size: 12px; line-height: 1.5; }
949
954
  .tile .ops { display: flex; gap: 6px; margin-top: 12px; }
950
955
  .tile .ops button { padding: 6px 12px; font-size: 12px; flex: 1; }
951
- /* 预置指令卡片:带渐变边框,和用户自定义区分 */
956
+ /* 棰勭疆鎸囦护鍗$墖锛氬甫娓愬彉杈规锛屽拰鐢ㄦ埛鑷畾涔夊尯鍒?*/
952
957
  .tile.builtin-tile {
953
958
  background: linear-gradient(135deg, var(--card) 0%, rgba(37,99,235,0.03) 100%);
954
959
  border: 1px solid var(--brand-soft);
@@ -957,7 +962,7 @@
957
962
  .tile.builtin-tile .ops { flex-wrap: wrap; }
958
963
  .tile.builtin-tile .ops button { flex: 1 1 auto; }
959
964
 
960
- /* ========== 产品发布故事页面 ========== */
965
+ /* ========== 浜у搧鍙戝竷鏁呬簨椤甸潰 ========== */
961
966
  .release-container { max-width: 900px; margin: 0 auto; }
962
967
  .release-hero {
963
968
  text-align: center;
@@ -1189,7 +1194,7 @@
1189
1194
  .cta-btn.secondary:hover { background: var(--brand-soft); }
1190
1195
  .cta-sub { color: var(--muted); font-size: 13px; }
1191
1196
 
1192
- /* ========== 通用样式 ========== */
1197
+ /* ========== 閫氱敤鏍峰紡 ========== */
1193
1198
  .card {
1194
1199
  background: var(--card);
1195
1200
  border: 1px solid var(--border);
@@ -1234,7 +1239,7 @@
1234
1239
  .badge.done { background: #f0fdf4; color: var(--ok); }
1235
1240
  .badge.failed { background: #fef2f2; color: var(--err); }
1236
1241
 
1237
- /* ========== 模态框 ========== */
1242
+ /* ========== 妯℃€佹 ========== */
1238
1243
  .mask {
1239
1244
  position: fixed;
1240
1245
  inset: 0;
@@ -1260,7 +1265,7 @@
1260
1265
  .modal .footer { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
1261
1266
  .close-x { float: right; cursor: pointer; color: var(--muted); font-size: 18px; }
1262
1267
 
1263
- /* ========== 下拉菜单 ========== */
1268
+ /* ========== 涓嬫媺鑿滃崟 ========== */
1264
1269
  .dropdown { position: relative; }
1265
1270
  .dropdown-menu {
1266
1271
  position: absolute;
@@ -1281,21 +1286,21 @@
1281
1286
  .dropdown-item:hover { background: var(--bg); }
1282
1287
  .dropdown-divider { height: 1px; background: var(--line); margin: 6px 0; }
1283
1288
 
1284
- /* ========== 权限窗口 ========== */
1289
+ /* ========== 鏉冮檺绐楀彛 ========== */
1285
1290
  .perm-section { margin-bottom: 14px; }
1286
1291
  .perm-title { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
1287
1292
  .perm-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 13px; }
1288
1293
  .perm-row input[type="checkbox"] { width: auto; margin: 0; }
1289
1294
  .perm-row label { margin: 0; color: var(--ink-2); }
1290
1295
 
1291
- /* ========== 智能体选择 ========== */
1296
+ /* ========== 鏅鸿兘浣撻€夋嫨 ========== */
1292
1297
  .agent-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
1293
1298
  .agent-card { border: 1px solid var(--border); border-radius: 12px; padding: 14px; text-align: center; cursor: pointer; }
1294
1299
  .agent-card:hover, .agent-card.selected { border-color: var(--brand); background: var(--brand-soft); }
1295
1300
  .agent-card .icon { font-size: 24px; }
1296
1301
  .agent-card .title { font-size: 13px; font-weight: 600; margin-top: 6px; }
1297
1302
 
1298
- /* ========== 大模型管理 ========== */
1303
+ /* ========== 澶фā鍨嬬鐞?========== */
1299
1304
  .model-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; max-height: 200px; overflow-y: auto; }
1300
1305
  .model-item {
1301
1306
  border: 1px solid var(--border);
@@ -1344,7 +1349,7 @@
1344
1349
  .ghost { background: var(--card); color: var(--ink-2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 16px; cursor: pointer; font-size: 13px; }
1345
1350
  .primary.sm, .ghost.sm { padding: 5px 12px; font-size: 12px; }
1346
1351
 
1347
- /* ========== 设置面板 ========== */
1352
+ /* ========== 璁剧疆闈㈡澘 ========== */
1348
1353
  .settings-layout { display: flex; gap: 0; min-height: 360px; }
1349
1354
  .settings-nav { flex: 0 0 130px; border-right: 1px solid var(--line); padding-right: 8px; }
1350
1355
  .settings-cat { padding: 9px 10px; border-radius: 8px; cursor: pointer; font-size: 13px; color: var(--ink-2); }
@@ -1369,7 +1374,7 @@
1369
1374
  .settings-item .si-desc { font-size: 12px; color: var(--muted); }
1370
1375
  .settings-item .si-arrow { color: var(--muted); }
1371
1376
 
1372
- /* ========== 设置·大模型管理(简洁卡片风) ========== */
1377
+ /* ========== 璁剧疆路澶фā鍨嬬鐞嗭紙绠€娲佸崱鐗囬锛?========== */
1373
1378
  .model-manage { margin-top: 4px; }
1374
1379
  .mm-list { display: flex; flex-direction: column; gap: 8px; }
1375
1380
  .mm-empty {
@@ -1413,7 +1418,7 @@
1413
1418
  align-items: center;
1414
1419
  gap: 4px;
1415
1420
  }
1416
- .mm-card-url::before { content: '🔗'; font-size: 11px; opacity: 0.7; }
1421
+ .mm-card-url::before { content: '馃敆'; font-size: 11px; opacity: 0.7; }
1417
1422
  .mm-card-meta { font-size: 11px; color: var(--muted); }
1418
1423
  .mm-card-actions {
1419
1424
  display: flex;
@@ -1438,7 +1443,7 @@
1438
1443
  .mm-act-primary:hover { background: var(--brand-soft); }
1439
1444
  .mm-act-danger { color: var(--muted); }
1440
1445
  .mm-act-danger:hover { color: var(--err); background: transparent; }
1441
- /* 分隔 */
1446
+ /* 鍒嗛殧 */
1442
1447
  .mm-divider {
1443
1448
  display: flex;
1444
1449
  align-items: center;
@@ -1453,7 +1458,7 @@
1453
1458
  height: 1px;
1454
1459
  background: var(--line);
1455
1460
  }
1456
- /* 表单 */
1461
+ /* 琛ㄥ崟 */
1457
1462
  .mm-form {
1458
1463
  display: flex;
1459
1464
  flex-direction: column;
@@ -1482,7 +1487,7 @@
1482
1487
  .mm-form-actions .mm-form-msg { font-size: 12px; color: var(--muted); margin-left: auto; }
1483
1488
  .mm-form-actions .mm-form-msg.err { color: var(--err); }
1484
1489
 
1485
- /* ========== 用户菜单(右侧侧边栏样式) ========== */
1490
+ /* ========== 鐢ㄦ埛鑿滃崟锛堝彸渚т晶杈规爮鏍峰紡锛?========== */
1486
1491
  .bottom-sheet-mask {
1487
1492
  position: fixed;
1488
1493
  inset: 0;
@@ -1511,7 +1516,7 @@
1511
1516
  .sheet-item .icon { width: 22px; text-align: center; }
1512
1517
  .sheet-item .right { margin-left: auto; font-size: 12px; color: var(--muted); }
1513
1518
 
1514
- /* ========== 工作区 ========== */
1519
+ /* ========== 宸ヤ綔鍖?========== */
1515
1520
  .workspace-box { border: 1px solid var(--border); border-radius: 10px; padding: 10px; background: var(--bg); }
1516
1521
  .workspace-cwd { font-size: 12px; color: var(--ink-2); word-break: break-all; margin-bottom: 8px; }
1517
1522
  .workspace-input { display: flex; gap: 6px; }
@@ -1525,10 +1530,10 @@
1525
1530
  .drive-option { padding: 3px 10px; margin-top: 4px; border-radius: 4px; font-size: 11px; cursor: pointer; color: var(--ink-2); }
1526
1531
  .drive-option:hover { background: var(--brand-soft); color: var(--brand); }
1527
1532
 
1528
- /* ========== 文件芯片 ========== */
1533
+ /* ========== 鏂囦欢鑺墖 ========== */
1529
1534
  .file-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--brand-soft); color: var(--brand); padding: 4px 8px; border-radius: 6px; font-size: 12px; cursor: pointer; }
1530
1535
  .file-chip:hover { opacity: 0.85; }
1531
- /* 输入区·待发送附件暂存(点发送时统一上传给 AI) */
1536
+ /* 杈撳叆鍖郝峰緟鍙戦€侀檮浠舵殏瀛橈紙鐐瑰彂閫佹椂缁熶竴涓婁紶缁?AI锛?*/
1532
1537
  .staged-area {
1533
1538
  display: none;
1534
1539
  flex-wrap: wrap;
@@ -1574,10 +1579,10 @@
1574
1579
  margin-left: 4px;
1575
1580
  }
1576
1581
 
1577
- /* ========== 截图遮罩 ========== */
1578
- .crop-overlay { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,0.35); cursor: crosshair; }
1579
- .crop-tip { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.7); color: #fff; padding: 6px 14px; border-radius: 20px; font-size: 13px; pointer-events: none; }
1580
- .crop-selection { position: fixed; border: 2px dashed #fff; background: rgba(255,255,255,0.12); box-shadow: 0 0 0 9999px rgba(0,0,0,0.25); pointer-events: none; }
1582
+ /* ========== 鎴浘閬僵 ========== */
1583
+ .crop-overlay { position: fixed; inset: 0; z-index: 9999; background: #000; cursor: crosshair; }
1584
+ .crop-tip { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.8); color: #fff; padding: 8px 18px; border-radius: 20px; font-size: 13px; pointer-events: none; z-index: 10001; }
1585
+ .crop-selection { position: fixed; border: 2px dashed #00ffcc; background: rgba(0,255,204,0.08); box-shadow: 0 0 0 9999px rgba(0,0,0,0.5); pointer-events: none; z-index: 10000; display: none; }
1581
1586
 
1582
1587
  /* ========== Toast ========== */
1583
1588
  .toast {
@@ -1597,10 +1602,10 @@
1597
1602
  }
1598
1603
  .toast.show { opacity: 1; }
1599
1604
 
1600
- /* ========== 隐藏文件输入 ========== */
1605
+ /* ========== 闅愯棌鏂囦欢杈撳叆 ========== */
1601
1606
  input[type="file"] { display: none; }
1602
1607
 
1603
- /* ========== 记忆系统 ========== */
1608
+ /* ========== 璁板繂绯荤粺 ========== */
1604
1609
  .stat-card { text-align: center; padding: 16px; }
1605
1610
  .stat-label { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
1606
1611
  .stat-value { font-size: 24px; font-weight: 700; color: var(--brand); }
@@ -1610,7 +1615,7 @@
1610
1615
  .memory-content pre { background: var(--bg); padding: 12px; border-radius: 8px; overflow-x: auto; }
1611
1616
  .memory-content code { background: var(--bg); padding: 2px 6px; border-radius: 4px; font-size: 12px; }
1612
1617
 
1613
- /* ========== 欢迎引导弹窗 ========== */
1618
+ /* ========== 娆㈣繋寮曞寮圭獥 ========== */
1614
1619
  #welcomeGuideModal .modal { width: 480px; }
1615
1620
  .welcome-guide-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
1616
1621
  .welcome-guide-header .icon { font-size: 32px; }
@@ -1670,7 +1675,7 @@
1670
1675
  font-size: 13px;
1671
1676
  }
1672
1677
 
1673
- /* ========== 后端服务断连提示横幅 ========== */
1678
+ /* ========== 鍚庣鏈嶅姟鏂繛鎻愮ず妯箙 ========== */
1674
1679
  .backend-offline-banner {
1675
1680
  position: fixed;
1676
1681
  top: 0;
@@ -1712,18 +1717,40 @@
1712
1717
  from { transform: translateY(-100%); opacity: 0; }
1713
1718
  to { transform: translateY(0); opacity: 1; }
1714
1719
  }
1720
+
1721
+ /* ========== P2-1: 璁捐绋胯浆浠g爜 ========== */
1722
+ @keyframes spin {
1723
+ to { transform: rotate(360deg); }
1724
+ }
1725
+ .design-result-tab.active {
1726
+ background: var(--accent, #2d5a3d) !important;
1727
+ color: #fff !important;
1728
+ border-color: var(--accent, #2d5a3d) !important;
1729
+ }
1730
+ #designDropZone:hover {
1731
+ border-color: var(--accent, #2d5a3d);
1732
+ background: var(--card, #f5f5f5);
1733
+ }
1734
+
1715
1735
 
1716
- /* ========== P2-1: 设计稿转代码 ========== */
1717
- @keyframes spin {
1718
- to { transform: rotate(360deg); }
1736
+ /* ===== 文字选择优化(精确选择、长按复制、不跳开) ===== */
1737
+ .msg, .msg * {
1738
+ -webkit-user-select: text !important;
1739
+ user-select: text !important;
1740
+ -webkit-touch-callout: default !important;
1719
1741
  }
1720
- .design-result-tab.active {
1721
- background: var(--accent, #2d5a3d) !important;
1722
- color: #fff !important;
1723
- border-color: var(--accent, #2d5a3d) !important;
1742
+ .msg {
1743
+ cursor: text;
1724
1744
  }
1725
- #designDropZone:hover {
1726
- border-color: var(--accent, #2d5a3d);
1727
- background: var(--card, #f5f5f5);
1745
+ .msg ::selection, .msg::selection {
1746
+ background: rgba(79, 110, 247, 0.25);
1747
+ color: inherit;
1728
1748
  }
1729
-
1749
+ .msg ::-moz-selection {
1750
+ background: rgba(79, 110, 247, 0.25);
1751
+ }
1752
+ /* 代码块内文字也可选择 */
1753
+ pre, code, .code-block, .code-block * {
1754
+ -webkit-user-select: text !important;
1755
+ user-select: text !important;
1756
+ }
@@ -4,6 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title data-i18n="app.title_login">飞虹 Code 控制台 / fhcode Console</title>
7
+ <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='20' fill='%231a1a2e'/><text x='50' y='68' font-size='52' font-family='monospace' font-weight='bold' fill='%2300d4aa' text-anchor='middle'>&lt;/&gt;</text></svg>" />
7
8
  <link rel="stylesheet" href="css/style.css">
8
9
  <!-- Monaco Editor AMD Loader(代码编辑器内核,VSCode 同款) -->
9
10
  <script src="vendor/monaco/vs/loader.js"></script>
@@ -342,6 +343,11 @@
342
343
  <div class="empty" data-i18n="common.loading">加载中…</div>
343
344
  </div>
344
345
  <textarea id="memLongEditor" style="display:none;width:100%;min-height:400px;padding:12px;border:1px solid var(--border);border-radius:8px;background:var(--bg);color:var(--ink);font-family:monospace;font-size:13px;resize:vertical;box-sizing:border-box;"></textarea>
346
+ <!-- P1-1: ghost text 补全建议条 -->
347
+ <div id="memGhostBar" style="display:none;margin-top:4px;padding:6px 10px;border:1px dashed var(--border,#ccc);border-radius:6px;background:rgba(45,90,61,0.06);font-family:monospace;font-size:12px;color:var(--muted,#777);white-space:pre-wrap;word-break:break-all;line-height:1.5;">
348
+ <span id="memGhostText" style="color:#888;"></span>
349
+ <span style="margin-left:8px;font-size:10px;color:#aaa;">按 <b>Tab</b> 接受补全 · Esc 取消</span>
350
+ </div>
345
351
  </div>
346
352
 
347
353
  <!-- 总结历史面板 -->
@@ -560,6 +566,7 @@
560
566
  <div class="right-tab" data-tab="design" id="designTab">🎨 设计稿</div>
561
567
  <div class="right-tab" data-tab="git" id="gitTab">🔀 Git</div>
562
568
  <div class="right-tab" data-tab="team" id="teamTab">👥 团队</div>
569
+ <div class="right-tab" data-tab="capabilities" id="capabilitiesTab">🧪 能力中心</div>
563
570
  <div class="right-tab" data-tab="computer" id="computerTab" style="display:none;">🖥 电脑操作</div>
564
571
  </div>
565
572
  <div class="right-body">
@@ -601,7 +608,7 @@
601
608
  <!-- P3: 多文件变更面板 -->
602
609
  <div class="preview-panel" id="changesPanel">
603
610
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
604
- <div style="font-size:13px;font-weight:600;">📝 待审批变更 <span id="changesCount" class="badge" style="margin-left:4px;">0</span></div>
611
+ <div style="font-size:13px;font-weight:600;">📝 待审批变更 <span id="changesCount" class="badge" style="margin-left:4px;">0</span><span id="changesConflictCount" class="badge" style="margin-left:4px;background:#c0392b;color:#fff;display:none;">0 冲突</span></div>
605
612
  <div style="display:flex;gap:6px;">
606
613
  <button id="changesDetectBtn" class="ghost-btn" style="font-size:11px;padding:3px 8px;" title="检测文件冲突">⚠️ 检测冲突</button>
607
614
  <button id="changesRefreshBtn" class="ghost-btn" style="font-size:11px;padding:3px 8px;">🔄</button>
@@ -763,6 +770,8 @@
763
770
  <div style="font-size:10px;color:var(--muted);">任务</div>
764
771
  </div>
765
772
  </div>
773
+ <!-- P7-4: 多 agent 协作总览(状态漏斗 + 成员负载) -->
774
+ <div id="teamOverview" style="display:none;margin-bottom:10px;"></div>
766
775
  </div>
767
776
  <!-- Tab 切换 -->
768
777
  <div style="display:flex;gap:4px;margin-bottom:8px;border-bottom:1px solid var(--border);padding-bottom:6px;">
@@ -794,6 +803,40 @@
794
803
  <div id="teamTasksList" style="max-height:300px;overflow-y:auto;"></div>
795
804
  </div>
796
805
  </div>
806
+ <!-- P0-3: 能力中心面板(v7.2 新能力前端接线:语音/资料库/插件市场) -->
807
+ <div class="preview-panel" id="capabilitiesPanel">
808
+ <div style="margin-bottom:10px;">
809
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
810
+ <span style="font-size:13px;font-weight:600;">🧪 能力中心 <span style="font-size:10px;color:var(--muted);">v7.2 实测可用</span></span>
811
+ </div>
812
+ <!-- 语音编程 -->
813
+ <div style="background:var(--card);padding:8px;border-radius:6px;margin-bottom:8px;">
814
+ <div style="font-size:11px;font-weight:600;margin-bottom:6px;">🎙 语音指令解析</div>
815
+ <div style="display:flex;gap:6px;">
816
+ <input id="capVoiceInput" placeholder="如:打开文件 / 生成排序函数" style="flex:1;font-size:11px;padding:4px 6px;" />
817
+ <button id="capVoiceBtn" class="primary" style="font-size:11px;padding:4px 10px;">解析</button>
818
+ </div>
819
+ <div id="capVoiceResult" style="font-size:11px;margin-top:6px;color:var(--muted);"></div>
820
+ </div>
821
+ <!-- AI 资料库 -->
822
+ <div style="background:var(--card);padding:8px;border-radius:6px;margin-bottom:8px;">
823
+ <div style="font-size:11px;font-weight:600;margin-bottom:6px;">📚 AI 资料库</div>
824
+ <div style="display:flex;gap:6px;">
825
+ <input id="capKnowledgeQuery" placeholder="搜索资料(如:私有化部署)" style="flex:1;font-size:11px;padding:4px 6px;" />
826
+ <button id="capKnowledgeSearchBtn" class="primary" style="font-size:11px;padding:4px 10px;">搜索</button>
827
+ </div>
828
+ <div id="capKnowledgeResult" style="font-size:11px;margin-top:6px;max-height:140px;overflow-y:auto;color:var(--muted);"></div>
829
+ </div>
830
+ <!-- 插件市场 -->
831
+ <div style="background:var(--card);padding:8px;border-radius:6px;">
832
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;">
833
+ <span style="font-size:11px;font-weight:600;">🧩 插件市场</span>
834
+ <button id="capPluginsBtn" class="ghost-btn" style="font-size:11px;padding:2px 8px;">🔄 加载</button>
835
+ </div>
836
+ <div id="capPluginsResult" style="font-size:11px;max-height:140px;overflow-y:auto;color:var(--muted);"></div>
837
+ </div>
838
+ </div>
839
+ </div>
797
840
  </div>
798
841
  </aside>
799
842
  </div>
@@ -295,7 +295,10 @@
295
295
  if (!text) return '';
296
296
  const d = await api('/api/security/public-key');
297
297
  const b64 = String(d.publicKey || '').replace(/-----[^-]+-----/g, '').replace(/\s+/g, '');
298
- if (!b64) throw new Error('未获取到加密公钥');
298
+ if (!b64) {
299
+ console.error('[rsaEncryptText] 公钥为空,完整响应:', d);
300
+ throw new Error('未获取到加密公钥(请按 Ctrl+F5 强制刷新页面,或检查服务是否已重启)');
301
+ }
299
302
  const bin = atob(b64);
300
303
  const buf = new Uint8Array(bin.length);
301
304
  for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
@@ -357,7 +360,7 @@
357
360
  async function api(path, method = 'GET', body) {
358
361
  let res;
359
362
  try {
360
- res = await fetch(path, { method, headers: authHeaders(), body: body ? JSON.stringify(body) : undefined });
363
+ res = await fetch(path, { method, headers: authHeaders(), body: body ? JSON.stringify(body) : undefined, cache: 'no-store' });
361
364
  } catch (e) {
362
365
  // 网络层失败(Failed to fetch / 连接拒绝 / 超时中断):标记后端可能已断开
363
366
  if (typeof BackendConn !== 'undefined') BackendConn.markFailure();
@@ -494,3 +497,62 @@
494
497
  } else {
495
498
  BackendConn.init();
496
499
  }
500
+
501
+ /* ========== v7.2.0 新能力 API 封装(voice / knowledge / plugins / sso)==========
502
+ * 修复:v7.2 新增能力此前前端 0 调用。以下封装供能力中心面板使用。
503
+ */
504
+ async function apiVoiceParse(text) {
505
+ return api('/api/voice/parse', 'POST', { text });
506
+ }
507
+ async function apiVoiceCommands() {
508
+ return api('/api/voice/commands');
509
+ }
510
+ async function apiVoiceToCode(description, language) {
511
+ return api('/api/voice/to-code', 'POST', { description, language: language || 'typescript' });
512
+ }
513
+ async function apiKnowledgeStats() {
514
+ return api('/api/knowledge/stats');
515
+ }
516
+ async function apiKnowledgeList(params) {
517
+ const qs = new URLSearchParams();
518
+ if (params) { for (const k of ['category', 'type', 'sortBy', 'order', 'limit', 'offset']) { if (params[k]) qs.set(k, params[k]); } }
519
+ const s = qs.toString();
520
+ return api('/api/knowledge/documents' + (s ? '?' + s : ''));
521
+ }
522
+ async function apiKnowledgeSearch(query, extra) {
523
+ return api('/api/knowledge/search', 'POST', { query, ...(extra || {}) });
524
+ }
525
+ async function apiKnowledgeAdd(data) {
526
+ return api('/api/knowledge/document', 'POST', data);
527
+ }
528
+ async function apiKnowledgeDelete(id) {
529
+ return api('/api/knowledge/document/' + encodeURIComponent(id), 'DELETE');
530
+ }
531
+ async function apiPluginsMarket(q, category) {
532
+ const qs = new URLSearchParams();
533
+ if (q) qs.set('q', q);
534
+ if (category) qs.set('category', category);
535
+ const s = qs.toString();
536
+ return api('/api/plugins/market' + (s ? '?' + s : ''));
537
+ }
538
+ async function apiPluginsList(status) {
539
+ const s = status ? '?status=' + encodeURIComponent(status) : '';
540
+ return api('/api/plugins' + s);
541
+ }
542
+ async function apiPluginsInstall(plugin) {
543
+ return api('/api/plugins/install', 'POST', { plugin });
544
+ }
545
+ async function apiSsoProviders() {
546
+ return api('/api/sso/providers');
547
+ }
548
+
549
+ /* ========== P1-1: 代码补全(ghost text)========== */
550
+ async function apiCompletion(filePath, fileContent, opts) {
551
+ return api('/api/completion', 'POST', {
552
+ filePath,
553
+ fileContent,
554
+ cursorOffset: opts?.cursorOffset ?? fileContent.length,
555
+ mode: opts?.mode ?? 'quick',
556
+ language: opts?.language,
557
+ });
558
+ }