feihong-code 0.2.1

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 (154) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +14 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +28 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +46 -0
  5. package/.github/SECURITY.md +67 -0
  6. package/.github/workflows/ci.yml +140 -0
  7. package/AGENT-GUIDE.md +237 -0
  8. package/CHANGELOG.md +73 -0
  9. package/CODE_OF_CONDUCT.md +56 -0
  10. package/CONTRIBUTING.md +68 -0
  11. package/LICENSE +22 -0
  12. package/README.md +500 -0
  13. package/dist/agent/code-review.js +115 -0
  14. package/dist/agent/code-review.js.map +1 -0
  15. package/dist/agent/code-writer.js +227 -0
  16. package/dist/agent/code-writer.js.map +1 -0
  17. package/dist/agent/context-compactor.js +108 -0
  18. package/dist/agent/context-compactor.js.map +1 -0
  19. package/dist/agent/experience.js +190 -0
  20. package/dist/agent/experience.js.map +1 -0
  21. package/dist/agent/orchestrator.js +212 -0
  22. package/dist/agent/orchestrator.js.map +1 -0
  23. package/dist/agent/parallel-orchestrator.js +94 -0
  24. package/dist/agent/parallel-orchestrator.js.map +1 -0
  25. package/dist/agent/planner.js +53 -0
  26. package/dist/agent/planner.js.map +1 -0
  27. package/dist/agent/prompts.js +26 -0
  28. package/dist/agent/prompts.js.map +1 -0
  29. package/dist/agent/quality-gate.js +143 -0
  30. package/dist/agent/quality-gate.js.map +1 -0
  31. package/dist/agent/repo-reader.js +384 -0
  32. package/dist/agent/repo-reader.js.map +1 -0
  33. package/dist/agent/repo-underwriter.js +132 -0
  34. package/dist/agent/repo-underwriter.js.map +1 -0
  35. package/dist/agent/self-heal.js +134 -0
  36. package/dist/agent/self-heal.js.map +1 -0
  37. package/dist/agent/self-improver.js +148 -0
  38. package/dist/agent/self-improver.js.map +1 -0
  39. package/dist/agent/subagent.js +75 -0
  40. package/dist/agent/subagent.js.map +1 -0
  41. package/dist/agent/swe-agent.js +162 -0
  42. package/dist/agent/swe-agent.js.map +1 -0
  43. package/dist/agent/swe-planner.js +155 -0
  44. package/dist/agent/swe-planner.js.map +1 -0
  45. package/dist/agent/swe-verifier.js +113 -0
  46. package/dist/agent/swe-verifier.js.map +1 -0
  47. package/dist/cli/commands.js +167 -0
  48. package/dist/cli/commands.js.map +1 -0
  49. package/dist/cli/index.js +179 -0
  50. package/dist/cli/index.js.map +1 -0
  51. package/dist/cli/repl.js +67 -0
  52. package/dist/cli/repl.js.map +1 -0
  53. package/dist/cli/run.js +762 -0
  54. package/dist/cli/run.js.map +1 -0
  55. package/dist/cli/version.js +14 -0
  56. package/dist/cli/version.js.map +1 -0
  57. package/dist/enterprise/audit.js +294 -0
  58. package/dist/enterprise/audit.js.map +1 -0
  59. package/dist/enterprise/guard.js +58 -0
  60. package/dist/enterprise/guard.js.map +1 -0
  61. package/dist/enterprise/index.js +99 -0
  62. package/dist/enterprise/index.js.map +1 -0
  63. package/dist/enterprise/policy.js +242 -0
  64. package/dist/enterprise/policy.js.map +1 -0
  65. package/dist/enterprise/quota.js +58 -0
  66. package/dist/enterprise/quota.js.map +1 -0
  67. package/dist/enterprise/tenant.js +143 -0
  68. package/dist/enterprise/tenant.js.map +1 -0
  69. package/dist/models/cost.js +13 -0
  70. package/dist/models/cost.js.map +1 -0
  71. package/dist/models/model-router.js +170 -0
  72. package/dist/models/model-router.js.map +1 -0
  73. package/dist/models/model.dto.js +61 -0
  74. package/dist/models/model.dto.js.map +1 -0
  75. package/dist/models/model.interface.js +3 -0
  76. package/dist/models/model.interface.js.map +1 -0
  77. package/dist/models/providers/mock.provider.js +35 -0
  78. package/dist/models/providers/mock.provider.js.map +1 -0
  79. package/dist/models/providers/ollama.provider.js +88 -0
  80. package/dist/models/providers/ollama.provider.js.map +1 -0
  81. package/dist/models/providers/openai-compatible.provider.js +106 -0
  82. package/dist/models/providers/openai-compatible.provider.js.map +1 -0
  83. package/dist/runtime/event-log.js +42 -0
  84. package/dist/runtime/event-log.js.map +1 -0
  85. package/dist/runtime/git.js +106 -0
  86. package/dist/runtime/git.js.map +1 -0
  87. package/dist/runtime/session-persist.js +60 -0
  88. package/dist/runtime/session-persist.js.map +1 -0
  89. package/dist/runtime/session-store.js +34 -0
  90. package/dist/runtime/session-store.js.map +1 -0
  91. package/dist/runtime/worktree.js +117 -0
  92. package/dist/runtime/worktree.js.map +1 -0
  93. package/dist/shared/config.js +184 -0
  94. package/dist/shared/config.js.map +1 -0
  95. package/dist/shared/errors.js +66 -0
  96. package/dist/shared/errors.js.map +1 -0
  97. package/dist/shared/logger.js +51 -0
  98. package/dist/shared/logger.js.map +1 -0
  99. package/dist/shared/types.js +9 -0
  100. package/dist/shared/types.js.map +1 -0
  101. package/dist/skills/goal.js +60 -0
  102. package/dist/skills/goal.js.map +1 -0
  103. package/dist/skills/grill.js +129 -0
  104. package/dist/skills/grill.js.map +1 -0
  105. package/dist/skills/plan.js +40 -0
  106. package/dist/skills/plan.js.map +1 -0
  107. package/dist/tools/analysis/code-analyzer.js +136 -0
  108. package/dist/tools/analysis/code-analyzer.js.map +1 -0
  109. package/dist/tools/file/edit.tool.js +43 -0
  110. package/dist/tools/file/edit.tool.js.map +1 -0
  111. package/dist/tools/file/list.tool.js +36 -0
  112. package/dist/tools/file/list.tool.js.map +1 -0
  113. package/dist/tools/file/read.tool.js +34 -0
  114. package/dist/tools/file/read.tool.js.map +1 -0
  115. package/dist/tools/file/write.tool.js +39 -0
  116. package/dist/tools/file/write.tool.js.map +1 -0
  117. package/dist/tools/generator/code-generator.js +119 -0
  118. package/dist/tools/generator/code-generator.js.map +1 -0
  119. package/dist/tools/generator/test-generator.js +65 -0
  120. package/dist/tools/generator/test-generator.js.map +1 -0
  121. package/dist/tools/index.js +53 -0
  122. package/dist/tools/index.js.map +1 -0
  123. package/dist/tools/safe-path.js +36 -0
  124. package/dist/tools/safe-path.js.map +1 -0
  125. package/dist/tools/search/grep.tool.js +81 -0
  126. package/dist/tools/search/grep.tool.js.map +1 -0
  127. package/dist/tools/shell/exec.js +50 -0
  128. package/dist/tools/shell/exec.js.map +1 -0
  129. package/dist/tools/shell/run-shell.tool.js +49 -0
  130. package/dist/tools/shell/run-shell.tool.js.map +1 -0
  131. package/dist/tools/tool.interface.js +8 -0
  132. package/dist/tools/tool.interface.js.map +1 -0
  133. package/dist/tools/tool.registry.js +75 -0
  134. package/dist/tools/tool.registry.js.map +1 -0
  135. package/dist/tools/verify/build-check.tool.js +37 -0
  136. package/dist/tools/verify/build-check.tool.js.map +1 -0
  137. package/dist/tools/verify/test-run.tool.js +37 -0
  138. package/dist/tools/verify/test-run.tool.js.map +1 -0
  139. package/dist/web/auth.js +25 -0
  140. package/dist/web/auth.js.map +1 -0
  141. package/dist/web/public/index.html +39 -0
  142. package/dist/web/server.js +60 -0
  143. package/dist/web/server.js.map +1 -0
  144. package/docs//344/272/247/345/223/201/345/274/200/345/217/221/346/226/207/346/241/243.md +614 -0
  145. 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 -0
  146. package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +358 -0
  147. 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 -0
  148. package/docs//346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +303 -0
  149. package/docs//346/236/266/346/236/204/344/270/216API.md +238 -0
  150. package/docs//347/224/250/346/210/267/346/211/213/345/206/214.md +196 -0
  151. package/docs//351/203/250/347/275/262/346/214/207/345/215/227.md +165 -0
  152. package/docs//351/205/215/347/275/256/345/217/202/350/200/203.md +127 -0
  153. package/package.json +83 -0
  154. package/tool-schema.json +127 -0
