deepseek-harness/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md

3.8 KiB
Raw Blame History

Agent Note: 会话内容搜索通过 openAt never 以 opt-in 方式交付

Status: implemented

English | 中文

问题

交付的 bundle 之前以启用状态挂载 SQLite 会话查询提供方的全文索引(openAt: first-search),因此每个默认部署都携带一个派生 FTS 索引,Web 侧边栏提供内容搜索。一个部署是否需要该索引——它的 node:sqlite 导入、每次搜索的来源对账和派生存储——是部署自身的选择,产品默认不携带它交付;面向模型的搜索工具此前已经是 opt-in 且未挂载(见非默认交付决策)。

通过卸载插件行来关闭该能力不可行。ApiProxyService 将 sessionQuery 声明为必需注入,没有该提供方时整个宿主 API 网关保持未加载,Web GUI 无法启动。会话日志导出通过 ctx.sessionQuery.traceSession 追踪子代理后代,子代理分叉也通过同一血缘追踪解析其 Workspace——两者都需要可选服务守卫加一个替代血缘来源,改动面大约扩大三倍,同时使精确读取在所有地方消失。

决策

内容搜索在提供方处强制关闭。openAt: 'never' 是 @deepseek-ai/dsh-session-query-sqlite 的第三个打开阶段:searchSessions 和 searchEvents 在任何请求规范化之前就以类型化的 SESSION_QUERY_SEARCH_DISABLED 代码失败,node:sqlite 绝不会被导入或打开,也不运行任何来源观察或对账。ctx.sessionQuery 上继承的全部精确读取、过滤和跟踪保持可用,因此会话导出、分叉的 Workspace 继承和标题读取不受影响。

SESSION_QUERY_SEARCH_DISABLED 加入封闭的 SessionQueryErrorCode 分类,tool-session-query 的服务边界将它映射为模型安全消息 session search is disabled in this deployment。

base bundle 在 session-query-sqlite 行上设置 openAt: never,web bundle 的重述保持该值;启用内容搜索只需在后续 patch 层用一行覆盖 openAt(first-search 或 startup),通常同时配一个持久 path。宿主 session.search 端点沿现有错误路径报告提供方失败,Web 侧边栏保持其既有降级:本地标题/工作区匹配加内容搜索不可用提示。CLI 兼容性测试固定交付的 openAt: never 行,而 Web e2e 脚手架保持内容搜索启用——其种子会话场景通过内容搜索导航,这些运行也是 opt-in 路径的装配级覆盖。

曾考虑的替代方案

  • 卸载插件行(在 base patch 中 disabled: true)——否决:api-gateway 的必需 sessionQuery 注入会使整个宿主 API 保持未加载,而把该注入改为可选需要守卫加上会话导出与分叉解析中的 header 遍历血缘回退。
  • 在消费方处关闭(宿主 session.search 端点或侧边栏)——否决:强制应由做出决定的操作执行;opt-in 的模型工具或任何其他消费方仍会触达索引。
  • 在 openAt 旁增加独立布尔开关——否决:打开阶段已经拥有"SQLite 何时启动"这一轴;never 延伸同一根轴,而不是增加一个可能与之矛盾的第二个旋钮。

结果

  • 默认部署不运行任何派生索引:没有 node:sqlite 导入或实验性 SQLite 启动警告,没有对账工作,磁盘上没有派生数据库。侧边栏搜索只匹配会话标题和工作区名称。
  • 默认状态下的搜索失败是类型化且稳定的,调用方可以把部署选择与索引故障(SESSION_QUERY_INDEX_FAILED)区分开。
  • 重新启用内容搜索是逐部署配置而非代码改动,并原样恢复完整的 FTS 行为。
  • 挂载搜索工具但未覆盖 openAt 的组合,每次搜索调用都会得到模型安全的已禁用消息;启用工具意味着同时启用索引。