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,170 @@
1
+ /**
2
+ * 工具函数模块:纯函数,无状态依赖,可被任意模块调用
3
+ */
4
+
5
+ function formatMarkdown(text) {
6
+ // 简单 Markdown 转换
7
+ return text
8
+ .replace(/&/g, '&')
9
+ .replace(/</g, '&lt;')
10
+ .replace(/>/g, '&gt;')
11
+ .replace(/^### (.*$)/gm, '<h3>$1</h3>')
12
+ .replace(/^## (.*$)/gm, '<h2>$1</h2>')
13
+ .replace(/^# (.*$)/gm, '<h1>$1</h1>')
14
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
15
+ .replace(/\*(.*?)\*/g, '<em>$1</em>')
16
+ .replace(/`(.*?)`/g, '<code>$1</code>')
17
+ .replace(/\n/g, '<br>');
18
+ }
19
+
20
+ function getDirectoryName(path) {
21
+ if (!path || path === '' || path === '/') return '/';
22
+ if (/^[A-Za-z]:$/.test(path)) return path + '\\';
23
+ if (/^[A-Za-z]:\\$/.test(path)) return path;
24
+ const parts = path.split(/[/\\]/).filter(Boolean);
25
+ if (parts.length <= 1) {
26
+ const driveMatch = parts[0].match(/^([A-Za-z]):$/);
27
+ if (driveMatch) return driveMatch[1] + ':\\';
28
+ return parts[0] || '/';
29
+ }
30
+ const parentParts = parts.slice(0, -1);
31
+ if (/^[A-Za-z]:$/.test(parentParts[0])) {
32
+ return parentParts[0] + '\\' + parentParts.slice(1).join('\\');
33
+ }
34
+ return parentParts.join('\\');
35
+ }
36
+
37
+ /** 渲染空状态提示,减少重复的 innerHTML 赋值代码 */
38
+ function renderEmpty(el, text) {
39
+ if (el) el.innerHTML = '<div class="empty">' + (text || '') + '</div>';
40
+ }
41
+
42
+ function extractUrl(text) {
43
+ if (!text) return '';
44
+ const m = text.match(/(https?:\/\/[^\s]+)/);
45
+ return m ? m[1] : '';
46
+ }
47
+
48
+ function linkifyArtifacts(text) {
49
+ let html = escapeHtml(text);
50
+ // 占位符保护:先提取已识别的片段,避免后续正则把已插入的 <span> 标签二次包裹
51
+ const tokens = [];
52
+ const protect = (s) => { const k = '\u0000TOK' + tokens.length + '\u0000'; tokens.push(s); return k; };
53
+ // 1) URL:排除结尾标点与 HTML 实体
54
+ html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, (m) => protect('<span class="artifact" data-kind="url" data-path="' + m + '">' + m + '</span>'));
55
+ // 2) Windows 绝对路径(支持正/反斜杠、中文、空格,排除结尾标点)
56
+ html = html.replace(/([A-Za-z]:[\\\/][^\s<>"'()]+?)(?=[\s<>"',。;:、))]|$)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
57
+ // 3) Unix 风格绝对路径(至少两级目录,避免误匹配 "2023/2024"、"a/b" 等相对写法)
58
+ html = html.replace(/(\/(?:[A-Za-z0-9_\-.]+\/){1,}[A-Za-z0-9_\-.]*)/g, (m) => protect('<span class="artifact" data-kind="file" data-path="' + m + '">' + m + '</span>'));
59
+ tokens.forEach((s, i) => { html = html.split('\u0000TOK' + i + '\u0000').join(s); });
60
+ return html;
61
+ }
62
+
63
+ function formatSize(n) {
64
+ if (!Number.isFinite(n)) return '';
65
+ if (n < 1024) return n + ' B';
66
+ if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
67
+ return (n / 1024 / 1024).toFixed(2) + ' MB';
68
+ }
69
+
70
+ function estimateDataUrlSize(dataUrl) {
71
+ // base64 长度 × 0.75 估算字节
72
+ const b64 = (dataUrl || '').split(',')[1] || '';
73
+ return Math.round(b64.length * 0.75);
74
+ }
75
+
76
+ function formatToolArgs(args) {
77
+ if (!args || typeof args !== 'object') return '';
78
+ const keys = Object.keys(args);
79
+ if (!keys.length) return '';
80
+ const rows = keys.map(function (k) {
81
+ let v = args[k];
82
+ if (v == null) v = '';
83
+ else if (typeof v === 'object') v = JSON.stringify(v);
84
+ return '<div><span style="color:var(--ink-2,#6b7280);">' + escapeHtml(k) + ':</span> ' + escapeHtml(String(v)) + '</div>';
85
+ });
86
+ return '<div class="tc-args">' + rows.join('') + '</div>';
87
+ }
88
+
89
+ function renderMarkdown(text) {
90
+ let html = escapeHtml(text == null ? '' : text);
91
+ const codeBlocks = [];
92
+ html = html.replace(/```(\w*)\n?([\s\S]*?)```/g, function (_, lang, code) {
93
+ const idx = codeBlocks.length;
94
+ codeBlocks.push('<pre style="background:var(--bg,#f5f6fa);padding:10px;border-radius:8px;overflow-x:auto;font-size:12px;margin:6px 0;white-space:pre-wrap;word-break:break-word;"><code>' + code + '</code></pre>');
95
+ return '\x00CB' + idx + '\x00';
96
+ });
97
+ html = html.replace(/`([^`]+)`/g, '<code style="background:var(--bg,#f5f6fa);padding:1px 5px;border-radius:4px;font-size:12px;">$1</code>');
98
+ html = html.replace(/\*\*([^*]+)\*\*/g, '<b>$1</b>');
99
+ html = html.replace(/^### (.*)$/gm, '<div style="font-weight:700;margin:8px 0 4px;">$1</div>');
100
+ html = html.replace(/^## (.*)$/gm, '<div style="font-weight:700;font-size:15px;margin:10px 0 4px;">$1</div>');
101
+ html = html.replace(/^# (.*)$/gm, '<div style="font-weight:700;font-size:16px;margin:10px 0 4px;">$1</div>');
102
+ html = html.replace(/^[-*] (.*)$/gm, '<div style="padding-left:14px;">• $1</div>');
103
+ html = html.replace(/^(\d+)\. (.*)$/gm, '<div style="padding-left:20px;">$1. $2</div>');
104
+ html = html.replace(/(https?:\/\/[^\s<>"'()]+)/g, '<a href="$1" style="color:var(--brand,#4f6ef7);text-decoration:underline;" target="_blank">$1</a>');
105
+ html = html.replace(/\n/g, '<br>');
106
+ html = html.replace(/\x00CB(\d+)\x00/g, function (_, idx) { return codeBlocks[parseInt(idx)]; });
107
+ return html;
108
+ }
109
+
110
+ function statusBadge(s) { return '<span class="badge ' + s + '">' + s + '</span>'; }
111
+
112
+ function closeModal(id) { document.getElementById(id).classList.remove('show'); }
113
+
114
+ function openModal(id) { document.getElementById(id).classList.add('show'); }
115
+
116
+ function toast(msg) {
117
+ const el = document.getElementById('toast');
118
+ el.textContent = msg; el.classList.add('show');
119
+ clearTimeout(el._t); el._t = setTimeout(() => el.classList.remove('show'), 2200);
120
+ }
121
+
122
+ function fmtTime(iso) { try { return new Date(iso).toLocaleString(); } catch { return iso || ''; } }
123
+
124
+ function escapeHtml(s) { return String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])); }
125
+
126
+ function applyI18nToEl(el) {
127
+ const key = el.getAttribute('data-i18n');
128
+ if (!key) return;
129
+ const dict = I18N[currentLang] || I18N.zh;
130
+ const tag = el.tagName;
131
+
132
+ // 1) 输入类控件:只处理 placeholder,用 ph.<id> 专用键;缺失则保留中文原文
133
+ if (tag === 'INPUT' || tag === 'TEXTAREA') {
134
+ if (el._i18nPhZh === undefined) el._i18nPhZh = el.getAttribute('placeholder') || '';
135
+ const phKey = 'ph.' + (el.id || '');
136
+ if (dict[phKey] != null) el.placeholder = dict[phKey];
137
+ else el.placeholder = el._i18nPhZh;
138
+ return;
139
+ }
140
+
141
+ // 2) <select>:只翻 title,内容交给 renderModelSelect 等渲染函数管理
142
+ if (tag === 'SELECT') {
143
+ if (el._i18nTitleZh === undefined) el._i18nTitleZh = el.getAttribute('title') || '';
144
+ const tiKey = 'title.' + (el.id || '');
145
+ if (dict[tiKey] != null) el.title = dict[tiKey];
146
+ else el.title = el._i18nTitleZh;
147
+ return;
148
+ }
149
+
150
+ // 3) 含元素子节点:保留子元素,只替换 title 与直接文本节点
151
+ if (el.firstElementChild) {
152
+ if (el.hasAttribute('title')) el.title = t(key);
153
+ let done = false;
154
+ el.childNodes.forEach((node) => {
155
+ if (node.nodeType === 3 && node.nodeValue.trim()) {
156
+ node.nodeValue = done ? '' : t(key);
157
+ done = true;
158
+ }
159
+ });
160
+ return;
161
+ }
162
+
163
+ // 4) 纯文本元素:直接覆盖
164
+ el.textContent = t(key);
165
+ }
166
+
167
+ function t(key) {
168
+ const dict = I18N[currentLang] || I18N.zh;
169
+ return dict[key] || key;
170
+ }