koishi-plugin-foxy-memory-bridge 0.1.13 → 0.1.15

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.
Files changed (4) hide show
  1. package/README.md +166 -147
  2. package/lib/handlers.js +408 -324
  3. package/lib/index.js +164 -159
  4. package/package.json +45 -44
package/README.md CHANGED
@@ -1,148 +1,167 @@
1
- # koishi-plugin-foxy-memory-bridge
2
-
3
- 把 DSH 里 Foxy 的对话写入 ChatLuna [`koishi-plugin-chatluna-livingmemory`](https://github.com/Procyon-Nan/koishi-plugin-chatluna-livingmemory),并在下一轮把记忆召回给 DSH。
4
-
5
- 这是 `dsh-foxy-memory` 的可选桥。没有这个桥时,DSH 侧的 Foxy 仍然可以用本地 JSONL 记忆;装上桥之后,DSH 与 QQ 可以共用 `foxy3(Character)` 记忆池。
6
-
7
- ## 链路
8
-
9
- ```text
10
- DSH session (foxy preset)
11
- └─ dsh-foxy-memory (provider: livingmemory)
12
- └─ HTTP POST /foxy-memory/record
13
- └─ koishi-plugin-foxy-memory-bridge
14
- └─ ctx.chatluna_living_memory.createMemory(...)
15
- └─ LivingMemory SQLite + PGlite 索引
16
- ```
17
-
18
- 读取时反向走 `/foxy-memory/context`,桥调用 `searchMemories()`,为空时退回 `listMemories()`。
19
-
20
- 桥不会直接 INSERT `koishi.db`,所以 speaker key、profile、向量索引都由 LivingMemory 自己维护。
21
-
22
- ## 安装
23
-
24
- Koishi 实例内:
25
-
26
- ```powershell
27
- cd C:\Users\MECHREV\AppData\Roaming\Koishi\Desktop\data\instances\default
28
- corepack yarn add "koishi-plugin-foxy-memory-bridge@file:./koishi-plugin-foxy-memory-bridge-0.1.13.tgz"
29
- ```
30
-
31
- Yarn 4 必须写成 `包名@file:路径`;装完在 Koishi 控制台启用 `foxy-memory-bridge`。它依赖:
32
-
33
- - `koishi` ^4.18
34
- - `koishi-plugin-chatluna-livingmemory`(peer,未安装时插件不会加载)
35
-
36
- ## 配置
37
-
38
- | 字段 | 默认 | 说明 |
39
- | --- | --- | --- |
40
- | `path` | `/foxy-memory` | HTTP 路由前缀 |
41
- | `token` | 空 | Bearer token;留空时只允许本机回环访问 |
42
- | `presetKind` | `character` | `character` 用 Character 预设,`chatluna` 用主插件预设 |
43
- | `chatlunaPresetId` | `foxy3` | ChatLuna 主插件预设(动态下拉) |
44
- | `characterPresetId` | `foxy3` | Character 预设(动态下拉;自动补 `(Character)`) |
45
- | `presetId` | `foxy3(Character)` | 兼容旧配置;实际由上面两项计算 |
46
- | `extractModel` | `deepseek/deepseek-flash` | 批量提取记忆用的 ChatLuna 模型 |
47
- | `platform` | `dsh` | speakerKey 的平台名 |
48
- | `userId` | `2242711967` | 人类用户 ID(kunfox) |
49
- | `userLabel` | `kunfox` | 人类显示名 |
50
- | `assistantId` | `2877932816` | Foxy 的 ID |
51
- | `assistantLabel` | `Foxy` | Foxy 显示名 |
52
- | `conversationPrefix` | `dsh:` | 生成 conversationId 的前缀 |
53
- | `maxContext` | `20` | 单次最多返回多少条 |
54
-
55
- 公网/局域网部署时务必设置 `token`。留空只适合 DSH 与 Koishi 在同一台机器。
56
-
57
- ## DSH 侧配置
58
-
59
- `dsh-foxy-memory` 的插件配置:
60
-
61
- ```yaml
62
- provider: livingmemory
63
- bridgeUrl: http://127.0.0.1:5140/foxy-memory
64
- bridgeToken: 与桥的 token 相同
65
- bridgePresetId: foxy3(Character)
66
- ```
67
-
68
- `bridgeUrl` 填到 `/foxy-memory` 为止,不要带 `/record`。配置后默认使用桥;桥失败会自动回退本地 JSONL,不会丢消息。
69
-
70
- ## API
71
-
72
- ### `POST /foxy-memory/ingest`
73
-
74
- DSH 侧每积累一批消息后调用;桥用 `extractModel` 把对话提炼成中文、Foxy 第一人称的长期记忆,再逐条写入 LivingMemory。提示词会明确这是 **DSH 私聊**,生成的记忆以“我记得在 DSH 私聊里,……”开头,而不是“kunfox 说/回复”。
75
-
76
- ```json
77
- {
78
- "sessionId": "session-...",
79
- "presetId": "foxy3(Character)",
80
- "messages": [
81
- { "role": "user", "text": "昨天群里聊了什么?", "at": 1790000000000 },
82
- { "role": "assistant", "text": "外设那摊,轨迹球和短屁股鼠标喵", "at": 1790000001000 }
83
- ]
84
- }
85
- ```
86
-
87
- 返回 `{ ok, presetId, created, ids }`。空内容或模型判断没有值得长期保存的信息时返回 `created: 0`,不会写流水账。
88
-
89
- `/record` 仍保留,用于兼容旧版或手工写单条;新版 DSH 批处理只调用 `/ingest`。
90
-
91
- ### `POST /foxy-memory/record`
92
-
93
- ```json
94
- {
95
- "role": "user",
96
- "text": "kunfox 今天在 DSH 做了插件",
97
- "sessionId": "session-...",
98
- "presetId": "foxy3(Character)"
99
- }
100
- ```
101
-
102
- 写一条 `type: "context"` 的记忆,content 形如:
103
-
104
- ```text
105
- kunfox 在 DSH 说:kunfox 今天在 DSH 做了插件
106
- ```
107
-
108
- ### `POST /foxy-memory/context`
109
-
110
- ```json
111
- { "query": "DSH 插件", "limit": 20, "presetId": "foxy3(Character)" }
112
- ```
113
-
114
- 返回:
115
-
116
- ```json
117
- { "ok": true, "count": 3, "text": "- [2026-11-06 20:00] [DSH] ...", "memories": [] }
118
- ```
119
-
120
- ### `GET /foxy-memory/health`
121
-
122
- 返回 `{ ok, presetId, platform, path, service }`,可用于探活。
123
-
124
- ## 鉴权
125
-
126
- - 设置 `token` 后,请求必须带 `Authorization: Bearer <token>` 或 `X-Foxy-Token: <token>`。
127
- - 未设置 `token` 时只接受 `127.0.0.1` / `::1` 的请求。
128
- - 桥不会把 token 写入日志。
129
-
130
- ## 限制
131
-
132
- - 写入依赖 LivingMemory 的 `createMemory`,所以必须是有效 preset;`foxy3(Character)` 不存在时会返回 500 和提示。
133
- - 召回走 `searchMemories`,向量索引未建立时可能为空,此时桥退回 `listMemories` 最近记录。
134
- - 记忆内容按“DSH 侧的一句话”写入,不做 LLM 摘要/合并;这与 LivingMemory 的 Dream/摘要流程是互补的。
135
- - 桥只处理 Foxy 的 DSH 对话;QQ 侧仍由 ChatLuna 原管线负责。
136
-
137
- ## 测试
138
-
139
- ```powershell
140
- node test/test-bridge.cjs
141
- ```
142
-
143
- 测试使用 mock LivingMemory service,不连接真实实例。
144
-
145
- ## License
146
-
147
- MIT
1
+ # koishi-plugin-foxy-memory-bridge
2
+
3
+ 把 DSH 里 Foxy 的对话写入 ChatLuna [`koishi-plugin-chatluna-livingmemory`](https://github.com/Procyon-Nan/koishi-plugin-chatluna-livingmemory),并在下一轮把记忆召回给 DSH。
4
+
5
+ 这是 `dsh-foxy-memory` 的可选桥。没有这个桥时,DSH 侧的 Foxy 仍然可以用本地 JSONL 记忆;装上桥之后,DSH 与 QQ 可以共用 `chatluna-livingmemory` 记忆池。
6
+
7
+ 从 0.1.15 起,桥还可以让 DSH 侧的 Foxy 通过 QQ 机器人主动发送私聊,用于 B 站视频分享等场景。
8
+
9
+ ## 链路
10
+
11
+ ```text
12
+ DSH session (foxy preset)
13
+ └─ dsh-foxy-memory (provider: livingmemory)
14
+ └─ HTTP POST /foxy-memory/record
15
+ └─ koishi-plugin-foxy-memory-bridge
16
+ └─ ctx.chatluna_living_memory.createMemory(...)
17
+ └─ LivingMemory SQLite + PGlite 索引
18
+ ```
19
+
20
+ 读取时反向走 `/foxy-memory/context`,桥调用 `searchMemories()`,为空时退回 `listMemories()`。
21
+
22
+ 桥不会直接 INSERT `koishi.db`,所以 speaker key、profile、向量索引都由 LivingMemory 自己维护。
23
+
24
+ ## 安装
25
+
26
+ Koishi 实例内:
27
+
28
+ ```powershell
29
+ cd C:\Users\MECHREV\AppData\Roaming\Koishi\Desktop\data\instances\default
30
+ corepack yarn add "koishi-plugin-foxy-memory-bridge@file:./koishi-plugin-foxy-memory-bridge-0.1.15.tgz"
31
+ ```
32
+
33
+ Yarn 4 必须写成 `包名@file:路径`;装完在 Koishi 控制台启用 `foxy-memory-bridge`。它依赖:
34
+
35
+ - `koishi` ^4.18
36
+ - `koishi-plugin-chatluna-livingmemory`(peer,未安装时插件不会加载)
37
+
38
+ ## 配置
39
+
40
+ | 字段 | 默认 | 说明 |
41
+ | --- | --- | --- |
42
+ | `path` | `/foxy-memory` | HTTP 路由前缀 |
43
+ | `token` | 空 | Bearer token;留空时只允许本机回环访问 |
44
+ | `presetKind` | `character` | `character` 用 Character 预设,`chatluna` 用主插件预设 |
45
+ | `chatlunaPresetId` | `foxy3` | ChatLuna 主插件预设(动态下拉) |
46
+ | `characterPresetId` | `foxy3` | Character 预设(动态下拉;自动补 `(Character)`) |
47
+ | `presetId` | `foxy3(Character)` | 兼容旧配置;实际由上面两项计算 |
48
+ | `extractModel` | `deepseek/deepseek-flash` | 批量提取记忆用的 ChatLuna 模型 |
49
+ | `platform` | `dsh` | speakerKey 的平台名 |
50
+ | `userId` | `2242711967` | 人类用户 ID(kunfox) |
51
+ | `userLabel` | `kunfox` | 人类显示名 |
52
+ | `assistantId` | `2877932816` | Foxy 的 ID |
53
+ | `assistantLabel` | `Foxy` | Foxy 显示名 |
54
+ | `botId` | 空 | 发送私聊使用的机器人 selfId;留空优先 `assistantId` |
55
+ | `conversationPrefix` | `dsh:` | 生成 conversationId 的前缀 |
56
+ | `maxContext` | `20` | 单次最多返回多少条 |
57
+
58
+ 公网/局域网部署时务必设置 `token`。留空只适合 DSH 与 Koishi 在同一台机器。
59
+
60
+ ## DSH 侧配置
61
+
62
+ `dsh-foxy-memory` 的插件配置:
63
+
64
+ ```yaml
65
+ provider: livingmemory
66
+ bridgeUrl: http://127.0.0.1:5140/foxy-memory
67
+ bridgeToken: 与桥的 token 相同
68
+ bridgePresetId: foxy3(Character)
69
+ ```
70
+
71
+ `bridgeUrl` 填到 `/foxy-memory` 为止,不要带 `/record`。配置后默认使用桥;桥失败会自动回退本地 JSONL,不会丢消息。
72
+
73
+ ## API
74
+
75
+ ### `POST /foxy-memory/ingest`
76
+
77
+ DSH 侧每积累一批消息后调用;桥用 `extractModel` 把对话提炼成中文、Foxy 第一人称的长期记忆,再逐条写入 LivingMemory。提示词会明确这是 **DSH 私聊**,生成的记忆以“我记得在 DSH 私聊里,……”开头,而不是“kunfox 说/回复”。
78
+
79
+ ```json
80
+ {
81
+ "sessionId": "session-...",
82
+ "presetId": "foxy3(Character)",
83
+ "messages": [
84
+ { "role": "user", "text": "昨天群里聊了什么?", "at": 1790000000000 },
85
+ { "role": "assistant", "text": "外设那摊,轨迹球和短屁股鼠标喵", "at": 1790000001000 }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ 返回 `{ ok, presetId, created, ids }`。空内容或模型判断没有值得长期保存的信息时返回 `created: 0`,不会写流水账。
91
+
92
+ `/record` 仍保留,用于兼容旧版或手工写单条;新版 DSH 批处理只调用 `/ingest`。
93
+
94
+ ### `POST /foxy-memory/record`
95
+
96
+ ```json
97
+ {
98
+ "role": "user",
99
+ "text": "kunfox 今天在 DSH 做了插件",
100
+ "sessionId": "session-...",
101
+ "presetId": "foxy3(Character)"
102
+ }
103
+ ```
104
+
105
+ 写一条 `type: "context"` 的记忆,content 形如:
106
+
107
+ ```text
108
+ kunfox 在 DSH 说:kunfox 今天在 DSH 做了插件
109
+ ```
110
+
111
+ ### `POST /foxy-memory/context`
112
+
113
+ ```json
114
+ { "query": "DSH 插件", "limit": 20, "presetId": "foxy3(Character)" }
115
+ ```
116
+
117
+ 返回:
118
+
119
+ ```json
120
+ { "ok": true, "count": 3, "text": "- [2026-11-06 20:00] [DSH] ...", "memories": [] }
121
+ ```
122
+
123
+ ### `POST /foxy-memory/send-private`
124
+
125
+ 让 QQ 机器人给指定用户发一条私聊。DSH 侧用于把有趣的 B 站视频主动推给主人;发送成功后,DSH 侧会再写一条 `scene: "private"` 的私聊记忆。
126
+
127
+ ```json
128
+ {
129
+ "userId": "2242711967",
130
+ "text": "我刷到一个视频,觉得你会喜欢。",
131
+ "selfId": "2877932816"
132
+ }
133
+ ```
134
+
135
+ `userId` 可省略,默认使用桥配置的 `userId`;`selfId` 可省略,优先 `botId`/`assistantId`。返回 `{ ok, userId, botId, messageIds }`。
136
+
137
+ ### `GET /foxy-memory/health`
138
+
139
+ 返回 `{ ok, presetId, platform, path, service }`,可用于探活。
140
+
141
+ ## 鉴权
142
+
143
+ - 设置 `token` 后,请求必须带 `Authorization: Bearer <token>` 或 `X-Foxy-Token: <token>`。
144
+ - 未设置 `token` 时只接受 `127.0.0.1` / `::1` 的请求。
145
+ - 桥不会把 token 写入日志。
146
+
147
+ ## 限制
148
+
149
+ - 写入依赖 LivingMemory 的 `createMemory`,所以必须是有效 preset;`foxy3(Character)` 不存在时会返回 500 和提示。
150
+ - 召回走 `searchMemories`,向量索引未建立时可能为空,此时桥退回 `listMemories` 最近记录。
151
+ - 记忆内容按“DSH 侧的一句话”写入,不做 LLM 摘要/合并;这与 LivingMemory 的 Dream/摘要流程是互补的。
152
+ - 桥只处理 Foxy 的 DSH 对话;QQ 侧仍由 ChatLuna 原管线负责。
153
+
154
+ ## 测试
155
+
156
+ ```powershell
157
+ node test/test-bridge.cjs
158
+ ```
159
+
160
+ 测试使用 mock LivingMemory service 和 mock 机器人,不连接真实实例,也不会真的发 QQ。
161
+
162
+ `test/test-route.cjs` 另外验证 HTTP 路由,包括 `/send-private`。
163
+
164
+ ## License
165
+
166
+ MIT
148
167