← 返回列表
⚠ 装前注意
将 DeepSeek Harness…
基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/20 · 已提供中文文档
将 DeepSeek Harness 桥接到语言服务器,以实现只读代码智能,支持多语言配置、多根工作区以及会话级服务器复用。
综合分
34.5
GitHub 分
34.5
用户评分
—
★ Stars
0
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/voidmind26/dsh-lsp-bridge.git信任档位:需留意实装验证未通过
- 是什么
- 生态插件(可安装,未声明 dsh 能力)
- 装得上吗
- 实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 5 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/9/25) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
数据截至 2026/9/25(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-lsp-bridge(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
未发布到 npm registry,仅可从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/25 18:40:38
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-lsp-bridge
将 DeepSeek Harness 桥接到语言服务器以实现代码智能——只读查询加上受权限门控的重写——具备模型驱动的安装与配置、多语言发现、多根工作区以及会话级服务器复用。
为 DeepSeek Harness 的 LLM 提供通用 LSP 查询工具 lsp。支持按语言配置多个 stdio 语言服务器、独立项目根目录和显式多根工作区,并在 Web 与 Desktop 的插件设置中提供自动发现和配置界面。Node.js ≥22,无安装期构建。
能力
| operation | 用途 | 额外必需参数 |
| --- | --- | --- |
| status | 查看配置的服务;不启动语言服务器 | 无 |
| hover | 类型与文档 | file、line、character |
| definition | 跳转定义 | file、line、character |
| typeDefinition | 类型定义 | file、line、character |
| implementation | 实现位置 | file、line、character |
| references | 引用,包含声明 | file、line、character |
| documentSymbols | 文档符号 | file |
| workspaceSymbols | 所选项目/多根工作区的符号 | query;建议显式 server、root |
| diagnostics | 单文件诊断,优先 pull,否则等待 push | file |
具体能力取决于服务器。输入 line / character 从 1 开始,character 按 UTF-16 计数;输出保留原始 LSP URI 与 从 0 开始 的 range。server 用于消除多个语言服务的匹配歧义;路径相对于当前会话工作目录,也可用其内部的绝对路径。
{"operation":"definition","file":"qsl-game-server/main.go","line":20,"character":8,"server":"go"}
以上行列只是参数示例,应替换成目标符号的真实位置。
{"operation":"workspaceSymbols","server":"go","root":"unityroomlib","query":"Router"}
输出值是 { "json": "...", "truncated": false },GUI/LLM 文本呈现为 json 内的内容。超长结果变为带 truncated 标记的预览,不可把预览视为完整结果。
安装:web 与 Desktop
本包是服务端 Bundle 插件:package.json 声明 dsh.bundle.patch,包根 cordis.patch.yml 通过包名挂载,不绑定个人路径或 profile。无需浏览器组件,也不需要编译。已核对 DSH 0.1.5-rc.2 / Desktop 2.0.10 的接口;其他版本需验证。
web profile
已安装 DSH CLI,且 PATH 中可用 pnpm 时,在本插件目录执行:
dsh plugin --profile web add github:voidmind26/dsh-lsp-bridge
应使用已经初始化的 web profile;安装后重启原有 web 进程并刷新页面,不要另起替代服务器。卸载:dsh plugin --profile web remove dsh-lsp-bridge。
Desktop profile(本机 macOS)
普通 DSH CLI 会拒绝保留的 desktop profile,应使用 Desktop 自带入口。下面的函数可操作 web 和 desktop,但请只选择你实际使用的 profile:
dsh_packaged() {
ELECTRON_RUN_AS_NODE=1 '/Applications/DSH Desktop.app/Contents/MacOS/DSH Desktop' \
--expose-internals '/Applications/DSH Desktop.app/Contents/Resources/app/lib/desktop-cli.js' "$@"
}
在本插件目录执行;需 PATH 中可用 pnpm。
dsh_packaged plugin --profile desktop add github:voidmind26/dsh-lsp-bridge
如果使用 Desktop 自带 CLI 管理 web:
dsh_packaged plugin --profile web add .
该命令面向 Desktop 已创建的现有 profile;不要用它代替首次启动 Desktop 初始化。应用安装路径不同时调整命令。安装后重启 Desktop,再刷新原有 GUI。卸载:dsh_packaged plugin --profile desktop remove dsh-lsp-bridge。其他操作系统需使用其 Desktop 提供的 CLI 入口,此处不声明已验证。
模型自动安装与配置(推荐)
插件向模型提供 lsp_setup 工具,因此不需要人工扫描或手写配置。典型流程是让智能体执行一次 lsp_setup:
| operation | 行为 | 是否执行程序 |
| --- | --- | --- |
| status | 诊断项目与服务器,报告缺什么、可用的安装方案 | 否 |
| install | 执行 catalog 允许列表内的安装命令(需 apply=true) | 是 |
| configure | 把可用服务器写入插件配置 | 否 |
| verify | 真实启动服务器完成 initialize,报告能力与错误 | 是 |
| auto | 串起以上全部步骤(安装需 apply=true) | 取决于 apply |
它会诊断“服务器存在但运行组件缺失”这类问题。例如只有 typescript-language-server 而没有 TypeScript SDK 时,status 会给出 missing-dependency 与原因,而不是谎报可用;auto + apply=true 会把 typescript@5 与语言服务器一起装进插件私有目录,并把 initializationOptions.tsserver.path 一并写入配置。
安全边界:
- 安装命令完全来自冻结的 src/catalog.js,模型只能选择服务器 ID,不能提供命令、参数、包名或安装路径。
- 不使用 shell、不使用 sudo;每条命令都会出现在工具调用结果中。
- 只有 install/auto 且显式 apply=true 才会执行安装;status 与 verify 从不安装。
- 安装目录默认 $DSH_HOME/lsp-bridge(本机 ~/.dsh/lsp-bridge),不修改业务工程;可用 install.directory 调整,install.enabled=false 可整体禁用,install.managers 可为某种安装方式指定绝对路径。
- 每次调用都要求目标会话为 danger-full-access,绝不自动提权。C/C++ 的 clangd 没有可移植安装方案,只给出人工安装建议。
配置与启用
1. Bundle 默认 servers: [];安装插件本身不会下载或启动任何语言服务器。推荐直接让智能体执行 lsp_setup(见上一节)自动完成,或手工配置。
2. 手工配置时,将 examples/cordis.patch.yml 的 id: lsp 配置覆盖合入 $DSH_HOME/profiles/web/cordis.patch.yml 或 $DSH_HOME/profiles/desktop/cordis.patch.yml 的顶层数组。默认 DSH_HOME=~/.dsh。保留其他插件条目;config 是整体替换,不是深合并。
3. 根据需要填写 servers。GUI 的 PATH 可能与终端不同,必要时使用服务器命令绝对路径。JSON 示例不会自动读取,应把内容放入配置。
4. 如果以前手动添加过 insert: ... id: lsp,迁移时先移除该旧插入,仅保留 Bundle 提供的挂载及 profile 的配置覆盖,避免重复注册工具。
5. 在目标工程会话中使用 danger-full-access,先调用 lsp 的 status,再查询真实文件中的定义。卸载时同时移除 profile 中仅属于本插件的覆盖条目,并重启相应宿主。
$DSH_HOME/cordis.patch.yml 可覆盖 profile 层,排查配置时也要检查。仅修改 profile 配置可由宿主 patch 重载处理;源码和 Bundle 安装变更以重启宿主为准。
验证范围: 已有协议、生命周期、Bundle 结构及模拟宿主契约测试;尚未修改运行中的 profile,不能把这些测试视为真实 web/Desktop GUI 安装成功。分发与收录检查见 分发说明。
设置 UI 与自动发现
安装并完整重启 Desktop(或重新启动 Web 宿主)后,进入「设置 → LSP」独立页面。页面分成三个视图:
服务器列表(默认):只显示当前已配置的每个语言服务器。页面会自动做一次只读诊断,并对齐备的服务器做一次短暂启动验证(initialize 后立即关闭),因此每张卡片同时标注配置状态(可用 / 缺少运行组件 / 未安装 / 未扫描)与验证状态(验证通过 / 验证失败 / 未验证)。点击卡片展开查看该服务器的程序路径、启动参数、语言、项目/工作区目录、初始化选项与配置方式;比如「验证通过 · 支持 悬停、定义、诊断 等 12 项能力 · utf-16」,协议里的完整能力清单收进折叠区,服务器自报的长版本信息不再原样铺开。也可用「重新扫描并验证」手动刷新。
语言服务器属于项目目录,不属于会话。 每台服务器的评估目标由它自己的 roots/workspaceFolders 决定;没有配置根目录时才回落到当前会话的工作区。因此一台配置在别的工程下的服务器(例如 gopls 指向另一个仓库)同样会得到状态与真实验证,不需要切换到那个项目的会话。卡片里会标注「评估目录:…(来自配置的项目根目录)」。
会话只承担两件事:授权(能否启动可信程序)与未声明根目录时的默认目录;代码查询(读取工作区文件)仍以会话工作区为边界。
配置的根目录只做 canonicalize 与目录校验,允许落在会话工作区之外;lsp 的 file/root 属于调用方输入,仍必须落在会话工作区内(符号链接解析后同样如此)。因此当工作区里的文件不属于该服务器配置的任何项目根时,查询会明确报 File is not covered by configured roots/workspaceFolders for ,而不是含混的越界错误。
项目根怎么定(三种模式)
| 配置形状 | 带 file 的查询 | 无 file 的 workspaceSymbols |
| --- | --- | --- |
| 都不填(只有 rootMarkers) | 从文件所在目录就近找到项目标记 | 会话根目录为评估根,预热会打开各项目的文件 |
| roots: [A, B](固定评估,可跨工作区) | 按覆盖文件的最深根选主根 | 主根取最深的一个,但 A、B 都声明给服务器,因此两个仓都能查到 |
| roots: [A](钉住一个工程) | 只有 A 里的文件可用,B 报 is not covered… | 只覆盖 A |
上面的行为用真实 gopls 在一个含两个独立 module 的工作区里实测过:不填根 / workspaceFolders: [A,B] / 修复后的 roots: [A,B] 都能在 workspace/symbol 里同时看到两个仓的符号,而钉住单根时只看到一个仓。选哪种取决于目的:要“走到哪个工程查哪个工程”就不填根;要多仓一起评估就填 workspaceFolders(或 roots);要在任意会话里固定查某个工程才用 roots。
新增语言服务器(右上角「+ 新增语言服务器」):以语言服务器为中心的添加流程——先选服务器、看它在这台机器与当前工作区里的状态,再「加入配置」,最后在页面底部保存。项目范围只是服务器的一个属性(折叠在卡片细节里),会话选择器只决定“扫哪些项目”和“用哪种授权启动”,不是配置主体。
Edit Configuration JSON ("Edit Configuration JSON" on the list page): A standalone view for manually editing the complete configuration, without mixing in scanning and candidates; each server card can also jump to this view with one click.
1. In the add view, select a session as the scan scope; the directories in the list are server-side session records, and arbitrary scan paths submitted by the browser are not accepted.
2. Click "Rescan". The plugin checks the Go, Rust, TypeScript/JavaScript, Python, and C/C++ project markers and server candidates in the fixed catalog, and simultaneously diagnoses whether the runtime components are complete.
3. Expand the candidate cards: available, pending selection, not installed, missing runtime components; when components are missing, the specific reason and the install command to be executed are displayed. Scanning does not execute candidates, version commands, or install commands, nor does it modify project files.
4. "Add to Configuration" merges available suggestions into the draft (multiple candidates require an explicit choice first), and lists which servers are already in the draft; to manually change fields (roots, workspaceFolders, initializationOptions, etc.), switch to "Edit Configuration JSON". Adding to the draft does not equal saving.
5. After verification, click "Save Configuration". The Host validates the configuration again and hot-swaps the server pool; saving itself does not start servers—the next semantic query triggers lazy startup. Saving does not require an additional trust checkbox, but please only configure trusted program paths and arguments.
The UI and Web/Desktop share the same platform: web client Bundle. Automatic discovery has limits on scan depth, directory/project count, and time; if the results are truncated, the interface will clearly indicate this, and it must not be treated as a complete enumeration. Languages outside the built-in catalog can still be configured manually.
Scanning and installation are two separate things: Scanning is read-only and never installs; installation only occurs when the agent explicitly executes lsp_setup's install/auto (and apply=true), the commands are limited to the catalog allowlist, and the interface displays the exact commands to be executed. When something is missing and there is no portable solution, only manual installation suggestions are given (for example, clangd). The discovery interface is read-only, and sessions with any permissions can call it; it will not automatically escalate privileges.
General Configuration
See examples/generic.config.json (Go, Python, TypeScript/JavaScript) and examples/uos.config.json (the uos standalone Go module and frontend project). Any server compatible with stdio LSP is supported, but this does not mean the plugin automatically downloads servers or configures their language SDKs.
| Field | Description |
| --- | --- |
| servers[].id | Unique server identifier |
| command / args | Trusted program and arguments, not executed through a shell |
| env | String environment variables that override the process environment; do not commit credentials |
| languages | LSP languageId to extension array, such as {"go":[".go"]} |
| rootMarkers | When roots is not filled in, search upward level by level from the file's directory to the workspace boundary for the nearest project marker; if none is found, use the session root directory |
| roots | A fixed list of project root directories to evaluate (can span workspaces); for this query, the primary root is selected as the deepest directory covering the file, and the remaining roots are also declared to the server |
| workspaceFolders | Multiple root directories explicitly declared to the server (multi-repo workspaces); relative paths are resolved against the session working directory |
| initializationOptions | Passed through to initialize as-is |
| settings | The data source for didChangeConfiguration configuration and workspace/configuration queries |
| timeoutMs | Timeout for a single protocol request, default 15000, maximum 300000 milliseconds |
| maxInstances | Maximum number of instances per engine, default 8, maximum 128 |
| idleTimeoutMs | Idle reclamation time for session engines, default 300000 milliseconds |
| maxSessions | Upper limit on the number of resident session engines, default 4 |
| maxFileBytes | File read limit, plugin default 1 MiB, maximum 8 MiB |
| maxOutputChars | Character limit for tool JSON output, default 30000, minimum 256 |
| sandbox.redirectCaches | Whether to redirect server cache variables to a writable temporary directory in restricted sessions, default true |
| sandbox.cacheDirectory | Cache redirection target, default os.tmpdir()/dsh-lsp-bridge, must be an absolute path |
Multi-directory Semantics
- uos is not a single Go module. The default configuration uses the nearest go.mod to locate each project, avoiding starting gopls directly from the top level and failing to find the module.
- Each directory in roots and workspaceFolders will be declared to the server as a workspaceFolders entry (one instance serves all declared roots), and the primary root is selected as the deepest directory covering the current file; therefore, a multi-repo workspace can cover multiple repos with one process.
- lsp_setup configure does not write the scanned project roots into the configuration (it only writes commands, arguments, languages, and rootMarkers): scan results are "facts in the current session", and writing them as absolute paths will become invalid after changing machines or checkout directories, and will narrow workspace symbol queries without a file to a single repo. Only manually fill in roots when you need to fix evaluation to a certain project; if you want the server to return to "automatically determined by workspace", write it as roots: [].
- Multiple roots do not automatically fix dependencies: whether cross-repo definitions resolve to local shared libraries still depends on go.work / replace, tsconfig project references, etc. The plugin does not automatically rewrite these files, nor does it guarantee that every server supports multiple roots.
- Directories in explicit roots must exist; if only part of the uos repository is checked out, remove the missing directories or use the generic rootMarkers example.
- Workspace symbols only query one selected instance and do not automatically aggregate all languages and all projects; explicitly pass in server + root.
- Vue SFC, Java, C#, etc. require the corresponding server and its initialization configuration. The TypeScript service in the example is not equivalent to full Vue .vue support.
Model Context and Server Selection
The plugin injects a very short piece of context into the model, explaining which language servers are configured in the current session workspace (name, language, most recent scan/validation conclusion), and prompts it to prefer lsp for code navigation and to use lsp_setup when components are missing. This snippet is generated synchronously on each assembly, only reading the in-memory configuration and the most recent diagnostic cache, without scanning or starting processes; when no servers are configured, it is not injected, the cache expires after 10 minutes, and at most 6 are listed.
Permissions do not affect injection: The context has no session permission determination, and read-only / workspace-write sessions also receive the server list and status (in restricted sessions, servers already run inside the session sandbox). What is actually affected is the status content:
- Validation successful → display "Most recent real validation: ...=passed";
- 受限会话且没有可用沙箱后端 → 扫描仍返回完整状态,验证部分给出明确原因,界面显示「验证未执行:…」,上下文不因此退化成「未扫描到」;
- read-only 会话里需要写缓存的服务器(如 tsserver)验证会失败,原因写进错误,状态如实显示为验证失败。
workspaceSymbols 没有文件可推断语言,因此插件会先按“是否覆盖当前工作区”自动选择服务器,只有多个服务器都覆盖时才要求显式传 server。指定 server 时始终按指定服务器查询。
冷启动时插件会先做一次有界预热:在服务器自己的项目根内(深度 ≤ 2、最多 200 个目录项、最多 24 个语言匹配文件,跳过依赖/构建目录与符号链接)打开匹配文件,让服务器建立项目。读取的包含性基准是这个项目根,而不是会话工作区——配置在别的工程下的服务器同样需要预热,否则 TypeScript 会在 workspace/symbol 上直接报 No Project.。预热只在实例还没有任何已打开文档时执行,代价一次。
安全与生命周期
语言服务器本质上是本地可执行程序,可能读取依赖、写缓存、加载插件或运行工具链。仅配置你信任的程序和项目。
写入能力(rename、format,以及服务器主动发起的 workspace/applyEdit)默认是先预览后写入:不带 apply: true 只返回将要改动的内容,apply: true 才落盘。写入始终限制在会话工作区内,并按会话权限判定:
| 会话权限 | 写入行为 |
| --- | --- |
| danger-full-access | 允许(仍限定在工作区内),服务器进程不被沙箱包装 |
| workspace-write | 允许工作区内的文件;服务器进程同时被会话沙箱约束 |
| read-only | 拒绝,并明确提示需要完全访问权限(danger-full-access) |
被沙箱或权限挡住时不会静默失败:只读会话、工作区外目标、非文本编辑(创建/重命名/删除文件)都会给出具体原因。
写入的可靠性细节:所有目标文件先读入并算出新内容,校验通过后才逐个原子替换(同目录临时文件 + rename,保留原权限);某一个文件写失败时会报告已经写了哪些、还剩哪些,不假装整批成功。验证探针(lsp_setup verify / 页面验证)固定以只读方式启动服务器,服务器即使请求 applyEdit 也不会改动文件。
- 权限模型:语言服务器进程按会话权限处理,且不会因为插件而放宽。
- danger-full-access:按用户授权直接启动(服务器是未被 OS 沙箱隔离的可信程序)。
- workspace-write / read-only:服务器 argv 先交给 DSH 沙箱服务(ctx.sandbox.confine,macOS 为 seatbelt)包装,因此它只能写会话工作区、/tmp 与用户临时目录;插件会把 GOCACHE、GOTMPDIR、XDG_CACHE_HOME 重定向到临时目录(可用 sandbox.redirectCaches=false 关闭,或 sandbox.cacheDirectory 指定绝对路径)。
- 部署没有可用沙箱后端时失败关闭:绝不退化成无沙箱启动,也不自动提权。read-only 会话下沙箱不允许任何写入,部分服务器可能因此启动失败,错误会说明原因。
- 扫描(只读诊断)在任何权限下都可用;lsp_setup 的 status/configure/verify 在受限会话可用,只有真正执行安装命令的步骤要求 danger-full-access(安装器在插件内直接执行、不经过会话沙箱)。
- 模型无法通过工具指定 command/env,也不能发送任意 LSP method;写入只能通过 rename/format 或服务器发起的 applyEdit,并受上面的权限与工作区边界约束。
- 文件与根目录经 realpath 工作区检查,拒绝路径穿越与符号链接逃逸。但这不限制服务器自行读取依赖,也不是对抗并发文件替换攻击的 OS 沙箱。
- 按会话与工作目录常驻复用引擎,同一语言、项目根目录的后续调用复用语言服务器,避免重复初始化;不同会话隔离。status.instances 可查看当前会话已启动的实例。
- 空闲超过 idleTimeoutMs(默认 5 分钟)回收会话引擎;活动请求不因空闲超时被回收。maxSessions(默认 4)限制会话池容量,maxInstances 限制每个引擎的服务器实例数。
- 监听 DSH 的 session/event 权限变更及 session/disposed 释放事件。权限收紧时取消相关请求、关闭服务;插件卸载关闭所有服务。每次调用仍检查有效权限,并每秒复查常驻会话权限以覆盖缺少专用事件的默认策略变化。该复查不是操作系统级即时权限撤销。
- 关闭一个 GUI 标签页不一定等于 DSH 释放会话;未收到释放事件时,由空闲超时负责回收。
- 超时针对各协议请求,不是整个索引任务的总时限。支持调用取消与插件卸载清理。
- 推送型诊断超时未收到时表示“尚无诊断结果”,不应解读为代码无错误。仅同步当前请求文档的磁盘内容,不提供编辑器未保存 buffer 或文件系统全局监听。
开发与验证
npm run build:client
npm run check
npm test
可选真实 Go LSP 集成验证,仅在临时 Go module 内运行:
LSP_TEST_GOPLS=/Users/voidmind/go/bin/gopls npm test
测试按主题组织,同一主题的断言合并在一个用例里(当前 54 个用例,覆盖模拟 stdio 分帧、多根与独立项目路由、UTF-16 参数、磁盘内容同步、符号/诊断、路径与符号链接边界、扫描限制与 PATH 处理、配置与权限门控、会话常驻与回收、安装/配置/验证流程、客户端契约与双视图)。新增覆盖请并入对应主题的现有用例,不要为同一行为再开一个用例。真实 gopls 测试默认跳过,设置 LSP_TEST_GOPLS 才执行。没有为此运行 uos 业务服务或修改其中代码。
实现入口:src/index.js(DSH 适配)、src/pool.js(会话常驻池与生命周期)、src/engine.js(路由与 LSP 会话)、src/transport.js(JSON-RPC stdio);设计见 docs/design.md。
常驻相关测试额外覆盖跨调用 PID 一致、不同会话隔离、文件同步、权限事件与周期复查回收、会话释放、插件卸载、空闲回收及满载保护。