@yolk_vat-y/dsh-project-memory 0.5.3 → 0.5.5
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/CHANGELOG.md +128 -0
- package/README.md +75 -42
- package/README.zh-CN.md +75 -42
- package/client/client.js +111 -92
- package/client/client.js.map +1 -1
- package/package.json +5 -2
- package/scripts/bench-store.mjs +113 -0
- package/scripts/bench-synthetic.mjs +364 -0
- package/scripts/bench.mjs +396 -0
- package/src/auto-inject.js +255 -52
- package/src/client/MemoryView.tsx +4 -2
- package/src/client/TaskComponents.tsx +7 -6
- package/src/client/TaskPanel.module.css +7 -0
- package/src/client/TaskPanel.tsx +12 -8
- package/src/client/task-ui-store.ts +11 -1
- package/src/commands/task-actions.js +3 -2
- package/src/doc-index.js +71 -0
- package/src/doc-pipeline.js +22 -27
- package/src/index.js +33 -3
- package/src/insight-store.js +6 -4
- package/src/lazy.js +4 -2
- package/src/link.js +2 -1
- package/src/llm-route.js +95 -0
- package/src/llm.js +20 -61
- package/src/parsers/pdfjs-parser.js +3 -0
- package/src/readiness.js +224 -0
- package/src/recall.js +217 -0
- package/src/reflection-pipeline.js +10 -4
- package/src/setup/taskbridge.js +8 -2
- package/src/store.js +21 -2
- package/src/tools/index-doc.js +3 -3
- package/src/tools/index-repo.js +14 -4
- package/src/tools/lesson-tools.js +7 -2
- package/src/tools/query-memory.js +66 -25
- package/src/tools/task-tools.js +3 -2
- package/src/tools/watch-repo.js +10 -1
- package/src/util/fs.js +41 -0
- package/src/util/search.js +2 -0
- package/src/util/text.js +13 -0
- package/src/watch.js +33 -6
package/README.zh-CN.md
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|

