前言¶
在 DeepSeek Harness(DSH)里做智能体开发,会话一多,「上次在某段思考里写过什么」「某个工作区里 agent 在某一小时说了哪些话」这类问题,往往只能逐条翻事件日志。官方 @deepseek-ai/dsh-session-query-sqlite 把索引单元定在事件上:一条事件抽一段文本、一行文档,命中结果通常是「哪个会话的第几号事件」,粒度对不上消息内部的 text、reasoning、tool-call 等块。
下面介绍社区插件 dsh-better-session-query(维护者 leolee9086,SkillHub 分类:记忆)。它在不替换官方 sessionQuery、不改 DSH 源码的前提下,给会话历史再挂一套块级并行索引,让块成为索引行,从而回答块级检索与元数据过滤问题。
这是什么¶
一句话:DSH 插件,对会话历史建立块级 FTS5 索引,与官方事件级 session-query 并行存在。
- 仓库:leolee9086/dsh-better-session-query
- 当前版本(package.json):0.1.1,许可证 MIT
- 依赖:分块逻辑来自
@leolee9086/dsh-session-blocks@0.1.0;存储使用 Node 自带的node:sqlite(FTS5) - 硬边界(README 原文):
- 不替换 provider,只消费运行时注入的
sessionQuery读会话 - 不 import 任何
@deepseek-ai/*包 - 可与官方 session-query 同时启用
v0.1.1 另导出 dsh-better-session-query/blocks 下的纯函数(extractRawBlocks、walkContentBlocks、parseToolArguments),可不加载索引服务单独使用。记忆同步、向量与混合召回仍在开发中,未包含在本版发行。
核心功能¶
与官方索引的差异¶
官方索引以事件为行;本插件把粒度下沉到块:一条消息里的 text / reasoning / tool-call / tool-result 等各自成块。块身份为 blockId = <sessionId>#<seq>#<path>,path 表示块在事件内的位置(如顶层 "0",tool-result 内层 "3.0")。
能回答的问题(摘要)¶
| 问题 | 方式 |
|---|---|
| 哪些块含某个词 | FTS5 + bm25;中文经拆字变换支持 ≥1 字子串召回 |
| 思考块里 2000~5000 字的块 | 元数据:blockTypes:["reasoning"] + lengthMin / lengthMax |
| 某段时间的 agent 消息 | granularity:"messages"、eventTypes:["assistant/message"]、timeFrom / timeTo |
| 某工作区有哪些会话/内容 | session_blocks_workspaces;检索带 workspace(= 会话头 cwd) |
| 标题含某词的会话 | session_blocks_workspaces(groupBy="session", titleContains="…") |
| 块正文 | session_blocks_read(blockId) 或 sessionId + seq (+ path) |
长度按 Unicode 码点计;时间用事件自带的 Unix epoch 毫秒(SessionEvent.time)。
块与倒排策略¶
默认进入全文倒排:text、tool-call、todo。reasoning、tool-result 外壳、image/file 等默认不进倒排,但元数据查询与 read 仍可用(与官方「思考块不入索引」语义一致)。思考内容若要被 search 命中,需打开 include.reasoning 并重建索引。
后台索引¶
索引在后台渐进更新(默认 reconcileOnSearch: "background",且每 30s 一轮定时);检索不等待索引完成。首次冷启动需对每个尚未索引的会话完整读日志建块,会话量大时会持续一段时间。可通过 session_blocks_list 指定会话 id,或 session_blocks_status {reindex:true} 手动推进。
索引库默认路径:<DSH_HOME>/session-blocks.db。倒排与过滤分表存储(block_fts、block_meta、block_text 等),与 session 持久化 JSONL 无关。
模型工具与服务¶
Agent 侧主要工具(README「模型工具」节):
session_blocks_search(query="并发模型", sessionId?, workspace?, excludeWorkspaces?, blockTypes?, surface?, limit?, offset?)
session_blocks_query(granularity="blocks"|"messages", workspace?, excludeWorkspaces?, blockTypes?, eventTypes?, surface?, lengthMin?, lengthMax?, timeFrom?, timeTo?, orderBy?, descending?, limit?, offset?, withText?)
session_blocks_list(sessionId, seq?, limit?, offset?)
session_blocks_workspaces(groupBy="workspace"|"session", workspace?, titleContains?, limit?, offset?)
session_blocks_read(blockId) | session_blocks_read(sessionId, seq, path?)
session_blocks_sql(sql, limit?)
session_blocks_status(sessionId?, reindex?, force?)
运行时还提供 ctx.sessionBlockQuery(刻意不复用 sessionQuery 名),含 searchBlocks、queryBlocks、queryMessages、reconcile、compact 等方法。
可选 Web 侧栏「会话块索引」监控(dsh.client.platform: "web");数据面仅本机 loopback。不需要界面时可设 monitor.enabled: false。
安装与启用¶
环境要求:Node.js 22.19.0 或更高(node:sqlite;Node 22.x 可能打印 ExperimentalWarning)。
README 说明:包位于 SAC_search 仓库的 dsh-better-session-query/ 子目录。开发时可把该目录放进 $DSH_HOME/plugins/,或在 profile 里 link:
dsh-better-session-query/ # 会话块级并行索引
在该 profile 的 cordis.patch.yml 里挂载(已有 insert 列表时只追加这一项):
- insert:
- id: dsh-better-session-query
name: dsh-better-session-query
config:
# path 留空 = <DSH_HOME>/session-blocks.db;要关后台索引更新就设 backgroundReconcileMs: 0
{}
包内已带 cordis.patch.yml,也可以直接作为 bundle 挂载:
- name: dsh-better-session-query
重载插件或重启 DSH 后生效。不需要修改官方 session-query-sqlite 配置;官方索引关闭时本插件仍可用。
常用配置项(节选,完整表见 README「配置」节):
| 键 | 默认 | 说明 |
|---|---|---|
path |
<DSH_HOME>/session-blocks.db |
索引库路径 |
backgroundReconcileMs |
30000 |
后台定时索引间隔;0 关闭定时 |
maxSessionsPerReconcile |
25 |
单轮最多处理的会话数 |
includeWorkspaces / excludeWorkspaces |
[] |
索引层白/黑名单(排除的工作区连日志都不读) |
reconcileOnSearch |
"background" |
检索时是否触发索引更新 |
典型用法¶
下列示例来自 README,可在 Agent 工具调用中复现。
按类型与长度筛思考块:
session_blocks_query(blockTypes=["reasoning"], lengthMin=2000, lengthMax=5000, orderBy="length")
按时间窗查 assistant 消息:
session_blocks_query(granularity="messages", eventTypes=["assistant/message"], timeFrom="2026-09-13 10:00", timeTo="2026-09-13 12:00")
工作区与会话清单、限定工作区全文检索:
session_blocks_workspaces()
session_blocks_workspaces(groupBy="session", workspace="D:\\work")
session_blocks_search(query="并发模型", workspace="D:\\work")
读取某事件的块:
session_blocks_read(sessionId="session-xxxx", seq=42)
需要自定义统计时,可用 session_blocks_sql 对公开表结构执行单条只读 SELECT/WITH(写操作与多语句会被拒绝;连接层启用 query_only)。
适用场景与注意¶
适合谁: 长期在 DSH 里跑多会话、多工作区的开发者;需要按块搜正文、按 reasoning 长度或时间窗筛 agent 输出、按 cwd 隔离检索范围,或希望与官方事件索引并存而不改 Harness 源码。
务必知晓:
- 插件在 当前 DSH 进程权限下运行,会读取会话日志并在本地 SQLite 中建索引。安装前请阅读 GitHub 源码 与 MIT 许可证,自行评估是否纳入 profile。
- 只有已被索引的会话可查;首次全量完成前未扫到的会话会缺失,可用
session_blocks_list指定 id 先拉入。 - 中文 FTS 为子串语义,单字查询面较宽,建议用小
limit;升级涉及STORE_SCHEMA_VERSION变更时会自动重建派生表,索引体积可能增大(README 给出中英混排约 +14%、纯中文约 +71% 的量级说明)。 - SkillHub(目录页)是社区插件目录,与 DeepSeek / 幻方无官方从属关系;DSH 生态本身是「一切皆插件」的扩展模型。
结尾¶
dsh-better-session-query 在官方 session-query 之外提供块级 FTS5 索引:块可搜、可滤、可读,后台渐进建库,并与事件级索引并行。若你的痛点是「事件太粗、思考块与工具块拆不开」,可以按 README 把包装进 profile,先用 session_blocks_status 看覆盖率,再按工作区与块类型组合查询。