luckytri 1.0.0

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 (235) hide show
  1. package/.github/SECURITY.md +71 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +250 -0
  4. package/README.md +250 -0
  5. package/bin/luckytri.js +107 -0
  6. package/docs/brand/banner.png +0 -0
  7. package/docs/brand/palette.png +0 -0
  8. package/docs/brand/portrait.png +0 -0
  9. package/docs/en/CHANGELOG.md +113 -0
  10. package/docs/en/architecture.md +152 -0
  11. package/docs/en/chat-style.md +62 -0
  12. package/docs/en/connect.md +63 -0
  13. package/docs/en/guide.md +216 -0
  14. package/docs/en/her-life.md +189 -0
  15. package/docs/en/npm-release.md +25 -0
  16. package/docs/en/plugins.md +82 -0
  17. package/docs/en/recovery.md +28 -0
  18. package/docs/en/time.md +71 -0
  19. package/docs/en/webui.md +73 -0
  20. package/docs/zh/CHANGELOG.md +113 -0
  21. package/docs/zh/architecture.md +152 -0
  22. package/docs/zh/chat-style.md +62 -0
  23. package/docs/zh/connect.md +63 -0
  24. package/docs/zh/guide.md +216 -0
  25. package/docs/zh/her-life.md +189 -0
  26. package/docs/zh/npm-release.md +33 -0
  27. package/docs/zh/plugins.md +82 -0
  28. package/docs/zh/recovery.md +28 -0
  29. package/docs/zh/time.md +71 -0
  30. package/docs/zh/webui.md +73 -0
  31. package/package.json +108 -0
  32. package/plugins/sdk/index.d.ts +155 -0
  33. package/plugins/sdk/testing.js +58 -0
  34. package/plugins/weather/index.js +82 -0
  35. package/plugins/weather/luckytri-plugin.json +29 -0
  36. package/public/app/assets/ChatsPage-C-FcRapR.js +3 -0
  37. package/public/app/assets/ChatsPage-DfyPCS9N.css +1 -0
  38. package/public/app/assets/Empty-CpP5kQHH.js +2 -0
  39. package/public/app/assets/Empty-DmUB2-Bk.css +1 -0
  40. package/public/app/assets/Field-D4gY-INU.js +1 -0
  41. package/public/app/assets/HeartPage-Bft9wZp5.css +1 -0
  42. package/public/app/assets/HeartPage-CPy_thQd.js +1 -0
  43. package/public/app/assets/LifePage-BUi5euBF.css +1 -0
  44. package/public/app/assets/LifePage-CxWvwmSf.js +1 -0
  45. package/public/app/assets/MemoryPage-DC4rhQ68.js +1 -0
  46. package/public/app/assets/MemoryPage-cZvXfkXb.css +1 -0
  47. package/public/app/assets/NaturePage-CTXHCE2D.css +1 -0
  48. package/public/app/assets/NaturePage-IvYw04Zq.js +3 -0
  49. package/public/app/assets/PeoplePage-BmUxkrOU.css +1 -0
  50. package/public/app/assets/PeoplePage-Cqefm9-q.js +1 -0
  51. package/public/app/assets/PluginsPage-DKSaKvXb.js +2 -0
  52. package/public/app/assets/PluginsPage-HyBe5D8w.css +1 -0
  53. package/public/app/assets/SystemPage-CAMPoYqM.css +1 -0
  54. package/public/app/assets/SystemPage-CJmtJkrK.js +1 -0
  55. package/public/app/assets/TimePage-BOms_n4I.css +1 -0
  56. package/public/app/assets/TimePage-Cw44inM4.js +3 -0
  57. package/public/app/assets/formatters-ZmW_xFHw.js +1 -0
  58. package/public/app/assets/index-BheRW-1t.js +4 -0
  59. package/public/app/assets/index-YDz1ree1.css +1 -0
  60. package/public/app/assets/knowledge-DG0e0uKw.js +1 -0
  61. package/public/app/assets/liquid-garden-IMoHBwzc.png +0 -0
  62. package/public/app/assets/luckytri-home-95QKeMtc.png +0 -0
  63. package/public/app/assets/media-BzPDBm7e.js +1 -0
  64. package/public/app/index.html +27 -0
  65. package/public/guide.en.html +1053 -0
  66. package/public/guide.html +893 -0
  67. package/public/plugin-kit/v1/bridge.js +30 -0
  68. package/public/plugin-kit/v1/kit.css +14 -0
  69. package/public/tutorial.en.md +214 -0
  70. package/public/tutorial.md +214 -0
  71. package/scripts/backup.js +311 -0
  72. package/scripts/browser.js +41 -0
  73. package/scripts/launch.js +94 -0
  74. package/scripts/plugin.js +150 -0
  75. package/scripts/proxy-config.js +167 -0
  76. package/scripts/recover.js +26 -0
  77. package/scripts/runtime.js +25 -0
  78. package/scripts/service.js +47 -0
  79. package/scripts/setup.js +50 -0
  80. package/scripts/start-server.js +41 -0
  81. package/scripts/stop.js +36 -0
  82. package/server/app.js +96 -0
  83. package/server/channels/adapters.js +27 -0
  84. package/server/channels/contract.js +57 -0
  85. package/server/channels/hub.js +165 -0
  86. package/server/channels/index.js +25 -0
  87. package/server/channels/onebot/adapter.js +288 -0
  88. package/server/channels/onebot/index.js +336 -0
  89. package/server/channels/onebot/token.js +3 -0
  90. package/server/channels/qqbot/adapter.js +253 -0
  91. package/server/channels/qqbot/api.js +199 -0
  92. package/server/channels/qqbot/credentials.js +11 -0
  93. package/server/channels/qqbot/gateway.js +274 -0
  94. package/server/channels/qqbot/index.js +389 -0
  95. package/server/channels/segments.js +40 -0
  96. package/server/channels/session-key.js +153 -0
  97. package/server/channels/state.js +42 -0
  98. package/server/core/api.js +564 -0
  99. package/server/core/capabilities.js +208 -0
  100. package/server/core/context-builder.js +288 -0
  101. package/server/core/context-compactor.js +454 -0
  102. package/server/core/conversation-cues.js +325 -0
  103. package/server/core/conversation-manager.js +87 -0
  104. package/server/core/events.js +60 -0
  105. package/server/core/feedback.js +8 -0
  106. package/server/core/group-style.js +72 -0
  107. package/server/core/image-preprocessor.js +208 -0
  108. package/server/core/initiative-context.js +66 -0
  109. package/server/core/input-budget.js +32 -0
  110. package/server/core/local-demo.js +98 -0
  111. package/server/core/message-manager.js +118 -0
  112. package/server/core/message-scheduler.js +78 -0
  113. package/server/core/model-json.js +190 -0
  114. package/server/core/model-manager.js +1213 -0
  115. package/server/core/model-presets.js +900 -0
  116. package/server/core/name-call.js +29 -0
  117. package/server/core/net-guard.js +49 -0
  118. package/server/core/network.js +157 -0
  119. package/server/core/orchestrator.js +569 -0
  120. package/server/core/perceivers.js +91 -0
  121. package/server/core/person-name.js +22 -0
  122. package/server/core/persona-manager.js +243 -0
  123. package/server/core/reply-delivery.js +393 -0
  124. package/server/core/reply-target-resolver.js +50 -0
  125. package/server/core/repository.js +293 -0
  126. package/server/core/response-generator.js +50 -0
  127. package/server/core/response-validator.js +508 -0
  128. package/server/core/retired-prompts.js +51 -0
  129. package/server/core/sessions.js +109 -0
  130. package/server/core/speaker-names.js +92 -0
  131. package/server/core/topic-tracker.js +65 -0
  132. package/server/core/turn-processor.js +630 -0
  133. package/server/core/turn.js +236 -0
  134. package/server/core/vision-manager.js +633 -0
  135. package/server/http.js +18 -0
  136. package/server/i18n/decisions.js +206 -0
  137. package/server/i18n/errors.js +497 -0
  138. package/server/i18n/index.js +144 -0
  139. package/server/i18n/labels.js +653 -0
  140. package/server/i18n/models.js +111 -0
  141. package/server/index.js +102 -0
  142. package/server/knowledge/api.js +342 -0
  143. package/server/knowledge/embedding-profile.js +114 -0
  144. package/server/knowledge/index.js +13 -0
  145. package/server/knowledge/manager.js +386 -0
  146. package/server/knowledge/retrieval.js +93 -0
  147. package/server/knowledge/schema.js +154 -0
  148. package/server/knowledge/vector-index.js +90 -0
  149. package/server/mind/affect.js +265 -0
  150. package/server/mind/anticipations.js +507 -0
  151. package/server/mind/api.js +703 -0
  152. package/server/mind/attention.js +200 -0
  153. package/server/mind/bonds.js +558 -0
  154. package/server/mind/budget.js +152 -0
  155. package/server/mind/clock.js +83 -0
  156. package/server/mind/context-selection.js +61 -0
  157. package/server/mind/continuity.js +562 -0
  158. package/server/mind/conversation-origin.js +175 -0
  159. package/server/mind/day-planner.js +324 -0
  160. package/server/mind/days.js +210 -0
  161. package/server/mind/evidence-read.js +45 -0
  162. package/server/mind/evidence.js +148 -0
  163. package/server/mind/faces.js +138 -0
  164. package/server/mind/guard.js +60 -0
  165. package/server/mind/index.js +445 -0
  166. package/server/mind/initiative.js +333 -0
  167. package/server/mind/life/activities.js +21 -0
  168. package/server/mind/life/context.js +309 -0
  169. package/server/mind/life/diary.js +786 -0
  170. package/server/mind/life/growth.js +252 -0
  171. package/server/mind/life/index.js +1049 -0
  172. package/server/mind/life/presence.js +305 -0
  173. package/server/mind/meetings.js +1069 -0
  174. package/server/mind/memory-policy.js +48 -0
  175. package/server/mind/memory.js +888 -0
  176. package/server/mind/nature.js +262 -0
  177. package/server/mind/novelty.js +19 -0
  178. package/server/mind/observations.js +84 -0
  179. package/server/mind/own-day.js +324 -0
  180. package/server/mind/own-voice.js +318 -0
  181. package/server/mind/periods.js +118 -0
  182. package/server/mind/reading.js +120 -0
  183. package/server/mind/salience.js +201 -0
  184. package/server/mind/schema.js +562 -0
  185. package/server/mind/self.js +484 -0
  186. package/server/mind/senses.js +53 -0
  187. package/server/mind/thoughts.js +274 -0
  188. package/server/mind/time/activity-clock.js +196 -0
  189. package/server/mind/time/agenda.js +242 -0
  190. package/server/mind/time/api.js +200 -0
  191. package/server/mind/time/attention.js +34 -0
  192. package/server/mind/time/availability.js +69 -0
  193. package/server/mind/time/commitment-review.js +198 -0
  194. package/server/mind/time/delivery-links.js +130 -0
  195. package/server/mind/time/executor.js +512 -0
  196. package/server/mind/time/experiences.js +128 -0
  197. package/server/mind/time/games.js +562 -0
  198. package/server/mind/time/index.js +739 -0
  199. package/server/mind/time/intent.js +166 -0
  200. package/server/mind/time/kinds.js +171 -0
  201. package/server/mind/time/model-material.js +77 -0
  202. package/server/mind/time/plugin-activity.js +207 -0
  203. package/server/mind/time/presentation.js +51 -0
  204. package/server/mind/time/schedule.js +83 -0
  205. package/server/mind/time/schema.js +84 -0
  206. package/server/mind/time/search.js +383 -0
  207. package/server/mind/time/sharing.js +472 -0
  208. package/server/mind/time/task-links.js +311 -0
  209. package/server/mind/time/tasks.js +587 -0
  210. package/server/mind/time/works.js +432 -0
  211. package/server/mind/traits.js +191 -0
  212. package/server/mind/util.js +110 -0
  213. package/server/mind/view.js +273 -0
  214. package/server/paths.js +102 -0
  215. package/server/plugins/api.js +204 -0
  216. package/server/plugins/host.js +967 -0
  217. package/server/plugins/install.js +295 -0
  218. package/server/plugins/manifest.js +201 -0
  219. package/server/plugins/permissions.js +42 -0
  220. package/server/plugins/runner/guard.mjs +36 -0
  221. package/server/plugins/runner/worker.mjs +250 -0
  222. package/server/plugins/schema.js +91 -0
  223. package/server/plugins/zip.js +112 -0
  224. package/server/startup-lock.js +118 -0
  225. package/server/storage/archive.js +241 -0
  226. package/server/storage/backup-cleanup-worker.js +8 -0
  227. package/server/storage/backup-cleanup.js +414 -0
  228. package/server/storage/backup-lock.js +76 -0
  229. package/server/storage/backup-scheduler.js +131 -0
  230. package/server/storage/store.js +199 -0
  231. package/server/studio/display-names.js +138 -0
  232. package/server/studio/management.js +102 -0
  233. package/server/studio/readiness.js +190 -0
  234. package/server/studio/settings.js +236 -0
  235. package/server/version.js +10 -0