@@ -0,0 +1,614 @@
1
+ # 飞虹 Code(Muse Code 参照复刻)产品开发文档
2
+
3
+ > 项目代号:**飞虹 Code / FeiHong Code**
4
+ > 文档类型:完整产品开发文档(定位 + 架构 + 模块 + 接口 + 数据模型 + 里程碑 + 落地计划)
5
+ > 版本:v0.1.0-draft
6
+ > 日期:2026-08-10
7
+ > 状态:实现中(M0、M1、M2、B 真实模型联调、部署就绪、M3 恢复与审计 已完成并通过验证;M4 待推进)
8
+
9
+ ---
10
+
11
+ ## 0. 署名与版权
12
+
13
+ | 项 | 内容 |
14
+ |----|------|
15
+ | 公司 | 晋江市飞虹智科技企业管理有限公司 |
16
+ | 中心 | 飞扬企源研发中心 |
17
+ | 负责人 | 吴赐虹 |
18
+ | 用途 | 版权声明、README、关于页、源码注释头部统一署名 |
19
+
20
+ ---
21
+
22
+ ## 1. 产品概述
23
+
24
+ ### 1.1 产品定位(一句话)
25
+
26
+ **飞虹 Code 是一款运行在终端的 AI 编程智能体:用户用自然语言描述需求,它自主完成「规划 → 写码 → 执行 → 验证」的完整软件工程任务,并通过多子代理并行与长时任务恢复机制,在大型代码库中稳定交付。**
27
+
28
+ ### 1.2 背景与动机
29
+
30
+ - Meta 于 2026-08 发布 **Muse Code**(终端 AI 编程 Agent,基于 Muse Spark 1.2),对标 Claude Code / OpenAI Codex,主打多智能体并行、长时任务、仓库级代码变更,并采用低价按量付费策略(贡献者套餐便宜逾 10 倍,但需授权数据留存)。
31
+ - 该形态验证了「终端 Agent 自主完成完整软件工程任务」的市场价值,但**闭源、依赖 Meta 模型、数据留存策略对国内企业不友好**。
32
+ - 飞虹 Code 的目标:**参照其能力范式,复刻一套自主可控、模型可切换、数据不出域、可私有化部署的终端编程智能体**,复用本团队 TS/Node 工程能力与飞扬企源企业管理方法学。
33
+
34
+ ### 1.3 参照对象能力拆解(Muse Code)
35
+
36
+ | 能力维度 | Muse Code 实现 | 我们是否复刻 | 我们的差异点 |
37
+ |----------|----------------|--------------|--------------|
38
+ | 安装方式 | 单命令 `curl … | bash` | ✅ | 增加 `npm i -g` / 国内镜像源 |
39
+ | 多智能体并行 | 主代理 + 多个持久化子代理,隔离 worktree 并行 | ✅ | 子代理角色可配置(规划/编码/审查) |
40
+ | 长时任务与崩溃恢复 | 本地事件日志作为单一可信源,可精确回放 | ✅ | 事件日志可导出/审计,支持断点续跑 |
41
+ | 内置技能 | `/plan`、`/grill`、`/goal` 等 | ✅ | 扩展为可插拔技能市场(本地+团队共享) |
42
+ | 多模态输入 | 视频/文档 → 完整应用 | 🔲 P2 | 先支持图片/文档,视频后置 |
43
+ | 模型绑定 | 绑定 Muse Spark | ❌ | **多模型路由层**,不绑定单一厂商 |
44
+ | 数据策略 | 低价套餐需授权数据留存 | ❌ | 默认本地/私有部署,数据不出域 |
45
+ | 透明度 | 完全可审计 | ✅ | 增加变更 diff 可视化与回滚 |
46
+
47
+ ### 1.4 目标用户
48
+
49
+ 1. **专业软件工程师 / 架构师**:处理大型代码库重构、跨模块迁移。
50
+ 2. **技术团队负责人**:把重复性编程任务自动化。
51
+ 3. **AI 研究人员 / 独立开发者**:需要长时迭代优化(如 GPU 内核调优)。
52
+ 4. (远期)**非技术业务人员**:通过自然语言生成内部工具/页面。
53
+
54
+ ### 1.5 核心价值主张
55
+
56
+ - **自主可控**:模型、数据、部署全链路可私有化,不绑定任何云厂商。
57
+ - **成本最优**:多模型路由按任务/成本/能力自动选优,避免为简单任务付高价。
58
+ - **稳交付**:长时任务事件日志 + 崩溃恢复 + 隔离 worktree,大型任务不中断。
59
+ - **可审计**:每一次模型调用、工具执行、文件变更可追溯、可回滚。
60
+
61
+ ### 1.6 与参照的差异总结
62
+
63
+ > 不追「模型最强」,而追「架构最稳、可控性最高、成本最优、最贴合国内企业私有化诉求」。
64
+
65
+ ---
66
+
67
+ ## 2. 功能规划
68
+
69
+ ### 2.1 功能全景图
70
+
71
+ ```
72
+ 飞虹 Code
73
+ ├── 交互层(终端 REPL / 单条命令)
74
+ │ ├── 自然语言需求输入
75
+ │ ├── /plan 规划 /grill 压力测试 /goal 目标达成
76
+ │ └── 审批确认(危险操作时)
77
+ ├── 编排层(Agent Orchestrator)
78
+ │ ├── 任务分解 → 子代理派发
79
+ │ ├── 子代理并行(隔离 worktree)
80
+ │ └── 结果汇总与冲突协调
81
+ ├── 工具层(Tool System)
82
+ │ ├── 文件:read / write / edit / list / grep
83
+ │ ├── 执行:run_shell(沙箱+审批)
84
+ │ ├── 检索:codebase_search / web_fetch
85
+ │ └── 验证:test_run / build_check
86
+ ├── 模型层(Multi-Model Router)
87
+ │ ├── OpenAI 兼容 API(DeepSeek/通义/OpenRouter…)
88
+ │ ├── 本地模型(Ollama)
89
+ │ └── 路由策略:能力/成本/延迟
90
+ ├── 运行时(Runtime)
91
+ │ ├── 事件日志(单一可信源)
92
+ │ ├── 会话/子代理状态
93
+ │ └── 崩溃恢复 / 断点续跑
94
+ └── 技能层(Skill System)
95
+ ├── 内置技能
96
+ └── 可插拔技能(本地 + 团队共享)
97
+ ```
98
+
99
+ ### 2.2 优先级
100
+
101
+ | 等级 | 功能 | 说明 |
102
+ |------|------|------|
103
+ | **P0(MVP)** | 终端 REPL、自然语言→代码、文件读写编辑、shell 执行(带审批)、基础规划、模型路由(单/多供应商切换)、事件日志、结构化错误/日志 | 能完成「描述需求→生成并验证代码」的最小闭环 |
104
+ | **P1** | 多子代理并行 + 隔离 worktree、长时任务崩溃恢复、技能系统(/plan /grill /goal)、成本计量、diff 可视化与回滚 | 对标 Muse Code 核心差异化能力 |
105
+ | **P2** | 多模态输入(图片/文档→应用)、技能市场、团队共享配置、Web 管理面板(可选)、自动 PR 提交 | 增强与生态 |
106
+
107
+ ### 2.3 核心用户故事
108
+
109
+ - **US-1(开发者)**:`fhcode "把 src/utils 里的 date 格式化抽成独立模块并补单测"` → 自动规划、改码、跑测试、汇报结果。
110
+ - **US-2(长时任务)**:`fhcode "对 CUDA 内核做 24h 迭代优化"` → 事件日志持久化,进程崩溃后 `fhcode resume` 从断点续跑。
111
+ - **US-3(并行)**:`fhcode "同时给登录/支付/报表三个模块加审计日志"` → 派发 3 个子代理,各自隔离 worktree 并行,合并无冲突。
112
+
113
+ ---
114
+
115
+ ## 3. 技术架构
116
+
117
+ ### 3.1 总体架构(分层)
118
+
119
+ ```
120
+ ┌─────────────────────────────────────────────┐
121
+ │ CLI 入口 (src/cli) │ argparse / REPL / 单命令
122
+ ├─────────────────────────────────────────────┤
123
+ │ Agent 编排层 (src/agent) │ Orchestrator / Planner / SubAgent
124
+ ├──────────────┬──────────────┬───────────────┤
125
+ │ 工具层 │ 技能层 │ 模型路由层 │ ToolSystem / SkillSystem / ModelRouter
126
+ │ (src/tools) │ (src/skills) │ (src/models) │
127
+ ├──────────────┴──────┬───────┴───────────────┤
128
+ │ 运行时 / 存储层 (src/runtime) │ 事件日志 / 会话状态 / 恢复
129
+ ├─────────────────────────────────────────────┤
130
+ │ 基础设施 (src/shared) │ config / errors / logger / types
131
+ └─────────────────────────────────────────────┘
132
+ ```
133
+
134
+ ### 3.2 分层职责(铁律)
135
+
136
+ | 层 | 职责 | ❌ 禁止 |
137
+ |----|------|---------|
138
+ | CLI | 解析参数、启动 REPL、渲染输出、收集审批 | 写业务/模型逻辑 |
139
+ | Agent | 任务分解、调度子代理、汇总 | 直接调用模型 HTTP / 直接碰文件系统 |
140
+ | Tool | 单条能力的纯实现(带 schema + 沙箱) | 跨工具编排 |
141
+ | Model | 统一 chat/stream 接口 + 路由 + 成本计量 | 感知业务语义 |
142
+ | Runtime | 事件日志、状态、恢复 | 业务逻辑 |
143
+ | Shared | config/errors/logger/types | 业务代码 |
144
+
145
+ ### 3.3 多模型路由层设计
146
+
147
+ **目标**:不绑定任何厂商,按「能力 / 成本 / 延迟 / 任务类型」动态选模型。
148
+
149
+ ```
150
+ ModelRouter
151
+ ├─ registerProvider(OpenAICompatibleProvider) // DeepSeek / 通义 / OpenRouter
152
+ ├─ registerProvider(LocalOllamaProvider)
153
+ └─ route(task: ModelTask): Provider
154
+ 策略:
155
+ - capability: code-gen | reasoning | long-context | vision | cheap
156
+ - cost-ceiling: 本次任务预算上限
157
+ - fallback: 主选失败自动切次选
158
+ ```
159
+
160
+ - `ModelTask` 携带 `capabilityTags`、`maxCost`、`requireStream`、`contextWindow` 等元数据。
161
+ - 每次调用记录 `tokenUsage` 与 `cost` 进事件日志,支持成本计量与告警。
162
+ - 配置化供应商清单,密钥仅存于环境变量(`.env`,不入库)。
163
+
164
+ ### 3.4 工具系统(Tool System)
165
+
166
+ 每个工具实现统一契约:
167
+
168
+ ```typescript
169
+ interface Tool {
170
+ name: string; // 唯一名,如 "edit_file"
171
+ description: string; // 给模型看的用途说明
172
+ inputSchema: JSONSchema; // 输入校验(Zod/JSON Schema)
173
+ risk: 'safe' | 'shell' | 'destructive';
174
+ execute(input: unknown, ctx: ToolContext): Promise<ToolResult>;
175
+ }
176
+ ```
177
+
178
+ | 工具 | 风险级 | 说明 |
179
+ |------|--------|------|
180
+ | read_file / list_files / grep | safe | 只读,免审批 |
181
+ | write_file / edit_file | safe* | 写文件,记录 diff 可回滚 |
182
+ | run_shell | shell | 默认需审批/沙箱,危险命令拦截 |
183
+ | web_fetch | safe | 联网检索,受白名单限制 |
184
+ | test_run / build_check | shell | 触发验证,结果回流 |
185
+
186
+ ### 3.5 运行时事件日志(单一可信源)
187
+
188
+ - **Append-only** 事件流,是长时任务可回放/恢复的基础。
189
+ - 事件类型:`session_start` / `model_call` / `tool_call` / `approval` / `file_edit` / `error` / `subagent_spawn` / `session_end`。
190
+ - 存储于本地 `~/.feihong-code/sessions/<id>.log`(JSONL)。
191
+ - `fhcode resume <id>` 重放事件重建状态,从最后未完成的步骤续跑。
192
+
193
+ ### 3.6 子代理隔离与并行
194
+
195
+ - 主代理分解任务 → 派发 N 个 `SubAgent`,每个在独立 `git worktree` 工作(互不污染工作副本)。
196
+ - 角色可配:`planner`(规划)/ `coder`(实现)/ `reviewer`(审查)。
197
+ - 合并阶段由 Orchestrator 协调冲突(基于文件归属/变更区间)。
198
+
199
+ ### 3.7 技能系统
200
+
201
+ - 技能 = 预置 prompt 模板 + 工具组合 + 触发词。
202
+ - 内置:`/plan`、`/grill`、`/goal`;远期支持本地目录 + 团队共享插件。
203
+
204
+ ---
205
+
206
+ ## 4. 工程结构(Feature-first)
207
+
208
+ ```
209
+ feihong-code/
210
+ ├── package.json
211
+ ├── .env.example
212
+ ├── tsconfig.json
213
+ ├── src/
214
+ │ ├── cli/ # 入口、REPL、参数解析
215
+ │ │ ├── index.ts
216
+ │ │ ├── repl.ts
217
+ │ │ └── commands.ts
218
+ │ ├── agent/ # 编排层
219
+ │ │ ├── orchestrator.ts
220
+ │ │ ├── planner.ts
221
+ │ │ ├── subagent.ts
222
+ │ │ └── agent.dto.ts
223
+ │ ├── tools/ # 工具层(feature-first)
224
+ │ │ ├── file/
225
+ │ │ │ ├── read-file.tool.ts
226
+ │ │ │ ├── write-file.tool.ts
227
+ │ │ │ └── edit-file.tool.ts
228
+ │ │ ├── shell/
229
+ │ │ │ └── run-shell.tool.ts
230
+ │ │ ├── search/
231
+ │ │ │ └── grep.tool.ts
232
+ │ │ ├── verify/
233
+ │ │ │ ├── test-run.tool.ts
234
+ │ │ │ └── build-check.tool.ts
235
+ │ │ ├── tool.interface.ts
236
+ │ │ └── tool.registry.ts
237
+ │ ├── models/ # 多模型路由层
238
+ │ │ ├── model-router.ts
239
+ │ │ ├── model.interface.ts
240
+ │ │ ├── providers/
241
+ │ │ │ ├── openai-compatible.provider.ts
242
+ │ │ │ └── ollama.provider.ts
243
+ │ │ └── model.dto.ts
244
+ │ ├── skills/ # 技能层
245
+ │ │ ├── skill.interface.ts
246
+ │ │ ├── plan.skill.ts
247
+ │ │ ├── grill.skill.ts
248
+ │ │ └── goal.skill.ts
249
+ │ ├── runtime/ # 运行时/存储
250
+ │ │ ├── event-log.ts
251
+ │ │ ├── session-store.ts
252
+ │ │ └── recovery.ts
253
+ │ └── shared/ # 基础设施
254
+ │ ├── config.ts # 集中配置,启动校验,fail-fast
255
+ │ ├── errors.ts # 类型化错误层级
256
+ │ ├── logger.ts # 结构化 JSON 日志 + requestId
257
+ │ └── types.ts
258
+ ├── tests/
259
+ │ ├── unit/
260
+ │ └── integration/
261
+ └── docs/
262
+ └── 产品开发文档.md
263
+ ```
264
+
265
+ ---
266
+
267
+ ## 5. 核心模块设计
268
+
269
+ ### 5.1 配置中心(集中、类型化、fail-fast)
270
+
271
+ ```typescript
272
+ // src/shared/config.ts
273
+ import 'dotenv/config';
274
+
275
+ function required(name: string): string {
276
+ const v = process.env[name];
277
+ if (!v) throw new Error(`缺少必需环境变量: ${name}`); // fail-fast
278
+ return v;
279
+ }
280
+
281
+ export const config = {
282
+ app: { name: 'feihong-code', version: '0.1.0', homeDir: required('FH_HOME') },
283
+ models: {
284
+ providers: JSON.parse(process.env.FH_PROVIDERS || '[]'), // 供应商清单(含 endpoint/key/标签)
285
+ defaultStrategy: process.env.FH_MODEL_STRATEGY || 'cost', // cost|capability|latency
286
+ budgetPerTaskUsd: Number(process.env.FH_BUDGET_USD || '0.5'),
287
+ },
288
+ runtime: { logDir: process.env.FH_LOG_DIR || '~/.feihong-code/sessions', maxRetries: 3 },
289
+ security: { shellAllowlist: (process.env.FH_SHELL_ALLOW || '').split(','), requireApproval: true },
290
+ } as const;
291
+ ```
292
+
293
+ ### 5.2 类型化错误层级
294
+
295
+ ```typescript
296
+ // src/shared/errors.ts
297
+ export class AppError extends Error {
298
+ constructor(
299
+ message: string,
300
+ public readonly code: string,
301
+ public readonly status: number,
302
+ public readonly isOperational = true,
303
+ ) { super(message); }
304
+ }
305
+ export class ConfigError extends AppError {
306
+ constructor(key: string) { super(`配置缺失: ${key}`, 'CONFIG_ERROR', 500); }
307
+ }
308
+ export class ModelError extends AppError {
309
+ constructor(msg: string, public readonly provider: string) {
310
+ super(`模型调用失败[${provider}]: ${msg}`, 'MODEL_ERROR', 502);
311
+ }
312
+ }
313
+ export class ToolError extends AppError {
314
+ constructor(tool: string, msg: string) { super(`工具[${tool}]失败: ${msg}`, 'TOOL_ERROR', 400); }
315
+ }
316
+ export class ApprovalRequiredError extends AppError {
317
+ constructor(action: string) { super(`需人工审批: ${action}`, 'APPROVAL_REQUIRED', 401); }
318
+ }
319
+ ```
320
+
321
+ ### 5.3 结构化日志
322
+
323
+ ```typescript
324
+ // src/shared/logger.ts
325
+ import { randomUUID } from 'crypto';
326
+ const reqId = randomUUID();
327
+ export const logger = {
328
+ info: (msg: string, meta = {}) => console.log(JSON.stringify({ level: 'info', msg, reqId, ...meta })),
329
+ error: (msg: string, meta = {}) => console.error(JSON.stringify({ level: 'error', msg, reqId, ...meta })),
330
+ };
331
+ // ❌ 禁止 console.log 散落业务代码;禁止记录密钥/PII
332
+ ```
333
+
334
+ ### 5.4 Agent 编排器(节选)
335
+
336
+ ```typescript
337
+ // src/agent/orchestrator.ts
338
+ export class Orchestrator {
339
+ constructor(
340
+ private readonly router: ModelRouter,
341
+ private readonly tools: ToolRegistry,
342
+ private readonly runtime: EventLog,
343
+ ) {}
344
+
345
+ async run(task: string): Promise<AgentResult> {
346
+ this.runtime.append({ type: 'session_start', task });
347
+ const plan = await this.planner.plan(task, this.router);
348
+ const results = await Promise.all(
349
+ plan.steps.map((s) => this.dispatchSubAgent(s)), // 隔离 worktree 并行
350
+ );
351
+ return this.aggregate(results);
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### 5.5 模型路由(节选)
357
+
358
+ ```typescript
359
+ // src/models/model-router.ts
360
+ export class ModelRouter {
361
+ private providers: ModelProvider[] = [];
362
+ register(p: ModelProvider) { this.providers.push(p); }
363
+ async route(task: ModelTask): Promise<ModelProvider> {
364
+ const scored = this.providers
365
+ .filter((p) => task.capabilityTags.every((t) => p.tags.includes(t)))
366
+ .sort((a, b) => this.score(a, task) - this.score(b, task)); // 按策略打分
367
+ const pick = scored[0];
368
+ if (!pick) throw new ModelError('无可用模型', 'router');
369
+ return pick;
370
+ }
371
+ }
372
+ ```
373
+
374
+ ### 5.6 工具实现示例(edit_file)
375
+
376
+ ```typescript
377
+ // src/tools/file/edit-file.tool.ts
378
+ export const editFileTool: Tool = {
379
+ name: 'edit_file',
380
+ description: '按 old_string→new_string 精确替换文件内容',
381
+ risk: 'safe',
382
+ inputSchema: { type: 'object', properties: { path: { type: 'string' }, old_string: { type: 'string' }, new_string: { type: 'string' } }, required: ['path','old_string','new_string'] },
383
+ async execute(input, ctx) {
384
+ const before = await fs.readFile(input.path, 'utf8');
385
+ if (!before.includes(input.old_string)) throw new ToolError('edit_file', 'old_string 未匹配');
386
+ const after = before.replace(input.old_string, input.new_string);
387
+ await fs.writeFile(input.path, after);
388
+ ctx.runtime.recordDiff(input.path, before, after); // 可回滚
389
+ return { ok: true, path: input.path };
390
+ },
391
+ };
392
+ ```
393
+
394
+ ### 5.7 运行时事件日志
395
+
396
+ ```typescript
397
+ // src/runtime/event-log.ts
398
+ export class EventLog {
399
+ constructor(private readonly file: string) {}
400
+ append(event: AgentEvent) {
401
+ appendFileSync(this.file, JSON.stringify({ ts: Date.now(), ...event }) + '\n');
402
+ }
403
+ replay(): AgentEvent[] { return readFileSync(this.file,'utf8').trim().split('\n').map(JSON.parse); }
404
+ }
405
+ ```
406
+
407
+ ### 5.8 技能系统
408
+
409
+ ```typescript
410
+ // src/skills/skill.interface.ts
411
+ export interface Skill {
412
+ name: string; // /plan
413
+ description: string;
414
+ trigger: RegExp;
415
+ run(ctx: SkillContext): Promise<void>;
416
+ }
417
+ ```
418
+
419
+ ---
420
+
421
+ ## 6. 关键接口契约(TypeScript)
422
+
423
+ ```typescript
424
+ // 模型层
425
+ interface ModelProvider {
426
+ id: string;
427
+ tags: CapabilityTag[]; // 'code-gen' | 'reasoning' | 'long-context' | 'vision' | 'cheap'
428
+ chat(req: ChatRequest): Promise<ChatResponse>;
429
+ stream(req: ChatRequest): AsyncIterable<ChatChunk>;
430
+ }
431
+ interface ChatRequest { messages: ChatMessage[]; temperature?: number; maxTokens?: number; }
432
+ interface ChatResponse { content: string; usage: TokenUsage; }
433
+ interface TokenUsage { promptTokens: number; completionTokens: number; costUsd: number; }
434
+
435
+ // 工具层
436
+ interface ToolContext { runtime: EventLog; cwd: string; askApproval(action: string): Promise<boolean>; }
437
+ interface ToolResult { ok: boolean; data?: unknown; error?: string; }
438
+
439
+ // Agent 层
440
+ interface AgentPlan { steps: PlanStep[]; }
441
+ interface PlanStep { id: string; goal: string; role: 'planner'|'coder'|'reviewer'; worktree: string; }
442
+ interface AgentResult { changes: FileChange[]; summary: string; costUsd: number; }
443
+ ```
444
+
445
+ ---
446
+
447
+ ## 7. 数据模型
448
+
449
+ ### 7.1 事件日志(JSONL,append-only)
450
+
451
+ ```json
452
+ { "ts": 1754790000000, "type": "model_call", "provider": "deepseek", "usage": {"promptTokens":120,"completionTokens":300,"costUsd":0.0009} }
453
+ { "ts": 1754790001000, "type": "tool_call", "tool": "edit_file", "input": {"path":"src/a.ts"}, "risk": "safe" }
454
+ { "ts": 1754790002000, "type": "approval", "action": "run_shell: npm test", "decision": "granted" }
455
+ ```
456
+
457
+ ### 7.2 会话状态
458
+
459
+ | 字段 | 类型 | 说明 |
460
+ |------|------|------|
461
+ | id | string | 会话 UUID |
462
+ | task | string | 原始需求 |
463
+ | status | enum | planning / running / paused / done / failed |
464
+ | subagents | SubAgent[] | 派发的子代理 |
465
+ | costUsd | number | 累计成本 |
466
+ | createdAt | number | 时间戳 |
467
+
468
+ ### 7.3 子代理
469
+
470
+ | 字段 | 类型 | 说明 |
471
+ |------|------|------|
472
+ | id | string | 子代理 UUID |
473
+ | role | enum | planner / coder / reviewer |
474
+ | worktree | string | 隔离工作树路径 |
475
+ | status | enum | idle / busy / done |
476
+
477
+ ---
478
+
479
+ ## 8. 配置管理(.env.example)
480
+
481
+ ```bash
482
+ # 应用
483
+ FH_HOME=~/.feihong-code
484
+ FH_LOG_DIR=~/.feihong-code/sessions
485
+
486
+ # 模型路由(多供应商,JSON 数组)
487
+ # 每个 provider: { id, type:"openai-compatible"|"ollama", baseURL, apiKey, tags:[], costPer1k }
488
+ FH_PROVIDERS='[
489
+ {"id":"deepseek","type":"openai-compatible","baseURL":"https://api.deepseek.com/v1","apiKey":"","tags":["code-gen","cheap"],"costPer1k":0.0001},
490
+ {"id":"qwen","type":"openai-compatible","baseURL":"https://dashscope.aliyuncs.com/compatible-mode/v1","apiKey":"","tags":["code-gen","long-context"],"costPer1k":0.0002},
491
+ {"id":"ollama","type":"ollama","baseURL":"http://localhost:11434","apiKey":"","tags":["code-gen","local"],"costPer1k":0}
492
+ ]'
493
+ FH_MODEL_STRATEGY=cost # cost | capability | latency
494
+ FH_BUDGET_USD=0.5 # 单任务预算上限
495
+
496
+ # 安全
497
+ FH_SHELL_ALLOW=git,npm,pnpm,node,ls,cat # shell 白名单(逗号分隔)
498
+ FH_REQUIRE_APPROVAL=true
499
+ ```
500
+
501
+ ---
502
+
503
+ ## 9. 安全与合规
504
+
505
+ 遵循飞扬企源「管理给方案,技术给步骤,安全守底线」原则:
506
+
507
+ 1. **命令沙箱**:`run_shell` 仅允许白名单命令;危险命令(rm -rf、:(){、curl|sh 等)强制拦截并需显式审批。
508
+ 2. **数据不出域**:默认本地/私有部署;供应商密钥仅存于环境变量,绝不入库、不打印、不写日志。
509
+ 3. **操作留痕**:所有模型调用、工具执行、文件变更进事件日志,可审计、可回滚。
510
+ 4. **敏感信息脱敏**:日志自动遮蔽密钥/PII;客户信息、合同、财务等内部机密绝不进入 Agent 上下文。
511
+ 5. **权限分级**:危险操作(删除、推送远端、修改系统配置)必须人工审批。
512
+ 6. **绝不越权**:不修改薪酬/股权/制度、不承诺效果、不伪造身份。
513
+ 7. **企业权限(M4)**:四角色 RBAC + deny 优先矩阵,危险命令/敏感路径在角色判定前即拦截(含 admin);策略覆盖只能加严不能放宽。
514
+ 8. **防篡改审计(M4)**:工具执行前由守卫统一留痕,审计日志按月切分并以 sha256 哈希链串联,任意篡改均可被 `audit verify` 定位断点。
515
+ 9. **多租户与成本治理(M4)**:租户物理目录隔离、ID 正则防穿越;单任务成本上限 + 租户日预算双重熔断,超限直接拒绝。
516
+
517
+ ---
518
+
519
+ ## 10. 开发里程碑
520
+
521
+ | 里程碑 | 周期(估) | 交付物 | 退出标准 |
522
+ |--------|----------|--------|----------|
523
+ | **M0 脚手架** | 3d | feature-first 工程结构、config/errors/logger、CLI 入口 | `fhcode --version` 可运行,构建通过 ✅(2026-08-10) |
524
+ | **M1 P0 闭环** | 10d | 模型路由(≥2 供应商)、文件/编辑/shell 工具、REPL、事件日志 | 能完成 US-1:`描述需求→改码→跑测试` ✅(2026-08-10 离线闭环验证通过) |
525
+ | **M2 编排升级** | 10d | 多子代理并行 + 隔离 worktree、规划/技能、成本计量 | 能完成 US-3 并行三模块 ✅(2026-08-10 离线 worktree 隔离并行端到端验证通过) |
526
+ | **B 真实模型联调** | 2d | 接入 OpenAI 兼容真实模型(Agnes 网关)、ReAct 闭环验证、.env 加载器 | 单命令问答 + list 工具调用真实跑通 ✅(2026-08-10 Agnes 网关联调通过;成本计量/事件日志正常) |
527
+ | **M3 恢复与审计** | 7d | `sessions`/`resume` 断点续跑、`diff`/`rollback` 会话作用域变更管理、交互式审批流 | 能完成 US-2 长时任务中断续跑 ✅(2026-08-10 离线端到端验证:sessions 列表/resume 续跑/diff/rollback 全绿,交互式与白名单审批 6 项断言通过) |
528
+ | **M4 打磨发布** | 5d | README/署名、安装脚本、冒烟测试、**企业级(RBAC/防篡改审计/多租户/三流水线 CI)**、v0.1.0 打包 | 端到端冒烟通过,可 `npm i -g` 安装;企业断言 41/41 通过 ✅(2026-08-10) |
529
+
530
+ ---
531
+
532
+ ## 11. 任务拆解(落地计划)
533
+
534
+ ```
535
+ M0:
536
+ [x] 初始化 npm/ts 工程、tsconfig、目录骨架
537
+ [x] shared/config、errors、logger、types
538
+ [x] cli/index + 参数解析 + --version
539
+ M1:
540
+ [x] models: interface + openai-compatible + ollama + router(含 cost 计量、zod 校验)
541
+ [x] tools: read/write/edit/list/grep + run_shell(沙箱) + test/build(含路径安全、白名单+审批)
542
+ [x] agent: orchestrator(ReAct 循环) + planner 最小版
543
+ [x] runtime: event-log(JSONL 单一可信源) + session-store
544
+ [x] REPL 交互 + 单命令模式(离线 Mock 驱动闭环)
545
+ M2:
546
+ [x] subagent + git worktree 隔离(git worktree add/remove 隔离工作区;离线 Mock 驱动子代理)
547
+ [x] /plan(只读目标分解,按 并且/以及/同时 等连词切分)/grill(红队式安全审查,误报已收敛)/goal(目标持久化到 ~/.feihong-code/goals)
548
+ [x] 并行编排器 runParallel:分解→建 worktree→Promise.allSettled 并行子代理→清理(已修复 Windows 上多 worktree 顺序移除连带清掉 .git/worktrees 的已知缺陷,改用 尽力移除+强制清目录+prune 鲁棒策略)
549
+ [x] 成本计量接入事件日志(每轮迭代累计 costUsd,落检查点 + 事件日志)
550
+ M3:
551
+ [x] sessions 列出历史会话 / resume 从检查点续跑(Orchestrator.run(goal, resume?) 重建对话继续 ReAct)
552
+ [x] diff 展示会话作用域变更 / rollback 回滚(git 辅助,touchedFiles 作用域,--yes 确认,非 git 仓库拒绝)
553
+ [x] 审批流:TTY 交互式 y/n 确认 + 非 TTY 白名单兜底(interactiveApprover / defaultApproverFor)
554
+ M4:
555
+ [x] 安装脚本 install.sh + npm 包(files 白名单防 .env 泄露、prepublishOnly 自动构建)
556
+ [x] README、署名、LICENSE(全部带晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹)
557
+ [x] 企业级四能力(src/enterprise/):
558
+ - tenant.ts 多租户物理目录隔离 + ID 正则防穿越 + 默认租户兼容
559
+ - policy.ts RBAC 四角色 + deny 优先 + 危险命令(23)/敏感路径(11)黑名单 + 策略覆盖加严
560
+ - audit.ts sha256 哈希链防篡改 + 按月切分 + redact 脱敏 + verifyAudit
561
+ - quota.ts 租户日预算 FH_TENANT_BUDGET_USD + 单任务 maxCostUsd 熔断
562
+ - guard.ts 唯一权威闸门(策略判定→审批→留痕一次性完成)
563
+ - index.ts 装配 isEnterpriseEnabled/assertQuota/renderWhoami
564
+ [x] CLI 企业命令:whoami / policy / audit [--limit N] / audit verify / tenants
565
+ [x] 三流水线 CI(build 多 Node 矩阵 / enterprise 41 项离线断言 / security 发布白名单+密钥扫描)
566
+ [x] 冒烟测试脚本 scripts/verify-m4.mjs(41 项全离线断言,7 节) + npm run verify:m4 / verify
567
+ [x] 文档:README §4.8 企业能力、用户手册 §2.7+安全模型、配置参考 M4 变量、架构与API §8、部署指南 §5 三流水线、常见问题 Q13-Q16、本文件 §9/§10/§11
568
+ ```
569
+
570
+ ---
571
+
572
+ ## 12. 风险与对策
573
+
574
+ | 风险 | 影响 | 对策 |
575
+ |------|------|------|
576
+ | 模型厂商接口变动 | 调用失败 | 供应商抽象层 + fallback 路由 |
577
+ | 长时任务进程崩溃 | 进度丢失 | 事件日志 append-only + resume |
578
+ | 并行 worktree 冲突 | 合并失败 | 文件归属/变更区间协调 + reviewer |
579
+ | shell 误执行危险命令 | 数据损失 | 白名单 + 危险拦截 + 审批 |
580
+ | 成本失控 | 超支 | 单任务预算上限 + 实时计量告警 |
581
+ | 数据合规 | 泄露 | 默认私有部署、密钥不入库、日志脱敏 |
582
+
583
+ ---
584
+
585
+ ## 13. 附录
586
+
587
+ ### 13.1 命令参考(草案)
588
+
589
+ | 命令 | 说明 |
590
+ |------|------|
591
+ | `fhcode "<需求>"` | 单命令模式:直接执行一条需求 |
592
+ | `fhcode` | 进入交互 REPL |
593
+ | `fhcode /plan <需求>` | 仅规划,不执行 |
594
+ | `fhcode /grill <计划>` | 对计划做压力测试/找漏洞 |
595
+ | `fhcode /goal <目标>` | 目标达成模式,循环推进 |
596
+ | `fhcode resume <id>` | 从断点恢复长时任务 |
597
+ | `fhcode log <id>` | 查看事件日志 |
598
+ | `fhcode diff <id>` | 查看变更 diff / 回滚 |
599
+
600
+ ### 13.2 命名约定
601
+
602
+ - 包名:`feihong-code`;命令:`fhcode`;配置前缀:`FH_`。
603
+ - 文件夹小写下划线/连字符;类型/接口 PascalCase;函数 camelCase。
604
+ - 所有源码文件头部注明署名(公司/中心/负责人)。
605
+
606
+ ### 13.3 与团队其他项目的关系
607
+
608
+ - **geo-saa**:本项目的成本计量/会话管理可借鉴其 Spring Boot 后端(远期 Web 面板复用)。
609
+ - **FyqyClaw**:若后续做桌面版 GUI,直接复用其 Electron + Vite 工程化经验。
610
+ - 统一署名规范、安全底线、冒烟测试方法论三项目一致。
611
+
612
+ ---
613
+
614
+ > 本文档为持续演进稿。M0/M1/M2/B 真实联调/M3/M4 已实现并附验证。最近更新:2026-08-10 完成 **M4 企业级**——新增 `src/enterprise/`(tenant 多租户隔离 / policy RBAC+deny 优先 / audit 防篡改哈希链 / quota 日预算熔断 / guard 唯一权威闸门 / index 装配),CLI 加 `whoami`/`policy`/`audit`/`audit verify`/`tenants` 五条企业命令;`scripts/verify-m4.mjs` 提供 41 项全离线断言(7 节),`npm run verify` 串联 typecheck+build+verify:m4,CI 升级为 build/enterprise/security 三流水线(零 Secrets 全离线)。验证结果:typecheck ✅ / build ✅ / verify-m4 **41/41** ✅;CLI 实测 whoami/policy/audit/tenants 正确,viewer 写文件被拒(audit DENY),租户 acme/beta 隔离互不串台,配额超限 `QUOTA_EXCEEDED` 正确触发。文档同步更新 README(§4.8 企业能力)、用户手册(§2.7+安全模型)、配置参考(M4 变量+安全建议)、架构与API(第 8 节企业级架构)、部署指南(§5 三流水线+合规建议)、常见问题(Q13-Q16)、本文件(§9/§10/§11)。M4 里程碑标记 ✅,可进入发布(v0.1.0)与 GitHub 推送准备。