Files
pi-agent-config/scenarios/curator/backend/docs/deployment.zh-CN.md
T
Kai 88b06d782f feat(curator): vendor the application backend as the scenario's tracked source
The curator Python backend (package, tests, systemd units, config templates, scripts) now lives under scenarios/curator/backend and is the single source of truth; the live checkout at the workspace path is a runtime copy. Exported from the app repo's tracked tree via git archive (no history, .pi/venv/caches excluded). 149 unit tests pass from the new location.

profile.toml backend is now repo-relative (scenarios/curator/backend); verify-generated.sh resolves a relative backend against REPO_ROOT. verify-no-secrets ASSIGN heuristic now requires value entropy so vendored kwargs like token=extraction_token no longer false-positive. README documents the backend/ layout and the operator-owned app rollout step.
2026-08-30 18:49:10 -07:00

17 KiB
Raw Blame History

date, updated, type, status, tags, aliases
date updated type status tags aliases
2026-08-26 2026-08-26 runbook active
书影音
Curator
Pi-Agent
Telegram
HomeLab
Curator 部署手册
书影音 Pi Agent 部署

Curator 书影音 Pi Agent 部署与运维

[!summary] Summary 本文是 Curator 在 192.168.50.145 上的生产部署手册,记录当前实际运行方式、依赖、配置、验证、备份和故障处理。架构目标与后续规划见 Curator 书影音管理中枢

本文不保存真实 Token、API Key 或密码。生产密钥只放在权限为 0600 的本机配置文件中。

1. 当前生产基线

截至 2026-08-26,生产服务如下:

项目 当前值
主机 192.168.50.145
LAN Web http://192.168.50.145:8766/
进程管理 systemd --user
服务 curator.service
维护定时器 curator-maintenance.timer
Python 入口 /usr/bin/python3 -m curator serve
Pi CLI @earendil-works/pi-coding-agent@0.84.3
主模型 zenmux/openai/gpt-5.6-lunahigh thinking
回退模型 zenmux/x-ai/grok-4.6
单次 Pi 超时 120 秒
SQLite /home/claw/.local/share/curator/curator.sqlite3
Pi 会话 /home/claw/.local/share/pi-curator/sessions
Pi workspace /home/claw/pi-workspaces/curator
书库 /mnt/truenas/multimedia/books
暂存 /mnt/truenas/multimedia/curator/staging/books
备份 /mnt/truenas/multimedia/curator/backup

当前已经接通 Telegram、Radarr、Radarr 4K、Sonarr 和 Sonarr 4K。Plex 音乐查询和 Tavily 是可选配置,当前健康检查中尚未启用;书籍评价仍可使用公开页面和 DuckDuckGo 回退。音乐自动获取、EPUB 自动翻译、Z-Library 自动下载均未接入 Curator。

生产环境直接从项目源码运行于专用 LLM VPS,Pi 作为 systemd --user 服务的子进程跑在 host 上,不做容器化。VPS 专用于 LLM,systemd 沙箱(ProtectSystem=strictProtectHome=read-onlyNoNewPrivileges 等)已是有意为之的隔离上限。

2. 运行架构与责任边界

Telegram / LAN Web
        |
        v
Curator Python API
  |-- 确定性预分类、权限、计划、执行、核验和审计
  |-- Pi Agent:理解意图、消歧、评价和组织答复
        |
        +-- SQLite:电子书权威目录、候选、任务和控制账本
        +-- Radarr/Sonarr:影视目录、版本和获取
        +-- Plex:音乐目录、管理和播放(配置后启用)
        +-- 微信正文服务:微信文章正文提取
        +-- 公共网页:书籍元数据与评价证据
        |
        v
TrueNAS / unRaid 文件存储

Pi Agent 使用独立 workspace 和持久会话,但启动参数为 --approve --no-tools。模型只输出结构化意图或自然语言答复,不直接调用 shell、修改文件、访问 SQLite 或写入 *Arr;所有事实查询和副作用都由 Curator 的确定性适配器完成。

