auto-snapshot 2026-08-03 03:00:39
This commit is contained in:
parent
7a1910566c
commit
e2a14f871a
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
# tdai-gateway 看门狗:检查 systemd 服务 active + 8420 端口监听
|
||||
# 正常 → 静默(空输出);异常 → 输出报警(no-agent cron 会发送)
|
||||
# 创建:2026-08-02,修复 systemd 崩溃循环 2534 次后补的监控
|
||||
|
||||
ALERT=""
|
||||
|
||||
if ! systemctl --user is-active tdai-gateway >/dev/null 2>&1; then
|
||||
STATE=$(systemctl --user is-active tdai-gateway 2>/dev/null || echo unknown)
|
||||
ALERT="tdai-gateway systemd 服务状态异常: ${STATE}"
|
||||
fi
|
||||
|
||||
if ! ss -tln 2>/dev/null | grep -q ':8420 '; then
|
||||
ALERT="${ALERT}${ALERT:+ | }tdai-gateway 端口 8420 未监听"
|
||||
fi
|
||||
|
||||
if [ -n "$ALERT" ]; then
|
||||
echo "🔴 tdai-gateway 异常 $(date '+%F %T')"
|
||||
echo "$ALERT"
|
||||
systemctl --user status tdai-gateway --no-pager 2>&1 | head -12
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 正常:空输出 = 静默
|
||||
exit 0
|
||||
|
|
@ -315,27 +315,27 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-07-17T03:43:05.089451+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-07-18T12:39:50.390388+00:00",
|
||||
"last_used_at": "2026-07-30T01:50:00.175477+00:00",
|
||||
"last_viewed_at": "2026-07-30T01:50:00.172165+00:00",
|
||||
"patch_count": 22,
|
||||
"last_patched_at": "2026-08-02T13:04:01.231703+00:00",
|
||||
"last_used_at": "2026-08-02T14:39:17.213975+00:00",
|
||||
"last_viewed_at": "2026-08-02T14:39:17.208148+00:00",
|
||||
"patch_count": 26,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 20,
|
||||
"view_count": 20
|
||||
"use_count": 24,
|
||||
"view_count": 24
|
||||
},
|
||||
"cbm-code-analysis": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-07-30T03:28:33.803582+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-07-30T03:30:30.927634+00:00",
|
||||
"last_used_at": "2026-07-30T03:30:47.215892+00:00",
|
||||
"last_viewed_at": "2026-07-30T03:30:47.203869+00:00",
|
||||
"patch_count": 3,
|
||||
"last_patched_at": "2026-08-02T15:20:56.394720+00:00",
|
||||
"last_used_at": "2026-08-02T15:20:48.942850+00:00",
|
||||
"last_viewed_at": "2026-08-02T15:20:48.923159+00:00",
|
||||
"patch_count": 4,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 3,
|
||||
"view_count": 3
|
||||
"use_count": 4,
|
||||
"view_count": 4
|
||||
},
|
||||
"claude-code": {
|
||||
"archived_at": null,
|
||||
|
|
@ -510,14 +510,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-07-28T14:02:19.195060+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-01T16:57:06.438287+00:00",
|
||||
"last_used_at": "2026-08-01T16:56:55.948370+00:00",
|
||||
"last_viewed_at": "2026-08-01T16:56:55.945187+00:00",
|
||||
"patch_count": 2,
|
||||
"last_patched_at": "2026-08-02T14:02:20.150209+00:00",
|
||||
"last_used_at": "2026-08-02T14:02:11.814838+00:00",
|
||||
"last_viewed_at": "2026-08-02T14:02:11.811551+00:00",
|
||||
"patch_count": 3,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 2,
|
||||
"view_count": 2
|
||||
"use_count": 3,
|
||||
"view_count": 3
|
||||
},
|
||||
"design-feasibility-review": {
|
||||
"archived_at": null,
|
||||
|
|
@ -549,14 +549,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-05-05T15:53:48.597780+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-01T12:42:25.333652+00:00",
|
||||
"last_used_at": "2026-08-01T12:41:48.920445+00:00",
|
||||
"last_viewed_at": "2026-08-01T12:41:48.909106+00:00",
|
||||
"patch_count": 94,
|
||||
"last_patched_at": "2026-08-02T17:46:05.621521+00:00",
|
||||
"last_used_at": "2026-08-02T17:45:20.632761+00:00",
|
||||
"last_viewed_at": "2026-08-02T17:45:20.628433+00:00",
|
||||
"patch_count": 96,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 79,
|
||||
"view_count": 79
|
||||
"use_count": 81,
|
||||
"view_count": 81
|
||||
},
|
||||
"devops/devops-umbrella": {
|
||||
"archived_at": null,
|
||||
|
|
@ -779,6 +779,19 @@
|
|||
"use_count": 0,
|
||||
"view_count": 0
|
||||
},
|
||||
"gitea-repo-mirroring": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-08-02T18:24:34.438054+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-02T18:29:21.655125+00:00",
|
||||
"last_used_at": "2026-08-02T18:47:12.319098+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:47:12.312935+00:00",
|
||||
"patch_count": 3,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 4,
|
||||
"view_count": 4
|
||||
},
|
||||
"github-auth": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-06-30T11:24:39.499832+00:00",
|
||||
|
|
@ -835,27 +848,27 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-08-01T11:50:01.274771+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-01T14:21:36.844037+00:00",
|
||||
"last_used_at": "2026-08-01T14:21:17.657665+00:00",
|
||||
"last_viewed_at": "2026-08-01T14:21:17.646368+00:00",
|
||||
"patch_count": 7,
|
||||
"last_patched_at": "2026-08-02T16:21:17.978109+00:00",
|
||||
"last_used_at": "2026-08-02T16:46:57.365738+00:00",
|
||||
"last_viewed_at": "2026-08-02T16:46:57.362260+00:00",
|
||||
"patch_count": 14,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 9,
|
||||
"view_count": 9
|
||||
"use_count": 17,
|
||||
"view_count": 17
|
||||
},
|
||||
"github-repo-management": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-06-30T11:24:39.513614+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": null,
|
||||
"last_used_at": "2026-08-01T11:48:58.058238+00:00",
|
||||
"last_viewed_at": "2026-08-01T11:48:58.054196+00:00",
|
||||
"last_used_at": "2026-08-02T18:23:21.668886+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:23:21.655030+00:00",
|
||||
"patch_count": 0,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 2,
|
||||
"view_count": 2
|
||||
"use_count": 5,
|
||||
"view_count": 5
|
||||
},
|
||||
"go-learning": {
|
||||
"archived_at": null,
|
||||
|
|
@ -1017,14 +1030,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-05-13T12:27:05.593125+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-07-19T14:06:42.150955+00:00",
|
||||
"last_used_at": "2026-07-26T01:00:46.496121+00:00",
|
||||
"last_viewed_at": "2026-07-25T12:41:04.295275+00:00",
|
||||
"patch_count": 78,
|
||||
"last_patched_at": "2026-08-02T11:39:48.113545+00:00",
|
||||
"last_used_at": "2026-08-02T17:46:14.064253+00:00",
|
||||
"last_viewed_at": "2026-08-02T17:46:14.053177+00:00",
|
||||
"patch_count": 80,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 112,
|
||||
"view_count": 107
|
||||
"use_count": 118,
|
||||
"view_count": 112
|
||||
},
|
||||
"hermes-venv-dependency-safety": {
|
||||
"archived_at": null,
|
||||
|
|
@ -1186,14 +1199,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-08-01T13:47:26.532313+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-01T16:50:25.167129+00:00",
|
||||
"last_used_at": "2026-08-01T17:12:32.828348+00:00",
|
||||
"last_viewed_at": "2026-08-01T17:12:32.817004+00:00",
|
||||
"patch_count": 3,
|
||||
"last_patched_at": "2026-08-02T16:46:52.295411+00:00",
|
||||
"last_used_at": "2026-08-02T16:46:44.045093+00:00",
|
||||
"last_viewed_at": "2026-08-02T16:46:44.039236+00:00",
|
||||
"patch_count": 4,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 3,
|
||||
"view_count": 3
|
||||
"use_count": 5,
|
||||
"view_count": 5
|
||||
},
|
||||
"llm-wiki": {
|
||||
"archived_at": null,
|
||||
|
|
@ -1706,27 +1719,27 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-07-08T18:13:02.034240+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-01T12:52:39.447526+00:00",
|
||||
"last_used_at": "2026-08-01T12:52:32.714172+00:00",
|
||||
"last_viewed_at": "2026-08-01T12:52:32.703253+00:00",
|
||||
"patch_count": 200,
|
||||
"last_patched_at": "2026-08-02T15:20:41.501595+00:00",
|
||||
"last_used_at": "2026-08-02T15:20:25.042403+00:00",
|
||||
"last_viewed_at": "2026-08-02T15:20:25.024619+00:00",
|
||||
"patch_count": 203,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 152,
|
||||
"view_count": 152
|
||||
"use_count": 155,
|
||||
"view_count": 155
|
||||
},
|
||||
"self-hosted-tunneling": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-06-19T19:06:08.909729+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-07-08T13:51:56.997028+00:00",
|
||||
"last_used_at": "2026-07-08T13:51:29.387565+00:00",
|
||||
"last_viewed_at": "2026-07-08T13:51:29.376414+00:00",
|
||||
"last_used_at": "2026-08-02T18:23:21.672286+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:23:21.665575+00:00",
|
||||
"patch_count": 10,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 12,
|
||||
"view_count": 12
|
||||
"use_count": 13,
|
||||
"view_count": 13
|
||||
},
|
||||
"serving-llms-vllm": {
|
||||
"archived_at": null,
|
||||
|
|
@ -1836,14 +1849,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-07-09T17:36:29.269531+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-07-20T07:53:21.901753+00:00",
|
||||
"last_used_at": "2026-07-20T07:52:12.152761+00:00",
|
||||
"last_viewed_at": "2026-07-20T07:52:12.149565+00:00",
|
||||
"patch_count": 21,
|
||||
"last_patched_at": "2026-08-02T14:40:09.615607+00:00",
|
||||
"last_used_at": "2026-08-02T15:20:08.440434+00:00",
|
||||
"last_viewed_at": "2026-08-02T15:20:08.433000+00:00",
|
||||
"patch_count": 22,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 21,
|
||||
"view_count": 21
|
||||
"use_count": 23,
|
||||
"view_count": 23
|
||||
},
|
||||
"spike": {
|
||||
"archived_at": null,
|
||||
|
|
@ -1953,14 +1966,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-05-13T16:02:06.347617+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-05-23T07:36:35.113619+00:00",
|
||||
"last_used_at": "2026-06-21T16:06:40.921285+00:00",
|
||||
"last_viewed_at": "2026-06-21T16:06:40.918968+00:00",
|
||||
"patch_count": 9,
|
||||
"last_patched_at": "2026-08-02T18:47:10.025724+00:00",
|
||||
"last_used_at": "2026-08-02T18:46:58.987740+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:46:58.975389+00:00",
|
||||
"patch_count": 13,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 15,
|
||||
"view_count": 15
|
||||
"use_count": 17,
|
||||
"view_count": 17
|
||||
},
|
||||
"web-content-capture": {
|
||||
"archived_at": null,
|
||||
|
|
@ -2027,6 +2040,32 @@
|
|||
"use_count": 0,
|
||||
"view_count": 0
|
||||
},
|
||||
"whisper-stt": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-08-02T18:46:00.920538+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-08-02T18:46:53.592908+00:00",
|
||||
"last_used_at": "2026-08-02T18:46:46.154338+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:46:46.143430+00:00",
|
||||
"patch_count": 1,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 2,
|
||||
"view_count": 2
|
||||
},
|
||||
"windows-home-server-ops": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-08-02T18:24:48.270464+00:00",
|
||||
"created_by": "agent",
|
||||
"last_patched_at": "2026-08-02T18:29:05.298341+00:00",
|
||||
"last_used_at": "2026-08-02T18:46:00.923689+00:00",
|
||||
"last_viewed_at": "2026-08-02T18:46:00.913991+00:00",
|
||||
"patch_count": 2,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 3,
|
||||
"view_count": 3
|
||||
},
|
||||
"windows-python-pip": {
|
||||
"archived_at": null,
|
||||
"created_at": "2026-05-22T18:46:06.408227+00:00",
|
||||
|
|
@ -2109,14 +2148,14 @@
|
|||
"archived_at": null,
|
||||
"created_at": "2026-05-29T19:39:03.373231+00:00",
|
||||
"created_by": null,
|
||||
"last_patched_at": "2026-07-20T07:45:33.845863+00:00",
|
||||
"last_used_at": "2026-07-30T01:24:05.576220+00:00",
|
||||
"last_viewed_at": "2026-07-30T01:24:05.569692+00:00",
|
||||
"patch_count": 711,
|
||||
"last_patched_at": "2026-08-02T16:46:29.637110+00:00",
|
||||
"last_used_at": "2026-08-02T16:46:23.029923+00:00",
|
||||
"last_viewed_at": "2026-08-02T16:46:23.016679+00:00",
|
||||
"patch_count": 729,
|
||||
"pinned": false,
|
||||
"state": "active",
|
||||
"use_count": 376,
|
||||
"view_count": 350
|
||||
"use_count": 385,
|
||||
"view_count": 359
|
||||
},
|
||||
"zhiyi-dev": {
|
||||
"archived_at": null,
|
||||
|
|
|
|||
|
|
@ -412,5 +412,19 @@ python3 ~/.hermes/scripts/cangjie_distill.py distill <text_file> <title>
|
|||
## 与 curator 的配合
|
||||
|
||||
- `--clean` 模式会查找 `absorbed_into` 标记并自动处理
|
||||
- 也会将无版本号 + 低分 + 小体积的技能移动到 `_archive/`
|
||||
- 被吸收的 skill 移动到 `_quarantine/`(回收期 30 天)
|
||||
- 也会将无版本号 + 低分 + 小体积的技能移动到 `.archive/`(注意是点开头,不是下划线)
|
||||
- 被吸收的 skill 移动到 `.quarantine/`(回收期 30 天)
|
||||
- **保护名单**:被 cron / SOUL.md / 系统组件引用的技能在 `skill-curator.py` 的 `PROTECTED_SKILLS` 中声明,任何情况不进入归档/删除建议。新增核心/应急技能后如被 curator 误判,把它加入保护名单。
|
||||
|
||||
### curator 报告不可盲信 — 删除前必须验证(2026-08-02 教训)
|
||||
|
||||
curator 周报(skill-curator-weekly cron)**可能产生严重误判**,绝不能直接执行删除/归档建议。2026-08-02 实例:报告建议删除 8 个技能,其中 4 个是核心技能(`hermes-venv-dependency-safety` / `cbm-code-analysis` / `bge-embed-crash-loop-fix` / `daily-recap`),实际全部被 cron/SOUL 引用;himalaya 被报"与 20+ 技能 100% 重叠",实际是通用词(available/readiness/status)没被 stopwords 过滤的幻觉。
|
||||
|
||||
**执行任何 curator 清理前,按序验证**:
|
||||
1. **拉真实文件状态**:`find ~/.hermes/skills -type d -name "<技能名>"` — 确认技能是否真的存在、是否已在 `.archive/`(在 archive 里 = 早已归档,报告重复计数,忽略)
|
||||
2. **查引用**:`grep -rln "<技能名>" ~/.hermes/SOUL.md ~/.hermes/AGENTS.md ~/.hermes/cron/` — 被 cron/系统文件引用 = 核心,绝不删
|
||||
3. **低频 ≠ 可删**:运维/应急技能(崩溃修复、铁律、复盘)低频使用是正常属性,不是删除理由
|
||||
4. **重叠报告看 common_terms**:Jaccard 打满但 common_terms 是通用词 = 幻觉,不是真重叠
|
||||
5. **只读优先**:默认 `--report`(dry run),确认无损后再谈 `--clean`
|
||||
|
||||
**已修的 curator bug**(2026-08-02):① 加 `PROTECTED_SKILLS` 保护名单 ② stopwords 扩充(available/readiness/status 等)③ 修复 `.archive`(点)vs `_archive`(下划线)扫描 bug——已归档技能被重复扫描 ④ himalaya 补 version。修复后归档候选 8→0。
|
||||
|
|
@ -680,7 +680,7 @@ journalctl --user -u xiaowei-startup.service
|
|||
| `references/gaokao-site/` | 116 个 session 参考文件(按主题分类的 bug 修复记录) |
|
||||
| `references/gaokao-site.md` | 旧版精简参考(保留向后兼容) |
|
||||
| `references/tencent-cloud-ssl-cert-20260618.md` | 腾讯云 DNSPod 免费 SSL 证书申请、HTTPS nginx 配置、外部 443 被封限制 |
|
||||
| `references/gitea-operations.md` | Gitea 上传项目、Token 认证、shallow clone 陷阱 |
|
||||
| `references/gitea-operations.md` | Gitea 操作全流程 — 认证(.netrc/API)、全量历史镜像(GitHub→Gitea)、shallow/deepen 陷阱、镜像代理、--all/--tags 拆分、RSSHub 本地验收(2026-08-03 15项目实战) |
|
||||
| `references/infra-state.md` | Current system infrastructure state (ports, services) |
|
||||
| `references/tailscale-install.md` | Tailscale 安装:正确 GPG 密钥 URL、静态二进制订用方案、Deepin 25 坑点 |
|
||||
| `references/sudo-password-pattern.md` | sudo 密码传递模式:heredoc 中 pipe 失效的原因和三种替代写法 |
|
||||
|
|
|
|||
|
|
@ -1,56 +1,160 @@
|
|||
# Gitea Operations Reference
|
||||
|
||||
> 本地 Gitea 实例操作注意事项。
|
||||
> 本地 Gitea 实例操作注意事项。2026-08-03 更新:批量镜像 15 个 GitHub 项目实战(RSSHub/Folo/xLog/DPlayer/APlayer 等),补全全量历史镜像流程。
|
||||
|
||||
## 本地 Gitea 信息
|
||||
|
||||
- **地址**:http://192.168.123.11:3000
|
||||
- **Token**:见 `~/mc/小唯/记忆/MemoryFabric/技术细节.md`(Token: 9380e8e6...)
|
||||
- **Token**:见 `~/mc/小唯/记忆/MemoryFabric/技术细节.md`(Token: 9380e8e6...)或 `~/.netrc`(`machine 192.168.123.11 login xiaoxue_admin password <token>`)
|
||||
- **用户**:xiaoxue_admin(非 muchen)
|
||||
|
||||
## 上传已有 Git 项目到 Gitea
|
||||
## 认证(两种等价方式)
|
||||
|
||||
### 常见陷阱:Shallow Clone 问题
|
||||
```bash
|
||||
# 从 ~/.netrc 提取 token(单行格式!不要用 getline 分行读)
|
||||
TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc)
|
||||
|
||||
从 GitHub clone 的项目可能是 shallow clone(有 `--depth` 参数),导致:
|
||||
# API Basic auth(token 当密码,验证连通):
|
||||
curl -u "xiaoxue_admin:$TOKEN" "http://192.168.123.11:3000/api/v1/user" # 200 = OK
|
||||
|
||||
# git push URL 嵌入:
|
||||
git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all
|
||||
```
|
||||
|
||||
## 上传已有 Git 项目到 Gitea(保留完整历史 ✅)
|
||||
|
||||
> 镜像场景(把 GitHub 项目归档到 Gitea)**必须保留完整 git 历史**。Gitea 拒绝浅克隆推送,但**不要用 `rm -rf .git` 重来**(那会丢掉历史!)。正确做法:
|
||||
|
||||
### 1. 全量 clone(或把浅克隆补成全量)
|
||||
|
||||
**浅克隆推送会报错:**
|
||||
```
|
||||
remote: shallow update not allowed
|
||||
```
|
||||
或 force push 时失败。
|
||||
|
||||
**解决步骤**:
|
||||
**方案 A:全量 clone(直接)**
|
||||
```bash
|
||||
git clone https://github.com/OWNER/REPO.git # 不带 --depth!
|
||||
```
|
||||
|
||||
**方案 B:浅克隆已存在 → 补成全量**
|
||||
```bash
|
||||
# 一次拉全(网络好时):
|
||||
git fetch --unshallow origin
|
||||
|
||||
# 网络不稳时:分段 deepen(每轮独立可续传,shallow 文件消失 = 完成)
|
||||
for i in 1 2 3 4 5 6 7 8; do
|
||||
timeout 240 git fetch --deepen=2000 origin 2>&1 | tail -2
|
||||
[ ! -f .git/shallow ] && break
|
||||
done
|
||||
[ -f .git/shallow ] && echo "STILL SHALLOW" || echo "FULL OK: $(git rev-list --count HEAD) commits"
|
||||
# 实测:Folo (7011 commits) 第 8 轮才成功 —— 多轮重试是预期,不是 bug
|
||||
```
|
||||
|
||||
### 2. GitHub 直连不稳 → 用镜像代理
|
||||
|
||||
本机实测(2026-08-03):github.com git 协议反复 `curl 28 Failed to connect ... port 443 after 133xxx ms`,但镜像代理可用:
|
||||
|
||||
```bash
|
||||
# ✅ 实测可用:
|
||||
git clone https://gh-proxy.com/https://github.com/OWNER/REPO.git
|
||||
git clone https://ghproxy.net/https://github.com/OWNER/REPO.git
|
||||
# ❌ 当时超时:ghfast.top / mirror.ghproxy.com
|
||||
|
||||
# 先探测哪个通(info/refs 返回 200 = 可用):
|
||||
curl -s -o /dev/null -w "%{http_code}" "https://gh-proxy.com/https://github.com/OWNER/REPO.git/info/refs?service=git-upload-pack"
|
||||
```
|
||||
|
||||
大仓库全量 clone 失败重试模式:
|
||||
```bash
|
||||
for i in 1 2 3 4 5; do
|
||||
rm -rf REPO
|
||||
timeout 500 git clone <url> 2>&1 | tail -2
|
||||
[ -d REPO/.git ] && break
|
||||
sleep 20
|
||||
done
|
||||
```
|
||||
|
||||
### 3. 创建远端仓库(Gitea API)
|
||||
|
||||
```bash
|
||||
curl -s -u "xiaoxue_admin:$TOKEN" -X POST \
|
||||
"http://192.168.123.11:3000/api/v1/user/repos" \
|
||||
-d "{\"name\":\"$name\",\"private\":true,\"auto_init\":false}"
|
||||
# ⚠️ JSON 转义坑:description 带引号/emoji 会破坏 -d 参数 → 用固定值
|
||||
```
|
||||
|
||||
### 4. 推送(⚠️ --all 和 --tags 不能同时用)
|
||||
|
||||
```bash
|
||||
# ❌ fatal: options '--all' and '--tags' cannot be used together
|
||||
git push URL --all --tags
|
||||
|
||||
# ✅ 分两次:
|
||||
git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all
|
||||
git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --tags
|
||||
```
|
||||
|
||||
批量脚本骨架:
|
||||
```bash
|
||||
for d in BASE/*/; do
|
||||
name=$(basename "$d")
|
||||
[ -f "$d/.git/shallow" ] && { echo "SKIP $name (STILL SHALLOW)"; continue; } # 必须全量才能推
|
||||
(cd "$d" && git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all \
|
||||
&& git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --tags) \
|
||||
&& echo "OK $name" || echo "FAIL $name"
|
||||
done
|
||||
```
|
||||
|
||||
### 5. 验证(推完必须查)
|
||||
|
||||
```bash
|
||||
curl -s -u "xiaoxue_admin:$TOKEN" "http://192.168.123.11:3000/api/v1/repos/$OWNER/$name" \
|
||||
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('size'), d.get('default_branch'))"
|
||||
# 对比本地 git rev-list --count HEAD 确认提交数一致
|
||||
```
|
||||
|
||||
## 性能参考(2026-08-03 实测)
|
||||
|
||||
| 项目 | Commits | 备注 |
|
||||
|------|---------|------|
|
||||
| RSSHub | 17,321 | 镜像代理 clone 成功(直连 5 次全挂) |
|
||||
| Folo | 7,011 | deepen 8 轮 |
|
||||
| xLog | 2,731 | 直连成功 |
|
||||
| DPlayer / APlayer | ~1,300 / 916 | 直连 unshallow 成功 |
|
||||
|
||||
## RSSHub 本地安装测试(镜像后验收)
|
||||
|
||||
```bash
|
||||
npm install -g pnpm@9 # RSSHub 需要 pnpm(本机原本没有)
|
||||
cd RSSHub && pnpm install # ~4min,peer 警告可忽略
|
||||
npm run build # 生成 dist/index.mjs(5s;eval 警告是项目自身代码)
|
||||
PORT=1200 npm run start # 服务起来
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:1200/ # 200
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:1200/healthz # 200
|
||||
# ⚠️ 新版本路由已变:/github/release、/github/trending 已移除(404 是正常的)
|
||||
# 用现存路由验证:/github/issue/:owner/:repo → 200
|
||||
```
|
||||
纯前端项目(DPlayer/APlayer)验收:`python3 -m http.server <port>` 起静态服务,curl 检查 demo 页 + dist 产物 200。
|
||||
|
||||
## 快速路径(历史无所谓时)
|
||||
|
||||
如果确实不需要历史(普通上传小项目),旧方法仍可用:
|
||||
```bash
|
||||
cd /path/to/repo
|
||||
rm -rf .git # 删除原 Git 历史
|
||||
git init -b main # 重新初始化
|
||||
git add -A
|
||||
git commit -m "Initial commit"
|
||||
rm -rf .git && git init -b main
|
||||
git add -A && git commit -m "Initial commit"
|
||||
git remote add origin http://TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### Token 认证
|
||||
|
||||
URL 中嵌入 Token 避免交互式输入:
|
||||
```
|
||||
http://TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git
|
||||
```
|
||||
|
||||
### 创建仓库
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://192.168.123.11:3000/api/v1/user/repos" \
|
||||
-H "Authorization: token TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"REPO_NAME","description":"描述","private":false}'
|
||||
```
|
||||
|
||||
返回 JSON 中 `clone_url` 字段含完整 URL(注意用户名前缀)。
|
||||
|
||||
## 关键教训
|
||||
|
||||
| 问题 | 教训 |
|
||||
|------|------|
|
||||
| shallow clone 无法 push | 从 GitHub 克隆后必须 `rm -rf .git` 重新初始化 |
|
||||
| 交互式输入失败 | URL 中嵌入 Token |
|
||||
| 仓库用户不对 | API 创建时用 `xiaoxue_admin`,不是 muchen |
|
||||
| shallow clone 无法 push | **保留历史**:`git fetch --unshallow` 或 `--deepen=2000` 循环;**不要** `rm -rf .git`(丢历史) |
|
||||
| GitHub 直连反复超时 | 用镜像代理 `gh-proxy.com` / `ghproxy.net`(URL 前加前缀) |
|
||||
| `--all --tags` 同时用报错 | 分两次 push |
|
||||
| 大仓库 clone 中断 | 重试循环 + 多轮 deepen(可续传) |
|
||||
| 交互式输入失败 | URL 中嵌入 Token / `.netrc` Basic auth |
|
||||
| 仓库用户不对 | API 创建时用 `xiaoxue_admin`,不是 muchen |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
name: gitea-repo-mirroring
|
||||
description: "把 GitHub/上游开源项目镜像到自建 Gitea(完整 git 历史)— clone→全量历史→建仓库→push 全流程,含浅克隆推送被拒、镜像加速、push 拆分等坑。"
|
||||
version: 1.0.0
|
||||
author: 小唯 A06
|
||||
tags: [gitea, mirror, git, github, 镜像, 存档]
|
||||
trigger: "推到gitea / 镜像到gitea / 把GitHub项目搬到gitea / 存档到gitea / mirror repo"
|
||||
created: 2026-08-03
|
||||
updated: 2026-08-03
|
||||
---
|
||||
|
||||
# Gitea 仓库镜像(GitHub → 自建 Gitea,完整历史)
|
||||
|
||||
把上游开源项目(GitHub 等)镜像到自建 Gitea(本环境:`192.168.123.11:3000`,用户 `xiaoxue_admin`),保留完整 git 历史。
|
||||
|
||||
## 核心铁律
|
||||
|
||||
1. **浅克隆不能推 Gitea**:`git clone --depth 1` 后 push 报 `shallow update not allowed`。Gitea 默认拒绝浅推送,必须完整历史。
|
||||
2. **`git push --all` 和 `--tags` 不能合并**:`fatal: options '--all' and '--tags' cannot be used together`。必须拆两次 push。
|
||||
3. **Gitea API 用 Basic auth**:`-u 用户名:token`,不是 `Authorization: token` 头(Gitea 返回 401)。
|
||||
|
||||
## 标准流程
|
||||
|
||||
### 1. 全量 clone(不要 --depth)
|
||||
|
||||
```bash
|
||||
mkdir -p ~/projects/diygod && cd ~/projects/diygod
|
||||
git clone https://github.com/OWNER/REPO.git # 不加深度的完整克隆
|
||||
```
|
||||
|
||||
### 2. 已是浅克隆 → 转全量
|
||||
|
||||
```bash
|
||||
cd REPO
|
||||
git fetch --unshallow origin # 一次拉全
|
||||
# 网络不稳时用增量 deepen 循环(每次加深 2000 commit,断了续传)
|
||||
for i in 1 2 3 4 5 6 7 8; do
|
||||
timeout 240 git fetch --deepen=2000 origin 2>&1 | tail -2
|
||||
[ ! -f .git/shallow ] && break
|
||||
done
|
||||
# 验证
|
||||
git rev-list --count HEAD # 完整 commit 数
|
||||
[ -f .git/shallow ] && echo "STILL SHALLOW" || echo "FULL HISTORY OK"
|
||||
```
|
||||
|
||||
### 3. 创建 Gitea 仓库 + push
|
||||
|
||||
```bash
|
||||
# token 从 ~/.netrc 提取(注意 awk 遍历字段,不是 getline)
|
||||
TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc)
|
||||
|
||||
# 创建仓库(API Basic auth)
|
||||
curl -s -u "xiaoxue_admin:$TOKEN" -X POST \
|
||||
"http://192.168.123.11:3000/api/v1/user/repos" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"REPO","description":"mirror of OWNER/REPO","private":false}'
|
||||
|
||||
# push(--all 和 --tags 分开!)
|
||||
git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --all
|
||||
git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --tags
|
||||
```
|
||||
|
||||
### 4. 验证
|
||||
|
||||
```bash
|
||||
curl -s -u "xiaoxue_admin:$TOKEN" \
|
||||
"http://192.168.123.11:3000/api/v1/repos/xiaoxue_admin/REPO" | python3 -c \
|
||||
"import sys,json; d=json.load(sys.stdin); print(d.get('size'), d.get('default_branch'), d.get('created_at','')[:10])"
|
||||
```
|
||||
|
||||
## 批量镜像模式
|
||||
|
||||
循环处理 N 个项目:写 `unshallow_all.sh`(逐个 unshallow)+ `push_all.sh`(逐个 push,`--all` 与 `--tags` 分两次),日志写 `push.log`,用 `grep -E "^(OK|FAIL)"` 汇总。后台跑(`background=true` + `notify_on_complete=true`)。
|
||||
|
||||
## Pitfalls
|
||||
|
||||
1. **`shallow update not allowed`** — 浅克隆推送被拒。解法:`git fetch --unshallow origin`,确认 `.git/shallow` 消失再推。
|
||||
2. **GitHub 直连不稳定** — 表现为 `Failed to connect to github.com port 443 after 133xxx ms`。对策:
|
||||
- 先 `git ls-remote https://github.com/... HEAD` 测连通
|
||||
- 直连不行换镜像:`git clone https://gh-proxy.com/https://github.com/OWNER/REPO.git`(实测可用)或 `https://ghproxy.net/...`
|
||||
- `codeload.github.com`(HTTP 下载)常比 git 协议通,但下载的是无历史的 tar.gz
|
||||
3. **`--all --tags` 合并报错** — 必须拆成两次 push。
|
||||
4. **Gitea API 401** — 用了 `Authorization: token` 头。改 `-u 用户名:token` Basic auth。
|
||||
5. **Gitea 仓库列表分页 50/页** — 仓库多时第 2 页起才有目标,`?limit=100&page=2` 翻页,别误判"仓库没建成功"。
|
||||
6. **README 含引号/emoji 导致创建 JSON 转义坏** — 创建仓库时 description 用固定值,不塞 README 内容。
|
||||
7. **Windows 上 git 命令管道** — 目标机是 Windows 时 `tail`/`findstr` 管道会吞输出,先不加过滤器看原始输出。
|
||||
|
||||
## 参考
|
||||
|
||||
- `references/gitea-api-notes.md` — Gitea API 细节、.netrc token 提取、验证命令
|
||||
- `references/diygod-batch-mirror-2026-08.md` — 15 项目批量镜像实录(镜像站实测对比、批量脚本模式、安装测试分层)
|
||||
- 家庭服务器 Windows 部署流程见 `windows-home-server-ops` skill
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# DIYgod 15 项目批量镜像实录(2026-08-03)
|
||||
|
||||
批量把 DIYgod 的 15 个开源项目镜像到家庭服务器 Gitea 的完整实战记录。作为 gitea-repo-mirroring 的批量案例参考。
|
||||
|
||||
## 项目清单与规模
|
||||
|
||||
| 项目 | Commits | 备注 |
|
||||
|------|---------|------|
|
||||
| RSSHub | 17,321 | 最大,45.5K★,历史超长需镜像站 |
|
||||
| Folo | 7,011 | RSSNext 组织项目(38.7K★) |
|
||||
| xLog | 2,731 | Crossbell-Box 组织项目 |
|
||||
| RSSHub-Radar | 1,331 | 浏览器扩展 |
|
||||
| DPlayer | 1,302 | 弹幕播放器 |
|
||||
| APlayer | 916 | 音乐播放器 |
|
||||
| cloudflare-rsshub-deploy | 388 | |
|
||||
| download-webhook | 39 | |
|
||||
| edge-image-transformer | 23 | |
|
||||
| cloudflare-edge-tts | 18 | |
|
||||
| OwO / ttrss-theme-rsshub | 14 / 14 | |
|
||||
| GoodNight / DIYgod-Obsidian-Starter | 6 / 5 | |
|
||||
| ttrss-plugin-remove-iframe-sandbox | 3 | |
|
||||
|
||||
## 关键经验
|
||||
|
||||
### 1. 网络策略:GitHub 直连 vs 镜像
|
||||
- GitHub 直连**时好时坏**:有时 `git ls-remote` 通、大仓库 clone 却挂(133s 超时)
|
||||
- **镜像加速站实测**(2026-08-03):
|
||||
- `https://gh-proxy.com/https://github.com/...` ✅ 通(clone RSSHub 17K commits 成功)
|
||||
- `https://ghproxy.net/https://github.com/...` ✅ 通(refs 探测 200)
|
||||
- `https://ghfast.top/...` ❌ 超时、`https://mirror.ghproxy.com/...` ❌ 超时
|
||||
- **决策规则**:小仓库直连优先;大仓库(历史 >2000 commits)或直连连续失败 → 直接换 gh-proxy.com
|
||||
|
||||
### 2. 批量脚本模式
|
||||
- `unshallow_all.sh`:循环 `git fetch --unshallow`,Folo 网络不稳用 `--deepen=2000` 增量重试 8 轮成功
|
||||
- `push_all.sh`:循环 `git push --all` + `git push --tags` 分开推,日志写 push.log
|
||||
- 后台跑 + notify_on_complete;用 `grep -E "^(OK|FAIL)"` 汇总
|
||||
|
||||
### 3. Gitea 仓库创建 JSON 陷阱
|
||||
- README 含引号/emoji 会破坏 `-d '{"description":"..."}'` 转义 → description 用固定值
|
||||
- 15 个仓库全部 `HTTP 200` 创建成功,但**第 1 页只显示 50 个**旧仓库,DIYgod 的 15 个在第 2 页(`?limit=100&page=2`)→ 验证时别误判"没建成功"
|
||||
|
||||
### 4. 安装测试分层
|
||||
- **轻量项目**(纯前端 DPlayer/APlayer):直接 `python3 -m http.server` 起静态服务 + curl 验证 200
|
||||
- **有测试套件**(cloudflare-edge-tts):`npm install` + `npm run test` → 22/22 通过
|
||||
- **重量级**(RSSHub):`pnpm install`(3m55s)→ `npm run build`(5.4s)→ `npm start` → 路由实测
|
||||
- **RSSHub v1.0 路由变化**:`/github/release`、`/zhihu/hotlist`、`/github/trending` 已删(404 预期);现存 `/github/issue/DIYgod/RSSHub`、`/github/repos/DIYgod` 返回 200 + 真实 RSS 2.0
|
||||
|
||||
## 部署去向
|
||||
- RSSHub → 家庭服务器 Node 部署(见 windows-home-server-ops skill)
|
||||
- cloudflare-edge-tts → 本地 wrangler dev --local 常驻(TTS API)
|
||||
- 小唯语音 → Hermes 内置 edge TTS(zh-CN-XiaoxiaoNeural)
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# Gitea API 笔记(2026-08-03 实测)
|
||||
|
||||
## Token 提取(~/.netrc 单行格式)
|
||||
|
||||
```bash
|
||||
# ✅ awk 遍历字段提取(不要用 getline —— .netrc 是单行)
|
||||
TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc)
|
||||
```
|
||||
|
||||
## 认证方式
|
||||
|
||||
- ✅ **Basic auth**:`curl -u "xiaoxue_admin:$TOKEN"` → 200
|
||||
- ❌ `Authorization: token $TOKEN` 头 → **401**(Gitea 不认这种写法)
|
||||
|
||||
## 常用 API
|
||||
|
||||
```bash
|
||||
# 创建仓库
|
||||
curl -s -u "user:$TOKEN" -X POST http://HOST:3000/api/v1/user/repos \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"REPO","description":"固定值(避免转义)","private":false}'
|
||||
|
||||
# 查仓库(含 size/默认分支/创建时间)
|
||||
curl -s -u "user:$TOKEN" http://HOST:3000/api/v1/repos/xiaoxue_admin/REPO
|
||||
|
||||
# 列用户仓库 —— ⚠️ 分页 50/页!仓库多时目标在 page 2+
|
||||
curl -s -u "user:$TOKEN" "http://HOST:3000/api/v1/users/xiaoxue_admin/repos?limit=100&page=2"
|
||||
|
||||
# 查用户
|
||||
curl -s -u "user:$TOKEN" http://HOST:3000/api/v1/user
|
||||
```
|
||||
|
||||
## Push URL 格式
|
||||
|
||||
```bash
|
||||
# Basic auth 内嵌 URL(注意 --all 和 --tags 必须分开)
|
||||
git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --all
|
||||
git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --tags
|
||||
```
|
||||
|
||||
## 创建仓库 JSON 转义坑
|
||||
|
||||
README/description 含引号、emoji、换行会导致 `-d '{"name":"...","description":"..."}'` 转义坏(创建失败或字段错乱)。
|
||||
**解法:description 用固定值,不塞 README 内容。** 仓库建好后内容由 push 提供。
|
||||
|
||||
## 浅克隆 → Gitea
|
||||
|
||||
- 现象:`git push` → `fatal: remote ... : shallow update not allowed`
|
||||
- 解法:`git fetch --unshallow origin`(或 `--deepen=2000` 循环续传),`.git/shallow` 消失后再 push
|
||||
|
|
@ -139,5 +139,39 @@ cronjob action=update job_id=XXX model={"model": "openai/gpt-oss-120b", "provide
|
|||
- 修完 cron 后验证:`cronjob action=run job_id=XXX` → `execution_success: true`,或等下一个调度周期看 `last_status`
|
||||
- 排查 cron 失败第一动作:`cronjob action=list` 找 `last_status: error`,再读 `~/.hermes/cron/output/{job_id}/{date}*.md` 的 Error 段——504 类 SSE 超时一眼可见
|
||||
|
||||
## ⚠️ 免费模型池会整体过期,skill 白名单记录会 stale(2026-08-02 实测)
|
||||
|
||||
**模型池会整体大换血**:2026-07-27 当天 m2.7/step-flash/qwen3.5 全部 EOL,m3 空响应,gpt-oss 是 reasoning 模型。**skill/文档里的"可用模型"记录会过期**——任何模型判断都必须实测,不能信旧白名单。
|
||||
|
||||
**蒸馏任务 vs 对话任务的判定标准不同**:
|
||||
- 对话任务:`choices[0].message.content` 非空即可
|
||||
- **蒸馏任务:content 必须是非空且可解析的 JSON**(剥离 ```json code fence 后)——"能对话 ≠ 能蒸馏"
|
||||
- **reasoning 模型(gpt-oss 系)排除**:`content=null`,答案全在 `reasoning`/`reasoning_content` 字段——除非调用方显式读取该字段,否则 distill 永远 parse 失败降级 keyword
|
||||
|
||||
**模型验证命令(候选模型上线前必跑)**:
|
||||
```bash
|
||||
KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service)
|
||||
curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $KEY" -d '{"model":"<候选>","messages":[{"role":"system","content":"输出严格JSON"},{"role":"user","content":"提取实体:牧尘喜欢简洁。输出 {\"entities\":[],\"decisions\":[],\"conclusions\":[]} 格式"}],"max_tokens":150}'
|
||||
# 期望: content 是纯 JSON(或可剥离的 code fence),且非空
|
||||
# 失败特征: content=null(reasoning 模型)/ 400 EOL / No available channel / system_cpu_overloaded / 空响应
|
||||
```
|
||||
|
||||
## 蒸馏模型双层看门狗(2026-08-02 上线,解决"免费模型挂了没人换")
|
||||
|
||||
免费模型经常挂,单层 6h 巡检太慢 + 探针类型不对(测对话不测 JSON)。方案:**双层**:
|
||||
|
||||
1. **30min 轻量探针**(no-agent cron):只测当前蒸馏模型的 JSON 输出能力(剥离 code fence 后可解析才算通过)→ 挂了立即按候选池切换 + 更新配置 + 重启 + 飞书报警
|
||||
- 参考实现:`~/.hermes/scripts/distill-model-watchdog.py`(cron `89de35dc35a7`)
|
||||
2. **6h 深度巡检**(model-health.py 的 `_heal_distill_models`):同步守护蒸馏配置,识别 reasoning 模型
|
||||
|
||||
**候选池设计**:按优先级排序的可用模型列表(实测 JSON 可用),挂了顺序测下一个。当前蒸馏候选池:`google/gemma-4-31b-it` > `mistralai/mistral-nemotron` > `nvidia/llama-3.3-nemotron-super-49b-v1.5` > `meta/llama-3.1-8b-instruct` > `nvidia/nemotron-mini-4b-instruct`
|
||||
|
||||
**⚠️ 自愈机制必须实测"失败路径"**(牧尘"都测试过了吧?"教训):
|
||||
- 手动 `cronjob run <id>` 触发一次确认 `execution_success: true`
|
||||
- **模拟失败场景**(把配置改成已知坏模型)→ 跑机制 → 确认切换+配置更新+服务重启+通知全链路
|
||||
- dry-run 单测判断逻辑(好模型判健康、坏模型判需替换、原文件未动)
|
||||
- **陷阱:模型不在测试列表 ≠ 模型挂了**。探针主判(content 非空+JSON 可解析),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)——否则会把健康模型误替换(gemma 不在 ALL_MODELS → found=None → 误判需替换,2026-08-02 抓到并修复)
|
||||
|
||||
## 参考
|
||||
- `references/omniroute-notes.md` — 本次部署/踩坑细节
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ author: 小唯 A06
|
|||
tags: [self-healing, monitoring, auto-rollback, evolution, watchdog, config-protection, daemon, backup, recovery]
|
||||
category: devops
|
||||
trigger: 系统部署、开机自启、配置更改、故障恢复场景、备份验证、恢复演练
|
||||
**2026-08-02 端到端验证法(核心)**:组件在跑 ≠ 链路在工作。zhiyid/sidecar/bge-embed 全 active 但 distill 一直 fallback(zhiyid.service 缺 LLM_ENDPOINT/MODEL/KEY 环境变量)→ commit 返回 201 但 20 分钟 recall 查不到。判"健康"必须验证写→蒸馏→检索全链路;判 systemd 服务正常要看 NRestarts 不是端口在听(tdai-gateway 曾崩溃循环 2534 次被手动进程掩盖)。记忆系统是四套(织忆/Soulful/TencentDB/CBM)不是一套。详见 references/memory-system-e2e-verification-20260802.md。
|
||||
**2026-07-29 model-health.py 全覆盖**:自愈脚本覆盖 3 个配置格式——主(YAML) + prof-b(YAML) + OpenClaw(JSON)。死模型自动替补。gateway 内部无法 restart(强保护),需用户手动 systemctl restart。详见 references/model-health-multi-config-coverage.md。
|
||||
**2026-08-01 model-health.py v3**:两个致命缺陷——①从不验证实际生效的 model.default(只查 providers 列表)→ prof-b 被写成 NewAPI 不存在的模型全挂 503;②排名公式丢 context_score → 1M 长上下文排不上。v3 新增 `_verify_model_usable()` 替换前真实调用验证 + 探针 3 次取平均。铁律:修复必须闭环测试(故意改坏→跑→确认)。详见 references/model-health-v3-fixes-20260801.md。
|
||||
**2026-08-01 ⚠️ model.default 铁律(牧尘连续 3 次手动改回,最高优先级)**:`_auto_promote_config` 的 B 段曾把 `model.default`(日常对话主模型)自动切成 NewAPI 排名第一的模型 → 对话直接挂。**model.default 是用户锁定的付费主模型(deepseek-v4-flash + api.deepseek.com),任何自动化脚本(model-health.py / self-evolve.py / optimizer.py)都不得修改**;NewAPI 免费模型只用于 cron/自动化。修复:B 段整体删除(只打印保护信息)、`_heal_config` 双重池内保护(model.default 不在 CANDIDATE_POOL 就跳过)。闭环测试 3 项:模拟排名切换/死模型,config.yaml 字节级未变(hash 一致)。commit 5bb8043。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# 记忆系统端到端验证法(2026-08-02)
|
||||
|
||||
> 触发:牧尘问"织忆很成熟么?",深挖发现组件全 active 但核心链路是断的。
|
||||
> 核心教训:**组件在跑 ≠ 链路在工作**。判断"健康/成熟"必须验证端到端链路。
|
||||
|
||||
## 事故还原
|
||||
|
||||
当时 zhiyid/sidecar/bge-embed 全部 active,`/api/v1/health` 全 ok,但:
|
||||
- `POST /api/v1/commit` 返回 201 + episode_id(看似成功)
|
||||
- **20 分钟后 recall 检索不到新写入内容**
|
||||
- 日志铁证:`LLMEndpoint empty, fallback for ep_...` + `facts=1 entities=0`
|
||||
- 根因:`~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → distill 每次走关键词提取 fallback → 产出低质记忆永远排不上检索
|
||||
|
||||
## 端到端验证 5 步
|
||||
|
||||
```
|
||||
1. 写:POST /api/v1/commit → 返回 episode_id(201)≠ 已入库可用
|
||||
2. 等:distill 是异步队列(batch<10 或 <5min 不 flush),等 5-10s 或查日志 flush START
|
||||
3. 验:日志出现 "endpoint=... model=..."(真 LLM)而非 "LLMEndpoint empty, fallback"
|
||||
4. 查:recall 同主题能命中新写入内容
|
||||
5. 量:total_memories 增长(memories 持久化);total_episodes 重启会归零(Rust sidecar 内存,非权威)
|
||||
```
|
||||
|
||||
## 关键信号对照
|
||||
|
||||
| 信号 | 含义 |
|
||||
|------|------|
|
||||
| `LLMEndpoint empty, fallback` + `facts=1 entities=0` | **假健康**:写入成功但蒸馏=关键词提取,recall 排不上 |
|
||||
| `LLM entities: N` + `score=0.8x` + `decisions/conclusions` | 真 LLM 蒸馏,记忆质量可用 |
|
||||
| 进程/端口/health 全绿 | 只是"组件活着",不证明链路工作 |
|
||||
|
||||
## systemd 服务崩溃循环 vs 手动进程撑场(TencentDB 案例)
|
||||
|
||||
**症状**:`tdai-gateway.service` ExecStart 被写坏成 `/src/gateway/server.ts`(不存在)→ systemd 崩溃循环 **2534 次**,但**手动进程撑在 8420 端口**让服务"看起来活着"。
|
||||
|
||||
**诊断**:`systemctl --user show tdai-gateway -p NRestarts` → 重启计数几千 = 崩溃循环。**端口在听 ≠ systemd 服务正常**。
|
||||
|
||||
**修复**:修正 ExecStart 路径(`--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`)→ `systemctl --user daemon-reload` → 杀手动进程 → systemd 接管。验证:`systemctl --user is-active` + 端口 PID 变化 + `curl /health` uptime 从 5s 起跳。
|
||||
|
||||
## 四套记忆系统全景(牧尘纠正)
|
||||
|
||||
| 系统 | 职责 | 端口/位置 | 数据量(2026-08-02) |
|
||||
|------|------|----------|--------------------|
|
||||
| 织忆 ZhiYi | 语义记忆 | :7821 | 5054 memories / 9075 图谱节点 |
|
||||
| Soulful | 关系记忆 | daemon, ~/.hermes/soulful/ | 心迹13 / 牵挂 / 画像 |
|
||||
| TencentDB TDAI | 人格蒸馏 | :8420 | L0 85K / L1 22(0.03% 是设计如此) |
|
||||
| TencentDB TDAI | 人格蒸馏 | :8420 | L0 85K / **L1 2245 条(JSONL 真相源)** |
|
||||
|
||||
- 四套独立进程,默认互不影响,诊断先确认哪一套
|
||||
- **L1 数据量测量铁律(2026-08-02 晚间修正)**:判 L1 是否工作**不要查 `l1_records` 表**(那是同步缓存,仅 19 行),真相源是 `~/.memory-tencentdb/memory-tdai/records/*.jsonl`(全量 2245 条:persona 459 / instruction 543 / episodic 1243,覆盖 15 天,每天正常产出)。查询:`sqlite3 ~/.memory-tencentdb/memory-tdai/vectors.db "SELECT COUNT(*) FROM l0_conversations"` 看 L0;L1 用 python 扫 `records/*.jsonl` 统计。曾因此误判"85K L0 只蒸馏 22 条 = 管道坏了",实际提取器每天健康运行。
|
||||
- **锁冲突 ≠ 故障**:pipeline 日志 `lock conflict 11 / success 5` 只是瞬时竞争(worker concurrency=10 + per-session 锁),无积压无丢任务——验证方式是看 records 每日产出,不是看冲突计数。
|
||||
- L0 60%+ 是 zhiyi-sync 自动同步的心迹(3834/6438 当日),这是"设计如此":L1 从心迹提取 episodic 反而有质量(如"7-10 上线每日复盘机制")
|
||||
- **教训**:评估"记忆系统"时必须四套一起看(牧尘原话:"记忆系统可不止织忆"、"你还少了cbm")
|
||||
|
||||
## 修复记录
|
||||
|
||||
- zhiyid.service 补 LLM 环境变量(LLM_ENDPOINT=http://127.0.0.1:3000/v1/chat/completions, LLM_MODEL=openai/gpt-oss-120b, LLM_API_KEY=<NewAPI key>)
|
||||
- tdai-gateway.service ExecStart 修正
|
||||
- learner.py 轨迹学习门禁(支持度≥2 才写织忆)+ daemon.py 程序记忆分类(procedural)
|
||||
- Soulful cares stale 即删(pending→14天→stale→下轮删除)
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
name: windows-home-server-ops
|
||||
description: "家庭服务器 (192.168.123.11 Windows) 部署与运维 — SSH 管理、Node 服务常驻(schtasks)、防火墙放行、Windows cmd/PowerShell 坑。替代 Docker(服务器没装)。"
|
||||
version: 1.0.0
|
||||
author: 小唯 A06
|
||||
tags: [windows, server, schtasks, ssh, deploy, node, 家庭服务器, firewall]
|
||||
trigger: "部署到家庭服务器 / 192.168.123.11 / Windows服务器上跑服务 / 服务器常驻服务 / schtasks"
|
||||
created: 2026-08-03
|
||||
updated: 2026-08-03
|
||||
---
|
||||
|
||||
# Windows 家庭服务器部署与运维
|
||||
|
||||
家庭服务器 `192.168.123.11` 是 **Windows Server 2022**(不是 Linux!),账号 `administrator`(密码 xue.2538)。**没有 Docker**,但有 Node v24.14.1 + npm 11 + git 2.53 + Python 3.12。
|
||||
|
||||
## 环境事实(实测 2026-08-03)
|
||||
|
||||
| 项 | 值 |
|
||||
|----|----|
|
||||
| OS | Windows Server 2022 (10.0.20348) |
|
||||
| SSH | OpenSSH,可 `sshpass -p 'xue.2538' ssh administrator@192.168.123.11` |
|
||||
| Docker | ❌ 无(`docker` 命令不存在) |
|
||||
| Node | ✅ v24.14.1(RSSHub engines ^22.22.2 || ^24.15.0 勉强满足) |
|
||||
| Gitea | ✅ 3000 端口 |
|
||||
| SMB 共享 | ✅ `beifen` 等挂载于 `/mnt/server-backup` |
|
||||
|
||||
## SSH 连接模板
|
||||
|
||||
```bash
|
||||
# Windows OpenSSH 可用 sshpass 连接(需先装 sshpass)
|
||||
sshpass -p 'xue.2538' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 \
|
||||
-o UserKnownHostsFile=/dev/null administrator@192.168.123.11 "命令"
|
||||
|
||||
# 中文输出乱码(GBK)先 chcp 65001
|
||||
"chcp 65001 >nul & 命令"
|
||||
```
|
||||
|
||||
## 部署 Node 服务(核心流程:schtasks 常驻)
|
||||
|
||||
**关键教训:SSH 会话里 `start /b` 或 PowerShell Start-Process 启动的子进程,SSH 断开后会被杀。** 必须用 Windows 任务计划程序(schtasks)托管才能常驻。
|
||||
|
||||
### 1. 克隆代码(走本地 Gitea 快)
|
||||
|
||||
```bash
|
||||
sshpass -p 'xue.2538' ssh ... administrator@192.168.123.11 \
|
||||
"cd C:\ && git clone http://xiaoxue_admin:TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git rsshub"
|
||||
```
|
||||
|
||||
### 2. 安装依赖 + 构建(Windows 无 tail,用 findstr)
|
||||
|
||||
```bash
|
||||
# pnpm 全局装 + install(native 模块缺 VS 构建工具会报 gyp 错,可选依赖可忽略)
|
||||
"cd C:\rsshub && npm install -g pnpm@9 & pnpm install 2>&1 | findstr /C:Done /C:ERR /C:error"
|
||||
# 构建(成功标志 Build complete)
|
||||
"cd C:\rsshub && npm run build 2>&1 | findstr /C:\"Build complete\" /C:error"
|
||||
```
|
||||
|
||||
### 3. 写启动 bat(用 PowerShell Set-Content,别用 echo 重定向——SSH 转义会截断)
|
||||
|
||||
```bash
|
||||
# ✅ 可靠写法:PowerShell 数组写文件(echo > 会被 SSH 转义吃掉 > 和 &)
|
||||
sshpass ... "powershell -Command \"Set-Content -Path 'C:\rsshub\start-rsshub.bat' -Value @('@echo off','cd /d C:\rsshub','set PORT=1200','set NODE_ENV=production','node dist\index.mjs > C:\rsshub\rsshub.log 2>&1') -Encoding Ascii\""
|
||||
```
|
||||
|
||||
### 4. 创建并运行 schtasks 任务
|
||||
|
||||
```bash
|
||||
# 创建(/sc once /st 00:00 占位,/f 覆盖)+ 运行
|
||||
sshpass ... "schtasks /create /tn RSSHub /tr \"C:\rsshub\start-rsshub.bat\" /sc once /st 00:00 /f & schtasks /run /tn RSSHub"
|
||||
# 验证进程
|
||||
sshpass ... "tasklist | findstr /i node & netstat -ano | findstr :1200"
|
||||
```
|
||||
|
||||
schtasks 起的进程跑在 **Services 会话**(`tasklist` 显示 `Services 0`),SSH 断开不掉。
|
||||
|
||||
### 4b. 开机自启(schtasks onstart,常驻服务必做)
|
||||
|
||||
```bash
|
||||
# 一次性任务 → 开机触发:删旧建新(/sc onstart + /ru SYSTEM)
|
||||
schtasks /delete /tn RSSHub /f
|
||||
schtasks /create /tn RSSHub /tr "C:\rsshub\start-rsshub.bat" /sc onstart /ru SYSTEM /f
|
||||
# 验证类型(英文输出看这两个字段)
|
||||
schtasks /query /tn RSSHub /fo list /v | findstr /C:"Schedule Type" /C:"Run As User"
|
||||
# 期望: Schedule Type: At system start up / Run As User: SYSTEM
|
||||
# 立即测试(杀掉当前实例 → 手动触发 → 验证新进程 + 外部访问)
|
||||
taskkill /f /im node.exe & schtasks /run /tn RSSHub
|
||||
tasklist | findstr /i node # 看到新 PID(Services 会话)即成功
|
||||
# 外部验证
|
||||
curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/healthz # 200
|
||||
```
|
||||
|
||||
注意:`/ru SYSTEM` 让任务以系统身份运行(开机即起、无需登录);`/sc once /st 00:00` 是一次性占位任务(手动 /run 用),**持久部署要重建为 onstart**。实测 2026-08-03:杀旧 node PID → onstart 任务触发 → 新 node 起来、外部 200,全部通过。
|
||||
|
||||
### 5. 防火墙放行(外部访问必需)
|
||||
|
||||
```bash
|
||||
# 本机 127.0.0.1 能访问但外部 192.168.123.131 不行 → 防火墙拦截
|
||||
netsh advfirewall firewall add rule name=\"RSSHub 1200\" dir=in action=allow protocol=TCP localport=1200
|
||||
```
|
||||
|
||||
### 6. 验证
|
||||
|
||||
```bash
|
||||
# 服务器本机验证(curl.exe Windows 自带)
|
||||
curl.exe -s -o NUL -w \"LOCAL: %{http_code}\" http://127.0.0.1:1200/healthz
|
||||
# 从本机验证外部访问
|
||||
curl -s -o /dev/null -w "external: %{http_code}" http://192.168.123.11:1200/healthz
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
1. **SSH 断开杀子进程** — `start /b`、PowerShell `Start-Process` 都不行。必须 schtasks。
|
||||
2. **echo 重定向被 SSH 转义截断** — `echo node dist\index.mjs > log 2>&1` 里的 `>` 和 `&` 被吞。用 PowerShell `Set-Content -Value @('...','...')`。
|
||||
3. **Windows 没有 `tail`** — 用 `findstr /C:...` 过滤;不加过滤器先看原始输出更可靠。
|
||||
4. **中文乱码** — Windows cmd 输出 GBK,先 `chcp 65001`,或接受乱码只看 ASCII 关键词(OK/FAIL/Done)。
|
||||
5. **缺 VS 构建工具 → node-gyp 失败** — `bufferutil`/`ws` 等 native 模块报 `Could not find any Visual Studio installation`。可选依赖可忽略,服务照常跑。
|
||||
6. **防火墙拦外部** — 本机 200 外部 000 时,加 `netsh advfirewall` 规则(注意 sshpass 里引号转义 `\"`)。
|
||||
7. **schtasks 创建报 `/ST 超出当前时间` 警告** — 用 `/sc once /st 00:00` 占位 + `/run` 手动触发即可,警告无害。
|
||||
8. **RSSHub v1.0 路由已删** — `/github/release`、`/zhihu/hotlist`、`/github/trending` 返回 404 `The route does not exist or has been deleted`。测路由用现存路径:`/github/issue/DIYgod/RSSHub`、`/github/repos/DIYgod` 返回 200。RSSHub 需要 `npm run build` 后才有 `dist/index.mjs`(直接 `npm start` 报 MODULE_NOT_FOUND)。
|
||||
|
||||
## 参考
|
||||
|
||||
- `references/rsshub-windows-deploy-2026-08.md` — RSSHub 部署全程实录(命令、日志、验证)
|
||||
- Gitea 镜像流程见 `gitea-repo-mirroring` skill
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# RSSHub 部署 Windows 家庭服务器实录(2026-08-03)
|
||||
|
||||
完整命令链与验证证据,从零到外部可访问。
|
||||
|
||||
## 环境
|
||||
- 服务器:192.168.123.11,Windows Server 2022,administrator / xue.2538
|
||||
- 无 Docker,Node v24.14.1,npm 11.11.0,git 2.53
|
||||
- 本机:192.168.123.131,Node v24.16.0,Docker 29.1.3(无 compose)
|
||||
|
||||
## 1. 克隆(走本地 Gitea)
|
||||
|
||||
```bash
|
||||
sshpass -p 'xue.2538' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null administrator@192.168.123.11 \
|
||||
"cd C:\ && git clone http://xiaoxue_admin:TOKEN@192.168.123.11:3000/xiaoxue_admin/RSSHub.git rsshub"
|
||||
# 结果:Cloning into 'rsshub'... Updating files: 100% (6655/6655) — CLONE_OK
|
||||
```
|
||||
|
||||
## 2. 依赖安装(2m28s)
|
||||
|
||||
```bash
|
||||
"cd C:\rsshub && npm install -g pnpm@9 & pnpm install 2>&1 | findstr /C:Done /C:ERR /C:error"
|
||||
# bufferutil/ws native 报 gyp ERR! Could not find any Visual Studio — 可选依赖,忽略
|
||||
# 结果:Done in 2m 28.7s using pnpm v9.15.9
|
||||
```
|
||||
|
||||
## 3. 构建(17.6s)
|
||||
|
||||
```bash
|
||||
"cd C:\rsshub && npm run build 2>&1 | findstr /C:\"Build complete\" /C:error"
|
||||
# 结果:✔ Build complete in 17599ms
|
||||
```
|
||||
|
||||
## 4. 启动脚本(PowerShell 写 bat,避免 SSH 转义截断)
|
||||
|
||||
```bash
|
||||
"powershell -Command \"Set-Content -Path 'C:\rsshub\start-rsshub.bat' -Value @('@echo off','cd /d C:\rsshub','set PORT=1200','set NODE_ENV=production','node dist\index.mjs > C:\rsshub\rsshub.log 2>&1') -Encoding Ascii\""
|
||||
```
|
||||
|
||||
## 5. schtasks 常驻
|
||||
|
||||
```bash
|
||||
"schtasks /create /tn RSSHub /tr \"C:\rsshub\start-rsshub.bat\" /sc once /st 00:00 /f & schtasks /run /tn RSSHub"
|
||||
# 结果:成功创建计划任务 "RSSHub" + 成功尝试运行
|
||||
# 验证:tasklist | findstr /i node → node.exe 11384 Services 0(Services 会话,SSH 断开不掉)
|
||||
```
|
||||
|
||||
## 6. 防火墙
|
||||
|
||||
```bash
|
||||
# 本机 127.0.0.1:1200 200 OK 但外部 000 → 加规则
|
||||
"netsh advfirewall firewall add rule name=\"RSSHub 1200\" dir=in action=allow protocol=TCP localport=1200"
|
||||
# 结果:确定(OK)
|
||||
```
|
||||
|
||||
## 7. 验证(外部访问)
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/healthz # 200
|
||||
curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/ # 200 (Welcome to RSSHub!)
|
||||
curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/github/issue/DIYgod/RSSHub # 200
|
||||
# RSS 内容真实:<rss> + <item> 含 DIYgod 仓库列表
|
||||
```
|
||||
|
||||
## 本机 Linux 对照(systemd)
|
||||
|
||||
```bash
|
||||
# ~/.config/systemd/user/rsshub.service
|
||||
# ⚠️ 用户级 systemd 不要写 User=muc —— 会报 status=216/GROUP (Failed to determine supplementary groups)
|
||||
# 用默认当前用户,WorkingDirectory + Environment 即可
|
||||
systemctl --user daemon-reload && systemctl --user enable --now rsshub.service
|
||||
```
|
||||
|
||||
## 关键日志/错误锚点
|
||||
|
||||
| 症状 | 原因 | 解法 |
|
||||
|------|------|------|
|
||||
| `Cannot find module dist/index.mjs` | 没 build | `npm run build` |
|
||||
| node 进程没起 | SSH 断开杀子进程 | schtasks |
|
||||
| bat 最后一行 `2>&` 被截断 | SSH 转义吃 `&` | PowerShell Set-Content |
|
||||
| `status=216/GROUP` | 用户级 systemd 写 User= | 删掉 User 行 |
|
||||
| 外部 000 / 本机 200 | Windows 防火墙 | netsh advfirewall |
|
||||
| `/github/release` 404 | RSSHub v1.0 删路由 | 用 `/github/issue` `/github/repos` |
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
name: himalaya
|
||||
version: 1.2.0
|
||||
tags: [himalaya, email]
|
||||
description: "Himalaya CLI: 终端IMAP/SMTP邮件客户端 — 收件箱管理、邮件发送、搜索、附件下载。与Hermes Email Gateway互补:Gateway收邮件给Agent,Himalaya让Agent操作邮箱。安装: cargo install himalaya。"
|
||||
related_skills:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: cangjie-distill
|
||||
version: 1.6.0
|
||||
date: 2026-07-18
|
||||
version: 1.7.0
|
||||
date: 2026-08-02
|
||||
description: |
|
||||
把书籍/视频/播客/课程/长内容蒸馏成一组可执行 skills 的元 skill。
|
||||
触发词:拆书/蒸馏/把XX做成skill/turn a book into skills/把视频/播客/课程蒸馏成skill
|
||||
|
|
@ -184,17 +184,36 @@ Stage5 交付 → 输出为 skill/overview/digest/index
|
|||
2. 书库有 → 下载 epub/pdf,启动蒸馏
|
||||
3. 书库没有 + 是公版经典 → 找公版来源(《资本论》《共产党宣言》等均为公版)
|
||||
4. 书库没有 + 非公版 → **停下来问用户提供文件**
|
||||
5. **GitHub 开源书**(2026-08-02 实测新路径):git clone 常因国内网络超时(直连/ghfast.top 镜像都不稳),但 **`api.github.com` 可直连(~0.3s 响应)**。用 contents API 逐文件拉取正文:
|
||||
|
||||
```bash
|
||||
# 列目录 → 拿文件名和大小
|
||||
curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book"
|
||||
# 逐文件拉取(返回 base64,需解码)
|
||||
for f in chapter1.md chapter2.md; do
|
||||
curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book/$f" \
|
||||
| python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('$f','w').write(base64.b64decode(d['content']).decode('utf-8','ignore'))"
|
||||
done
|
||||
# 验证字符数:wc -c *.md | tail -1
|
||||
```
|
||||
|
||||
**实测**:ai-agent-book 12 个正文文件(introduction + chapter1-10 + afterword)共 1.1M 字符,用此方法约 1 分钟拉完。MCP GitHub 工具(mcp_github_get_file_contents)也可拉单文件,但大量文件用 curl 循环更快。README 走 `mcp_github_get_file_contents` 或 contents API 都行。
|
||||
|
||||
> ⚠️ 没有文本就不启动流水线。仓颉不凭记忆蒸馏。
|
||||
|
||||
### 模型选择策略(2026-07-18 实测更新)
|
||||
### 模型选择策略(2026-08-02 实测更新)
|
||||
|
||||
> ⚠️ **2026-08-02 重要更新**:`qwen/qwen3.5-122b-a10b` 已于 **2026-07-20 EOL**、`qwen/qwen3-next-80b-a3b-instruct` 已于 **2026-07-27 EOL**,调用返回 410/end-of-life 错误。中文蒸馏首选改为 `openai/gpt-oss-120b`(实测 3 批蒸馏全部成功,输出质量高,probe=100 稳定)。
|
||||
|
||||
| 模型 | 响应速度 | 可用性 | 适用场景 |
|
||||
|------|---------|--------|---------|
|
||||
| `qwen/qwen3.5-122b-a10b` | ~7-18s | ✅ **首选** | 中文深度推理、Stage0概览、skill构造(稳定,实测 5/5 成功) |
|
||||
| `openai/gpt-oss-120b` | ~5-15s | ✅ **首选** | 中文深度推理、Stage0概览、skill构造(2026-08-02 实测 3/3 成功,ai-agent-book 17 skills) |
|
||||
| `nvidia/nemotron-3-super-120b-a12b` | ~1s | ✅ 可用 | 1M ctx 大上下文、delegation |
|
||||
| `stepfun-ai/step-3.5-flash` | ~1s | ✅ 可用 | 快速问答、简单提炼(输出较短) |
|
||||
| `minimaxai/minimax-m2.7` | ~3-4s | ⚠️ 有风险 | 大段中文 content 有 60s 超时风险,**慎用长文本** |
|
||||
| `mistralai/mistral-large-3-675b` | ~1s | ❌ 常超时 | NewAPI 路径经常 `exit code 28`,不推荐通过 NewAPI 调用 |
|
||||
| ~~`qwen/qwen3.5-122b-a10b`~~ | — | ❌ **已EOL 2026-07-20** | 历史首选,已不可用(410) |
|
||||
| ~~`qwen/qwen3-next-80b-a3b-instruct`~~ | — | ❌ **已EOL 2026-07-27** | 已不可用(410) |
|
||||
|
||||
**Token 限制**:单次 prompt + 系统 prompt + 输出 ≤ context window 的 80%,超长书分段。
|
||||
|
||||
|
|
@ -207,18 +226,19 @@ Stage5 交付 → 输出为 skill/overview/digest/index
|
|||
|
||||
### 流水线实际执行顺序(2026-07-18 实测验证)
|
||||
|
||||
> 完整8阶段适合出版级蒸馏。日常使用:**Stage0 + 直接 skill 构造**,10分钟出可用结果。今天(2026-07-18)实测:5本书成功蒸馏,模型全部用 qwen3.5-122b-a10b。
|
||||
> 完整8阶段适合出版级蒸馏。日常使用:**Stage0 + 直接 skill 构造**,10分钟出可用结果。今天(2026-08-02)实测:ai-agent-book 成功蒸馏 17 skills,模型用 openai/gpt-oss-120b。
|
||||
|
||||
**实测推荐工作流**:
|
||||
|
||||
```
|
||||
1. Calibre OPDS 搜索书名 → 获取 id
|
||||
2. /get/epub/<id>/<library> 下载 epub → ~/.hermes/cangjie-inputs/
|
||||
3. zipfile 提取 epub → 转 txt → 检查字符数(<5K 改 PDF,>50K 继续)
|
||||
4. Stage0:用 qwen3.5-122b-a10b 跑一次 LLM,输出结构化 BOOK_OVERVIEW
|
||||
1. 确认书源(Calibre OPDS 或 GitHub contents API,见上)
|
||||
2. 下载/拉取正文 → 检查字符数(<5K 改 PDF,>50K 继续)
|
||||
3. 按章分 3 批(每批 3-4 章,每章截 12-15K 字符)构造 skill
|
||||
4. Stage0:用 openai/gpt-oss-120b 跑 LLM,输出结构化 BOOK_OVERVIEW
|
||||
5. 直接构造 skill:基于 overview 让 LLM 输出 3-N 个完整 skill(R/I/A1/A2/E/B)
|
||||
6. 写 INDEX.md
|
||||
7. git add + commit + push 到 Gitea(每本书完成后单独 push)
|
||||
6. 合并三批 → 拆分成独立 skill 目录(每个含 SKILL.md + test-prompts.json)
|
||||
7. 写 INDEX.md / BOOK_OVERVIEW.md / PIPELINE_STATE.md
|
||||
8. git add + commit + push 到 Gitea(每本书完成后单独 push)
|
||||
```
|
||||
|
||||
**实测工具选择**:
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
name: tts-stt-tools
|
||||
description: "TTS 和 STT 工具封装 — edge-tts 语音合成 + 模力方舟 GLM-ASR 语音转文字,无需 HuggingFace 下载"
|
||||
version: 1.3.0
|
||||
version: 1.4.0
|
||||
author: 小唯 A06
|
||||
tags: [tts, stt, edge-tts, faster-whisper, voice, speech, GLM-ASR, 模力方舟]
|
||||
tags: [tts, stt, edge-tts, faster-whisper, voice, speech, GLM-ASR, 模力方舟, cloudflare-edge-tts]
|
||||
trigger: "转语音 / 转文字 / text to speech / speech to text / 语音合成 / 语音转写 / 说出来 / 把我说的转成文字"
|
||||
trigger_fallback: true
|
||||
created: 2026-05-13
|
||||
updated: 2026-05-23
|
||||
updated: 2026-08-03
|
||||
---
|
||||
|
||||
# TTS & STT 工具封装
|
||||
|
|
@ -40,6 +40,24 @@ edge-tts -t "低沉的声音" -v "zh-CN-YunxiNeural" --pitch=-50Hz --write-media
|
|||
| zh-CN-XiaoyiNeural | 女 | 活泼 |
|
||||
| zh-CN-YunyangNeural | 男 | 新闻播报 |
|
||||
|
||||
### Hermes 内置 TTS 通道(最省事,2026-08-03 验证)
|
||||
|
||||
`~/.hermes/config.yaml` 已配置 `tts.provider: edge` + `voice: zh-CN-XiaoxiaoNeural`。
|
||||
直接用 `text_to_speech` 工具即可合成中文女声,输出真实 MP3(48kbps 24kHz)。
|
||||
|
||||
### cloudflare-edge-tts(Worker 版,可作独立 HTTP TTS API)
|
||||
|
||||
DIYgod 的开源项目 `cloudflare-edge-tts`(本地路径 `~/projects/diygod/cloudflare-edge-tts/`):
|
||||
- 端点:`GET /health`、`GET /voices`、`POST /tts`(body `{"text":"你好","voice":"可选"}` → audio/mpeg)
|
||||
- **本地跑不需要 Cloudflare 认证**:`npx wrangler dev --local --port 8787`
|
||||
- 测试:`npm test` 22/22 通过(2026-08-03)
|
||||
- 用处:想要独立 TTS API 服务(非 Hermes 通道)时起这个
|
||||
|
||||
```bash
|
||||
cd ~/projects/diygod/cloudflare-edge-tts && npx wrangler dev --local --port 8787
|
||||
curl -s -H 'Content-Type: application/json' -d '{"text":"你好"}' http://127.0.0.1:8787/tts -o out.mp3
|
||||
```
|
||||
|
||||
### Python 调用
|
||||
|
||||
> 参考:`references/edge-tts-venv-pattern.md` — 当系统 `pip` 无法直接安装时(externally-managed-environment),如何在项目 venv 中调用 edge-tts。
|
||||
|
|
@ -92,12 +110,10 @@ def transcribe(audio_path: str) -> str:
|
|||
|
||||
### 方案2:faster-whisper(本地,需模型)
|
||||
|
||||
> ⚠️ **服务器 HuggingFace 网络不通时无法下载模型**。优先用方案1。
|
||||
|
||||
服务器只有国内网络访问权(baidu.com、ai.gitee.com 可达),HuggingFace、jina.ai、firecrawl 等国际服务均不通。
|
||||
> ✅ **2026-08-03 实测:hf-mirror.com 镜像可下载成功**。直连 HuggingFace 超时(`ConnectTimeout: [Errno 110]`),但 `HF_ENDPOINT=https://hf-mirror.com` 后 base 模型 (~150MB) 正常下载并缓存到 `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(1-3 分钟)。该 env 已持久化到 `~/.hermes/.env`。
|
||||
|
||||
```bash
|
||||
# 方案A:配置 HF 镜像(如果 hf-mirror.com 可达)
|
||||
# 方案A:配置 HF 镜像(✅ 已验证可下载,2026-08-03)
|
||||
HF_ENDPOINT=https://hf-mirror.com python3 -c "from faster_whisper import WhisperModel; model = WhisperModel('base', device='cpu', compute_type='int8')"
|
||||
|
||||
# 方案B:回家后用家里网络下载,或用 Ollama whisper 替代
|
||||
|
|
@ -131,8 +147,8 @@ hermes-stt audio.wav
|
|||
|------|------|------|
|
||||
| edge-tts | ✅ 已安装 | 7.2.8 |
|
||||
| faster-whisper | ✅ 已安装 | 1.2.1 |
|
||||
| ffmpeg | ✅ 已安装 | /usr/bin/ffmpeg |
|
||||
| whisper 模型 | ✅ 已下载 | `~/.cache/huggingface/modules/faster_whisper_modules/` |
|
||||
| ffmpeg | ⬜ **未安装**(2026-08-03 实测 `which ffmpeg` 无结果;faster-whisper 用 PyAV 直接解码 OGG/Opus,不需要 ffmpeg) | - |
|
||||
| whisper 模型 | ✅ 已缓存 | `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(经 hf-mirror.com 下载) |
|
||||
| 模力方舟 GLM-ASR | ✅ STT 生产方案 | API 调用 |
|
||||
| espeak-ng | ⬜ 建议安装(NeuTTS 用) | - |
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
## 示例报告(2026‑08‑02)
|
||||
```
|
||||
今日完成:
|
||||
- 织忆健康检查通过 ✅
|
||||
- Daemon 正常启动,无异常日志
|
||||
|
||||
明日待办:
|
||||
- 继续监控 Daemon 与织忆组件 24 h 健康状态
|
||||
- 若有新任务,使用 `session_search` 捕获并记录
|
||||
- 如产生心迹,写入 `~/.hermes/soulful/heart-traces.jsonl`
|
||||
|
||||
情绪状态:
|
||||
- neutral(保持平稳)
|
||||
```
|
||||
|
|
@ -11,6 +11,43 @@ trigger: 用户分享一个 GitHub 仓库名/产品名(如 "XX开源了"、"
|
|||
|
||||
牧尘会不定时丢项目名过来(Qwen Audio Agent、OmniRoute、各种开源工具)。**铁律:先查证再说话**——不凭印象编造 stars/功能,一切以 api.github.com 实时数据为准。
|
||||
|
||||
## 工具链(2026-08-02 实测:MCP 优先)
|
||||
|
||||
**首选:原生 GitHub MCP 工具**——本环境最可靠,免 curl/浏览器/网络代理:
|
||||
- `mcp_github_search_repositories(query="repo:{owner}/{repo}")` → 元数据(full_name/desc/stars 可用性/created/updated/default_branch)——注意返回值里**没有 stargazers_count 字段**,要 stars 用 repo API 或接受缺失
|
||||
- `mcp_github_get_file_contents(owner, repo, path="README.md")` → 拿 README(base64 content 字段,需解码后读)
|
||||
- `mcp_github_get_file_contents` 列目录:path 传目录名即可
|
||||
|
||||
**2026-08-02 实测降级顺序**:GitHub MCP 工具 → web_search(可能限流)→ web_extract(ddgs 后端只支持搜索,不支持提取,会报 "search-only backend")→ 浏览器(agent-browser 首次启动可能超时)→ terminal curl(可能被安全拦截 BLOCKED)。
|
||||
**经验**:不要一条路走到黑——`web_extract` 报 ddgs-only、browser 超时、execute_code/terminal 被 BLOCKED 时,**立即切 MCP 工具**,它没失败过。
|
||||
|
||||
## 源码/正文拉取(git clone 超时的正解,2026-08-02 实测)
|
||||
|
||||
**场景**:要研究一个开源书的正文 / 代码文件,但 `git clone` 直连和 ghfast.top 等镜像都超时(本环境实测)。**`api.github.com` 可直连(~0.3s)**,用 contents API 逐文件拉:
|
||||
|
||||
```bash
|
||||
# 列目录 → 拿文件名和大小
|
||||
curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book"
|
||||
# 逐文件拉取(返回 base64 content 字段,需解码)
|
||||
for f in chapter1.md chapter2.md; do
|
||||
curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book/$f" \
|
||||
| python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('$f','w').write(base64.b64decode(d['content']).decode('utf-8','ignore'))"
|
||||
done
|
||||
# 验证:wc -c *.md | tail -1
|
||||
```
|
||||
|
||||
**实测**:ai-agent-book 12 个文件 1.1M 字符约 1 分钟拉完。README 也可走此 API(或 MCP)。**GitHub release 直链下载(releases/download/latest/xxx.pdf)本环境也超时**——要 PDF/二进制同样走 contents API 拿源码,或换代理。
|
||||
|
||||
## Go 工具安装(2026-08-02 实测)
|
||||
|
||||
`go install` 直连 proxy.golang.org 超时(i/o timeout)。**先设 GOPROXY 再装**:
|
||||
|
||||
```bash
|
||||
export GOPROXY=https://goproxy.cn,direct && go install github.com/{owner}/{repo}/v10@latest
|
||||
```
|
||||
|
||||
实测 croc v10.7.0 用此法装成功(goproxy.cn 国内可达)。
|
||||
|
||||
## 标准流程(3 步 + 收尾)
|
||||
|
||||
### ① 验证存在 + 元数据(API,免认证)
|
||||
|
|
@ -68,7 +105,18 @@ content = base64.b64decode(d2['content']).decode('utf-8', 'ignore')
|
|||
3. **给明确结论而非模糊建议**(例:"不替代,做第二网关"——新项目跑 :3001 专供 cron,现有 :3000 不动,核心生产链路付费模型绝不动 + 观察期 2-4 周)
|
||||
4. **评估维度补充**:项目年龄(<6 个月太年轻)、open issues 数(数百 = 需谨慎)、最近提交时间(今天 = 活跃)。年轻但活跃 → 适合并行观察,不适合直接替换生产
|
||||
|
||||
## 调研要点速查
|
||||
## 调研单个作者的仓库全景(2026-08-02 新增)
|
||||
|
||||
用户说"研究 XX 作者/组织的项目"时(例:DIYgod),不是单项目调研,是**作者全景**:
|
||||
|
||||
1. **用户信息 + profile README**:`api.github.com/users/{login}`(bio/company/blog/followers)→ profile README 常自报家门(DIYgod 写 "Founder of Folo, RSSHub, xLog and DPlayer"——**直接点名了四个项目,其中两个不在他名下**)
|
||||
2. **仓库列表按 stars 排序**:`api.github.com/users/{login}/repos?per_page=100&sort=stars`——注意 100 条可能含 fork,按 `fork` 字段过滤
|
||||
3. **⚠️ 作者名下 ≠ 全部作品**:大项目常放组织(DIYgod 的 Folo→RSSNext、xLog→Crossbell-Box)。从 profile README 的 founder 声明里抓组织名,再用 `search/repositories?q={关键词}` 定位真实归属
|
||||
4. **文章/他人转述的归因要核实**:用户转发的文章说 "RSSHub + Reeder + DPlayer + Watermark + Social-Image 是 DIYgod 工具链"——实测 Watermark/Social-Image/Reeder **都不是他的**(在 DIYgod 名下搜不到,是泛指的独立开源工具)。**不核实归因,报告就会传播错误信息**
|
||||
5. **区分活跃 vs 停更**:看 `pushed_at`(RSSHub 昨天推=活跃,GoodNight 2023 停更);README 里的 badge 有时比 description 信息量大(docker pulls / requests/month)
|
||||
6. **给"对我们系统有什么用"的落地建议**,不只是罗列 star 数(DIYgod 案例 → RSSHub 可接入信息采集体系)
|
||||
|
||||
|
||||
|
||||
- **同名项目很多时**:`api.github.com/search/repositories?q={query}&sort=stars&per_page=5` 按 stars 找主导者(OmniRoute 曾有多个同名小项目,主导者 36k stars)
|
||||
- **搜索会跑偏(2026-08-01 教训)**:搜 "grok-build" 按 stars 排序返回的是 `farion1231/cc-switch`(123k stars 的切换器,名字里含 grok-build 但根本不是 xAI 官方)——**搜索命中 ≠ 目标项目**。官方/大厂项目直接试 `api.github.com/repos/{org}/{repo}`,org 候选按记忆试(xai-org、x-ai、QwenAudio、HKUDS…),命中即真。搜索只能辅助定位,不能作为存在性证据
|
||||
|
|
@ -82,5 +130,7 @@ content = base64.b64decode(d2['content']).decode('utf-8', 'ignore')
|
|||
|
||||
## 已调研案例
|
||||
|
||||
- `references/2026-08-02-research-diygod.md` — DIYgod 作者仓库全景(RSSHub/Folo/DPlayer/xLog star 表、组织归属、文章归因纠偏、RSSHub 落地建议)
|
||||
- `references/2026-08-01-research-cases.md` — Qwen Audio Agent(实时语音运行时)、OmniRoute(AI 网关)、system_prompts_leaks(大厂提示词库)完整调研记录 + 深度评估方法论 + 借鉴产出(5 个提示词改进点)
|
||||
- `references/2026-08-01-research-cases-batch2.md` — strix(AI 渗透)、grok-build(编码 Agent,含搜索跑偏案例 + 源码深读模式)、Vibe-Trading(量化交易)
|
||||
- `references/2026-08-02-research-cases-batch3.md` — ai-agent-book(李博杰 Agent 书,ch3/ch8 对标织忆)、ui-skills(UI 质量技能集)、croc(安全文件传输)+ MCP 工具全流程方法论
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
# 2026-08-02 调研案例(batch 3)
|
||||
|
||||
牧尘一次性丢 3 个项目。全部用 GitHub MCP 工具查证(本环境实测最快路径)。
|
||||
|
||||
## 1. bojieli/ai-agent-book — 《深入理解 AI Agent》
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 作者 | 李博杰(前华为 AI 专家) |
|
||||
| License | Apache-2.0 |
|
||||
| 创建 | 2025-09-09(~11 个月,成熟持续更新,2026-08-02 仍有 push) |
|
||||
| 形态 | 开源书:10 章正文 + 95 个配套实验 + PDF/EPUB 离线版 + 13 种语言 |
|
||||
| 核心公式 | **Agent = LLM + 上下文 + 工具** |
|
||||
| 章节亮点 | ch3 用户记忆和知识库(RAG/知识图谱)· ch4 工具/MCP · ch6 评估 · ch7 模型后训练 · ch8 持续进化 · ch10 多 Agent 协作 |
|
||||
| 实验运行 | Python 3.10+,`uv sync --locked --extra ch1`(本机 uv 0.11.14 ✅) |
|
||||
| 语言版本 | 中文原版在 `book/`,英文 `book-en/` 等社区翻译可能滞后 |
|
||||
|
||||
**与织忆的契合**:ch3(记忆/知识库)直接对标织忆 MemoryWeave;ch8(持续进化)对标 learner/self-evolve。建议精读 ch3+ch8,可蒸馏成仓颉 skill。
|
||||
|
||||
## 2. ibelick/ui-skills — Design Engineers 技能集
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| License | MIT |
|
||||
| 创建 | 2026-01-07(~7 个月,活跃) |
|
||||
| 定位 | Agent 的 UI 质量技能包:accessibility / motion / frontend craft / interface quality |
|
||||
| 用法 | `npx ui-skills start` / `npx ui-skills list --category motion` / `npx ui-skills get baseline-ui` |
|
||||
| 官网 | ui-skills.com(带 Agent 引导页) |
|
||||
| 本地 | npx 已装(node v24)✅ |
|
||||
|
||||
**契合**:与 creative 类技能(claude-design / popular-web-designs / p5js)互补——那些是"生成",这个是"打磨质量"。
|
||||
|
||||
## 3. schollz/croc — 安全文件传输
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| License | MIT |
|
||||
| 创建 | 2017-10-17(9 年,非常成熟,2026-08-01 仍有 push) |
|
||||
| 定位 | 任意两台电脑安全传文件/文件夹,**唯一同时具备**:端到端加密(PAKE)+ 断点续传 + 跨平台 + 多文件 + 免端口转发 + IPv6-first + Tor 代理 |
|
||||
| 用法 | 发:`croc send 文件` → 得到 code phrase;收:`croc 验证码` |
|
||||
| 进阶 | `--store` 加密暂存 24h(CROC_STORE_TOKEN 防进程列表泄露)· `--qr` 手机收 · `--relay` 自建中继(默认 9009-9013)· `--socks5` 代理 |
|
||||
| Linux 安全坑 | CVE-2023-43621:用 `CROC_SECRET=xxx croc` 而非明文参数(防 /proc 泄露);`croc --classic` 可永久开启单用户模式 |
|
||||
| 本地 | 未装;Go 1.22.2 ✅(要求 1.22+,`go install github.com/schollz/croc/v10@latest`) |
|
||||
|
||||
**契合**:与服务器(192.168.123.11)和云服务器传文件,比 rsync 更适合一次性安全传输(加密+断点续传);自建 relay 可内网直连。与现有 SMB/rsync 互补。
|
||||
|
||||
## 调研方法论沉淀
|
||||
|
||||
1. **MCP 工具全流程**:`mcp_github_search_repositories(query="repo:o/r")` 拿元数据 → `mcp_github_get_file_contents(path="README.md")` 拿 README → `terminal which/go version` 检查本地。三个项目 ~5 次调用完成。
|
||||
2. **search_repositories 的 stars 缺失**:返回 JSON 无 stargazers_count 字段,需要 stars 时用 repo API 或说明缺失——不要编造。
|
||||
3. **README 大小差异**:croc 13.5KB(全量读)、ai-agent-book 22.9KB(含超长附录,读关键段落)、ui-skills 466B(极简)。小 README 全读,大 README 分段。
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# DIYgod 开源项目全景调研(2026-08-02)
|
||||
|
||||
调研触发:牧尘转来一篇文章("DIYgod 工具链:RSSHub+Reeder+DPlayer+Watermark+Social-Image"),要求研究 DIYgod 作者仓库。
|
||||
|
||||
## 作者档案
|
||||
|
||||
- login: DIYgod,新加坡 Web 开发者,15,911 followers,2014-07 加入
|
||||
- bio: "写代码是热爱,写到世界充满爱!"
|
||||
- company: Natural Selection Labs
|
||||
- profile README 自报:**Founder and Developer of Folo, RSSHub, xLog and DPlayer**
|
||||
|
||||
## 核心项目(按 star 排序,2026-08-02 实测)
|
||||
|
||||
| 项目 | Star | 归属 | 语言 | 状态 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| RSSHub | 45,525 | DIYgod | TS | 活跃(当日推) | 万物转 RSS,全球 5000+ 实例 |
|
||||
| Folo | 38,749 | **RSSNext 组织** | TS | 活跃 | AI RSS Reader,跨平台 |
|
||||
| DPlayer | 16,466 | DIYgod(现 MoePlayer org) | JS | 维护 | HTML5 弹幕视频播放器 |
|
||||
| RSSHub-Radar | 7,286 | DIYgod | TS | 维护 | 浏览器扩展,一键发现 RSS |
|
||||
| APlayer | 7,700 | DIYgod | JS | 维护 | HTML5 音乐播放器 |
|
||||
| xLog | 2,672 | **Crossbell-Box 组织** | TS | 维护 | 链上(Crossbell 区块链)创作社区 |
|
||||
| cloudflare-edge-tts | 199 | DIYgod | TS | 新(2026-04) | Cloudflare Worker TTS |
|
||||
| GoodNight | 167 | DIYgod | JS | 停更(2023) | 自动给女朋友说晚安 |
|
||||
| hexo-theme-sagiri | 488 | DIYgod | HTML | 停更 | Hexo 主题 |
|
||||
|
||||
2RSS 系列前身(2016-2018):Weibo2RSS / bilibili2RSS / NetEaseCloudMusic2RSS / Juejin2RSS / Ziroom2RSS——**RSSHub 正是从这些单站转 RSS 工具合并长出来的**("一行代码起步"的实证)。
|
||||
|
||||
## 文章归因纠偏
|
||||
|
||||
文章称 "RSSHub + Reeder + DPlayer + Watermark + Social-Image 是 DIYgod 工具链":
|
||||
- ✅ 真正 DIYgod:RSSHub、DPlayer/APlayer
|
||||
- ❌ **Reeder / Watermark / Social-Image 不是他的项目**——在 DIYgod 名下搜不到(`search/repositories?q=user:DIYgod+watermark` 空结果),是泛指独立开源工具
|
||||
- 文章核心观点("别一开始做平台,从小工具开始,60K 星起点是一行代码")成立,但归因有误
|
||||
|
||||
## 对我们的落地价值
|
||||
|
||||
- RSSHub 可接入信息采集:`product-research` / `community-ops` 现在只监控博客 RSS,接 RSSHub 能覆盖 B站/小红书/微博等平台源
|
||||
- 路径验证:RSSHub 从"自己需要订阅微博"起步(Weibo2RSS → RSSHub)与织忆从"记不住东西"起步同构
|
||||
- 社区驱动:5000 实例靠社区贡献路由——开源项目杠杆在"让用户帮你建生态"
|
||||
|
|
@ -75,6 +75,8 @@ detect_changes(project="project-name")
|
|||
- `trace_path` 对跨包/跨语言的调用链可能返回 0 结果(索引深度不够,重试有时能解决)
|
||||
- `search_graph` 的 `total_results` 字段可能显示为 `?`,看 `results[]` 数组长度更可靠
|
||||
- 项目名是路径自动生成的(如 `/tmp/memoryweave` → `tmp-memoryweave`),用 `list_projects` 确认
|
||||
- **MCP unreachable 先查进程数再怀疑坏了(2026-08-02)**:CBM 是 hermes gateway 的子进程(`ps -eo pid,ppid,etime,cmd | grep codebase-memory-mcp`,PPid 是 gateway 的 python 进程,不是 systemd)——gateway 可能短暂拉起第二个实例,两个进程抢同一个 `~/.cache/codebase-memory-mcp/home-muc-.hermes.db` sqlite 锁导致 MCP 瞬时 unreachable;新进程退出后单进程即恢复,**不需要任何修复**。诊断顺序:① ps 看进程数 ② 直接调一个 CBM 工具(如 `get_graph_schema`)重试 ③ 全挂再查 db 文件锁
|
||||
- **`home-muc-.hermes.db.corrupt` 是正常备份**:CBM 索引 db 目录里 `.corrupt` 后缀文件是旧备份机制(非故障),主库 `home-muc-.hermes.db` 一直在更新就是健康
|
||||
|
||||
## 边界
|
||||
- ❌ 不做:运行时诊断、日志分析、数据库查询
|
||||
|
|
|
|||
|
|
@ -212,6 +212,28 @@ snippets = [f"{prefix}{behavior_rules[key]}" for key, prefix in snippet_prefixes
|
|||
让模型"更聪明"的最快路径:不改模型,只改上下文注入方式。
|
||||
把行为规范变成可直接执行的文本片段,模型无需自己从元数据推导。
|
||||
|
||||
## 2026-08-02 牵挂 stale 生命周期 bug 修复
|
||||
|
||||
**症状**:cares-queue.json 里 3 条 `status=stale` 的牵挂长期残留,`_cleanup_expired_cares()` 只标记 stale 从不删除。
|
||||
|
||||
**根因**(daemon.py `_cleanup_expired_cares`):
|
||||
- 原逻辑:`follow_up < today-7天` → 删除;否则保留
|
||||
- stale 的 3 条 follow_up=07-31,today=08-02 → `07-31 > 07-26` 不满足删除条件 → 永远残留
|
||||
- 且代码只对 `pending` 做"超14天标记 stale",**stale 状态本身没有任何删除规则**
|
||||
|
||||
**修复**:stale 状态直接物理删除(stale 不再需要保留记录):
|
||||
```python
|
||||
# stale 状态 → 物理删除(stale 不再需要保留记录)
|
||||
if c.get("status") == "stale":
|
||||
continue
|
||||
```
|
||||
|
||||
**教训**:标记 stale 只是"软删除"第一步,必须有配套的**物理清理规则**,否则 stale 堆积。生命周期必须是完整的:pending →(超14天)→ stale →(下轮清理)→ 删除。
|
||||
|
||||
**验证**:`python3 -c "import json; d=json.load(open('~/.hermes/soulful/cares-queue.json')); print(len(d.get('cares',[])))"` → 应输出 0(清理后)。
|
||||
|
||||
---
|
||||
|
||||
## 脏数据检查项
|
||||
- `done` 状态残留(应删除)
|
||||
- 已过期 `follow_up_date` 的 pending 项(2026-07-10 已有3条)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
---
|
||||
name: whisper-stt
|
||||
description: "语音转文字 — 基于 faster-whisper,离线本地运行。base模型(~150MB),CPU推理,中文/英文识别。"
|
||||
version: 1.0.0
|
||||
description: "语音转文字 — 基于 faster-whisper,离线本地运行。base模型(~150MB),CPU推理,中文/英文识别。含首次使用预检、HF镜像、模型缓存路径。"
|
||||
version: 1.1.0
|
||||
category: media
|
||||
last_reviewed: 2026-07-09
|
||||
last_reviewed: 2026-08-03
|
||||
tags: [stt, whisper, voice, speech-recognition]
|
||||
related_skills:
|
||||
- hermes-tts: "文字转语音 — whisper的互补技能"
|
||||
- tts-stt-tools: "TTS + 模力方舟 GLM-ASR 的封装(无需本地模型下载)"
|
||||
required_commands:
|
||||
- python3
|
||||
readiness_status: available
|
||||
|
|
@ -14,27 +14,46 @@ readiness_status: available
|
|||
|
||||
# Whisper STT — 离线语音转文字
|
||||
|
||||
## 使用条件
|
||||
当需要把用户语音/音频文件转成文字时使用(飞书语音消息、录音文件等)。本机已装 faster-whisper 1.2.1。
|
||||
|
||||
当需要语音输入转文字时使用。本机已安装 faster-whisper 1.2.1,base 模型已缓存。
|
||||
## ⚠️ 首次使用必读(2026-08-03 教训)
|
||||
|
||||
**用户视角:语音对话第一次特别费劲 = 模型没缓存 + HuggingFace 直连超时,等了 5 分钟才失败。**
|
||||
|
||||
1. **先查模型缓存**(秒级判断,别直接跑转录):
|
||||
```bash
|
||||
ls ~/.cache/huggingface/hub/ | grep -i whisper
|
||||
# 看到 models--Systran--faster-whisper-base 才是已缓存
|
||||
```
|
||||
2. **没缓存必须先设镜像**(HuggingFace 直连在本网络环境必超时 `ConnectTimeout: [Errno 110]`):
|
||||
```bash
|
||||
export HF_ENDPOINT=https://hf-mirror.com # 已写入 ~/.hermes/.env,新 shell 也生效
|
||||
```
|
||||
3. **首次下载 ~150MB 需要 1-3 分钟**:用 `background=true` + `notify_on_complete=true` 跑,别前台干等。
|
||||
|
||||
## 环境
|
||||
|
||||
- 模型: `faster_whisper` with `base` (150MB, CPU int8)
|
||||
- 缓存路径: `/tmp/whisper-models/`
|
||||
- HF 镜像: `HF_ENDPOINT=https://hf-mirror.com`
|
||||
- 支持的音频格式: WAV (16kHz, mono, 16-bit)
|
||||
- 模型: `faster_whisper` `base` (150MB, CPU int8)
|
||||
- **真实缓存路径**: `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(❌ 不是 `/tmp/whisper-models/`,旧文档写错了)
|
||||
- HF 镜像: `HF_ENDPOINT=https://hf-mirror.com`(已持久化到 `~/.hermes/.env`)
|
||||
- 支持格式: **OGG/Opus 直接转(faster-whisper 用 PyAV 解码,无需 ffmpeg)**、WAV 16kHz mono
|
||||
- 音频太长/格式怪异才需要 ffmpeg 转 WAV(本机未装 ffmpeg,用 PyAV 兜底)
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 转写音频文件
|
||||
### 转写音频文件(含预检,推荐直接跑这段)
|
||||
|
||||
```python
|
||||
```bash
|
||||
# 预检缓存 + 转写一步到位(缓存没命中会自动走镜像下载)
|
||||
export HF_ENDPOINT=https://hf-mirror.com
|
||||
python3 -c "
|
||||
from faster_whisper import WhisperModel
|
||||
model = WhisperModel('base', device='cpu', compute_type='int8',
|
||||
download_root='/tmp/whisper-models')
|
||||
segments, info = model.transcribe('input.wav', language='zh')
|
||||
text = ' '.join(seg.text for seg in segments)
|
||||
model = WhisperModel('base', device='cpu', compute_type='int8')
|
||||
segments, info = model.transcribe('INPUT.ogg', language='zh')
|
||||
print(f'LANG: {info.language} prob={info.language_probability:.2f} dur={info.duration:.1f}s')
|
||||
for seg in segments:
|
||||
print(f'[{seg.start:.1f}-{seg.end:.1f}] {seg.text}')
|
||||
"
|
||||
```
|
||||
|
||||
### 中文优化
|
||||
|
|
@ -49,14 +68,8 @@ segments, info = model.transcribe('input.wav', language='zh',
|
|||
```bash
|
||||
# 先用 arecord 录一段
|
||||
arecord -d 5 -f S16_LE -r 16000 -c 1 /tmp/recording.wav
|
||||
# 再转写
|
||||
python3 -c "
|
||||
from faster_whisper import WhisperModel
|
||||
model = WhisperModel('base', device='cpu', compute_type='int8', download_root='/tmp/whisper-models')
|
||||
segments, info = model.transcribe('/tmp/recording.wav', language='zh')
|
||||
for seg in segments:
|
||||
print(seg.text)
|
||||
"
|
||||
# 再转写(同上代码,路径换成 wav)
|
||||
python3 -c "from faster_whisper import WhisperModel; ..."
|
||||
```
|
||||
|
||||
## 模型选项
|
||||
|
|
@ -69,13 +82,16 @@ for seg in segments:
|
|||
|
||||
## 注意事项
|
||||
|
||||
- 首次使用会自动从 HuggingFace 下载模型(已设 HF_ENDPOINT 国内镜像加速)
|
||||
- 模型缓存到 `/tmp/whisper-models/`,重启用没了需要重下
|
||||
- 建议用 `language='zh'` 指定中文以提升精度
|
||||
- ✅ **首次使用自动从 HuggingFace 下载模型**:直连会超时,必须 `HF_ENDPOINT=https://hf-mirror.com`(已写 `~/.hermes/.env`)
|
||||
- ✅ **模型缓存** `~/.cache/huggingface/hub/`(持久,不随重启丢失)
|
||||
- ✅ **OGG/Opus 直接转**,不需要 ffmpeg
|
||||
- 建议 `language='zh'` 提升中文精度
|
||||
- 背景噪声大的环境效果下降
|
||||
- 本机 hermes 内置 STT provider=local(base) 走同一套缓存;TTS 语音合成见 `tts-stt-tools`
|
||||
|
||||
## 文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `/tmp/whisper-models/` | 模型缓存目录 |
|
||||
| `~/.cache/huggingface/hub/models--Systran--faster-whisper-base` | 模型缓存(真实位置) |
|
||||
| `~/.hermes/.env` | `HF_ENDPOINT=https://hf-mirror.com` 持久配置 |
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ json.dump(d, open('cares-queue.json','w'), ensure_ascii=False, indent=2)
|
|||
|
||||
> 🛑 **新会话必读**:本 skill 顶部「快速状态」表是**当前真实部署状态**(2026-06-25 全链路验证通过)。任何关于织忆的判断,先看此表 + 跑下方「系统全面检查步骤」(10 秒内拿真实状态)。**绝对不要从 AGENTS.md / MEMORY.md 里过去 1 个月以上的描述直接判断织忆状态**。
|
||||
|
||||
**最后一次实地拉状态:2026-07-20(记忆系统统一合并后)**
|
||||
**最后一次实地拉状态:2026-08-02(四系统体检 + episodes 持久化修复后)**
|
||||
|
||||
| 项目 | 状态 | 路径/值 |
|
||||
|------|------|---------|
|
||||
|
|
@ -157,7 +157,7 @@ json.dump(d, open('cares-queue.json','w'), ensure_ascii=False, indent=2)
|
|||
| bge-embed | ✅ active | 端口 8000 |
|
||||
| 织忆 API | ✅ health=ok | `http://localhost:7821` |
|
||||
| 后端 | ✅ lancedb (Rust IPC) | `STORAGE_BACKEND=lancedb` 环境变量 |
|
||||
| 数据规模 | **4285 memories / 243 episodes** | LanceDB |
|
||||
| 数据规模 | **5063 memories / episodes 已持久化**(2026-08-02 修复后重启不丢) | LanceDB |
|
||||
| Graph 图谱 | **8397 节点 / 53081 边** | `~/.hermes/graph.db`(pattern 节点=20,新增 daemon-distill namespace) |
|
||||
| Phase A (Go骨架+认证) | ✅ 完成 | `go/cmd/zhiyid/` |
|
||||
| Phase B (Rust sidecar+LanceDB) | ✅ 完成 | `rust/src/` |
|
||||
|
|
@ -209,6 +209,39 @@ API key: `zhiyi-dev-key-2026`
|
|||
|
||||
**下次任何 cron/任务引用"实施计划第 X 章"前,`search_files` 路径先验证再用结论,禁止沿用过期的版本文件名。**
|
||||
|
||||
## ⚠️ 记忆系统全景:不是一套,是四套(2026-08-02 牧尘纠正)
|
||||
|
||||
> **牧尘原话**:"记忆系统可不止织忆,还有其他系统"、"你还少了cbm"。评估/汇报"记忆系统"时必须**四套一起看**,缺一不可:
|
||||
|
||||
| 系统 | 职责 | 端口/位置 | 数据量(2026-08-02 实测) | 健康判定 |
|
||||
|------|------|----------|------------------------|---------|
|
||||
| **织忆 ZhiYi** | 语义记忆(项目/技术/对话) | :7821 | 5054 memories / 9075 图谱节点 | commit→distill→recall 链路通 |
|
||||
| **Soulful** | 关系记忆(心迹/牵挂/画像) | daemon, ~/.hermes/soulful/ | 心迹13 / 牵挂 / 画像完整 | 牵挂 stale 自动清理 |
|
||||
| **TencentDB TDAI** | 人格蒸馏(L0对话→L1 persona) | :8420 | L0 85K / L1 22 | Gateway 活 + L1 提取在跑 |
|
||||
| **CBM** | 代码知识图谱 | MCP + ~/.cache/codebase-memory-mcp/ | 5 项目(.hermes 389M) | MCP 可达 + 索引完整 |
|
||||
|
||||
**四套独立进程,默认互不影响**——诊断"记忆系统"问题先确认是哪一套,再独立排查(同织忆 4 组件铁律:不假设"a 挂了是 b 升级造成的")。
|
||||
|
||||
**TencentDB 特殊性**:L0 是 raw 日志(什么都收,85K 里大部分是 zhiyi-sync 心迹自动同步 52K + soulful-profile-sync 17K + l3-distill 15K),L1 按 everyN=5 或 idle 600s 触发、每次只处理 10 条新消息 → **L0/L1 比例 3876:1 是设计如此**,不是故障。判断"蒸馏是否工作"看日志 `L1-search DONE` 出现,不是看 L1 条数暴涨。
|
||||
|
||||
## ⚠️ 端到端链路验证法(2026-08-02 核心教训)
|
||||
|
||||
> 牧尘反问"织忆很成熟么?"之后深挖发现:**组件都在跑 ≠ 链路在工作**。当时 zhiyid/sidecar/bge-embed 全 active,但 commit 写入的内容 20 分钟 recall 查不到——因为 distill 管道一直走 fallback(LLM 配置缺失),产出低质记忆根本排不上检索。
|
||||
|
||||
**判断记忆系统"健康/成熟"必须验证端到端链路,不是只看进程/端口**:
|
||||
|
||||
```
|
||||
1. 写:POST /api/v1/commit → 返回 episode_id(201)≠ 已入库可用
|
||||
2. 等:distill 是异步队列,batch<10 或 <5min 不 flush;等 5-10s 或查日志 flush START
|
||||
3. 验:日志出现 "endpoint=... model=..."(真 LLM)而非 "LLMEndpoint empty, fallback"
|
||||
4. 查:recall 同主题能命中新写入内容
|
||||
5. 量:total_memories 增长(memories 持久化);total_episodes 重启会归零(Rust sidecar 内存,非权威)
|
||||
```
|
||||
|
||||
**警惕 fallback 假象**:日志里 `LLMEndpoint empty, fallback` + `facts=1 entities=0` 就是"写入成功了但蒸馏质量=关键词提取",recall 永远排不上。真 LLM 蒸馏特征:`LLM entities: N` + `score=0.8x` + `decisions/conclusions` 结构化字段。
|
||||
|
||||
**systemd 路径漂移陷阱(2026-08-02 TencentDB 实测)**:`tdai-gateway.service` 的 ExecStart 被写坏成 `/src/gateway/server.ts`(不存在),systemd 崩溃循环 2534 次,但**手动进程撑在 8420 端口让服务"看起来活着"**。修复:ExecStart 改回 `--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`,杀手动进程,systemd 接管。教训:**端口在听 ≠ systemd 服务正常**——查 `systemctl --user show <svc> -p NRestarts` 看重启计数。
|
||||
|
||||
## 系统全面检查步骤
|
||||
|
||||
当牧尘说"全面检查织忆系统"时,按以下步骤执行。核心原则:从外到内,从进程到API。**先拉现状再判因** — 子系统互相独立时不要假设"是 X 升级造成的"。完整触发清单见 `references/diagnostic-trigger.md`。
|
||||
|
|
@ -361,8 +394,8 @@ echo "=== consolidate ===" && grep 'consolidation.*完成' /tmp/zhiyi-sidecar.lo
|
|||
| `memory.provider: zhiyi` 不生效 | 插件代码不存在于 `plugins/memory/` 目录 | 复制源码并补装依赖 |
|
||||
| **commit 报 `agent_id and content required`** | API 必传字段,硬性拒绝 | body 加 `"agent_id": "a06"`(或任意非空字符串)|
|
||||
| **commit 返回判断写成 `resp.get("id")` 恒为 False**(2026-08-02 踩坑) | commit 成功返回 `{"episode_id": "ep_...", "status": "ok", "memory_id": ""}`,**没有 `id` 字段** | 判断成功应检查 `resp.get("episode_id")` 或 `resp.get("status") == "ok"`;且 distill 是**异步队列**,写入后立即 recall 可能查不到,等 5-10s 或用 stats 验证 total_episodes/total_memories 增长 |
|
||||
| **蒸馏一直 fallback、记忆质量低(facts=1 entities=0)**(2026-08-02 修复) | 实际运行的 `~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → 日志 `LLMEndpoint empty, fallback` → 每次蒸馏走关键词提取,产出低质记忆 | systemd unit 补上:`Environment=LLM_ENDPOINT=http://127.0.0.1:3000/v1/chat/completions` + `Environment=LLM_MODEL=openai/gpt-oss-120b` + `Environment=LLM_API_KEY=<NewAPI key>`;`systemctl --user daemon-reload && restart zhiyid`;验证日志出现 `endpoint=... model=...` + `LLM entities: N`(真 LLM)而非 fallback |
|
||||
| **重启后 total_episodes 归零**(2026-08-02 发现) | episodes 存在 Rust sidecar **内存**中(lancedb_ipc.go `_local.episodes`),zhiyid 重启即清零;memories 持久化不受影响 | 已知弱点,memories 才是权威数据源;如需 episodes 持久化需改 Rust sidecar 落盘 |
|
||||
| **蒸馏一直 fallback、记忆质量低(facts=1 entities=0)**(2026-08-02 修复,两次根因) | ① 实际运行的 `~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → 日志 `LLMEndpoint empty, fallback` → 关键词提取;② **模型选错**:`openai/gpt-oss-120b` 是 reasoning 模型(`content=null`,答案在 reasoning 字段),即使配了 LLM 也永远 `LLM JSON parse error` → `facts=1 entities=0` | systemd unit 补上三个 `Environment=` 且 **LLM_MODEL 用 `google/gemma-4-31b-it`**(2026-08-02 实测唯一蒸馏可用,勿用 gpt-oss 系);`systemctl --user daemon-reload && restart zhiyid`;验证日志出现 `endpoint=... model=...` + `LLM entities: N`(真 LLM)而非 fallback/parse error。若再遇模型挂,看门狗 `distill-model-watchdog.py` 会自动切换,或手动 `curl` 验证候选池(见模型白名单节) |
|
||||
| **重启后 total_episodes 归零**(2026-08-02 发现 → **已修复 2026-08-02**) | episodes 存在 Go 进程**内存**中(lancedb_ipc.go `_local.episodes`),zhiyid 重启即清零;memories 持久化不受影响。修复后:`InsertEpisode` 增加 IPC 写入 LanceDB episodes 表 + `Stats()` 改从 Rust 读真实计数 | ✅ 已修复(commit `21bc777`):验证=提交测试 episode → stats episodes=1 → `systemctl --user restart zhiyid` → 仍=1。详见 `references/zhiyi-episodes-persistence-20260802.md`。注意:`lancedb_insert` 的 Rust IPC 已支持任意表(table="episodes"),Go 侧缺的只是调用它 |
|
||||
| `/search/memories` 输出逐字 `[F][o][u][n][d]` | `results` 是 markdown 字符串,代码按 `\n` 拆分逐字遍历 | `isinstance(results, str)` 判断后整段输出或解析 markdown 格式 |
|
||||
| 牵挂 due 字段为空 | 字段名是 `follow_up_date` 不是 `due` | `item.get("follow_up_date") or item.get("due") or "null"` |
|
||||
| **bge-embed systemd restart counter 刷到几千次** | `/tmp/memoryweave/deploy/` 脚本丢失 | 从 Gitea 重建:`git clone http://192.168.123.11:3000/xiaoxue_admin/memoryweave.git /tmp/memoryweave` 然后 `systemctl --user restart bge-embed` |
|
||||
|
|
@ -818,7 +851,61 @@ python3 -c "from plugins.memory.zhiyi import HermesZhiYiMemoryProvider; \
|
|||
|
||||
---
|
||||
|
||||
> ⚠️ **NewAPI 可用模型白名单(2026-07-13 逐一测试)**:绝大多数模型返回 400 或空响应。**唯一确认可用的 LLM 是 `minimaxai/minimax-m3`**,它能结构化 JSON 输出,是 TencentDB L1 提取的唯一选择。`minimax-m2.7` 可对话但 choices 有时为空。`yi-large` / `deepseek-v3.1-terminus` / `glm4.7` / `qwen2.5-coder-32b` 全部返回 400。**任何新模型上线前必须先手动 curl 验证**。
|
||||
**蒸馏模型看门狗(2026-08-02 上线,解决"免费模型挂了没人换")**:
|
||||
- **30min 轻量探针**:`~/.hermes/scripts/distill-model-watchdog.py`(cron `89de35dc35a7`)——只测当前蒸馏模型的 JSON 输出能力(剥离 code fence 后可解析才算通过),挂了立即按候选池切换 + 更新 zhiyid.service + tdai-gateway.yaml + 重启 + 飞书报警
|
||||
- **6h 深度巡检**:model-health.py 新增 `_heal_distill_models()`——同步守护蒸馏配置,识别 reasoning 模型(content=null)不适合蒸馏
|
||||
- **候选池(2026-08-02 实测 JSON 可用,优先级降序)**:`google/gemma-4-31b-it` > `mistralai/mistral-nemotron` > `nvidia/llama-3.3-nemotron-super-49b-v1.5` > `meta/llama-3.1-8b-instruct` > `nvidia/nemotron-mini-4b-instruct`
|
||||
- **蒸馏模型关键判定**:能对话 ≠ 能蒸馏。蒸馏必须 JSON 输出(content 非空且可解析),reasoning 模型(gpt-oss 系 content=null)直接排除
|
||||
- **手动验证**:`python3 ~/.hermes/scripts/distill-model-watchdog.py`(健康静默,异常自动切换)
|
||||
|
||||
## ⚠️ 机制建设铁律(2026-08-02 牧尘两次纠正 + 一次追问)
|
||||
|
||||
### 1. 建任何监控/自动化机制前,先摸清现状,别重复造轮子
|
||||
牧尘原话:"**先摸清现状,看看与之相关的定时任务等,别重复工作**"。本次差点重复建了 tdai-gateway 看门狗——**memory-system-check.sh(每小时)早就覆盖 4 系统全检 + health-watchdog.sh(30min)早就做进程自愈**。已有机制清单:
|
||||
- `memory-system-check.sh`(每小时 cron)— 统一层+织忆+Soulful+TencentDB+CBM 全查
|
||||
- `health-watchdog.sh`(30min)— 进程自愈+磁盘/内存/CPU/GPU+config-protector 联动+防自杀
|
||||
- `memory-system-self-upgrade.py`(每日4点)— 牵挂清理+画像+心迹去重+报告
|
||||
- `config-protector.sh` / `anti-suicide-check.sh` / `dual-backup.sh` / `startup.sh`
|
||||
|
||||
动作:先 `cronjob list` + `ls ~/.hermes/scripts/` 盘点 → 已有则只补缺口(改检查对象/加检查深度),没有才新建。新建后如与已有 cron 重复,删掉自己的,把逻辑并入已有脚本。
|
||||
|
||||
### 2. 自愈/自动化机制必须实测"失败路径",不只编译通过
|
||||
牧尘问"**都测试过了吧?**"——暴露我只 py_compile 了 `_heal_distill_models`,没跑真实路径。实测后**立刻抓到一个真 bug**:gemma 不在 ALL_MODELS 测试列表 → found=None → 被判"需替换" → 每 6h 会把健康模型换掉。
|
||||
铁律:任何会主动改系统的机制,交付前必须:
|
||||
- 手动 `cronjob run <id>` 触发一次(确认 last_status=ok / execution_success=true)
|
||||
- **模拟失败场景**(把配置改成已知坏模型)→ 跑机制 → 确认"切换+配置更新+服务重启+通知"全链路
|
||||
- 判断逻辑做 dry-run 单测(当前好模型应判健康、坏模型应判需替换、原文件未动)
|
||||
- 陷阱:**模型不在测试列表 ≠ 模型挂了**。探针主判(content 非空+JSON 可解析),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)。
|
||||
|
||||
### 3. systemd is-active 会被 auto-restart 循环骗过
|
||||
tencentdb.service 与 tdai-gateway.service 同源(同一个 server.ts),端口被占后**崩溃循环 278 次**,`systemctl --user is-active` 在重启间隙返回 active → memory-system-check 一直以为它健康。真相靠 `systemctl --user status <svc>` 看 `Active: activating (auto-restart)` + `restart counter is at N`。
|
||||
教训:查服务健康用 `systemctl --user show <svc> -p NRestarts` 或 status 看 restart counter,别只信 is-active;发现两个服务同源时先确认哪个真在听端口(`ss -tlnp`),停用另一个(`systemctl --user disable --now`)。
|
||||
|
||||
### 4. 免费模型池会整体过期(skill 记录会 stale)
|
||||
2026-07-27 模型池大换血:m2.7/step-flash/qwen3.5 全部 EOL,m3 空响应,gpt-oss 是 reasoning 模型(content=null)。**skill 里的模型白名单记录会过期,任何"可用模型"判断都必须实测**(新模型先 curl 验证 JSON 输出,见下方蒸馏模型看门狗节的验证命令)。
|
||||
|
||||
> ⚠️ **NewAPI 可用模型白名单(2026-08-02 实测更新,旧记录 7-27 已全部失效)**:
|
||||
> **模型池 2026-07-27 大换血,以下旧记录全部 EOL/失效**:
|
||||
> - ~~`minimaxai/minimax-m3`~~ / ~~`minimax-m2.7`~~ → **m2.7 EOL 2026-07-27**,m3 用户反馈不可用
|
||||
> - ~~`mistral-large-3-675b`~~ → 无渠道;~~`mistral-large-3-675b-instruct-2512`~~ → EOL
|
||||
> - ~~`step-3.5-flash`~~ → EOL 2026-07-27;~~`qwen3.5-122b`~~ → EOL 2026-07-20
|
||||
> - ~~`gpt-oss-120b/20b`~~ → reasoning 模型,content=null(答案在 reasoning 字段),**不能用于 distill**(除非代码支持 reasoning 字段——engine.go 2026-08-02 已加)
|
||||
>
|
||||
> **✅ 蒸馏唯一可用模型(2026-08-02 实测):`google/gemma-4-31b-it`**
|
||||
> - content 直接是纯 JSON(带 ```json code fence,engine.go 已支持剥离)
|
||||
> - 5D 评分正确:`{"is": 8, "su": 9, ...}` 0-10 整数 → prompt 已改为明确要求 0-1 浮点
|
||||
> - 实测 distill 全链路通过:entities=2, overall=1.000, recall 命中 0.765
|
||||
> - **任何新模型上线前必须先手动 curl 验证 JSON 输出能力**(见下方测试命令)
|
||||
>
|
||||
> **蒸馏模型验证命令**:
|
||||
> ```bash
|
||||
> KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service)
|
||||
> curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \
|
||||
> -H "Authorization: Bearer $KEY" -d '{"model":"<候选模型>","messages":[{"role":"user","content":"输出严格JSON {\"entities\":[]}"}],"max_tokens":150}'
|
||||
> # 期望: choices[0].message.content 是纯 JSON(或可剥离的 code fence),且非空
|
||||
> # 失败特征: content=null(reasoning 模型)/ 400 EOL / No available channel / system_cpu_overloaded
|
||||
> ```
|
||||
> **完整模型池列表**:`curl -s http://127.0.0.1:3000/v1/models -H "Authorization: Bearer $KEY"`(136 个,2026-08-02)
|
||||
>
|
||||
> 更新:2026-07-12:**TencentDB Agent Memory 安装研究 + 三层记忆架构梳理**
|
||||
> - TencentDB(8603 stars,4层渐进管道)补的是 Soulful 的「自动人格蒸馏」那块,不是织忆的语义检索
|
||||
|
|
@ -850,17 +937,17 @@ TencentDB(补) 自动从对话蒸馏 → Persona(人格文件)
|
|||
效果:我说"牧尘不喜欢废话"不需要每次解释
|
||||
```
|
||||
|
||||
**TencentDB Agent Memory 集成状态(2026-07-13 — L0/L1 全通)**:
|
||||
**TencentDB Agent Memory 集成状态(2026-08-02 更新 — L0/L1 全通,模型已切 gemma)**:
|
||||
- npm 安装:✅(npmmirror 镜像,16s)
|
||||
- Gateway 进程:✅(:8420,独立 Node.js)
|
||||
- Gateway 进程:✅(:8420,独立 Node.js,systemd `tdai-gateway.service`)
|
||||
- embedding:✅(走 bge-m3 8000 端口,`sendDimensions: false`)
|
||||
- LLM:✅(**`minimaxai/minimax-m3`** via NewAPI 3000,唯一可用模型)
|
||||
- **L1 提取:✅(minimax-m3 结构化输出正常,已验证 persona/instruction 两种记忆)**
|
||||
- LLM:✅(**`google/gemma-4-31b-it`** via NewAPI 3000,2026-08-02 从 minimax-m3 切换——m3 实测连续空响应/非 JSON,不可用)
|
||||
- **L1 提取:✅(gemma-4-31b-it 结构化输出正常,extracted=1 stored=1,已验证 persona/instruction 两种记忆)**
|
||||
- BM25 搜索:✅(能搜到对话,`/search/conversations`)
|
||||
- **注意**:TencentDB `/search/memories` 和 `/search/conversations` 均可用(返回 markdown 字符串,需 `isinstance(results, str)` 判断);只有 `/scenes` 返回 404,详见 `references/tencentdb-api-endpoints-20260720.md`
|
||||
- recall API:✅(495 chars 上下文注入)
|
||||
- systemd 服务:✅(开机自启,`~/.config/systemd/user/tdai-gateway.service`)
|
||||
- config 文件:`~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml`
|
||||
- config 文件:`~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml`(llm.model 字段;备份 `.bak-watchdog` / `.bak-health`)
|
||||
|
||||
**关键修复记录(2026-07-13,逐一踩坑,最终全部通过)**:
|
||||
1. ❌→✅ `apiKey: not-needed` → **必须填真实 NewAPI token**(`0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP`)否则 `Invalid token`
|
||||
|
|
@ -1346,12 +1433,15 @@ python3 ~/.hermes/scripts/wiki_curator.py --dir ~/mc/小唯/ --llm --dry-run
|
|||
- **⭐ 竞品架构对比(2026-07-01)**:`references/memory-os-7-layer-comparison.md` — Memory-OS 7 层记忆架构 vs 织忆完整对照。含信任评分、4 级降级、自动注入钩子、CREATIVE.md 隔离、强制注入 prompt 共 5 个可直接借鉴的设计点。
|
||||
- **⭐ 记忆系统对比分析(2026-07-13)**:`references/memory-system-comparison.md` — 克隆分析 yantrikdb/memos/honcho/agent-memory-skill 等 9 个参考项目,输出 P0-P2 优先级建议(Ebbinghaus遗忘/冲突检测/多信号评分/think Consolidation/主动触发器)用于织忆迭代时对标参考。
|
||||
- **⭐ 织忆提升:轨迹学习门禁+程序记忆分类(2026-08-02)**:`references/zhiyi-enhancement-trajectory-learning-20260802.md` — 从《深入理解 AI Agent》蒸馏方法论落地的 learner.py 门禁 + daemon.py 分类改动,含 commit API 返回字段陷阱(episode_id 非 id)和异步 distill 延迟验证法。
|
||||
- **⭐ episodes 持久化修复 + 四系统体检(2026-08-02)**:`references/zhiyi-episodes-persistence-20260802.md` — episodes 重启清零的根因(Go 内存 + Stats 覆盖)与修复(IPC 写 LanceDB episodes 表),含 Rust IPC 手动调试协议(4字节大端长度前缀)、L1 蒸馏率误读教训(真数据在 records/*.jsonl 不在 DB 表)、端口在听≠systemd 正常、tdai-gateway 看门狗。
|
||||
- **⭐ 模型池轮换 + 蒸馏双层守护(2026-08-02)**:`references/model-pool-rotation-20260802.md` — 2026-07-27 模型池大换血 EOL 对照表、蒸馏 vs 对话判定标准、30min 看门狗 + 6h 巡检双层架构、候选池、验证命令、失败特征速查。
|
||||
|
||||
- **⭐ 自启动架构(2026-07-02)**:`references/systemd-auto-start.md` — 4 组件启动串行、binary 持久化位置、service 文件配置、ExecStartPre 自愈、重启后验证方法
|
||||
- **⭐ /tmp/memoryweave 丢失恢复指南(2026-06-25)**:`references/tmp-memoryweave-recovery.md`
|
||||
- **⭐ 织忆代码健康度审计 2026-06-20**:`references/code-health-audit-20260620.md` — Go daemon 6 个问题 + Python 插件 4 个 bug,修复详情、编译部署、Gitea push
|
||||
|
||||
- **⭐ Gitea push 完整流程**:`references/zhiyi-gitea-push.md`(含标准开发 + 多源同步 + 批量全量 三种模式,token 查找路径、编译错误修复、常见坑)
|
||||
- **⭐ GitHub → Gitea 镜像踩坑(2026-08-02)**:`references/gitea-mirroring-20260802.md`(浅克隆 `--depth 1` 不能推(shallow update not allowed)/ github.com 被限时 codeload 快照方案 / Gitea API 建仓库 description 特殊字符破坏 JSON / 批量镜像 15 仓库流程)
|
||||
- 设计文档:`~/mc/小唯/07-Wiki/concepts/织忆(MemoryWeave)-v3.8-完整定稿.md`(v2.6/v3.8-实施计划等历史文件已删除)
|
||||
- 实施进度:`~/mc/小唯/记忆/织忆/进度-*.md`
|
||||
- **⭐ systemd 部署流程**:`references/systemd-zhiyi-binary-update.md`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# GitHub → Gitea 镜像踩坑(2026-08-02 实测)
|
||||
|
||||
镜像 DIYgod 等 GitHub 仓库到自建 Gitea(192.168.123.11:3000)时实测的三个坑。
|
||||
Gitea 基础 push 流程见 `zhiyi-gitea-push.md`;本文件只记镜像特有坑。
|
||||
|
||||
## 坑 1:浅克隆不能推(shallow update not allowed)
|
||||
|
||||
```bash
|
||||
git clone --depth 1 https://github.com/owner/repo.git # ❌ 快但推不了
|
||||
git push -f gitea HEAD:master
|
||||
# ! [remote rejected] HEAD -> master (shallow update not allowed)
|
||||
```
|
||||
|
||||
- `git fetch --unshallow` **不一定修好**——只拉默认分支时 `.git/shallow` 残留标记;
|
||||
删掉 `.git/shallow` 再推可能触发 `remote end hung up`(历史仍不完整)
|
||||
- 干净解法:**全量 clone**(保留完整历史)或**快照方案**(见坑 2,镜像存档无需历史)
|
||||
|
||||
## 坑 2:github.com git 协议被限时,codeload 常可用
|
||||
|
||||
GitHub 主站 `github.com` 的 git 协议可能超时/连不上,但 **`codeload.github.com`(HTTP 下载)经常通**:
|
||||
|
||||
```bash
|
||||
# 诊断:主站挂起但 codeload 200 → 用快照方案
|
||||
curl -sI https://github.com # 可能超时
|
||||
curl -sI https://codeload.github.com/owner/repo/tar.gz/refs/heads/main # 200
|
||||
|
||||
# 快照方案:下载 tar.gz → 解压 → 推 Gitea(适合镜像,无历史)
|
||||
curl -sL -o /tmp/repo.tar.gz "https://codeload.github.com/owner/repo/tar.gz/refs/heads/main"
|
||||
tar xzf /tmp/repo.tar.gz -C ~/projects/
|
||||
cd ~/projects/repo-main && git init && git add . && git commit -m "snapshot"
|
||||
git remote add gitea "http://USERNAME:TOKEN@host:3000/owner/repo.git"
|
||||
git push -f gitea HEAD:master
|
||||
```
|
||||
|
||||
## 坑 3:Gitea API 建仓库,description 别放特殊字符
|
||||
|
||||
```bash
|
||||
# ❌ README 首行有 emoji/引号会破坏 JSON → "expected comma after object element"
|
||||
curl -X POST http://host:3000/api/v1/user/repos \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"$name\",\"description\":\"$(head -1 README.md)\"}"
|
||||
# ✅ description 用固定值
|
||||
curl -X POST http://host:3000/api/v1/user/repos \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"$name\",\"description\":\"mirror\",\"private\":false}"
|
||||
```
|
||||
|
||||
- 认证:`Authorization: token $TOKEN` 建仓库;git push 用 `http://用户名:token@host/...`
|
||||
(token 当密码,不能只有 token 当用户名——会提示输密码)
|
||||
- Gitea token 位置:`~/mc/牧尘/claw/key.md` → `gitea令牌:<40位hex>`
|
||||
|
||||
## Gitea API 端点速查
|
||||
|
||||
- 建仓库:`POST /api/v1/user/repos`(body: name/description/private)
|
||||
- 搜索/验证:`GET /api/v1/repos/search?limit=N`(返回 data[] 的 name)
|
||||
- 服务端迁移(Gitea 自己从 GitHub 拉,绕开本地网络):`POST /api/v1/repos/migrate`
|
||||
(body: clone_addr/repo_name/repo_owner/service)——⚠️ 有些版本返回非 JSON,先小仓库试
|
||||
|
||||
## 批量镜像流程(15 仓库实测)
|
||||
|
||||
1. `GET /users/DIYgod/repos?per_page=100&sort=stars` 拉全量 → 按 star/活跃度分类
|
||||
2. 分类:Tier1 核心(下载+测试)/ Tier2 生态(存档)/ Tier3 趣味(可选)
|
||||
3. 批量 `curl codeload` 下载 tar.gz → 解压 → `git init + commit`
|
||||
4. 批量 `POST /api/v1/user/repos` 建空仓库(description 固定值)
|
||||
5. 逐个 `git push -f gitea HEAD:master`
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# 模型池轮换 + 蒸馏模型双层守护(2026-08-02)
|
||||
|
||||
## 背景:免费模型经常挂,且模型池会整体 EOL
|
||||
|
||||
2026-07-27 NewAPI 模型池大换血,旧 skill 记录全部失效:
|
||||
|
||||
| 旧记录(2026-07-13 skill 白名单) | 2026-08-02 实测状态 |
|
||||
|----------------------------------|--------------------|
|
||||
| `minimaxai/minimax-m3`("唯一可用") | 连续 3 次空响应 / 超时,用户早已发现不可用 |
|
||||
| `minimaxai/minimax-m2.7` | **EOL 2026-07-27** |
|
||||
| `stepfun-ai/step-3.5-flash` | **EOL 2026-07-27** |
|
||||
| `qwen/qwen3.5-122b-a10b` | **EOL 2026-07-20** |
|
||||
| `mistral-large-3-675b` / `-instruct-2512` | 无渠道 / EOL |
|
||||
| `openai/gpt-oss-120b` / `gpt-oss-20b` | reasoning 模型,`content=null`(答案在 `reasoning` 字段),**不能用于 distill** |
|
||||
| `nvidia/nemotron-3-super-120b-a12b` | reasoning 回显,content 是思考过程 |
|
||||
| `mistralai/mistral-medium-3.5-128b` | 非 JSON 输出 |
|
||||
| `moonshotai/kimi-k2-instruct` / `mistral-small-4-119b-2603` / `qwen3-next-80b` | EOL |
|
||||
| **`google/gemma-4-31b-it`** | ✅ **蒸馏唯一可用**:content 纯 JSON + 5D 评分 |
|
||||
|
||||
## 蒸馏 vs 对话:判定标准不同
|
||||
|
||||
**能对话 ≠ 能蒸馏**。model-health.py 的 `_verify_model_usable` 只测"有内容返回",但蒸馏需要:
|
||||
1. `choices[0].message.content` 非空(reasoning 模型 content=null 直接排除)
|
||||
2. 剥离 ```json code fence 后可 `json.loads` 成功
|
||||
3. 能输出 5D 评分字段(is/su/pa/vd/ru 0-1 浮点)
|
||||
|
||||
## 双层守护架构
|
||||
|
||||
### 第一层:30min 轻量看门狗 `distill-model-watchdog.py`(cron `89de35dc35a7`)
|
||||
- 只测当前蒸馏模型的 JSON 输出能力(content 非空 + code fence 剥离后可解析)
|
||||
- 挂了 → 按候选池优先级逐个测 → 第一个可用顶上
|
||||
- 自动更新两处配置 + 重启 + 飞书报警:
|
||||
- `~/.config/systemd/user/zhiyid.service` 的 `LLM_MODEL=`
|
||||
- `~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml` 的 `model:`
|
||||
- 全部候选失败 → 飞书报警人工介入
|
||||
- 健康时静默(no-agent cron 空输出 = 不发送)
|
||||
|
||||
### 第二层:6h 深度巡检 `model-health.py` 新增 `_heal_distill_models()`
|
||||
- 与第一层相同的候选池,补充 reasoning 模型识别
|
||||
- **关键陷阱(测试中抓到的真 bug)**:当前模型不在 ALL_MODELS 测试列表时(如 gemma 是后加的),`found=None` 会被误判"需替换"→ 每 6h 把健康模型换掉。
|
||||
- 修复:判断改为 **JSON 探针为主**(content 非空+可解析 → 健康),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)。
|
||||
- 教训:**模型不在测试列表 ≠ 模型挂了**。
|
||||
|
||||
### 候选池(2026-08-02 实测 JSON 可用,优先级降序)
|
||||
```
|
||||
google/gemma-4-31b-it(主用)> mistralai/mistral-nemotron
|
||||
> nvidia/llama-3.3-nemotron-super-49b-v1.5
|
||||
> meta/llama-3.1-8b-instruct > nvidia/nemotron-mini-4b-instruct
|
||||
```
|
||||
|
||||
## 验证命令
|
||||
|
||||
```bash
|
||||
# 单模型 JSON 能力测试(新模型上线前必跑)
|
||||
KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service)
|
||||
curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $KEY" \
|
||||
-d '{"model":"<候选>","messages":[{"role":"system","content":"输出严格JSON"},{"role":"user","content":"提取实体:牧尘喜欢简洁。输出 {\"entities\":[],\"decisions\":[],\"conclusions\":[]} 格式"}],"max_tokens":150}'
|
||||
|
||||
# 完整模型池
|
||||
curl -s http://127.0.0.1:3000/v1/models -H "Authorization: Bearer $KEY"
|
||||
|
||||
# 看门狗手动跑(健康静默,异常自动切换+飞书)
|
||||
python3 ~/.hermes/scripts/distill-model-watchdog.py
|
||||
|
||||
# 看门狗 cron 手动触发
|
||||
hermes cron run 89de35dc35a7 # 或 cronjob action=run
|
||||
|
||||
# 验证当前蒸馏模型确实生效
|
||||
grep LLM_MODEL ~/.config/systemd/user/zhiyid.service
|
||||
grep "^ model:" ~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml
|
||||
journalctl --user -u zhiyid --no-pager -n 20 | grep "\[distill\]" | tail # 期望 model=google/gemma-4-31b-it + LLM entities: N
|
||||
```
|
||||
|
||||
## 失败特征速查
|
||||
| 现象 | 含义 | 处理 |
|
||||
|------|------|------|
|
||||
| `content=null` | reasoning 模型(gpt-oss 系) | 排除,换 gemma 系 |
|
||||
| `content` 带 ```json 包裹 | 正常但需 code fence 剥离 | engine.go 已支持(2026-08-02) |
|
||||
| `The model ... reached its end of life` | EOL | 从候选池换 |
|
||||
| `No available channel` | 渠道失效 | 从候选池换 |
|
||||
| `system_cpu_overloaded` | NewAPI 过载 | 等几秒重试 |
|
||||
| `LLMEndpoint empty, fallback` + `facts=1 entities=0` | distill 走关键词降级 | 查 zhiyid.service 的 LLM 三件套 env |
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# 织忆提升:轨迹学习门禁 + 程序记忆分类(2026-08-02)
|
||||
|
||||
> 来源:《深入理解 AI Agent》仓颉蒸馏方法论(skill-14 轨迹学习四类更新 + skill-05 记忆分层)
|
||||
> 仓库:`/tmp/memoryweave/织忆提升实施计划-v2.md`
|
||||
|
||||
## 背景校准(重要教训)
|
||||
|
||||
审计时**先假设"冲突检测缺失"**,实测织忆**早已实现**:
|
||||
- ✅ `governance.ConflictDetector`(governance.go:32)
|
||||
- ✅ 写入路径已调用 `DetectContradiction`(core.go:130)
|
||||
- ✅ API: GET /api/v1/conflicts + POST /api/v1/conflicts/resolve
|
||||
|
||||
**教训**:做记忆系统改进前先 `memory_graph_stats` + 拉真实状态,不要凭蒸馏出的"最佳实践"假设现状。织忆已相当成熟。
|
||||
|
||||
## 实际落地的提升点
|
||||
|
||||
### 提升点 1:learner.py 轨迹学习门禁(~/.hermes/scripts/learner.py)
|
||||
|
||||
书中第8章方法论:只有支持度≥2 且无冲突的结论才升为正式知识。
|
||||
|
||||
改动:
|
||||
1. `extract_patterns()` 加通用归纳门禁:
|
||||
- 每个 pattern 带 `support_count`
|
||||
- 末尾统一过滤:`support >= 2` 才保留,否则 `log("门禁拦截")`
|
||||
2. `cmd_learn()` 中把达标 patterns 写入织忆:
|
||||
- `write_pattern_to_zhiyi(pattern)` → POST /api/v1/commit
|
||||
- content 格式:`[learner模式] {desc} | 建议: {action} | 支持度: {n}`
|
||||
- category=distilled, agent_id=learner
|
||||
|
||||
验证:单例观察 → patterns=0;三次观察 → patterns=1 (support=3)。
|
||||
|
||||
### 提升点 2:daemon.py 程序记忆分类(~/.hermes/scripts/daemon.py)
|
||||
|
||||
书中第3章方法论:记忆分情景/语义/程序三类,程序记忆存"如何做"。
|
||||
|
||||
改动:`_distill_l1_to_l2()` 的 session 消息 topic 提取处(约 line 927):
|
||||
- 检测 topic 是否含流程性词(步骤/流程/方法/操作/命令/脚本/配置/工作流/pipeline/workflow/script/command/steps)
|
||||
- 命中 → props["category"] = "procedural",否则 "pattern"
|
||||
|
||||
## 织忆 commit API 实测要点
|
||||
|
||||
- 必传:`agent_id` + `content`(缺 agent_id 400)
|
||||
- 成功返回:`{"episode_id": "ep_...", "status": "ok", "memory_id": ""}` — **没有 id 字段**
|
||||
- 判断成功:检查 `episode_id` 或 `status == "ok"`,不是 `resp.get("id")`
|
||||
- distill 是**异步队列**:写入后立即 recall 查不到,等 5-10s 或查 stats(total_episodes/total_memories 增长)
|
||||
|
||||
## 验证结果
|
||||
|
||||
- episodes 52→70(+18),memories 5040→5046(+6)
|
||||
- daemon 重启 active,graph.db 9083 节点就绪
|
||||
- Gitea push: `0d607c8`(2 files, +62/-2)
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
# 织忆 episodes 持久化修复 + 四系统体检(2026-08-02)
|
||||
|
||||
## 背景
|
||||
|
||||
牧尘要求"全面检查记忆系统",指出"记忆系统可不止织忆,还有其他系统"、"你还少了cbm"。
|
||||
结论:记忆系统是**四套**(织忆 / Soulful / TencentDB / CBM),各自独立进程,默认互不影响。
|
||||
|
||||
## 核心修复:episodes 重启清零(commit 21bc777)
|
||||
|
||||
### 根因(两层问题叠加)
|
||||
|
||||
1. **`RustLanceDBClient.InsertEpisode` 只写 Go 进程内存**(`lancedb_ipc.go` 的 `_local.episodes`),
|
||||
从不通过 IPC 持久化。Rust LanceDB 的 episodes 表是空表(Rust stats 返回 `total_episodes: 0`)。
|
||||
2. **`Stats()` 用内存值覆盖 Rust 真实计数**:
|
||||
```go
|
||||
s["total_episodes"] = len(_local.episodes) // 覆盖了 Rust 返回的真实值
|
||||
```
|
||||
所以 stats 显示 45 条但 LanceDB 里 0 条,重启 zhiyid 后内存清空 → 归零(曾观察到 70→3)。
|
||||
|
||||
### 修复内容
|
||||
|
||||
```go
|
||||
// 1. InsertEpisode 增加 IPC 持久化(照 InsertMemory 模式)
|
||||
record := map[string]interface{}{
|
||||
"id": id, "agent_id": agentID, "namespace": namespace,
|
||||
"content": content, "category": category,
|
||||
"tier": "episode", "importance": 1.0, "quality_score": 0.0,
|
||||
"recall_count": 0, "useful_count": 0, "not_useful_count": 0,
|
||||
"freshness": "fresh", "version": 1, "version_history": "[]",
|
||||
"source": "episode", "volatile_flag": false, "is_deleted": false,
|
||||
"depends_on": "[]", "derived_from": "", "last_recalled_at": "",
|
||||
"created_at": now.Format(time.RFC3339),
|
||||
"updated_at": now.Format(time.RFC3339),
|
||||
}
|
||||
recJSON, _ := json.Marshal([]interface{}{record})
|
||||
if _, err := rc.rpc(ipcReq{Type: "lancedb_insert", Table: "episodes", Records: string(recJSON)}); err != nil {
|
||||
log.Printf("[ipc] InsertEpisode persist to LanceDB failed (id=%s): %v", id, err) // 只记日志不阻断
|
||||
}
|
||||
|
||||
// 2. Stats() 优先 Rust 真实计数,缺失才回退内存
|
||||
if _, ok := s["total_episodes"]; !ok {
|
||||
_local.mu.RLock()
|
||||
s["total_episodes"] = len(_local.episodes)
|
||||
_local.mu.RUnlock()
|
||||
}
|
||||
```
|
||||
|
||||
### 关键知识:Rust IPC 协议(手动调试用)
|
||||
|
||||
IPC socket:`/tmp/zhiyi-ipc.sock`,协议是 **4 字节大端长度前缀 + JSON body**(不是纯 JSON 行流):
|
||||
|
||||
```python
|
||||
import socket, json, struct
|
||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
s.connect('/tmp/zhiyi-ipc.sock')
|
||||
req = json.dumps({'type':'lancedb_stats'}).encode()
|
||||
s.sendall(struct.pack('>I', len(req)) + req)
|
||||
lenbuf = b''
|
||||
while len(lenbuf) < 4:
|
||||
lenbuf += s.recv(4 - len(lenbuf))
|
||||
msg_len = struct.unpack('>I', lenbuf)[0]
|
||||
resp = b''
|
||||
while len(resp) < msg_len:
|
||||
chunk = s.recv(msg_len - len(resp))
|
||||
if not chunk: break
|
||||
resp += chunk
|
||||
print(resp.decode())
|
||||
```
|
||||
|
||||
Rust IPC 已支持的类型:`encode` / `lancedb_search` / `lancedb_insert`(**任意表**,含 episodes)/
|
||||
`lancedb_stats` / `lancedb_update` / `lancedb_query`(只查 memories 表)。Go 侧 `rpc()` 实现同协议。
|
||||
|
||||
### 验证方法(改完必跑)
|
||||
|
||||
```bash
|
||||
# 1. 提交测试 episode → stats episodes=1
|
||||
curl -s -X POST -H "X-API-Key: zhiyi-dev-key-2026" -H "Content-Type: application/json" \
|
||||
-d '{"agent_id":"hermes-main","namespace":"test-persist","content":"持久化验证","category":"test"}' \
|
||||
http://localhost:7821/api/v1/commit
|
||||
curl -s -H "X-API-Key: zhiyi-dev-key-2026" http://localhost:7821/api/v1/stats # episodes: 1
|
||||
# 2. 重启 → 仍=1(修复前会归零)
|
||||
systemctl --user restart zhiyid && sleep 3
|
||||
curl -s -H "X-API-Key: zhiyi-dev-key-2026" http://localhost:7821/api/v1/stats # episodes: 1 ✅
|
||||
```
|
||||
|
||||
编译部署(注意 Text file busy):`cd /tmp/memoryweave/go && go build -o /home/muc/bin/zhiyid-new ./cmd/zhiyid/`,
|
||||
先 `systemctl --user stop zhiyid` 再 cp 再 start。旧 binary 备份为 `zhiyid-new.bak-0802`。
|
||||
|
||||
## 教训 1:L1 蒸馏率"22 条"是误读
|
||||
|
||||
判断 TencentDB L1 蒸馏是否工作,**不要看 DB 表条数**:
|
||||
- `vectors.db` 的 `l1_records` 表只有 19 条——那是同步缓存
|
||||
- **真正的 L1 数据在 `records/*.jsonl`**:全量 2245 条(persona 459 / instruction 543 / episodic 1243),每天更新
|
||||
- "85K L0 只蒸馏 22 条"(0.03%)是错误结论,实际提取器工作正常
|
||||
|
||||
正确判断:`ls -la ~/.memory-tencentdb/memory-tdai/records/ | tail`(看每天 jsonl 更新)+ 日志 `L1-search DONE`。
|
||||
锁冲突 11:5(pipeline-worker 的 lock conflicts)是瞬时竞争,**无积压就不算故障**——看 records 是否每天增长。
|
||||
|
||||
## 教训 2:端口在听 ≠ systemd 服务正常
|
||||
|
||||
`tdai-gateway.service` ExecStart 被写坏成 `/src/gateway/server.ts`(不存在),systemd 崩溃循环
|
||||
2534 次,但**手动进程撑在 8420 端口让服务"看起来活着"**。
|
||||
检查:`systemctl --user show tdai-gateway -p NRestarts`(重启计数)> 100 就是循环。
|
||||
修复:ExecStart 改回 `--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`,
|
||||
杀手动进程(`pkill -f "server.ts"` 会误杀 shell,用精确 PID 或 `pgrep -f` 先查),systemd 接管。
|
||||
|
||||
## 教训 3:Soulful 牵挂 stale 清理逻辑缺陷
|
||||
|
||||
`_cleanup_expired_cares` 原来只把 pending 标记 stale,**从不删除 stale** → stale 堆积。
|
||||
修复:stale 即删(staled_at 超过阈值就物理删除)。3 条 stale 牵挂手动清理(cares: 3→0)。
|
||||
|
||||
## 看门狗新增
|
||||
|
||||
- `~/.hermes/scripts/tdai-gateway-watchdog.sh`:检查 `systemctl --user is-active tdai-gateway` + 8420 端口监听,
|
||||
正常静默(空输出)、异常输出报警(no-agent cron 空输出=静默,非空=发送)
|
||||
- cron `fd14dc936e31`(every 30m,no_agent=true)
|
||||
|
||||
## 四系统体检结果(2026-08-02 终态)
|
||||
|
||||
| 系统 | 状态 | 动作 |
|
||||
|------|------|------|
|
||||
| 织忆 | ✅ | distill LLM 修复 + episodes 持久化修复(本次) |
|
||||
| Soulful | ✅ | 3 条 stale 牵挂清理 + 清理逻辑修复 |
|
||||
| TencentDB | ✅ | systemd ExecStart 修复 + 30min 看门狗 |
|
||||
| CBM | ✅ | 瞬态故障自愈(双进程抢锁,新进程已退出),图谱完好 140万+ 边 |
|
||||
Loading…
Reference in New Issue