DSH plugin 接 LSP:LspQueryRequest、四种操作与 LspProvider 契约

插件开发发布于 2026-10-17作者: DeepSeek Plugin 插件市场
DeepSeek HarnessDSH pluginLspQueryRequestLspProvider代码导航seam
DSH plugin 的 LSP 导航 seam 怎么接:四项闭合操作、全部必填的查询请求、0 基 UTF-16 坐标与 1 基光标转换、以及 resolvedWorkspaceUri 的正确用法。

DSH plugin 的 LSP seam 只有四项操作,而且这个联合是闭合的:goToDefinition、findReferences、goToImplementation、hover。 闭合不是为了少写代码,而是让「新增一种查询」变成跨 seam、提供方与工具的编译期联动——漏改一处就编译不过。另一个容易踩的点是坐标:seam 用 0 基 UTF-16,面向模型的工具用 1 基光标,转换在边界处完成;把两层的坐标直接拼起来,导航就会偏一行。

最后,结果里的 resolvedWorkspaceUri 才是相对化的正确基准,不要拿请求路径去套宿主路径规则。

DSH plugin 的 LSP seam:四项闭合操作

一句话结论:四项语义查询构成闭合联合,符号与调用层级不在这里——它们需要不同的 schema。

  1. 四项操作:定义跳转、引用查找、实现跳转、悬停。
  2. 闭合联合:新增操作会编译失败,强制同步修改 seam、提供方与工具。
  3. 不包含什么:符号列表与调用层级不属于这四项,别硬塞。
  4. 分层:服务定义、通用 stdio 提供方、面向模型的 lsp 工具,各管一层。
  5. 可选能力:不在 agent loop 主干内,换提供方不改变模型请求导航的方式。

DSH plugin 的 LspQueryRequest:每个字段必填,没有 resolve

一句话结论:没有需要补默认值的字段,所以这套接口没有 resolve() 这一步。

ts
interface LspQueryRequest {
  operation: LspOperation
  filePath: string          // 相对 workspaceRoot 或绝对路径,由提供方规范化
  position: LspPosition     // 0 基 UTF-16
  workspaceRoot: string     // 必填,绝不默认
}
  1. workspaceRoot 由调用方给:提供方据此解析与索引。
  2. languageId 不在请求里:它来自提供方的扩展名映射,只用于同步瞬态文档,不参与提供方选择。
  3. 超时与结果上限归消费方:提供方不负责这些策略。
  4. 提供方收到的形状:请求加上派生出的 languageId。
  5. 验证:传一个不带 workspaceRoot 的请求,应在调用前就被类型或校验拒绝。

DSH plugin 的坐标约定:0 基 UTF-16 与 1 基光标

一句话结论:协议层用 0 基 UTF-16,工具层用 1 基;转换只发生在边界。

  1. 位置:从零开始的行号与行内 UTF-16 码元偏移。
  2. 范围:半开区间 [start, end)。
  3. 工具层:面向模型的光标从 1 开始,输入与输出各转换一次。
  4. 常见错误:把工具层坐标直接传给提供方,导航整体偏移一行。
  5. 验证:在一个已知符号上做定义跳转,返回范围应精确覆盖该符号。

DSH plugin 的结果联合:locations 与 hover

一句话结论:导航统一成 locations,hover 统一成内容或 null;findReferences 一定包含声明。

操作结果形态
goToDefinitionlocations + resolvedWorkspaceUri
findReferenceslocations(含声明)
goToImplementationlocations
hoverhover 内容或 null
  1. 穷尽处理:对 kind 做 switch,新增分支必须处理。
  2. 声明无开关:findReferences 始终包含声明,由提供方内部保证。
  3. 位置 URI 原样返回:uri 来自语言服务器,可能是 file: 也可能是别的。
  4. hover 范围可选:服务器给了就有,没给就没有。
  5. 提供方转换:把 LSP 原始响应规范化成这两类,别把协议细节漏给消费方。