影视默认优先查询和收集 4K 版本。SQLite 只作为电子书权威目录及跨后端审计账本,不复制 *Arr 和 Plex 已有的完整媒体目录。

3. 前置条件

主机需要:

  • Debian/Linux 用户 claw,支持 systemd --user
  • Python 3.13 或兼容版本;
  • Node.js 22、npm
  • 可访问 ZenMux、Telegram、书籍评价网页和局域网后端;
  • TrueNAS NFS 已挂载到 /mnt/truenas/multimedia,并对 claw 可写;
  • Radarr/Sonarr API Key;需要音乐查询时再配置 Plex Token;
  • 独立 Telegram Bot Token 和允许访问的 Telegram user ID。

先检查挂载和写权限:

findmnt -T /mnt/truenas/multimedia
touch /mnt/truenas/multimedia/curator/.curator-write-test
rm /mnt/truenas/multimedia/curator/.curator-write-test

如果 findmnt 显示为只读,先修复宿主机 NFS 挂载。Codex 沙盒里看到的只读视图不能代替宿主机检查。

4. 目录初始化

claw 用户下执行:

install -d -m 700 ~/.config/curator
install -d -m 700 ~/.local/share/curator
install -d -m 700 ~/.local/share/pi-curator/sessions
install -d -m 700 ~/pi-workspaces/curator/.pi/skills/curator-media

install -d -m 775 /mnt/truenas/multimedia/books
install -d -m 775 /mnt/truenas/multimedia/curator/staging/books
install -d -m 775 /mnt/truenas/multimedia/curator/backup

敏感的配置、SQLite 和 Pi 会话目录建议保持 0700;共享媒体目录根据 NFS 身份映射维持可写权限。

5. 安装并配置 Pi CLI

安装当前验证版本:

npm install -g @earendil-works/pi-coding-agent@0.84.3
pi --version

Pi 的 ZenMux 自定义 provider 位于 ~/.pi/agent/models.json。以下是最小结构示意,真实 API Key 只写在本机:

{
  "providers": {
    "zenmux": {
      "name": "ZenMux",
      "baseUrl": "https://zenmux.ai/api/v1",
      "api": "openai-responses",
      "apiKey": "<ZENMUX_API_KEY>",
      "authHeader": true,
      "models": [
        {
          "id": "openai/gpt-5.6-luna",
          "name": "GPT-5.6 Luna",
          "reasoning": true,
          "input": ["text", "image"],
          "contextWindow": 1050000,
          "thinkingLevelMap": {
            "minimal": "minimal",
            "low": "low",
            "medium": "medium",
            "high": "high",
            "xhigh": "xhigh"
          }
        }
      ]
    }
  }
}
chmod 600 ~/.pi/agent/models.json

部署 Curator 专用 workspace。仓库文件是权威源,生产目录只是运行副本(工作区由 pi-agent-config 的 scripts/deploy-scenario.shscenarios/curator/workspace/ 部署, 不再是本仓库内的文件):

分别验证主模型和回退模型:

pi --mode text --print --provider zenmux --model openai/gpt-5.6-luna \
  --thinking high --no-tools --no-session '只输出 OK'

pi --mode text --print --provider zenmux --model x-ai/grok-4.6 \
  --thinking high --no-tools --no-session '只输出 OK'

回退模型如果不在 models.json 中,Pi 可能提示 Model not found ... Using custom model id;只要随后正常输出 OK,该提示本身不是故障。

6. 配置 Curator

从模板创建生产环境文件:

cd /home/claw/pi-workspaces/curator
install -m 600 config/curator.env.example ~/.config/curator/curator.env

编辑 ~/.config/curator/curator.env,至少填写:

