Skip to content

dsh-wsl-first

Verified

dsh-wsl-first · v0.1.1 · MIT

Route DSH command execution to WSL first: a configurable system-prompt section that makes the wsl tool the default executor instead of pwsh

Install

dsh plugin add dsh-wsl-first

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

dsh-wsl-first

English | 中文

让 DSH 在 Windows 上优先用 WSL 执行命令。

🎯 装了 WSL 就先用 WSL,别让模型默认去写 PowerShell。

理念

DSH 在 Windows 上给模型的默认命令工具是 pwsh。这本身没什么问题,但如果机器上已经装了 WSL,这个默认就有点亏。

模型写 bash 比写 PowerShell 顺手,它的命令习惯基本是 POSIX 那一套。硬切到 PowerShell,就得在管道、转义、路径之间来回换算,换算错了还得重来一遍。每多一次重试,就是白烧掉的 token。

输出也是一样。Linux 那边的命令输出大多紧凑;PowerShell 默认给你带表格、带对象属性,同样的信息占的地方明显更大。

路径同理。WSL 工具会自动把 C:\... 转成 /mnt/c/...,不需要模型自己操心。

所以这个插件做的事情很简单:往系统提示词里加一段,写明执行命令先找 wsl。不加能力、不禁用工具,只是把默认顺序调过来。

那段提示词里只列真实注册了的工具。哪个工具没装,里面就不会出现它,也就不会出现"让模型去用一个不存在的工具"这种事。静态的指令文件做不到这点,它只会照抄。

特性

🚀 省 token 少一次语法换算,就少一次重试
🐧 对准 WSL 模型按 bash 来写,直接跑在 Linux 侧
🪟 留退路 真需要 Windows 原生功能时,pwsh 还在工具表里
🔧 可配置 想改成 bash 优先,或者只想提 wsl,改配置就行
🩺 不乱说 只宣传真实注册的工具,没装的不写

依赖

DSH >=0.1.7-rc.2
必需服务 systemPrompt,标准 profile 都自带
必需插件 dsh-wsl-tool,提供 wsl / wsl-path / wsl-env / wsl-doctor
WSL WSL2,至少一个已注册的发行版,wsl.exe 在 PATH 上
平台 任意。Windows 是动机场景,路由器本身与平台无关

本插件自己不注册任何工具,只在别的插件提供的工具之间做路由。没有 dsh-wsl-tool 就没有 wsl 可首选,那段提示词会渲染成空。

安装

npm install dsh-wsl-first

装完加进 profile 的 package.json:

{
  "dsh": {
    "profile": {
      "bundles": ["...", "dsh-wsl-first"]
    }
  }
}

bundle 自带 cordis.patch.yml,会把这个路由行进程级插进去,每个 agent preset 都能拿到这段提示词,不用各自声明。需要重启 profile,loader 在启动时读组合配置。

如果 wsl 工具本身还没装,先装它:

npm install dsh-wsl-tool

DSH 版本兼容

package.json 里声明了 engines.dsh: ">=0.1.7-rc.2"。