DSH plugin 的 resolvedWorkspaceUri 与 LspProvider 契约

一句话结论:位置 URI 相对化时用提供方的规范工作区 URI,不要解析请求路径。

  1. 为什么不能用请求路径:它可能经过符号链接,而且执行平台可能与调用方不同。
  2. 正确做法:用结果里的 resolvedWorkspaceUri 作为基准做相对化。
  3. 跨平台:提供方在它的执行世界里规范化,调用方不应套用自己的宿主路径规则。
  4. 验证:在带符号链接的工作区里做一次引用查找,相对路径应落在真实工作区内。
  5. 边界:如果结果 URI 不在工作区内,保持原样,不要强行相对化。

DSH plugin 排查注意事项

一句话结论:LSP 问题先分「选错提供方」「坐标偏移」「结果未规范化」三类。

  1. 没有结果 → 检查提供方是否注册、语言服务器是否就绪、workspaceRoot 是否正确。
  2. 偏移一行 → 坐标基准搞混了,检查 0 基与 1 基的转换。
  3. 引用里没有声明 → 不该发生,findReferences 由提供方保证包含。
  4. 相对路径错乱 → 用了请求路径而不是 resolvedWorkspaceUri。
  5. 想加第五种查询 → 那是一次跨包改动,不是加个分支就行。
  6. 修复状态如实:本文的四项操作、请求必填约束、坐标约定与结果联合均取自官方「LSP 导航」页面;接口签名以该页 Cordis API 与你所用版本为准。

来源:LSP 导航、dsh-lsp 源码、dsh-lsp-stdio。

常见问题

DSH plugin 的 LSP seam 支持哪些导航操作?

DSH plugin 的 LSP seam 恰好公开四项:goToDefinition、findReferences、goToImplementation 与 hover。这个联合是闭合的,新增操作会编译失败,强制同步修改 seam、提供方与工具。

DSH plugin 里,为什么 LspQueryRequest 没有 resolve() 这一步?

DSH plugin 的 LspQueryRequest 每个字段都必填:workspaceRoot 由调用方给,languageId 来自提供方注册,超时与结果上限由消费方定。没有字段需要实现补默认值,因此不需要 resolve。

DSH plugin 里,seam 的坐标是 0 基还是 1 基?

DSH plugin 的 seam 用 0 基 UTF-16 坐标,与 LSP 协议一致;面向模型的工具用 1 基光标约定,在输入与输出时做转换。跨层拼坐标之前先确认自己在哪一层。

DSH plugin 里,findReferences 需要额外传参数才会包含声明吗?

不需要,DSH plugin 的 findReferences 始终包含声明,由提供方内部强制保证,调用方没有对应开关。位置结果统一走 locations 联合,不需要另写分支。

DSH plugin 里,把位置 URI 相对化时,应该用请求里的 workspaceRoot 吗?

不应该,DSH plugin 要求用结果里的 resolvedWorkspaceUri:它是提供方的规范 file: URI。请求路径可能经过符号链接,执行平台也可能与调用方不同。

相关术语

LspOperation(导航操作)
LspOperation 是 DSH plugin 的 LSP seam 公开的四项语义查询,取值限定为 goToDefinition、findReferences、goToImplementation 与 hover。它是闭合联合,新增操作需要同步改 seam、提供方与工具。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/lsp
LspQueryRequest(查询请求)
LspQueryRequest 是一次规范化导航查询,operation、filePath、position 与 workspaceRoot 全部必填。languageId 不在请求里,而由提供方的扩展名映射派生。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/lsp
LspQueryResult(查询结果)
LspQueryResult 是闭合的可辨识联合:导航操作规范化为 locations,hover 规范化为内容或 null。消费方对 kind 做穷尽处理,新增分支会编译失败。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/lsp
resolvedWorkspaceUri
resolvedWorkspaceUri 是提供方为请求工作区给出的规范 file: URI,随 locations 结果返回。相对化位置 URI 时必须用它,而不是请求里可能经过符号链接的路径。— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/lsp

来源