CURATOR_DATA_ROOT=/home/claw/.local/share/curator
CURATOR_LIBRARY_ROOT=/mnt/truenas/multimedia/books
CURATOR_STAGING_ROOT=/mnt/truenas/multimedia/curator/staging/books
CURATOR_BACKUP_ROOT=/mnt/truenas/multimedia/curator/backup
CURATOR_HOST=0.0.0.0
CURATOR_PORT=8766
CURATOR_MAX_UPLOAD_BYTES=268435456

CURATOR_TELEGRAM_BOT_TOKEN=<TELEGRAM_BOT_TOKEN>
CURATOR_TELEGRAM_ALLOWED_USERS=<TELEGRAM_USER_ID>

CURATOR_RADARR_URL=http://192.168.50.10:7878
CURATOR_RADARR_API_KEY=<RADARR_API_KEY>
CURATOR_RADARR_4K_URL=http://192.168.50.100:7878
CURATOR_RADARR_4K_API_KEY=<RADARR_4K_API_KEY>
CURATOR_SONARR_URL=http://192.168.50.10:8989
CURATOR_SONARR_API_KEY=<SONARR_API_KEY>
CURATOR_SONARR_4K_URL=http://192.168.50.100:8989
CURATOR_SONARR_4K_API_KEY=<SONARR_4K_API_KEY>

CURATOR_RADARR_ROOT_FOLDER=/mnt/truenas/multimedia/movies
CURATOR_RADARR_QUALITY_PROFILE_ID=4
CURATOR_RADARR_4K_ROOT_FOLDER=/mnt/unRaid/movie4k
CURATOR_RADARR_4K_QUALITY_PROFILE_ID=5
CURATOR_SONARR_ROOT_FOLDER=/mnt/truenas/multimedia/tv
CURATOR_SONARR_QUALITY_PROFILE_ID=4
CURATOR_SONARR_4K_ROOT_FOLDER=/mnt/unRaid/tv4k
CURATOR_SONARR_4K_QUALITY_PROFILE_ID=7

CURATOR_ZLIB_SEARCH_URL_TEMPLATE=https://zlib.li/s/{query}

可选能力:

# Plex 是音乐目录、管理和播放的权威源。
CURATOR_PLEX_URL=http://192.168.50.100:32400
CURATOR_PLEX_TOKEN=<PLEX_TOKEN>
CURATOR_PLEX_MUSIC_SECTION_ID=

# 配置后增加书评网络证据;留空时使用零 Key 回退。
CURATOR_TAVILY_API_KEY=<TAVILY_API_KEY>
CURATOR_BOOK_WEB_REVIEW_MAX_RESULTS=6

检查权限,且不要把该文件提交到 Git:

chmod 600 ~/.config/curator/curator.env
stat -c '%a %U:%G %n' ~/.config/curator/curator.env

微信链接依赖本机正文服务。当前 systemd unit 使用:

CURATOR_WECHAT_ARTICLE_BASE_URL=http://192.168.50.145:8091

微信正文服务不可用时,普通文字、普通网页、电子书和本地目录查询仍可工作,只有微信文章提取会失败。

7. 部署 systemd 用户服务

install -d -m 700 ~/.config/systemd/user
cd /home/claw/pi-workspaces/curator
install -m 600 systemd/curator.service ~/.config/systemd/user/curator.service
install -m 600 systemd/curator-maintenance.service \
  ~/.config/systemd/user/curator-maintenance.service
install -m 600 systemd/curator-maintenance.timer \
  ~/.config/systemd/user/curator-maintenance.timer

systemctl --user daemon-reload
systemctl --user enable --now curator.service curator-maintenance.timer

为确保用户退出 SSH 后服务仍运行,由 root 一次性执行:

sudo loginctl enable-linger claw

常用命令:

systemctl --user status curator.service
systemctl --user restart curator.service
systemctl --user stop curator.service
systemctl --user status curator-maintenance.timer
journalctl --user -u curator.service -f
journalctl --user -u curator-maintenance.service -n 100 --no-pager

8. 上线验收

8.1 服务与存储