|
|
18
18
|
## 特性
|
|
19
19
|
|
|
20
|
-
- **TaskBridge:跨会话开发任务** — 监听会话内宿主 `todo_write` 维护的任务清单与 `tool/call` 读文件:进度快照(steps)与触碰文件自动同步进跨会话的任务实体。未绑定会话写 todo 时自动建档。关联文件按**最近活跃排序(写过/编辑的排最前,任何读取不越过写过文件)**,续接时一眼看到该看哪些文件。新会话通过 `list_tasks` → `select_task`(绑定/改名/解归档)续接;`query_memory` 新增 `type:'task'`,`type:'all'` 结果尾部附任务计数提示。用户侧 `/tasks`
|
|
21
|
-
- **Task Panel(v0.4.2+):dsh web 浮动任务面板** — 按 dsh web 0.1.
|
|
20
|
+
- **TaskBridge:跨会话开发任务** — 监听会话内宿主 `todo_write` 维护的任务清单与 `tool/call` 读文件:进度快照(steps)与触碰文件自动同步进跨会话的任务实体。未绑定会话写 todo 时自动建档。关联文件按**最近活跃排序(写过/编辑的排最前,任何读取不越过写过文件)**,续接时一眼看到该看哪些文件。新会话通过 `list_tasks` → `select_task`(绑定/改名/解归档)续接;`query_memory` 新增 `type:'task'`,`type:'all'` 结果尾部附任务计数提示。用户侧 `/tasks` 命令展示任务栈、步骤进度、涉及文件与当前会话绑定。由模型经 `select_task(title=…)` 命名的任务沿用该标题;由首次 `todo_write` **自动建档**的任务取**清单首条**(≤48 字符)为标题,回退到首条真人消息(取最后一个「:」后的任务段),再回退 `Untitled Task`。以**子代理**身份启动的会话被排除在自动建档之外(`origin: 'subagent'` / `delegationDepth > 0`);把委派出去的工作并回任务这件事**有意没做**——见「设计取舍」第 11 条。容量随项目体积自适应(fileCount/20,clamp 5–100)。存储:`.dsh-project-memory/tasks.json` + `binding.json`。自动同步需含会话事件与 `todo_write` 的 dsh(0.1.2-alpha.x 实测,并已针对 0.1.5-rc.1 宿主面复核);旧宿主下降级为纯记录。
|
|
21
|
+
- **Task Panel(v0.4.2+):dsh web 浮动任务面板** — 按 dsh web 0.1.5-rc.1 真实 client 插件契约落地(cordis inject + apply,注册进宿主 `shell.overlay` 槽)。卡片可拖拽、展开查看步骤/文件(点击复制路径);折叠为可拖拽顶部迷你条;可彻底隐藏(输入 `/task` / `/tasks` 唤起)。渲染错误有边界兜底,面板崩溃不再拖垮宿主。
|
|
22
22
|
- **任务面板行为** —
|
|
23
23
|
- **默认隐藏**:dsh web 启动时面板不显示
|
|
24
24
|
- **显式唤起**:输入 `/tasks` 或 `/task`(列表形式)打开;模型调用 `show_task_panel` 工具打开
|
|
@@ -26,40 +26,39 @@
|
|
|
26
26
|
- **刷新页面**:面板保持隐藏(UI 状态 `closed` 不持久化)
|
|
27
27
|
- **手动关闭**:点击 × 彻底隐藏(无迷你条);重新打开需显式唤起
|
|
28
28
|
- **折叠迷你条**:点击 ↓ 仅保留顶部可拖拽迷你条;点击迷你条展开
|
|
29
|
+
- **隐藏提示信息**:点击 ? 关闭面板内所有悬停提示气泡(含拖拽把手、风格/视图/收起/关闭、双击改名、步骤状态、复制路径、迷你条与记忆视图),偏好写入 localStorage,刷新后保持;关闭态按钮变暗,再点恢复
|
|
29
30
|
- **任务清单双向同步(宿主 ↔ 插件任务,v0.4.2+)** — `select_task` 或 `/task switch` 绑定任务时,将任务 steps 推给宿主 `todo/write`,dsh 渲染的任务清单跟随我们维护的任务实体。配置 `tasklist.syncHostOnAdopt`(默认开)可关。空 `todo/write` 语义定为「清空」:未绑定会话清空清单不再误建垃圾任务;已绑定则清空该任务 steps(任务保留)。面板编辑(改步骤文本/状态)= 写回绑定任务并推宿主清单,与模型 `todo_write` 共用一套逻辑,无第二套同步。`/task` 新增 `switch` / `archive` / `unbind` / `rename` / `todos`(均由面板按钮/双击调用,不经模型);`unbind` 同时清掉输入框上方的宿主任务清单。
|
|
30
31
|
- **面板编辑与风格(v0.4.2+)** — 绑定卡片:双击标题/步骤行内编辑(输入框随内容自动增高),点步骤状态图标循环 待办→进行中→已完成;非绑定卡片只读。**四档外观风格**(点标题左侧文件夹图标切换,本地记忆):原生 / 玻璃拟态 / 粗野主义 / 终端等宽——只改材质、几何、字型与密度,颜色始终取自 dsw 别名令牌,跟随宿主明暗与主题插件。
|
|
31
|
-
- **文档记忆** — PDF、Markdown
|
|
32
|
-
-
|
|
33
|
-
- **L1 增强正则** — 零依赖正则扫描器现可提取泛型、参数/返回类型、重载、接口、类型别名,产出单行身份签名 `fn(a: A, b: B): R — file.ts:42`。
|
|
32
|
+
- **文档记忆** — PDF、Markdown、纯文本按块切分并生成摘要,**索引期不调用任何模型**:每条记忆保留 ≤300 字符的 `summary` 供注入、一个有界(≤160)且确定性、去停用词的 `terms` 集合覆盖**整个 chunk**(仅用于检索,因此召回不受开头几行限制),并携带 `路径:行号` 引用回源文件。历史字段 `blindSpots` 在索引期不调用模型后恒为空,仅为兼容早期版本写下的存储而保留。
|
|
33
|
+
- **代码符号记忆(L1 正则)** — 零依赖扫描器提取函数、类与方法及其完整签名(泛型、参数/返回类型、重载),并覆盖接口与类型别名,支持 8 种语言,产出单行身份签名 `fn(a: A, b: B): R — file.ts:42`;含字符串/注释掩码、多行签名续行、Python 缩进感知与类方法上下文,不使用 LLM token。
|
|
34
34
|
- **可选 TypeScript 语义增强 (L2/L3)** — 当用户项目安装了 `typescript`(`npm i -D typescript@5` 或 `npm i -D typescript@6`),插件自动激活第二层(L2),利用 TS Compiler API 推导返回类型、实例化泛型、提取接口与类型别名、丰富箭头函数签名 —— 全部在优先级队列中异步后台处理(P0:`fs/observed` 读文件瞬间、P1:`watch` 变更后、P2:`index_repo` 批量索引)。结果按文件内容哈希缓存到磁盘(L3),冷启动毫秒级复用。零配置:装 TS 再重启 dsh 即可。完全可选;若无 TS 或设置 `enableTypeScript: false`,回退至 L1 正则提取。
|
|
35
35
|
- **自动刷新** — `watch_repo` 后台轮询,按内容哈希识别新增或变更文件,仅重记这些文件。
|
|
36
36
|
- **读到即记忆** — 文件在模型**实际读取的瞬间**被记忆(监听 `fs/observed`),记忆是正常工作的副产品,而非额外的一次全量扫描。从未读过的文件不会被记忆。项目根通过标记(`.git`、`package.json` 等)、README 加源码目录、或兜底到文件所在目录逐级识别。
|
|
37
37
|
- **文档 ↔ 代码交叉链接** — 文档提及某符号时记录为 `reference`;查询符号时同时带出描述该符号的文档。
|
|
38
38
|
- **BM25 记忆召回** — 对文档、符号与经验笔记进行排序召回,可选 LLM 查询扩展以应对表述不一致。**CJK 增强**:精确短语乘法加分(3+ 字短语在标题/关键词命中 ×1.5)、同义词表(如 数据库连接池 ↔ 连接池 ↔ DB pool)、CJK 感知的文档↔符号链接边界。
|
|
39
|
-
- **blindSpots 感知召回** — 文档摘要携带 `blindSpots` 字段(明确说明摘要未覆盖的内容)。查询命中盲区时,`query_memory` 追加提示引导模型去读原文,防止半截摘要误导。
|
|
40
39
|
- **经验笔记** — 记录问题 → 方案;相似问题覆盖而非重复;笔记仅在检索命中时返回。笔记数量有界:容量随项目规模伸缩(钳制在 100–2000),超限时淘汰最旧的笔记。**覆盖阈值收紧为双向 0.7 重叠**(原 0.6);**经验 `problem` 字段现参与 CJK 短语加分**,提升长尾问句召回。
|
|
41
|
-
- **v0.5 分层 insight 记忆(教训 / 决策 / 流程)** — 一个 `insight` 实体贯穿三级:`task`(任务私有草稿,存 `tasks.json`)、`project`(`.dsh-project-memory/insights.json`)、`global`(`~/.config/dsh-project-memory/global.json`)。`save_lesson` 三级可写;去重采用双向 token overlap ≥ 0.7(合并)外加 0.65–0.7 近重复强化带;**提升 = scope 字段变更而非复制**——同一 insight 被 2 个任务命中升 project、3+ 升 global。归档为软删(`archived`),容量/衰减只清归档区;写盘前过滤密钥/token 形态内容。LLM **反思默认关闭**,且只产任务级草稿(`source: reflect`,触发于任务切走/归档时)。面板新增 Task / Project / Global 记忆视图:审核、提升/降级、归档/恢复、删除、编辑与新建表单(procedure 可带"作为 Skill"触发关键词)。旧 `experience.json` 笔记**非破坏**导入 `insights.json`
|
|
42
|
-
- **流式 TF + IDF 缓存** — 查询路径按存储版本缓存 IDF(词逆频率);命中时单次流式遍历 20k
|
|
43
|
-
- **无锁同步事务** — 不采用锁:所有写入(index / watch / remember / forget / watch_repo)统一走同步事务 `store.commit(fn)`,fn 成功后才一次落盘;JS 单线程事件循环保证事务间不交错,`remember`/`forget` 不会被 watch
|
|
40
|
+
- **v0.5 分层 insight 记忆(教训 / 决策 / 流程)** — 一个 `insight` 实体贯穿三级:`task`(任务私有草稿,存 `tasks.json`)、`project`(`.dsh-project-memory/insights.json`)、`global`(`~/.config/dsh-project-memory/global.json`)。`save_lesson` 三级可写;去重采用双向 token overlap ≥ 0.7(合并)外加 0.65–0.7 近重复强化带;**提升 = scope 字段变更而非复制**——同一 insight 被 2 个任务命中升 project、3+ 升 global。归档为软删(`archived`),容量/衰减只清归档区;写盘前过滤密钥/token 形态内容。LLM **反思默认关闭**,且只产任务级草稿(`source: reflect`,触发于任务切走/归档时)。面板新增 Task / Project / Global 记忆视图:审核、提升/降级、归档/恢复、删除、编辑与新建表单(procedure 可带"作为 Skill"触发关键词)。旧 `experience.json` 笔记**非破坏**导入 `insights.json` 一次。所有 kind 都可带 authored `trigger`(`keywords` / `symbols` / `actions` / `paths`):命中即**在动手前**确定性注入——v0.5 仅 procedure,就绪层起覆盖全部 kind。
|
|
41
|
+
- **流式 TF + IDF 缓存** — 查询路径按存储版本缓存 IDF(词逆频率);命中时单次流式遍历 20k 条目(5k 文件)为 p50 2.6 ms / p95 5.4 ms,4k 条目(1k 文件)为 p50 0.6 ms / p95 1.6 ms,零中间对象。只有**真正脏了**的写入才递增版本号并清空缓存——无变更时 `save()` 在碰盘前直接返回,因此 15 秒一轮的 watch 轮询不会把查询刚建好的 IDF 缓存清掉。
|
|
42
|
+
- **无锁同步事务** — 不采用锁:所有写入(index / watch / remember / forget / watch_repo)统一走同步事务 `store.commit(fn)`,fn 成功后才一次落盘;JS 单线程事件循环保证事务间不交错,`remember`/`forget` 不会被 watch 重索引阻塞排队。全部写入在**进程内**串行;CAS 幂等更新保证同一文件的重复写入不会写坏。但这里**没有跨进程文件锁**——请勿让多个 dsh 实例同时写同一项目存储(见「设计」的一致性一节)。
|
|
44
43
|
- **依赖极简** — 纯 JavaScript;唯一运行时依赖是 `pdfjs-dist`(PDF 文本提取),无需原生构建。
|
|
45
|
-
- **开销可忽略** —
|
|
44
|
+
- **开销可忽略** — 纯进程内操作;5k 文件的 store 冷加载 40 ms,20k 条目的缓存查询 p50 2.6 ms / p95 5.4 ms(4k 条目:p50 0.6 ms / p95 1.6 ms);瓶颈在 PDF 解析与磁盘 I/O,插件本身的打分开销不阻塞。
|
|
46
45
|
|
|
47
46
|
## 性能
|
|
48
47
|
|
|
49
|
-
###
|
|
48
|
+
### 合成基准测试(Node 24.19,WSL2 / 20 vCPU,Linux 文件系统)
|
|
50
49
|
|
|
51
50
|
| 场景 | 规模 | 实测 |
|
|
52
51
|
|------|------|------|
|
|
53
|
-
| 批量冷记忆构建 | 5,000 文件 / 20k 条目 |
|
|
54
|
-
| 冷加载 | 5,000 文件 |
|
|
55
|
-
| 热路径懒记忆 | 单文件重记忆+落盘 |
|
|
56
|
-
| query_memory (缓存命中) | 5k 文件 / 20k 条目 |
|
|
57
|
-
| query_memory (缓存命中) | 1k 文件 / 4k 条目 |
|
|
58
|
-
| 批量冷记忆构建 | 10,000 文件 / 40k 条目 |
|
|
59
|
-
| 冷加载 | 10,000 文件 |
|
|
60
|
-
| 热路径懒记忆 | 单文件重记忆+落盘 |
|
|
52
|
+
| 批量冷记忆构建 | 5,000 文件 / 20k 条目 | 269 ms 均值(p50 267)|
|
|
53
|
+
| 冷加载 | 5,000 文件 | 40 ms |
|
|
54
|
+
| 热路径懒记忆 | 单文件重记忆+落盘 | p50 2.4 ms / 最大 5.5 ms (5k) |
|
|
55
|
+
| query_memory (缓存命中) | 5k 文件 / 20k 条目 | p50 2.6 ms / p95 5.4 ms |
|
|
56
|
+
| query_memory (缓存命中) | 1k 文件 / 4k 条目 | p50 0.6 ms / p95 1.6 ms |
|
|
57
|
+
| 批量冷记忆构建 | 10,000 文件 / 40k 条目 | 551 ms 均值(p50 528)|
|
|
58
|
+
| 冷加载 | 10,000 文件 | 90 ms |
|
|
59
|
+
| 热路径懒记忆 | 单文件重记忆+落盘 | p50 5.4 ms / 最大 9.2 ms (10k) |
|
|
61
60
|
|
|
62
|
-
> 合成基准:生成代码(~4–5 符号/文件),Node 24
|
|
61
|
+
> 合成基准:生成代码(~4–5 符号/文件),Node 24.19 / WSL2 / 20 vCPU / Linux 文件系统,实测于 2026-09-14。复现命令 `npm run bench:synthetic -- 5000`(脚本 `scripts/bench-synthetic.mjs`)。测量纯索引开销,不含 LLM 调用。query_memory 使用 IDF 缓存 + 预计算 searchText;写入后的首次查询会重建 IDF(**40k 条目 106 ms**,20k 条目 57 ms,4k 条目 12 ms),后续查询命中缓存。
|
|
63
62
|
|
|
64
63
|
### 真实项目存储体积
|
|
65
64
|
|
|
@@ -70,13 +69,34 @@
|
|
|
70
69
|
|
|
71
70
|
> 真实项目(Java + Vue),测试于 Linux 文件系统(Node 24)。真实项目单条目体积小于合成基准,因符号密度更低、声明行更短。
|
|
72
71
|
|
|
72
|
+
### 自己复现这些数字
|
|
73
|
+
|
|
74
|
+
与其让你相信上面的表格,不如把测量本身一起发布——它随仓库发布,**也随 npm 包一起发布**(`scripts/` 已包含在 tarball 中)。脚本**不需要 dsh 实例、不需要网络、不调用任何模型**,也**不碰被测项目自己的 store**——结果写进临时目录,跑完删除:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run bench -- /你的/项目路径
|
|
78
|
+
# 或带参数:
|
|
79
|
+
node scripts/bench.mjs /你的/项目路径 [--json] [--samples 100] [--no-pdf] [--keep]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
输出包含:冷索引(拆成 read+hash / extract / commit 三段)、冷加载、IDF 重建、冷查询与热查询延迟(走线上同一套 scorer,100 条采样报 p50/p95/max)、单文件热重索引、存储体积与每条字节数。示例——我们内部的 Vue 项目(289 文件 / 2,141 条目,Node 24,20 CPU,Linux):
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
冷索引 253 ms (read+hash 9 ms · extract 229 ms · commit 13 ms)← 第二次、页缓存已热
|
|
86
|
+
存储 1.10 MB · 538 bytes/条目 · 冷加载 4.6 ms
|
|
87
|
+
热查询 p50 0.80 ms · p95 1.35 ms (2,141 条目)
|
|
88
|
+
单文件重索引 p50 0.33 ms
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
两个我们宁可自己说清楚的坑:`read+hash` 受操作系统页缓存影响——同一个语料第一遍花了 787 ms、第二遍 253 ms,报数时请说明是第几遍;**真实项目比上面的合成基准慢**——在一个大型 TypeScript 仓库的 3,000 文件切片上(15,594 条目)热查询 p50 为 7.5 ms,因为真实声明文本比生成出来的桩代码长得多。带 `--queries 你的查询集.json` 可以在你自己的项目上跑同一套标注集方法(hit@5 / hit@10 / MRR)。
|
|
92
|
+
|
|
73
93
|
## 工作原理
|
|
74
94
|
|
|
75
95
|
设计遵循四个原则:
|
|
76
96
|
|
|
77
97
|
- **易失性** — 上下文是临时的,会话压缩即丢失。
|
|
78
98
|
- **持久性** — **记忆**存于磁盘,跨压缩与会话保留。
|
|
79
|
-
- **紧凑性** —
|
|
99
|
+
- **紧凑性** — 代码层每个符号只存一行声明,所以代码为主的项目仍约 **0.5% 源码体积**(示例项目中 8.8 MB 源码 → 49 KB 索引),**召回**替代了通读整个文件。文档层按设计更重:每个 chunk 保留 ≤300 字符的注入 `summary`、覆盖整 chunk 的 `terms`,以及预计算的 `searchText`。纯文档语料实测(179 chunk / 225 KB Markdown):`terms` ≈ 源码 **27.5%**,整库落盘 ≈ 源码 **166%**——文档占比高的项目请按「约等于文档本身大小」估,而不是 0.5%。
|
|
80
100
|
- **可核验性** — **召回**在适用时携带 `路径:行号` 引用,agent 可对照源文件核实。
|
|
81
101
|
|
|
82
102
|
构建**记忆**无需预先全量扫描:文件在模型读取时被记忆,**记忆**恰好覆盖实际处理过的内容。未变更的文件重读是空操作(内容哈希),因此**记忆**的持续维护开销很低。
|
|
@@ -113,11 +133,11 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
|
|
|
113
133
|
|
|
114
134
|
| 工具 | 用途 |
|
|
115
135
|
|---|---|
|
|
116
|
-
| `index_doc file_path` | 索引单个文档(PDF/MD/txt):分块 →
|
|
117
|
-
| `index_repo root` |
|
|
118
|
-
| `watch_repo root` | 启用自动刷新:后台轮询检测新增/变更文件(mtime +
|
|
136
|
+
| `index_doc file_path` | 索引单个文档(PDF/MD/txt):分块 → 确定性 `summary` + 整 chunk `terms` → 带 `路径:行号` 入库。未变更文件自动跳过。 |
|
|
137
|
+
| `index_repo root` | 索引整个项目:文档生成确定性摘要 + 整 chunk 词项,代码文件生成零 token 符号表。增量更新、清理已删除文件、文档与符号交叉链接。根目录不存在(含在 Linux/macOS 上被解析成相对路径的 Windows 风格路径)时,会在写入任何内容前直接拒绝。 |
|
|
138
|
+
| `watch_repo root` | 启用自动刷新:后台轮询检测新增/变更文件(mtime + 内容哈希),仅重抽这些文件。监听的项目在插件重启后自动恢复;不存在的根目录、文件系统根与共享临时目录都会被拒绝,已消失的根目录会被丢弃而不是被重新创建。 |
|
|
119
139
|
| `memory_stats root` | 查看记忆库内容:总量(文件 / 条目 / 经验笔记)、最近索引时间,以及按时间排序的逐文件清单。 |
|
|
120
|
-
| `query_memory query` |
|
|
140
|
+
| `query_memory query` | 对文档、符号、经验与 insight(教训/决策/流程)执行 BM25 检索,可选 LLM 查询扩展。`type` 选择层(`all` / `doc` / `symbol` / `experience` / `insight` / `task`)。返回带相对分数(0-100)、引用或 insight id、以及文档→符号链接的排序结果。 |
|
|
121
141
|
| `list_tasks` | 列出本项目任务记录(含归档,带标记)。新会话/续接前先调用。 |
|
|
122
142
|
| `select_task` | 将会话绑定到某任务(此后 todo 清单与读文件同步进该任务)。按 `taskId` 精确绑定,或按 `title` 完全匹配(多个同名返回候选;无则新建)。带 title 可改名;自动解归档。 |
|
|
123
143
|
| `archive_task` | 归档任务(隐藏默认视图、不占容量、停止同步)。`select_task` 可恢复。 |
|
|
@@ -127,7 +147,7 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
|
|
|
127
147
|
| `/insight`(用户输入,不经模型) | v0.5 记忆视图动作(面板按钮触发):`list [task|project|global]`、`confirm` / `promote` / `demote` / `archive` / `restore` / `delete` `<scope> <id>`、`save <scope> <json>`、`edit <scope> <id> <json>`。 |
|
|
128
148
|
| `remember problem solution` | 保存经验笔记。相似问题覆盖而非重复。 |
|
|
129
149
|
| `forget id_or_query` | 删除过期经验笔记。 |
|
|
130
|
-
| `save_lesson`(模型工具) | 在 task/project/global 任一作用域保存教训/决策/流程(单一 insight 实体)。近重复按双向 overlap ≥ 0.7 合并、0.65–0.7 强化;同一 insight 被 2+ 任务命中自动 task→project、3+ → global。参数:`title`、`kind`、`scope`、`pattern`/`fix` 或 `choice`/`reason` 或 `steps`/`
|
|
150
|
+
| `save_lesson`(模型工具) | 在 task/project/global 任一作用域保存教训/决策/流程(单一 insight 实体)。近重复按双向 overlap ≥ 0.7 合并、0.65–0.7 强化;同一 insight 被 2+ 任务命中自动 task→project、3+ → global。参数:`title`、`kind`、`scope`、`pattern`/`fix` 或 `choice`/`reason` 或 `steps`、`trigger`(`keywords`/`symbols`/`actions`/`paths`/`scope`,所有 kind 通用,命中即在动手前注入)、`task_id`、`files`、`symbols`、`confidence`、`root`。 |
|
|
131
151
|
|
|
132
152
|
## 设计
|
|
133
153
|
|
|
@@ -147,7 +167,7 @@ v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次
|
|
|
147
167
|
|
|
148
168
|
- **增量** — 按文件内容哈希,仅重新抽取变更文件。
|
|
149
169
|
- **交叉链接** — 索引后将文档摘要与符号名匹配,命中符号以 `references` 挂载到文档条目,由 `query_memory` 带出。
|
|
150
|
-
- **查询扩展** — `llmQueryExpansion` 开启时,`query_memory` 让 `ctx.llm` 将查询改写为多个变体(同义词、中英、符号名猜测),再跨变体合并 BM25 分数;关闭时查询完全不碰 LLM
|
|
170
|
+
- **查询扩展** — `llmQueryExpansion` 开启时,`query_memory` 让 `ctx.llm` 将查询改写为多个变体(同义词、中英、符号名猜测),再跨变体合并 BM25 分数;关闭时查询完全不碰 LLM。索引本身不调用模型:keywords 由规则推导(标题加权词项),doc↔symbol 链接也会从中文命中带出英文符号名。
|
|
151
171
|
- **一致性** — 事实层跟随代码库(哈希重抽 / 删除即移除);经验层仅检索,配合覆盖与 `forget` 机制。每个记忆目录的写入走同步事务 `store.commit(fn)`:fn 内完成校验与变更、成功后才原子落盘,单进程内天然串行;请避免多个 dsh 实例同时写同一项目存储。
|
|
152
172
|
|
|
153
173
|
## 架构(任务面板)
|
|
@@ -172,11 +192,11 @@ TaskPanel (Container)
|
|
|
172
192
|
|
|
173
193
|
### 2. Watch:事务外计算,事务内提交
|
|
174
194
|
|
|
175
|
-
**我们做:** 重活(mtime
|
|
195
|
+
**我们做:** 重活(mtime/哈希/扫描/解析/PDF 抽取)在事务外跑,单次 `commit` 原子应用全部变更。失败回滚 snapshot,下轮自动重试。
|
|
176
196
|
|
|
177
|
-
**不做:**
|
|
197
|
+
**不做:** 持锁做解析,或用 `fs.watch` 事件。
|
|
178
198
|
|
|
179
|
-
**为什么:**
|
|
199
|
+
**为什么:** PDF 抽取与大文件解析耗时明显,持锁会阻塞 `remember`/`forget`/`query_memory`。轮询 + mtime+内容哈希跨平台一致(网络盘、Docker 卷、WSL 皆可),避免 `fs.watch` 的「重复触发/漏事件」噩梦。
|
|
180
200
|
|
|
181
201
|
### 3. 损坏文件隔离,不自动修复
|
|
182
202
|
|
|
@@ -192,23 +212,25 @@ TaskPanel (Container)
|
|
|
192
212
|
|
|
193
213
|
**不做:** 向量嵌入、稠密检索、重排序、混合搜索。
|
|
194
214
|
|
|
195
|
-
**为什么:** 向量需要嵌入模型(本地重、远程慢+贵+隐私)、向量索引(HNSW/IVF 占内存+建索引慢)、重排序(再调一次 LLM
|
|
215
|
+
**为什么:** 向量需要嵌入模型(本地重、远程慢+贵+隐私)、向量索引(HNSW/IVF 占内存+建索引慢)、重排序(再调一次 LLM)。对本插件所针对的查询,词法 BM25 已经够用且可核实:基准(真实 Vue 项目 29 条查询)文件级 hit@5 为 **96.6%**,其中 28 条是精确符号名查询、词法检索基本必中;整 chunk `terms` 把文档词项覆盖从 **27.3% 提到 100%**,而原本可答的查询排序不变(MRR **0.958** vs **0.955**)。这些数字来自内部一个 Vue 项目 + 手工标注的 29 条查询集,出了那个语料无法复现——但**方法**已随代码发布:`scripts/bench.mjs --queries 你的查询集.json`,可以在你自己的项目上跑完全相同的测量。边际收益不抵 10x 复杂度/成本。
|
|
196
216
|
|
|
197
|
-
### 5.
|
|
217
|
+
### 5. 索引确定且不调用模型
|
|
198
218
|
|
|
199
|
-
**我们做:**
|
|
219
|
+
**我们做:** keywords 由规则推导(标题加权词项),并构建覆盖整 chunk 的 `terms`——两者都确定、可复现。doc↔symbol 链接从中文命中带出英文符号名,CJK 分词保证跨语种命中。`llmQueryExpansion: false` 时查询完全不碰 LLM。
|
|
200
220
|
|
|
201
|
-
**不做:**
|
|
221
|
+
**不做:** 索引时调用模型去翻译或改写文档,也不在查询时翻译。
|
|
202
222
|
|
|
203
|
-
**为什么:**
|
|
223
|
+
**为什么:** 索引期调用模型会让索引变慢、不确定、不可复现——同一份文档两次索引可能得到不同结果。查询时翻译增延迟,且有一个硬失败模式(译错 = 零召回)。规则 + 符号链接覆盖常见情况,离线可用,并让索引期保持零模型调用。
|
|
204
224
|
|
|
205
|
-
### 6.
|
|
225
|
+
### 6. 面向模型的记忆:agent 自己写,不把人放进回路
|
|
206
226
|
|
|
207
|
-
**我们做:**
|
|
227
|
+
**我们做:** 把 agent 当作一等写入者。`remember` / `save_lesson` **随时可写任意作用域**(`task` / `project` / `global`),不需要人参与;提升是确定性的,就发生在普通写入路径里:跨任务的 token 重叠去重会累积 `sourceTaskIds`,随后 `promoteAllTasksToProject` / `promoteProjectToGlobal` 在佐证数达标时把条目上移(升 project 需 ≥2 个任务命中,升 global 需 ≥ `globalPromoteTasks`,默认 3)。整条链路不等任务面板:用户从不打开 UI,记忆照样会积累、去重、逐级提升。
|
|
208
228
|
|
|
209
|
-
|
|
229
|
+
**我们做(标注):** 让「推断出来的」和「记录下来的」可区分。v0.5 `reflection`(可选、**默认关闭**)是唯一做推断而非记录的写入者:它写的是 task 级草稿,带 `draft: true` / `source: 'reflect'`;只要还是草稿,`recall` 与静默注入就会跳过它。
|
|
210
230
|
|
|
211
|
-
|
|
231
|
+
**不做:** 不要求「人工批准」记忆才能生效,也不把 UI 变成写入路径上的一步。`draft` 是**来源标记 + 佐证门槛**,不是审批队列。
|
|
232
|
+
|
|
233
|
+
**为什么:** 记忆的消费方是 agent,而 agent 通常是无头的——只在有人点卡片时才升级的记忆,等于永远不会升级。保留标注就保住了这份谨慎里有用的那一半(推断 ≠ 记录,且未经佐证的单任务推断不进提示词),同时又不用给正常路径加税。草稿靠佐证毕业:第二个任务通过模型自己的写入命中了它,或者模型把同一知识直接写到 project 级(此时会挂到既有条目上,而不是复制一份)。
|
|
212
234
|
|
|
213
235
|
### 7. 直接返回完整条目
|
|
214
236
|
|
|
@@ -216,7 +238,7 @@ TaskPanel (Container)
|
|
|
216
238
|
|
|
217
239
|
**不做:** 先返回极简索引(如 700 字符),再二次调工具取详情。
|
|
218
240
|
|
|
219
|
-
**为什么:** 完整返回保持 **可核验性**——Agent 能看到每条声明的出处行号。也避免了每次有效命中多一轮工具调用+上下文切换。条目本已紧凑(~300
|
|
241
|
+
**为什么:** 完整返回保持 **可核验性**——Agent 能看到每条声明的出处行号。也避免了每次有效命中多一轮工具调用+上下文切换。条目本已紧凑(~300 字摘要+引用,外加一个从不进上下文的检索用 `terms`),完整返回的 token 成本低于二次调用。
|
|
220
242
|
|
|
221
243
|
### 8. 符号提取聚焦开发者实际搜索的内容
|
|
222
244
|
|
|
@@ -242,6 +264,14 @@ TaskPanel (Container)
|
|
|
242
264
|
|
|
243
265
|
**为什么:** 强制 TS 会让非 TS 项目装不上。阻塞增强会卡死大项目 `index_repo`。全程序检查慢 10x、内存重。设计:读到即增强、缓存复用、热路径永不阻塞。
|
|
244
266
|
|
|
267
|
+
### 11. 子代理会话暂不纳入(以后可能做)
|
|
268
|
+
|
|
269
|
+
**我们做:** 把以子代理身份启动的会话(`origin: 'subagent'` / `delegationDepth > 0`)排除在自动建档与绑定之外:它们的 `todo_write` 不建任务,也不继承任何任务绑定。
|
|
270
|
+
|
|
271
|
+
**不做:** 把委派出去的运行的 steps 与文件并回派发它的那条任务。这块**尚未设计**:目前没有委派工作的父子关联模型,而粗暴实现只会让每个子代理各铸一条项目任务。
|
|
272
|
+
|
|
273
|
+
**为什么:** 子代理只要写一次 todo 就会各自建档,一次 fan-out 就会往任务列表里灌进一批没人会续接的临时条目。排除掉它们,任务列表才等于「用户真正拥有的工作」。代价是委派进度在任务记录里不可见;正确的合并方式(子步骤折进父任务,或单列一个委派视图)属于后续工作。
|
|
274
|
+
|
|
245
275
|
## 配置
|
|
246
276
|
|
|
247
277
|
| 键 | 默认值 | 含义 |
|
|
@@ -264,7 +294,7 @@ TaskPanel (Container)
|
|
|
264
294
|
| `enableTypeScript` | true | 设为 `false` 彻底禁用 L2 TS 增强(仅保留 L1 正则) |
|
|
265
295
|
| `insight.*` | dedupOverlap `0.7` · reinforceBand `0.65` · maxProject `100` · maxGlobalProcedures `200` · promoteConfidence `0.7` · globalPromoteTasks `3` · decayDays `90` · `globalFile`(自动) | v0.5 insight 去重/强化/提升/容量/归档设置 |
|
|
266
296
|
| `reflection.enabled` | false | v0.5 LLM 反思,**只写任务级草稿**(触发于任务切走/归档)。`cooldownMs` `1800000`、`maxLessonsPerReflect` `3`、`maxDecisionsPerReflect` `2` |
|
|
267
|
-
| `autoContext.enabled` | true | v0.5 静默注入包装(entry 常驻块 + relevance)。宿主无法解析会话 cwd 时完全透传(零副作用);`maxTokens` `400`、`editedMax` `3`(resident 任务卡显示最近"编辑中"文件数)、`skipEchoSelfTodo` `true`(模型自己写/维护任务清单后、无新人类消息时不回声任务卡,省 token;相关 insights
|
|
297
|
+
| `autoContext.enabled` | true | v0.5 静默注入包装(entry 常驻块 + relevance)。宿主无法解析会话 cwd 时完全透传(零副作用);`maxTokens` `400`、`editedMax` `3`(resident 任务卡显示最近"编辑中"文件数)、`signalMinRatio` `0.5`(提示至少要达到该层最高分的一半)、`skipEchoSelfTodo` `true`(模型自己写/维护任务清单后、无新人类消息时不回声任务卡,省 token;相关 insights 仍注入)、`budgetLog` `off`(预算丢弃审计写到 stderr:`off` 静默 / `once` 每会话最多一行 / `all` 丢弃组合每变化一次一行。注入按优先级排程,预算不够时丢掉低优先级条目属于**正常降级而非故障**,所以默认不占用用户终端)、`reinjectItemsAfter` `0`(同一条 insight 重复注入的冷却步数;`0` = 正文没变就不在本会话内再注入——注入消息留在会话历史里,重发只是重复占位) |
|
|
268
298
|
|
|
269
299
|
### 功能开关
|
|
270
300
|
|
|
@@ -281,6 +311,8 @@ TaskPanel (Container)
|
|
|
281
311
|
watch: true # 开启:被监听根目录后台保持新鲜(默认)
|
|
282
312
|
watchInterval: 15 # 轮询间隔(秒)
|
|
283
313
|
enableTypeScript: true # 开启:装了 TS 时启用 L2 语义增强(默认)
|
|
314
|
+
# budgetLog: once # 调试用:注入被预算挤掉时在 stderr 留痕(默认 off 静默)
|
|
315
|
+
# reinjectItemsAfter: 20 # 调试用:同一条 insight 隔 N 步才允许重发(默认 0 = 本会话只发一次)
|
|
284
316
|
# tsPath: /custom/path/to/typescript # 可选:强制指定 TS 安装路径
|
|
285
317
|
```
|
|
286
318
|
|
|
@@ -300,7 +332,8 @@ dsh web --patch ./config.yml
|
|
|
300
332
|
|
|
301
333
|
```bash
|
|
302
334
|
npm install
|
|
303
|
-
npm test #
|
|
335
|
+
npm test # 286 项测试(核心 184 + TaskBridge 16 + insight-store 11 + insight-actions 9 + doc-index 8 + auto-inject 7 + host-contract 9 + reflection 5 + llm-route 4 + client-hints 2 + recall 8 + readiness 13 + insight-derive 6 + readiness-eval 4)
|
|
336
|
+
npm run bench -- /你的/项目路径 # 对任意项目量索引/查询性能,不需要 dsh
|
|
304
337
|
```
|
|
305
338
|
|
|
306
339
|
## 许可证
|