@ssamurias/dsh-fish 0.8.9 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +64 -10
- package/CHANGELOG.md +129 -2
- package/LICENSE +7 -0
- package/README.md +69 -17
- package/RELEASE-NOTES-0.8.0.md +87 -0
- package/RELEASE-NOTES-0.8.1.md +93 -0
- package/RELEASE-NOTES-0.8.2.md +57 -0
- package/RELEASE-NOTES-0.8.3.md +71 -0
- package/RELEASE-NOTES-0.8.4.md +47 -0
- package/RELEASE-NOTES-0.8.5.md +244 -0
- package/RELEASE-NOTES-0.8.6.md +224 -0
- package/RELEASE-NOTES-0.8.7.md +202 -0
- package/RELEASE-NOTES-0.8.8.md +224 -0
- package/RELEASE-NOTES-0.9.0.md +267 -0
- package/RELEASE-NOTES-0.9.1.md +296 -0
- package/RELEASE.md +151 -0
- package/THIRD-PARTY-NOTICES.md +3 -0
- package/lib/ask.js +18 -5
- package/lib/away.js +7 -2
- package/lib/browse.js +1 -0
- package/lib/capture.js +16 -1
- package/lib/channels.js +53 -13
- package/lib/client.js +145 -56
- package/lib/comment.js +74 -0
- package/lib/compact.js +71 -2
- package/lib/curiosity.js +6 -2
- package/lib/derive.js +21 -8
- package/lib/desk.js +4 -2
- package/lib/dream.js +3 -0
- package/lib/dreamtable.js +28 -2
- package/lib/drive.js +58 -9
- package/lib/freewake.js +21 -2
- package/lib/home.js +141 -24
- package/lib/inbox.js +7 -2
- package/lib/index.js +8 -12
- package/lib/interest.js +26 -4
- package/lib/log.js +22 -1
- package/lib/look.js +25 -5
- package/lib/note.js +35 -13
- package/lib/notify.js +2 -0
- package/lib/observe.js +22 -7
- package/lib/outing.js +2 -0
- package/lib/owner.js +5 -2
- package/lib/persona.js +18 -3
- package/lib/proactive.js +78 -18
- package/lib/say.js +104 -58
- package/lib/scheduler.js +162 -60
- package/lib/selfcheck.js +2 -3
- package/lib/selfdoc.js +8 -9
- package/lib/selfupdate.js +183 -41
- package/lib/settings.js +33 -2
- package/lib/status.js +31 -3
- package/lib/store.js +14 -2
- package/lib/tenant.js +12 -0
- package/lib/turns.js +46 -4
- package/lib/update.js +14 -0
- package/lib/upgrade.js +23 -4
- package/lib/voices.js +2 -0
- package/package.json +5 -2
- package/scripts/fix-legacy-link.mjs +254 -0
package/AGENTS.md
CHANGED
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
node --test
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
当前基线 **
|
|
72
|
+
当前基线 **1512 个**,独立进程跑 `node --test` 应全绿。任何一条红都不许提交——包括看起来"不是我弄的"那条。
|
|
73
73
|
|
|
74
74
|
按环境挑跑法:
|
|
75
75
|
|
|
@@ -99,7 +99,7 @@ CI 也跑同一套(`.github/workflows/test.yml`,Node 20 / 22 / 24 各跑一
|
|
|
99
99
|
|
|
100
100
|
```
|
|
101
101
|
POST /dsh-fish/say
|
|
102
|
-
{ "text": "…", "channel": "qq-group:987654", "scene": "group", "speaker": "张三" }
|
|
102
|
+
{ "text": "…", "channel": "qq-group:987654", "scene": "group", "speaker": "张三", "title": "摸鱼群" }
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
| 字段 | 必填 | 说明 |
|
|
@@ -108,13 +108,23 @@ POST /dsh-fish/say
|
|
|
108
108
|
| `image` | 否 | base64 图片 |
|
|
109
109
|
| `channel` | 否 | 渠道标识,桥自己起名。**同一个名字 = 同一间房** |
|
|
110
110
|
| `scene` | 否 | `desk`(默认,等于不传)/ `private` / `group` |
|
|
111
|
-
| `
|
|
111
|
+
| `room` | 否 | `house`(并进书房)或 `channel`(另开一间)。不传时私聊回书房、群聊另开 |
|
|
112
|
+
| `speaker` | 否 | 这句话是谁说的。**任何场次都写进正文前缀**,不再只限群聊 |
|
|
113
|
+
| `guest` | 否 | `true` = 外客(群友私聊这类)。标明「不是他」,不算他来过、不涨轮数、不进书房桶 |
|
|
114
|
+
| `title` | 否 | 侧栏显示名(群名、昵称)。不传才回落到 channel 键 |
|
|
112
115
|
|
|
113
116
|
路由规则(`lib/channels.js` 的 `resolveChannel`):
|
|
114
117
|
|
|
115
118
|
- **不传 `channel`** → 家里那条会话。观测台、侧栏、老桥的行为一字不变。
|
|
116
|
-
- **`
|
|
117
|
-
- **`scene: '
|
|
119
|
+
- **`room: 'house'`** → 并进家里那条会话,场次照记(群聊仍记 `group`)。
|
|
120
|
+
- **`scene: 'private'`** → 默认**仍进家里那条会话**("QQ 私聊和 DSH 对话融合"那个选项)。要每人一间,传 `room: 'channel'`。
|
|
121
|
+
- **`scene: 'group'`** → 默认按 `channel` 自建/复用一间房(记在 `channels.json`),cwd 仍是她的屋子,身份、工具面、白板都照旧——**还是同一个人,只是换了个房间说话**。想让所有群并进书房,传 `room: 'house'`。
|
|
122
|
+
- **`guest: true`** → 房间照开(如果 `room` 要求),但这条不算他来过:不写 `seen:`、不 `bumpTurns`、不触发轮换;正文标「有个不是他的人跟你说话」,她不会把群友当成主人。
|
|
123
|
+
|
|
124
|
+
**常见布局都由桥表达,插件不写死:** 全部并进书房(不传 `channel`,或 `room:'house'`);每群一间(`channel:'qq-group:<群号>'` + `group`);群友私聊每人一间(`channel:'qq:dm:<QQ号>'` + `private` + `room:'channel'` + `guest:true`);群友私聊进书房但标身份(`private` + `guest:true` + `speaker`);只有 @ 她才进(桥侧过滤,不投递就不建房)。
|
|
125
|
+
|
|
126
|
+
**群房会轮换。** 默认一间群房用满 **7 天**换新的(`config.rooms.groupRotateDays`,`0` = 不换):旧房改名成「… YYYY-MM-DD 之前」留在侧栏,新房从当天重新算天数。200 条上下文对热闹的群不够用,所以按天而不是按轮数。
|
|
127
|
+
|
|
118
128
|
|
|
119
129
|
启动前可以先探一句:
|
|
120
130
|
|
|
@@ -127,13 +137,31 @@ GET /dsh-fish/whoami
|
|
|
127
137
|
|
|
128
138
|
**桥那边怎么实现是桥的事**;我们这边只保证上面这几个字段能收、能落到正确的地方。
|
|
129
139
|
|
|
130
|
-
### 7.2
|
|
140
|
+
### 7.2 四个配套约定(改桥之后的正确性全押在这四条上)
|
|
131
141
|
|
|
132
142
|
1. **场次要进事件流**。`validateEvent` 现在接受可选 `scene`(非 `desk` 才落库,纯加法,不升 `EVENT_SCHEMA_VERSION`)。桥注入 `user/message` 时把 `scene` 写进 **`source.scene`**,`classifyMessage` 才会认出来(`lib/turns.js`)。
|
|
133
|
-
2.
|
|
134
|
-
3.
|
|
143
|
+
2. **外客不动生命体征**。`seen:`、`heard`、`bumpTurns`、会话轮换只由 desk/private 且非 `guest` 触发;群聊与群友私聊一条都不写。否则群里一天几百句,冷落检测永远不会触发——他一周没露面,面板还显示"今天聊过"。
|
|
144
|
+
3. **外来场次必须带说话人前缀**。`lib/say.js` 对 `group` 与 `guest` 都用 `speaker` 拼 `某某在群里说:…` / `某某说:…`。不拼的话,群里三个人的话在她看来跟一个人连说三句一模一样,她会把三个人的观点拼成一个"他"。外来文本统一过 `lib/guard.js` 的 `sanitizeForeign`。
|
|
145
|
+
4. **桥不要用宿主的 `source.form`**。`snapshot`、`notice`、`catalog`、`instructions`、`recall` 是宿主前端的保留词表,`classifyMessage` 见到就当上下文,不算人(`MACHINE_FORMS`)。转述人说的话,要么不带 `form`,要么用 `relay`。
|
|
146
|
+
|
|
147
|
+
### 7.3 对话靠工具发出去的部署
|
|
148
|
+
|
|
149
|
+
先问一句:**她写的正文会被插件自动发出去吗?** 会,就什么都不用填,只认正文的默认行为是对的。不会,也就是正文只留在会话里、要调工具才发得出去,才填下面这几项。都不认具体插件,工具名由配置给。
|
|
150
|
+
|
|
151
|
+
- `proactive.sendTools`:发送工具的名字,也要放进 `tools.allow`(工具面收窄开着时,没放行她调不到)。填了之后,只有这些工具调成功才算她开了口(记 `proactive-turn:`,占额度,不折叠),代码模式(run_code)里调的也算;只写正文算没开口。处境和身份段会照实写用这个工具、正文发不到聊天里。工具自己返回「没发出去」但没有报错的,这里认不出来。
|
|
152
|
+
- `proactive.idleCountsSeen`:`true` 时 `seen:` 也算打断安静、也算「他接了」。她靠工具回话、正文不进事件流时要开。它要有 `seen:` 可认:走 `/say`,或者 `source.kind` 不是 `user`,或者带 `clientTimeZone`;`{kind:'user'}` 不带时区的桥要自己写。代价是他在这台机器上和别的 agent 说话也算,所以默认关。
|
|
135
153
|
|
|
136
|
-
|
|
154
|
+
还有一项和工具无关:`proactive.foldSilent` 是 `false` 时,没开口的一轮只记账、不折。折叠会改历史,上下文很大、靠缓存省钱时可以关。
|
|
155
|
+
|
|
156
|
+
插件知道她在忙时(比如在打一局游戏),挂一个事件就行,不用知道 dsh-fish 的包名和路径:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
ctx.on('dsh-fish/busy', (sessionId) => stillPlaying(sessionId) ? true : undefined)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
定时叫醒和主动回合投递前都会问一声。监听要同步返回,只有 `true` 算忙;不忙返回 `undefined`、`null` 或 `false`,返回别的值会挡住后面的插件,返回 Promise 按不忙算。忙的标记卡住时她就一直不被叫醒,所以结束时记得放开。不挂也没事,调度器自己知道家里那条会话正在跑的那一轮。
|
|
163
|
+
|
|
164
|
+
### 7.4 另一条老路:工具白名单(仍然有效)
|
|
137
165
|
|
|
138
166
|
桥如果是以插件形式装进来、暴露工具给她的,仍然可以在 `config.tools.allow`(设置页「插件能力白名单」)里放行工具名。qq-bridge 默认要放行的是:
|
|
139
167
|
|
|
@@ -161,6 +189,32 @@ qq_send_message, qq_get_unread_messages, qq_reply
|
|
|
161
189
|
- [ ] 三个依赖字段还是 `{}`
|
|
162
190
|
- [ ] 没有新增人格设置入口
|
|
163
191
|
- [ ] 新输入口都过了 `guard.js`
|
|
164
|
-
- [ ] `node --test`
|
|
192
|
+
- [ ] `node --test` 1512 全绿
|
|
165
193
|
- [ ] 界面文案没有「他」「四道门」「三道门」
|
|
166
194
|
- [ ] 改了 `EVENT_SCHEMA_VERSION` 的话,`CHANGELOG.md` 里写了迁移说明
|
|
195
|
+
- [ ] 没动包名;真要动,先看下面「包名与装法」那节
|
|
196
|
+
- [ ] 动了升级 / 迁移脚本(`scripts/fix-legacy-link.mjs`、`lib/selfupdate.js`)的话,`README.md` 的升级表与 `RELEASE-NOTES-*.md` 同步改了
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 包名与装法(0.8.10 起,改名踩过一次,别再踩)
|
|
201
|
+
|
|
202
|
+
包名是 **`@ssamurias/dsh-fish`**(带 scope 的全名)。装法看 `README.md` 的「安装」,这里只列动代码时容易破坏的四条:
|
|
203
|
+
|
|
204
|
+
1. **`lib/client.js` 里 `__ModuleLoader__.load({ id })` 必须等于 `package.json` 的 `name`**,不是短名。client-modules 按 loader 条目名(完整包标识)解析浏览器包,名字对不上时客户端那半**静默不加载**——宿主照常跑、设置页空着,看起来像没装上。`test/client.test.mjs` 直接从 `package.json` 读 `name` 比对,别把那条断言改成写死字符串。
|
|
205
|
+
2. **`cordis.patch.yml` 的 `id` 保持短名 `dsh-fish`、`name` 写全名**(与 `@goodandready/dsh-voice` 一致)。`id` 变了会连带 client bundle 的 URL 对不上;`name` 写短名则 import 失败、直接崩在 web boot。
|
|
206
|
+
3. **别删升级脚本里的 normalize 那一步**(`lib/selfupdate.js` 的 `normalizeScript()`,安装脚本第 5/6 步)。0.8.9 之前装的 profile 里旧键还在,不清掉就会同时有两条鱼、两条 insert 撞一个 id,启动报 `duplicate factory registration`。
|
|
207
|
+
4. **`scripts/fix-legacy-link.mjs` 必须三种依赖写法都认**:源码目录 `link:`、`file:` 装的 tgz、`@ssamurias/dsh-fish@x.y.z` 版本号。版本号那条是 issue #43 的根因——照更新说明用 `dsh plugin add` 升上来的人,profile 里留下的就是版本号;脚本过去只认前两种,一句「没有老依赖,跳过」退出 0,旧键与旧 `bundles` 条目原封不动。改它之前先跑 `test/fix-legacy-link.test.mjs`(`migrateOne()` 是给它直接测的)。
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 发版
|
|
212
|
+
|
|
213
|
+
完整步骤(发布前自检、push、npm publish、tag、GitHub Release、发布后验证、回滚)写在 **`RELEASE.md`**,动手前通读一遍。三条不能省的顺序:
|
|
214
|
+
|
|
215
|
+
1. `node --test` 全绿、`npm pack --dry-run` 清单对(见 §6)。
|
|
216
|
+
2. 先推代码,再发 npm:**npm 成功之后才打 tag / 建 Release**——npm 失败时不留悬空 tag。
|
|
217
|
+
3. 发完核对 `npm view @ssamurias/dsh-fish version dist-tags`,再去回 issue。
|
|
218
|
+
|
|
219
|
+
本机约束另见 `D:\deepseekagent\避坑指南.md` 第 1 节(profile 的 `bundles` 与 `dependencies` 必须一一对应)与第 3 节(运行中替换已加载包会 `ERR_PNPM_EPERM`、`minimumReleaseAge` 会回滚刚发布的版本、`desktop` profile 被应用独占)。
|
|
220
|
+
|
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,134 @@
|
|
|
1
|
-
## 0.
|
|
1
|
+
## 0.9.1 — 2026-11-06
|
|
2
|
+
|
|
3
|
+
社区报的 issue #32–#38、#41–#43(十条,@BBleae)加用户直接反馈的几条(换房问话每轮回弹、B 站评论看不到、艾特不出来、cookie 观感),另外合入四个社区 PR(#39、#40、#44、#45)。每一条都在本地复现过,都是我们这边的错,逐条修掉。
|
|
4
|
+
|
|
5
|
+
- **聊天行把时间线刷满,`idleWakes` 也被清零(#32)。** 她答你的话(`lib/turns.js` 打的 `uncommitted` 标)以前和「她自己认下的判断」混在一起数:一次醒来撞上你连说几十句,时间线 40 条全是「说了:…」,那一块也从「在发呆」变成「干了事」。现在单列成「聊天」:不进 `said`、不算这一轮做了什么、时间线上折成一行「聊了 N 句」,面板上的 `说 N` 也把聊天行减掉、另起一个 `聊天 N`。**事件流一个字节没动**,只是读法变了。
|
|
6
|
+
- **「她记下 N 条」和「记下的事」永远对不上(#32)。** 那个数字是 `countEvents().real`,本来就含你说话、她读到别人的说法、开局那份起点;文案只写「她记下」,看起来就像「她写了 N 条」。`real` 的定义**不改**(动了会牵一大串派生数字,测试也逐字段钉着返回形状),改成把话说清楚:两处文案各加一句口径说明(鼠标停上去能看见)。
|
|
7
|
+
- **当前会话被归档时,认回来的是最旧那条(#33)。** 宿主建会话是 `sessionIds: [新id, ...旧的]`,往**前**插;`pickLiveSession` 却取 `live[live.length - 1]`,注释还写着「末尾即最近那条」——方向反了。改成取 `live[0]`,注释一起改,测试里的假宿主也调成同样的方向。提醒一句:你在侧栏拖动过顺序时 `live[0]` 未必最新,那要问 `sessionController.list()`;这次只修明显反了的方向。
|
|
8
|
+
- **群聊那轮也写 `seen:`,冷落检测失灵(#34)。** `lib/capture.js` 里那条「他在场」的记账只看在不在叫醒窗口里,不看这句话是在哪儿说的:群里她调一次 `growth_commit` 就多一条 `seen:`,群友说一百句也算他来过,于是「你多久没说话」永远不触发。现在先查 `channels.json`,群房一律不记。窗口外那条兜底写法保留——删掉会让换房、定时任务那几次醒来失去在场证据(这也是 issue 作者试删后红了 4 条测试的原因)。
|
|
9
|
+
- **卡片里手打的答案认不出来,原文还落进日志(#35)。** 宿主回的是 `{id, selected: [], custom: '…'}`,`lib/ask.js` 以前只看 `selected[0]`,空数组于是取到 `undefined`,一律判成 `NO_MATCH`。改用 `askinchat.js` 早就写对的 `picked()`(非空 `selected` 优先,否则退回 `custom`)。顺带把日志里的回执原文换成形状摘要——只留 id、选了几个、自定义文本多长,你手打的私事不再落到日志文件里。
|
|
10
|
+
- **排队叫醒被上一轮的 `turn/end` 收走(#36)。** `watchTurnEnd` 认会话不认回合:手动叫她一次时她常常正开在别的一轮里,宿主的 `followup` 会把我们这条排进下一轮,当前那一轮先 `turn/end`,处境段当场被清,真醒的那一轮反而什么都没有。现在要求「监听挂上之后先见到本条会话的 `turn/start`,之后的 `turn/end` 才算」。拿不到事件总线(单测 / 老宿主)时退回老行为,靠 `waitIdle` 兜。
|
|
11
|
+
- **Windows 上 `withFileLock` 遇 EPERM 直接抛(#37)。** 文件正在被删除时 `open(..., 'wx')` 返回 EPERM 而不是 EEXIST,于是这一次换会话就失败。现在 EPERM 走独立重试分支、受 `timeout` 约束,且只认 win32——POSIX 上 EPERM 是真没权限,重试没意义。**不能并进 EEXIST 分支**:那里 stat 失败就判 stale 再 continue,不看超时,真的是权限错误时会死循环。
|
|
12
|
+
- **带 BOM 的 JSON 被当成坏文件改名(#38)。** `readJson` 直接 `JSON.parse`,BOM 抛 SyntaxError 就进坏文件分支,**内容完好的文件**被改名成 `.corrupt.<时间>`:`config.json` 退回全默认、`owner.json` 变 null、`home.json` 新建一条会话,用户以为自己的改动丢了。现在读之前先剥掉开头那一个 `\uFEFF`;`lib/upgrade.js` 里自己那份 `readJson` 同样的坑,一起修。
|
|
13
|
+
- **换房那句「想给下一个房间留一句话吗」每回一句都弹(用户报,2026-11-06)。** `rotateTalkSessionOnce` 先问话、再建会话:问话那条 `sc.prompt({mode:'queue'})` 投进的是她**此刻正在用的旧会话**,也就是你眼前的对话窗口。要是随后 `sc.create` 抛错或宿主没给 id,函数当场返回、`turns` 不归零,下一轮结账又到点、又进来、又问一遍——你那边看到的就是「每回一句都弹这句」。修法两处:① 问话挪到**新会话建好之后**,换不成就不问;② 换失败记一笔 `rotateFailAt`,5 分钟内不再重试(`ROTATE_RETRY_MS`),免得每轮都去撞一次宿主。顺带把 `PLUGIN_RPC` 补上 `carry` 前缀——原来漏了,`carry-ask-*` 掉进 `unknown` 分支,每换一次会话就多一行「这条消息认不出来源」的日志。**注意**:这条跟「轮数设 0 = 永不换」无关,`rotateAfter > 0` 的守卫一直都在,0 根本进不来;真因是「换失败后无限重试」。
|
|
14
|
+
- **设置里那句「上下文占满后会自动换」是空头承诺。** `lib/client.js` 的 hint 原来这么写,代码里没有任何「上下文满了就换」的实现——设 0 的人会一直聊到宿主上下文撑不住、那一轮直接失败。文案改成说实话:0 = 永不换,撑不住就那一轮失败,不会自动换。
|
|
15
|
+
- **「多久看一次有没有人回复」是个空旋钮,评论永远看不到(用户报,2026-11-06)。** 这个设置(`comment.scanEveryMin`)从写下来那天起就没人读:全仓只有设置页读写和 `/comment` 回显,调度器一次都没用过。真正的扫描只发生在「她被叫醒的那一轮里顺便拼一句」——不叫醒就永远不扫,用户开了开关、设了 5 分钟也一条都收不到。现在 `tick` 每分钟看一眼到点没有(`repliesScanDue`),到点就扫,**扫完无论有没有都记一笔 `lastScanAt`**(不记的话每 30 秒重问一次 B 站);扫到新回复就投一条笔记进她的会话(`queueNote` + `deliverQueued`,跟回复量那边同一套投递)。设 0 仍然表示不主动问。
|
|
16
|
+
- **她醒着的时候没有「看我自己的评论区」这个动作(同一条反馈)。** `bili_look` 只有首页 / 搜索 / 接着看 / 看某一条,翻不到自己的评论区;`bili_speak` 回楼中楼又要 `parentRpid`,她手上没有,于是「知道有人回了,回不了」。新增 `bili_look what=replies`:读她最近发过的评论下面的楼中楼,**不受「已读过」标记限制**(她主动看就该看全),每行末尾给出 `[reply=… parent=…]`,回楼中楼要用哪个编号一眼可见。`LOOK_BRIEF` 与工具说明同步。
|
|
17
|
+
- **@ 艾特:昵称被改成下划线,等于 @ 一个不存在的人(用户报,2026-11-06)。** `mentionPrefix` 原来把昵称里的空格换成 `_` 再拼 `@`。真机抓到的真实 @ 评论(`content.members` 非空)证明 B 站是按昵称**原文**匹配的,换了下划线就认不出来。改成原样拼;昵称为空时仍然不拼(空的 @ 只是一串没人认领的字符),设置页 hint 补一句「要跟 B 站上显示的一字不差」。
|
|
18
|
+
- **只粘 cookie 保存一次,就把「要 @ 的 uid / 昵称」清空了(同一条反馈)。** 保存按钮原来无条件提交 `{mid, nickname}`,空串也照发;而 `saveOwner` 对空串是「写入空值」。用户只粘 cookie、没填那两格,存一次就把 `@` 的对象抹掉——表现就是「说了能艾特,其实艾特不出来」。现在三格各自只在非空时提交,全空直接提示「没东西可存」。
|
|
19
|
+
- **cookie「填完就消失」不是丢,是只上行不下行。** 接口从来不下发 cookie 原文(只给 `hasCookie` / `hasCsrf`),输入框保存后清空是设计。但原本文案只说「不再回显」,容易被读成「没存上」。补一句「空着不代表没存上,上面那行『已存…』才是凭据」。
|
|
20
|
+
- **顺带说清:看不到评论跟 cookie 无关。** `scanReplies` 用的是匿名客户端;真机实测带同一份 cookie 去读 `/x/v2/reply` 一样 `-412 request was banned`(同一台机器早些时候又能读通),是 B 站按 IP 的间歇风控,插件这边只做冷却退避。真要「看不到」的那种情况,先看设置里开关有没有开、再看日志里有没有 `-412`。
|
|
21
|
+
- **`her_say` 的「一天最多几次」是句空话(#41)。** 工具说明写着有上限,`writeSay` 读了配置却没用、也不数当天条数:开关关着、`maxPerDay=0` 时连写 8 次全成功。现在按 `proactive-say:<日期>:` 数当天条数,到上限就拒、并说明「明天再说,不是工具坏了」。**开关仍然不是闸门**——它管的是「要不要由系统替她开一轮」,工具本身一直在(这跟 README 里「关掉之后工具本身还在」一致)。
|
|
22
|
+
- **`her_say` 把成长坐标写死成 1/1(#41)。** 别的写入点都用 `deriveSelf` 的 `{day, stage}`,只有这里硬编码,于是 `consistency()` 会跟她早期的行错配对:阶段 1 少算一对、阶段 4 多算一对。改成跟日记同一套算法。
|
|
23
|
+
- **「`[说出去了]`」这个名字在骗人(#41)。** 那一步只是往她自己的流水里记一行,正文有没有落进对话取决于她这一轮写没写。回执改成 `[记下了]`,工具说明与人设里的那两段同步说清:「要让他看见,得你这一轮直接写出来」;「他看得见」这种断言也去掉了——装了渠道路由插件时它不一定成立。
|
|
24
|
+
- **「关掉就完全没有这个功能」这句不对(#41)。** 设置页这么写,可实际关掉只停「系统替她开这一轮」,工具与说明都还在。两边对齐成一种口径:按 README 的说法改文案,不改行为。
|
|
25
|
+
- **关了「兴趣」,她还是每 6 小时因为旧句子空醒一次(#42)。** 旧句子那一段(`tableFor`)从来不看 `interest.enabled`:只要桌上有旧句子、隔了 6 小时,就叫醒,而且这一轮**不摆事件卡、不写 `fired:`、不想一想、不递规则申请**——卡池永远空不了。作者实测 14 天:叫醒 14 次、14 次全是旧句子、事件卡 0、想一想 0。现在「兴趣」关掉就不摆旧句子,这一轮回到正常的空醒判断。
|
|
26
|
+
- **三处说死了的话(#42)。** 「这次隔了 N 个小时」其实只数 `wake:`(她主动开口、你跟她聊的那些都不算),改成「距你上次醒来,隔了 N 个小时」;「这些天再没被提起过」的判据只是「之后有没有事件 `refs` 指回它」,改成「还摊在那儿」;桌上的「还有一件没合上的事」暗示她还没得到答案,其实只是她反复问过,改成「还有一件你反复问起的事」。设置页兴趣卡那句「问过还没答案的问题」一起改。
|
|
27
|
+
- **用 `plugin add` 升级之后,旧包名留在 profile 里清不掉(#43)。** `scripts/fix-legacy-link.mjs` 原来只认 `link:` / `file:` 两种写法,而按更新说明用 `dsh plugin add "@ssamurias/dsh-fish@0.9.0"` 升级的人,profile 里留下的是**版本号**——脚本一句「没有老依赖,跳过」就退出 0,旧键 `dsh-fish` 与旧 `bundles` 条目原封不动,下次 pnpm 清理时两条 fish 打架。现在三种写法都收拾(源码目录 / tgz / 版本号),并且拆出 `migrateOne()` 可以直接测。
|
|
28
|
+
- **pnpm isolated 布局下「检查更新」永远不出现下载按钮(#43)。** `profileDirOf` 从模块路径反推 profile 时,遇到 `node_modules/.pnpm/<包>@<版本>/node_modules/<包>/` 这种真身路径,会截到 `.pnpm/...` 那一层——那里没有 `package.json`,于是判成 `missing`、`managed:false`。现在往回退到 profile 根。
|
|
29
|
+
- **两个社区 PR 已合入**(@BBleae):#40 主动搭话关着时不再每轮同步算一遍 `deriveSelf`(8000 条事件实测从 7.6 秒降到 50 毫秒级);#39 「只留证」的事件(聊天行、带 `selfmod` 的说法)不再被当成她问过的 / 总说到的摆回桌上,也不算她「自己动过」。
|
|
30
|
+
- **另两个社区 PR(#44、#45)也合入了**:`writeAtomic` 的临时文件名加了随机后缀——原来只有 `pid + Date.now()`,同一进程同一毫秒的两次写会交出半个 JSON,坏文件被当成坏档收走、`config.json` 整个回默认(低频,但后果重)。另一处让「她的话靠发送工具出去」的部署能正确记账:`proactive.sendTools` 指定发送工具名,工具调成功才算开了口、占额度、不折;`idleCountsSeen` 让 `seen:` 也算打断安静;`foldSilent=false` 时没开口的一轮只记账不折(上下文很大时折叠带来的缓存失效可能比省下的贵);主动回合投递前也先看她在不在忙(定时叫醒一直有这个判断,主动回合没有)。
|
|
31
|
+
- **上游断流时那行红字被当成「她开口说了话」(用户报,2026-11-06 01:32)。** ACP 代理在发现输出退化、nudge 之后仍然退化时,会往她那一轮里写一行 `❌ [ACP] stream error: …`。`followWake` 原先只判「有没有非空文本块」,于是这行报错被算成开口:记 `proactive-turn:`、占掉当天额度、留在对话流里、也不走静默折叠。现在先认这类断流信号(`❌` 开头 / 含 `stream error` / 含 `turn degenerated`),认出来就不算开口,按「没开口」那一套记账并尝试折叠。**澄清一句**:这行字不是插件产生的,是上游退化;插件只能保证不把系统报错记成她的行为。
|
|
32
|
+
|
|
33
|
+
### 迁移
|
|
34
|
+
|
|
35
|
+
- 无必改项。这一版不改事件字段、不升 `EVENT_SCHEMA_VERSION`;旧数据照读,行为只朝「更少误判」的方向变。
|
|
36
|
+
- **新增三个可选配置**(`proactive.sendTools` / `foldSilent` / `idleCountsSeen`),默认值等于旧行为:不填、不配置的部署一处不变。只在「她写的正文不会被自动转发、要靠工具才发得出去」的部署里才需要填 `sendTools`。
|
|
37
|
+
- 有一处**观感上会变**:`her_say` 回执从 `[说出去了]` 改成 `[记下了]`,桌上一句从「还有一件没合上的事」改成「还有一件你反复问起的事」——都是措辞,不动数据。
|
|
38
|
+
- 已经被误改名成 `.corrupt.<时间>` 的老文件不会自动恢复——那是上一版留下的现场,需要的话手动改回原名(内容本身是完好的)。
|
|
2
39
|
|
|
3
|
-
|
|
40
|
+
### 测试
|
|
41
|
+
|
|
42
|
+
全量 `node --test` = **1512 pass / 0 fail**(0.9.0 是 1441,本版新增 70 条,其中四个社区 PR 带来 29 条)。新增的都是这几条的回归:#33 认最新会话;#34 群房不记 `seen:` / 家里那间照记;#35 手打答案能认出来、日志不落原文;#36 前一轮的 `turn/end` 收不走处境;#37 EPERM 重试 + 一直失败时受超时约束;#38 带 BOM 照读且不改名;#32 聊天折行与 idle、判断与聊天的分界、聊天之后的状态;换房失败不问话、失败后冷却、冷却过去能再试并清账;`carry-ask-*` 判成 plugin。新增里还有:#41 `her_say` 按上限拦、成长坐标不是 1/1;#42 兴趣关掉不再摆旧句子;#43 版本号依赖也能清账、pnpm isolated 布局认得 profile 根。另有 #44 的 20 条(靠工具发话、空闲时钟、忙闲检查、处境与身份段说实话)与 #45 的 1 条(同时写同一个文件不出半截内容)。**#36、换房、#41 那几条已验证能复现**——把判据改回去就红。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 0.9.0 — 2026-11-05
|
|
47
|
+
|
|
48
|
+
这一版八件事(外加 0.8.9 未单独发版的两件事):**她自己会攒劲儿、会惦记、会缺工具就问你要**(不再藏在本机实验里);**梦、主动性、兴趣、主动搭话各有一个开关**;**「让她去刷 B 站」砍掉了**;**劲儿与开口的节奏改成一套数**;**两处会让人看不懂的措辞改成人话**;**桥可以自己决定开几间房、谁是外客**;**群房按天换新**;**40 轮换房不再多建一条会话**。
|
|
49
|
+
|
|
50
|
+
- **本机实验转正。** 梦、空醒、桌子(好奇 / 旧句子 / 回音 / 反复主题)、主动搭话,以前都要在数据目录里放一个 `.dev` 文件才生效;0.9.0 起对所有人可见,不需要再改任何文件。主动搭话的开关默认仍是关的,其余默认打开。
|
|
51
|
+
- **她自己攒劲儿,而不是按钟点掷骰子。** 距上一次自己动过多久(每小时 0.12)、桌上有没有新料(没答的问题、久未提起的旧句子、他回了你留的话、最近总回到的那件事),合起来算一个「劲儿」;满 1.0 才开一轮,动完按 0.8 记账,两次之间至少 2 小时。效果是:桌上有东西时更早醒,一直没什么可说时会拖得很久,而不是每天固定几次。
|
|
52
|
+
- **缺工具不许绕着走。** 每次醒来都带一句:想做什么但手上没有那件工具,就直接说你要它做什么、问主人能不能装上,或者开一张 ask 卡去问;缺工具不是失败。她的工具面仍然是那十只,这一版没有加任何工具。
|
|
53
|
+
- **「她做过的梦」搬到住所页。** 和日记、她写的小纸条放在一起——这一页回答的是「东西都在哪」;开关仍在「做梦」那张卡里,不放两边。
|
|
54
|
+
- **「她做过的梦」对所有人可见。** 以前这张卡按 `.dev` 藏起来,文案还写着「只在这台机器的开发副本里显示」;0.9.0 起 `her_dream` 与 `/dream` 都已公开,卡也一起打开,文案改成「她偶尔会把真实发生过的事重新拼成一句梦;不算成长,也不会被当成新的记忆」。开关仍在「做梦」那张卡里,关掉只停止记新的,旧的一条不删。
|
|
55
|
+
- **空醒进设置页(`memory.selfWake`,默认开)。** 醒来时没有待办、桌上也没有东西,她可以自己翻翻旧句子、写点什么,也可以什么都不做;关掉只影响这一种醒来,摆料那种照旧。
|
|
56
|
+
- **四个开关都进设置页。** 「主动搭话」「主观能动性」「兴趣」「梦」各自一张卡;主动搭话另有「一天最多几次」「多久没说话才可能开口」,兴趣卡里带「醒着没事时,自己找点事做」。关掉只是以后不做,已经写下的梦、日记、事件一条都不删。
|
|
57
|
+
- **「让她去刷 B 站」整条路砍掉。** 唤醒不再顺带去看首页;`browse.enabled` 默认改成 `false`。她自己的 `bili_look` / `bili_watch` 仍然可用(受 `bili.enabled` 管,默认开),只是不再由叫醒驱动。
|
|
58
|
+
- **两处措辞**:桌上的「(你最近又提到它)」改成「(最近你总说到它)」;反复主题从一整句「最近你总回到「…」这件事上」改成只留一句她自己的说法(去旁注、断在第一个逗号、最多 24 字),不再出现嵌套引号。
|
|
59
|
+
|
|
60
|
+
### 两处真机才暴露的 bug(2026-11-05 晚,用户 m02797)
|
|
61
|
+
|
|
62
|
+
- **劲儿永远是 0.00。** `drive.js` 里把事件的 `ts` 当毫秒数读(`Number(...)`),而它其实是 ISO 字符串,于是「出生时刻」和「上次自己动过」都被算成 0,日志里一直是 `drive 0.00 · 还没有任何记录,不急着动`——就算她 11 天没动过也一样。改成先按数字、再按日期解析。
|
|
63
|
+
- **她永远等不到「安静够久」。** 安静时长(`minIdleHours`)原本把 `meta seen:` 也算作「他来过」,而这条记录会被**别的会话**的用户活动误写:他在这台机器上跟别的 agent 说话,她的安静时钟就被清零,于是 `proactive skip 刚说过话,还不到时候` 一直挂着,主动搭话一次都开不出来。现在只有真的有话落进她的房间(`heard` 等)才算,记账行一律不算。
|
|
64
|
+
|
|
65
|
+
### 聊满 40 轮时会分裂出两间房(2026-11-05,用户反馈的 0.8.8 问题)
|
|
66
|
+
|
|
67
|
+
- **两条结账入口撞在同一秒,各建了一条新会话。** 桥接从 QQ 往屋里递话(`POST /dsh-fish/say`)时,满 `chat.rotateAfter` 的那一轮会有两条路同时结账:`lib/say.js` 的投递收尾与 `lib/turns.js` 的轮次收尾,两边都调 `rotateTalkSession`,中间没有互斥——于是 115ms 内各 `sc.create` 一条:先建的收到唤醒、在里面跑了一轮,之后成了侧栏里看不到的孤儿;后建的被写进 `home.json`。长期记忆不丢(`events.jsonl`、日记、搬运段都是全局的),但侧栏多一间同名空房,孤儿里那一轮再也翻不到,轮数也被多算。
|
|
68
|
+
- **现在换房间同一时刻只有一次在飞。** `rotateTalkSession` 包了一层单飞(同一数据目录内合并成一次;跨进程由 `withFileLock` 的 `.talk-session.lock` 兜底):并发进来的第二声直接等第一声的结果,不再建第二条。两条入口再各传一个 `from`(这句话 / 这一轮真正落在哪条会话),`home.json` 已经指着别的会话时就返回 `skipped`,日志写「换会话跳过」,既不建会话也不写重复的 `rotate:` 记录。
|
|
69
|
+
- 回归:`test/rotate-race.test.mjs` 3 条(同一刻两条入口只建一条、换完后迟到的那次跳过、`from` 不是当前屋子时不换)。
|
|
70
|
+
|
|
71
|
+
### 「没什么要说的」不再算一次开口(2026-11-05 晚,用户 m02937)
|
|
72
|
+
|
|
73
|
+
- **她开口了,但说的是「这一轮没什么要说的」。** 真机第一次自动开口,她回的是一整句元话语:「这一轮没什么要说的。今天想说的话,一小时前已经说完了。」——她的判断没错(一小时前刚说过),错在我们把这句话记成了一次开口:占掉当天额度、进了对话流、还挡住了静默折叠。
|
|
74
|
+
- **根因是「什么都不做」在文本界面上不成立。** 醒来提示原来写「不想说,就这一轮什么都别做」,可一个回合总得产出点什么,模型就只能写一句「没什么要说」。现在提示改成明确的出口:不想说就**不要写任何字**,也不要解释为什么不说;同时记账侧兜底——一轮里只有一句这样的元话语时,按静默记、把整轮折成一行,不占额度、不留噪音。判据做得窄(短、且开头就交代「这一轮 / 今天没什么要说的」),真话不会被吞。
|
|
75
|
+
- **空桌不醒。** 劲儿只回答「攒够了没有」,不回答「攒够了有没有事可说」。桌上没有任何材料(没答的问题、久未提起的旧句子、他回了你留的话、最近总回到的那件事)时,即使劲儿满也不起——否则醒来只能回一句「没什么要说」。
|
|
76
|
+
- **安静门槛调高。** 本机配置 `minIdleHours` 从 1 小时调到 3 小时:1 小时等于「刚说完又来问一句」。默认值(6 小时)不变。
|
|
77
|
+
|
|
78
|
+
### 桥:开几间房、谁是外客(原 0.9.1,并入本版)
|
|
79
|
+
|
|
80
|
+
- **三个可选字段。** `room`(`house` / `channel`)决定这句话并进书房还是另开一间,`title` 决定侧栏里那间房叫什么,`guest: true` 标记「外面的人」。不传时行为与 0.9.0 之前一致:私聊回书房,群聊按 `channel` 开房。
|
|
81
|
+
- **群友私聊可以单独一间,并标成外客。** 以前私聊不论谁发的都落进书房、写成「他跟你说话了」,群友会被当成主人本人。现在桥给 `channel + room:'channel' + guest:true` 就另开一间;标了 `guest` 的消息不写 `seen:`、不涨轮数、不触发轮换、不进「上次我们说到这」,正文写「有个不是他的人跟你说话」。
|
|
82
|
+
- **`speaker` 对所有场次生效。** 以前只有群聊拼「某某在群里说:」,现在私聊(尤其是群友私聊)也会带上是谁说的,免得三个人被当成一个人。
|
|
83
|
+
- **群房按天轮换。** 默认一间群房用满 **7 天**换新的(`config.rooms.groupRotateDays`,`0` = 不换)。热闹的群 200 条上下文一会儿就满,按轮数不好估,所以按天。旧房改名成「… YYYY-MM-DD 之前」留在侧栏,新房从当天重新算。
|
|
84
|
+
- **房间收纳按「最近说话」。** `channels.json` 新增 `bornAt` / `lastAt`,超过 40 间时先丢最久没说话的,不再丢最早建的(旧的「最早建的先被忘掉」会让被丢的群下次说话时再建一间同名房,旧房成孤儿)。老档没有这两个字段时按 `at` 兼容。
|
|
85
|
+
|
|
86
|
+
这些是桥的协议字段,不改插件内置任何 IM;桥仍然只走 HTTP(`POST /dsh-fish/say`)。
|
|
87
|
+
|
|
88
|
+
### 0.8.9 的两件事(未单独发版,已并入本版)
|
|
89
|
+
|
|
90
|
+
- **递话、叫醒不再在宿主里堆一条空白会话。** 以前 `sayToHer`、主动开口、叫醒三处都直接 `sc.create({ sessionId })`;会话已经被别的原因关掉时,宿主会新建一条空会话,侧栏里于是多出一间没内容的房。现在 `lib/deliver.js` 先 `ensureSessionLive()`:`resolveAgent()` 探活,探不通才 `create`;三处调用点统一走它。`test/boot.test.mjs` 拆成两条,`test/wake-spacing.test.mjs` 的时机钩子也从 `create` 挪到 `resolveAgent`。
|
|
91
|
+
- **社区 PR #26 的回忆两处显示修复。** `brief` 档里长聊天的原话保留「|聊天里说的」;改口引用标「他说 / 读到别人说 / 回复」,并且先截原话再加标记,避免标记被截断。顺带删掉不再使用的 `UNCLAIMED_PENALTY`,`latestRevisions` 不再导出。没有动 `+4` 认领加分,也没有动 voice / heard / answer 的排序。
|
|
92
|
+
- 0.8.9 没有单独的 GitHub Release(npm 上的 0.8.9 是改名首发),所以这两件事也写进 0.9.0 的说明;从 0.9.0 起生效。
|
|
93
|
+
|
|
94
|
+
### 迁移
|
|
95
|
+
|
|
96
|
+
- 以前放过 `.dev` 文件的,留着不影响,也可以删掉。
|
|
97
|
+
- `browse.enabled` 默认值变了(`true` → `false`)。想恢复「叫醒顺带刷首页」的,目前没有开关,属于有意取消。
|
|
98
|
+
- 新增配置键:`memory.selfWake`、`drive.enabled`、`interest.enabled`、`dream.enabled`、`bili.enabled`(都是默认 `true`),以及 `rooms.groupRotateDays`(默认 `7`,`0` = 不换)。`proactive.enabled` 仍是默认 `false`,去设置页打开。
|
|
99
|
+
|
|
100
|
+
### 测试
|
|
101
|
+
|
|
102
|
+
全量 `node --test` = **1441 pass / 0 fail**。0.9.0 自身新增 4 条(元话语判据的正反例、`followWake` 把她说的话带出来、空桌不醒的材料判据);`test/switches.test.mjs` 4 条(三个开关默认开、关掉不被默认值盖回、白名单里有、三处闸真的会关);`test/rotate-race.test.mjs` 3 条(换房间的两条入口并发时只建一条);桥接 8 条(`room` 两种用法、`title` 显示名、按天过期判据、群房到期换新房、群友私聊另开房且不碰生命体征、`guest` 回书房但标外客、真实 `/dsh-fish/say` 路由透传)。并入社区 PR #27–#31 后再加 20 条(宿主拼的上下文识别、假宿主探活时机、`her_note` 划掉、未认领聊天行、导出事件流只留元数据)。
|
|
103
|
+
|
|
104
|
+
### 鸣谢
|
|
105
|
+
|
|
106
|
+
- **@BBleae(晴猫)**:从 0.8.6 起的五个 PR——#10 匿名 buvid3、#11 叫醒间隔、#15 叫醒那一轮不记成「他来过」、#23 日报 / 回忆分三种话、#26 回忆 `brief` 档的两处显示。0.9.0 期间还收到 #27–#31 五个 PR(#27 宿主拼的上下文不算他来过、#28 假宿主探活时机、#29 `her_note` 按她自己写过的话划掉、#30 未认领聊天行、#31 导出事件流只留元数据),已全部并入本版。
|
|
107
|
+
- **交流群 2 群的群友「无」**:主观能动性的机制灵感来自他讲的「主动性不该是定时器,而是攒够了的冲动」;落进本插件时全部重新实现,没有代码或文本的直接搬运。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 0.8.10 — 未单独发布(已并入 0.9.0)
|
|
112
|
+
|
|
113
|
+
这一版六件事:**升级改走 npm**;**升级时不再弹那个黑窗口**;**升级时把旧名字的残留一起清掉**;**插件市场能认出我们的包了**;**设置页那半边补回来了**;**`link:` 装的用户有迁移脚本**。
|
|
114
|
+
|
|
115
|
+
- **升级走 npm,不再偷偷下 tarball 再用 `file:` 装。** 以前那条路会把依赖记成 `file:updates/xxx.tgz`——一个临时路径,下次升级时它自己都认不出来,被当成「开发版」拒掉。现在写成 `@ssamurias/dsh-fish@x.y.z`,是一条能一直往上走的版本记录。下载那步保留,只用来确认这个版本真的在、内容没被换。
|
|
116
|
+
- **黑窗口没了。** 以前用 detached 起 `cmd.exe`,Windows 会给它另开一个控制台——用户看到一块黑的、关不掉,以为卡死。现在改由一个 VBS 启动器(`WScript.Shell.Run …, 0, False`)经 `wscript //B` 把同一份批处理藏起来跑:窗口完全不显示,脚本照样等宿主退出、装、校验、失败回滚、再把它拉起来。同一件事以前也在做,只是没人看得懂那块黑的东西。
|
|
117
|
+
- **老用户不用先卸。** 反推 profile 目录、读依赖都同时认 `@ssamurias/dsh-fish` 和老的 `dsh-fish` 两种装法,0.8.9 之前装上来的人也能直接升。
|
|
118
|
+
- **升级时顺手把旧名字的残留清掉,别让它在启动时炸。** 0.8.9 之前装的 profile 里,依赖和 `bundles` 记的都是裸名 `dsh-fish`。改名后只往里面 `pnpm add` 新包,旧那条会原地留着,`node_modules` 里于是同时有两条鱼、`bundles` 里还是旧名——两条 insert 撞同一个 id,web boot 抛 `duplicate factory registration` 直接崩。现在安装脚本装完新包先收拾现场:删旧依赖键、删旧 `bundles` 条目、把旧的 `node_modules/dsh-fish` 改名收起来(不删,留着能回退),改 `package.json` 之前先备份。这一步失败不阻断安装,只记进日志。
|
|
119
|
+
- **市场指向修好了。** 0.8.9 之前仓库根 `package.json` 还是裸名 `dsh-fish`,插件市场按名字去 npm 查,查到的是别人 9 月抢注的同名包(0.0.1)。改名之后市场下次重建就会指到 `@ssamurias/dsh-fish`。
|
|
120
|
+
- **改名那一下把客户端半边弄丢了,这版补回来。** 包名从 `dsh-fish` 换成 `@ssamurias/dsh-fish` 之后,`lib/client.js` 里注册的 id 还是短名,而 client-modules 是按 loader 条目名(完整包名)解析的——宿主那半边照常跑,设置页却空着,像没装上。现在注册名跟着包名走,测试直接拿 `package.json` 的 `name` 比对,以后再改名会当场红。
|
|
121
|
+
- **`link:` 装的用户升级前要跑一次迁移脚本**(0.8.10 之前用源码目录装的人)。原因同上:他们的 `node_modules` 里只有裸名链接,而新包名带 scope,条目 import 会失败、DSH 起不来。跑 `node scripts/fix-legacy-link.mjs` 看清要改什么,加 `--write` 真改,然后启动。从 npm / GitHub 装的不用管。
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
## 0.8.9 — 2026-11-05
|
|
127
|
+
|
|
128
|
+
这一版十三件事:**递话、叫醒之后不再在宿主里堆一条空白会话**;社区 PR #26 的两处回忆显示修复;调度器收摊时把叫醒窗口一起关掉(CI 抓到的泄漏);**按她手上真有的工具,摘掉讲别的工具的提示词段**;**把最容易变的那四段挪到提示词最末尾**;**醒过来没开口的那一轮收起来**;**沉默不再扣额度、也不再吃冷却**;**醒来时把很久没被提起的旧句子摆在桌上**(本机实验里的梦材料);**有些醒来不再派活**(本机实验:摆料那一次、以及她连着七天没动过时兜底空一次;摆料那一次连 B 站与惦记清单也不带);**她开口那一行换成「她自己开口」的小胶囊**;**醒来时把惦记着的旧问题摊到自己面前**(本机实验第一步);**两张桌子并成一张**(惦记的口子与旧句子不再各摆一摞);以及**她自己开口的时机改成「攒够了」**(本机实验:劲儿 + 兴趣 + 缺工具就开口)。另外把 0.8.8 里来自社区 PR #23 的部分补上署名,见本节末的「鸣谢」。
|
|
4
129
|
|
|
130
|
+
- **同一批旧句子不再在一轮里摆两遍**:摆料那一次 `tableFor` 已经把旧句子摆出来了,桌子又摆了一遍——2026-11-05 18:44 真机那轮她读到同三句原话两次,像系统在盘货。现在 `staleForDesk()` 让摆料那一轮不再把 stale 交给桌子。
|
|
131
|
+
- **摆料那一轮,连世界的动静也不带了**(2026-11-05 用户 m01128):以前那轮既摆旧句子,又刷四条 B 站、又摊一张惦记清单,她挑了最像活的那件去干(核对八天前那个赌),梦一次没想起来。现在 `keepWorldOnWake()` 让这一轮只剩便条、时间、旧句子、「这一轮没有待办」,外加那句「你手上没有能说话的工具」——那是她世界里的常量,不是活。手动「让她去刷 B 站」不跟着收。
|
|
5
132
|
- **她的会话列表不再越积越多空壳**:本机 `~/.dsh-fish/home` 这个 cwd 下 52 条会话里 39 条是空壳,同一台机器其他工作区几乎没有。
|
|
6
133
|
- **「只说开头」的回忆里,长的聊天原话也带着「|聊天里说的」**,不再被 40 字截掉、看着她像认领过。
|
|
7
134
|
- **改口关系引用别人的话时也说清来路**(「他说:」「读到别人说:」「回复:」)。
|
package/LICENSE
CHANGED
|
@@ -19,3 +19,10 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 第三方来源与致谢
|
|
26
|
+
|
|
27
|
+
- 主观能动性的攒劲机制灵感来自交流群 2 群的群友「无」;落进本插件时全部重新实现,没有代码或文本的直接搬运。
|
|
28
|
+
- 兴趣与好奇的判据为自研实现(`lib/interest.js`、`lib/curiosity.js`),未移植任何第三方插件代码;概念上参考了 Loewenstein 的信息缺口理论(1994)、Generative Agents 的记忆时间衰减排序(2023)与 Oudeyer 关于内在动机中「新奇会失效」的论述(2007)。
|
package/README.md
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
📺 **[看视频讲解(19 分钟)](https://www.bilibili.com/video/BV1oTnZ6LEtc/)** —— 这个插件是怎么想出来的、她为什么会长成那样、13 亿 token 都花在哪了。
|
|
14
14
|
|
|
15
|
-
> **当前版本 0.
|
|
15
|
+
> **当前版本 0.9.1**(2026-11-06)。这一版是修 bug 版,没有新功能,修了社区报的十条(issue #32–#38、#41–#43)加用户直接反馈的几条,另合入四个社区 PR(#39、#40、#44、#45):面板上「说 N」不再被聊天撑大、归档后认回最近那条会话、群聊不再让冷落检测失灵、卡片里手打的答案能认出来、排队叫醒不会被上一轮清掉、Windows 上 EPERM 会重试、带 BOM 的 JSON 不再被当成坏文件、换房那句「想给下一个房间留一句话吗」不再每回一句都弹(换会话失败时也不问,并冷却 5 分钟再试);「多久看一次有没有人回复」真的按间隔去问了、扫到的回复会主动投给她、`bili_look` 也能读自己的评论区;@ 艾特改按昵称原文匹配,只粘 cookie 保存不再清空 uid / 昵称;`her_say` 说好的「一天最多几次」真的生效了、写下的成长坐标不再是 1/1、回执从「说出去了」改成「记下了」;关掉「兴趣」后不再每 6 小时因为一句旧句子把她叫醒;用 `plugin add` 升级留下的旧包名能清干净,「检查更新」在 pnpm 布局下也认得出装在哪。另外:配置偶尔整个回默认(同一毫秒两次写撞进一个临时文件)也修了;「她靠发送工具发话」的部署现在会正确记成开了口;主动回合投递前会先看她在不在忙。完整说明见 **[0.9.1 更新说明](RELEASE-NOTES-0.9.1.md)**。
|
|
16
|
+
>
|
|
17
|
+
> 上一版 **0.9.0**(2026-11-05)把一直只在开发机上生效的四样东西对所有人打开了:**她会自己开口**(攒够一股想动的劲、你在她的时段里、你确实一阵没说话、桌上有可说的东西,四条同时满足才开一轮;不想说就真的不写,只留一行记录)、**梦里记事**、**醒来没事时自己找点事做**(空醒)、**她会自己攒劲儿、惦记、缺工具就问你要**(主观能动性 / 兴趣)。刷 B 站不再挂在叫醒上(`bili_*` 工具仍可用)。0.9.0 起桥可以自己决定开几间房、每间是谁(`room` / `title` / `guest` 三个可选字段),群房默认满 7 天换新。四个设置卡可以单独关:主动搭话 / 主观能动性 / 兴趣 / 梦。完整说明见 **[0.9.0 更新说明](RELEASE-NOTES-0.9.0.md)**,上一版见 **[0.8.8 更新说明](RELEASE-NOTES-0.8.8.md)**。
|
|
18
|
+
>
|
|
16
19
|
> **出门仍是实验功能**:它会真的把一条对话交出去,也会读那个工作区的项目笔记和记忆文件;最坏的情况是她把不该看的内容写进日记,而日记撤不回。第一次使用要先确认,风险与回退方式见 **[0.8.0 更新说明](RELEASE-NOTES-0.8.0.md)**。
|
|
17
20
|
|
|
18
21
|
## 和别的养成插件差在哪
|
|
@@ -141,6 +144,27 @@
|
|
|
141
144
|
|
|
142
145
|
**只在还没有起点的一局生效**。已经有起点时会拒绝,让你先重置——覆盖一个已经在长的她,这个决定不该由插件替你做。带过来的称呼也会顶掉我们第一天的起名事件,她不会再问一遍「该怎么叫你」。
|
|
143
146
|
|
|
147
|
+
## 她会自己开口吗(0.9.0)
|
|
148
|
+
|
|
149
|
+
会。但**默认是关着的**,你想要的时候再在设置里打开。
|
|
150
|
+
|
|
151
|
+
**她什么时候会开口**:她自己会攒一股「想动」的劲,默认大约六七个小时攒满(桌上东西多的时候四小时上下),攒满之后还要同时满足三件事才会真的开一轮——你在她的醒着时段里(默认 12:00–02:00)、你确实有一阵没跟她说话了(默认 6 小时,下限 1 小时)、桌上有可说的东西。三件事都满足,她才自己醒一次;醒来说不说、说什么,仍然由她决定。
|
|
152
|
+
|
|
153
|
+
**桌上有可说的东西**,指这几样:她自己问过、还没答案的问题;搁了很久的旧句子;她给你留过话、而你后来有没有来过;她最近总说到的那件事。桌上什么都没有的时候,劲儿再满她也不动——这条是 0.9.0 加的,为了让「醒来」有由头,而不是按表打卡。
|
|
154
|
+
|
|
155
|
+
**她可以真的什么都不说**:不写就是不写。那一轮不会出现在对话里,只留一行记录(0.9.0 起「这一轮没什么要说的」这类元话也按「没开口」处理,不会占掉当天的次数)。
|
|
156
|
+
|
|
157
|
+
**在哪调**:设置 → 大肥鱼,有四个独立卡:
|
|
158
|
+
|
|
159
|
+
- **主动搭话** —— 开/关;一天最多几次(0–6);你多久没说话她才可能开口(1–24 小时)。
|
|
160
|
+
- **主观能动性** —— 她要不要自己攒这股劲(关掉就只按日程叫醒,不会自己开)。
|
|
161
|
+
- **兴趣** —— 要不要把「她最近总说到的那件事」摆到桌上,以及「醒着没事时,自己找点事做」(空醒:没有待办、桌上也没有东西时,她可以自己翻翻旧句子、写点什么,或者什么都不做)。
|
|
162
|
+
- **梦** —— 梦里记不记事。
|
|
163
|
+
|
|
164
|
+
**花多少**:一次开口大约 1.5 分钱(0.9.0 实测一次 `¥0.0146`,上下文 50 万 token 量级)。想省就把「一天最多几次」调到 1,或者把「你多久没说话」调大。
|
|
165
|
+
|
|
166
|
+
**关掉之后**:工具本身还在(`her_say`、`her_note`、`her_dream` 都在,她照样能记、能写、能做梦),只是不会再自己开一轮。
|
|
167
|
+
|
|
144
168
|
## 数据在哪
|
|
145
169
|
|
|
146
170
|
默认全部在 `~/.dsh-fish/`,但可以整个搬走(0.6.2):设置 → 大肥鱼 →「数据」页签 →「迁移工作区」,选一个文件夹就行。搬走之后路径记在 `~/.dsh-fish-location.json`(刻意放在数据目录外面),**重启 DSH 才生效**。老实现在原处改名成 `dsh-fish-backups/moved-<时间戳>/`,不删。`DSH_FISH_HOME` 环境变量仍然优先,高于这个指针。
|
|
@@ -347,7 +371,7 @@ lib/
|
|
|
347
371
|
toolschema.js 简写参数 DSL → 标准 JSON Schema
|
|
348
372
|
observe.js 宿主侧 JSON API(/dsh-fish/state、/events、/beliefs、/diary、/config、/wake、/browse、/reports、/update)
|
|
349
373
|
client.js 浏览器半边:设置 → 大肥鱼
|
|
350
|
-
test/
|
|
374
|
+
test/ 1512 个测试,node --test 全绿
|
|
351
375
|
```
|
|
352
376
|
|
|
353
377
|
## 跑测试
|
|
@@ -368,28 +392,25 @@ ffmpeg 写文件这件事不需要额外权限:抽帧和拼图都从 stdout
|
|
|
368
392
|
|
|
369
393
|
默认不校验证书(ffmpeg 的 `tls_verify` 默认就是 0),拉到能出就直接出。只有你明确想校验证书、或某个构建不带 CA 时,才设置 `DSH_FISH_CA_FILE` 指向 CA 包——设了它会同时打开 `-tls_verify 1`,两者必须成对,光给 CA 不开校验是空转(2026-10-30 实测:传一个不存在的 CA 文件照样出图)。
|
|
370
394
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
1. **从 npm 装**(最省事,推荐给只是想用的):
|
|
395
|
+
**从 npm 装**——推荐,一条命令,不用先下载,也不用关掉 DSH:
|
|
374
396
|
|
|
375
397
|
```
|
|
376
398
|
"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "@ssamurias/dsh-fish"
|
|
377
399
|
```
|
|
378
400
|
|
|
379
|
-
|
|
380
|
-
3. **命令行装源码目录**(先关掉 DSH,运行中替换已加载的包会 EPERM):
|
|
401
|
+
不想经过 npm 就直接从 GitHub 装,同样不用关 DSH:
|
|
381
402
|
|
|
382
403
|
```
|
|
383
|
-
"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "
|
|
404
|
+
"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "github:ssamurias/dsh-fish"
|
|
384
405
|
```
|
|
385
406
|
|
|
386
|
-
|
|
407
|
+
要改代码才用源码目录,而且**必须先关掉 DSH**——运行中替换已被加载的包会 `EPERM`,包目录会被留成「已删除」,下次启动缺包:
|
|
387
408
|
|
|
388
409
|
```
|
|
389
|
-
"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "
|
|
410
|
+
"<DSH>/resources/runtime/cli/bin/dsh.cmd" plugin --profile <profile> add "link:<本目录绝对路径>"
|
|
390
411
|
```
|
|
391
412
|
|
|
392
|
-
|
|
413
|
+
> 升级已有的安装也等于「替换已被加载的包」:DSH 开着的时候先关掉再装,或者直接用设置页里的插件管理器升级。
|
|
393
414
|
|
|
394
415
|
无论哪种,都要保证 profile 的 `package.json` 里 **`dependencies` 与 `dsh.profile.bundles` 都有 `@ssamurias/dsh-fish`** —— 只有一边会在下次 `pnpm` 清理时把包删掉,表现为「重启后 DSH 崩了 / 设置页没有鱼」。包名必须与 `cordis.patch.yml` 里的 `name` 完全一致(都是 `@ssamurias/dsh-fish`,**带 scope 的全名,写短名客户端那半会静默不加载**)。
|
|
395
416
|
|
|
@@ -401,14 +422,43 @@ ffmpeg 写文件这件事不需要额外权限:抽帧和拼图都从 stdout
|
|
|
401
422
|
|
|
402
423
|
**查到新版可以直接在这儿升级**(0.6.14 起):点「下载 vX」→ 下载并校验 → 点「现在重启并安装」→ 应用自己关掉、换包、重开。中间有两次确认,没点确认什么都不会发生:第一次只下载,不碰现有安装;第二次才关应用。
|
|
403
424
|
|
|
404
|
-
-
|
|
405
|
-
-
|
|
406
|
-
-
|
|
425
|
+
- **0.8.10 起走 npm 装**(`add "@ssamurias/dsh-fish@x.y.z"`),不再用 `file:<临时 tgz>`——那条路会把依赖记成一个临时路径,下次升级时连自己都认不出来,被当成「开发版」拒掉。下载那一步保留,只用来确认这个版本真的在、内容没被换掉(先解开验包名、版本、`lib/index.js`,镜像回 HTML 错误页或给了旧版本都会被拒)。
|
|
426
|
+
- **不再弹黑窗口**。以前用 detached 起 `cmd.exe`,Windows 会给它另开一个控制台,用户看到一块黑的、关不掉。现在同一份批处理由 VBS 启动器经 `wscript //B` 藏起来跑:窗口不显示,脚本照常等宿主退出、装、校验、失败回滚、再把它拉起来。日志仍在 `updates/last.log`,界面上能看到最后几行。
|
|
427
|
+
- 版本号走三条源并发取(npm 官方源、npmmirror 镜像,加上 GitHub 那几条),国内通哪条算哪条。失败会写清哪条源、什么原因,卡片里留「重试下载」,不用刷新页面。
|
|
407
428
|
- **开发版不升级**:依赖写的是 `link:` / `file:`(装到源码目录那种)时按钮不会出现,服务端也会拒——那会把源码目录换成下载包。非桌面版(拿 `node` 跑起来的)同样拒绝安装:换上去却没有能重开的 exe,等于把人关在门外。
|
|
408
429
|
- 同一张卡里还有个 GitHub 入口(「或去 GitHub 手动下载」),代码、更新记录、怎么装都在那边。
|
|
409
430
|
|
|
431
|
+
> **0.8.10 之前用 `link:` 装的人,先跑一次迁移。** 包名从 `dsh-fish` 改成了 `@ssamurias/dsh-fish`,插件自带的 `cordis.patch.yml` 条目名也跟着变成完整包名——而你 profile 的 `node_modules` 里只有裸名 `dsh-fish` 那条链接,条目 import 会失败,DSH 直接起不来。先关应用,然后:
|
|
432
|
+
>
|
|
433
|
+
> ```
|
|
434
|
+
> node scripts/fix-legacy-link.mjs # 先看它要改什么
|
|
435
|
+
> node scripts/fix-legacy-link.mjs --write # 真改(会备份 package.json)
|
|
436
|
+
> ```
|
|
437
|
+
>
|
|
438
|
+
> 它会把 `node_modules/@ssamurias/dsh-fish` 建好、把依赖键改成新名、把老链接改名停用。从 npm / GitHub 装的人不受影响,不用跑。
|
|
439
|
+
|
|
410
440
|
> 路径里带中文时,用 ASCII 目录联接(junction)指过去更稳:先 `fs.symlinkSync(真目录, ASCII 别名, 'junction')`,再 `link:<ASCII 别名>`。用 `mklink /J` 接中文目标路径常把目录名写成乱码,随后 `MODULE_NOT_FOUND`。
|
|
411
441
|
|
|
442
|
+
## 从旧版升到 0.9.x(含改名与升级修复)
|
|
443
|
+
|
|
444
|
+
0.8.9 把包名从 `dsh-fish` 改成了 `@ssamurias/dsh-fish`;0.9.0 又把原本准备在 0.8.10 发的升级修复一起带了进来;0.9.1 补上了「按更新说明用 `plugin add` 升上来」那一类的残留清理。老安装分几种,走的路不一样:
|
|
445
|
+
|
|
446
|
+
| 你当初怎么装的 | 怎么升 | 会发生什么 |
|
|
447
|
+
| --- | --- | --- |
|
|
448
|
+
| npm / GitHub | 设置 → 大肥鱼 → 插件 → 检查更新 → 下载 → 重启安装 | 脚本装完新包会先收拾现场:删旧的裸名依赖键、删旧 `bundles` 条目、把旧的 `node_modules/dsh-fish` 改名成 `.disabled-<时间戳>` 收起来(不删,能回退),改 `package.json` 前先备份。全程不弹窗口,日志在 `~/.dsh-fish/updates/last.log` |
|
|
449
|
+
| `link:` 源码目录 | 先跑 `node scripts/fix-legacy-link.mjs --write`,再启动 | 不跑就起不来:条目名是全名,你本地只有裸名链接,import 失败会让 DSH 直接崩 |
|
|
450
|
+
| 0.8.9 从 npm 装(包名已经是 `@ssamurias/dsh-fish`) | 手动一条命令:`plugin --profile <profile> add "@ssamurias/dsh-fish@0.9.0"` | 0.8.9 的升级代码只认裸名 `dsh-fish`,自动检查更新会把它判成「开发版 / 不归我管」;客户端半边也还是短 id,设置页可能空着 |
|
|
451
|
+
| 还停在 0.8.8 或更早(GitHub 装) | 手动一条命令:`plugin --profile <profile> add "@ssamurias/dsh-fish@0.9.0"` | 0.8.8 及更早的升级脚本还是老代码(用 `file:` 装临时 tgz),大概率装不上新名字,卡在旧版本 |
|
|
452
|
+
| 用上面那条 `plugin add "@ssamurias/dsh-fish@..."` 升上来的 | 再跑一次 `node scripts/fix-legacy-link.mjs --profile <profile> --write` | 0.9.1 起这个脚本认得**版本号**依赖(以前只认 `link:` / `file:`,一句「没有老依赖,跳过」就退出 0),会删掉残留的裸名 `dsh-fish` 键与旧 `bundles` 条目,老目录改名成 `.disabled-<时间戳>` 收起来,改之前先备份。不加 `--write` 是预览 |
|
|
453
|
+
|
|
454
|
+
升级完自检三行,缺一行就会「重启后崩 / 设置页没有鱼」:
|
|
455
|
+
|
|
456
|
+
```
|
|
457
|
+
package.json 的 dependencies 里有 "@ssamurias/dsh-fish"
|
|
458
|
+
package.json 的 dsh.profile.bundles 里有 "@ssamurias/dsh-fish"
|
|
459
|
+
node_modules 里 没有裸名 dsh-fish 目录
|
|
460
|
+
```
|
|
461
|
+
|
|
412
462
|
## 卸载 / 停用
|
|
413
463
|
|
|
414
464
|
- **卸载**:设置 → 插件 → 卸载(或 `dsh plugin --profile <profile> remove @ssamurias/dsh-fish`),然后重启。`~/.dsh-fish/` 不会被动,她的记忆留在那儿。
|
|
@@ -419,17 +469,19 @@ ffmpeg 写文件这件事不需要额外权限:抽帧和拼图都从 stdout
|
|
|
419
469
|
P1(骨架):事件流、派生、阶段门、生物钟、工具、冷落检测、日记、观测台。
|
|
420
470
|
P2(她真的会刷 B 站并写报告):`lib/bili.js` 只读客户端 + `lib/browse.js` 选题筛读 + `lib/look.js` 的 `bili_look` 工具 + `lib/report.js` 写稿,已接进生物钟。
|
|
421
471
|
|
|
422
|
-
**已有
|
|
472
|
+
**已有 1512 个测试全绿**,真接口跑通过一轮(10.8s,含首页+详情+评论+弹幕)。
|
|
423
473
|
|
|
424
|
-
`browse.enabled` 默认 **
|
|
474
|
+
`browse.enabled` 默认 **false**(0.9.0 起不再由叫醒驱动);想让她醒来顺带刷首页,在 `config.json` 里设回 `true`,关掉后定时器一次都不会调 B 站接口。`bili_*` 工具仍然可用,只是不再挂在唤醒上。
|
|
425
475
|
|
|
426
476
|
## 鸣谢
|
|
427
477
|
|
|
428
478
|
这个插件不依赖任何第三方库(`package.json` 的三个依赖字段都是空的),但想法不是一个人想出来的。
|
|
429
479
|
|
|
430
480
|
- **@吴晓观**(交流群 1 群群友)—— 记忆机制这一块的思路起点来自他。0.8.6 里「固化下来的认知也会随时间退下去」「翻旧事可以先只给清单再给全文」「记忆相关的数字要说得清它数的是什么」这几条,最初都是他在群里讲的。落进本插件时全部重新实现了一遍,没有代码或文字的直接搬运;具体的取舍与改法记在 [CHANGELOG](CHANGELOG.md) 的 0.8.6 一节。
|
|
481
|
+
- **@无**(交流群 2 群群友)—— 主观能动性的思路起点来自对方在群里的一句话:「主动性不该是定时器,而是攒够了的冲动。」0.9.0 的「劲儿攒够才动、兴趣会回灌」就是把这句落成实现;代码全部自写,没有搬运。
|
|
431
482
|
- **@Bacon-01** —— 0.8.6 的 B 站手机扫码登录(含自写的零依赖二维码编码器 `lib/qr.js`)由他贡献,见 [PR #17](https://github.com/ssamurias/dsh-fish/pull/17)。
|
|
432
|
-
- **@BBleae**(晴猫)—— 从 0.8.6 起先后提了五个 PR:三个直接合入([#10](https://github.com/ssamurias/dsh-fish/pull/10) 匿名 buvid3、[#11](https://github.com/ssamurias/dsh-fish/pull/11) 叫醒间隔、[#15](https://github.com/ssamurias/dsh-fish/pull/15) 叫醒那一轮不记成「他来过」);[#23](https://github.com/ssamurias/dsh-fish/pull/23) 的复现与改法落进 0.8.8(日报/回忆分三种话、被推翻的话不再排第一);[#26](https://github.com/ssamurias/dsh-fish/pull/26) 修掉回忆 `brief`
|
|
483
|
+
- **@BBleae**(晴猫)—— 从 0.8.6 起先后提了五个 PR:三个直接合入([#10](https://github.com/ssamurias/dsh-fish/pull/10) 匿名 buvid3、[#11](https://github.com/ssamurias/dsh-fish/pull/11) 叫醒间隔、[#15](https://github.com/ssamurias/dsh-fish/pull/15) 叫醒那一轮不记成「他来过」);[#23](https://github.com/ssamurias/dsh-fish/pull/23) 的复现与改法落进 0.8.8(日报/回忆分三种话、被推翻的话不再排第一);[#26](https://github.com/ssamurias/dsh-fish/pull/26) 修掉回忆 `brief` 档的两处显示问题(已并入 0.9.0)。
|
|
484
|
+
- **@BBleae**(晴猫)在 0.9.0 期间又提交了 #27–#31 五个 PR:宿主拼的上下文不算他来过、`wake-spacing` 假宿主探活、`her_note` 按她自己写的话划掉、没认领的聊天行、导出事件流只留元数据。这五个 PR 都已并入 0.9.0(合并提交 `85b5b9c`、`72aefed`、`d49738a`、`a21d472`、`c230109`)。
|
|
433
485
|
|
|
434
486
|
原理页里引用的 Kolb / Piaget / Bowlby / Festinger / Bartlett / Dewey / Schön,只是思想引用(页底标了作者与年份),不含他人代码或文字。
|
|
435
487
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# 大肥鱼 0.8.0 更新说明
|
|
2
|
+
|
|
3
|
+
> 这一版你可以做三件以前做不到的事:**让她去别的地方干活**、**让她有事来问你**、**让她记住你说过的话**。
|
|
4
|
+
> 下面按「你会看到什么」来写,不需要懂代码。
|
|
5
|
+
|
|
6
|
+
## 一、设置里多了一个「出门」页
|
|
7
|
+
|
|
8
|
+
位置:**设置 → 大肥鱼 → 出门**。这是这一版最大的变化。
|
|
9
|
+
|
|
10
|
+
打开后有四件事可以做:
|
|
11
|
+
|
|
12
|
+
1. **让她去工作园区**
|
|
13
|
+
一个专门给她干活用的空工作区,不会碰你别的项目目录。第一次点会自动建好。
|
|
14
|
+
它默认就叫「工作园区」——新建出来的就是这个标题;以前版本建的「出门口袋」会在重启后自动改成这个名字,还是同一个目录,不用删、不用重建。
|
|
15
|
+
2. **让她去别的工作区**
|
|
16
|
+
选一个你已有的工作区,让她在那边新开一条对话干活。
|
|
17
|
+
她会读到那个工作区的项目笔记、交接记录和记忆文件——也就是说,她可能知道一些本来不该她知道的事。只想让她干活的话,用上面的工作园区。
|
|
18
|
+
3. **请她上身**
|
|
19
|
+
把一条**正开着的**对话临时交给她。从你下一句话开始,回你的是她;你说「结束请神」,这条对话就恢复成原来的样子。
|
|
20
|
+
她接管期间,那条对话改不了她家里的东西(屋子、记忆、对话、配置),会被一起拦下来;别的对话不受影响。
|
|
21
|
+
4. **回家核对**
|
|
22
|
+
一趟结束,她这趟写下的东西会一条条列出来,默认全算上。
|
|
23
|
+
- 不想算的,把前面的勾去掉;
|
|
24
|
+
- 也可以整趟不算;
|
|
25
|
+
- 如果这期间她的记录被人动过(人为或意外),这趟会先不算数,你把记录恢复原样,再点「核对一次」。
|
|
26
|
+
|
|
27
|
+
**出门是实验功能。** 第一次进这个页会要求你点一下「我知道了,开始用」。最坏的情况不是数据坏了,是她可能把不该看的内容写进日记,而**日记撤不回**。接受不了这一点,就别点确认。
|
|
28
|
+
|
|
29
|
+
想退回去:到 GitHub 的 Releases 页面下载 v0.7.5 的源码包,解压后用「设置 → 插件 → 从本地安装」选那个文件夹。数据格式没变,回退之后记录照常能读。
|
|
30
|
+
|
|
31
|
+
## 二、她可以主动问你了
|
|
32
|
+
|
|
33
|
+
以前她想改作息、想歇一天,只能在聊天里提一句,等你自己看到。现在她可以直接弹一张卡问你:
|
|
34
|
+
|
|
35
|
+
- 选项是「可以」「这次不行」,或者「以后再说」;
|
|
36
|
+
- 一天最多问一次,一周最多三次(写死的,不用你配);
|
|
37
|
+
- 答应了就真的照办:改作息,或者当天不叫她;
|
|
38
|
+
- 不答应就记下来,不会追着问第二次;过了一天没答,自动算「以后再说」;
|
|
39
|
+
- 在**设置 → 大肥鱼 → 住所 → 她的请求**里,能看到她问过什么、你怎么答的,没答的可以补答。
|
|
40
|
+
|
|
41
|
+
## 三、她开始记住你说的话
|
|
42
|
+
|
|
43
|
+
你们聊天时,她每 3 轮会记下你说过的一句原话(不加工、不改写)。以后翻回忆,那句话会显示成「他说:……」,还带「几天前」。
|
|
44
|
+
|
|
45
|
+
不想要:设置里把「每几轮记一句」改成 0 就关掉了。
|
|
46
|
+
|
|
47
|
+
## 四、翻回忆更好用了
|
|
48
|
+
|
|
49
|
+
- 默认翻**全部时间**,不再只翻最近 30 天;
|
|
50
|
+
- 一次给 8 条(以前 5 条),最多能要 20 条;
|
|
51
|
+
- 可以只看某一类,比如只看「你说过的话」;
|
|
52
|
+
- 重要的记忆会排前面,每条都标着「多少天前」。
|
|
53
|
+
|
|
54
|
+
## 五、记忆体检
|
|
55
|
+
|
|
56
|
+
位置:**设置 → 大肥鱼 → 记忆 → 记忆体检**,点「查一下」。
|
|
57
|
+
|
|
58
|
+
它只做四件事:找出哪两句话对不上、哪些判断快被忘了、哪些快固定下来了、一共记了多少条跨了多少天。
|
|
59
|
+
|
|
60
|
+
只给你看,不进她的界面——**这不是她的分数**。
|
|
61
|
+
|
|
62
|
+
## 六、开两个 DSH 窗口不再重复建对话
|
|
63
|
+
|
|
64
|
+
以前开第二个窗口会多长一条会话,还会多叫醒她一次。现在第二个窗口是只读的,会提示「这个家在别处也开着」;关掉另一个窗口,它就自动接管。
|
|
65
|
+
|
|
66
|
+
## 七、顺手修掉的小问题
|
|
67
|
+
|
|
68
|
+
- 一天里的几次叫醒不再一分钟一个连着发,也不会打断她正在说的话;
|
|
69
|
+
- B 站没登录时也能正常读到视频信息(以前常常只有标题和播放量);
|
|
70
|
+
- 设置页「去上网页存」按钮点了没反应——修好了(GitHub issue #12);
|
|
71
|
+
- 日志不再刷屏,该记的也记上了;
|
|
72
|
+
- 出门、请神的整套界面文案换成了说人话的版本。
|
|
73
|
+
|
|
74
|
+
## 怎么升级
|
|
75
|
+
|
|
76
|
+
1. 在 DSH 里打开「设置 → 插件」,检查更新,装 v0.8.0;或者
|
|
77
|
+
2. 到 GitHub 的 Releases 页面下载这次的源码包,解压后用「设置 → 插件 → 从本地安装」选那个文件夹。
|
|
78
|
+
|
|
79
|
+
> 这个插件**不走 npm**(`dsh-fish` 这个名字在 npm 上属于另一个项目),别用 `npm i dsh-fish` 装。
|
|
80
|
+
|
|
81
|
+
装完**重启 DSH**(插件只在启动时加载)。重启后第一次进「出门」页看到确认卡,是正常的。
|
|
82
|
+
|
|
83
|
+
## 出问题了怎么办
|
|
84
|
+
|
|
85
|
+
- 先看日志:`~\.dsh-fish\logs\dsh-fish.log`,第一行会写这次启动的版本号;
|
|
86
|
+
- 反馈时带三样:版本号、截图、`~\.dsh-fish\possessions.json` 最后一条的 `status`;
|
|
87
|
+
- 记录被判「对不上」不是 bug:说明文件在出门期间被改过,把文件恢复成出门时的样子,再点「核对一次」。
|