cd /home/claw/pi-workspaces/curator
PYTHONPATH=. python3 -m curator health
curl -fsS http://127.0.0.1:8766/api/health | jq
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8766/
systemctl --user is-active curator.service
systemctl --user is-enabled curator.service curator-maintenance.timer

健康结果至少应满足:

  • status=ok
  • library_writable=truestaging_writable=true
  • Telegram 为 true
  • 四个 *Arr catalog 为 true
  • pi_model 与 systemd unit 一致;
  • Web 根页面返回 HTTP 200

8.2 Telegram 功能

依次测试:

  1. /status:确认服务有响应。
  2. 权力的游戏,库里有什么版本:应查询 Sonarr/Sonarr 4K 后自然语言答复,不应要求用户先选媒体类型。
  3. 发送一部不存在的电影并明确说“加入”:应优先加入 Radarr 4K 并触发搜索;若已经存在则报告现有状态。
  4. 发送一篇普通网页或微信文章:应先提取文章中的书、电影、剧集或音乐,再逐项查重和评价,不能评价文章本身。
  5. 发送 EPUB/PDF:应建立独立导入任务,校验文件并在 /library 可见。
  6. 发送 再试一次:应重跑当前聊天最近一次来源。

8.3 LAN Web

检查以下页面:

  • /candidates:待决策作品与评价证据;
  • /wanted:已决定获取的书籍和手动 Z-Library 搜索链接;
  • /library:已验证的电子书及后端已入库媒体;
  • /sources:原始来源与提取结果;
  • /activity:导入、分析和执行任务;
  • /upload:批量上传 EPUB/PDF。

9. 数据、会话与备份

9.1 权威数据

  • SQLite:电子书 Work/Edition/Asset、候选、wanted、来源、任务、意图、计划、命令和事件。
  • Radarr/Sonarr:影视目录、监控、质量和下载状态。
  • Plex:音乐目录与播放状态,配置后生效。
  • TrueNAS:实际电子书、暂存文件和数据库备份。
  • Pi sessionTelegram 对话连续性;不是媒体事实库。

9.2 当前自动维护策略

curator-maintenance.timer 每天 03:15 运行,另有最多 10 分钟随机延迟。维护任务:

  • 使用 SQLite 在线备份接口生成一致备份;
  • 执行完整性检查;
  • 为备份写入 .sha256
  • 保留最近 14 天的日备份;
  • 删除超过 7 天的 staging 文件。

当前代码尚未实现架构文档中设想的周备份和月备份。TrueNAS 快照、媒体文件备份以及 curator.env、Pi provider 配置和 Pi session 备份,也不属于当前 timer 的职责,应由宿主机/存储层另行承担。

立即执行一次维护并检查结果:

systemctl --user start curator-maintenance.service
systemctl --user status curator-maintenance.service
find /mnt/truenas/multimedia/curator/backup -type f \
  \( -name '*.sqlite3' -o -name '*.sha256' \) -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort

9.3 SQLite 恢复

先停服务并保留当前数据库,再恢复指定备份:

systemctl --user stop curator.service
cd /mnt/truenas/multimedia/curator/backup/database/daily
sha256sum -c <BACKUP_FILE>.sha256

cp /home/claw/.local/share/curator/curator.sqlite3 \
  /home/claw/.local/share/curator/curator.sqlite3.before-restore
install -m 600 <BACKUP_FILE> \
  /home/claw/.local/share/curator/curator.sqlite3.restore

python3 -c "import sqlite3; p='/home/claw/.local/share/curator/curator.sqlite3.restore'; print(sqlite3.connect(p).execute('PRAGMA integrity_check').fetchone()[0])"
mv /home/claw/.local/share/curator/curator.sqlite3.restore \
  /home/claw/.local/share/curator/curator.sqlite3

systemctl --user start curator.service
curl -fsS http://127.0.0.1:8766/api/health | jq

