@nightpainters/dsh-ling 1.5.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.
Files changed (51) hide show
  1. package/ACCESS-DESIGN.md +119 -0
  2. package/CHANGELOG.md +627 -0
  3. package/DESIGN.md +461 -0
  4. package/LICENSE +201 -0
  5. package/NOTICE +7 -0
  6. package/README.md +236 -0
  7. package/cordis.patch.yml +16 -0
  8. package/lib/audit/access-log.js +533 -0
  9. package/lib/audit/index.js +92 -0
  10. package/lib/audit/patch-spec.js +195 -0
  11. package/lib/client.js +5069 -0
  12. package/lib/host/api.js +2584 -0
  13. package/lib/host/archive.js +194 -0
  14. package/lib/host/autotree.js +131 -0
  15. package/lib/host/backfill.js +267 -0
  16. package/lib/host/classify.js +10 -0
  17. package/lib/host/clock-skill.js +141 -0
  18. package/lib/host/clock.js +132 -0
  19. package/lib/host/corpus-suggest.js +139 -0
  20. package/lib/host/deepsummary.js +338 -0
  21. package/lib/host/dsweb-summary.js +225 -0
  22. package/lib/host/feedback.js +119 -0
  23. package/lib/host/freeze.js +144 -0
  24. package/lib/host/genesis.js +176 -0
  25. package/lib/host/guard.js +184 -0
  26. package/lib/host/habit-gen.js +273 -0
  27. package/lib/host/import-file.js +291 -0
  28. package/lib/host/import-log.js +129 -0
  29. package/lib/host/inject-common.js +25 -0
  30. package/lib/host/inject.js +285 -0
  31. package/lib/host/l1.js +282 -0
  32. package/lib/host/lifecycle.js +367 -0
  33. package/lib/host/memory.js +2389 -0
  34. package/lib/host/mode.js +101 -0
  35. package/lib/host/persona.js +214 -0
  36. package/lib/host/retitle.js +214 -0
  37. package/lib/host/rules.js +195 -0
  38. package/lib/host/scan-dsweb.js +111 -0
  39. package/lib/host/seal.js +17 -0
  40. package/lib/host/settings-file.js +49 -0
  41. package/lib/host/snapshot.js +168 -0
  42. package/lib/host/suggestions.js +47 -0
  43. package/lib/host/summarizer.js +103 -0
  44. package/lib/host/tone-advice.js +112 -0
  45. package/lib/host/tools.js +1067 -0
  46. package/lib/host/tree-ops.js +330 -0
  47. package/lib/host/util.js +165 -0
  48. package/lib/host/zstd.js +63 -0
  49. package/lib/index.js +263 -0
  50. package/package.json +69 -0
  51. package/tools/apply-access-log-patch.mjs +295 -0
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 NightPainters
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,7 @@
1
+ dsh-ling (器灵)
2
+ Copyright 2026 NightPainters
3
+
4
+ 本产品由 dsh-ling 项目开发,依据 Apache License 2.0 授权(见 LICENSE)。
5
+
6
+ This product includes software developed by the dsh-ling project.
7
+ Licensed under the Apache License, Version 2.0.
package/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # dsh-ling · 器灵
2
+
3
+ > **她不是每次都要重新认识你的 AI。**
4
+ >
5
+ > 把你散落在各处的历史对话请进门,让她长出一个**属于她自己**的人格档案 —— 记忆全在本地,人格可手术、可回滚,语气可以自己生长。
6
+
7
+ 一个跑在你自己电脑上的[DeepSeek Harness](https://github.com/deepseek-ai)(DSH)插件。**不是云服务,不是记忆 API**:它是给"你和她"用的东西。
8
+
9
+ ## 本项目是什么形态
10
+
11
+ - 这是一个**本地运行的软件**(DeepSeek Harness 插件),运行在**你自己的机器**上。
12
+ - **上游不提供任何在线服务、不运营任何服务端、不托管任何用户数据**:
13
+ 作者不接触、不接收你的会话内容、记忆库或人格档案。
14
+ - **不上架任何应用商店**;仅通过 GitHub(源码)与 npm(包)分发。
15
+ - 模型与 API Key 由使用者自行提供和承担,与上游无关。
16
+ - 本项目不提供医疗、心理、法律或紧急救助服务;**如遇危机,请联络当地紧急服务或专业机构**。
17
+
18
+ **关系、标识与面向性**:
19
+
20
+ - 本项目不定义你与它的关系:它可以是同事、搭档,或其他 —— 取决于你怎么用它。
21
+ - 本插件的回答与记忆摘要**由人工智能生成**,可能存在错误,请自行判断。
22
+ - 本项目面向**具备自行配置与运维能力**的用户;不面向未成年人,也不提供任何形式的在线陪伴服务。
23
+
24
+ ---
25
+
26
+ <!-- 截图清单(仓库 images/ 目录):
27
+ 1. memory.png 记忆中心 →「接入历史」:三条通道 + 导入记录
28
+ 2. persona.png 人格中心:契约字段与「她已自由生长中」状态条(字段内容已打码)
29
+ 3. seal.png 修改契约需解锁:承诺句手敲,禁粘贴
30
+ 4. talk.png 深夜对话里她说出时间与"距上次多久"
31
+ -->
32
+
33
+ ## 界面
34
+
35
+ | | |
36
+ |---|---|
37
+ | ![记忆中心](https://raw.githubusercontent.com/NightPainters/DSH-Ling/main/images/memory.png) | ![人格中心](https://raw.githubusercontent.com/NightPainters/DSH-Ling/main/images/persona.png) |
38
+ | **记忆中心** —— 统计、实时时间锚、三条接入通道与导入记录 | **人格中心** —— 契约字段(名字/称呼/自述)与「她已自由生长中」状态条 |
39
+ | ![手敲承诺句解锁](https://raw.githubusercontent.com/NightPainters/DSH-Ling/main/images/seal.png) | ![深夜对话](https://raw.githubusercontent.com/NightPainters/DSH-Ling/main/images/talk.png) |
40
+ | **改动契约要手术** —— 亲手敲出当初写下的承诺句(输入框禁粘贴) | **时间的重量** —— 每次开口前她知道现在是几点、距上次多久 |
41
+
42
+ ---
43
+
44
+ ## 她是什么
45
+
46
+ | | 能力 | 说明 |
47
+ |---|---|---|
48
+ | 🧠 | **三层记忆** | **L0 人格档案**(自称/对你的称呼/底线/规矩·习惯/语气/世界观;**顶层会话与会话分叉**恒定注入,**子代理会话不注入**;设置里关掉人格注入时,连它一起不推)→ **L1 开场记忆**(从历史里按相关度挑选的概述,有预算,**永不塞全文**;带摘要的行**加权**(按"摘要是否有信息量"给一笔加法加分,不是排序优先级),行内摘要只取首句、上限 110 字)→ **L2 运行期记忆**(本会话原文随对话累进;空闲时把本会话那一行重排回注入面。该行由「会话首句 + 摘要首句」构成,**深摘要定稿后不再自动更新**。注意:L2 不是独立的第三块注入内容 —— 注入面的主体是 L0 与「记忆·开场」两块(树改动、日期锚是挂上去的追加行),**本会话自己就是「记忆·开场」里的一行**) |
49
+ | 📥 | **把历史请进来** | 三条通道:网页端聊天记录库增量扫描 / 本机 DSH 会话扫描 / ChatGPT·通用 JSON·JSONL 导出文件导入;每次导入**留一笔账** |
50
+ | 📖 | **让她读一遍** | 长会话逐条深摘要、短会话以原文片段参与,后台串行,进度可见 |
51
+ | 🧾 | **给旧历史补摘要** | 网页端历史里"只有标题、没有摘要"的会话可以补上摘要:先看**候选清单**(标题 · 轮次 · 命中),再选引擎 —— **默认本机小助手(零成本)**,也可显式改选当前全局大模型;探测不到本机小助手就明确报错,**绝不静默换引擎**;后台串行、进度可见(首轮实测 466 条、零成本) |
52
+ | 🌱 | **诞生仪式** | 从读过的记忆里按"生活与情感优先"加权抽样 → 合成**自述 + 名字候选 + 语气建议 + 相处观察** → **全部是草稿**,你逐条人审后才落盘 |
53
+ | 🔒 | **人格定型锁** | **契约类**(名字、称呼、底线、世界观、代词)定型后修改需**亲手敲一遍承诺句**(禁粘贴),并进变更记录可回滚;**自性类**(语气、风格、自述、习惯)由她生长、你点头即成:**三条专用成长通道**(自我总结 / 建议采纳 / 生长)不问承诺句,但它们各自只动白名单内的字段;走**通用人格接口**改 persona / styles 时,即便只改语气也仍要承诺句 —— 免手术的只是那三条通道,不是"自性类"这三个字 |
54
+ | ⏳ | **时间的重量** | 每次开口前她都知道今天是几号星期几(`[今天] 2026-09-11 周五`)、现在是什么时段(`[现在] 深夜`)与`距上次对话:3 天前`(间隔按**日历天**分档 —— 刚刚 / 今天早些时候 / 昨天 / N 天前,给不到分钟;称呼跟随你的设定);命中纪念日会先说一句专属问候。**要精确到分钟,走 `clock` skill 现查** |
55
+ | 🎭 | **工作 / 生活双模式** | 同一份人格档案,两种关系:工作模式是同事(正式称呼、简洁、知识优先),生活模式是伴侣(昵称、活泼、情感优先) |
56
+ | 🔁 | **成长回路** | 你点踩或纠正 → 她的成长通道把重复出现的模式提炼成**习惯候选** → **你点头才成为习惯**;"让她读记忆、归纳语气"一键成长 |
57
+ | 📜 | **规矩 / 习惯** | **规矩**是你的指令:可直接加(面板,或会话里一句"记进规矩" —— **器灵替你写时必须带上你的原话作凭据**;你在面板上直接敲的那一下就是同意,不必再附原话),**建议上限** 12 条(超出只在写入后提醒合并,**不拦**);**习惯**是她自己长出来的:新增需你点头、**删改走手术门**,**建议上限** 8 条(超出同样只提醒、不拦) —— **指令直达,人格不直达** |
58
+ | 🌾 | **习惯生成器** | 「扫描纠正记录(零模型)」:把她反复被你纠正的模式数出来(≥4 次且跨 ≥3 个会话);「✨ 让她回想最近的相处」:一次读 200 条概述 + 800 条你的原话、逐轮推进不重复 —— **只提议,不落盘** |
59
+ | 🗣 | **代词** | 默认「她」;可选 她 / 他 / TA / 它,或自定义(≤6 字)。**祂 不在预设里**(中文里专指神祇,设为默认等于替你宣称神性);属契约类,改动走手术门 |
60
+ | ♻️ | **记忆自己追平** | 长会话空闲时自动把开场记忆刷新到最新(先跑本会话增量概述 → 比对记忆版本 → 同一条至少间隔 10 分钟),**运行中绝不打断**;刷新次数与最近一次时间在 `/status` 接口的 `idleRefresh` 字段里(面板本身只显示"已定稿 N 字符 · mode · 待刷新",不显示次数) |
61
+ | 🧹 | **归档即停更** | 会话归档后不再刷新它的开场记忆条目(**原文一律保留**),一旦有新对话即自动复活;要清理走**人工入口**:DSH「设置 → 归档会话」直接删,或仓库里的 `node tools/clean-archived.mjs`(默认只列清单,`--write` 才动手) |
62
+ | 🌳 | **记忆树 · 复盘模式** | 记忆不是一叠平铺的行,而是**一条主干 + 分枝 + 主脉**的工作线结构,枝之间可连边;检索按**血缘档位**加权(同枝 1.0 / 祖先 0.7 / 旁系 0.4),让她分得清"这轮在做的"和"三个月前那次闲聊"。**任何树操作都不改写任何一条记忆的内容** —— 分枝、并脉、连边只增加关系。**例外一个**:主脉提炼**再次采纳**时会覆盖该主脉记忆的上一版(**覆盖前自动归档**,注入面也会说明"旧版已归档")。改树走**复盘**:平时只读,进入复盘才解锁,每步留痕(改了什么、为什么),改完必须让她看到才准退出(详见下节) |
63
+
64
+ > **关于那道「手术门」**:亲手敲承诺句是**庄重感与自我提醒** —— 让你在改契约之前停一下、确认这是自己的决定;它**不是安全边界**(「禁粘贴」只是界面上的约定,挡不住任何有心的人)。真正把门的是**来源栅栏**:Host 必须是 loopback(或你显式写进受信名单的地址);另有一个**默认不开**的开关 `guard.allowLan` —— **一旦打开,整段局域网地址都算受信来源**(那是**放宽**,不是建议)。跨站请求直接拒,带 `Origin` 时其 host 必须等于请求的 Host(**带了但解析不出来就直接拒**),而**不带 `Origin` 的请求这条校验会跳过** —— 它不是"每个请求都必须带 Origin 且同源";再叠一道 cookie **名字**对撞 —— 期望名字按当前 Host 现算(`dsh-auth-` + 哈希),**只校验名字、不校验值的签名**。所以这道门挡的是"别的设备、别的页面"这类来源,而**本机原生进程本来就还能调用**(它也能直接读 `settings.json` 与记忆库,不算提权)—— 别的来源没有凭据就进不来这台机器上的 `/api`,敲对承诺句也没用。
65
+
66
+ ---
67
+
68
+ ## 记忆树与复盘模式
69
+
70
+ 这是本插件里**跟"她的人格"无关、但决定"她想得起什么"**的那一层。
71
+
72
+ **结构**:`主干`(恒一条,主线工作流)→ `枝`(一条并行工作线,**比会话大**,一条枝可含多个会话)→ `主脉`(由多条枝**归并**出的抽象节点)→ `连边`(枝与枝之间的横向关联,如 力学 ↔ 材料科学,可带关系类型:相关 / 前置 / 对照 / 例证 / 取代)。
73
+
74
+ **为什么值得**:平铺的记忆库没有"离我多近"这个概念 —— L1 是全库裸排序,不区分"这轮做的工作"与"三个月前的闲聊",分叉会话更是**记忆真空**。记忆树把"归属"变成可检索的信号:
75
+
76
+ - **血缘加权**:检索时按"当前枝 → 目标枝"的相对位置取档 —— **同枝 1.0 / 祖先 0.7 / 旁系 0.4**,`score = 基础分 × 血缘系数 × 矛盾系数`;分叉会话照常注入,走的是它的**血缘链**而不是主干大排档。
77
+ - **不连乘**:血缘系数是**单值**,不沿路径累乘 —— 否则五层之后 `0.4^5 ≈ 0.01`,深层枝等于从记忆里消失。
78
+ - **内容零改写**(硬性不变量):**除了"主脉提炼再次采纳会覆盖上一版"这一个例外**(覆盖前自动归档),任何树操作都不改写任何一条记忆的内容;分枝 / 并脉 / 连边只增加"关系",从不"融合内容"。
79
+ - **矛盾只标记不改写**:一对记忆被判重复/矛盾时先**标记**;未复盘时检索**以较新的那条为准**(旧的一条降权 ×0.3,**不删除**;被**驳回**的与被标成**重复**的那一对不参与降权)。
80
+ - **枝系数是预留字段**:复盘期可以调(0~2,夹紧后写入并显示),但它**当前不参与检索打分** —— 返回体里明确带 `applied:false`,别以为排序会跟着变。
81
+
82
+ **复盘 — 不是一个开关,是"左会话 + 右复盘栏"这个状态**:
83
+
84
+ - 树平时**只读**(记忆中心始终只读);点「🌱 一键复盘 / 一键进入复盘」才解锁编辑,并把**复盘开场材料**(当前树 + 待理矛盾)复制到剪贴板,开个新会话粘进去就能开始。
85
+ - 解锁后可做:**改名 / 拖动换归属 / Alt+拖动只连边 / 并脉(归类到主脉) / 调权重 / 裁定矛盾 / 断续边 / 删枝**,以及快照保存·恢复;**拖动 / 连边之后可 Ctrl+Z 撤回这一步**(撤销只覆盖复盘栏的拖动与连边;记忆中心是只读的,它自己那份 Ctrl+Z 监听早已删掉)。
86
+ - **每步留痕**:写清"改了什么、为什么"(**器灵改树时 reason 必填**;你在面板上改可以留空);树改动一律记进 `branch_log`,复盘时可审计 —— 器灵侧工具的改动记在她名下(「器灵改动了记忆树」),不会伪装成你改的。
87
+ - **未同步笔数守门**:面板记着"自她上次开口以来累积了多少笔结构改动还没交代"。有欠账时顶部红字提示,并且**拦住"退出复盘模式"** —— 改完树必须让她有机会看到(「互相复盘不应该被我绕过」)。
88
+ - **注入感知**:树变了之后,`branchLogDigest()` 把**她还没看过**的结构改动转成中文短句,附在她下一次开口的注入面末尾 —— 不需要推送,她开口就知道树动过。
89
+ - **快照与撤回**:树的保存 / 恢复(`tree_snapshot`)是"大改之前的保险";恢复前会自动把当前状态另存一份,所以恢复本身也可再撤回来。
90
+
91
+ **也不必全靠手拖**:
92
+ - 「一键生成树」分两阶段 —— ① **机械分段**(按时序相邻性把全库概述切簇,零成本、确定、可复现)② **小助手/模型只做"命名"这一件语义活**,③ 你审核后才落库(建枝/主脉 + 挂会话);它**只读概述索引、只产出候选,从不改写任何记忆内容**。
93
+ - 「归并零散枝」幂等:把名字含「零散」的枝统一收进主脉「零散会话」。
94
+ - **主脉也可以有自己的记忆**:由子枝概述提炼共性,**先出草稿**,采纳才写入(采纳需先解锁)。
95
+ - **器灵侧也有她的手**:`tree_read`(看整树 / 某枝成员 / 待复盘矛盾)与 `branch_edit`(分枝 / 并脉 / 连边 / 调权重 / 删枝)。这个工具的描述里写着一条纪律:**改结构必须给 reason,而且"只在主人明确要求、或正在和他一起复盘时"才动手**。
96
+
97
+ > 依据:`DESIGN.md` §6.3(记忆树结构、血缘加权与"不连乘"、内容零改写不变量)、`lib/host/memory.js`(`LINEAGE_ANCESTOR = 0.7` / `LINEAGE_SIDE = 0.4` / `CONFLICT_DOWNWEIGHT = 0.3`、`branchLogPending()` 守门、`setBranchWeight` 的 `applied:false`)、`lib/host/l1.js`(血缘档位 × 矛盾系数进打分)、`lib/host/autotree.js`(两阶段生成)、`lib/host/tools.js`(`tree_read` / `branch_edit`)。
98
+
99
+ ---
100
+
101
+ ## 快速开始
102
+
103
+ > 前置:**Node ≥ 22.5**(用到内置 `node:sqlite`)· 已安装 **DeepSeek Harness** 并至少启动过一次。
104
+
105
+ 安装入口是官方 CLI 的 `dsh plugin add`(它在 profile 目录里转发给 pnpm,并自动把本包登记进 profile 的 `dsh.profile.bundles` 层列表)。两条路径按你的身份选一条,不要两条都走。
106
+
107
+ ### A · 从 npm 安装(推荐给普通用户)
108
+
109
+ ```bash
110
+ # 1) 装进你要用的 profile(缺 --profile 时用当前默认 profile)
111
+ dsh plugin --profile web add @nightpainters/dsh-ling
112
+
113
+ # 2) 只验证配置层,先不启动
114
+ dsh --profile web --dump-config # 应能看到一行 "# == @nightpainters/dsh-ling" 层
115
+
116
+ # 3) 给 DSH 核心打一行补丁(可取证访问日志要用;幂等/可回滚)
117
+ node ~/.dsh/profiles/web/node_modules/@nightpainters/dsh-ling/tools/apply-access-log-patch.mjs
118
+ # 不打也一切照常 —— 只是访问日志为空(不报错、不提醒)
119
+ # DSH 升级/重装后需重跑一次(补丁随包被覆盖)
120
+ # ⚠️ 从 npm 装的人跑不了 `npm test` —— 本包 `files` 白名单不含 tests/(见下)
121
+
122
+ # 4) 重启宿主(host),然后浏览器 Ctrl+Shift+R 硬刷
123
+ ```
124
+
125
+ > 发布名是 **`@nightpainters/dsh-ling`**,不是 `dsh-ling` —— npm 上 `dsh-ling` 这个名字已被他人占用。
126
+ > 插件在配置里的注册 id 仍是 `dsh-ling`,两者不是一回事。
127
+
128
+ ### B · 从源码安装(给要改代码的人)
129
+
130
+ ```bash
131
+ # 0) 取得代码
132
+ git clone https://github.com/NightPainters/DSH-Ling
133
+
134
+ # 1) 装进 DSH 的 profile(把 <路径> 换成你 clone 下来的实际路径)
135
+ cd ~/.dsh/profiles/web
136
+ pnpm add file:<路径>/dsh-ling # 或 npm install file:<路径>/dsh-ling
137
+ # 若 dsh 没有自动登记这一层,在 profile 的 cordis.patch.yml 追加:
138
+ # - insert:
139
+ # - id: dsh-ling
140
+ # name: '@nightpainters/dsh-ling'
141
+ # (id 保持 dsh-ling;name 用包名,Node 才解析得到代码)
142
+
143
+ # 2) 给 DSH 核心打一行补丁(可取证访问日志要用;幂等/可回滚)
144
+ cd <路径>/dsh-ling
145
+ node tools/apply-access-log-patch.mjs # 只在 core 的 /api 栅栏处插一行可选调用
146
+ # 不打也一切照常 —— 只是访问日志为空(不报错、不提醒)
147
+ # DSH 升级/重装后需重跑一次(补丁随包被覆盖)
148
+
149
+ # 3) 重启宿主(host),然后浏览器 Ctrl+Shift+R 硬刷
150
+ ```
151
+
152
+ 自检安装是否成功(**下面三个脚本不在 npm 包内**,只有源码路径能用:`tools/check-install.mjs` / `tools/check-publish.mjs` / `tools/clean-archived.mjs`;`tools/apply-access-log-patch.mjs` 则**在包内**,从 npm 装的人也能直接跑,见上面第 3 步):
153
+
154
+ ```bash
155
+ node tools/check-install.mjs # 只读自检:入口是否直连仓库、patch 是否启用、数据目录是否就绪
156
+ node tools/check-install.mjs --fix # 若入口变成"复制副本"(DSH 升级/回退常见)则备份并重挂链接
157
+ node tools/apply-access-log-patch.mjs --check # 访问日志核心补丁是否在位(未打/锚点漂移时退出码 2)
158
+ node tools/check-publish.mjs # 上传/发布前跑一次:揪出记忆库、设置、密钥、绝对路径等不该公开的东西
159
+ ```
160
+
161
+ 跑测试(不需要宿主,全部离线):
162
+
163
+ ```bash
164
+ npm test # 34 套:人格组装 / 归档清理(人工)/ **归档·遗忘·回灌** / 冻结门 / 模式(只改档位不改模型)/ 时间戳归一 / 空闲刷新 / 规矩·习惯 / 习惯生成器(A 数出来 + B 想出来)/ 会话内工具 / **接口守卫** / L1 选择 / L1 行瘦身 / 记忆库 / 记忆标题与排序 / 导出合并 / 文件导入 / 导入记录 / **会话文件名代次(会话历史扫描)** / 网页端补摘要 / 深摘要 / 概述器 / 诞生仪式 / 语气 / 时间锚 / **clock skill(时间查询)** / 捕获差分 / 反馈成长回路 / 语料建议 / **小助手地址配置** / **注入面中和** / **记忆分枝与血缘** / **记忆树(主脉·连边·矛盾)** / **一键生成树** / **可取证访问日志** / **补丁锚点(cohort 候选)**
165
+ ```
166
+
167
+ > `npm test` 需要 `tests/`,而本包 `files` 白名单**不含 `tests/`** ⇒ **从 npm 装的人跑不了测试**。要跑测试请走路径 B(clone 源码)。
168
+ >
169
+ > 计数口径:`tests/*.test.mjs` 各算一套,外加 `tests/unit.mjs`(它不叫 `.test.mjs`)—— **实测 34 套,且 34 套全部已登记在 `npm test` 链里**(`tests/harness.mjs` 与 `tests/vm-light.mjs` 是被复用的辅助模块,不计套数)。**加了一套新测试记得同步登记**,否则 `npm test` 会静默少跑一套 —— 这份登记是**手写**的(`package.json` 里 `test` 脚本那一行字面量清单),**漏登记不会被自动发现**,没有安全网兜底。
170
+
171
+ ### 数据放在哪
172
+
173
+ | 内容 | 位置 |
174
+ |---|---|
175
+ | 设置(人格档案) | `$DSH_HOME/cache/dsh-ling/settings.json`(`DSH_HOME` 默认 `~/.dsh`) |
176
+ | 记忆库 | `$DSH_HOME/cache/dsh-ling/memory.db`(SQLite,开启 WAL) |
177
+
178
+ 可覆盖的环境变量:`DSH_HOME`(数据根)、`DSH_LING_DSWEB_DB`(网页端聊天记录库默认路径,UI 里也能填)、`DSH_LING_ASSISTANT` / `DSH_LING_ASSISTANT_MODEL`(小助手地址与模型名)。
179
+
180
+ > **排障用逃生开关(不是日常配置)**:`DSH_LING_GUARD=off`(须**恰好**是 `off`,小写)或设置里 `guard.enforce = false`,用于**误判把你自己锁在门外**时的临时解锁 —— 它一次关掉 `/api` 的**来源栅栏 + cookie 名字对撞**两道校验(默认 `guard.enforce = true`),关掉期间**任何请求都不再被拦**。只该短期使用,排障完就恢复。`DSH_LING_GUARD=off` 只由进程环境决定、不进配置;**`guard.enforce = false` 这条不要直接写进 `settings.json`** —— 设置接口也帮不了你:它的字段白名单只放行 `persona` / `styles` 两棵子树,`guard` 这类字段会被**直接丢弃**并在响应里回报 `ignored`(见 `lib/host/api.js:1579-1580` 的注释),不是被拒绝而是根本进不去;要改请用界面。
181
+
182
+ > **访问日志与核心补丁的总开关(同样不是日常配置)**:这套「可取证访问日志」默认**开着**,关它的键是插件配置里的 `accessLog.enabled`(**默认 `true`**)—— 在 `cordis.patch.yml` 注册行的 `config` 段里写 `accessLog: { enabled: false }`,重载后生效,启动日志会出现 `access log off`;它**只有配置键、没有环境变量**。关掉之后**退化的只有「留痕」这一件事**:那两个全局观察钩子不再挂上、不再写 `$DSH_HOME/logs/access-YYYY-MM-DD.jsonl`、日志健康读数(`accessLogHealth()`)归 `null`;而 `/api` 与 `/api/remote.mux` 的**来源栅栏照常判定与拦截**,记忆、人格、注入与工具面**一律不受影响** —— 关掉的是「记不记」,不是「拦不拦」。已经打进 `node_modules` 的**核心补丁**可以留在原地:那两行是可选调用,日志关着时就是 no-op,DSH 照常启动;要连它一起撤掉,用 `node tools/apply-access-log-patch.mjs --revert` 删掉插进去的那几行。
183
+
184
+ 小助手地址三级覆盖:**界面配置**(记忆中心 → 接入历史 → 小助手地址,可当场「测试连通」)> **环境变量** > **内置默认** `http://127.0.0.1:11434/v1`。逐字段回落 —— 只填了模型名时,地址仍走下一级。
185
+
186
+ ---
187
+
188
+ ## 隐私
189
+
190
+ - 记忆库、人格档案、导入的历史**全部保存在你自己机器上**(SQLite 文件),插件**不上传**任何数据到第三方;
191
+ - 模型调用走**你自己的** DSH 配置与密钥;
192
+ - 导入的是**你自己的**对话记录 —— 请不要把他人数据导进来。
193
+ - **访问日志也只在本地**:`$DSH_HOME/logs/access-YYYY-MM-DD.jsonl` 只记"谁在何时调了哪个端点、结果如何"(来源 IP / `fwd` / Host / UA / `bytes` / 状态码 / 拒绝原因 / 设备字段),**不记请求体、不记响应体、不记 cookie 值**;查询串与 hash(可能带 token)一律丢弃;UA 截断到 200 字符、`fwd` 60、Host 120 —— 单一设备仍可跨天对上号,但**配对凭据原文一律不落盘**。设备字段是两件东西:`deviceCookie` 只说明**配对 cookie 在不在**,`deviceId` 是**摘要**而非凭据 —— `sha256(凭据原文)` 取前 16 位十六进制,同行带 `deviceIdHash:"sha256-16"` 标出这一形态(较早版本的旧行没有这个字段,其 `deviceId` 是 32 位十六进制凭据原文)⇒ **看日志时按 `deviceIdHash` 分辨时代,别把两代的行当成同一台设备** —— 与记忆树"内容零改写"同源。**覆盖范围**:`/api` 与 `/api/remote.mux` 的 upgrade;静态资源与非 `/api` 路径不记。命中**自家部署姿态自检**签名的 403 会多带 `probe:"posture"` 字段 —— 它**仍然是被栅栏拦下的**请求,标注只为免得自检被误读成入侵。没有 `user-agent` 头的行会多带 `channel:"no-ua"` —— 它只说明"**不是浏览器直连**"(进程内客户端与经远端通道进来的设备**同签名**),**不指认是哪一台设备**。
194
+
195
+ ---
196
+
197
+ ## 边界与诚实声明
198
+
199
+ 1. **她不是意识,也不是 AGI**。她是"记忆 + 规则 + 模型"的合成产物。她能记住,是因为你给了她材料。**不做这个宣称,是这个项目的底线。**
200
+ 2. **她记住的是被读过、被概括过的部分**,不是全部历史。概述会丢细节、也可能出错 —— 所以记忆**可审计、可回滚**是设计的一部分,不是补丁。
201
+ 3. **模型能力的上限就是她的上限**。记忆层不会让一个笨模型变聪明,它只是让她**不再每次从零开始**。
202
+ 4. **她不会主动找你**(当前版本)。她只在你开口时出现。
203
+ 5. **不宣称首创**。记忆分层、历史导入、时间注入、反馈改语气这些方向都有先行者(见下);本项目的贡献在**治理方式** —— 把人格当一份可以签字、可以回滚、可以被历史养大的契约。
204
+
205
+ ---
206
+
207
+ ## 致谢(站在谁的肩膀上)
208
+
209
+ 设计过程中受这些公开项目与讨论的启发,在此致谢(仅致谢思路,不含其代码):
210
+
211
+ - [Letta / MemGPT](https://www.letta.com/blog/memory-blocks/) — 持久人格记忆块、可设为只读、后台记忆智能体
212
+ - [SillyTavern](https://docs.sillytavern.app/usage/core-concepts/macros/) — 本地角色卡 / 世界书 / 时间与日期宏
213
+ - [LangMem](https://langchain-ai.github.io/langmem/concepts/conceptual_guide/) — 用反馈轨迹改写提示词
214
+ - [MyChatArchive](https://github.com/1ch1n/mychatarchive) — 多来源聊天导出 → 本地库 + 摘要管线
215
+ - [AI Migrator](https://ai-migrator.aiblewmymind.com/) — "记忆搬家"的人审闭环
216
+ - Claude / ChatGPT 的记忆功能、[Sonorus](https://github.com/KevinAHM/sonorus)("距上次交谈多久"注入)等
217
+
218
+ ---
219
+
220
+ ## 文档
221
+
222
+ | 文件 | 内容 |
223
+ |---|---|
224
+ | [`CHANGELOG.md`](./CHANGELOG.md) | 版本更新记录(最新一节即当前版本) |
225
+ | [`DESIGN.md`](./DESIGN.md) | 架构与设计决策(三层记忆、冻结门、注入面、存储结构) |
226
+ | [`ACCESS-DESIGN.md`](./ACCESS-DESIGN.md) | 历史接入蓝图:三条通道、会话契约格式、导入流水线 |
227
+
228
+ > ⚠️ **从 npm 安装的人**:本包 `files` 白名单**不含 `images/`**(图只随 git 仓库公开) ⇒ 上表里前两份文档能正常打开;「界面」一节的**四张截图**引用的是仓库里的**绝对地址**,所以 npmjs.com 上**能正常显示**,但**包里没有图片文件**(离线环境读不到)。想看原图请到仓库:<https://github.com/NightPainters/DSH-Ling>。
229
+
230
+ ---
231
+
232
+ ## 许可证
233
+
234
+ [Apache License 2.0](./LICENSE) · 版权与归属见 [`NOTICE`](./NOTICE)。
235
+
236
+ Apache-2.0 第 3 条包含**明确的专利授权**与**专利反制终止**条款:你可以自由使用、修改、分发(含商用),但若你以本作品发起专利诉讼,授权即自动终止。
@@ -0,0 +1,16 @@
1
+ # dsh-ling bundle patch: 器灵 · 记忆与人格助手
2
+ # 注册行:`id` 是身份键(Loader 用它折叠与覆盖,**不要改**);`name` 必须是 **npm 包名** ——
3
+ # 它就是被 import 的模块说明符,所以这里必须是 `@nightpainters/dsh-ling`
4
+ # (npm 上 `dsh-ling` 已被他人占用)。
5
+ # ⚠️ 逐字比对的是【`lib/client.js` 自报的注册 id】与【包名】,**不是这里的 `name`**。
6
+ # bundle 顶部 `window.__ModuleLoader__.load({ id: … })` 的 id 必须等于 package.json 的 name;
7
+ # 不符时客户端判定"该 row 没到货",会回退去取单资源 URL 把同一份字节**再执行一遍**,
8
+ # 第二次注册抛 `duplicate factory registration` ⇒ 前端整片黑屏(2026-09-26 实测两次)。
9
+ # ⇒ 改包名时 `lib/client.js` 必须同批改;`tests/unit.mjs` 已加断言守着。
10
+ # HMR live 热载后浏览器硬刷即可看到 client 模块。
11
+ - insert:
12
+ - id: dsh-ling
13
+ name: '@nightpainters/dsh-ling'
14
+ # config(可选,覆盖默认值):
15
+ # dataDir: 覆盖数据目录(默认 $DSH_HOME/cache/dsh-ling)
16
+ # injectEnabled: false # 完全关闭系统提示注入(逃生开关)