dsh-daughter 0.0.0-stage → 0.6.2
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/LICENSE +21 -0
- package/README.md +303 -3
- package/bin/connector-token.mjs +78 -0
- package/client.js +65 -0
- package/config.yaml +315 -0
- package/cordis.patch.yml +4 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +506 -0
- package/dist/host.d.ts +34 -0
- package/dist/host.js +952 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +894 -0
- package/dist/runtime/body-link.d.ts +33 -0
- package/dist/runtime/body-link.js +78 -0
- package/dist/runtime/connector-auth.d.ts +56 -0
- package/dist/runtime/connector-auth.js +148 -0
- package/dist/runtime/content.d.ts +58 -0
- package/dist/runtime/content.js +338 -0
- package/dist/runtime/desktop-input.d.ts +64 -0
- package/dist/runtime/desktop-input.js +260 -0
- package/dist/runtime/desktop-observe.d.ts +95 -0
- package/dist/runtime/desktop-observe.js +284 -0
- package/dist/runtime/douyin-link.d.ts +49 -0
- package/dist/runtime/douyin-link.js +102 -0
- package/dist/runtime/expression.d.ts +60 -0
- package/dist/runtime/expression.js +113 -0
- package/dist/runtime/filter.d.ts +52 -0
- package/dist/runtime/filter.js +170 -0
- package/dist/runtime/maintenance.d.ts +81 -0
- package/dist/runtime/maintenance.js +946 -0
- package/dist/runtime/memory.d.ts +59 -0
- package/dist/runtime/memory.js +313 -0
- package/dist/runtime/mood-motion.d.ts +32 -0
- package/dist/runtime/mood-motion.js +55 -0
- package/dist/runtime/motivation.d.ts +65 -0
- package/dist/runtime/motivation.js +282 -0
- package/dist/runtime/observability.d.ts +56 -0
- package/dist/runtime/observability.js +111 -0
- package/dist/runtime/panels.d.ts +55 -0
- package/dist/runtime/panels.js +352 -0
- package/dist/runtime/personality.d.ts +70 -0
- package/dist/runtime/personality.js +387 -0
- package/dist/runtime/pet-link.d.ts +87 -0
- package/dist/runtime/pet-link.js +129 -0
- package/dist/runtime/reset.d.ts +40 -0
- package/dist/runtime/reset.js +253 -0
- package/dist/runtime/safety.d.ts +7 -0
- package/dist/runtime/safety.js +67 -0
- package/dist/runtime/speak.d.ts +79 -0
- package/dist/runtime/speak.js +277 -0
- package/dist/runtime/state.d.ts +12 -0
- package/dist/runtime/state.js +160 -0
- package/dist/runtime/vpet-control.d.ts +53 -0
- package/dist/runtime/vpet-control.js +172 -0
- package/dist/runtime/vpet-events.d.ts +152 -0
- package/dist/runtime/vpet-events.js +237 -0
- package/dist/store.d.ts +204 -0
- package/dist/store.js +1074 -0
- package/dist/types.d.ts +892 -0
- package/dist/types.js +1 -0
- package/dist/util.d.ts +69 -0
- package/dist/util.js +246 -0
- package/icon.svg +13 -0
- package/index.js +8 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +82 -6
- package/web/star-map/index.html +1411 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 han0han0le0ni
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,303 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# dsh-daughter
|
|
2
|
+
|
|
3
|
+
给 DSH 的"大脑"插件:**人格分层、性格演化、长期记忆、运行时状态、技能与反射、安全降级**。它不负责表现层——气泡、形象、动效由桌宠端决定。
|
|
4
|
+
|
|
5
|
+
> 记忆跟着角色走,不跟着会话走:换对话框、换工作区,关系与经历都还在。
|
|
6
|
+
|
|
7
|
+
## 对接对象(先看这张表)
|
|
8
|
+
|
|
9
|
+
| 项 | 具体是什么 |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| 桌宠软件 | **VPet-Simulator**(虚拟桌宠模拟器,Steam 版,Windows / WPF)。本机实测游戏版本 `11074`,构建引用其 `VPet-Simulator.Windows.Interface.dll` 等 5 个 DLL |
|
|
12
|
+
| 配套 MOD | **`DshDaughter`**(`PluginName = dshdaughter`)——自己写的 **C# 代码 MOD**,不是 Steam 创意工坊的现成 MOD |
|
|
13
|
+
| 是否改游戏本体 | **否**。不替换、不 patch VPet 的任何文件;MOD 只通过 VPet 官方 `MainPlugin` 扩展点加载 |
|
|
14
|
+
| 是否改第三方 MOD | **否**。仓库里的 10 个 `.cs` 全部为新增代码,没有基于别人的 MOD 改造 |
|
|
15
|
+
| 两端怎么通信 | 只有 HTTP:MOD 轮询 `http://127.0.0.1:47612/vpet/events`,处理完 `POST /vpet/events/ack`;状态回传 `/vpet/consumer/report`,身体信号 `/vpet/heartbeat` |
|
|
16
|
+
| 另一个可选前端 | `connectors/pet-shell`(独立 WPF 壳),不启动游戏,直接读 VPet 的 PNG 素材帧;与 MOD **共用一个 ack 游标,只能二选一运行** |
|
|
17
|
+
|
|
18
|
+
## 桌宠联动
|
|
19
|
+
|
|
20
|
+
### A. VPet-Simulator + `DshDaughter` MOD(推荐)
|
|
21
|
+
|
|
22
|
+
**装到哪里**:VPet 安装目录下的 `mod\DshDaughter\`,结构为
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
<VPet 安装目录>\
|
|
26
|
+
└── mod\
|
|
27
|
+
└── DshDaughter\
|
|
28
|
+
├── info.lps # MOD 清单(vupmod#DshDaughter / author / gamever 11074)
|
|
29
|
+
└── plugin\
|
|
30
|
+
├── DshDaughter.dll # .NET 编译产物
|
|
31
|
+
└── token.txt # 连接器令牌(v0.6.1 起必需,见下)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**令牌怎么拿**:插件端点不再接受"本机来的就放行"(详见设计文档 §12.2)。先让插件跑起来一次(会生成 `brain/brainstem/connector_token`),然后:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run connector:token -- --write-to "<VPet 安装目录>\mod\DshDaughter\plugin"
|
|
38
|
+
# 从 npm 安装的用户:
|
|
39
|
+
npx dsh-daughter-token --write-to "<VPet 安装目录>\mod\DshDaughter\plugin"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
也可以手动把 `brain/brainstem/connector_token` 的内容复制成 `plugin/token.txt`,或设置环境变量 `DSH_DAUGHTER_TOKEN`。令牌缺失时 MOD 仍会启动,但请求会被 401 拒绝,日志里会写明原因。
|
|
43
|
+
|
|
44
|
+
**怎么编译**(MOD 源码在 `connectors/vpet/mod-src/`,目标框架 `net10.0-windows`):
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
cd connectors/vpet/mod-src
|
|
48
|
+
dotnet build -c Release -p:VPetDir="E:\SteamLibrary\steamapps\common\VPet"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`VPetDir` 默认就是上面那个路径,装在别处时用参数覆盖。5 个 VPet 程序集以 `Private=false` 引用,**不随 DLL 分发**,运行时由游戏自身提供。
|
|
52
|
+
|
|
53
|
+
**怎么装**:把 `bin/Release/DshDaughter.dll` 复制到 `mod\DshDaughter\plugin\`,把 `info.lps` 复制到 `mod\DshDaughter\`,重启游戏。日志写在游戏目录的 `dsh-daughter-mod.log`。
|
|
54
|
+
|
|
55
|
+
**改了哪些文件**(全部为新增,`connectors/vpet/mod-src/`):
|
|
56
|
+
|
|
57
|
+
| 文件 | 职责 |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `Plugin.cs` | 唯一入口,继承 `MainPlugin`;1s 轮询、游标推进、忙闲裁决、置顶自愈 |
|
|
60
|
+
| `DshClient.cs` | HTTP 客户端:`/vpet/events`、`/vpet/events/ack`、`/vpet/consumer/report`、`/vpet/heartbeat` |
|
|
61
|
+
| `EventRouter.cs` | 把 `thinking / tool / reply / error / motion / move` 事件翻译成气泡与待执行指令 |
|
|
62
|
+
| `MotionPlayer.cs` | 播放 VPet 原生 `GraphType` 动画,处理旧动画回调不打断新动画 |
|
|
63
|
+
| `PetWindowController.cs` | 窗口置顶、相对像素平移、头顶锚点 |
|
|
64
|
+
| `InteractionGuard.cs` | 玩家摸头/点击后的短时间内本地优先,DSH 动作排队等待 |
|
|
65
|
+
| `CommandQueue.cs` | 待执行桌宠指令的排队与去重 |
|
|
66
|
+
| `ConsumerState.cs` | 能力清单(支持的 GraphType)、忙闲、玩家交互,上报给 DSH |
|
|
67
|
+
| `CloudBubble.cs` | 头顶云朵气泡:点击穿透、不抢焦点、默认 6s 淡出 |
|
|
68
|
+
| `PetLog.cs` | 异步轻量日志,避免 UI 线程被文件 I/O 拖住 |
|
|
69
|
+
| `info.lps` | MOD 清单(游戏读取的元信息) |
|
|
70
|
+
|
|
71
|
+
**行为边界**:MOD 只调用 VPet 公开 API(`IMainWindow`、`GraphInfo.GraphType`、气泡与窗口句柄),不写 VPet 存档;插件侧对身体信号只做单向只读(见设计文档 §12.1)。
|
|
72
|
+
|
|
73
|
+
### B. `connectors/pet-shell`(独立壳,可选)
|
|
74
|
+
|
|
75
|
+
不启动游戏本体,直接按 VPet 素材目录的 PNG 序列帧播放。
|
|
76
|
+
|
|
77
|
+
- 素材默认探测 `...\VPet\mod\0000_core\pet\vup`,也可在设置里改
|
|
78
|
+
- 配置在 `%LOCALAPPDATA%\DshPet\pet.json`(首次启动生成):素材路径、缩放、置顶、点击穿透、气泡、桥地址
|
|
79
|
+
- 桥地址默认 `http://127.0.0.1:47612`(旧版本写死的 `47614` 是桌面连接器端口,启动时会自动纠正)
|
|
80
|
+
- 与 MOD 共用同一 ack 游标,**同时开会互相抢事件**,只保留一个
|
|
81
|
+
|
|
82
|
+
### C. 其它连接器
|
|
83
|
+
|
|
84
|
+
| 连接器 | 端口 / 入口 | 说明 |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `connectors/android` | ADB | 受限动作 + 前台事件,需 `adb` 可用 |
|
|
87
|
+
| `connectors/desktop` | `127.0.0.1:47614` | 窗口/前台/媒体查询、截图、抽帧、ffmpeg 推流、输入注入 |
|
|
88
|
+
| 外部消息通用入口 | `POST /connectors/<source>/ingest` | QQ / Minecraft / 单机暂走这里,来源白名单校验;抖音改走共享记忆只读拉取(见「抖音联动」) |
|
|
89
|
+
|
|
90
|
+
## 能力
|
|
91
|
+
|
|
92
|
+
| 模块 | 内容 |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| 人格 | L1 基线 / L2 关系 / L3 认知 / L4 情境子人格 / L5 运行时状态;L1–L4 慢速写回并留演化日志,L5 不写回人格 |
|
|
95
|
+
| 记忆 | 摘要层 + 全文层分离;SQLite FTS5 trigram + Dice 双路;五维加权(语义/近因/权重/情绪/链接);一跳二跳联想 + 概率联想;衰减、归档、情绪历史合并 |
|
|
96
|
+
| 认知滤网 | 写入前四类裁决(屏蔽 / 丢弃 / 合并 / 放行)+ 来源可信度降权 + 显著性 + 习惯化签名 + 定期忘却;存量治理脚本 |
|
|
97
|
+
| 技能与资产 | `draft → active → frozen → deprecated`;按技能形态自动固化为 MAC / CON / CMB / MOT,失败两次自动回退 |
|
|
98
|
+
| 行为动机 | 人格双通路(降阈值 + 方向舵)、熟悉度倒 U、记忆三路径、情绪覆盖、情境乘子;分数与阈值比较后给出 `act / hold / avoid`;失败熔断;零信号恒不触发 |
|
|
99
|
+
| 主动开口 | **默认关闭**。开启后按思念/人格/情绪/关系决定要不要自己开口;欲言又止会攒劲;安静时段、冷却期、日上限兜底;模板文案经可插拔出口投递到桌宠气泡 |
|
|
100
|
+
| 反射 | 关键词 / 正则 / 状态 / 事件四类匹配,毫秒级,不调用模型(短路默认关闭) |
|
|
101
|
+
| 安全 | 三档降级 + 滞回 + 写类工具熔断 + 输出侧诊断词检查;只描述强度与持续时间 |
|
|
102
|
+
| 注入预算 | 硬上限 3000 tokens,按优先级裁剪,`constraint` 永不裁 |
|
|
103
|
+
| 星图 | `/star-map/` 只读可视化:九个星系、Canvas 2D 手写透视、无需联网与 three.js |
|
|
104
|
+
|
|
105
|
+
## 安装
|
|
106
|
+
|
|
107
|
+
三种方式,按需选一种。
|
|
108
|
+
|
|
109
|
+
**1. 通过 DSH 插件市场(推荐)**
|
|
110
|
+
|
|
111
|
+
仓库自带一份 format 1 索引:[`market/index.json`](market/index.json)。在 DSH 里打开 **插件 → 发现 → 索引源 → 添加**,填入:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
https://fastly.jsdelivr.net/gh/han0han0le0ni/dsh-daughter@main/market/index.json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
(`cdn.jsdelivr.net` 同路径也可;部分网络下它会被重置,`fastly` 节点更稳。)
|
|
118
|
+
|
|
119
|
+
之后在「发现」里搜 `daughter` 安装即可。索引里每个版本都钉死了 commit,装到的是可复现的版本。
|
|
120
|
+
|
|
121
|
+
> 社区目录(`dsh-plugin-catalog`,也就是「发现」里默认那份)收录的是 npm 上的包,本插件发布到 npm 之后会被抓取;在那之前,请用上面的自带索引源。
|
|
122
|
+
|
|
123
|
+
**2. 直接从 git 装**
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
dsh plugin add git+https://github.com/han0han0le0ni/dsh-daughter.git
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**3. 本地开发**
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm install
|
|
133
|
+
npm run build # tsc → dist/
|
|
134
|
+
npm test # 211 项
|
|
135
|
+
npm run check:link # 适配性 / 联动性自检,19 项
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> 仓库里提交了 `dist/`:市场与 git 安装没有构建步骤,必须带一份可直接加载的产物。改了 `src/` 记得 `npm run build` 再提交(`prepare` 脚本也会兜一层)。
|
|
139
|
+
|
|
140
|
+
- 运行配置见 `config.yaml`(数值均有范围校验,非法值回落默认并告警)。
|
|
141
|
+
- 运行时数据写到 `data_root`(默认 `.`),目录按脑区划分:`brain/hippocampus`、`brain/neocortex`、`brain/prefrontal` 等。
|
|
142
|
+
- 桌宠是可选件:没有 MOD、没有 bridge、没有 `vpet` 配置时,插件行为与"完全不知道桌宠存在"一致。
|
|
143
|
+
|
|
144
|
+
## 记忆体检
|
|
145
|
+
|
|
146
|
+
记忆是「SQLite 索引 + 全文/归档文件 + 星图」三层,容易出现"表里删了、文件还在"这类对不上的状态。`npm run memory:doctor` 只读扫一遍,`--fix` 才动手修:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npm run memory:doctor -- --root=<数据根> # 只报告
|
|
150
|
+
npm run memory:doctor -- --root=<数据根> --fix # 修可安全修的那几项
|
|
151
|
+
npm run memory:doctor -- --root=<数据根> --json # 给脚本用
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
检查项:SQLite 完整性、事件/归档计数、孤儿回看记录、FTS 索引是否真的查得到已有事件(外部内容表的 `COUNT(*)` 和 `integrity-check` 都看不出索引被清空,所以用真实标题做功能探针)、全文与归档文件的缺失/孤儿、字段越界、出边悬空/自环/重复/超过 12 条上限、星图边的引用一致性。
|
|
155
|
+
|
|
156
|
+
`--fix` 的动作都是可逆或安全的:孤儿文件移到 `logs/memory-doctor-trash/<时间戳>/`(不删)、缺失全文用摘要补一份、悬空边从出边里摘掉、越界值夹回 0..1、FTS 必要时 rebuild。
|
|
157
|
+
|
|
158
|
+
## 重置数据
|
|
159
|
+
|
|
160
|
+
清记忆 / 恢复出厂人格 / 清条件反射 / 清技能 / 恢复出厂设置,都走 `npm run reset`。默认只列清单(dry-run),加 `--apply` 才真的删,删完会读回真实状态复核,复核不过退出码非 0:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npm run reset -- memory # 只报告:会清掉多少事件、回看、全文与归档
|
|
164
|
+
npm run reset -- memory --apply # 清记忆
|
|
165
|
+
npm run reset -- personality --apply # 人格恢复出厂 L1–L4
|
|
166
|
+
npm run reset -- reflex --apply # 反射规则与冷却状态
|
|
167
|
+
npm run reset -- skills --apply # 技能卡与动作模板
|
|
168
|
+
npm run reset -- all --apply --yes # 恢复出厂设置(多一道 --yes 确认)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
可选:`--no-backup` 跳过备份、`--root=<路径>` 指定数据根。建议先停掉 DSH 再重置,否则插件会把内存里的状态写回去。
|
|
172
|
+
|
|
173
|
+
被清掉的目录不会递归删除,而是整体移到 `logs/reset-trash/<时间戳>/`(想捞回来搬回去即可);备份在 `logs/reset-backup/<时间戳>/`。
|
|
174
|
+
|
|
175
|
+
## 目录
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
src/ 插件主体(23 个 TS 文件)
|
|
179
|
+
runtime/ 记忆、人格、状态、动机、主动开口、安全、滤网、反射、可观测性
|
|
180
|
+
scripts/ 自检与存量治理(link-check / filter-sweep / reset / memory-doctor)
|
|
181
|
+
connectors/
|
|
182
|
+
vpet/ VPet MOD 源码(mod-src/,10 个 .cs + info.lps)与桥接脚本(bridge.mjs)
|
|
183
|
+
pet-shell/ 独立 WPF 壳(读 VPet 素材,不启动游戏)
|
|
184
|
+
android/ ADB 受限动作
|
|
185
|
+
desktop/ 桌面观察与输入
|
|
186
|
+
web/ 星图页面(纯静态)
|
|
187
|
+
tests/ 21 个测试文件
|
|
188
|
+
docs/ 设计文档、实现核对、评估、检测报告
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 文档
|
|
192
|
+
|
|
193
|
+
- [设计文档](docs/dsh-daughter-design.md)——数据模型、检索算法、接口契约、里程碑
|
|
194
|
+
- [实现核对](docs/dsh-daughter-实现核对.md)——完成度、代码落点、剩余缺口
|
|
195
|
+
- [记忆 / 情感评估](docs/dsh-daughter-记忆情感评估.md)——真实数据体检与改进优先级
|
|
196
|
+
- [检测报告](docs/dsh-daughter-检测报告.md)——适配性与联动性自检结果
|
|
197
|
+
|
|
198
|
+
## 性格演化
|
|
199
|
+
|
|
200
|
+
出生时五维按有界区间抽样,并把结果写入 `innate` 锚点;同角色同种子可复现。日常闲聊不动人格,只有累积/关键事件才按通道推动五维,任一项不超出锚点 `±0.6`。依恋底色出生只抽安全/焦虑/回避,混乱型只能靠经历演化。面板只展示证据与数值,不输出"你是 X 型"的结论。完整规则见设计文档 §4.8。
|
|
201
|
+
|
|
202
|
+
## 行为动机
|
|
203
|
+
|
|
204
|
+
决策层不再用"文本相似度过线"就执行技能,而是给每个技能算一个动机分,再和阈值比。两层结构,职责不重叠:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
阈值侧(够不够力) skills.min_main_score + 人格偏移 + 情绪偏移 → 不低于 min_threshold
|
|
208
|
+
分数侧(想不想走) signal ×(熟悉度)×(记忆)×(情境)×(方向舵) → 0..1
|
|
209
|
+
决策 熔断 → avoid;零信号 → avoid;score ≥ 阈值 → act;≥ 0.7×阈值 → hold
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**人格走两条独立通路**,这是这套设计的关键:
|
|
213
|
+
|
|
214
|
+
| 通路 | 参数 | 作用 | 类比 |
|
|
215
|
+
| --- | --- | --- | --- |
|
|
216
|
+
| 阈值偏移 | `trait_threshold_gain` | 五维按通道映射成阈值的升降 | 门有多重 |
|
|
217
|
+
| 方向舵 | `trait_signal_gain` | 五维按通道映射成分数乘子 `1±g` | 更想走哪条路 |
|
|
218
|
+
|
|
219
|
+
只有阈值通路时,人格无法影响"几个候选技能里选哪个",只能影响"一个都别选"——所以补了方向舵。方向舵是**乘子不是加项**:`signal=0` 时乘什么都不会高于 0,零信号永远不会被凭空变成行动。
|
|
220
|
+
|
|
221
|
+
其余因子:
|
|
222
|
+
|
|
223
|
+
- **熟悉度倒 U**:`exposure = uses/(uses+k)`,太少犹豫、太多厌倦,峰值在 `peak`。
|
|
224
|
+
- **记忆三路径**:结果预期(按 `lastUsedAt` 半衰)/情绪记忆(近 `lookback_days` 天相关事件的愉悦度)/自我效能(L3 自我价值),权重归一化。
|
|
225
|
+
- **情绪覆盖**:安全感低、压力高、心情低、疲劳高 → 更谨慎;高唤醒 → 更容易动。总偏移被 `clamp_min/max` 截断。
|
|
226
|
+
- **情境乘子**:关系深度 + 子人格披露度,社交通道吃满,其余通道折半。
|
|
227
|
+
- **失败熔断**:连续失败 `fail_streak` 次进入指数冷却,期间只 `avoid`,成功即清零。
|
|
228
|
+
|
|
229
|
+
每个技能的因子都留在 `MotivationBreakdown` 里(`signal / personalityOffset / emotionOffset / threshold / familiarityGain / memoryGain / situationMultiplier / traitSignalGain / score / decision`),面板与日志可以逐项复算。`motivation.enabled = false` 时退回旧的相似度打分,便于对照。数值含义与取值范围见 `config.yaml` 注释。
|
|
230
|
+
|
|
231
|
+
## 主动开口
|
|
232
|
+
|
|
233
|
+
没人说话的时候,她会不会自己开口。这条链和上面的动机层是分开的:动机回答"这个技能该不该用",需要用户输入;主动开口回答"这会儿想不想说话",信号来自沉默时长而不是文本。
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
强度侧(想不想) 思念累积 + 人格 + 情绪 + 关系 + 上一轮攒下的"憋劲"
|
|
237
|
+
门槛侧(合不合适) 基础阈值 + 安静时段 + 压力
|
|
238
|
+
决策 冷却期/日上限 → silent;urge ≥ 阈值 → act;≥ 0.75×阈值 → hold
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
拟人靠三件事:
|
|
242
|
+
|
|
243
|
+
- **思念有饱和**:`idle / (idle + 180min)`。沉默一小时只有 0.25,十小时到 0.77——不会两小时没回就急,但一整天没动静会明显想说话。
|
|
244
|
+
- **欲言又止**:`hold` 不是失败。它把"这次的憋劲"累进 `carry`,攒够下一次才真开口。所以会看到"她想了好几次,最后才说一句"。
|
|
245
|
+
- **时机不对就不说**:安静时段(默认 0–7 点)抬门槛 0.35,压力大再抬 0.06;刚说过话有 90 分钟冷却;一天最多 5 次。她说完话也算"刚联系过",不会因为对方没回就靠沉默累积刷屏。
|
|
246
|
+
|
|
247
|
+
文案按动机分类取池(想念 / 关心 / 分享 / 不安 / 无聊),最近 5 句会被避开。**目前是模板,不是模型生成**——接模型后可替换这一层,其余决策逻辑不用动。
|
|
248
|
+
|
|
249
|
+
**默认是关闭的**(`speak.enabled: false`)。"她会自己开口"属于自主行为,装完插件不该自动开始——要用就改成 `true`,并确认桌宠在跑。
|
|
250
|
+
|
|
251
|
+
**能看见屏幕时会先看场景。** `connectors/desktop` 桥接在跑时,每次评估先读一眼前台窗口,按打扰成本抬门槛:开会 ×0.85、游戏 ×0.7、写代码 ×0.4、其它 ×0.15(再乘 `busy_penalty 0.25`)。桥接没启动就静默跳过——不会因为探测失败变成一整天不说话的哑巴。
|
|
252
|
+
|
|
253
|
+
投递走可插拔的表达出口(`expression.sinks`,类型 `ExpressionSink`):`pet` 投给 DSH 内置桌宠 dsh-pet(气泡走 `/dsh-pet-7340/broadcast`,情绪动作走 `/anim`),`vpet` 把文本塞进 VPet 的 `/vpet/events` 队列(`kind: reply`),`http` 把事件 JSON POST 给任意应用,`file` 追加 JSONL 供本地 `tail -f`。多个出口可同时开,并发投递、单个出口抛错不影响其他;决策层只负责"想说什么",往哪发由配置决定,加一个出口不用动决策。
|
|
254
|
+
|
|
255
|
+
**换了桌宠不用改代码。** `pet` 出口的地址由宿主自己拼(`webServer` 端口 + dsh-pet 的路由段),不需要填端口;出厂配置只有 `vpet` 时,启动会探一下 dsh-pet 在不在,在就让它接管(`prefer_pet: true`),免得两套桌宠把同一句话各弹一遍。VPet 卸掉之后,`vpet` 出口只是往没人消费的队列里写,不会再出现在屏幕上。
|
|
256
|
+
|
|
257
|
+
**干活时桌宠也会动。** dsh-pet 接管后,她的 thinking / tool / reply / error 会点播成 dsh-pet 内置的工作状态动画(`events.workStatus`):思考冒泡、忙碌点按、清点归档、垂头叹气冒汗。这些动画是 dsh-pet 自带的,不用从 VPet 搬素材——两边的动作词汇表不通用,VPet 认 `GraphType`(Say/Touch_Head/Sleep),dsh-pet 认它素材目录里的中文名,所以按接管方各选各的。
|
|
258
|
+
|
|
259
|
+
**说过的话留痕。** 星图面板的「主动开口」分组能翻到:今天开口几次、几次欲言又止、憋着多少劲、最近说过哪几句。没有这块的话,她说什么只存在于气泡队列里,测完什么都看不到。
|
|
260
|
+
|
|
261
|
+
没有桌宠在轮询时,消息只会入队、不会出现在聊天记录里——插件没有往宿主会话里插消息的权限。
|
|
262
|
+
|
|
263
|
+
## 抖音联动
|
|
264
|
+
|
|
265
|
+
装了 `dsh-douyin-browser-local` 时,她能知道你刷了什么。不是靠对方推送——那个插件没有对外事件或 webhook——而是**只读**它的共享记忆库(`~/.dsh/douyin-browser/memory/shared.sqlite`)里 `origin='video'` 的条目,把新出现的记录写成自己的一条事件(`source: douyin_content`),之后走同一套认知滤网、衰减与联想。
|
|
266
|
+
|
|
267
|
+
- **只读连接**:不写对方的库,观看记录也不会被反向同步回去
|
|
268
|
+
- **游标在内存里推进**:首次启动与长时间关机后只补最近 24 小时,不把上周刷的当成"刚看到的"
|
|
269
|
+
- **失败即静默**:库不存在、表结构变了、运行环境没有 `node:sqlite`,都只是"这次没有新内容",不影响其它功能
|
|
270
|
+
- 参数在 `config.yaml` 的 `douyin` 段:`enabled` / `memory_db` / `poll_interval_min`(默认 10 分钟)/ `max_items`(单次最多 5 条)
|
|
271
|
+
|
|
272
|
+
## 当前状态
|
|
273
|
+
|
|
274
|
+
P0–P8 已落地并核对(当前 `npm test` **211 项全绿**,`check:link` PASS 19);P9 外部连接 4/7(VPet 桌宠 / Android / 桌面已通,抖音走只读共享记忆拉取,QQ、Minecraft、单机待适配器)。已知短板与后续优先级见上面两份文档。
|
|
275
|
+
|
|
276
|
+
## 发布(维护者)
|
|
277
|
+
|
|
278
|
+
**两个渠道必须一起更新**:只 push GitHub 不发布 npm,插件市场「发现」里装到的仍是旧版。
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# 1. 版本 + 构建 + 校验
|
|
282
|
+
npm version <ver> --no-git-tag-version
|
|
283
|
+
npm run build && npm test && npm run check:link
|
|
284
|
+
|
|
285
|
+
# 2. 推送 GitHub,并把市场索引钉到本次发布提交
|
|
286
|
+
git add -A && git commit -m "feat(...): ..."
|
|
287
|
+
git push origin main
|
|
288
|
+
# 编辑 market/index.json:新增 { version, publishTimestamp, source.commit = 发布提交号 }
|
|
289
|
+
git add market/index.json && git commit -m "chore(market): 索引锁定到 <ver>(<sha>)" && git push origin main
|
|
290
|
+
|
|
291
|
+
# 3. 发布 npm(社区目录靠它抓取)
|
|
292
|
+
npm publish
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
发布后可用 `npm view dsh-daughter version` 与 `npx dsh-daughter-token --json` 验证;jsDelivr 对 `@main` 有缓存,索引更新后可请求 `https://purge.jsdelivr.net/gh/han0han0le0ni/dsh-daughter@main/market/index.json` 刷新。
|
|
296
|
+
|
|
297
|
+
## 隐私
|
|
298
|
+
|
|
299
|
+
`brain/`、`logs/`、`archive/`、`star_map/`、`docs/screenshots/` 与 C# 的 `bin/obj` 均排除在版本库之外:前四者包含真实对话记忆、人格状态与界面截图,只在本地生成。`dist/` 例外——**故意提交**,因为市场与 git 安装没有构建步骤。
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
[MIT](LICENSE) © 2026 han0han0le0ni
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 连接器令牌工具:打印、导出、轮换。
|
|
4
|
+
*
|
|
5
|
+
* 桥接端点(47612)与桌面 / 安卓连接器(47614 / 47613)都要求令牌,
|
|
6
|
+
* VPet MOD、独立壳、第三方脚本需要拿到同一个值才能连上。
|
|
7
|
+
*
|
|
8
|
+
* 这里直接用 dist/ 里的实现,所以 npm 安装的用户也能用:
|
|
9
|
+
* npx dsh-daughter-token
|
|
10
|
+
* npx dsh-daughter-token --write-to "<MOD 目录>"
|
|
11
|
+
* npx dsh-daughter-token --rotate
|
|
12
|
+
*
|
|
13
|
+
* 参数:
|
|
14
|
+
* --write-to <目录> 同时写入 <目录>/token.txt(MOD / 壳直接读)
|
|
15
|
+
* --rotate 删掉旧令牌重新生成(所有连接器都要换新值)
|
|
16
|
+
* --json 机器可读
|
|
17
|
+
*
|
|
18
|
+
* 从源码仓库运行时等价于 `npm run connector:token`。
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { dirname, join, resolve } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { loadConfig, resolveDataRoot } from '../dist/config.js';
|
|
24
|
+
import { CONNECTOR_TOKEN_FILE, ensureConnectorToken } from '../dist/runtime/connector-auth.js';
|
|
25
|
+
import { silentLogger } from '../dist/util.js';
|
|
26
|
+
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const has = (name) => args.includes(`--${name}`);
|
|
29
|
+
const value = (name, fallback) => {
|
|
30
|
+
const index = args.indexOf(`--${name}`);
|
|
31
|
+
return index >= 0 && args[index + 1] ? args[index + 1] : fallback;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// 插件根目录:bin/ 的上一级
|
|
35
|
+
const pluginRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
36
|
+
|
|
37
|
+
const config = loadConfig(pluginRoot, silentLogger);
|
|
38
|
+
const dataRoot = resolveDataRoot(pluginRoot, config);
|
|
39
|
+
const tokenPath = join(dataRoot, CONNECTOR_TOKEN_FILE);
|
|
40
|
+
|
|
41
|
+
if (has('rotate')) {
|
|
42
|
+
if (existsSync(tokenPath)) rmSync(tokenPath, { force: true });
|
|
43
|
+
console.error('已删除旧令牌,下面输出的是新生成的值。');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const state = ensureConnectorToken(dataRoot, config.security?.connector_token);
|
|
47
|
+
if (!state.token) {
|
|
48
|
+
console.error(`无法取得连接器令牌:${state.path}`);
|
|
49
|
+
console.error(' 检查目录是否可写,或在 config.yaml 的 security.connector_token 里显式指定(≥16 字符)。');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const writeTo = value('write-to', '');
|
|
54
|
+
const written = [];
|
|
55
|
+
if (writeTo) {
|
|
56
|
+
const target = resolve(writeTo, 'token.txt');
|
|
57
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
58
|
+
writeFileSync(target, `${state.token}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
59
|
+
written.push(target);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (has('json')) {
|
|
63
|
+
console.log(JSON.stringify({ token: state.token, source: state.source, path: state.path, files: written }, null, 2));
|
|
64
|
+
} else {
|
|
65
|
+
console.log(`令牌来源:${state.source}`);
|
|
66
|
+
console.log(`令牌文件:${state.path}`);
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(state.token);
|
|
69
|
+
for (const file of written) console.log(`\n已写入:${file}`);
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log('把它交给连接器:');
|
|
72
|
+
console.log(' · VPet MOD:放到 MOD 的 plugin 目录下的 token.txt,或设置环境变量 DSH_DAUGHTER_TOKEN');
|
|
73
|
+
console.log(' · 独立壳 / 桥接脚本:--token <值>,或设置 DSH_DAUGHTER_TOKEN');
|
|
74
|
+
console.log('提示:令牌只在本机使用,不要提交进仓库。');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 打印完立即退出,避免残留句柄把命令挂住
|
|
78
|
+
process.exit(0);
|
package/client.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// dsh-daughter 的浏览器侧入口:在侧边栏「面板」列表里加一个「脑星图」按钮,
|
|
2
|
+
// 点开后由宿主的主栏渲染一张同源 iframe(/star-map/),数据由插件自带的路由提供。
|
|
3
|
+
// 模式与 dsh-thoughtdag / dsh-synapse 一致:window.__ModuleLoader__.load +
|
|
4
|
+
// inject 声明依赖的客户端服务。
|
|
5
|
+
window.__ModuleLoader__.load({
|
|
6
|
+
id: 'dsh-daughter',
|
|
7
|
+
factory: (require) => {
|
|
8
|
+
const module = { exports: {} };
|
|
9
|
+
|
|
10
|
+
let React = null;
|
|
11
|
+
try {
|
|
12
|
+
React = require('react');
|
|
13
|
+
} catch {
|
|
14
|
+
React = null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports.inject = ['slots', 'locale'];
|
|
18
|
+
module.exports.apply = (ctx) => {
|
|
19
|
+
const NS = 'dsh-daughter';
|
|
20
|
+
const CSS_ID = 'dsh-daughter/client.css';
|
|
21
|
+
let style = document.head.querySelector(`style[data-plugin-css="${CSS_ID}"]`);
|
|
22
|
+
if (!style) {
|
|
23
|
+
style = document.createElement('style');
|
|
24
|
+
style.setAttribute('data-plugin', 'dsh-daughter');
|
|
25
|
+
style.setAttribute('data-plugin-css', CSS_ID);
|
|
26
|
+
document.head.append(style);
|
|
27
|
+
}
|
|
28
|
+
style.textContent =
|
|
29
|
+
'.dsh-dd-frame{display:block;width:100%;height:100%;min-height:100%;border:0;background:#06070b}';
|
|
30
|
+
|
|
31
|
+
if (!React || !ctx.slots || !ctx.locale || typeof ctx.effect !== 'function') {
|
|
32
|
+
console.warn('[dsh-daughter] 当前宿主没有面板插槽,脑星图只能通过 /star-map/ 访问');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const h = React.createElement;
|
|
37
|
+
const PanelIcon = ({ size }) =>
|
|
38
|
+
h(
|
|
39
|
+
'svg',
|
|
40
|
+
{ width: size ?? 16, height: size ?? 16, viewBox: '0 0 16 16', 'aria-hidden': 'true' },
|
|
41
|
+
h('circle', { cx: 8, cy: 8, r: 6.2, fill: 'none', stroke: '#6d5dfc', 'stroke-width': 1.4 }),
|
|
42
|
+
h('circle', { cx: 8, cy: 8, r: 2.2, fill: '#f0a35a' }),
|
|
43
|
+
h('circle', { cx: 13.2, cy: 4.4, r: 1.4, fill: '#a99cff' }),
|
|
44
|
+
);
|
|
45
|
+
const PanelPage = () => h('iframe', { className: 'dsh-dd-frame', title: '脑星图', src: '/star-map/' });
|
|
46
|
+
|
|
47
|
+
ctx.effect(
|
|
48
|
+
() => ctx.locale.register(NS, { zh: { panel: '脑星图' }, en: { panel: 'Star Map' } }),
|
|
49
|
+
'dsh-daughter:dictionaries',
|
|
50
|
+
);
|
|
51
|
+
const t = ctx.locale.bind(NS);
|
|
52
|
+
ctx.slots.inject('main', () =>
|
|
53
|
+
ctx.slots.register({ name: 'main', key: 'daughter-starmap', locale: NS, inject: () => ({}) }, PanelPage),
|
|
54
|
+
);
|
|
55
|
+
ctx.slots.inject('sidebar.panellist', () =>
|
|
56
|
+
ctx.slots.register(
|
|
57
|
+
{ name: 'sidebar.panellist', id: 'daughter-starmap', order: 31, locale: NS, label: () => t('panel') },
|
|
58
|
+
PanelIcon,
|
|
59
|
+
),
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return module.exports;
|
|
64
|
+
},
|
|
65
|
+
});
|