# dhc-pet — mcore 宠物桥(独立插件) > 2026-11-02 起,mcore 不再自带宠物/形象实现。**渲染归 dsh-pet,人格与记忆归 mcore。** ## 为什么拆成两层 mcore v0.48.0 曾把自研形象引擎(`dsh/avatar-app/`,含骨骼/渲染/行为树)整体删除。 现在不重新造轮子,而是复用一个已经成熟的渲染层: | 层 | 谁负责 | 做什么 | |---|---|---| | 渲染 / 交互 | **dsh-pet** 插件 | 立绘、动画、气泡、物理、桌面窗口、右键菜单 | | 人格 / 情绪 / 关系 / 长期记忆 | **dhc-pet**(本插件)+ mcore | 情绪节点、关系值、进化、记忆检索与写入 | 两层之间只用 HTTP 通信,互不 import。好处是 dsh-pet 升级换版、mcore 重构主文件, 都不会把对方打断。 ## 接线关系 ``` ┌───────────────────────────────┐ │ mcore (dhc-core) │ │ GET /api/dhc/state │ │ POST /api/dhc/emotion │ └───────────▲───────────────────┘ │ HTTP ┌────────────────────────────┴────────────────────────────┐ │ dhc-pet(本插件,独立加载) │ │ GET /api/pet/status 诊断:三层各自是否在线 │ │ POST /api/pet/sync 强制把当前情绪推给桌宠 │ │ POST /api/pet/event 摸头/戳/表扬 → 回写 mcore 情绪 │ │ POST /api/pet/chat 对话(带 Hindsight 长期记忆) │ └────────────┬───────────────────────────┬────────────────┘ │ HTTP │ HTTP ┌────────────▼─────────────┐ ┌──────────▼─────────────────┐ │ dsh-pet │ │ Hindsight daemon │ │ POST /dsh-pet-7340/ │ │ 127.0.0.1:9077 │ │ broadcast?pet=main │ │ /memories /memories/recall│ └──────────────────────────┘ └────────────────────────────┘ ``` ## 安装 1. 装渲染层(另一个包,本仓库不打包它): ``` dsh plugin --profile add dsh-pet ``` 2. 装 mcore(本仓库)。`cordis.patch.yml` 已经同时挂上 `dhc-core` 与 `dhc-pet`, 不需要额外操作。 3. 本机记忆 daemon(可选但推荐): ``` uvx hindsight-embed@latest daemon --profile coding-agent start ``` 没起 daemon 时插件照常工作,只是 `/api/pet/chat` 没有长期记忆,情绪/气泡功能不受影响。 ## 配置 全部走环境变量,不引入配置文件(与 mcore 主程序同一约定): | 变量 | 默认 | 说明 | |---|---|---| | `MCORE_API` | `http://127.0.0.1:/api/dhc` | mcore API 基址 | | `DSH_PET_BASE` | `http://127.0.0.1:/dsh-pet-7340` | dsh-pet 路由前缀 | | `DHC_PET_ID` | `main` | 操作哪一只桌宠(对应 dsh-pet 配置里的 `pets[].id`) | | `DHC_PET_SYNC_MS` | `15000` | 情绪轮询间隔;`0` = 关闭自动同步 | | `DHC_PET_AUTOSAY` | `1` | 情绪变化时是否自动出气泡 | | `DHC_PET_PROMPT` | 内置一句 | 对话用人设(覆盖默认) | | `HINDSIGHT_URL` | `http://127.0.0.1:9077` | 记忆 daemon 地址 | | `HINDSIGHT_BANK` | `coding-agent::dsh` | 记忆库 | | `HINDSIGHT_TIMEOUT` | `8000` | 单次记忆请求超时(ms) | ## 接口 ### `GET /api/pet/status` 一次看清三层状态,排障先看它: ```json { "ok": true, "plugin": { "name": "dhc-pet", "version": "0.1.0" }, "pet": { "id": "main", "base": "http://127.0.0.1:3080/dsh-pet-7340" }, "mcore": { "api": "http://127.0.0.1:3080/api/dhc", "online": true, "emotion": { } }, "memory": { "ok": true, "status": "healthy", "bank": "coding-agent::dsh" }, "sync": { "intervalMs": 15000, "autoSay": true, "lastPushAt": 0, "bridgeErrors": 0 }, "routes": ["/api/pet/status", "..."], "errors": [] } ``` ### `POST /api/pet/sync` 把当前情绪推给桌宠。 - **默认强制**投喂(人在面板上点「同步」就是想立刻看到话)。 - `?force=0` 走去重路径:文案与上次相同时 `skipped: "unchanged"`,不投喂。 定时任务/外部巡检用这个,避免刷屏。 ```json { "ok": true, "line": "心情不错", "forced": false, "skipped": "unchanged" } ``` ### `POST /api/pet/event` ```json { "type": "pet", "note": "摸了三下" } ``` `type` 只接受 mcore 已有的十个触发器:`praise` `criticism` `success` `failure` `share` `demand` `poke` `pet` `talk` `learn`。**不在这里自造词表**——情绪的唯一持有者是 mcore, 本插件只做转发,避免两处定义漂移。 ### `POST /api/pet/chat` ```json { "text": "今天累不累" } → { "ok": true, "reply": "...", "recalled": 3, "retained": true } ``` 流程:Hindsight 召回 → 拼进 system prompt(并明确标注「是过去的记录,可能过时,不要当当前事实复述」) → `ctx.llm` 生成 → 写回 Hindsight(`document_id` 按天固定,重复写是覆盖不是堆垃圾)→ 投喂 dsh-pet 显示。 ## 冒烟测试 ```bash node dsh/pet/smoke.mjs ``` 真实打本机 daemon,不 mock:健康检查 → 召回 → 写入 → 再召回验证。daemon 不在线时退出码 1。 ## 测试(三支,各管一段) ```bash npm run test:pet # 路由逻辑:mcore/dsh-pet 都是桩,daemon 故意离线验降级 npm run smoke:pet # 记忆客户端:真打本机 daemon(健康/召回/写入/再召回) npm run test:pet:e2e # 记忆往返:真 daemon + 桩 LLM,验「召回→生成→写回→再召回」 npm run test:pet:integration # 真机集成:**真 mcore 本体** + 真 dhc-pet 同进程共存 ``` `test:pet:integration` 是最有说服力的一支——它把 mcore 真的 `apply` 起来(注册 64 条 `/api/dhc` 路由), 再把 dhc-pet 挂在**同一个 webServer** 上,然后经真 HTTP 验证: ``` 1) 真 mcore apply 成功,注册 64 条 /api/dhc 路由 2) 真 dhc-pet apply 成功,注册 4 条 /api/pet 路由 4) pet/sync → ok=true line="心情超好,想蹦跶" ← 方向一:mcore 情绪 → 桌宠气泡 5) sync?force=0 → skipped=unchanged;气泡数不变 ← 去重生效 6) pet/event {type:'pet'} → mcore 情绪已变化 ✓ ← 方向二:桌宠互动 → mcore 情绪 7) 摸头应答气泡已投喂 ✓ 8) 非法 type → 400;mcore 情绪未被污染 ✓ ``` 用独立的 `DSH_HOME` 临时目录隔离状态,**不会碰你真实的 `~/.dsh/persona-core.json`**。 ## 已知边界 - **不改 dsh-pet 源码**:它是独立发布包,改它会被升级覆盖。所以 dsh-pet 自己的 `/dsh-pet-7340/chat`(本地 5 轮记忆)仍然存在,只是**这条对话不走它**——走 `/api/pet/chat`。 - 气泡投喂不带频率限制(与 dsh-pet 的 `broadcast` 口径一致):调用方自己负责别刷屏。 本插件的自动同步按「文案变化」去重,只是最低限度的自我保护。