只有完整性检查输出 ok 才继续替换。恢复 SQLite 不会自动回滚 *Arr、Plex 或文件系统中已经执行的外部动作。

10. 更新与回滚

更新前:

systemctl --user start curator-maintenance.service
systemctl --user status curator-maintenance.service

更新源码后执行测试并重启:

cd /home/claw/pi-workspaces/curator
PYTHONPATH=. python3 -m unittest discover -s tests -v
systemctl --user restart curator.service
curl -fsS http://127.0.0.1:8766/api/health | jq

如果 systemd 文件有变化,先重新安装 unit 并执行 systemctl --user daemon-reload。代码回滚后若数据库 schema 不兼容,再按上一节恢复更新前备份;不要只恢复数据库而保留不匹配的代码版本。

11. 常见故障

Web 无法打开或 8766 未监听

systemctl --user status curator.service
journalctl --user -u curator.service -n 200 --no-pager
ss -ltnp | grep ':8766'

重点检查 Python 异常、端口冲突、环境文件路径和 NFS 可写性。

Telegram 不回复

检查:

  • Bot Token 是否正确;
  • user ID 是否在 CURATOR_TELEGRAM_ALLOWED_USERS
  • ZenMux 主模型是否可调用;
  • journalctl 是否持续出现 Telegram 网络错误。

Telegram 偶发 SSL EOF、读超时或 502 时,gateway 会记录错误、等待 5 秒并继续轮询。短暂出现无需重启;持续数分钟再检查网络、代理和 Telegram API。

Pi 请求超时或模型异常

手动运行第 5 节的两个模型探针。主模型超过 120 秒后 Curator 会尝试 Grok 4.6 回退。主、备都失败时,检查 ~/.pi/agent/models.json、ZenMux 配额和 journalctl;不要把 provider API Key 写进 systemd unit 或仓库。

微信文章提取失败

确认 192.168.50.145:8091 的正文服务仍在运行且登录态有效。微信风控、扫码态过期或正文服务不可用都可能导致失败;普通 URL 和手工粘贴作品名仍可使用。

NFS 出现 Stale file handle

确认 TrueNAS export 仍存在,然后在没有写任务时重新挂载对应 NFS。恢复后重新执行写探针和 /api/health。避免在 NFS 失效期间反复启动导入或维护任务。

封面返回 404

通常表示候选项没有可用本地封面,不代表作品、数据库或导入任务失败。先看候选详情中的元数据和评价状态,再判断是否需要刷新。

数据库报错

python3 -c "import sqlite3; p='/home/claw/.local/share/curator/curator.sqlite3'; print(sqlite3.connect(p).execute('PRAGMA integrity_check').fetchone()[0])"

输出不是 ok 时先停服务,保留故障数据库,再从最近通过校验的备份恢复。

12. 外部调用与当前限制

Curator LAN Web/API 只用于 LAN 或 tailnet,当前不设计公网暴露。删除、覆盖和批量清理没有开放给 Telegram Agent。

书籍候选页提供 zlib.li 手动搜索。独立下载器位于 /home/claw/pi-workspaces/zlib-fetcher/,支持持久登录态、匿名额度识别和普通 HTTP/SOCKS 代理,但尚未接入 Curator wanted 队列。调用方式见 /home/claw/pi-workspaces/zlib-fetcher/docs/

音乐查询必须配置 Plex;gamdl 只应由未来的 Curator Downloader 封装为下载执行器,不能代替 Plex 目录。当前没有自动音乐下载。

13. 部署文件索引

文件 用途
README.md 功能与开发入口
config/curator.env.example 无密钥环境变量模板
systemd/curator.service 生产 Web、Telegram、Pi 服务
systemd/curator-maintenance.* 备份和清理任务
curator/pi_agent.py Pi 调用、模型回退和结构化提示
curator/telegram.py Telegram gateway 与交互流程
curator/maintenance.py SQLite 备份与 retention
docs/obsidian/Curator 书影音管理中枢.md 总体架构、边界与路线图