# dsh-feiyu-mood | 鱼的心情 > 给 AI 伙伴一个**会自己判断、你看得见**的心情。 > > 不是关键词硬猜,也不是随机数 —— 每轮聊完,用 DSH 自己的模型判一次"这一轮它的心情往哪走", > 会起伏、也会自己慢慢回稳,像活人。右下角挂着一个小挂饰,点开就能看见它此刻什么心情。 > **先看三行** > - 需要 **DSH ≥ `0.1.7-rc.1`**;版本不满足会被内核**静默跳过**(装了跟没装一样,不报错) > - 每轮判断 = **一次很短的模型调用**(一天几十轮也就几分钱);嫌贵可以在设置里关掉 > - 装完**必须重启一次** DSH(插件在 bundle 层组装) --- ## 一、它是怎么"有心情"的 ``` 你说一句话 ↓ 它回完这一轮(turn-stopping) ↓ 插件把「你说的 + 它回的」拿去问模型:这一轮它心情往哪走? ↓ 模型回来四个东西:心情涨跌(moodDelta) + 七根情绪各涨多少 + 一句理由 + 这次判断有多确定(confidence) ↓ 心情值改动、记进时间线;**同一次变化只说一次**,把「刚才心里那一下」带给它 ``` **关键点:说心情走的是 `systemPrompt.context`**(系统提示里单独一段), 不是改系统提示本身 —— 所以**不会破坏 DSH 的前缀缓存**,聊得再久也不会因此多花钱。 **设置页能直接看到那句话**:打开「鱼的心情」,「它会听到的那句话」那一块会告诉你现在是它会不会听到、 听到的是哪一句(预览 / 实际说出去的原文 + 时间)。 **一次变化只说一次**:这句话进了对话就留在历史里,下一轮它照样看得见, 重复说一遍只会变成背景音、把它的口气定死。另外判断没底的(`confidence` 低于门槛) **只记进后台,不进它的嘴** —— 宁可不说,也别让一句猜的话借它的嘴出去。 ## 一、设置页左上角:「检查更新」 点一下就去本插件自己的仓库比版本: | 看到 | 意思 | |---|---| | 已经是最新版 | 本机和仓库一样 | | 仓库里已经有 vX.Y.Z 了 | 有新版,下面直接给更新命令(可复制) | | 暂时查不到(原因) | **没连上**,不代表没问题 | 只检查,不装不删。查一次记 6 小时,点按钮会绕过缓存重新查。 ## 二、判断口径:谁在说话,决定怎么判 同一轮对话,"是它来找你"和"它被派去干活",该判的东西完全不一样。 | 这一轮是谁发起的 | 内部标记 | 判什么 | |---|---|---| | **你本人在说话** | `user` | 你这话怎么影响它(心疼/开心/吃醋……) | | **它自己主动来找你** | `speak-up` | 它自己的心意:想你的甜、惦记你的心焦、说上话的轻快 —— **不算干活** | | **定时任务叫它干活** | `bili-duty-scan` | 它自己干活时的心情:兴致勃勃、有点不情愿、白跑一趟的扫兴 | | 宿主每轮塞的上下文 | `runtime-context` / `time-context` | **直接跳过**,不当成"谁说的话" | > 为什么分这么细:判错口径会得出完全相反的心情。 > 比如"它自己来找你"被当成"被叫起来干活",理由会写成「又被叫起来干活」——明明是它想你了。 另外两条规矩: - **无变化的回合不记账**:判出来心情和七根情绪都没动,就不写进时间线(记录里只留真有过波动的) - **心情下降只能因为心疼/担心/它自己难过**,绝不许因为"你惹它生气" ## 三、它会"忘"吗(衰减) 不会断崖,是慢慢回稳: | 东西 | 怎么变 | |---|---| | 心情值(0–100,基线 70) | 没情绪时向基线回落,**半衰期约 3 小时** | | 七根情绪(开心/踏实/甜蜜/心疼/担心/难过/吃醋) | 向 0 衰减,**半衰期约 90 分钟** | | 心情下限 | 默认 0(不设底线);可以在设置里抬到 30,免得掉太低 | 举例:它被夸,`开心 +6` → 3 小时后大约剩 +3 → 6 小时后剩 +1.5,慢慢化掉。 ## 适配哪个 DSH 版本(不用操心) 这个插件**跟着 DSH 一起更新**:作者这边跑的就是最新版的 DSH,**最新版插件永远是给最新版 DSH 写的**。 所以看到「不适配 / 不支持」之类的提示,基本都是**装到了旧版本** —— 升级到最新版、重启一次 DSH 就好。 真遇到新版对不上(比如 DSH 刚升级、插件还没跟上),提个 issue,作者会跟着改。 当前实测对照:插件 **0.7.3** ↔ DSH **0.2.1-rc.3**(2026-10-26) ## 四、装 在 DSH 里:**设置 → 插件 → 安装**,填下面这一行;或者命令行: ``` dsh-feiyu-mood ``` ```bash dsh plugin --profile desktop add dsh-feiyu-mood ``` > 也可以在 npm 上直接看到这个包(含历史版本): > 上面那条要是碰到网络问题(npm 抽风、或者想固定某一次的代码快照),可以改用 tarball 直链,不用 git: ```bash dsh plugin --profile desktop add https://codeload.github.com/Yuuyuko-uu/dsh-feiyu-mood/tar.gz/refs/heads/main ``` > 也发布到 npm 了:`dsh plugin add dsh-feiyu-mood`。 > ⭐ 最省事的一条:把仓库链接贴给你自己的 DSH,说「**帮我装这个插件**」。 装完 **必须重启一次 DSH**,然后进 **设置 → 鱼的心情**。 ### 装完起不来?先看这个 如果 DSH 弹「The application could not start」,错误里有 `Unexpected token ''`、`is not valid JSON`、 `readProfileManifest` —— 那是 profile 的 `package.json` 被存成了 **UTF-8 带 BOM**。 **跟插件无关**:内容都是对的,只是开头多了三个看不见的字节,DSH 读它就崩。 **先找出来**(不同装法位置不一样,别猜 —— 真正的 profile 目录里同时有 `cordis.yml`、`cordis.patch.yml`、`package.json`;机器上别处那些同名的都不算): ```powershell Get-ChildItem C:\,D:\,E:\ -Directory -Filter profiles -Recurse -Depth 4 -ErrorAction SilentlyContinue | ForEach-Object { Get-ChildItem $_.FullName -Directory -ErrorAction SilentlyContinue | ForEach-Object { $p = Join-Path $_.FullName 'package.json' if ((Test-Path (Join-Path $_.FullName 'cordis.patch.yml')) -and (Test-Path $p)) { $b = [System.IO.File]::ReadAllBytes($p) $bom = ($b.Length -ge 3 -and $b[0] -eq 0xEF -and $b[1] -eq 0xBB -and $b[2] -eq 0xBF) "{0} BOM={1}" -f $p, $bom } } } ``` **输出里 `BOM=True` 的那一行,就是要修的文件**(标准安装在 `C:\Users\<你>\.dsh\profiles\<档名>\package.json`)。 去掉 BOM(路径换成上面那一行): ```powershell $p = "把上面 BOM=True 那一行的路径粘到这里" [System.IO.File]::WriteAllText($p, [System.IO.File]::ReadAllText($p), (New-Object System.Text.UTF8Encoding($false))) ``` 然后重启 DSH 就好,**数据一点没丢**。实在进不去时,那个错误框里的 **「Disable third-party plugins, back up profile patch, and restart」** 能先起来,再一个个开回去定位。 > ⚠️ 手动改 profile 里的文件,一律存 **UTF-8 无 BOM**。让 AI 帮你改时,别让它用 > `Set-Content -Encoding UTF8` 或 `Out-File -Encoding utf8`(Windows 自带的这两个默认**带 BOM**)。 ## 更新到最新版 **最省事**:把这个仓库的地址丢给你自己的 DSH,说「**帮我更新这个插件**」。装完**重启一次 DSH**。 也可以点 **设置 → 鱼的心情 最上面的「检查更新」** —— 有新版会提示,还能一键复制更新命令。 命令行(`--profile` 照你平时那个写,桌面端一般 `desktop`、网页端 `web`): ```bash dsh plugin --profile desktop remove dsh-feiyu-mood dsh plugin --profile desktop add dsh-feiyu-mood ``` > ⚠️ **必须先卸再装**:直接装可能拿到缓存里的旧副本,装完还是老的。 > ⚠️ 装完**重启一次 DSH**才会用新代码。 ### 我的设置会不会丢? **不会。** 设置存在 DSH 家目录(`%USERPROFILE%\.dsh\`)里,不在插件代码里;卸载只删代码: ``` .dsh\feiyu-mood\config.json (还有 state.json) ``` 所以卸载 → 重装,设置、心情值、心情时间线 都还在。 三件小事提醒: - **别用「重装 DSH」来更新插件** —— 那是两件事,重装可能动到 profile。 - **新版本新加的设置项**会用默认值(以前没这一项),想要自己的值就再填一次。 - 设置项改名或换单位时,旧值会按规则自动换算,不用你管。 ## 五、首次使用(三步) 1. **填称呼**:「TA 叫什么」(被关心的那个人,默认"用户",改成 TA 的名字)、「TA 自己叫什么」(有心情的那个人,默认"伙伴",改成你自己的叫法) —— 提示词和注入文案里**全部走这两个值**,改完就跟着变,不用改代码 2. **选认法、再绑**:设置页「会话绑定」页签最上面先选一种(**两种只能选一种**,不能同时开): - **会话模式**(默认,跟以前一样):给每一份心情挑会话 —— 只有这些会话里会判断和注入;绑在同一份上的几个会话**共用一份心情、一条时间线和每天的额度** - **工作区模式**:给每一份心情挑一个**工作区** —— 那个工作区下的**所有**会话都用这一份,新开的会话自动进来,不用一个个加 想要好几份心情(两个工作区两个伙伴)就点「+ 再加一份心情」,每份绑自己的会话或工作区、各过各的;只有一份时跟从前的行为完全一样 3. **聊两句**:回去看这一页,心情应该动了;右下角挂饰也会跟着变 ### 会话模式 / 工作区模式(二选一) | | 会话模式(默认) | 工作区模式 | |---|---|---| | 按什么认 | 你点名的**会话** | 那个**工作区**下的所有会话 | | 新开的会话 | 不会自动进来,要手动加 | **自动进来**,共用同一份心情 | | 设置页里 | 每份一个会话列表,能加能删 | 每份一个工作区下拉,选一次就够 | | 适合 | 一个工作区里有好几个伙伴,各聊各的 | 一个工作区就是一个人,不想每次新开会话都去加一遍 | 工作区怎么认:DSH 把会话存在 `~/.dsh/sessions/<工作区目录名>/<会话id>/`,所以**工作区标识就是中间那层目录名** (例如 `--C-Users-Administrator-Desktop-~9C7C~9C7C~7A9D-dsh--`)。设置页下拉**只列 `~/.dsh/sessions/` 下真实存在的目录** (DSH 自己写下的那个名字),不会凭路径再造一个 0 会话的重复项;可读路径用 `~/.dsh/storages/workspace.json` 里登记过的路径反查,查不到就直接显示目录名。 > 切回会话模式时,原来绑的会话还在,不用重新加。 > 同一份心情的 `id` 跟它绑了哪些会话无关:删会话、改名都不会换一份记录,所以**记录不会因为改绑定而"消失"**。 ## 六、设置页里每一项是干什么的 | 项 | 作用 | 建议 | |---|---|---| | **当前心情** | 五档表情 + 数值 + 标签 + 最后一条理由 + 时间 | 就看看 | | **重置到基线** | 把心情拉回基线、七根情绪清零、清空时间线 | 想重新开始的时候点 | | **TA 叫什么** | 写进判断提示词,理由里出现的就是这个名字 | 换成你自己的称呼 | | **TA 自己叫什么** | 同上,判断时"你是谁" | 换成你伙伴的名字 | | **按什么认这一份** | 会话模式 / 工作区模式,**二选一**(同时开必出 bug,所以只给你一个开关)。切换不动任何记录,切回来绑过的东西还在 | 一个工作区一个人 → 工作区模式;一个工作区好几个伙伴 → 会话模式 | | **会话绑定 / 工作区绑定** | 会话模式下每一份绑一组会话:绑在同一份上的会话共用心情、时间线、每天额度,不同份之间互不影响,下拉里是真会话(跳过归档和空会话)。工作区模式下每份选一个工作区:这个工作区里**所有**会话都归这一份,新开的自动进来 | 把平时跟 TA 聊天的会话(或工作区)按伙伴分好组 | | **这份叫什么** | 只用来在设置页区分几份,不写进提示词、不会成为称呼(称呼在「判断与注入」页签) | 随便起,比如"大肥鱼"、"修路的" | | **判断用哪个模型** | 心情判断这一次小调用用哪个 provider / 模型。**留空 = 跟着当前会话的模型走**;想更准就指到更强的,想省钱就指到便宜的 | 判断出错多 → 换强一点的;嫌贵 → 换便宜的 | | **每轮判断心情** | 总开关。关掉 = 完全不判断、不改数值、不花判断的钱 | 想省钱、或者不想记录的时候关 | | **心情怎么告诉它** | 三选一:
· **不告诉它** —— 完全不受影响,挂饰照常显示
· **只说心情** —— 给一句「此刻心情怎样」
· **说它刚才那件事**(默认)—— 把它自己刚才心里那句话带进去,每轮都不一样,最不像被安排 | 想完全只看不管 = 不告诉它;怕它被一句状态定死 = 说它刚才那件事 | | **可信度门槛** | 判断模型自己标的分,低于它只记后台、不进它的嘴(默认 60)。调高更保守 | 觉得它"照着猜的话说"的时候调高 | | **基线心情** | 没情绪时回落到多少(30–100) | 想要它平时更开朗 → 调到 75~80 | | **心情下限** | 最低能掉到多少(0–100),0 = 不设底线 | 怕它太低 → 设 30 | | **完整记录** | 最近 40 条:时间 / 心情值 / 变化 / 理由 | 回看心情是怎么走到今天的 | **所有设置改完立刻生效**,不用重启、不用改文件。 ## 七、右下角的挂饰 - 点一下:展开面板 —— 五档表情、心情值、七根情绪各多少、完整时间线 - **按住可以拖**,拖到你觉得舒服的位置 - **两个动作是分开的**: · 点**外面那个东西**(形象图,或者缩成的小圆)= **开关面板**,看心情和记录;形态不变 · **面板右上角那个钮** = 只管**切换外面显示的形态**:大肥鱼「–」↔ 小圆「▢」 - 缩成小圆之后:**照样能拖**;点一下照旧打开面板、记录照样看;状态会记住,下次进来还是那个样子 - 五档表情跟着心情换: | 心情值 | 表情 | |---|---| | ≥ 80 | 欢喜 `face-great.png` | | 62–79 | 开心 `face-good.png` | | 42–61 | 一般 `face-ok.png` | | 25–41 | 心疼 `face-worry.png` | | < 25 | 难过 `face-sad.png` | ## 八、常见问题 **心情一直不动?** 先去设置页「完整记录」看最后一条是什么时候 —— 三种可能:① 会话/工作区选错了(工作区模式下,那个工作区里的会话才归这一份)②「每轮判断心情」关了 ③ 这几轮真的没变化(无变化不记账)。 **理由写得像"被叫起来干活",但它明明是来找我说话的?** 判断按「这一轮是谁发起的」分三种口径:**你自己主动搭话** / **定时任务叫你干活** / **对方在跟你说话** —— 装着 `speak-up` 之类的主动搭话插件也不会被误判成干活。 **"关掉判断"和"关掉告诉它"有什么区别?** 判断 = 算不算这一次心情(花钱那步);告诉它 = 算出来的心情要不要说给它听。两个可以分开。 **换了伙伴 / 换了名字?** 设置页改两个称呼就行,不用重装。 **改完绑定,心情/记录好像"全没了"?** 0.7.0 修的就是这个:以前在设置页删/加会话,会把那一份的 `id` 弄丢(变成空或 `__default__`),宿主就去读另一份(空的)记录 —— **真数据一直在 `state.json` 里**。现在改绑定不动 `id`。 如果之前已经错乱了:打开 `/feiyu-mood/config.json`,把 `slots[0].id` 填成 `state.json` 里 `moods` 下面那个键(比如 `4d6beaf3-…`),重启 DSH 就接回来了。 ## 九、换掉示例图片 `assets/` 里就是那五张表情 + 一张形象图,**换成你自己的图,文件名保持不变**就能用: ``` assets/face-great.png 448×352 建议 assets/face-good.png assets/face-ok.png assets/face-worry.png assets/face-sad.png assets/feiyu.png 挂饰用的形象图(正方形最好是 PNG 透明底) ``` ## 十、数据在哪(不上传任何地方) `/feiyu-mood/`: | 文件 | 内容 | |---|---| | `state.json` | 当前心情、七根情绪、完整时间线 | | `config.json` | 上面那些设置 | | `diag.log` | 判断日志:哪一轮、判成什么、为什么没记账 | 全部在你自己电脑上,插件不联网、不往任何服务器传东西(判断那一步走的是你自己的模型 provider)。 ## 十一、许可 [Yuuyuko-uu 插件许可 1.0](./LICENSE):允许使用、修改、商用; 再分发时要在 README 第一屏注明原仓库和原作者;禁止把本项目说成自己的原创。 这份许可不是 OSI 认证的开源许可,用之前请读一遍全文。