feihong-code 7.6.0 → 8.0.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +36 -22
- package/.github/ISSUE_TEMPLATE/config.yml +10 -13
- package/.github/ISSUE_TEMPLATE/feature_request.md +38 -13
- package/.github/PULL_REQUEST_TEMPLATE.md +65 -30
- package/.github/workflows/ci.yml +2 -2
- package/.github/workflows/release.yml +5 -5
- package/.github/workflows/swebench-real.yml +2 -2
- package/CONTRIBUTING.md +52 -3
- package/dist/cli/version.js +1 -1
- package/dist/memory/honcho-store.js +231 -0
- package/dist/memory/honcho-store.js.map +1 -0
- package/dist/shared/log-rotator.js +238 -0
- package/dist/shared/log-rotator.js.map +1 -0
- package/dist/shared/sqlite-store.js +512 -0
- package/dist/shared/sqlite-store.js.map +1 -0
- package/dist/tools/docker-sandbox.js +212 -0
- package/dist/tools/docker-sandbox.js.map +1 -0
- package/dist/web/public/favicon.svg +11 -0
- package/dist/web/public/index.html +4 -1
- package/dist/web/public/robots.txt +14 -0
- package/dist/web/server.js +70 -0
- package/dist/web/server.js.map +1 -1
- package/docs/API.md +827 -0
- package/docs/PROJECT-ANALYSIS-AND-TEST.md +721 -0
- package/docs/TECHNICAL-SPECIFICATION.md +746 -0
- package/docs/UPGRADE-v7.9.0.md +291 -0
- package/docs/UPGRADE-v8.0.0.md +237 -0
- package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246-v8.0.0.md +922 -0
- package/package.json +6 -6
|
@@ -1,37 +1,51 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Bug 报告
|
|
3
|
-
about:
|
|
4
|
-
title:
|
|
5
|
-
labels:
|
|
3
|
+
about: 报告飞虹 Code 的缺陷或异常行为
|
|
4
|
+
title: "[Bug] "
|
|
5
|
+
labels: bug, needs-triage
|
|
6
6
|
assignees: ''
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 缺陷描述
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- **Node.js 版本**: `node --version`
|
|
13
|
-
- **fhcode 版本**: `fhcode --version`
|
|
14
|
-
- **模型配置**: Ollama / DeepSeek / OpenAI / 其他
|
|
15
|
-
- **CLI 模式**: 单命令 / --parallel / swe
|
|
11
|
+
<!-- 清晰简洁地描述这个 bug 是什么 -->
|
|
16
12
|
|
|
17
13
|
## 复现步骤
|
|
18
14
|
|
|
19
|
-
1.
|
|
20
|
-
2.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
1. 启动方式:<!-- 如 `node dist/cli/index.js serve` / CLI / APP -->
|
|
16
|
+
2. 操作步骤:
|
|
17
|
+
1.
|
|
18
|
+
2.
|
|
19
|
+
3.
|
|
20
|
+
3. 预期行为:<!-- 你期望发生什么 -->
|
|
21
|
+
4. 实际行为:<!-- 实际发生了什么 -->
|
|
22
|
+
|
|
23
|
+
## 环境信息
|
|
24
|
+
|
|
25
|
+
| 项目 | 值 |
|
|
26
|
+
|------|-----|
|
|
27
|
+
| 飞虹 Code 版本 | <!-- 如 v8.0.0,`fhcode --version` 或 /api/health --> |
|
|
28
|
+
| 操作系统 | <!-- 如 Windows 11 / macOS 14 / Ubuntu 22.04 --> |
|
|
29
|
+
| Node.js 版本 | <!-- `node --version` --> |
|
|
30
|
+
| 部署方式 | <!-- 本地 / Docker / 服务器 / 移动端 --> |
|
|
31
|
+
| 模型提供商 | <!-- 如 Agnes / DeepSeek / Ollama / 免密网络层 --> |
|
|
32
|
+
| Docker 版本(如使用沙盒) | <!-- `docker --version` --> |
|
|
33
|
+
|
|
34
|
+
## 错误日志
|
|
24
35
|
|
|
25
|
-
|
|
36
|
+
<!-- 粘贴相关的错误日志、终端输出或截图 -->
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
```
|
|
39
|
+
在此粘贴日志
|
|
40
|
+
```
|
|
28
41
|
|
|
29
|
-
##
|
|
42
|
+
## 附加信息
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
<!-- 任何有助于定位问题的附加信息:配置文件(脱敏后)、复现频率、是否偶现等 -->
|
|
32
45
|
|
|
33
|
-
##
|
|
46
|
+
## 自查清单
|
|
34
47
|
|
|
35
|
-
- [ ]
|
|
36
|
-
- [ ]
|
|
37
|
-
- [ ]
|
|
48
|
+
- [ ] 我已搜索现有 Issues,未发现重复报告
|
|
49
|
+
- [ ] 我已尝试升级到最新版本,问题仍然存在
|
|
50
|
+
- [ ] 我已提供完整的复现步骤和环境信息
|
|
51
|
+
- [ ] 日志中不包含 API Key、Token 等敏感信息(已脱敏)
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
blank_issues_enabled:
|
|
1
|
+
blank_issues_enabled: false
|
|
2
2
|
contact_links:
|
|
3
|
-
- name:
|
|
4
|
-
url: https://github.com/
|
|
5
|
-
about:
|
|
6
|
-
- name:
|
|
7
|
-
url: https://github.com/
|
|
8
|
-
about:
|
|
9
|
-
- name:
|
|
10
|
-
url: https://github.com/
|
|
11
|
-
about:
|
|
12
|
-
- name: 🔐 安全漏洞报告
|
|
13
|
-
url: https://github.com/wch887292/feihong-code/blob/master/.github/SECURITY.md
|
|
14
|
-
about: 发现安全问题,请通过安全渠道报告
|
|
3
|
+
- name: 文档与使用说明
|
|
4
|
+
url: https://github.com/feihong-code/feihong-code/blob/main/docs/使用说明书-v8.0.0.md
|
|
5
|
+
about: 先阅读详细使用说明书,常见问题可在故障排查章节找到答案
|
|
6
|
+
- name: 社区讨论
|
|
7
|
+
url: https://github.com/feihong-code/feihong-code/discussions
|
|
8
|
+
about: 一般性问题、使用交流、想法分享请到 Discussions
|
|
9
|
+
- name: 贡献指南
|
|
10
|
+
url: https://github.com/feihong-code/feihong-code/blob/main/CONTRIBUTING.md
|
|
11
|
+
about: 想贡献代码?先阅读贡献指南
|
|
@@ -1,28 +1,53 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: 功能请求
|
|
3
|
-
about:
|
|
4
|
-
title:
|
|
5
|
-
labels:
|
|
3
|
+
about: 为飞虹 Code 提出新功能或改进建议
|
|
4
|
+
title: "[Feature] "
|
|
5
|
+
labels: enhancement, needs-triage
|
|
6
6
|
assignees: ''
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 功能描述
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<!-- 清晰简洁地描述你希望添加的功能 -->
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 解决的问题
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
<!-- 这个功能解决了什么问题?当前有什么痛点? -->
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 期望的解决方案
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
<!-- 描述你期望的实现方式、交互流程或 API 设计 -->
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
### 建议的 API / 命令 / 界面
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
<!-- 如果有具体的 API、CLI 命令或界面设计建议,请描述 -->
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
```
|
|
26
|
+
示例代码或界面草图
|
|
27
|
+
```
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
## 替代方案
|
|
30
|
+
|
|
31
|
+
<!-- 你考虑过哪些替代方案?为什么选择当前方案? -->
|
|
32
|
+
|
|
33
|
+
## 适用场景
|
|
34
|
+
|
|
35
|
+
<!-- 这个功能在什么场景下最有价值?目标用户是谁? -->
|
|
36
|
+
|
|
37
|
+
## 优先级建议
|
|
38
|
+
|
|
39
|
+
- [ ] P0 - 阻塞性问题,必须尽快实现
|
|
40
|
+
- [ ] P1 - 重要功能,近期规划
|
|
41
|
+
- [ ] P2 - 增强功能,可排期
|
|
42
|
+
- [ ] P3 - 想法/探索,长期考虑
|
|
43
|
+
|
|
44
|
+
## 附加信息
|
|
45
|
+
|
|
46
|
+
<!-- 任何附加信息:参考实现、相关项目、截图、用户调研等 -->
|
|
47
|
+
|
|
48
|
+
## 自查清单
|
|
49
|
+
|
|
50
|
+
- [ ] 我已搜索现有 Issues 和 Discussions,未发现重复请求
|
|
51
|
+
- [ ] 我已描述清楚功能的价值和使用场景
|
|
52
|
+
- [ ] 我已考虑过替代方案
|
|
53
|
+
- [ ] 这个功能不违反安全或合规要求
|
|
@@ -1,46 +1,81 @@
|
|
|
1
|
-
##
|
|
1
|
+
## 变更描述
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- [ ] 新功能
|
|
5
|
-
- [ ] 性能优化
|
|
6
|
-
- [ ] 文档更新
|
|
7
|
-
- [ ] 重构
|
|
8
|
-
- [ ] 测试补充
|
|
3
|
+
<!-- 清晰简洁地描述这个 PR 做了什么变更 -->
|
|
9
4
|
|
|
10
5
|
## 关联 Issue
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
<!-- 关联的 Issue 编号,如 Closes #123 / Fixes #456 -->
|
|
13
8
|
|
|
14
|
-
##
|
|
9
|
+
## 变更类型
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
- [ ] 🐛 Bug 修复(修复缺陷)
|
|
12
|
+
- [ ] ✨ 新功能(新增能力)
|
|
13
|
+
- [ ] 💄 界面/样式优化
|
|
14
|
+
- [ ] ♻️ 代码重构(不改变功能)
|
|
15
|
+
- [ ] 📝 文档更新
|
|
16
|
+
- [ ] ⚡ 性能优化
|
|
17
|
+
- [ ] 🧪 测试补充
|
|
18
|
+
- [ ] 🔧 配置/构建/CI 变更
|
|
19
|
+
- [ ] 📦 依赖升级
|
|
20
|
+
- [ ] 其他(请说明):
|
|
17
21
|
|
|
18
|
-
##
|
|
22
|
+
## 变更范围
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
- [ ] 单元测试通过:`npm test`
|
|
22
|
-
- [ ] M4 企业能力验证:`npm run verify:m4`
|
|
23
|
-
- [ ] 全量验证:`npm run verify`
|
|
24
|
-
- [ ] 手动测试覆盖(如有新功能)
|
|
24
|
+
<!-- 列出主要修改的文件/模块 -->
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
- `src/...`
|
|
27
|
+
- `docs/...`
|
|
28
|
+
- `app-mobile/...`
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
- 向后兼容性:是 / 否(如有破坏性变更请说明)
|
|
30
|
-
- 需要更新文档:是 / 否
|
|
30
|
+
## 验证方式
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
<!-- 描述你如何验证这个变更 -->
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
- [ ] 本地编译通过(`npm run build` / `npx tsc`)
|
|
35
|
+
- [ ] 冒烟测试通过(`node tests/smoke-v8.js`)
|
|
36
|
+
- [ ] 集成测试通过(`node tests/integration/api.test.js`)
|
|
37
|
+
- [ ] 手动验证(描述步骤和结果)
|
|
38
|
+
- [ ] 移动端验证(如涉及 APP)
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
### 验证结果
|
|
41
|
+
|
|
42
|
+
<!-- 粘贴测试输出或截图 -->
|
|
37
43
|
|
|
38
44
|
```
|
|
39
|
-
|
|
40
|
-
fix(scope): 简要描述
|
|
41
|
-
docs(scope): 简要描述
|
|
42
|
-
test(scope): 简要描述
|
|
43
|
-
refactor(scope): 简要描述
|
|
44
|
-
perf(scope): 简要描述
|
|
45
|
-
chore(scope): 简要描述
|
|
45
|
+
在此粘贴测试结果
|
|
46
46
|
```
|
|
47
|
+
|
|
48
|
+
## 版本号
|
|
49
|
+
|
|
50
|
+
<!-- 如涉及版本变更,确认版本号已同步更新 -->
|
|
51
|
+
|
|
52
|
+
- [ ] `package.json` version 已更新
|
|
53
|
+
- [ ] `src/cli/version.ts` VERSION 已同步
|
|
54
|
+
- [ ] `CHANGELOG.md` 已更新
|
|
55
|
+
- [ ] `android/app/build.gradle` versionCode/versionName 已同步(如涉及移动端)
|
|
56
|
+
|
|
57
|
+
## 安全检查
|
|
58
|
+
|
|
59
|
+
- [ ] 代码中不包含硬编码的 API Key、Token、密码等敏感信息
|
|
60
|
+
- [ ] 日志输出中不包含敏感数据(密钥已脱敏)
|
|
61
|
+
- [ ] 新增的外部输入已做校验(zod / 类型检查)
|
|
62
|
+
- [ ] Shell 命令执行已走沙盒/白名单/审批机制
|
|
63
|
+
- [ ] 不引入已知漏洞的依赖
|
|
64
|
+
|
|
65
|
+
## 兼容性
|
|
66
|
+
|
|
67
|
+
- [ ] 向后兼容(旧配置/旧 API 仍可使用)
|
|
68
|
+
- [ ] 包含破坏性变更(已在描述中说明迁移方式)
|
|
69
|
+
- [ ] 不涉及兼容性问题
|
|
70
|
+
|
|
71
|
+
## 附加说明
|
|
72
|
+
|
|
73
|
+
<!-- 任何需要评审者特别注意的事项:设计决策、已知限制、后续 TODO 等 -->
|
|
74
|
+
|
|
75
|
+
## 自查清单
|
|
76
|
+
|
|
77
|
+
- [ ] 代码遵循项目编码规范(TypeScript、架构分层、署名注释)
|
|
78
|
+
- [ ] 已阅读并遵循 `CONTRIBUTING.md`
|
|
79
|
+
- [ ] 变更最小化,不包含无关修改
|
|
80
|
+
- [ ] 注释清晰,复杂逻辑有说明
|
|
81
|
+
- [ ] 已自测,功能符合预期
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -147,7 +147,7 @@ jobs:
|
|
|
147
147
|
--output=osv-scanner.sarif
|
|
148
148
|
.
|
|
149
149
|
- name: 上传 osv-scanner 结果
|
|
150
|
-
uses: actions/upload-artifact@
|
|
150
|
+
uses: actions/upload-artifact@v7
|
|
151
151
|
with:
|
|
152
152
|
name: osv-scanner.sarif
|
|
153
153
|
path: osv-scanner.sarif
|
|
@@ -157,7 +157,7 @@ jobs:
|
|
|
157
157
|
npx --yes @cyclonedx/cyclonedx-npm --output-file sbom.cdx.json --omit dev
|
|
158
158
|
echo "SBOM 已生成"
|
|
159
159
|
- name: 上传 SBOM
|
|
160
|
-
uses: actions/upload-artifact@
|
|
160
|
+
uses: actions/upload-artifact@v7
|
|
161
161
|
with:
|
|
162
162
|
name: sbom.cdx.json
|
|
163
163
|
path: sbom.cdx.json
|
|
@@ -107,7 +107,7 @@ jobs:
|
|
|
107
107
|
- name: P7-1 SWE-bench harness 链路冒烟(mock)
|
|
108
108
|
run: node dist/cli/index.js harness lite --limit 1 --mode mock || echo "⚠️ harness 需网络拉取数据集,失败不阻断(真实跑分见 docs/SWE_BENCH_REPORT.md)"
|
|
109
109
|
- name: 上传构建产物
|
|
110
|
-
uses: actions/upload-artifact@
|
|
110
|
+
uses: actions/upload-artifact@v7
|
|
111
111
|
with:
|
|
112
112
|
name: dist-${{ needs.version.outputs.version }}
|
|
113
113
|
path: dist/
|
|
@@ -126,7 +126,7 @@ jobs:
|
|
|
126
126
|
node-version: ${{ env.NODE_VERSION }}
|
|
127
127
|
registry-url: 'https://registry.npmjs.org'
|
|
128
128
|
- name: 下载构建产物
|
|
129
|
-
uses: actions/download-artifact@
|
|
129
|
+
uses: actions/download-artifact@v7
|
|
130
130
|
with:
|
|
131
131
|
name: dist-${{ needs.version.outputs.version }}
|
|
132
132
|
path: dist/
|
|
@@ -150,12 +150,12 @@ jobs:
|
|
|
150
150
|
- name: 设置 Docker Buildx
|
|
151
151
|
uses: docker/setup-buildx-action@v3
|
|
152
152
|
- name: 登录 Docker Hub
|
|
153
|
-
uses: docker/login-action@
|
|
153
|
+
uses: docker/login-action@v4
|
|
154
154
|
with:
|
|
155
155
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
156
156
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
157
157
|
- name: 构建并推送镜像
|
|
158
|
-
uses: docker/build-push-action@
|
|
158
|
+
uses: docker/build-push-action@v7
|
|
159
159
|
with:
|
|
160
160
|
context: .
|
|
161
161
|
push: true
|
|
@@ -192,7 +192,7 @@ jobs:
|
|
|
192
192
|
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/feihong-code:latest" >> RELEASE_NOTES.md
|
|
193
193
|
echo "\`\`\`" >> RELEASE_NOTES.md
|
|
194
194
|
- name: 创建 Release
|
|
195
|
-
uses: softprops/action-gh-release@
|
|
195
|
+
uses: softprops/action-gh-release@v3
|
|
196
196
|
with:
|
|
197
197
|
tag_name: ${{ needs.version.outputs.tag }}
|
|
198
198
|
name: 飞虹 Code ${{ needs.version.outputs.tag }}
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
with:
|
|
30
30
|
node-version: '22'
|
|
31
31
|
|
|
32
|
-
- uses: actions/setup-python@
|
|
32
|
+
- uses: actions/setup-python@v7
|
|
33
33
|
with:
|
|
34
34
|
python-version: '3.11'
|
|
35
35
|
|
|
@@ -61,7 +61,7 @@ jobs:
|
|
|
61
61
|
|
|
62
62
|
- name: 上传结果
|
|
63
63
|
if: always()
|
|
64
|
-
uses: actions/upload-artifact@
|
|
64
|
+
uses: actions/upload-artifact@v7
|
|
65
65
|
with:
|
|
66
66
|
name: swebench-real-results
|
|
67
67
|
path: |
|
package/CONTRIBUTING.md
CHANGED
|
@@ -24,14 +24,24 @@
|
|
|
24
24
|
```
|
|
25
25
|
src/
|
|
26
26
|
cli/ 入口、参数解析、REPL、运行时装配
|
|
27
|
-
shared/
|
|
27
|
+
shared/ 配置、错误、日志、共享类型、SQLite 统一存储(基础设施)
|
|
28
28
|
agent/ Orchestrator / Planner / Prompts
|
|
29
|
-
tools/ 工具实现(file / shell / search / verify)+ registry
|
|
29
|
+
tools/ 工具实现(file / shell / search / verify / docker-sandbox)+ registry
|
|
30
30
|
models/ 模型路由 + providers(openai-compatible / ollama / mock)
|
|
31
31
|
runtime/ 事件日志、会话状态(单一可信源)
|
|
32
32
|
skills/ 高级技能(/plan /grill /goal)
|
|
33
|
+
memory/ 持久记忆 + Honcho 语义记忆(v8.0)
|
|
34
|
+
web/ Express Web 控制台 + API 路由
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
**v8.0 新增模块**:
|
|
38
|
+
|
|
39
|
+
| 模块 | 路径 | 说明 |
|
|
40
|
+
|------|------|------|
|
|
41
|
+
| SQLite 统一存储 | `src/shared/sqlite-store.ts` | 10 张表,AES-256-GCM 加密,版本化迁移,基于 node:sqlite 零依赖 |
|
|
42
|
+
| Docker 沙盒执行 | `src/tools/docker-sandbox.ts` | 容器隔离、禁网、只读挂载、资源限制、危险命令拦截、超时强杀 |
|
|
43
|
+
| Honcho 语义记忆 | `src/memory/honcho-store.ts` | 用户建模、事实记忆、跨会话检索、记忆注入提示词 |
|
|
44
|
+
|
|
35
45
|
铁律:
|
|
36
46
|
|
|
37
47
|
1. **边界必须校验**:所有外部输入(CLI 参数、模型响应、工具入参)用 zod 校验。
|
|
@@ -60,7 +70,33 @@ src/
|
|
|
60
70
|
- **CI 强制校验**:`npm run check:version` 已接入 `npm run verify` 与 CI build job,任何不一致会阻塞合并。
|
|
61
71
|
- **两套编号解耦**:M0→M9.1 为能力里程碑(已冻结),7.x 为产品化成熟度版本号,说明见 README §十二。
|
|
62
72
|
|
|
63
|
-
##
|
|
73
|
+
## 五、测试规范
|
|
74
|
+
|
|
75
|
+
提交 PR 前必须通过以下测试:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 1. 编译检查
|
|
79
|
+
npm run build # tsc 编译到 dist/,零错误
|
|
80
|
+
|
|
81
|
+
# 2. 冒烟测试(v8.0 三项新功能)
|
|
82
|
+
node tests/smoke-v8.js # 25 项:SQLite 11 + Docker 6 + Honcho 8
|
|
83
|
+
|
|
84
|
+
# 3. 集成测试(API 全量)
|
|
85
|
+
node tests/integration/api.test.js # 34 项 API 用例
|
|
86
|
+
|
|
87
|
+
# 4. 仅运行指定模块(调试用)
|
|
88
|
+
node tests/smoke-v8.js --only=sqlite
|
|
89
|
+
node tests/smoke-v8.js --only=docker
|
|
90
|
+
node tests/smoke-v8.js --only=honcho
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**测试要求**:
|
|
94
|
+
- 新功能必须包含测试用例
|
|
95
|
+
- Bug 修复必须包含回归测试(复现该 Bug 的测试)
|
|
96
|
+
- 测试不依赖外部网络(Docker 沙盒测试除外,需本机 Docker)
|
|
97
|
+
- 测试中不包含真实 API Key,使用 Mock 或环境变量
|
|
98
|
+
|
|
99
|
+
## 六、本地开发
|
|
64
100
|
|
|
65
101
|
```bash
|
|
66
102
|
npm install
|
|
@@ -72,4 +108,17 @@ node dist/cli/index.js "<需求>" # 未配 FH_PROVIDERS 自动离线 Mock 闭
|
|
|
72
108
|
|
|
73
109
|
---
|
|
74
110
|
|
|
111
|
+
## 相关社区文档
|
|
112
|
+
|
|
113
|
+
| 文档 | 说明 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| [`GOVERNANCE.md`](GOVERNANCE.md) | 社区治理结构、角色职责、决策机制、版本发布流程 |
|
|
116
|
+
| [`COMMUNITY.md`](COMMUNITY.md) | 社区参与指南、贡献方式、支持渠道、活动信息 |
|
|
117
|
+
| [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) | 社区行为准则 |
|
|
118
|
+
| [`.github/ISSUE_TEMPLATE/`](.github/ISSUE_TEMPLATE/) | Issue 模板(Bug 报告 / 功能请求) |
|
|
119
|
+
| [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md) | PR 模板 |
|
|
120
|
+
| [`docs/使用说明书-v8.0.0.md`](docs/使用说明书-v8.0.0.md) | 详细使用说明书 |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
75
124
|
© 2026 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
|
package/dist/cli/version.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.SIGNATURE = exports.TAGLINE = exports.PRODUCT = exports.VERSION = void 0
|
|
|
7
7
|
*
|
|
8
8
|
* 版本号集中定义
|
|
9
9
|
*/
|
|
10
|
-
exports.VERSION = '
|
|
10
|
+
exports.VERSION = '8.0.0';
|
|
11
11
|
exports.PRODUCT = '飞虹 Code';
|
|
12
12
|
exports.TAGLINE = '终端 AI 编程智能体(对标 Muse Code / Claude Code / Cursor CLI · 自研内核差异化)';
|
|
13
13
|
exports.SIGNATURE = '晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹';
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 飞虹 Code — Honcho 云端记忆层(v8.0,本地部署)
|
|
4
|
+
* 晋江市飞虹智科技企业管理有限公司 · 飞扬企源研发中心 · 负责人:吴赐虹
|
|
5
|
+
*
|
|
6
|
+
* 对标 Honcho(GetZep 的开源语义记忆服务)能力:
|
|
7
|
+
* - 用户建模:为每个用户维护偏好/特质/画像(users 表)
|
|
8
|
+
* - 事实记忆:用户说过的关键事实,带重要度排序(user_memory 表)
|
|
9
|
+
* - 会话摘要:每轮对话自动摘要,跨会话检索(memory_history 表)
|
|
10
|
+
* - 语义检索:关键词 + 时间衰减加权(本地实现,无需外部服务)
|
|
11
|
+
*
|
|
12
|
+
* 本地部署策略:
|
|
13
|
+
* - 默认用 SQLiteStore 作为持久化后端(零外部依赖)
|
|
14
|
+
* - 可选 FH_HONCHO_URL 指向外部 Honcho 服务(API 兼容预留)
|
|
15
|
+
* - 数据目录 $FH_HOME/honcho/(用户画像 JSON + 记忆索引)
|
|
16
|
+
*
|
|
17
|
+
* 与现有 memory/(文件记忆)和 app-mobile hermes-agent.js(前端记忆)互补:
|
|
18
|
+
* - memory/index.ts:短期工作日志 + 长期 MEMORY.md(文件)
|
|
19
|
+
* - honcho-store.ts:用户级语义记忆 + 跨会话检索(数据库)
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.HonchoStore = void 0;
|
|
23
|
+
exports.getHonchoStore = getHonchoStore;
|
|
24
|
+
exports.resetHonchoStore = resetHonchoStore;
|
|
25
|
+
const path_1 = require("path");
|
|
26
|
+
const fs_1 = require("fs");
|
|
27
|
+
const sqlite_store_1 = require("../shared/sqlite-store");
|
|
28
|
+
class HonchoStore {
|
|
29
|
+
store;
|
|
30
|
+
userId;
|
|
31
|
+
dataDir;
|
|
32
|
+
remoteUrl;
|
|
33
|
+
apiKey;
|
|
34
|
+
constructor(options = {}) {
|
|
35
|
+
const home = process.env.FH_HOME || (0, path_1.join)(process.env.HOME || process.env.USERPROFILE || '.', '.feihong-code');
|
|
36
|
+
this.dataDir = options.dataDir || (0, path_1.join)(home, 'honcho');
|
|
37
|
+
this.userId = options.userId || process.env.FH_HONCHO_USER || 'default';
|
|
38
|
+
this.remoteUrl = options.remoteUrl || process.env.FH_HONCHO_URL || null;
|
|
39
|
+
this.apiKey = options.apiKey || process.env.FH_HONCHO_API_KEY || null;
|
|
40
|
+
// apiKey 供远程 Honcho 模式使用(预留)
|
|
41
|
+
void this.apiKey;
|
|
42
|
+
if (!(0, fs_1.existsSync)(this.dataDir))
|
|
43
|
+
(0, fs_1.mkdirSync)(this.dataDir, { recursive: true });
|
|
44
|
+
// 使用 SQLiteStore 作为本地持久化后端
|
|
45
|
+
this.store = (0, sqlite_store_1.getStore)();
|
|
46
|
+
// 确保用户存在
|
|
47
|
+
this.store.userUpsert({ id: this.userId });
|
|
48
|
+
}
|
|
49
|
+
/* ========== 用户建模 ========== */
|
|
50
|
+
/** 更新用户偏好/画像 */
|
|
51
|
+
setUserProfile(profile) {
|
|
52
|
+
this.store.userUpsert({
|
|
53
|
+
id: this.userId,
|
|
54
|
+
name: profile.name,
|
|
55
|
+
preferences: profile.preferences,
|
|
56
|
+
traits: profile.traits,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
getUserProfile() {
|
|
60
|
+
const user = this.store.userGet(this.userId);
|
|
61
|
+
if (!user)
|
|
62
|
+
return { id: this.userId };
|
|
63
|
+
return {
|
|
64
|
+
id: String(user.id),
|
|
65
|
+
name: user.name ? String(user.name) : undefined,
|
|
66
|
+
preferences: user.preferences,
|
|
67
|
+
traits: user.traits,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/* ========== 事实记忆 ========== */
|
|
71
|
+
/** 记录用户陈述的事实(自动评估重要度) */
|
|
72
|
+
rememberFact(content, importance) {
|
|
73
|
+
const imp = importance ?? this.estimateImportance(content);
|
|
74
|
+
this.store.userAddMemory(this.userId, content, 'fact', imp);
|
|
75
|
+
}
|
|
76
|
+
/** 批量记录事实 */
|
|
77
|
+
rememberFacts(contents) {
|
|
78
|
+
for (const c of contents)
|
|
79
|
+
this.rememberFact(c);
|
|
80
|
+
}
|
|
81
|
+
/** 简单重要度评估:关键词命中加权 */
|
|
82
|
+
estimateImportance(content) {
|
|
83
|
+
let score = 0.5;
|
|
84
|
+
const HIGH = /(我喜欢|我偏好|我习惯|我讨厌|我坚持|公司|项目|客户|订单|利润|重要|必须|每次|总是)/;
|
|
85
|
+
const MEDIUM = /(用|使用|需要|希望|计划|目标|做|开发|编码|编程)/;
|
|
86
|
+
if (HIGH.test(content))
|
|
87
|
+
score += 0.3;
|
|
88
|
+
if (MEDIUM.test(content))
|
|
89
|
+
score += 0.15;
|
|
90
|
+
if (content.length > 40)
|
|
91
|
+
score += 0.05;
|
|
92
|
+
return Math.min(1, score);
|
|
93
|
+
}
|
|
94
|
+
/** 列出用户记忆(按重要度排序) */
|
|
95
|
+
listMemories(limit = 20) {
|
|
96
|
+
const rows = this.store.userListMemory(this.userId, limit);
|
|
97
|
+
return rows.map((r) => ({
|
|
98
|
+
id: Number(r.id),
|
|
99
|
+
content: String(r.content),
|
|
100
|
+
category: r.category ? String(r.category) : 'fact',
|
|
101
|
+
importance: Number(r.importance || 0.5),
|
|
102
|
+
createdAt: Number(r.created_at),
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
/* ========== 会话摘要与跨会话检索 ========== */
|
|
106
|
+
/** 记录会话摘要 */
|
|
107
|
+
addSessionSummary(summary, type) {
|
|
108
|
+
this.store.memoryAddHistory(this.userId, summary, type);
|
|
109
|
+
}
|
|
110
|
+
/** 关键词检索历史记忆(近期加权) */
|
|
111
|
+
recall(query, limit = 5) {
|
|
112
|
+
const memory = this.store.userSearchMemory(this.userId, query, limit).map((r) => ({
|
|
113
|
+
id: Number(r.id),
|
|
114
|
+
content: String(r.content),
|
|
115
|
+
category: r.category ? String(r.category) : 'fact',
|
|
116
|
+
importance: Number(r.importance || 0.5),
|
|
117
|
+
createdAt: Number(r.created_at),
|
|
118
|
+
}));
|
|
119
|
+
const history = this.store.memoryRecall(query, limit).map((r) => ({
|
|
120
|
+
id: Number(r.id),
|
|
121
|
+
summary: String(r.summary),
|
|
122
|
+
type: r.type ? String(r.type) : undefined,
|
|
123
|
+
createdAt: Number(r.created_at),
|
|
124
|
+
}));
|
|
125
|
+
return {
|
|
126
|
+
memory,
|
|
127
|
+
users: [this.getUserProfile()],
|
|
128
|
+
history,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** 生成记忆注入提示词(类似 hermes-agent.js 的 getContextPrompt) */
|
|
132
|
+
buildContextPrompt() {
|
|
133
|
+
const profile = this.getUserProfile();
|
|
134
|
+
const memories = this.listMemories(10);
|
|
135
|
+
const recentHistory = this.store.memoryList().slice(0, 5);
|
|
136
|
+
let prompt = '## Honcho 语义记忆(云端风格,跨会话持久)\n\n';
|
|
137
|
+
prompt += '### 用户画像\n';
|
|
138
|
+
if (profile.name)
|
|
139
|
+
prompt += `- 用户:${profile.name}\n`;
|
|
140
|
+
if (profile.preferences) {
|
|
141
|
+
const prefs = profile.preferences;
|
|
142
|
+
Object.entries(prefs).forEach(([k, v]) => { prompt += `- 偏好·${k}:${String(v)}\n`; });
|
|
143
|
+
}
|
|
144
|
+
if (profile.traits) {
|
|
145
|
+
const traits = profile.traits;
|
|
146
|
+
Object.entries(traits).forEach(([k, v]) => { prompt += `- 特质·${k}:${String(v)}\n`; });
|
|
147
|
+
}
|
|
148
|
+
if (!profile.name && !profile.preferences && !profile.traits) {
|
|
149
|
+
prompt += '(暂无画像,等待积累)\n';
|
|
150
|
+
}
|
|
151
|
+
prompt += '\n### 用户重要记忆(按重要度)\n';
|
|
152
|
+
if (memories.length) {
|
|
153
|
+
memories.slice(0, 5).forEach((m) => {
|
|
154
|
+
const imp = m.importance ?? 0.5;
|
|
155
|
+
prompt += `- [${imp >= 0.7 ? '重要' : '一般'}] ${m.content}\n`;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
prompt += '(暂无记忆)\n';
|
|
160
|
+
}
|
|
161
|
+
if (recentHistory.length) {
|
|
162
|
+
prompt += '\n### 近期会话\n';
|
|
163
|
+
recentHistory.slice(0, 3).forEach((h) => {
|
|
164
|
+
const row = h;
|
|
165
|
+
prompt += `- ${String(row.content || '').slice(0, 80)}\n`;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
prompt += '\n请利用以上记忆提供个性化回答,如果用户提到之前的内容请主动回忆。\n\n';
|
|
169
|
+
return prompt;
|
|
170
|
+
}
|
|
171
|
+
/* ========== 记忆自动沉淀 ========== */
|
|
172
|
+
/** 从对话中自动提取并沉淀事实(简单规则,可与 LLM 结合) */
|
|
173
|
+
digestConversation(messages) {
|
|
174
|
+
if (!messages || !messages.length)
|
|
175
|
+
return;
|
|
176
|
+
const userMsgs = messages.filter((m) => m.role === 'user');
|
|
177
|
+
if (!userMsgs.length)
|
|
178
|
+
return;
|
|
179
|
+
const lastUser = userMsgs[userMsgs.length - 1].content;
|
|
180
|
+
// 提取事实类偏好
|
|
181
|
+
const factPatterns = [
|
|
182
|
+
/(?:我喜欢|我偏好|我习惯|我常用|我用)\s*([^,。!?]{2,40})/g,
|
|
183
|
+
/(?:我叫|我是)\s*([^,。!?]{2,20})/g,
|
|
184
|
+
/(?:我的|我在|我是从事)\s*([^,。!?]{2,40})/g,
|
|
185
|
+
/(?:我讨厌|我不喜欢|不要)\s*([^,。!?]{2,40})/g,
|
|
186
|
+
];
|
|
187
|
+
const facts = [];
|
|
188
|
+
factPatterns.forEach((re) => {
|
|
189
|
+
let m;
|
|
190
|
+
while ((m = re.exec(lastUser)) !== null) {
|
|
191
|
+
if (m[1] && m[1].length > 1)
|
|
192
|
+
facts.push(m[1]);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
if (facts.length)
|
|
196
|
+
this.rememberFacts(facts);
|
|
197
|
+
// 生成会话摘要(用最后一条用户消息 + 消息数)
|
|
198
|
+
const summary = `会话摘要:用户询问「${lastUser.slice(0, 50)}」(共${messages.length}条消息)`;
|
|
199
|
+
this.addSessionSummary(summary, 'chat');
|
|
200
|
+
}
|
|
201
|
+
/* ========== 统计与健康 ========== */
|
|
202
|
+
stats() {
|
|
203
|
+
const s = this.store.stats();
|
|
204
|
+
return {
|
|
205
|
+
users: s.users,
|
|
206
|
+
userMemory: s.userMemory,
|
|
207
|
+
memoryHistory: s.memoryHistory,
|
|
208
|
+
schemaVersion: s.schemaVersion,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
health() {
|
|
212
|
+
const h = this.store.health();
|
|
213
|
+
return {
|
|
214
|
+
ok: h.ok,
|
|
215
|
+
backend: this.remoteUrl ? 'remote:' + this.remoteUrl : 'sqlite-local',
|
|
216
|
+
dbFile: h.dbFile,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
exports.HonchoStore = HonchoStore;
|
|
221
|
+
/** 全局单例 */
|
|
222
|
+
let honchoInstance = null;
|
|
223
|
+
function getHonchoStore(options) {
|
|
224
|
+
if (!honchoInstance)
|
|
225
|
+
honchoInstance = new HonchoStore(options);
|
|
226
|
+
return honchoInstance;
|
|
227
|
+
}
|
|
228
|
+
function resetHonchoStore() {
|
|
229
|
+
honchoInstance = null;
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=honcho-store.js.map
|