本插件没有声明任何 @deepseek-ai/* peer dependency,也不 import 它们的值。这是一条刻意的设计:DSH 启动时会用 evaluatePluginCompatibility 逐个校验 profile bundle 的 peer 区间,只要有一个不覆盖当前运行时版本,整个 bundle 会被跳过,cordis.patch.yml 不生效,表现就是"插件装了但没反应"。本插件没有任何 peer 区间可校验,也就不会因为这种原因被跳过。

升级 DSH 大版本后如果本插件突然没了动静,先看 stderr 有没有 skipping profile bundle 字样,再查 engines.dsh 是否还覆盖。

已知问题

在插件管理器里切换开关可能报错

在插件管理器里关闭(或重新开启)本插件时,可能弹出下面其中之一:

停用失败: dsh: profile reload requires the root Include entry
启用失败: dsh: warning: 1 entry did not activate

这不影响插件正常工作。 路由段仍在系统提示词里,插件照常运行 —— 只是这一次的开关没有生效,配置也不会丢失。

重启 DSH 即可:关掉应用再打开。改动会在启动时生效,之后一切正常。

在同一个 profile 里切换其他插件时,也可能出现同样的提示。

另外值得留意:DSH 运行期间编辑 profile 的 cordis.patch.yml,可能会让正在进行的会话丢失部分工具。改完这个文件请重启,不要依赖热重载。

配置

每个字段都可选,写在 profile patch(- id: wsl-first-routing / config:)或环境变量里。优先级:行配置 > 环境变量 > 内置默认值。

字段 默认值 环境变量 说明
preferred wsl DSH_WSL_FIRST_PREFERRED 最先尝试的工具
alternatives ['bash'] DSH_WSL_FIRST_ALTERNATIVES 首选项之后依次尝试(逗号分隔)
discouraged ['pwsh'] DSH_WSL_FIRST_DISCOURAGED 压到"最后手段"的工具(逗号分隔)
promptPolicy true — 是否发布这一段
sectionOrder 3260 — 段的排序位置
sectionName dsh-wsl-first:shell-routing — 段的稳定名称
extraGuidance '' — 追加到段末尾的额外文字
labels 内置 — 表格里 {工具: 任务描述}
requirePreferred false — 仅当 preferred 可见时才发布

只提 wsl,别的都不要

- id: wsl-first-routing
  config:
    preferred: wsl
    alternatives: []
    discouraged: []

这样那段只写 wsl,在没装 wsl 的环境里干脆不出现。

改成 bash 优先

- id: wsl-first-routing
  config:
    preferred: bash
    alternatives: []
    discouraged: []

wsl 只是默认值,这插件本质是个通用的执行器路由器。

两条配置规则

同一个工具既当执行器又当"最后手段"是矛盾,会直接报错,不让某个静默的胜者决定。而 preferred 在 alternatives 里重复出现不算矛盾,那只是冗余(把 preferred 指到 bash 时会自然发生),直接去重。

渲染出来的提示词

# Shell routing: wsl first

**For every command execution, call `wsl` as the first and default tool.**

| Task | Tool |
| --- | --- |
| Any command, build, git, pipeline, script, file listing, search | `wsl` |
| Windows-native only: registry, services, COM, cmdlets with no Linux equivalent | `pwsh` (last resort) |

## Rules

- `wsl` is the primary command executor. Reach for it first, every time.
- Use `pwsh` **only** when the task genuinely requires functionality no other available tool provides — and say why in the same reply.
- Never use `pwsh` merely because it appears first in a tool list, and never as a fallback when a `wsl` command fails: fix the command and retry there.
- Do not mix shell syntaxes. A `wsl` call contains the syntax of the shell that tool runs; each executor has its own quoting and path rules.
- `wsl` paths are Linux paths (`/mnt/c/...`). Windows paths in `command`/`workdir` are translated automatically; pass `translatePaths: false` to hand a native path to a Windows program.

上面这份是从真实会话的系统提示词里读回来的。注意里面没有 bash 那一行:在实测的那个 profile 里 bash 工具没注册,路由器就把它去掉了。

它刻意不做的事

不隐藏、不禁用任何工具。 目标是让 wsl 被优先选中,而不是让 pwsh 消失。隐藏工具改变的是模型能做什么,路由段改变的只是它默认先够哪个。

想要硬版本(把 pwsh 整个摘掉)是你自己 profile patch 的事:

- id: pwsh-sandbox
  disabled: true

改之前先在活着的 loader 树里确认那一行的真实 id,写错会静默失效。

项目结构

dsh-wsl-first
├── index.js          # Host 端插件:注册 systemPrompt 段
├── lib/
│   ├── config.js     # 配置解析、优先级、校验
│   └── policy.js     # 层级排序与提示词渲染
├── test/
│   ├── smoke.mjs     # 配置与渲染(27 项)
│   ├── mount.mjs     # 真实 apply() 挂载(8 项)
│   └── docs.mjs      # 断言两份 README 引用的是真实渲染(3 项)
├── cordis.patch.yml  # bundle 层:进程级插入路由行
├── dsh-plugin.json   # 插件清单
└── package.json

测试

npm test

lib/ 下两个模块都是纯函数,所以测试不需要 DSH 宿主。mount.mjs 用假的 cordis context 跑 index.js 里真实的 apply,断言注册出的段名、顺序和渲染文本。docs.mjs 重新渲染一次,逐字节比对两份 README 里引用的那段,所以文档里的输出不可能和代码实际产出脱节。

许可证

MIT