跳到主要内容
路径文档

会话检索

一句话版ctx.sessionQuery会话检索能力缝:在 live 与 durable 会话日志上做授权读取、关系轨迹和搜索,独立于 compaction。session-query 是服务定义,session-query-sqlite 用 SQLite FTS5 实现,tool-session-query 把工作区授权的检索暴露给模型。

一、是什么

会话检索让 DSH 能在不依赖压缩的前提下,检索自己的历史会话——精确读历史、追关系、全文搜。抽象服务组合了精确会话历史检索、关系追踪、以及与 provider 无关的过滤,作用于 live ctx.sessions 加上可选的动态挂载 ctx.sessionPersistence

ctx key角色
session-queryctx.sessionQuery定义可信读取、关系查询与搜索操作
session-query-sqlitectx.sessionQuery用 SQLite 全文检索实现会话查询
tool-session-query(注册在 ctx.tools 上)把工作区授权的会话查询暴露给模型

匹配到同一 id 只产生一条记录:live 事件优先,live/persisted 报告双方的源可用性;冲突的不可变头失败于 SESSION_QUERY_SOURCE_CONFLICT

二、读取 API(session-query

SessionQueryEngine 是组合的抽象 ctx.sessionQuery 契约:

Member语义
listSessions(signal?)读当前持久化元数据,live 优先合并,返回确定性 newest-first 排序的克隆记录
readSession(sessionId)返回一份完整分离的原始日志(经与 resume 相同的核心回放校验),不把会话放进 live store
filterSessions(filters, signal?)对同一克隆逻辑语料应用 provider 无关的会话元数据与可用性谓词
filterEvents(sessionId, filters)抽取一方案语义文档,按升序 seq 应用元数据与字面文本谓词
listEvents(sessionId)把每个事件分类为 current / shadowed / log-only
readSurface(sessionId)返回克隆头、原始日志捕获边界、完整折叠的当前 surface(模型历史序)
readEvent(request, signal?)返回克隆头、完整目标事件、有界原始 seq 窗口(before/after 缺省 0,不超 readWindowMax
traceSession(sessionId, signal?)读一次语料,返回向外祖先 + 确定性递归后代树;complete: false 标识首个缺失父节点
traceEvent(request, signal?)返回克隆源头、直接位置替换、直接引用源事件链(replacementChain 跟随位置替换到最终替换)

持久化可选、可动态挂载/卸载。挂载的持久化不可读时,跨语料列表与关系追踪失败于 SESSION_QUERY_PERSISTENCE_FAILED;成功读出但未过 Session 校验的 durable 记录报 SESSION_QUERY_CORRUPT_SESSION。针对已知 live 会话的标题读、事件轨迹、事件读不查持久化,所以 durable 后端健康不影响当前内存状态。

三、过滤与文本提取

  • SessionResultFilter:id、可空 cwd、created-at 范围、可空 parent、源可用性
  • SessionEventResultFilter:seq/time 范围、事件类型、surface、语义文本

过滤数组 AND,单个列表子句内的值 OR;空列表值不匹配任何东西,范围含端点。文本子句独立于 FTS provider:调用方文本转义成 Unicode、大小写不敏感正则,每个空白串匹配一个或多个空白字符——这是字面语义文本扫描,不是全文查询。

extractSessionEventText() / buildSessionEventSearchDocuments() 定义共享的一方案文档投影;reasoning 块、结构边界、stream chunk、请求头、未知 declaration-merged 变体不产生文档。

四、全文检索(session-query-sqlite

SqliteSessionQueryEngine 继承精确读/轨迹/provider 无关过滤,用 SQLite FTS5 实现两个全文方法。

  • searchSessions(request, exec?) 跨语料按最强匹配事件分组返回 SessionSearchHit 页;searchEvents(request, exec?) 搜单个逻辑会话
  • 查询必填,是 trim 后空白归一化的字面短语;FTS5 语法(引号、ORNEAR*)按数据对待,不按可执行 MATCH 语法
  • 相关性跨持久表与 TEMP 表可比:FTS5 高亮匹配 span 数降序,再存文档码点长度升序;事件时间 / 会话 id / seq 打破平局
  • 游标是不透明品牌值,绑定归一化请求与服务实例,相关代变化时失败;会话内游标不因无关会话变化而失效
  • 索引用 FTS5 unicode61:是 token/phrase 召回,不是任意子串召回(AI 匹配不到 token BRAID);要字面子串用 filterEvents()text 子句
  • 三个 surface(current / shadowed / log-only)默认都可搜,传 surface 过滤收窄

五、模型工具(tool-session-query

tool-session-query 注册 session_searchsession_event_searchsession_tracesession_event_tracesession_event_readopt-in(出厂组合默认不挂载)。

  • 调用方只来自 ToolExecution.exec.agent;跨会话访问要求目标与调用方会话 cwd 精确相等,无 cwd 的调用方只能检视自己
  • 搜索从不暴露 provider 游标、offset、页大小或模型可控的 limit;两个搜索工具与其他工具调用互斥执行,三个精确轨迹/读工具可并行
  • session_search 始终省略调用方自身会话;请求的 parent id 先去重并按工作区授权检查再进 FTS
  • 系统提示注入一段固定的 prior-history guidance,指引模型"用 session_search 找历史、用 session_event_search 搜单会话、命中后用 session_trace/session_event_trace/session_event_read 取关系或精确数据"
  • 每个 ctx.sessionQuery 调用都过一道模型边界 sanitizer,取消原因精确保留

六、配置

session-query 服务定义:

Key默认契约
readWindowMax50before/after 原始事件计数上限
persistedInspectConcurrency4单批读并发检查持久化日志数上限(正整数)

session-query-sqlite

Key默认契约
path必填专用派生索引 SQLite 路径;:memory: 可用
openAtstartupstartup 激活前打开;first-search 推迟到首次搜索;never 关闭全文检索但保留精确读取/过滤/trace
journalModewalwal / delete / truncate / persist
defaultLimit20请求省略 limit 时的页大小
maxLimit100接受的最大请求页大小
snippetChars240snippet 最大长度(Unicode 码点)

tool-session-query

Key默认含义
maxSearchResults100跨 provider 页收集的最大授权非自身命中数
searchTimeoutMs30000附加到两个全文搜索工具的合作截止时间

七、挂载状态

  • session-query-sqlite 默认挂载(base 组合),中性默认 path: ':memory:'openAt: first-search——进程本地、只在用到时打开
  • tool-session-query opt-in,出厂组合不默认挂载
  • session-query 是抽象服务定义,无独立具体插件

八、已知限制

  • 无调用方授权session-query/session-query-sqlite 是可信的全上下文基础设施;模型工具或 UI 必须自行约束可检视的会话
  • 同步查询执行DatabaseSync 在 MATCH 执行时阻塞 JS 线程,无法打断已运行的语句
  • openAt: never 是部署级关闭开关:两个全文搜索入口在参数规范化前返回 SESSION_QUERY_SEARCH_DISABLEDnode:sqlite、source observation 与 reconciliation 均不启动;继承的精确读取、过滤和 trace 仍可用
  • token 召回而非任意子串unicode61 不匹配更大 token 内的子串
  • 单所有者派生索引:一个索引路径只归一个进程里的一个服务;外部写入与多进程共享不支持

九、验证

# 看 session-query-sqlite 是否装载(默认挂载)
dsh web --dump-config | grep -iE "session-query"
# tool-session-query opt-in,默认不挂,应看不到
dsh web --dump-config | grep -iE "tool-session-query"

下一步

  • 内置工具tool-session-query 在工具清单的位置
  • 会话系统:被检索的事件溯源会话日志
  • 存储层:会话检索走 ctx.sessionPersistence,不经过 storage