feihong-code 0.2.3 → 0.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 (180) hide show
  1. package/.github/FUNDING.yml +4 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +37 -37
  3. package/.github/ISSUE_TEMPLATE/config.yml +14 -14
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +28 -28
  5. package/.github/PULL_REQUEST_TEMPLATE.md +46 -46
  6. package/.github/SECURITY.md +67 -67
  7. package/.github/dependabot.yml +16 -0
  8. package/.github/workflows/ci.yml +1 -1
  9. package/AGENT-GUIDE.md +382 -237
  10. package/CHANGELOG.md +392 -0
  11. package/CODE_OF_CONDUCT.md +56 -56
  12. package/CONTRIBUTING.md +68 -68
  13. package/LICENSE +22 -22
  14. package/README.md +586 -522
  15. package/README.self-evolve.md +274 -0
  16. package/dist/agent/code-review.js +2 -0
  17. package/dist/agent/code-review.js.map +1 -1
  18. package/dist/agent/code-writer.js +74 -18
  19. package/dist/agent/code-writer.js.map +1 -1
  20. package/dist/agent/context-compactor.js +13 -4
  21. package/dist/agent/context-compactor.js.map +1 -1
  22. package/dist/agent/experience.js +319 -84
  23. package/dist/agent/experience.js.map +1 -1
  24. package/dist/agent/orchestrator.js +233 -71
  25. package/dist/agent/orchestrator.js.map +1 -1
  26. package/dist/agent/planner.js +30 -7
  27. package/dist/agent/planner.js.map +1 -1
  28. package/dist/agent/prompts.js +9 -0
  29. package/dist/agent/prompts.js.map +1 -1
  30. package/dist/agent/quality-gate.js +10 -4
  31. package/dist/agent/quality-gate.js.map +1 -1
  32. package/dist/agent/repo-context.js +181 -0
  33. package/dist/agent/repo-context.js.map +1 -0
  34. package/dist/agent/repo-reader.js +92 -99
  35. package/dist/agent/repo-reader.js.map +1 -1
  36. package/dist/agent/self-heal.js +80 -60
  37. package/dist/agent/self-heal.js.map +1 -1
  38. package/dist/agent/self-improver.js +65 -61
  39. package/dist/agent/self-improver.js.map +1 -1
  40. package/dist/agent/subagent-summary.js +31 -0
  41. package/dist/agent/subagent-summary.js.map +1 -0
  42. package/dist/agent/subagent.js +52 -2
  43. package/dist/agent/subagent.js.map +1 -1
  44. package/dist/agent/symbol-index.js +160 -0
  45. package/dist/agent/symbol-index.js.map +1 -0
  46. package/dist/agent/team.js +193 -0
  47. package/dist/agent/team.js.map +1 -0
  48. package/dist/cli/commands.js +124 -143
  49. package/dist/cli/commands.js.map +1 -1
  50. package/dist/cli/index.js +113 -106
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/cli/repl.js +82 -7
  53. package/dist/cli/repl.js.map +1 -1
  54. package/dist/cli/run.js +600 -95
  55. package/dist/cli/run.js.map +1 -1
  56. package/dist/cli/tui.js +145 -0
  57. package/dist/cli/tui.js.map +1 -0
  58. package/dist/cli/version.js +1 -1
  59. package/dist/enterprise/audit.js +145 -23
  60. package/dist/enterprise/audit.js.map +1 -1
  61. package/dist/enterprise/index.js +14 -11
  62. package/dist/enterprise/index.js.map +1 -1
  63. package/dist/enterprise/policy.js +22 -10
  64. package/dist/enterprise/policy.js.map +1 -1
  65. package/dist/harness/executor.js +127 -0
  66. package/dist/harness/executor.js.map +1 -0
  67. package/dist/harness/harness.js +87 -0
  68. package/dist/harness/harness.js.map +1 -0
  69. package/dist/harness/index.js +31 -0
  70. package/dist/harness/index.js.map +1 -0
  71. package/dist/harness/loader.js +138 -0
  72. package/dist/harness/loader.js.map +1 -0
  73. package/dist/harness/reporter.js +34 -0
  74. package/dist/harness/reporter.js.map +1 -0
  75. package/dist/harness/types.js +10 -0
  76. package/dist/harness/types.js.map +1 -0
  77. package/dist/harness/verifier.js +48 -0
  78. package/dist/harness/verifier.js.map +1 -0
  79. package/dist/hello.js +14 -0
  80. package/dist/hello.js.map +1 -0
  81. package/dist/memory/auto-summarize.js +208 -0
  82. package/dist/memory/auto-summarize.js.map +1 -0
  83. package/dist/memory/index.js +228 -0
  84. package/dist/memory/index.js.map +1 -0
  85. package/dist/models/model-router.js +100 -27
  86. package/dist/models/model-router.js.map +1 -1
  87. package/dist/models/model.dto.js +25 -3
  88. package/dist/models/model.dto.js.map +1 -1
  89. package/dist/models/providers/ollama.provider.js +12 -0
  90. package/dist/models/providers/ollama.provider.js.map +1 -1
  91. package/dist/models/providers/openai-compatible.provider.js +14 -1
  92. package/dist/models/providers/openai-compatible.provider.js.map +1 -1
  93. package/dist/plugins/plugin-loader.js +179 -0
  94. package/dist/plugins/plugin-loader.js.map +1 -0
  95. package/dist/runtime/event-log.js.map +1 -1
  96. package/dist/runtime/hooks.js +80 -0
  97. package/dist/runtime/hooks.js.map +1 -0
  98. package/dist/self-evolve/hook.js +60 -0
  99. package/dist/self-evolve/hook.js.map +1 -0
  100. package/dist/self-evolve/hook.ts +80 -0
  101. package/dist/self-evolve/manager.d.ts +8 -0
  102. package/dist/self-evolve/manager.js +401 -0
  103. package/dist/shared/config.js +35 -3
  104. package/dist/shared/config.js.map +1 -1
  105. package/dist/shared/errors.js +6 -2
  106. package/dist/shared/errors.js.map +1 -1
  107. package/dist/shared/i18n.js +535 -0
  108. package/dist/shared/i18n.js.map +1 -0
  109. package/dist/shared/secure-store.js +117 -0
  110. package/dist/shared/secure-store.js.map +1 -0
  111. package/dist/skills/grill.js +2 -1
  112. package/dist/skills/grill.js.map +1 -1
  113. package/dist/skills/self-heal.js +73 -0
  114. package/dist/skills/self-heal.js.map +1 -0
  115. package/dist/skills/skill-loader.js +131 -0
  116. package/dist/skills/skill-loader.js.map +1 -0
  117. package/dist/skills/skill-market.js +195 -0
  118. package/dist/skills/skill-market.js.map +1 -0
  119. package/dist/tools/analysis/code-analyzer.js +45 -18
  120. package/dist/tools/analysis/code-analyzer.js.map +1 -1
  121. package/dist/tools/index.js +5 -0
  122. package/dist/tools/index.js.map +1 -1
  123. package/dist/tools/mcp/index.js +84 -0
  124. package/dist/tools/mcp/index.js.map +1 -0
  125. package/dist/tools/mcp/mcp-client.js +194 -0
  126. package/dist/tools/mcp/mcp-client.js.map +1 -0
  127. package/dist/tools/sandbox.js +126 -0
  128. package/dist/tools/sandbox.js.map +1 -0
  129. package/dist/tools/shell/exec.js +72 -3
  130. package/dist/tools/shell/exec.js.map +1 -1
  131. package/dist/tools/shell/run-shell.tool.js +37 -7
  132. package/dist/tools/shell/run-shell.tool.js.map +1 -1
  133. package/dist/tools/skills/load-skill.tool.js +36 -0
  134. package/dist/tools/skills/load-skill.tool.js.map +1 -0
  135. package/dist/tools/tool.interface.js.map +1 -1
  136. package/dist/tools/tool.registry.js +69 -1
  137. package/dist/tools/tool.registry.js.map +1 -1
  138. package/dist/tools/web/web.tool.js +139 -0
  139. package/dist/tools/web/web.tool.js.map +1 -0
  140. package/dist/web/auth.js +178 -3
  141. package/dist/web/auth.js.map +1 -1
  142. package/dist/web/channels.js +171 -0
  143. package/dist/web/channels.js.map +1 -0
  144. package/dist/web/public/css/style.css +1546 -0
  145. package/dist/web/public/index.html +804 -37
  146. package/dist/web/public/js/api.js +309 -0
  147. package/dist/web/public/js/app.js +1472 -0
  148. package/dist/web/public/js/ui.js +832 -0
  149. package/dist/web/public/js/utils.js +170 -0
  150. package/dist/web/server.js +937 -11
  151. package/dist/web/server.js.map +1 -1
  152. package/dist/web/task-queue.js +470 -0
  153. package/dist/web/task-queue.js.map +1 -0
  154. package/dist/web/web-config.js +143 -0
  155. package/dist/web/web-config.js.map +1 -0
  156. package/docs/App/344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +299 -0
  157. package/docs/App/346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +554 -0
  158. package/docs/Deployment_Guide_EN.md +288 -0
  159. package/docs/SELF-EVOLVE-GUIDE.md +313 -0
  160. package/docs/Technical_Manual_EN.md +216 -0
  161. package/docs/User_Manual_EN.md +314 -0
  162. package/docs/error-codes.md +198 -0
  163. package/docs/screenshots/cli-demo.png +0 -0
  164. package/docs/screenshots/feature-comparison.png +0 -0
  165. package/docs/screenshots/web-console.png +0 -0
  166. package/docs/self-evolve-implementation.md +165 -0
  167. package/docs/self-evolve.md +166 -0
  168. package/docs//344/272/247/345/223/201/345/274/200/345/217/221/346/226/207/346/241/243.md +614 -614
  169. package/docs//344/274/201/344/270/232/351/203/250/347/275/262/344/270/216/345/220/210/350/247/204.md +267 -267
  170. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +318 -358
  171. package/docs//345/270/270/350/247/201/351/227/256/351/242/230/344/270/216/346/225/205/351/232/234/346/216/222/346/237/245.md +130 -130
  172. package/docs//346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +216 -303
  173. package/docs//346/236/266/346/236/204/344/270/216API.md +238 -238
  174. package/docs//347/224/250/346/210/267/346/211/213/345/206/214.md +196 -196
  175. package/docs//351/203/250/347/275/262/346/214/207/345/215/227.md +165 -165
  176. package/docs//351/203/250/347/275/262/350/257/264/346/230/216/344/271/246.md +288 -0
  177. package/docs//351/205/215/347/275/256/345/217/202/350/200/203.md +127 -127
  178. package/docs//351/241/265/351/235/242/345/212/237/350/203/275/345/244/215/347/233/230/344/270/216/345/206/222/347/203/237/346/265/213/350/257/225/346/212/245/345/221/212.html +117 -0
  179. package/package.json +108 -109
  180. package/tool-schema.json +117 -46
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseHooks = parseHooks;
4
+ exports.runHooks = runHooks;
5
+ /**
6
+ * 飞虹 Code (Muse Code 参照复刻)
7
+ * 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
8
+ *
9
+ * P2-1 hooks 确定性控制(对齐 Claude Code hooks):
10
+ * - PreToolUse 工具执行前触发;命令退出码非 0 → 阻止该工具调用(硬拦截)
11
+ * - PostToolUse 工具执行后触发(可跑 linter/格式化等,结果只记录不阻断)
12
+ * - PostEdit 文件编辑工具(write/edit)成功落盘后触发(只针对被改文件)
13
+ * - SessionStart 会话开始时触发(预留,CLI 装配处调用)
14
+ *
15
+ * 配置来源:FH_HOOKS 环境变量(JSON 数组)或配置文件 hooks 字段。
16
+ * 占位符:{cwd} {tool} {path} {runId} {ok}(PostToolUse 的 ok=1/0)。
17
+ * 零上下文成本:hook 是"代码/命令"而非"指令文本",不占 system prompt。
18
+ */
19
+ const exec_1 = require("../tools/shell/exec");
20
+ const logger_1 = require("../shared/logger");
21
+ /** 解析 FH_HOOKS / 配置文件 hooks(非法 JSON 返回空并告警) */
22
+ function parseHooks(raw) {
23
+ if (!raw?.trim())
24
+ return [];
25
+ try {
26
+ const parsed = JSON.parse(raw);
27
+ if (!Array.isArray(parsed))
28
+ return [];
29
+ return parsed.filter((h) => !!h && typeof h === 'object' && typeof h.command === 'string' && typeof h.event === 'string');
30
+ }
31
+ catch {
32
+ logger_1.logger.warn('FH_HOOKS 不是合法 JSON,已忽略');
33
+ return [];
34
+ }
35
+ }
36
+ /** 替换占位符 */
37
+ function substitute(cmd, ctx) {
38
+ return cmd
39
+ .replace(/\{cwd\}/g, ctx.cwd)
40
+ .replace(/\{runId\}/g, ctx.runId)
41
+ .replace(/\{tool\}/g, ctx.tool ?? '')
42
+ .replace(/\{path\}/g, ctx.path ?? '')
43
+ .replace(/\{ok\}/g, ctx.ok === undefined ? '' : ctx.ok ? '1' : '0');
44
+ }
45
+ function hookMatches(hook, ctx) {
46
+ if (hook.tools && hook.tools.length > 0 && ctx.tool && !hook.tools.includes(ctx.tool))
47
+ return false;
48
+ if (hook.paths && hook.paths.length > 0 && ctx.path && !hook.paths.some((p) => ctx.path.includes(p)))
49
+ return false;
50
+ return true;
51
+ }
52
+ /**
53
+ * 运行事件相关 hooks,返回是否应阻止(仅 PreToolUse 有阻断语义)。
54
+ * 单个 hook 命令失败不影响其他 hook 执行。
55
+ */
56
+ async function runHooks(hooks, event, ctx) {
57
+ const matched = hooks.filter((h) => h.event === event && hookMatches(h, ctx));
58
+ for (const hook of matched) {
59
+ const cmd = substitute(hook.command, ctx);
60
+ try {
61
+ const res = await (0, exec_1.runCommand)(cmd, ctx.cwd, hook.timeoutMs ?? 10000);
62
+ if (event === 'PreToolUse' && res.code !== 0) {
63
+ logger_1.logger.warn('hook blocked tool', { tool: ctx.tool, command: cmd, code: res.code });
64
+ return {
65
+ blocked: true,
66
+ reason: `PreToolUse hook 拒绝(exit ${res.code}): ${(res.stderr || res.stdout).slice(0, 200)}`,
67
+ };
68
+ }
69
+ }
70
+ catch (e) {
71
+ logger_1.logger.warn('hook execution failed', {
72
+ event,
73
+ command: cmd,
74
+ error: e instanceof Error ? e.message : String(e),
75
+ });
76
+ }
77
+ }
78
+ return { blocked: false };
79
+ }
80
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/runtime/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selfEvolveHook = exports.SelfEvolveHook = void 0;
4
+ const manager_1 = require("./manager");
5
+ /**
6
+ * Hook: 任务完成后自动检查是否需要记录失败
7
+ * 集成到工具调用流程中
8
+ */
9
+ class SelfEvolveHook {
10
+ manager;
11
+ constructor() {
12
+ this.manager = new manager_1.SelfEvolveManager();
13
+ this.manager.init();
14
+ }
15
+ /**
16
+ * 在工具调用失败时触发
17
+ */
18
+ onToolFailure(context) {
19
+ const { tool, input, error, attemptedSolutions } = context;
20
+ console.log(`[自我迭代] 检测到工具 ${tool} 调用失败`);
21
+ const failure = this.manager.recordFailure(`${tool}: ${JSON.stringify(input).slice(0, 100)}`, error, attemptedSolutions || []);
22
+ // 尝试查找已知解决方案
23
+ const solutions = this.manager.searchSolution(failure.error_type, failure.error_message);
24
+ if (solutions.length > 0) {
25
+ console.log(`[自我迭代] 找到已知解决方案: ${solutions[0].name}`);
26
+ // 这里可以自动应用解决方案
27
+ }
28
+ else {
29
+ console.log(`[自我迭代] 新问题,建议创建技能解决`);
30
+ }
31
+ return failure;
32
+ }
33
+ /**
34
+ * 在任务完成时触发
35
+ */
36
+ onTaskComplete(context) {
37
+ if (!context.success && context.error) {
38
+ return this.onToolFailure({
39
+ tool: 'task',
40
+ input: { task: context.task },
41
+ error: context.error
42
+ });
43
+ }
44
+ return null;
45
+ }
46
+ /**
47
+ * 每日自动复盘
48
+ */
49
+ async dailyReview() {
50
+ const report = this.manager.generateDailyReport();
51
+ if (report.pending > 0) {
52
+ console.warn(`[自我迭代] 今日仍有 ${report.pending} 个未解决问题`);
53
+ }
54
+ return report;
55
+ }
56
+ }
57
+ exports.SelfEvolveHook = SelfEvolveHook;
58
+ // 导出单例
59
+ exports.selfEvolveHook = new SelfEvolveHook();
60
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/self-evolve/hook.ts"],"names":[],"mappings":";;;AAAA,uCAA8C;AAE9C;;;GAGG;AACH,MAAa,cAAc;IACjB,OAAO,CAAoB;IAEnC;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,2BAAiB,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,OAKb;QACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;QAE3D,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CACxC,GAAG,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EACjD,KAAK,EACL,kBAAkB,IAAI,EAAE,CACzB,CAAC;QAEF,aAAa;QACb,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QAEzF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,oBAAoB,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACrD,eAAe;QACjB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,OAId;QACC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,aAAa,CAAC;gBACxB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;gBAC7B,KAAK,EAAE,OAAO,CAAC,KAAK;aACrB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAElD,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAtED,wCAsEC;AAED,OAAO;AACM,QAAA,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { SelfEvolveManager } from './manager';
2
+
3
+ /**
4
+ * Hook: 任务完成后自动检查是否需要记录失败
5
+ * 集成到工具调用流程中
6
+ */
7
+ export class SelfEvolveHook {
8
+ private manager: SelfEvolveManager;
9
+
10
+ constructor() {
11
+ this.manager = new SelfEvolveManager();
12
+ this.manager.init();
13
+ }
14
+
15
+ /**
16
+ * 在工具调用失败时触发
17
+ */
18
+ onToolFailure(context: {
19
+ tool: string,
20
+ input: any,
21
+ error: Error | string,
22
+ attemptedSolutions?: string[]
23
+ }) {
24
+ const { tool, input, error, attemptedSolutions } = context;
25
+
26
+ console.log(`[自我迭代] 检测到工具 ${tool} 调用失败`);
27
+
28
+ const failure = this.manager.recordFailure(
29
+ `${tool}: ${JSON.stringify(input).slice(0, 100)}`,
30
+ error,
31
+ attemptedSolutions || []
32
+ );
33
+
34
+ // 尝试查找已知解决方案
35
+ const solutions = this.manager.searchSolution(failure.error_type, failure.error_message);
36
+
37
+ if (solutions.length > 0) {
38
+ console.log(`[自我迭代] 找到已知解决方案: ${solutions[0].name}`);
39
+ // 这里可以自动应用解决方案
40
+ } else {
41
+ console.log(`[自我迭代] 新问题,建议创建技能解决`);
42
+ }
43
+
44
+ return failure;
45
+ }
46
+
47
+ /**
48
+ * 在任务完成时触发
49
+ */
50
+ onTaskComplete(context: {
51
+ success: boolean,
52
+ task: string,
53
+ error?: Error | string
54
+ }) {
55
+ if (!context.success && context.error) {
56
+ return this.onToolFailure({
57
+ tool: 'task',
58
+ input: { task: context.task },
59
+ error: context.error
60
+ });
61
+ }
62
+ return null;
63
+ }
64
+
65
+ /**
66
+ * 每日自动复盘
67
+ */
68
+ async dailyReview() {
69
+ const report = this.manager.generateDailyReport();
70
+
71
+ if (report.pending > 0) {
72
+ console.warn(`[自我迭代] 今日仍有 ${report.pending} 个未解决问题`);
73
+ }
74
+
75
+ return report;
76
+ }
77
+ }
78
+
79
+ // 导出单例
80
+ export const selfEvolveHook = new SelfEvolveHook();
@@ -0,0 +1,8 @@
1
+ declare class SelfEvolveManager {
2
+ init(): void;
3
+ recordFailure(errorType: string, error: any, attemptedSolutions?: string[]): any;
4
+ searchSolution(errorType: string, errorMessage: string): any[];
5
+ generateDailyReport(): any;
6
+ }
7
+
8
+ export { SelfEvolveManager };
@@ -0,0 +1,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
+ 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
+ }