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
@@ -0,0 +1,348 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadFeishuConfig = loadFeishuConfig;
4
+ exports.isFeishuEnabled = isFeishuEnabled;
5
+ exports.decryptFeishuEvent = decryptFeishuEvent;
6
+ exports.parseFeishuEvent = parseFeishuEvent;
7
+ exports.setFeishuBridgeDeps = setFeishuBridgeDeps;
8
+ exports.handleFeishuCallback = handleFeishuCallback;
9
+ exports.sendFeishuReply = sendFeishuReply;
10
+ exports.initFeishuBridge = initFeishuBridge;
11
+ /**
12
+ * 飞虹 Code (对标 Muse Code · 自研内核)
13
+ * 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
14
+ *
15
+ * 飞书桥接(Feishu/Lark Bridge):
16
+ * - 入站:飞书事件订阅(im.message.receive_v1),URL 验证 + 消息接收 + 签名校验 + 解密
17
+ * - 出站:复用 FeishuIntegration 发送文本/卡片消息
18
+ * - 桥接:消息 → TaskQueue → 结果主动推送
19
+ *
20
+ * 环境变量配置:
21
+ * FH_FEISHU_ENABLED=true
22
+ * FH_FEISHU_APP_ID=飞书应用App ID
23
+ * FH_FEISHU_APP_SECRET=飞书应用App Secret
24
+ * FH_FEISHU_VERIFICATION_TOKEN=事件订阅验证Token
25
+ * FH_FEISHU_ENCRYPT_KEY=事件加密Key(可选,配置后消息需解密)
26
+ * FH_FEISHU_WORKSPACE=飞书任务工作目录(默认 ~/.fhcode/feishu-workspace)
27
+ *
28
+ * 飞书开放平台配置:
29
+ * - 事件订阅请求地址:https://your-domain:8080/api/feishu/callback
30
+ * - 订阅事件:接收消息 im.message.receive_v1
31
+ * - 权限:im:message(获取与发送消息)、im:message:send_as_bot(以应用身份发消息)
32
+ *
33
+ * 安全:
34
+ * - verification_token 校验(fail-closed)
35
+ * - encrypt_key AES-256-CBC 解密(配置后强制)
36
+ * - event_id 幂等去重
37
+ * - 用户会话隔离
38
+ */
39
+ const crypto_1 = require("crypto");
40
+ const fs_1 = require("fs");
41
+ const os_1 = require("os");
42
+ const path_1 = require("path");
43
+ const logger_1 = require("../shared/logger");
44
+ const collaboration_1 = require("./collaboration");
45
+ function loadFeishuConfig() {
46
+ const enabled = process.env.FH_FEISHU_ENABLED === 'true';
47
+ const workspace = process.env.FH_FEISHU_WORKSPACE || (0, path_1.join)((0, os_1.homedir)(), '.fhcode', 'feishu-workspace');
48
+ if (enabled && !(0, fs_1.existsSync)(workspace))
49
+ (0, fs_1.mkdirSync)(workspace, { recursive: true });
50
+ return {
51
+ enabled,
52
+ appId: process.env.FH_FEISHU_APP_ID || '',
53
+ appSecret: process.env.FH_FEISHU_APP_SECRET || '',
54
+ verificationToken: process.env.FH_FEISHU_VERIFICATION_TOKEN || '',
55
+ encryptKey: process.env.FH_FEISHU_ENCRYPT_KEY,
56
+ workspace,
57
+ };
58
+ }
59
+ function isFeishuEnabled(cfg) {
60
+ return cfg.enabled && !!cfg.appId && !!cfg.appSecret && !!cfg.verificationToken;
61
+ }
62
+ /* ===================== 飞书事件解密 ===================== */
63
+ /**
64
+ * 飞书事件加密解密(AES-256-CBC)。
65
+ * 规范:key = sha256(encrypt_key) 前 32 字节;IV = 密文 base64 解码后前 16 字节;
66
+ * 密文 = IV + 加密内容;PKCS7 填充。
67
+ */
68
+ function decryptFeishuEvent(encryptKey, encryptedBase64) {
69
+ const key = (0, crypto_1.createHash)('sha256').update(encryptKey).digest();
70
+ const encrypted = Buffer.from(encryptedBase64, 'base64');
71
+ const iv = encrypted.subarray(0, 16);
72
+ const data = encrypted.subarray(16);
73
+ const decipher = (0, crypto_1.createDecipheriv)('aes-256-cbc', key, iv);
74
+ decipher.setAutoPadding(true);
75
+ const decrypted = Buffer.concat([decipher.update(data), decipher.final()]);
76
+ return decrypted.toString('utf8');
77
+ }
78
+ /** 解析飞书事件订阅 v2.0 消息 */
79
+ function parseFeishuEvent(body) {
80
+ // URL 验证事件
81
+ if (body.type === 'url_verification')
82
+ return null;
83
+ // v2.0 事件格式
84
+ const header = (body.header || {});
85
+ const event = (body.event || {});
86
+ const eventType = header.event_type;
87
+ if (eventType !== 'im.message.receive_v1') {
88
+ logger_1.logger.info('feishu: ignoring non-message event', { eventType });
89
+ return null;
90
+ }
91
+ const sender = (event.sender || {});
92
+ const senderId = (sender.sender_id || {});
93
+ const message = (event.message || {});
94
+ const openId = (senderId.open_id || '');
95
+ const messageId = (message.message_id || '');
96
+ const messageType = (message.message_type || '');
97
+ const chatType = (message.chat_type || 'p2p');
98
+ const chatId = (message.chat_id || '');
99
+ // 解析文本内容(content 是 JSON 字符串)
100
+ let text;
101
+ if (messageType === 'text' && message.content) {
102
+ try {
103
+ const content = JSON.parse(message.content);
104
+ text = content.text || '';
105
+ }
106
+ catch {
107
+ text = message.content;
108
+ }
109
+ }
110
+ return {
111
+ eventId: (header.event_id || ''),
112
+ openId,
113
+ userId: senderId.user_id || undefined,
114
+ messageId,
115
+ messageType,
116
+ text,
117
+ chatType,
118
+ chatId,
119
+ raw: body,
120
+ };
121
+ }
122
+ const feishuSessions = new Map();
123
+ const FEISHU_SESSION_FILE = (0, path_1.join)((0, os_1.homedir)(), '.fhcode', 'feishu-sessions.json');
124
+ function loadFeishuSessions() {
125
+ if ((0, fs_1.existsSync)(FEISHU_SESSION_FILE)) {
126
+ try {
127
+ const data = JSON.parse((0, fs_1.readFileSync)(FEISHU_SESSION_FILE, 'utf8'));
128
+ for (const [k, v] of Object.entries(data))
129
+ feishuSessions.set(k, v);
130
+ }
131
+ catch (e) {
132
+ logger_1.logger.warn('feishu sessions load failed', { error: e instanceof Error ? e.message : String(e) });
133
+ }
134
+ }
135
+ }
136
+ function saveFeishuSessions() {
137
+ try {
138
+ const dir = (0, path_1.join)((0, os_1.homedir)(), '.fhcode');
139
+ if (!(0, fs_1.existsSync)(dir))
140
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
141
+ const data = {};
142
+ for (const [k, v] of feishuSessions)
143
+ data[k] = v;
144
+ (0, fs_1.writeFileSync)(FEISHU_SESSION_FILE, JSON.stringify(data, null, 2), 'utf8');
145
+ }
146
+ catch (e) {
147
+ logger_1.logger.warn('feishu sessions save failed', { error: e instanceof Error ? e.message : String(e) });
148
+ }
149
+ }
150
+ function getFeishuSession(openId) {
151
+ let s = feishuSessions.get(openId);
152
+ if (!s) {
153
+ s = { openId, lastActive: new Date().toISOString(), eventIds: [] };
154
+ feishuSessions.set(openId, s);
155
+ }
156
+ return s;
157
+ }
158
+ function isFeishuDuplicate(session, eventId) {
159
+ if (!eventId)
160
+ return false;
161
+ if (session.eventIds.includes(eventId))
162
+ return true;
163
+ session.eventIds.push(eventId);
164
+ if (session.eventIds.length > 100)
165
+ session.eventIds = session.eventIds.slice(-100);
166
+ return false;
167
+ }
168
+ /* ===================== 桥接核心 ===================== */
169
+ let taskQueueRef = null;
170
+ let feishuIntegration = null;
171
+ /** 注入 TaskQueue 引用和 FeishuIntegration(web server 启动时调用) */
172
+ function setFeishuBridgeDeps(queue, integration) {
173
+ taskQueueRef = queue;
174
+ feishuIntegration = integration;
175
+ }
176
+ /**
177
+ * 处理飞书事件订阅回调:
178
+ * 1. URL 验证(type=url_verification)→ 返回 challenge
179
+ * 2. 解密(如配置了 encrypt_key)
180
+ * 3. verification_token 校验(fail-closed)
181
+ * 4. 消息解析(im.message.receive_v1)
182
+ * 5. 幂等去重(event_id)
183
+ * 6. 转发到 TaskQueue
184
+ * 7. 立即返回 200,结果异步推送
185
+ */
186
+ async function handleFeishuCallback(cfg, body) {
187
+ if (!isFeishuEnabled(cfg)) {
188
+ return { status: 404, body: { error: 'feishu bridge not configured' }, contentType: 'application/json' };
189
+ }
190
+ try {
191
+ let eventBody = body;
192
+ // 加密消息解密
193
+ if (body.encrypt && cfg.encryptKey) {
194
+ try {
195
+ const decrypted = decryptFeishuEvent(cfg.encryptKey, body.encrypt);
196
+ eventBody = JSON.parse(decrypted);
197
+ }
198
+ catch (e) {
199
+ logger_1.logger.error('feishu event decrypt failed', { error: e instanceof Error ? e.message : String(e) });
200
+ return { status: 400, body: { error: 'decrypt failed' }, contentType: 'application/json' };
201
+ }
202
+ }
203
+ // URL 验证
204
+ if (eventBody.type === 'url_verification') {
205
+ const token = (eventBody.token || '');
206
+ if (token !== cfg.verificationToken) {
207
+ logger_1.logger.warn('feishu url_verification token mismatch');
208
+ return { status: 403, body: { error: 'invalid token' }, contentType: 'application/json' };
209
+ }
210
+ return { status: 200, body: { challenge: eventBody.challenge }, contentType: 'application/json' };
211
+ }
212
+ // verification_token 校验(v2.0 header.token)
213
+ const header = (eventBody.header || {});
214
+ const headerToken = (header.token || '');
215
+ if (headerToken && headerToken !== cfg.verificationToken) {
216
+ logger_1.logger.warn('feishu event token mismatch', { expected: cfg.verificationToken.slice(0, 4) + '...' });
217
+ return { status: 403, body: { error: 'invalid verification token' }, contentType: 'application/json' };
218
+ }
219
+ // 解析消息
220
+ const msg = parseFeishuEvent(eventBody);
221
+ if (!msg) {
222
+ // 非消息事件(如关注、群聊加入等),返回 200 确认
223
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
224
+ }
225
+ logger_1.logger.info('feishu inbound message', { openId: msg.openId, type: msg.messageType, chatType: msg.chatType, eventId: msg.eventId });
226
+ // 非文本消息 → 提示
227
+ if (msg.messageType !== 'text' || !msg.text) {
228
+ await sendFeishuReply(cfg, msg.openId, '目前仅支持文本消息,请输入文字描述您的需求。');
229
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
230
+ }
231
+ // 幂等去重
232
+ const session = getFeishuSession(msg.openId);
233
+ if (isFeishuDuplicate(session, msg.eventId)) {
234
+ logger_1.logger.info('feishu duplicate event ignored', { eventId: msg.eventId });
235
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
236
+ }
237
+ session.lastActive = new Date().toISOString();
238
+ saveFeishuSessions();
239
+ // 转发到 TaskQueue
240
+ if (!taskQueueRef) {
241
+ logger_1.logger.error('feishu bridge: taskQueue not initialized');
242
+ await sendFeishuReply(cfg, msg.openId, '服务未就绪,请稍后重试。');
243
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
244
+ }
245
+ const goal = msg.text.trim();
246
+ let record;
247
+ // 多轮续接
248
+ if (session.taskId) {
249
+ const existing = taskQueueRef.get(session.taskId);
250
+ if (existing && (existing.status === 'done' || existing.status === 'failed')) {
251
+ const continued = taskQueueRef.continueTask(session.taskId, goal);
252
+ if (continued) {
253
+ record = continued;
254
+ }
255
+ else {
256
+ record = taskQueueRef.submit(goal, { workspaceDir: cfg.workspace });
257
+ session.taskId = record.id;
258
+ }
259
+ }
260
+ else if (existing && (existing.status === 'queued' || existing.status === 'running')) {
261
+ await sendFeishuReply(cfg, msg.openId, '上一个任务仍在处理中,请稍候...');
262
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
263
+ }
264
+ else {
265
+ record = taskQueueRef.submit(goal, { workspaceDir: cfg.workspace });
266
+ session.taskId = record.id;
267
+ }
268
+ }
269
+ else {
270
+ record = taskQueueRef.submit(goal, { workspaceDir: cfg.workspace });
271
+ session.taskId = record.id;
272
+ }
273
+ saveFeishuSessions();
274
+ // 异步推送结果
275
+ void pushFeishuResult(cfg, msg.openId, record.id);
276
+ // 立即返回确认(飞书要求 3 秒内响应)
277
+ await sendFeishuReply(cfg, msg.openId, '⏳ 已收到,正在处理中... 完成后将主动推送结果。');
278
+ return { status: 200, body: { code: 0, msg: 'ok' }, contentType: 'application/json' };
279
+ }
280
+ catch (e) {
281
+ logger_1.logger.error('feishu callback handler error', { error: e instanceof Error ? e.message : String(e) });
282
+ return { status: 500, body: { error: 'internal error' }, contentType: 'application/json' };
283
+ }
284
+ }
285
+ /** 发送飞书文本消息(通过 FeishuIntegration 或直接 API) */
286
+ async function sendFeishuReply(cfg, openId, content) {
287
+ if (feishuIntegration) {
288
+ await feishuIntegration.sendMessage({
289
+ title: '飞虹 Code',
290
+ content,
291
+ receiver: openId,
292
+ });
293
+ return;
294
+ }
295
+ // 降级:直接调用 API
296
+ const feishuCfg = { appId: cfg.appId, appSecret: cfg.appSecret, defaultReceiver: openId };
297
+ const integration = new collaboration_1.FeishuIntegration(feishuCfg);
298
+ await integration.sendMessage({ title: '飞虹 Code', content, receiver: openId });
299
+ }
300
+ /** 异步轮询任务结果并推送到飞书 */
301
+ async function pushFeishuResult(cfg, openId, taskId) {
302
+ if (!taskQueueRef)
303
+ return;
304
+ for (let i = 0; i < 60; i++) {
305
+ await new Promise((r) => setTimeout(r, 10000));
306
+ const record = taskQueueRef.get(taskId);
307
+ if (!record)
308
+ return;
309
+ if (record.status === 'done') {
310
+ const answer = record.result?.finalAnswer || '任务完成,但未生成结果。';
311
+ const maxLen = 3000; // 飞书消息长度限制较宽松
312
+ const truncated = answer.length > maxLen ? answer.slice(0, maxLen) + '\n\n...(结果过长,已截断,请在 Web 控制台查看完整内容)' : answer;
313
+ try {
314
+ await sendFeishuReply(cfg, openId, truncated);
315
+ }
316
+ catch (e) {
317
+ logger_1.logger.error('feishu result push failed', { error: e instanceof Error ? e.message : String(e) });
318
+ }
319
+ return;
320
+ }
321
+ if (record.status === 'failed') {
322
+ try {
323
+ await sendFeishuReply(cfg, openId, `❌ 任务失败: ${(record.error || '未知错误').slice(0, 300)}`);
324
+ }
325
+ catch (e) {
326
+ logger_1.logger.error('feishu failure push failed', { error: e instanceof Error ? e.message : String(e) });
327
+ }
328
+ return;
329
+ }
330
+ }
331
+ try {
332
+ await sendFeishuReply(cfg, openId, '⏱️ 任务处理超时,请在 Web 控制台查看进度。');
333
+ }
334
+ catch { /* 忽略 */ }
335
+ }
336
+ /* ===================== 初始化 ===================== */
337
+ function initFeishuBridge() {
338
+ loadFeishuSessions();
339
+ const cfg = loadFeishuConfig();
340
+ if (isFeishuEnabled(cfg)) {
341
+ logger_1.logger.info('feishu bridge enabled', { appId: cfg.appId, workspace: cfg.workspace });
342
+ }
343
+ else {
344
+ logger_1.logger.info('feishu bridge disabled (set FH_FEISHU_ENABLED=true and configure credentials)');
345
+ }
346
+ return cfg;
347
+ }
348
+ //# sourceMappingURL=feishu-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu-bridge.js","sourceRoot":"","sources":["../../src/integrations/feishu-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GITHUB_MCP_TOOL_CATALOG = void 0;
4
+ exports.loadGithubMcpConfig = loadGithubMcpConfig;
5
+ exports.isValidGithubToken = isValidGithubToken;
6
+ exports.isGithubMcpAvailable = isGithubMcpAvailable;
7
+ exports.buildGithubMcpConfig = buildGithubMcpConfig;
8
+ exports.getGithubMcpServers = getGithubMcpServers;
9
+ exports.detectNpxAvailable = detectNpxAvailable;
10
+ exports.getGithubMcpStatus = getGithubMcpStatus;
11
+ /**
12
+ * 飞虹 Code (对标 Muse Code · 自研内核)
13
+ * 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
14
+ *
15
+ * GitHub MCP Server 接入:
16
+ * - 官方包:@modelcontextprotocol/server-github
17
+ * - 启动方式:npx -y @modelcontextprotocol/server-github
18
+ * - 认证:GITHUB_PERSONAL_ACCESS_TOKEN 环境变量
19
+ * - 能力:仓库管理、Issue/PR、代码搜索、文件读写、推送等
20
+ *
21
+ * 环境变量配置:
22
+ * FH_GITHUB_MCP_ENABLED=true # 启用 GitHub MCP(默认 false)
23
+ * GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx # GitHub Personal Access Token(必需)
24
+ * FH_GITHUB_MCP_PACKAGE=@modelcontextprotocol/server-github # 自定义包名(可选)
25
+ * FH_GITHUB_MCP_COMMAND=npx # 启动命令(默认 npx)
26
+ *
27
+ * 配置文件方式(fhcode.config.json):
28
+ * {
29
+ * "githubMcp": { "enabled": true, "token": "ghp_xxx" }
30
+ * }
31
+ *
32
+ * 安全:
33
+ * - Token 仅通过环境变量传递给 MCP 子进程,不落盘
34
+ * - 启用前校验 Token 格式(ghp_ 前缀,长度 >= 40)
35
+ * - MCP 工具受 ToolRegistry 沙箱/守卫统一约束
36
+ */
37
+ const fs_1 = require("fs");
38
+ const path_1 = require("path");
39
+ const logger_1 = require("../shared/logger");
40
+ function loadGithubMcpConfig(fileCfg) {
41
+ const file = (fileCfg?.githubMcp ?? {});
42
+ return {
43
+ enabled: process.env.FH_GITHUB_MCP_ENABLED === 'true' || file.enabled === true,
44
+ token: process.env.GITHUB_PERSONAL_ACCESS_TOKEN || file.token || '',
45
+ packageName: process.env.FH_GITHUB_MCP_PACKAGE || file.packageName || '@modelcontextprotocol/server-github',
46
+ command: process.env.FH_GITHUB_MCP_COMMAND || file.command || 'npx',
47
+ args: file.args,
48
+ };
49
+ }
50
+ /** 校验 GitHub Personal Access Token 格式(ghp_ 前缀,经典 Token;github_pat_ 前缀,细粒度 Token) */
51
+ function isValidGithubToken(token) {
52
+ if (!token || token.length < 40)
53
+ return false;
54
+ return token.startsWith('ghp_') || token.startsWith('github_pat_') || token.startsWith('gho_') || token.startsWith('ghu_') || token.startsWith('ghs_') || token.startsWith('ghr_');
55
+ }
56
+ /** GitHub MCP 是否可用(启用 + Token 有效) */
57
+ function isGithubMcpAvailable(cfg) {
58
+ if (!cfg.enabled)
59
+ return false;
60
+ if (!isValidGithubToken(cfg.token)) {
61
+ logger_1.logger.warn('GitHub MCP token 格式无效,已跳过', { tokenPrefix: cfg.token.slice(0, 4) + '...' });
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ /* ===================== McpServerConfig 生成 ===================== */
67
+ /**
68
+ * 生成 GitHub MCP Server 的 McpServerConfig。
69
+ * 工具名会以 github_<toolName> 前缀注册(如 github_create_issue)。
70
+ */
71
+ function buildGithubMcpConfig(cfg) {
72
+ return {
73
+ name: 'github',
74
+ command: cfg.command,
75
+ args: cfg.args ?? ['-y', cfg.packageName],
76
+ env: {
77
+ GITHUB_PERSONAL_ACCESS_TOKEN: cfg.token,
78
+ // 禁用 npm fund/audit 提示,减少 stderr 噪音
79
+ npm_config_fund: 'false',
80
+ npm_config_audit: 'false',
81
+ },
82
+ initTimeoutMs: 60000, // 首次 npx 下载包可能较慢
83
+ callTimeoutMs: 120000,
84
+ };
85
+ }
86
+ /**
87
+ * 从配置生成 GitHub MCP 服务器列表(可用时返回单元素数组,否则空数组)。
88
+ * 供 config.ts 叠加到 mcp.servers。
89
+ */
90
+ function getGithubMcpServers(fileCfg) {
91
+ const cfg = loadGithubMcpConfig(fileCfg);
92
+ if (!isGithubMcpAvailable(cfg))
93
+ return [];
94
+ const mcpCfg = buildGithubMcpConfig(cfg);
95
+ logger_1.logger.info('GitHub MCP Server 已启用', { package: cfg.packageName, command: cfg.command });
96
+ return [mcpCfg];
97
+ }
98
+ /* ===================== GitHub MCP 工具清单(参考) ===================== */
99
+ /**
100
+ * GitHub MCP Server 提供的主要工具(实际工具列表以运行时 tools/list 为准)。
101
+ * 用于文档说明和前端展示,不影响实际注册。
102
+ */
103
+ exports.GITHUB_MCP_TOOL_CATALOG = [
104
+ { category: '仓库', tools: ['get_repository', 'list_repositories', 'search_repositories', 'create_repository'] },
105
+ { category: 'Issue', tools: ['create_issue', 'get_issue', 'list_issues', 'search_issues', 'update_issue', 'add_issue_comment'] },
106
+ { category: 'Pull Request', tools: ['create_pull_request', 'get_pull_request', 'list_pull_requests', 'search_pull_requests', 'merge_pull_request', 'update_pull_request'] },
107
+ { category: '代码', tools: ['get_file_contents', 'create_or_update_file', 'push_files', 'search_code', 'get_commit', 'list_commits'] },
108
+ { category: '分支/标签', tools: ['list_branches', 'create_branch', 'list_tags', 'create_release'] },
109
+ { category: '工作流', tools: ['list_workflow_runs', 'get_workflow_run', 'trigger_workflow_dispatch'] },
110
+ ];
111
+ /* ===================== 环境检测 ===================== */
112
+ /** 检测 npx 是否可用(同步检查 node_modules/.bin 或全局) */
113
+ function detectNpxAvailable() {
114
+ // npx 随 npm 一起安装,检查 npm 是否可用即可
115
+ try {
116
+ // 简单检查:npm 根目录是否存在
117
+ const npmRoot = process.env.npm_config_prefix || (0, path_1.join)(process.env.APPDATA || '', 'npm');
118
+ return (0, fs_1.existsSync)((0, path_1.join)(npmRoot, 'npx.cmd')) || (0, fs_1.existsSync)((0, path_1.join)(npmRoot, 'npx'));
119
+ }
120
+ catch {
121
+ return true; // 假设可用,实际启动失败时 attachMcpTools 会容错跳过
122
+ }
123
+ }
124
+ /** 生成 GitHub MCP 接入状态报告(用于 /api/health 或诊断) */
125
+ function getGithubMcpStatus(fileCfg) {
126
+ const cfg = loadGithubMcpConfig(fileCfg);
127
+ return {
128
+ enabled: cfg.enabled,
129
+ available: isGithubMcpAvailable(cfg),
130
+ tokenConfigured: !!cfg.token,
131
+ tokenValid: isValidGithubToken(cfg.token),
132
+ package: cfg.packageName,
133
+ command: cfg.command,
134
+ toolCount: exports.GITHUB_MCP_TOOL_CATALOG.reduce((sum, c) => sum + c.tools.length, 0),
135
+ };
136
+ }
137
+ //# sourceMappingURL=github-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-mcp.js","sourceRoot":"","sources":["../../src/integrations/github-mcp.ts"],"names":[],"mappings":"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"}