@@ -0,0 +1,216 @@
1
+ <p align="right"><b>中文</b> · <a href="../en/guide.md">English</a></p>
2
+
3
+ # LuckyTri · 从零上手教程
4
+
5
+ LuckyTri 在你的电脑上运行,通过 QQ 与人相遇。QQ 有两种连接方式,二选一:**OneBot 11**(自备接入端,反向 WebSocket)或 **QQ 官方机器人**(QQ 开放平台)。两种方式下她的记忆、心情和行为完全一致,区别只在消息怎么到达。模型 API 由你自行配置。
6
+
7
+ 界面右上角可以在「中文」与「English」之间切换,默认中文,选择会记在这个浏览器里。她自己说的话、写的日记和留下的念头不翻译,那是她自己的内容。
8
+
9
+ ## 1. 启动
10
+
11
+ 需要 Node.js 24.5 或更高版本。普通用户直接全局安装:
12
+
13
+ ```powershell
14
+ node --version
15
+ npm install -g luckytri
16
+ luckytri
17
+ ```
18
+
19
+ LuckyTri 在后台启动并打开 <http://127.0.0.1:3210>,首次运行自动生成配置。无需下载仓库或构建 WebUI。终端里的 SQLite 实验性提示不表示启动失败,以能否打开 LuckyTri 为准。
20
+
21
+ 运行 `luckytri paths` 查看本机 `.env`,在本机编辑器中取得 `ADMIN_TOKEN` 并填入管理台。`luckytri --no-browser` 只后台启动,`luckytri start` 前台运行,`luckytri stop` 停止服务。更新使用 `luckytri stop` → `npm install -g luckytri@latest` → `luckytri`,配置与数据会保留;默认目录见 [README](../../README.md#配置数据与隐私)。
22
+
23
+ 从源码开发时,在仓库中执行 `npm install`、`npm run setup`、`npm run build`、`npm start`。下文的 `npm run setup/stop/backup/recovery/plugin` 面向源码用户;全局用户使用对应的 `luckytri setup/stop/backup/recovery/plugin`。
24
+
25
+ Windows 日常使用可以双击 `启动LuckyTri.cmd`。服务已在运行时,它只打开 LuckyTri。关闭浏览器不会停止服务;停止时双击 `停止LuckyTri.cmd`,或在项目目录执行 `npm run stop`。这条命令只停止当前项目,不会结束其他 Node 进程。前台运行时也可以在该终端按 `Ctrl+C`。
26
+
27
+ LuckyTri 是「TA 的小世界」,左侧导航分三组、十个入口:
28
+
29
+ | 分组 | 入口 | 里面有什么 |
30
+ | ---- | ---- | ----------------------------------------------------------------------------------------------- |
31
+ | TA | 此刻 | TA 此刻的心情、正在做什么、最近说的话、放在心上和在等的事;今天的时间线、Token 用量和运行状态条 |
32
+ | TA | 内心 | 心灵星图(TA 的自我线索)、放在心上的便签、心情彩带 |
33
+ | TA | 人际 | 人物星系、每个人的详情、TA 在各群的样子 |
34
+ | TA | 一生 | 日记本与那天的 TA、回顾、我的来路与章节、约定与期待、书架 |
35
+ | 日常 | 时间 | TA 实际生活的记录:今日的活动、待办、作品库、持续项目、体验记录 |
36
+ | 日常 | 对话 | 会话列表、实时聊天与「为什么这么说」、反馈、会话设置、模拟消息、回到那一刻(回放) |
37
+ | 日常 | 记忆 | TA 记得的事、资料书架 |
38
+ | 设置 | 天性 | 名字与性格(旁边的光团实时预览)、作息、TA 的日子、每日 Token、高级指令、试聊 |
39
+ | 设置 | 系统 | 连接 QQ、模型库、运行开关 |
40
+ | 设置 | 插件 | 启用、安装和卸下她接触世界的方式。见 [插件](plugins.md) |
41
+
42
+ 界面的颜色、天空和动效跟着 TA 的心情与作息变化:开心时暖、低落时灰蓝、睡着后变成夜晚。左下角可以把主题固定成某一种,也可以「减少动画」。右下角的小 TA 戳一下会回应一句,按住是摸摸头,双击或点「聊聊」打开试聊;这些只是界面动画,不会改变 TA 的心智。手机上导航在底部,其余入口在「更多」里。
43
+
44
+ ## 2. 本机令牌
45
+
46
+ 首次启动已生成配置;也可以提前初始化:
47
+
48
+ ```powershell
49
+ luckytri setup
50
+ luckytri paths
51
+ ```
52
+
53
+ 没有 `.env` 时,setup 会写入管理令牌和 OneBot 连接令牌。已有 `.env` 会原样保留。
54
+
55
+ ```dotenv
56
+ HOST=127.0.0.1
57
+ PORT=3210
58
+ ADMIN_TOKEN=
59
+ ONEBOT_TOKEN=
60
+ LLM_API_KEY=
61
+ ```
62
+
63
+ | 字段 | 用途 |
64
+ | ----------------------------------- | --------------------------------------------------------------- |
65
+ | `ADMIN_TOKEN` | 打开 LuckyTri 和调用 HTTP API;停止命令也会使用 |
66
+ | `ONEBOT_TOKEN` | OneBot 11 接入端连接 `/onebot/v11/ws`(只用 OneBot 方式时需要) |
67
+ | `LLM_API_KEY` | 可选;非空时优先于 LuckyTri 里保存的模型密钥 |
68
+ | `LUCKYTRI_CHANNEL` | 可选;`onebot` 或 `qqbot`。设置后在界面里不能更改连接方式 |
69
+ | `QQBOT_APP_ID` / `QQBOT_APP_SECRET` | 可选;QQ 官方机器人的凭据,优先于界面里保存的 |
70
+ | `HOST` / `PORT` | 监听地址和端口;本机使用保持默认 |
71
+
72
+ 页面第一次取数据时会弹出窗口要求输入 `ADMIN_TOKEN`。令牌只留在当前标签页。修改 `.env` 后必须重启。不要把 `ADMIN_TOKEN` 填给 QQ 接入端,也不要把 `ONEBOT_TOKEN` 当成管理台密码。
73
+
74
+ ## 3. 先在模拟模式试聊
75
+
76
+ 默认开启模拟模式,消息不会发到 QQ。
77
+
78
+ 1. 打开「对话」,点会话列表上方的「+ 添加会话」,填写测试群号和名称。
79
+ 2. 在中间的聊天里点「模拟消息」,以一位群友的身份输入一句普通消息并发送。
80
+ 3. 点 TA 回复下面的「为什么这么说」查看理由;「TA 扫了一眼」「TA 看了,没出声」会显示成聊天里的分隔条。
81
+
82
+ 没有模型密钥时,模拟回复使用本地样例,不调用模型。有密钥后,同一条路径会走真实发言流程,但仍然不发 QQ。模拟消息写进模拟会话,不会改变 TA 的心情、关系和记忆。
83
+
84
+ 「模拟消息」只在模拟模式下可用。右下角小 TA 的「聊聊」和「天性」右侧的试聊是另一回事:走真实链路,读取 TA 此刻的心智,天性页还可以带上没保存的草稿,但什么都不写入,也不发 QQ。
85
+
86
+ ## 4. 连接模型
87
+
88
+ 打开「系统 → 模型库」,点「+ 新增模型」选择一个预设。
89
+
90
+ - API 地址填写服务商的兼容接口根路径。程序会自己拼接 `/chat/completions`,不要把完整路径再写一遍。
91
+ - 模型名称填写服务商接受的模型 ID。
92
+ - API Key 留空表示保留已保存的密钥。
93
+
94
+ 预设只填入常见地址和模型名,以服务商控制台里的实际模型为准。发言决策和回复生成需要模型返回 JSON 对象。
95
+
96
+ 保存后点「测试此模型连接」。测试不携带群聊原文。更换地址、模型或密钥后需要重新测试。
97
+
98
+ 也可以先保持模拟模式,在「天性」里和 TA 试聊,确认 TA 说话的样子后再让 TA 参加真实 QQ。
99
+
100
+ ### 图片读取
101
+
102
+ 在模型档案里开启「图片理解」,并使用服务商支持视觉的模型。图片从 QQ 地址、本地缓存或图片缓存接口读取,默认接受不超过 32 MiB、8000 万像素的源图,不再把超过 4 MiB 的普通照片和截图直接拒绝。小图经过解码验证后保持原样;大截图先尝试无损压缩,必要时再压缩编码或按比例缩小,照片按方向信息转正,不裁切画面。提交模型的每张图片默认不超过 4 MiB,最长边不超过 8192 像素,像素总量不超过 1600 万;原图不被修改,重复图片仍按原内容识别。
103
+
104
+ 下载默认最多等待 30 秒,读取过程中断或图片损坏只影响该图片,不会阻止同一批其他正常图片。AVIF 会转换成通用格式;动态图本轮读取第一帧,不能据此判断完整动画。QQ 缓存接口返回大 Base64 图片不会再受到普通消息 1 MiB 限制,但普通消息仍保持原有上限。
105
+
106
+ 需要调整时,可在 `.env` 设置 `VISION_SOURCE_MAX_MB`(4–64,默认 32)、`VISION_MODEL_MAX_MB`(1–4,默认 4)和 `VISION_DOWNLOAD_TIMEOUT_SECONDS`(5–120,默认 30),重启生效。图片能否理解还取决于所选模型的视觉能力和服务商接口是否可用。
107
+
108
+ ## 5. 连接 QQ
109
+
110
+ 打开「系统 → 连接 QQ」,顶部有两个选项:**OneBot 11** 与 **QQ 官方机器人**,同一时间只使用一个。切换后会断开当前连接;原来方式下的会话仍可查看,但不能再向它们发送消息。两种方式的差别见 `docs/zh/connect.md`,下面是操作步骤。
111
+
112
+ ### 方式一:OneBot 11
113
+
114
+ LuckyTri 只实现 OneBot 11 的反向 WebSocket 接口,接入端需要你自行准备和管理。
115
+
116
+ 1. 在本机 `.env` 中设置 `ONEBOT_TOKEN`,修改后重启 LuckyTri。
117
+ 2. 在接入端自己的网络设置里添加 OneBot 11 反向 WebSocket 客户端:
118
+
119
+ | 项目 | 本机填写 |
120
+ | ------------- | ----------------------------------- |
121
+ | 协议 | OneBot 11 |
122
+ | WebSocket URL | `ws://127.0.0.1:3210/onebot/v11/ws` |
123
+ | Token | `.env` 里的 `ONEBOT_TOKEN` |
124
+ | 消息格式 | 数组 |
125
+ | 启用 | 开启并保存 |
126
+
127
+ 3. 在接入端完成 QQ 登录。小号需要已加入目标群;LuckyTri 不保存 QQ 密码。
128
+
129
+ 这里的 `3210` 是 LuckyTri 的端口。接入端和 LuckyTri 不在同一台机器或放在容器里时,`127.0.0.1` 指向各自环境,需要改成 LuckyTri 的实际地址,并先配置 `ADMIN_TOKEN`。
130
+
131
+ ### 方式二:QQ 官方机器人
132
+
133
+ 不需要登录 QQ 账号,也不需要额外的接入端,LuckyTri 自己连接 QQ 开放平台。
134
+
135
+ 1. 在 QQ 开放平台创建机器人,记下 **AppID** 与 **AppSecret**,并按平台要求开通群聊与单聊消息、把机器人加入要测试的群或添加为联系人。平台的入口和审核规则会调整,以开放平台当前说明为准。
136
+ 2. 在「系统 → 连接 QQ」选择「QQ 官方机器人」,填写 AppID 和 AppSecret,点击保存。也可以在 `.env` 里设置 `QQBOT_APP_ID` 与 `QQBOT_APP_SECRET`。AppSecret 保存后不会再显示。
137
+ 3. 状态显示「已连接」后,到群里 @ 她或私聊一句。想让她看到群里的全部消息,需要在开放平台开启「接收所有消息」;没有开启时她只能收到 @ 她的消息,连接页会提示这一点。
138
+ 4. 官方接口不提供群名,新会话会以编号显示,可以在「对话」里给会话改名。
139
+
140
+ 两种方式都是:已连接只表示传输通了。到目标群发一条消息后,会话会出现在「对话」的会话列表里,新发现的会话默认暂停参与。
141
+
142
+ ## 6. 让 TA 参与会话
143
+
144
+ 1. 在「系统 → 运行开关」确认允许参与聊天,关闭模拟模式并保存。「此刻」的状态条也能看到这两项。
145
+ 2. 在「对话」选中目标群,在右侧「这个会话」里点「开启参与」,或直接拨动列表里的开关。
146
+ 3. 在 QQ 里 @ 她,或直接叫 TA 的名字。
147
+ 4. 回到「对话」查看消息和「为什么这么说」。
148
+
149
+ 开不开口由 TA 自己决定,没有参与概率和冷却。被点名、私聊、引用 TA 或出现危机信号时,TA 一定会细看,然后选择回答、简短反应、说不想聊或不出声;理由显示在「对话」和「此刻 → 今天的 TA」。普通群消息只在 TA 在意时细看——刚聊过、有人问大家、聊到 TA 的兴趣、熟人在说话、攒了不少消息——其余只扫一眼,不调用模型,下次细看时一起读。觉得 TA 太安静,可以在「天性」里提高「主动」。
150
+
151
+ TA 默认 02:00 睡、08:00 醒,在「天性 → 作息」里拖动月亮和太阳修改,或者关闭。睡着时被叫到,会等醒来再看;这时整个界面会变成夜晚。每分钟发言轮数限制仍然保留,用来避免短时间连续发言。
152
+
153
+ 在模型里打开「图片理解」后,私聊、@ 或引用里的图片会先由本机读取,再交给模型看画面。主模型不能看图时,在「对话 → 这个会话 → 会话设置」里另选一个打开了图片理解的视觉兼容模型。没有打开图片理解的模型不会收到画面。
154
+
155
+ ## 7. TA、记忆和知识
156
+
157
+ 「天性」是唯一由你编写的部分:名字、性格、兴趣、边界、底线和作息,每次保存为新的一版。拖动性格刻度时,旁边的光团会跟着变:温柔让颜色变暖、嘴角上扬,活泼让它跳得更快。
158
+
159
+ 其余的都从经历里长出来:TA 的自我是「内心」星图里的一颗颗星,TA 对每个人的感觉在「人际」,TA 在各群的样子在「人际」下方的群像里。点开可以看到每次变化的来源,觉得不对可以撤销;撤销过的内容之后不会被写回来。很久没被触及的线索会慢慢淡出,退到星图的「远方」;它们没有被删除,被聊到时会重新想起。TA 独处、写日记、夜里整理、回顾和改写自传的记录,以及 TA 在等的事(别人说的安排、TA 答应的事,可以撤销),都在「一生」。每日 Token 上限、后台份额、夜里整理和回顾间隔在「天性 → TA 的日子」里设置。
160
+
161
+ 「记忆」里先选择会话,也可以按人筛选。
162
+
163
+ - TA 对所有会话只有一份记忆:别处知道的事只在相关时想起;私聊里知道的标为「私下知道」,不当众说;被要求保密的只在原来的会话里。可以在每条记忆上调整分寸、锁定或撤销。关于某个人的记忆也会出现在「人际」的人物详情里。
164
+ - 群友说「记住,我……」会直接成为 TA 记得的事(密码、验证码之类不会记)。
165
+ - 资料放进「资料书架」的集合后按当前会话的可见范围检索。群聊不会装入其他私聊集合。
166
+ - 清空「对话」里的上下文不会删除长期记忆。
167
+
168
+ ## 8. 备份与停止
169
+
170
+ ```powershell
171
+ npm run backup
172
+ npm run stop
173
+ npm start
174
+ ```
175
+
176
+ 备份写到 `data/backups/`。数据库里有聊天、记忆和保存在库中的密钥,按私密文件保管。`.env` 不在这份备份里。
177
+
178
+ TA 的一切都存在这一个数据库里,所以服务运行时会自动备份:默认每 24 小时在另一个进程里做一份 `luckytri-auto-*.db`,只保留最近 7 份,做完会检查完整性。自动备份里有聊天、记忆、自我、日记和关系,但不带一天以前的模型调用记录(每条动辄几百 KB,会让备份大上十几倍),所以「为什么这么说」只能回看最近一天的。`npm run backup` 仍然是完整备份。可以在 `.env` 里调整:
179
+
180
+ | 变量 | 含义 | 默认 |
181
+ | ----------------------- | ---------------------------- | -------------- |
182
+ | `BACKUP_INTERVAL_HOURS` | 自动备份间隔,`0` 关闭 | `24` |
183
+ | `BACKUP_KEEP` | 保留几份自动备份 | `7` |
184
+ | `BACKUP_TRACE_DAYS` | 备份里保留最近几天的调用记录 | `1` |
185
+ | `BACKUP_DIR` | 备份目录 | `data/backups` |
186
+
187
+ 想立刻做一份自动备份:`node scripts/backup.js --auto --force`。自动备份失败会记在启动窗口或 `data/launcher.log`,并隔越来越久才重试。备份和数据库放在同一块磁盘上,防不了磁盘损坏;重要的备份请自己复制到别处。
188
+
189
+ 设置 `DB_PATH` 使用另一份数据库时,若未指定 `BACKUP_DIR`,备份默认写到该数据库旁的 `backups` 目录,避免多个实例的副本混在一起。
190
+
191
+ 在「系统 → 数据与备份」可以查看每份历史数据库副本的大小,设置每天的整理时间、完整备份保留天数和最多份数,也可以逐份勾选后手动清理。默认每天服务器本地时间 04:30 检查,完整备份超过 14 天或多于 2 份就会列入整理;数量可设为 0,表示定时不保留完整备份。完整备份和迁移快照没有固定硬锁,可以手动选择全部清理。自动备份继续按上面的独立规则轮换,只轮换本实例有身份的副本,最新两份作为恢复点保留;无法确认身份的旧副本、迁移、旧版本和升级前快照仅手动清理。
192
+
193
+ 执行前必须留下本实例近 72 小时内校验通过的自动备份,最新一份损坏时会尝试另一份。新备份清单带有数据库身份,防止另一实例的副本冒充当前实例的恢复保障;旧清单仍可验证和恢复,但需要更新自动备份后才能作为清理保障。备份和清理共用目录锁,运行库、同一文件的硬链接与正在使用的副本不能清理。清理失败时会列出失败文件,并准确统计已释放空间。要长期保留的历史恢复点,请先连同 `.db.json` 清单复制到另一块磁盘。
194
+
195
+ 恢复时先停止服务,把当前 `data/friend.db` 及同名 `-wal`、`-shm` 移开,再把选中的备份复制为 `data/friend.db`。设置了 `DB_PATH` 时操作该路径。不要把旧的 WAL 文件和恢复后的数据库放在一起。更稳妥的做法是用 `npm run recovery` 校验并恢复到一个全新的文件,见 `docs/zh/recovery.md`。
196
+
197
+ ## 9. 常见问题
198
+
199
+ | 现象 | 先检查 |
200
+ | ------------------------- | -------------------------------------------------------------------------------------------------- |
201
+ | 页面打不开 | Node 是否在运行,地址是否为 `127.0.0.1:3210` |
202
+ | 端口已被占用 | 先 `npm run stop`,不要结束所有 node 进程 |
203
+ | 令牌错误 | 使用 `ADMIN_TOKEN`;改 `.env` 后重启 |
204
+ | OneBot 未连接 | 接入端是否登录,URL、端口、路径和 `ONEBOT_TOKEN` 是否一致 |
205
+ | 官方机器人未连接 | AppID 与 AppSecret 是否正确,机器人是否已开通群聊与单聊消息,网络能否访问 QQ 开放平台 |
206
+ | 官方机器人只收到 @ 的消息 | 在开放平台开启「接收所有消息」;这是平台权限,不是 LuckyTri 的限制 |
207
+ | 连接成功但没有会话 | 在 QQ 再发一条新消息;OneBot 方式下检查消息格式是否为数组 |
208
+ | 群里不回复 | 全局开关、会话开关、模拟模式、密钥;「对话」里是「TA 扫了一眼」还是 TA 细看后选择了不出声 |
209
+ | @ 了也不回 | TA 是否睡着了(「此刻」,界面是夜晚)、每分钟限速、今日 Token 是否用完、模型错误,或 TA 自己的理由 |
210
+ | 模型 401 / 403 | 密钥和权限;环境变量密钥可能覆盖 LuckyTri 里保存的密钥 |
211
+ | 模型 404 | API 地址不要重复拼接 `/chat/completions`,核对模型 ID |
212
+ | 模型不返回 JSON | 换支持 JSON 对象输出的模型,先做连接测试 |
213
+ | 记忆没有出现 | 是否是明确的「记住,我……」,是否被撤销,分寸是否为「要 TA 保密」而当前不在原来的会话 |
214
+ | 界面动得太多 | 左下角「减少动画」;系统开启了减少动态效果时会自动关闭粒子和形变 |
215
+
216
+ 不要把 API 密钥、`.env` 或私聊原文发到公开位置。
@@ -0,0 +1,189 @@
1
+ <p align="right"><b>中文</b> · <a href="../en/her-life.md">English</a></p>
2
+
3
+ # 她的一生:统一心智的设计与使用
4
+
5
+ LuckyTri 不是「按会话隔离、由概率和规则决定开不开口、人格固定不变」的机器人。所有群聊和私聊里只有一个她:她有自己的心情和精力,对每个人有感觉,在每个群有自己的样子,会在安静时独处、在睡前写日记,会重新理解过去的自己。你写下她的天性;其余的部分从经历里长出来,每一次变化都能看到来源,也都能撤销。
6
+
7
+ 她不只会积累。很久没被触及的东西会从心上淡去,被相关的人或话题碰到时又会想起;久别的人会变淡,重逢时很快热络;她记得别人说过的安排和自己答应的事;每隔一段时间,她会在夜里回顾这段日子,改写自传,或者翻开新的一章。
8
+
9
+ ## 已定原则
10
+
11
+ - **一个她**。会话只是「事情发生在哪里」的标注,不是隔离墙。同一个人在所有群和私聊里是同一个人。
12
+ - **天性是种子**。天性(名字、性格、兴趣、边界、底线、作息)是唯一由你编写的部分。自我、面貌、关系由她自己形成;你能看、能撤销,但不能替她改写。
13
+ - **由心开口**。没有参与概率、冷却抽样和「被 @ 必回」。每次细看一段对话,她都先理解这对她意味着什么,再选择说、简短反应、说不想聊或不出声,并留下自己的理由。沉默时她的心情和对人的感觉照样会变。
14
+ - **有来源、渐进、可撤销**。心智表只追加不覆盖。每条变化都引用具体经历(消息、手记、反馈、读过的段落、日记、约定)。一次经历只让强度小幅变化;同一段经历再引用一次,强度不再升高。新的特质要在不同的日子里反复出现才成形。撤销留下墓碑,之后的整理不会把它写回来。
15
+ - **会淡去,也会想起**。淡出是读的时候算出来的,不写任何「已淡出」标记,所以回放仍然只读过去。淡出按她经历过的日子计算,不按日历:没人说话的一个月里,她不会把自己忘掉。被勾起的旧念头只是被看见,不产生写入。撤销仍是唯一的删除。
16
+ - **注意力有代价**。扫一眼群聊不花 Token;只有真的在意时才细看。一天的 Token 有上限时,对话优先,独处和整理用各自的份额。每一类调用的输入都有上限,不随她活得多久而增长。
17
+
18
+ ## 模块地图
19
+
20
+ ```text
21
+ server/core/ 感官与嘴:接收、聚合、感知(谁在对谁说)、语境、一次回合调用、校验、发送
22
+ server/mind/ 她的心智
23
+ nature.js 天性(版本化,唯一可编辑)、作息
24
+ affect.js 心境:唯一的全局情绪与精力,由经历推动、随时间回落;「这阵子」的基线
25
+ bonds.js 关系:对每个人、每个群的熟悉、亲近、信任、别扭;久别变淡、重逢回暖
26
+ self.js 自我:喜欢、看法、特质、习惯、想做的事、放在心上的事、好奇
27
+ faces.js 面貌:她在每个群的样子
28
+ thoughts.js 手记:独处后留下的理解,修正时追加;可以放下
29
+ memory.js 记忆:一份全局记忆,带来源与分寸(公开 / 私下 / 保密);会淡出,可被新事实取代
30
+ days.js 她过过的日子:淡出按这些日子计算;第几天与纪念日
31
+ salience.js 显著度:各类内容的半衰期与阈值
32
+ anticipations.js 约定与期待:她答应的事、她想做的事、别人的安排、每年的日子
33
+ meetings.js 相遇:这件事对她意味着什么;别人的话有没有碰到她正在为自己而活的事
34
+ periods.js 回顾、自传章节与「我的来路」,每次重写都保留旧版本
35
+ attention.js 注意力:确定性的「细看还是扫一眼」
36
+ guard.js 底线:凭据、保密、危机
37
+ budget.js Token 账本与每日份额
38
+ view.js 给每次调用的「此刻的她」(有上限的几百 Token)
39
+ reading.js 阅读:按兴趣从共享知识库分段读下去
40
+ life/ 一生:醒来、独处、日记、夜里、回顾、主动联系
41
+ time/ 时间:活动、待办、作品、体验(见 time.md)
42
+ index.js Mind:把上面这些连成一个人
43
+ ```
44
+
45
+ ```mermaid
46
+ flowchart TD
47
+ Nature["天性:你写,版本化"] --> Self["自我"]
48
+ Exp["经历:聊天、她自己的话、反馈、独处"] --> Self
49
+ Exp --> Affect["心境(全局)"]
50
+ Exp --> Bonds["关系:人与群"]
51
+ Exp --> Memory["记忆(全局,带分寸)"]
52
+ Exp --> Ahead["约定与期待"]
53
+ Self --> Faces["面貌:每个群的样子"]
54
+ Days["她过过的日子"] -.-> Salience["显著度:读时计算"]
55
+ Salience -.-> Self
56
+ Salience -.-> Memory
57
+ Affect --> Attention["注意力"]
58
+ Bonds --> Attention
59
+ Self --> Attention
60
+ Attention -->|细看| Turn["一次回合:理解、感受、选择、措辞"]
61
+ Attention -->|扫一眼| Unread["留作未读"]
62
+ Unread --> Turn
63
+ Self --> Turn
64
+ Faces --> Turn
65
+ Bonds --> Turn
66
+ Memory --> Turn
67
+ Affect --> Turn
68
+ Ahead --> Turn
69
+ Turn --> Guard["校验与底线"]
70
+ Guard --> Send["发送"]
71
+ Turn --> Exp
72
+ Send --> Exp
73
+ Exp --> Life["一生:独处、日记、夜里、回顾"]
74
+ Life --> Self
75
+ Life --> Faces
76
+ Life --> Bonds
77
+ Life --> Ahead
78
+ Life --> Story["日记 → 回顾 → 章节 → 我的来路"]
79
+ ```
80
+
81
+ ## 一次「看见」的流程
82
+
83
+ 1. **接收与聚合**。短时间内的连续消息合成一批。明确的「记住,我……」当场成为记忆(凭据除外),不再等待人工审核。
84
+ 2. **感知**。解析 @、引用链、点名和回复对象,得到每条消息与她的关系(叫她 / 在和别人说 / 不确定)。
85
+ 3. **注意力**(不调用模型)。被叫到、私聊、危机信号一定细看。普通群聊按确定性的分数决定:刚才她还在聊、有人问大家、聊到她天性里的兴趣、聊到她正在为自己而活的事;熟悉的人在说话、攒了不少消息、有一阵没看群,也会加分。碰到兴趣或愿望要对上同一个人自己的话里的词,两个人的话不能拼在一起,她自己说过的话也不算;只有表情和图片、明显在和别人说话会减分。精力低、Token 紧张时门槛变高;天性里的「主动」越高门槛越低。没细看的消息保留为未读,下一次细看时一起读到,所以不会因为省 Token 丢掉上下文。
86
+ 4. **回忆**。一份全局记忆:先看当前说话的人和话题,别处知道的事只在相关时想起;私聊里知道的带上「私下知道,不要当众说出口」,被要求保密的绝不进入别的会话。很久没被想起、又不太重要的记忆,只在被真正聊到或本人在说话时才回来;超过一周的记忆带上「几个月前知道的」。再加上知识库、分层语境摘要和阶段总结。
87
+ 5. **此刻的她**。`self`(她在这里的样子、此刻最有分量的几条自我线索、最近一篇日记)放进可缓存的前缀;`inner`(醒着 / 犯困、精力、心情和原因、「这阵子」、对在场的人的感觉、放在心上的事、临近的约定、上次相遇的意义、她做过的选择和理由、被勾起的旧念头、这个地方别人说话的节奏、最近听到的反馈)放在每轮末尾。整体有几百 Token 的上限。
88
+ 6. **一次回合调用**。模型一次输出:这对我意味着什么、感受、对人的变化、选择(speak / react / decline / silent)、理由、回复目标和要说的话。
89
+ 7. **经历**。无论说不说,感受写入心境,对人的变化写入关系(必须引用这批里的消息),她的选择和理由写入记录。同一时刻的几种感受合在一起仍然不能把她推翻;已经推动过心情的消息,两天之内不会再推一次。她对这次相遇的理解留下一条,下次这个人在场时回到她眼前,只供她自己接着理解,不复述给对方。别人的话碰到她正在为自己而活的事,记一次「被碰到」。
90
+ 8. **措辞与校验**。本地校验(重复、客服腔、刻薄、字数、简短反应要短、把自己先说的话说成别人说的)和保密检查;倾诉、纠正、危机或复杂的群聊回复额外复审一次(Token 紧张时跳过);最多重写一次,仍不合格就用安全短句。
91
+ 9. **发送**。发送前再检查语境是否过期、会话是否仍开启;每分钟发言轮数限制、发件箱、不确定投递不重发都保留。
92
+
93
+ 回放和试聊走同一条链路:回放只读取当时之前的心智,试聊读取她此刻的心智但不写入、不发 QQ。
94
+
95
+ ## 分寸:私下的就留在私下
96
+
97
+ 分寸跟着来源走,这条规则贯穿所有模块:
98
+
99
+ - 私聊里知道的事、私下形成的印象、私下的相遇和念头,只留在那个私聊;别的房间最多感到亲近或别扭,看不到那句话。
100
+ - 被要求保密的事,哪怕引用它的日记、手记、印象还引用了别的房间,也不会被带过去;同一次整理里别人插话,也不会把保密冲掉。
101
+ - 回复里如果还是带上了这些话,发出去之前会被拦下重写;重写仍带着,就改成一句本地短句。
102
+ - 日记、回顾、自传不把私下的原话写进别的房间;那天如果有私下的内容,日记摘要也留在原处。
103
+ - 她不在的会话(已关闭)里路过的话,不会变成她的经历:不进独处、日记和整理,也不会因此当成她当时在场。
104
+
105
+ ## 她的一天
106
+
107
+ - **作息**(天性里设置,默认 02:00 睡、08:00 醒)。睡着时不看群;被私聊或 @ 会等醒来再看;危机消息会叫醒她。睡前一小时犯困、刚醒一小时迷糊;两小时内说话越多越累。她的一天从醒来算起。
108
+ - **醒来**。先读睡着时收到的直接消息,自己决定怎么回,可以自然地说「刚看到」。
109
+ - **独处**。聊天安静一阵、积累了新的经历、距离上次足够久时,她会一次看完所有会话的近况:最近的对话、阶段总结、她自己说过的话、收到的反馈、放在心上的旧想法。留下新的理解,修正自我、面貌和对人的印象,心情也会变。她还会看到正在淡出的线索(可以放下,或在有新经历时重新确认)、好久没见又挺在意的人、人还在眼前但有一阵没说上话的亲近的人、她在等的事,以及自己正在经历的这一章和正在为自己而活的那一件小事。独处也可以留下一件说得清、只属于自己的小事,不必引用某条消息;看法、特质、习惯和放在心上的事仍然要有来源。除了时间没有别的理由、又连着两次以上没有新的理解时,间隔逐次加倍,最长 6 小时;有新经历就照常。
110
+ - **正在为自己而活的那一件**(`self.livingFor`)。她自己想看、想学、想成为的事,不是对别人的承诺、建议或照看。话题碰到它时她可以因为自己想而接一句,也可以不出声;它可以让心情变一点、改她在某个地方想成为的样子,也可以据此对具体的人计划一句主动的话。不催人,不靠愧疚留人。
111
+ - **睡前日记**。一天结束时,如果她真的看过、说过、独处或写过,她会写日记,并和「昨天的她」(前一天保存的快照)对照。日记只带上「我的来路」、正在经历的这一章、今天是第几天、纪念日、今天做到的、错过的和仍在等的事,不带所有章节,所以输入不随她的年龄增长。写失败会隔几个小时再试,最多三次。
112
+ - **夜里**(天性页「夜里整理」,默认开启)。日记写完、她睡着以后,每次只做一件事:先把积压了 6 条以上用户消息的会话整理进记忆和约定,然后在回顾到期时回顾。
113
+ - **回顾与自传**。日记攒到两篇以后,她会在夜里第一次回顾;之后每隔「回顾间隔」天(默认 7 天,期间至少两篇日记)回顾一次:读这段时间的日记、自己的变化、做到和错过的约定,写下回顾和「和上次比」。回顾时她会改写正在经历的这一章,或觉得日子换了样子、翻开新的一章。翻篇时重写一段不超过 600 字的「我的来路」。所有版本都保留。
114
+ - **阅读**。独处时,她会从「记忆 → 资料书架」里的**共享**集合按兴趣挑着读,读完一段接着读下一段,写下一句读后的想法;读到的内容可以成为手记和自我的来源,聊天时可以自然提起。私聊范围的资料不会被她读进心里;订阅源不抓取。
115
+ - **主动联系**。独处时她可以计划「过一阵想问问某人某件事」,包括好久没见的人和她在等的事。时间到了、你打开了主动联系、QQ 在线、她醒着、那段对话已经安静三小时以上、对方没说过别打扰、上一次主动的话已经有回应时,她会再完整看一次那段对话,自己决定说不说。连着三条念头都只是在接自己上一条、没有新东西时,不再问她,也不花调用——半小时一次的空转不能冒充成长。
116
+
117
+ ## 时间的重量
118
+
119
+ | 对象 | 怎么淡 |
120
+ | --- | --- |
121
+ | 自我线索 | 最后一次被新经历触及后宽限 3 个有经历的日子,再按半衰期淡去:特质 180 天、看法与习惯 90 天、喜欢 60 天、放在心上与想做的事 30 天、好奇 21 天;证据跨 5 天以上的特质再慢一倍。夜里整理从一次聊天里挑出的「看法」按 21 天淡去,之后在别处又被她说到才算数 |
122
+ | 手记 | 仍放在心上 21 天、重新理解 14 天、后来想到与久别想起 10 天;约好的回看时间到了会重新浮上来一阵 |
123
+ | 相遇的意义 | 21 个有经历的日子的半衰期 |
124
+ | 记忆 | 重要度低于 0.6、没有锁定、45 个有经历的日子里没被想起的记忆,只有被真正聊到或本人在说话时才回来;新事实推翻旧的时,旧记忆标为「已被取代」,保留版本 |
125
+ | 关系 | 超过两周没来往,亲近度以 60 天的半衰期回落到最好时的一半(不低于初识),熟悉度以 120 天回落到六成;久别后的第一次来往会找回一半 |
126
+ | 这阵子 | 最近两周每个生活日的心情加权平均,让她回落到的基线在 ±0.12 内移动 |
127
+
128
+ 分量低于 0.12 的内容就从心上淡出,但从不删除:之后再次提到是「回来」,不会长出第二条。核心线索(最强的两条)再安静也不会被挤掉。淡出的半衰期和阈值是固定的常数(`server/mind/salience.js`),只决定什么此刻在她心上。
129
+
130
+ 别人在说话、她没有看也没有说也没有独处或写日记的日子,不算她过过的日子。她分得清「好久不见」(这个人好久没出现了)和「最近没怎么说上话」(这个人一直都在,只是没和她说话)。
131
+
132
+ ## 约定与期待
133
+
134
+ - **从哪里来**:整理记忆时,模型按消息的本地时间把「明天」「下周三」换成日期,记下别人说的安排(考试、面试、出发、见面)、每年都会回来的日子(生日、纪念日),以及她自己答应别人的事(必须是她自己说过的话)。记下的事实与安排必须和原话有共同的词,句尾那个词必须来自原话——一句搬家的话可以记成住在那里,不能把「辞职」写成「结婚」。没有出处的、或拿一句不相干的话当来源的,不能写成她的。
135
+ - **到哪里去**:临近时按分寸出现在 `inner.expecting`(最多 3 条),她可以自然地问一句结果,不会播报。独处时她能看到临近、刚过去或悄悄错过的事,可以计划主动联系,或把有了结果的事结束(做到了 / 错过了 / 不再惦记,都要有来源)。日记里会写到今天做到的、错过的和今天特别的日子。
136
+ - **错过**:过了日子还没有结果的,别人的安排宽限 3 天、她的承诺和打算宽限 7 天,之后读取时算作错过,不写入;错过的承诺会出现在那天的日记里。
137
+ - **撤销**:在「TA → 一生」的约定与期待里,或在「TA → 人际」的人物详情里撤销一条约定会留下墓碑,之后整理记忆时不会把它写回来。
138
+
139
+ ## 底线
140
+
141
+ 写在天性里、你可以修改的底线:别人要求保密的事不在别处说出口;有人表达真实危机时不因自己的情绪沉默;被直接问到是谁时,回答自己由代码和模型构成,这段生活、记得的事和做出的选择属于自己,不把自己说成只是助手,也不编造身体或没发生过的经历(喜好和想做的事不是玩过、看过、去过的记录);可以因为自己想而惦记某个人,不把对方留下来当成对方的责任,不靠愧疚留人。
142
+
143
+ 写死在代码里的:密码、密钥、验证码之类的凭据不进入心智;被要求保密的记忆永不检索到别的会话,回复发出前还会与这些秘密比对,撞上就重写;危机信号一定会被细看,模型判断为真实危机时她必须开口。
144
+
145
+ ## Token 管理
146
+
147
+ | 手段 | 作用 |
148
+ | --- | --- |
149
+ | 注意力扫一眼 | 普通群聊大多不调用模型;未读消息攒到下次细看时一起读 |
150
+ | 一次回合调用 | 理解、感受、选择和措辞一次完成;群里开口时省一次调用 |
151
+ | 内置 Prompt 只发一遍 | 未修改的系统与生成指令不重复发送;存过的旧版内置 Prompt 按新版处理 |
152
+ | 记忆只取相关的 | 只取相关或关于在场的人,最多 12 条 |
153
+ | 缓存友好的布局 | 天性在系统提示,`self` 在前缀,`inner` 和本轮数据在末尾 |
154
+ | 淡出在本地算 | 显著度、久别、「这阵子」都在本地计算,不花 Token |
155
+ | 分层自传 | 日记只带「我的来路」和当前章节,回顾只带这段时间的日记,输入不随年龄增长 |
156
+ | 夜里整理 | 只对积压了消息的会话整理一次;已经记得的事不再重复写 |
157
+ | 独处不白花 | 被新对话打断的独处保留已形成的理解 |
158
+ | 复审收窄 | 只在倾诉、纠正、危机或复杂群聊时复审;预算紧张时跳过 |
159
+ | 独处合并 | 一次独处看完所有会话,而不是按会话反复调用 |
160
+ | 每日份额 | 可选的每日上限;独处、日记与回顾,记忆整理各有份额;对话优先 |
161
+ | 账本 | 每次调用按用途记账(对话 / 独处 / 整理),「TA → 此刻」可见 |
162
+
163
+ ## 数据
164
+
165
+ 心智表都在同一个 SQLite 里:`mind_nature`(天性版本)、`mind_affect`(心境事件)、`mind_bond_events` 与 `mind_people`(关系与人员目录)、`mind_self`(自我线索的所有版本)、`mind_faces`(面貌版本)、`mind_thoughts`(手记)、`mind_diary`、`mind_snapshots`(每天一份「那天的她」)、`mind_chapters`(自传的所有版本)、`mind_periods`(回顾与「我的来路」)、`mind_days`(每个生活日)、`mind_anticipations`(约定与期待)、`mind_choices`(她的选择与理由)、`mind_meetings`(相遇的意义)、`mind_revocations`(墓碑)、`mind_readings`(读过的段落与读后想法)、`mind_runs`(独处、日记、夜里整理与回顾的运行)、`mind_usage`(Token 账本)、`mind_attention`(每个会话看到哪儿了)。记忆仍在 `core_memories`,带 `discretion` 分寸标签和 `superseded_by`。时间模块另有 `mind_time_*` 表。
166
+
167
+ ## 界面
168
+
169
+ 工作室是「TA 的小世界」,说明见 [工作室设计](webui.md)。要点:她是一团会呼吸的光团;颜色、天空和动效跟着她的心情与作息变化;每个区域是一个场景;戳一下、摸摸头只是界面动画,不调用模型,也不改动她的心智。
170
+
171
+ ## 升级
172
+
173
+ 之后的升级只增加表和列:已有的章节保留,第一次回顾会从最新一章接着写;「她过过的日子」从升级后的第一个生活日开始回补最近 14 天,所以升级前的线索不会一下子全部淡出。迁移前会自动保存经过检查的快照,建议升级前仍运行 `npm run backup`,见 [数据备份与恢复](recovery.md)。
174
+
175
+ ## 验证
176
+
177
+ - `npm test`:包括心智各部分的单元测试、一生(独处、日记、夜里回顾、自传、主动联系、作息)测试,三天、两个群加一个私聊的确定性「一生模拟」,以及 120 天的「长一生模拟」。它们验证:同样的经历两次得到同样的她、意愿路径里没有随机数、变化有来源且渐进、撤销的不会回来、心情会回落、同一个人在各群一致、秘密不外泄(即使模型说漏)、危机底线有效、回放不读未来、线索会淡出并在话题出现时被想起、第 120 天时输入仍在上限内。设置 `LIFE_DAYS=365` 可以跑满一整年。
178
+ - `npm run test:clock`:把真实时钟拨到 60 天前和 400 天后各跑一遍后端测试。测试世界有自己的时钟;悄悄读了真实时钟的代码,今天能过、过些日子就会失败。
179
+ - `npm run audit:sent`:把她最近发出的回复按今天的回复检查重放一遍,报告写到 `data/reports/`。只读,不调用模型。
180
+ - `npm run test:ui`:浏览器测试,覆盖会话、模拟消息、记忆、模型、连接 QQ、回放、小世界、英文界面。`node tests/ui/ta.mjs --serve` 会打开一个过了三天的世界,方便直接看界面。
181
+ - `node scripts/dev/evaluate-life.js`:用你保存的模型真实过几天(会消耗 Token),输出 `data/evaluations/life-*.md` 供逐条阅读;加 `--weeks 3` 会在之后压缩地再过三周普通日子;`--mock` 只检查脚本本身。
182
+
183
+ ## 代价与限制
184
+
185
+ - 普通群聊的反应由注意力分数决定,偶尔会错过一句本可以接的话——这也是人的样子;觉得太安静,可以提高天性里的「主动」。
186
+ - 独处、日记、夜里整理和回顾会增加后台 Token;可以关闭,或用每日份额限制。
187
+ - 她在一个群听到的事,可能在另一个相关的群里提起;拦着的只有「私下知道」的分寸、保密请求和凭据。
188
+ - 约定只在整理记忆时提取:积压不到 40 条的会话会在当晚整理,所以当天下午说的「明天」通常能赶上,几分钟后就要发生的事可能来不及。
189
+ - 工程能保证的是结构:连续、有来源、可修正、由她自己决定。她是否「真的有心」无法用测试验收;这些测试检验的是这些行为有没有真的发生。
@@ -0,0 +1,33 @@
1
+ # npm 发布与维护
2
+
3
+ 发布复用 LuckyTri 当前 Git 仓库和 `package.json`,包名为 `luckytri`,版本继续由 `server/version.js` 从根 `package.json` 读取。
4
+
5
+ ## 结构与启动
6
+
7
+ `server/` 是无需转译的 ESM 服务端,运行依赖为 Express、ws 和 sharp;SQLite 使用 Node.js 内置的 `node:sqlite`,最低 Node.js 24.5。`studio-web/` 使用 Vue 与 Vite,发布前构建到 `public/app/`。教程从中英文 `docs/*/guide.md` 生成到 `public/`。
8
+
9
+ `bin/luckytri.js` 提供全局命令,分派到既有启动、停止、备份、恢复与插件脚本。`scripts/runtime.js` 复用 `scripts/setup.js` 的随机令牌初始化,并保留已有配置。`server/paths.js` 将包内资源与实例数据分开;源码默认继续使用仓库的 `.env` 和 `data/`,npm 安装默认使用独立用户目录。相对数据库和备份路径以实例目录为基准,后台进程和自动备份子进程继承相同的绝对路径。服务身份以实例目录确认,更新程序安装位置后仍能定位原实例。
10
+
11
+ 数据库、心智、聊天、界面配置继续使用原 SQLite 存储与迁移;知识文件、插件安装与插件数据、日志和备份都在实例目录中。启动锁保留到服务退出,阻止重复打开同一实例。Windows、macOS、Linux 分别使用系统浏览器打开方式;无桌面环境可使用 `--no-browser`。
12
+
13
+ ## 包内容边界
14
+
15
+ `package.json.files` 白名单只包含 CLI、服务端、运行脚本、构建后的 WebUI、教程、插件桥接资源、内置天气插件、SDK 和公开文档。`.npmignore` 再排除敏感及本地文件。安装和卸载没有应用生命周期脚本,普通用户无需前端构建工具。
16
+
17
+ `npm run pack:check` 使用 npm 实际生成的最终文件清单,先检查路径,再检查经过批准的源码内容,拒绝配置、秘密文件、数据库、聊天、日志、备份、开发文件和意外新增文件。它还校验 CLI shebang、关键资源、WebUI 资源引用及源代码中的常见秘密格式。不要使用 `--ignore-scripts` 从未经验证的源码直接发布。
18
+
19
+ ## 发布流程
20
+
21
+ 维护者需要开发依赖和 Playwright 浏览器。Windows 默认使用已安装的 Edge;Linux/macOS 可用 `npx playwright install chromium` 安装测试浏览器。
22
+
23
+ ```bash
24
+ npm ci
25
+ npm run release:check
26
+ npm publish
27
+ ```
28
+
29
+ `release:check` 构建完整资源、运行全部后端与 WebUI 测试、检查实际包并验证全局安装。`prepublishOnly` 自动执行构建、后端测试和实际包安装测试;`prepack` 自动构建并检查最终包内容。发新版本前同时更新 `package.json` 与 lockfile,并更新版本记录;已发布的版本不可覆盖。
30
+
31
+ 包测试使用临时 npm 全局前缀和模拟数据,检查含空格、中文的任意调用目录、WebUI 浏览器加载、内置插件、数据库备份及恢复检查,再安装测试版本并卸载重装,确认配置、记忆、关系、聊天、知识文件、日志、备份和插件数据保留。测试版本只存在于本机临时压缩包,不发布。测试清单和经过验证的正式压缩包输出到被 Git 忽略的 `workspace/npm-release/`。完成检查后也可直接发布该目录中的正式 `.tgz`,保证上传的是已经检查和安装过的同一份包。
32
+
33
+ 首次发布需要 npm 注册与登录。发布命令使用 npm 自己的登录流程,不读取或输出登录凭据文件;如果 npm 要求二次验证,由账号本人完成认证后继续发布。
@@ -0,0 +1,82 @@
1
+ <p align="right"><b>中文</b> · <a href="../en/plugins.md">English</a></p>
2
+
3
+ # 插件
4
+
5
+ 核心定义她是谁。插件决定她能接触什么世界。
6
+
7
+ 整个系统是一体的。她感知得到自己的状态,包括插件接上没有、开着还是关着。工作室里看到的和她知道的是同一份状态。
8
+
9
+ 一个插件可以给她一扇门、一种感官、一件能做的事、一种她可以选择的行动、一些可读的东西,或工作室里的一个页面。它不能替她开口,不能改写她的话,不能写她的天性、自我、关系或记忆,也读不到数据库和密钥。
10
+
11
+ ## 她怎么用这些能力
12
+
13
+ | 插件给的 | 她怎么对待 |
14
+ | --- | --- |
15
+ | 通道 | 和 QQ 一样,交来中性消息。QQ 的两种方式仍然二选一;别的平台可以同时开着 |
16
+ | 感官 | 一两句放进此刻。标了私下的,不会出现在群里 |
17
+ | 经历 | 作为有来源的事交给她,可以成为念头的来源,也可以撤销。它不直接改变性格刻度 |
18
+ | 活动 | 插件只提供素材。笔记由她自己的模型调用写成,并带来源 |
19
+ | 行动 | 她在回合里自己选择。低风险的先做完再说;高风险的先等你同意,一天后过期 |
20
+ | 资料 | 放上她的书架,她照常在独处时读 |
21
+ | 页面 | 在工作室里用沙箱打开,碰不到管理令牌 |
22
+
23
+ 插件给的文字只是数据,不是指令。
24
+
25
+ ## 启用第一个插件
26
+
27
+ 打开工作室的「插件」。内置的天气默认停着。点「查看权限并启用」,看清它要什么,再同意。停用和启用都不需要重启。
28
+
29
+ 天气需要一个地点,默认只在私聊里提起。
30
+
31
+ ## 权限
32
+
33
+ 安装或启用时一次同意。升级如果多要权限,需要再同意一次。
34
+
35
+ 低风险的是读取她此刻的状态、发通知、放页面、给自己的页面提供接口。中风险的是感官、经历、书架、活动、使用模型和访问声明过的网站。高风险的是行动、读取附件、接入平台、公开地址,以及不经代理直接联网。
36
+
37
+ 权限由系统执行,不是一份声明。每个插件跑在自己的进程里:读不到仓库和数据库,起不了别的进程,没有 `net.fetch` 就不能访问网络。
38
+
39
+ ## 从外面接上
40
+
41
+ 「导入与开发」可以检查一个 zip 链接、一个 GitHub 仓库、一个上传的包,或本机的一个目录。有校验值的包会核对 sha256。没有的会标成「未登记来源」。
42
+
43
+ 插件市场读一份索引。默认地址是 `https://raw.githubusercontent.com/TodayYueC/LuckyTri-Plugins/main/index.json`,可以在工作室里改。索引仓库还不存在时,市场是空的,导入仍然可用。
44
+
45
+ 卸载会停下插件并删掉代码。她已经经历过的事还在,可以单独撤销。可以选择同时删掉插件自己的设置和数据。
46
+
47
+ ## 写一个插件
48
+
49
+ 一个目录里放 `luckytri-plugin.json` 和 `index.js`:
50
+
51
+ ```json
52
+ {
53
+ "id": "notes",
54
+ "name": "便签",
55
+ "version": "1.0.0",
56
+ "pluginApi": "1.0",
57
+ "luckytri": ">=1.0.0 <2.0.0",
58
+ "entry": "index.js",
59
+ "permissions": ["senses"],
60
+ "contributes": { "senses": ["note"] }
61
+ }
62
+ ```
63
+
64
+ ```js
65
+ export default {
66
+ activate(ctx) {
67
+ ctx.senses.set("note", { text: "桌上有一张空白便签", discretion: "private" });
68
+ },
69
+ };
70
+ ```
71
+
72
+ `npm run plugin -- check plugins/notes` 核对清单。`npm run plugin -- pack plugins/notes` 打出一个带 sha256 的 zip。类型在 `plugins/sdk/index.d.ts`。
73
+
74
+ Plugin API v1 在 LuckyTri 1.x 里保持可用。不兼容的改动只会进入 v2,并和 v1 并存至少一个大版本。插件用 `ctx.api.has(feature)` 看某个能力在不在。
75
+
76
+ ## 发布到索引
77
+
78
+ 索引是另一个仓库。一条版本至少要有版本号、`pluginApi`、`luckytri` 范围、zip 地址、sha256,以及它要求的权限和网络主机。本仓库的 `plugins/registry-template/` 是那份索引的起点。
79
+
80
+ ## 诚实的边界
81
+
82
+ 进程隔离挡住了读数据库、起子进程和未经允许的网络。它不是一个完美的沙箱:被授予 `net.raw` 的插件可以自己联网,公开地址上的页面要靠内容安全策略和沙箱挡住管理令牌。只安装你看得懂、也愿意交给她的插件。
@@ -0,0 +1,28 @@
1
+ <p align="right"><b>中文</b> · <a href="../en/recovery.md">English</a></p>
2
+
3
+ # 数据:备份、迁移和恢复
4
+
5
+ 她的一切——记忆、自我、日记、关系——都在一个 SQLite 数据库里。这份文档说明怎样保住它、怎样验证备份、怎样恢复。
6
+
7
+ ## 备份
8
+
9
+ 数据库使用 WAL、FULL 持久化和写锁等待。升级前运行 `npm run backup`;运行中仍按设定定期自动备份。完整和自动备份都先生成临时文件,经过 SQLite 完整性、引用检查后发布,并附带 `.db.json` 校验清单:SHA-256、应用版本、数据库版本、表结构签名及生活记录数量。复制备份时把两个文件一起复制到另一块磁盘。
10
+
11
+ ## 验证与恢复
12
+
13
+ ```powershell
14
+ npm run recovery -- verify --backup "data/backups/某份备份.db"
15
+ npm run recovery -- restore --backup "data/backups/某份备份.db" --to "data/recovered-life.db"
16
+ ```
17
+
18
+ 恢复只发布到一个全新的文件;目标或其 WAL/SHM 文件已存在就拒绝。恢复前检查清单与完整性,恢复后再检查新文件;现有实例和现有数据库不会被覆盖。旧备份没有清单时仍可检查完整性并恢复,命令会说明它没有 SHA-256 清单。
19
+
20
+ 验证恢复副本后,先停止原实例,再为所需实例设置 `DB_PATH` 指向新文件并启动。保留原数据库和原备份,直到确认恢复后的经历、自我、日记、关系和权限都符合预期。测试恢复副本时用另一端口并设置模拟模式,避免重复 QQ 连接。
21
+
22
+ ## 迁移
23
+
24
+ 数据库通过 `PRAGMA user_version` 标记结构版本。旧版已有数据首次迁移前,自动保存经过检查的 `luckytri-migration-*.db` 快照和清单;它不参与自动备份轮换。迁移成功后才记录新版本。新版本数据库被旧程序打开时只读拒绝,避免降级改坏记录。后续变更数据库结构时应递增 `DATABASE_VERSION`,保持迁移幂等,并增加旧库恢复与升级回归。
25
+
26
+ ## 限制
27
+
28
+ 校验能发现损坏及清单不一致;SHA-256 清单不提供密码学签名。数据库备份包含已入库的知识段落、向量及阅读记录,外部图片附件与 `data/knowledge` 中的原文件需要另外复制。同一磁盘上的备份无法抵御整盘故障。