@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
@@ -0,0 +1,119 @@
1
+ # ACCESS-DESIGN — 历史会话接入蓝图(让用户把"他们的历史"请进来)
2
+
3
+ > 状态:2026-09-08 方向已拍板(见 §7 决策记录),本文是实施时的对照蓝本。
4
+ > 服务对象:**非开发者用户**——想用"TA 与 TA 的 AI 的共同对话历史"培养自己的器灵(每人不同:小灵、小肥鱼,或任何别的名字)。
5
+
6
+ ## 0. 四条铁律
7
+
8
+ 1. **零数据库知识**:绝不要求用户"把库改造成什么样"再接入——schema 是插件的事;
9
+ 2. **数据本地**:文件只在浏览器 → 本机插件之间流动,不上任何云;
10
+ 3. **渐进接入**:有多少给多少——轻量档先入,完整消息与摘要由后台管线慢慢补;
11
+ 4. **幂等安全**:重复导入只刷新、不重复;绝不覆盖用户态字段(summary / importance / 置顶)。
12
+
13
+ ## 1. 会话契约 v1(统一搬运格式)
14
+
15
+ **文件形态**:JSON 或 JSONL(逐行一个会话对象;大文件优先 JSONL,便于流式分批)。
16
+
17
+ ```
18
+ 顶层: {"format":"dsh-ling-import","version":1,"sessions":[ … ]} // JSON 数组亦可
19
+ ```
20
+
21
+ **会话对象**:
22
+
23
+ ```jsonc
24
+ {
25
+ "id": "唯一 id(建议 平台:本地id;无则自动 文件:序号)",
26
+ "startedAt": "2026-01-01T10:00:00Z", // 与 updatedAt 至少其一
27
+ "updatedAt": "2026-01-02T10:00:00Z",
28
+ "title": "可选但强烈建议(缺省=首条用户消息前 40 字)",
29
+ "category": "knowledge|daily|feeling", // 可选,缺省走启发式
30
+ // 二选一(深度可升级):
31
+ "messages": [{ "role": "user|assistant", "text": "…", "at": "ISO" }], // 完整档
32
+ // 或 轻量档:
33
+ "summary": "…", "keywords": ["…"]
34
+ }
35
+ ```
36
+
37
+ - **完整档** → 原始轮次入库(dsh_turns_raw 语义)+ 生成概述,与 DSH 会话同质量;
38
+ - **轻量档** → 只入概述;后续由深摘/摘要管线按热度补全(叙事:"器灵先认得这些日子,再慢慢读你们的对话");
39
+ - 角色过滤与现有捕捉规则一致:仅 user/assistant;系统提示与 reasoning 丢弃;
40
+ - 同 `id` 再导入 = 更新刷新;轻量 → 完整可原地升级(补 raw)。
41
+
42
+ ## 2. 通道(当前范围:先对齐 DeepSeek 体系)
43
+
44
+ | 通道 | 说明 | 状态 |
45
+ |---|---|---|
46
+ | **A. DSH 一键扫描** | 扫描本机 `~/.dsh/sessions` 存量(顶层会话、zstd 多帧解码、弱会话过滤、幂等)→ 收纳现有 `tools/backfill-dsh.mjs` 逻辑,用户零准备 | P0 |
47
+ | **B. 文件导入**(契约文件) | DeepSeek 网页端官方**无导出** → 发布材料(P1)附两种获取路径:① 已有 ds-search/数据整理产物(`deepseek_library.db` 或 conversations.json)→ 导入器直接接受 db 路径(现 scan-dsweb UI 化)或提供转换脚本导出为契约文件;② 从零开始:网页抓取不在本包范围,文档如实说明(P2 再决策是否自研) | P0(契约)/P1(网页端指引) |
48
+ | ~~C. 纯文本粘贴~~ | **暂缓**(2026-09-08):见下 | P2 再评估 |
49
+
50
+ **为什么文本粘贴暂缓(决策记录)**:① 批量历史靠手工复制粘贴成本畸高,与"接入应省力"相悖;② 它真正的价值只剩"补最近零散对话"这一小场景,与"想办法抓数据"的路径重叠且更弱;③ 未来若做官方/浏览器渠道抓取,该通道价值近零。故 P2 前不投入。
51
+
52
+ ## 3. 导入流水线与工程约束
53
+
54
+ - **分页提交**:`/api` 读 body 上限 4MB → 前端流式读文件(JSONL 逐行),每批 ≤200 会话 POST;
55
+ - **端点语义**(`/import/batch` 或扩展现有 /import):逐批校验 → 返回统计对象 → UI 确认后落库(每批事务);
56
+ 字段口径(与实现一致):`ok` 本批是否正常跑完 · `accepted` 通过校验、进入落库流程的条数 · `newRows` 新写入的行 · `refreshed` 同 id 已存在、只更新标题/时间/类别/关键词的行 · `upgraded` 原本只有概述、本次补上原文的行 · `folded` 命中网页端旧域、元数据与原文并入旧域的行 · `removedImport` 随折叠一并清掉的本域残留副本 · `degraded` + `degradedReasons` 校验通过但降级收下的条数,以及按原因聚合的计数 · `rejected` 未通过校验的条目(`{i, reason}`,不落库,交给 UI 报"异常");
57
+ - **幂等键**:`source="import:<平台>"` 命名空间 + 本地 id;轻量档不写空 summary 覆盖用户已有内容;
58
+ - **导入后衔接**:新概述 `overview_ok=1` 入队 → 现有 summarizer/deep 通道按热度自动补摘要与深摘;
59
+ - **进度体验**:批处理期间显示进度、可中断;完成后给一句"她开始读你的历史了"式的总结,而不是"已写入 N 行"。
60
+
61
+ ## 4. UI:记忆中心 →「接入历史」页签
62
+
63
+ - 区块一:通道 A 一键扫描(按钮 + 结果:新增/刷新/跳过);**当前**:单个扫描按钮 + 一行结果 —— 候选 `scanned` / 顶层 `topLevel` / 新增 `created` / 已存在跳过 `skippedExists` / 弱会话跳过 `skippedWeak` / 解码失败 `failed` / 库内 DSH 共 `totalDsh`(零候选时另给 `note`,不把"没扫到"与"没有历史"说成一回事);设计的"刷新"口径与返回字段一致,但实现里没有独立的刷新计数,只是已存在即跳过。
64
+ - 区块二:通道 B 文件导入(拖放/选文件 → 格式说明 → 预览表 新增/刷新/跳过/异常 → 确认导入);**当前**:只有「选择对话文件…」按钮(拖放未实现),格式说明 = 区块内常驻契约字段说明,不单独占一步;选完即解析,预览只报已解析的会话条数并让「确认导入」带上同一数字,没有逐条预览表 —— 设计里的"跳过/异常"落在导入结果的 `rejected`(`{i,reason}`,拒绝条数与原因预览)与 `degraded`/`degradedReasons` 上;确认后按批写入、批大小固定,完成汇总给「写入新记忆 `newRows` · 刷新已有 `refreshed` · 补全对话原文 `upgraded` · 并入网页端历史 `folded` · 清理重复副本 `removedImport`」+「校验通过 `accepted` · 拒绝 `rejected`」,零退化时才说"导入完成",有退化则显式说明"只有标题、没有对话正文"。
65
+ - 区块三:帮助与文案(轻量/完整档是什么、如何拿到契约文件——DeepSeek 网页端指引在 P1 补入此区);**当前**:尚无独立区块(列为待补)—— 轻量/完整档是什么、如何拿到契约文件这部分,目前由区块 B 内的常驻契约字段说明承载;DeepSeek 网页端指引尚未实现。
66
+ - 基调:接入 = "把你们的历史请进门",不是技术操作。**当前**:基调不做独立承载,只在区块 B 导入完成后的收尾一句上体现;区块三的帮助文案本身尚未实现(随区块三一并待补)。
67
+
68
+ ## 5. 命名空间与落库映射(实施对照)
69
+
70
+ | 契约字段 | 记忆库 |
71
+ |---|---|
72
+ | `id`(含命名空间) | conv_overview.conv_id / dsh_turns_raw.session_id |
73
+ | `source=import:<平台>` | conv_overview.source('dsweb'/'dsh' 之外的第三类) |
74
+ | startedAt / updatedAt / title / category | 同名列(类别缺省走启发式) |
75
+ | summary / keywords(轻量档) | 同名列(importance/heat/hit 不动) |
76
+ | messages(完整档) | dsh_turns_raw + 摘要管线 |
77
+
78
+ > 注意:引入第三来源后,L1/统计格/筛选器需确认对 `source` 的既有假设(现在 UI 按 dsweb/dsh 两类写死标签,需泛化为"已命名空间")。
79
+
80
+ ## 6. 排期
81
+
82
+ - **P0**:通道 A 收纳 backfill;通道 B 契约导入(JSON/JSONL、两档深度);页签 UI;分页/幂等/校验统计;
83
+ - **P1**:DeepSeek 网页端数据获取指引;`deepseek_library.db` 直接导入(scan-dsweb UI 化);L1/统计对第三来源泛化;
84
+ - **P2(再评估)**:文本启发式通道;导出契约文件(器灵可搬家/备份到他人环境);是否自研网页抓取;多平台适配。
85
+
86
+ ## 7. 决策记录(2026-09-08,作者拍板)
87
+
88
+ - ✅ 契约支持**轻量档**(仅标题/日期也可入,后续深摘补全);
89
+ - ✅ **只做文件接入**;纯文本粘贴暂缓(理由见 §2);
90
+ - ✅ 先对齐 **DeepSeek 体系**(DSH 存量 + 网页端文件/库);
91
+ - ✅ 向导入口 = **记忆中心内新页签**;
92
+ - ⏸ 对外叙事稿(起源→机制→效果)按下不表,另行撰写。
93
+
94
+ ## 8. 实施状态
95
+
96
+ - **P0 已实施(2026-09-08)**:记忆中心「接入历史」页签(通道 A 一键扫描 + 通道 B JSON/JSONL 契约导入,200/批);host 模块 `lib/host/backfill.js`(tools/backfill-dsh.mjs 已改薄壳复用)与 `lib/host/import-file.js`;接口 `POST /dsh/backfill`、`POST /import/file/batch`;
97
+ - **库迁移**:conv_overview.source 曾 CHECK 限 dsweb/dsh → schema v2 放开(自动整表重建,数据无损,真机副本演练通过);`upsertOverview` 不再强制改写来源;
98
+ - **来源泛化**:记忆浏览筛选/概览统计/L1 溯源标签新增"文件导入(import)";
99
+ - 单测:`tests/importfile.test.mjs`(两档/幂等/降级/坏行/auto-id/来源过滤)全绿;全套回归绿。
100
+ - **诞生仪式已实施(2026-09-09)**:接入历史页签新增一键深摘(import 源,后台串行 + 轮询)+ 人格初稿合成(`POST /persona/genesis`)。纯函数与测试:`lib/host/genesis.js`、`tests/genesis.test.mjs`。
101
+ - **第 2 波(2026-09-10,按作者在真机验收后的拍板)**
102
+ - genesis 原料 **scope 参数化**:"全部记忆"(全库加权抽样 ≤140,默认)vs"刚导入的这段";UI 下拉可选;提示明示「翻遍全部记忆,按生活/情感加权选出 N 条样本」;
103
+ - **生活/情感加权**:feeling 1.0 / daily 0.7 / knowledge 0.2 + 置顶 +1.5(`GENESIS_WEIGHTS`);prompt 声明"她首先是伴侣,其次才是同事";"评价用户/画像类任务才平权"作为语义规则保留给未来层;
104
+ - 原料三级取用:深摘(deep.sum)→ 非占位概述 → 原文片段(短会话,≤3 轮)/关键词线索——短会话不再静音;
105
+ - **名字主客过滤**(`filterNamePairs`):剔除 userTitle 成分与常见称谓词;prompt 明令名字属于她;
106
+ - **草稿制(乙方案)**:genesis 候选不再直接落盘;自述/名字单选加入草稿,语气建议与相处观察可一并携带;「带着草稿去人格中心人审」→ 对应字段旁浮现「她建议…[填入]」(纵向插入,修复过 flex 行溢出);语气/观察进入「她的话」区块,可一键**作为惯例记下**(`POST /persona/hint-adopt`,惯例成长通道,定型下无需手术);
107
+ - **深摘语义**:一次跑完所有未读会话(含快速通过的短会话),进度「已完成 x / 本轮共 y · z%」;按钮「让她读未读过的会话」;全部读完时直接亮出自述按钮(非失败态);
108
+ - 语音语气建议等错误 toast 补齐 `error` 字段兜底。
109
+ - **第 3 波(2026-09-11)**
110
+ - **导入记录(留账)**:三条入口(文件导入 / 本机 DSH 扫描 / 网页端库扫描)每次成功都落一条账,`lib/host/import-log.js` 存 kv `import.log.<开始时刻>`(最近 50 条自动修剪),`GET /import/history` 倒序返回,「接入历史」页签底部卡片 D 展示;**一次导入 = 一条账**:传输层仍按批(200/批)发送,各批带同一 `runId` 由 host 累加(批数/失败批数一并入账),`at` 固定为导入开始时刻;失败批经 `POST /import/log` 上报;
111
+ - **语气 P1**:`POST /persona/tone-advice`(只读,读两侧记忆归纳语气建议)+ `POST /persona/grow`(成长通道:语气枚举替换 + 风格只追加),归"自性类"、定型锁下免手术。
112
+ - **P1 待办**:DeepSeek 网页端数据获取指引;聊天记录库直接导入 UI 化;帮助文案。
113
+
114
+ ## 9. 诞生仪式(genesis)设计速览(发布文档引用用)
115
+
116
+ 1. **入口**:记忆中心 →「接入历史」页签底部「🌱 诞生仪式」卡;流程 = 让读(深摘未读)→ 第一次自我介绍(加权样本合成初稿)→ 人审草稿 → 人格中心落盘;
117
+ 2. **初稿四件**:自述候选 ×2~3、名字组 ×2~3、语气建议、相处观察(JSON 契约,解析带围栏剥离与长度清洗);
118
+ 3. **人审闭环**:草稿携带 → 字段旁「她建议…[填入]」/「她的话…作为惯例记下」;终审与保存一律在人格中心(新老用户同路径;已定型字段需手术门);
119
+ 4. **材料口径**:她的名字/自述基于"生活情感优先"的加权样本;历史中属于用户的称谓一律过滤,不得混入她的身份。