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,401 +1,517 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Self-Evolve Manager - 自我迭代升级管理器
4
- * 负责记录失败、创建技能、定期复盘
5
- */
6
-
7
- const fs = require('fs');
8
- const path = require('path');
9
- const { v4: uuidv4 } = require('uuid');
10
-
11
- // 确保uuid已安装或实现简单的UUID
12
- function generateId() {
13
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
14
- const r = Math.random() * 16 | 0;
15
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
16
- return v.toString(16);
17
- });
18
- }
19
-
20
- class SelfEvolveManager {
21
- constructor() {
22
- this.baseDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code', 'self-evolve');
23
- this.failuresFile = path.join(this.baseDir, 'failures.json');
24
- this.skillsIndexFile = path.join(this.baseDir, 'skills-index.json');
25
- this.historyFile = path.join(this.baseDir, 'history.json');
26
-
27
- this.ensureDirs();
28
- this.loadData();
29
- }
30
-
31
- ensureDirs() {
32
- if (!fs.existsSync(this.baseDir)) {
33
- fs.mkdirSync(this.baseDir, { recursive: true });
34
- }
35
- // 确保用户技能目录也存在
36
- const userSkillsDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code', 'skills');
37
- if (!fs.existsSync(userSkillsDir)) {
38
- fs.mkdirSync(userSkillsDir, { recursive: true });
39
- }
40
- }
41
-
42
- loadData() {
43
- this.failures = this.loadJSON(this.failuresFile, []);
44
- this.skillsIndex = this.loadJSON(this.skillsIndexFile, []);
45
- this.history = this.loadJSON(this.historyFile, []);
46
- }
47
-
48
- loadJSON(file, defaultValue) {
49
- try {
50
- if (fs.existsSync(file)) {
51
- const content = fs.readFileSync(file, 'utf8');
52
- return JSON.parse(content);
53
- }
54
- } catch (e) {
55
- console.error(`加载 ${file} 失败:`, e.message);
56
- }
57
- return defaultValue;
58
- }
59
-
60
- saveData() {
61
- this.saveJSON(this.failuresFile, this.failures);
62
- this.saveJSON(this.skillsIndexFile, this.skillsIndex);
63
- this.saveJSON(this.historyFile, this.history);
64
- }
65
-
66
- saveJSON(file, data) {
67
- try {
68
- fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8');
69
- } catch (e) {
70
- console.error(`保存 ${file} 失败:`, e.message);
71
- }
72
- }
73
-
74
- /**
75
- * 记录任务失败
76
- */
77
- recordFailure(task, error, attemptedSolutions = [], rootCause = null) {
78
- const failure = {
79
- id: generateId(),
80
- timestamp: new Date().toISOString(),
81
- task: task,
82
- error_type: this.categorizeError(error),
83
- error_message: typeof error === 'string' ? error : (error?.message || String(error)),
84
- attempted_solutions: attemptedSolutions,
85
- root_cause: rootCause || '待分析',
86
- solution: null,
87
- created_skill: false,
88
- skill_name: null,
89
- status: 'pending'
90
- };
91
-
92
- this.failures.push(failure);
93
- this.history.push({
94
- type: 'failure',
95
- timestamp: failure.timestamp,
96
- failure_id: failure.id
97
- });
98
-
99
- this.saveData();
100
- console.log(`[自我迭代] 记录失败任务 #${failure.id.slice(0, 8)}`);
101
- return failure;
102
- }
103
-
104
- /**
105
- * 错误分类
106
- */
107
- categorizeError(error) {
108
- const msg = typeof error === 'string' ? error.toLowerCase() : '';
109
-
110
- if (msg.includes('error ts') || msg.includes('syntax error') || msg.includes('编译')) {
111
- return 'compile-error';
112
- }
113
- if (msg.includes('typeerror') || msg.includes('referenceerror')) {
114
- return 'runtime-error';
115
- }
116
- if (msg.includes('path traversal') || msg.includes('outside workspace')) {
117
- return 'path-error';
118
- }
119
- if (msg.includes('timeout') || msg.includes('etimedout')) {
120
- return 'timeout';
121
- }
122
- if (msg.includes('permission denied') || msg.includes('eacces')) {
123
- return 'permission-error';
124
- }
125
- if (msg.includes('rate limit') || msg.includes('429') || msg.includes('5xx')) {
126
- return 'api-error';
127
- }
128
- return 'unknown';
129
- }
130
-
131
- /**
132
- * 搜索已知解决方案
133
- */
134
- searchSolution(errorType, errorMessage) {
135
- // 先按类型精确匹配
136
- let matches = this.skillsIndex.filter(s => s.error_pattern === errorType);
137
-
138
- // 再按关键词模糊匹配
139
- if (matches.length === 0) {
140
- const keywords = errorMessage.toLowerCase().split(/\s+/).filter(k => k.length > 3);
141
- for (const keyword of keywords) {
142
- matches = this.skillsIndex.filter(s =>
143
- s.triggers && s.triggers.some(t => t.includes(keyword))
144
- );
145
- if (matches.length > 0) break;
146
- }
147
- }
148
-
149
- return matches;
150
- }
151
-
152
- /**
153
- * 标记问题已解决
154
- */
155
- markResolved(failureId, solution, skillName = null) {
156
- const failure = this.failures.find(f => f.id === failureId);
157
- if (!failure) return null;
158
-
159
- failure.solution = solution;
160
- failure.status = 'resolved';
161
- if (skillName) {
162
- failure.created_skill = true;
163
- failure.skill_name = skillName;
164
- }
165
-
166
- this.history.push({
167
- type: 'resolved',
168
- timestamp: new Date().toISOString(),
169
- failure_id: failureId,
170
- solution: solution
171
- });
172
-
173
- this.saveData();
174
- console.log(`[自我迭代] 问题 #${failureId.slice(0, 8)} 已解决`);
175
- return failure;
176
- }
177
-
178
- /**
179
- * 创建新技能
180
- */
181
- createSkill(name, description, triggers, errorPattern, solution) {
182
- const skill = {
183
- name,
184
- description,
185
- triggers: triggers || [name],
186
- error_pattern: errorPattern,
187
- solution,
188
- created_at: new Date().toISOString(),
189
- usage_count: 0,
190
- version: '1.0.0'
191
- };
192
-
193
- // 添加到索引
194
- this.skillsIndex.push(skill);
195
-
196
- // 创建SKILL.md文件
197
- this.saveSkillToFile(skill);
198
-
199
- // 更新相关失败记录
200
- this.failures.forEach(f => {
201
- if (f.error_type === errorPattern ||
202
- (f.error_message && f.error_message.toLowerCase().includes(name.toLowerCase()))) {
203
- f.solution = `应用技能: ${name}`;
204
- f.status = 'resolved';
205
- f.created_skill = true;
206
- f.skill_name = name;
207
- }
208
- });
209
-
210
- this.history.push({
211
- type: 'skill_created',
212
- timestamp: new Date().toISOString(),
213
- skill_name: name
214
- });
215
-
216
- this.saveData();
217
- console.log(`[自我迭代] 新技能已创建: ${name}`);
218
- return skill;
219
- }
220
-
221
- /**
222
- * 保存技能到文件
223
- */
224
- saveSkillToFile(skill) {
225
- const skillDir = path.join(
226
- process.env.HOME || process.env.USERPROFILE || '.',
227
- '.feihong-code',
228
- 'skills',
229
- skill.name
230
- );
231
-
232
- if (!fs.existsSync(skillDir)) {
233
- fs.mkdirSync(skillDir, { recursive: true });
234
- }
235
-
236
- const triggersText = skill.triggers ? skill.triggers.join(', ') : skill.name;
237
- const content = `---
238
- name: ${skill.name}
239
- description: ${skill.description}
240
- triggers: [${triggersText}]
241
- ---
242
-
243
- # ${skill.name} 技能
244
-
245
- **自动创建的解决技能**
246
-
247
- ## 触发条件
248
- ${skill.triggers ? skill.triggers.join('\n- ') : skill.name}
249
-
250
- ## 错误模式
251
- ${skill.error_pattern}
252
-
253
- ## 解决方案
254
- ${skill.solution}
255
-
256
- ## 创建时间
257
- ${skill.created_at}
258
- `;
259
-
260
- fs.writeFileSync(path.join(skillDir, 'SKILL.md'), content, 'utf8');
261
- }
262
-
263
- /**
264
- * 生成每日复盘报告
265
- */
266
- generateDailyReport() {
267
- const today = new Date().toISOString().split('T')[0];
268
- const todayFailures = this.failures.filter(f => f.timestamp.startsWith(today));
269
- const todayResolutions = this.history.filter(h =>
270
- h.timestamp.startsWith(today) && h.type === 'resolved'
271
- );
272
-
273
- const report = {
274
- date: today,
275
- total_failures: todayFailures.length,
276
- resolved: todayResolutions.length,
277
- pending: todayFailures.filter(f => f.status !== 'resolved').length,
278
- new_skills: this.history.filter(h =>
279
- h.timestamp.startsWith(today) && h.type === 'skill_created'
280
- ).length,
281
- failures: todayFailures.map(f => ({
282
- id: f.id.slice(0, 8),
283
- type: f.error_type,
284
- message: f.error_message.slice(0, 100),
285
- status: f.status
286
- }))
287
- };
288
-
289
- // 保存报告
290
- const reportFile = path.join(this.baseDir, `report-${today}.json`);
291
- fs.writeFileSync(reportFile, JSON.stringify(report, null, 2));
292
-
293
- console.log(`[自我迭代] 每日报告已生成: ${today}`);
294
- console.log(` - 失败任务: ${report.total_failures}`);
295
- console.log(` - 已解决: ${report.resolved}`);
296
- console.log(` - 待处理: ${report.pending}`);
297
- console.log(` - 新技能: ${report.new_skills}`);
298
-
299
- return report;
300
- }
301
-
302
- /**
303
- * 统计分析
304
- */
305
- getStatistics() {
306
- const totalFailures = this.failures.length;
307
- const resolved = this.failures.filter(f => f.status === 'resolved').length;
308
- const byType = {};
309
-
310
- this.failures.forEach(f => {
311
- byType[f.error_type] = (byType[f.error_type] || 0) + 1;
312
- });
313
-
314
- return {
315
- total_failures: totalFailures,
316
- resolved: resolved,
317
- pending: totalFailures - resolved,
318
- resolution_rate: totalFailures > 0 ? ((resolved / totalFailures) * 100).toFixed(1) + '%' : '0%',
319
- by_type: byType,
320
- total_skills: this.skillsIndex.length,
321
- history_entries: this.history.length
322
- };
323
- }
324
-
325
- /**
326
- * 列出所有失败记录
327
- */
328
- listFailures(filters = {}) {
329
- let result = this.failures;
330
-
331
- if (filters.type) {
332
- result = result.filter(f => f.error_type === filters.type);
333
- }
334
- if (filters.status) {
335
- result = result.filter(f => f.status === filters.status);
336
- }
337
- if (filters.days) {
338
- const cutoff = new Date(Date.now() - filters.days * 24 * 60 * 60 * 1000);
339
- result = result.filter(f => new Date(f.timestamp) >= cutoff);
340
- }
341
-
342
- return result;
343
- }
344
-
345
- /**
346
- * 列出所有技能
347
- */
348
- listSkills() {
349
- return this.skillsIndex;
350
- }
351
-
352
- /**
353
- * 初始化系统
354
- */
355
- init() {
356
- this.ensureDirs();
357
- this.loadData();
358
-
359
- // 创建初始数据文件(如果不存在)
360
- if (!fs.existsSync(this.failuresFile)) {
361
- this.saveData();
362
- }
363
-
364
- console.log('[自我迭代] 系统已初始化');
365
- console.log(` - 基础目录: ${this.baseDir}`);
366
- console.log(` - 失败记录: ${this.failures.length} 条`);
367
- console.log(` - 技能库: ${this.skillsIndex.length} 个`);
368
- console.log(` - 历史记录: ${this.history.length} 条`);
369
- }
370
- }
371
-
372
- module.exports = { SelfEvolveManager };
373
-
374
- // CLI 入口
375
- if (require.main === module) {
376
- const manager = new SelfEvolveManager();
377
- const args = process.argv.slice(2);
378
-
379
- if (args[0] === 'init') {
380
- manager.init();
381
- } else if (args[0] === 'status') {
382
- console.log(JSON.stringify(manager.getStatistics(), null, 2));
383
- } else if (args[0] === 'failures' && args[1] === 'list') {
384
- const filters = {};
385
- if (args[2] === '--type' && args[3]) filters.type = args[3];
386
- if (args[2] === '--days' && args[3]) filters.days = parseInt(args[3]);
387
- console.log(JSON.stringify(manager.listFailures(filters), null, 2));
388
- } else if (args[0] === 'skills' && args[1] === 'list') {
389
- console.log(JSON.stringify(manager.listSkills(), null, 2));
390
- } else if (args[0] === 'review' && args[1] === '--daily') {
391
- manager.generateDailyReport();
392
- } else {
393
- console.log('自我迭代管理系统');
394
- console.log('用法:');
395
- console.log(' self-evolve init - 初始化系统');
396
- console.log(' self-evolve status - 查看统计');
397
- console.log(' self-evolve failures list - 列出失败');
398
- console.log(' self-evolve skills list - 列出技能');
399
- console.log(' self-evolve review --daily - 每日复盘');
400
- }
401
- }
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Self-Evolve Manager - 自我迭代升级管理器
4
+ * 负责记录失败、创建技能、定期复盘
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ // 注意:不再 require('uuid')——该依赖从未安装且 uuidv4 从未被使用,
11
+ // 本项目自带 generateId()(下方 RFC-4122 v4 实现),移除后 CLI 不再崩溃。
12
+
13
+ // 实现简单的 UUID v4
14
+ function generateId() {
15
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
16
+ const r = Math.random() * 16 | 0;
17
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
18
+ return v.toString(16);
19
+ });
20
+ }
21
+
22
+ class SelfEvolveManager {
23
+ constructor() {
24
+ this.baseDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code', 'self-evolve');
25
+ this.failuresFile = path.join(this.baseDir, 'failures.json');
26
+ this.skillsIndexFile = path.join(this.baseDir, 'skills-index.json');
27
+ this.historyFile = path.join(this.baseDir, 'history.json');
28
+ // 双系统收敛:失败/技能/解决 统一回流到共享经验库(experiences.jsonl),
29
+ // 与新一代 self-improve(src/agent/experience.ts)共用同一存储,供 orchestrator 检索注入。
30
+ this.experiencesDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code', 'experiences');
31
+ this.experiencesFile = path.join(this.experiencesDir, 'experiences.jsonl');
32
+
33
+ this.ensureDirs();
34
+ this.loadData();
35
+ }
36
+
37
+ /** 稳定短哈希(与 src/agent/experience.ts shortHash 语义一致,保证跨系统 id 可对齐) */
38
+ static shortHash(s) {
39
+ let h = 5381;
40
+ for (let i = 0; i < s.length; i++) h = ((h << 5) + h + s.charCodeAt(i)) | 0;
41
+ return (h >>> 0).toString(36);
42
+ }
43
+
44
+ /** 生成与 experience.ts 一致的稳定经验 id */
45
+ static experienceId(type, key) {
46
+ return `exp-${SelfEvolveManager.shortHash(`${type}:${key}`)}`;
47
+ }
48
+
49
+ /** 读取共享经验库全部记录 */
50
+ loadExperiences() {
51
+ if (!fs.existsSync(this.experiencesFile)) return [];
52
+ try {
53
+ return fs
54
+ .readFileSync(this.experiencesFile, 'utf8')
55
+ .split('\n')
56
+ .filter(Boolean)
57
+ .map((line) => {
58
+ try { return JSON.parse(line); } catch { return null; }
59
+ })
60
+ .filter(Boolean);
61
+ } catch {
62
+ return [];
63
+ }
64
+ }
65
+
66
+ /**
67
+ * 追加/合并一条经验到共享经验库(upsert 语义,与 experience.ts 一致):
68
+ * id 已存在 → sessionCount+1、成功率按次数加权平均、标签合并、刷新 lastUsedAt;
69
+ * 否则新增。失败学习因此回流到 orchestrator 的检索闭环。
70
+ */
71
+ upsertExperience(type, key, title, content, tags, successRate) {
72
+ const id = SelfEvolveManager.experienceId(type, key);
73
+ const now = new Date().toISOString();
74
+ const entry = {
75
+ id,
76
+ type,
77
+ title,
78
+ content,
79
+ metadata: {
80
+ sessionCount: 1,
81
+ successRate: typeof successRate === 'number' ? successRate : 0,
82
+ tags,
83
+ createdAt: now,
84
+ lastUsedAt: now,
85
+ },
86
+ };
87
+ try {
88
+ if (!fs.existsSync(this.experiencesDir)) fs.mkdirSync(this.experiencesDir, { recursive: true });
89
+ const existing = this.loadExperiences();
90
+ const idx = existing.findIndex((e) => e && e.id === id);
91
+ if (idx >= 0) {
92
+ const prev = existing[idx];
93
+ const prevCount = prev.metadata && prev.metadata.sessionCount ? prev.metadata.sessionCount : 0;
94
+ entry.metadata = {
95
+ sessionCount: prevCount + 1,
96
+ successRate: (prev.metadata.successRate * prevCount + entry.metadata.successRate) / (prevCount + 1),
97
+ tags: [...new Set([...(prev.metadata.tags || []), ...tags])],
98
+ createdAt: prev.metadata.createdAt || now,
99
+ lastUsedAt: now,
100
+ };
101
+ existing[idx] = entry;
102
+ } else {
103
+ existing.push(entry);
104
+ }
105
+ fs.writeFileSync(this.experiencesFile, existing.map((e) => JSON.stringify(e)).join('\n') + '\n', 'utf8');
106
+ } catch (e) {
107
+ console.error(`[自我迭代] 写入共享经验库失败: ${e.message}`);
108
+ }
109
+ return entry;
110
+ }
111
+
112
+ ensureDirs() {
113
+ if (!fs.existsSync(this.baseDir)) {
114
+ fs.mkdirSync(this.baseDir, { recursive: true });
115
+ }
116
+ // 确保用户技能目录也存在
117
+ const userSkillsDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code', 'skills');
118
+ if (!fs.existsSync(userSkillsDir)) {
119
+ fs.mkdirSync(userSkillsDir, { recursive: true });
120
+ }
121
+ // 双系统收敛:共享经验库目录
122
+ if (!fs.existsSync(this.experiencesDir)) {
123
+ fs.mkdirSync(this.experiencesDir, { recursive: true });
124
+ }
125
+ }
126
+
127
+ loadData() {
128
+ this.failures = this.loadJSON(this.failuresFile, []);
129
+ this.skillsIndex = this.loadJSON(this.skillsIndexFile, []);
130
+ this.history = this.loadJSON(this.historyFile, []);
131
+ }
132
+
133
+ loadJSON(file, defaultValue) {
134
+ try {
135
+ if (fs.existsSync(file)) {
136
+ // 去除 BOM(EF BB BF),兼容 PowerShell Set-Content -Encoding UTF8 等写入的带 BOM JSON
137
+ const content = fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, '');
138
+ return JSON.parse(content);
139
+ }
140
+ } catch (e) {
141
+ console.error(`加载 ${file} 失败:`, e.message);
142
+ }
143
+ return defaultValue;
144
+ }
145
+
146
+ saveData() {
147
+ this.saveJSON(this.failuresFile, this.failures);
148
+ this.saveJSON(this.skillsIndexFile, this.skillsIndex);
149
+ this.saveJSON(this.historyFile, this.history);
150
+ }
151
+
152
+ saveJSON(file, data) {
153
+ try {
154
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8');
155
+ } catch (e) {
156
+ console.error(`保存 ${file} 失败:`, e.message);
157
+ }
158
+ }
159
+
160
+ /**
161
+ * 记录任务失败
162
+ */
163
+ recordFailure(task, error, attemptedSolutions = [], rootCause = null) {
164
+ const failure = {
165
+ id: generateId(),
166
+ timestamp: new Date().toISOString(),
167
+ task: task,
168
+ error_type: this.categorizeError(error),
169
+ error_message: typeof error === 'string' ? error : (error?.message || String(error)),
170
+ attempted_solutions: attemptedSolutions,
171
+ root_cause: rootCause || '待分析',
172
+ solution: null,
173
+ created_skill: false,
174
+ skill_name: null,
175
+ status: 'pending'
176
+ };
177
+
178
+ this.failures.push(failure);
179
+ this.history.push({
180
+ type: 'failure',
181
+ timestamp: failure.timestamp,
182
+ failure_id: failure.id
183
+ });
184
+
185
+ this.saveData();
186
+ // 双系统收敛:失败 → error-pattern 经验回流共享库
187
+ this.upsertExperience(
188
+ 'error-pattern',
189
+ failure.error_type,
190
+ `常见错误模式: ${failure.error_type}`,
191
+ `任务「${String(failure.task).slice(0, 120)}」遇到 ${failure.error_type} 类错误:${String(failure.error_message).slice(0, 200)}。规避建议:提前校验前置条件(路径/权限/依赖),增加超时重试与最小改动原则。`,
192
+ [failure.error_type, 'failure'],
193
+ 0
194
+ );
195
+ console.log(`[自我迭代] 记录失败任务 #${failure.id.slice(0, 8)}`);
196
+ return failure;
197
+ }
198
+
199
+ /**
200
+ * 错误分类
201
+ */
202
+ categorizeError(error) {
203
+ const msg = typeof error === 'string' ? error.toLowerCase() : '';
204
+
205
+ if (msg.includes('error ts') || msg.includes('syntax error') || msg.includes('编译')) {
206
+ return 'compile-error';
207
+ }
208
+ if (msg.includes('typeerror') || msg.includes('referenceerror')) {
209
+ return 'runtime-error';
210
+ }
211
+ if (msg.includes('path traversal') || msg.includes('outside workspace')) {
212
+ return 'path-error';
213
+ }
214
+ if (msg.includes('timeout') || msg.includes('etimedout')) {
215
+ return 'timeout';
216
+ }
217
+ if (msg.includes('permission denied') || msg.includes('eacces')) {
218
+ return 'permission-error';
219
+ }
220
+ if (msg.includes('rate limit') || msg.includes('429') || msg.includes('5xx')) {
221
+ return 'api-error';
222
+ }
223
+ return 'unknown';
224
+ }
225
+
226
+ /**
227
+ * 搜索已知解决方案
228
+ */
229
+ searchSolution(errorType, errorMessage) {
230
+ // 先按类型精确匹配
231
+ let matches = this.skillsIndex.filter(s => s.error_pattern === errorType);
232
+
233
+ // 再按关键词模糊匹配
234
+ if (matches.length === 0) {
235
+ const keywords = errorMessage.toLowerCase().split(/\s+/).filter(k => k.length > 3);
236
+ for (const keyword of keywords) {
237
+ matches = this.skillsIndex.filter(s =>
238
+ s.triggers && s.triggers.some(t => t.includes(keyword))
239
+ );
240
+ if (matches.length > 0) break;
241
+ }
242
+ }
243
+
244
+ return matches;
245
+ }
246
+
247
+ /**
248
+ * 标记问题已解决
249
+ */
250
+ markResolved(failureId, solution, skillName = null) {
251
+ const failure = this.failures.find(f => f.id === failureId);
252
+ if (!failure) return null;
253
+
254
+ failure.solution = solution;
255
+ failure.status = 'resolved';
256
+ if (skillName) {
257
+ failure.created_skill = true;
258
+ failure.skill_name = skillName;
259
+ }
260
+
261
+ this.history.push({
262
+ type: 'resolved',
263
+ timestamp: new Date().toISOString(),
264
+ failure_id: failureId,
265
+ solution: solution
266
+ });
267
+
268
+ this.saveData();
269
+ // 双系统收敛:解决 success-pattern 经验回流共享库(含可复用方案)
270
+ if (solution) {
271
+ this.upsertExperience(
272
+ 'success-pattern',
273
+ `fix:${failure.error_type}`,
274
+ `自愈修复经验: ${failure.error_type}`,
275
+ `问题「${String(failure.task).slice(0, 120)}」的 ${failure.error_type} 类错误已解决${skillName ? `(应用技能 ${skillName})` : ''},可用方案:${String(solution).slice(0, 300)}`,
276
+ [failure.error_type, 'self-heal', 'fix', 'success'],
277
+ 1.0
278
+ );
279
+ }
280
+ console.log(`[自我迭代] 问题 #${failureId.slice(0, 8)} 已解决`);
281
+ return failure;
282
+ }
283
+
284
+ /**
285
+ * 创建新技能
286
+ */
287
+ createSkill(name, description, triggers, errorPattern, solution) {
288
+ const skill = {
289
+ name,
290
+ description,
291
+ triggers: triggers || [name],
292
+ error_pattern: errorPattern,
293
+ solution,
294
+ created_at: new Date().toISOString(),
295
+ usage_count: 0,
296
+ version: '1.0.0'
297
+ };
298
+
299
+ // 添加到索引
300
+ this.skillsIndex.push(skill);
301
+
302
+ // 创建SKILL.md文件
303
+ this.saveSkillToFile(skill);
304
+
305
+ // 更新相关失败记录
306
+ this.failures.forEach(f => {
307
+ if (f.error_type === errorPattern ||
308
+ (f.error_message && f.error_message.toLowerCase().includes(name.toLowerCase()))) {
309
+ f.solution = `应用技能: ${name}`;
310
+ f.status = 'resolved';
311
+ f.created_skill = true;
312
+ f.skill_name = name;
313
+ }
314
+ });
315
+
316
+ this.history.push({
317
+ type: 'skill_created',
318
+ timestamp: new Date().toISOString(),
319
+ skill_name: name
320
+ });
321
+
322
+ this.saveData();
323
+ // 双系统收敛:新技能 → success-pattern 经验回流共享库(未来任务可检索到该技能)
324
+ this.upsertExperience(
325
+ 'success-pattern',
326
+ `skill:${name}`,
327
+ `技能沉淀: ${name}`,
328
+ `已沉淀可复用技能「${name}」(触发词:${triggers.join(', ')};错误模式:${errorPattern}),处理方案:${String(solution).slice(0, 300)}。未来遇到同类问题直接应用该技能。`,
329
+ [name, errorPattern, 'skill', 'success'],
330
+ 1.0
331
+ );
332
+ console.log(`[自我迭代] 新技能已创建: ${name}`);
333
+ return skill;
334
+ }
335
+
336
+ /**
337
+ * 保存技能到文件
338
+ */
339
+ saveSkillToFile(skill) {
340
+ const skillDir = path.join(
341
+ process.env.HOME || process.env.USERPROFILE || '.',
342
+ '.feihong-code',
343
+ 'skills',
344
+ skill.name
345
+ );
346
+
347
+ if (!fs.existsSync(skillDir)) {
348
+ fs.mkdirSync(skillDir, { recursive: true });
349
+ }
350
+
351
+ const triggersText = skill.triggers ? skill.triggers.join(', ') : skill.name;
352
+ const content = `---
353
+ name: ${skill.name}
354
+ description: ${skill.description}
355
+ triggers: [${triggersText}]
356
+ ---
357
+
358
+ # ${skill.name} 技能
359
+
360
+ **自动创建的解决技能**
361
+
362
+ ## 触发条件
363
+ ${skill.triggers ? skill.triggers.join('\n- ') : skill.name}
364
+
365
+ ## 错误模式
366
+ ${skill.error_pattern}
367
+
368
+ ## 解决方案
369
+ ${skill.solution}
370
+
371
+ ## 创建时间
372
+ ${skill.created_at}
373
+ `;
374
+
375
+ fs.writeFileSync(path.join(skillDir, 'SKILL.md'), content, 'utf8');
376
+ }
377
+
378
+ /**
379
+ * 生成每日复盘报告
380
+ */
381
+ generateDailyReport() {
382
+ const today = new Date().toISOString().split('T')[0];
383
+ const todayFailures = this.failures.filter(f => f.timestamp.startsWith(today));
384
+ const todayResolutions = this.history.filter(h =>
385
+ h.timestamp.startsWith(today) && h.type === 'resolved'
386
+ );
387
+
388
+ const report = {
389
+ date: today,
390
+ total_failures: todayFailures.length,
391
+ resolved: todayResolutions.length,
392
+ pending: todayFailures.filter(f => f.status !== 'resolved').length,
393
+ new_skills: this.history.filter(h =>
394
+ h.timestamp.startsWith(today) && h.type === 'skill_created'
395
+ ).length,
396
+ failures: todayFailures.map(f => ({
397
+ id: f.id.slice(0, 8),
398
+ type: f.error_type,
399
+ message: f.error_message.slice(0, 100),
400
+ status: f.status
401
+ }))
402
+ };
403
+
404
+ // 保存报告
405
+ const reportFile = path.join(this.baseDir, `report-${today}.json`);
406
+ fs.writeFileSync(reportFile, JSON.stringify(report, null, 2));
407
+
408
+ console.log(`[自我迭代] 每日报告已生成: ${today}`);
409
+ console.log(` - 失败任务: ${report.total_failures}`);
410
+ console.log(` - 已解决: ${report.resolved}`);
411
+ console.log(` - 待处理: ${report.pending}`);
412
+ console.log(` - 新技能: ${report.new_skills}`);
413
+
414
+ return report;
415
+ }
416
+
417
+ /**
418
+ * 统计分析
419
+ */
420
+ getStatistics() {
421
+ const totalFailures = this.failures.length;
422
+ const resolved = this.failures.filter(f => f.status === 'resolved').length;
423
+ const byType = {};
424
+
425
+ this.failures.forEach(f => {
426
+ byType[f.error_type] = (byType[f.error_type] || 0) + 1;
427
+ });
428
+
429
+ return {
430
+ total_failures: totalFailures,
431
+ resolved: resolved,
432
+ pending: totalFailures - resolved,
433
+ resolution_rate: totalFailures > 0 ? ((resolved / totalFailures) * 100).toFixed(1) + '%' : '0%',
434
+ by_type: byType,
435
+ total_skills: this.skillsIndex.length,
436
+ history_entries: this.history.length,
437
+ total_experiences: this.loadExperiences().length
438
+ };
439
+ }
440
+
441
+ /**
442
+ * 列出所有失败记录
443
+ */
444
+ listFailures(filters = {}) {
445
+ let result = this.failures;
446
+
447
+ if (filters.type) {
448
+ result = result.filter(f => f.error_type === filters.type);
449
+ }
450
+ if (filters.status) {
451
+ result = result.filter(f => f.status === filters.status);
452
+ }
453
+ if (filters.days) {
454
+ const cutoff = new Date(Date.now() - filters.days * 24 * 60 * 60 * 1000);
455
+ result = result.filter(f => new Date(f.timestamp) >= cutoff);
456
+ }
457
+
458
+ return result;
459
+ }
460
+
461
+ /**
462
+ * 列出所有技能
463
+ */
464
+ listSkills() {
465
+ return this.skillsIndex;
466
+ }
467
+
468
+ /**
469
+ * 初始化系统
470
+ */
471
+ init() {
472
+ this.ensureDirs();
473
+ this.loadData();
474
+
475
+ // 创建初始数据文件(如果不存在)
476
+ if (!fs.existsSync(this.failuresFile)) {
477
+ this.saveData();
478
+ }
479
+
480
+ console.log('[自我迭代] 系统已初始化');
481
+ console.log(` - 基础目录: ${this.baseDir}`);
482
+ console.log(` - 失败记录: ${this.failures.length} 条`);
483
+ console.log(` - 技能库: ${this.skillsIndex.length} 个`);
484
+ console.log(` - 历史记录: ${this.history.length} 条`);
485
+ }
486
+ }
487
+
488
+ module.exports = { SelfEvolveManager };
489
+
490
+ // CLI 入口
491
+ if (require.main === module) {
492
+ const manager = new SelfEvolveManager();
493
+ const args = process.argv.slice(2);
494
+
495
+ if (args[0] === 'init') {
496
+ manager.init();
497
+ } else if (args[0] === 'status') {
498
+ console.log(JSON.stringify(manager.getStatistics(), null, 2));
499
+ } else if (args[0] === 'failures' && args[1] === 'list') {
500
+ const filters = {};
501
+ if (args[2] === '--type' && args[3]) filters.type = args[3];
502
+ if (args[2] === '--days' && args[3]) filters.days = parseInt(args[3]);
503
+ console.log(JSON.stringify(manager.listFailures(filters), null, 2));
504
+ } else if (args[0] === 'skills' && args[1] === 'list') {
505
+ console.log(JSON.stringify(manager.listSkills(), null, 2));
506
+ } else if (args[0] === 'review' && args[1] === '--daily') {
507
+ manager.generateDailyReport();
508
+ } else {
509
+ console.log('自我迭代管理系统');
510
+ console.log('用法:');
511
+ console.log(' self-evolve init - 初始化系统');
512
+ console.log(' self-evolve status - 查看统计');
513
+ console.log(' self-evolve failures list - 列出失败');
514
+ console.log(' self-evolve skills list - 列出技能');
515
+ console.log(' self-evolve review --daily - 每日复盘');
516
+ }
517
+ }