dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
编码正确的命令执行与乱码还原:encoding_run 自动识别 UTF-8/UTF-16LE/GBK 并正确解码子进程输出,encoding_decode 把乱码文本还原为正确 Unicode。
Correct-encoding command runner and mojibake recovery for DeepSeek Harness.
让 DeepSeek Harness 在 Windows 上不再乱码。
dsh-encoding is a thin tools plugin for DeepSeek Harness (dsh). On Chinese Windows, legacy CLIs, Git Bash/MSYS2 and PowerShell 5.1 often write GBK (cp936) or UTF-16LE bytes, which dsh's built-in bash/pwsh tools decode as UTF-8 and show as mojibake. The decoding happens inside the non-pluggable core service (dsh-subprocess-local), so this plugin does not try to patch it. Instead it adds two complementary tools:
| Tool | What it does |
|---|---|
encoding_run | Spawns its own child process, captures raw bytes of stdout/stderr, auto-detects UTF-8 / UTF-16LE / GBK and decodes them correctly. |
encoding_decode | Recovers already-garbled text (e.g. GBK bytes misread as latin1) back to correct Chinese. |
0.2.0 breaking change: tool names were renamed from
run/decode_texttoencoding_run/encoding_decode(collision-safe prefix). 0.1.0 is deprecated on npm.
run / decode_text tools. Verified with a clean, plugin-free profile (dsh --profile pmaudit --dump-config): the base config contains no such tool rows (built-in tools are tool-bash, tool-pwsh, tool-fs, …), and the official tools reference documents none.bash/pwsh tools still have no encoding configuration — the shell seam's ShellExecRequest has no encoding field — and a GBK-producing command through the built-in pwsh tool still returns mojibake on this environment. This plugin's premise therefore holds.run_code name (official tools.md).From npm:
dsh plugin --profile <name> add dsh-encoding
From a local checkout (this repo):
dsh plugin --profile <name> add ./dsh-encoding
From GitHub (works with no build authorization because the package is pure ESM JavaScript with no build step):
dsh plugin --profile <name> add github:Lostforest7/dsh-encoding
Verify the layer is active, then start:
dsh --profile <name> --dump-config # shows a "# == dsh-encoding" layer
dsh --profile <name>
encoding_run| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
command | string | yes | — | Command line to execute (Windows: cmd /d /s /c, POSIX: /bin/bash -c). |
workdir | string | no | — | Working directory for the child process. |
timeoutMs | number | no | 120000 | Timeout; the whole process tree is killed on expiry. |
encoding | string | no | auto | auto (detect) or force utf-8 / utf-16le / gbk. |
Example output (GBK output on Windows):
中文
[stderr]
... (if any stderr)
[encoding: gbk/utf-8 (auto-detected)]
[exit code: 0]
The last line is always [exit code: N]. When the output contains U+FFFD (�), an explicit warning line is appended instead of silently pretending the decode was right.
Positioning, stated plainly:
encoding_runis an independent new tool. It does not have the built-inbashtool's sandbox, approvals, or background-task support, and it executes with the same permissions as the harness process.
encoding_decode| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
text | string | yes | — | The garbled text to recover. |
from | string | no | auto | How to turn characters back into bytes: latin1 / utf-16le / auto. |
to | string | no | auto | Target decoding: gbk / utf-16le / auto. |
The classic mojibake path is from=latin1, to=gbk: GBK bytes were misread as latin1 (one character per byte), so the tool re-encodes each character to one byte and decodes the bytes as GBK.
With auto, the direction is guessed: embedded NULs → latin1 → utf-16le; wide characters → utf-16le → gbk; everything else → the classic latin1 → gbk.
Irreversible cases are reported, never faked: if the input already contains U+FFFD (�) — i.e. the shell already destroyed the bytes with an earlier mis-decode — the result is ok: false with an explicit note.
Note:
from=gbkis rejected with a clear explanation. Node.js ships a GBK decoder (TextDecoder) but no GBK encoder, and this plugin is zero-dependency, so re-encoding characters back to GBK bytes is not possible.to=gbkis fully supported.
Built-in bash shows ÖÐÎÄ where 中文 was expected (GBK bytes read as latin1):
encoding_decode with {"text": "ÖÐÎÄ"} → 中文 — done.encoding_run with {"command": "chcp 936 >nul & echo 中文"} → output 中文 plus [encoding: gbk (auto-detected)] [exit code: 0].The CLI subcommands keep their short names (run / decode_text) — they are a dev smoke runner, not the registered tool names:
node src/cli.js decode_text "ÖÐÎÄ" # -> 中文
node src/cli.js run "chcp 936 >nul & echo 中文" # GBK output, auto-decoded
node src/cli.js run "echo hello"
node src/cli.js detect D6D0CEC4 # -> detected: gbk / decoded: 中文
Zero dependencies — none at runtime, none for development; tests use only Node built-ins (node:test, node:assert). No npm install, no DSH, no build step needed:
node --test test/
Architecture:
dsh-encoding/
├── package.json # type: module, dsh.bundle.patch -> cordis.patch.yml
├── cordis.patch.yml # inserts one loader row: id "encoding", name "dsh-encoding"
├── src/index.js # Cordis entry (dependency-free), registers encoding_run + encoding_decode
├── src/encoding.js # pure functions: detect / decode / mojibake recovery
├── src/exec.js # spawn wrapper + run formatting (spawnImpl injectable)
├── src/cli.js # manual smoke runner (no DSH required)
└── test/ # node:test suites, mock child_process.spawn
src/encoding.js and src/exec.js import nothing from @deepseek-ai/*. src/index.js is dependency-free too: it emits the registry-ready tool shape directly (the same {type:'object', properties, required} + output.schema/render form that the official defineTool compiles to — locked by literal-schema assertions in test/index.test.js, and accepted by the live 0.2.0-rc.2 registry). This is deliberate — when a plugin is installed as a local checkout (dsh plugin add ./path, a pnpm link), the package lives outside the profile tree, and Node's ESM resolver cannot reach the host's @deepseek-ai/* packages from the checkout directory (the import dies with ERR_MODULE_NOT_FOUND, verified on 0.2.0-rc.2). Emitting the registry shape directly keeps the plugin working under npm, git, and local-link installs alike.
bash/pwsh tools, ctx.shell, or dsh-subprocess-local — those are out of scope by design (version-fragile core work). This plugin is a supplement, and says so.encoding_run.encoding when you know the answer.taskkill /T /F, POSIX: process-group SIGKILL).dsh-plugin — Lostforest7/dsh-encodingdsh-encoding (was unoccupied; published 0.1.0 → 0.2.0)npm publish --registry=https://registry.npmjs.org (China mirrors are read-only; always publish against the official registry)awesome-dsh-plugin list and the dsh-plugin.org market (optional, not yet done)dsh-encoding 是 DeepSeek Harness(dsh)的一个薄工具插件。在中文 Windows 上,老式 CLI、Git Bash/MSYS2、PowerShell 5.1 经常输出 GBK(cp936)或 UTF-16LE 字节,被 dsh 内置的 bash/pwsh 工具按 UTF-8 解码后变成乱码;而解码发生在不可插拔的核心服务(dsh-subprocess-local)里。本插件不去修补内置 bash,而是新增两个补充工具:
| 工具 | 作用 |
|---|---|
encoding_run | 自己 spawn 子进程、按原始字节收 stdout/stderr,自动识别 UTF-8 / UTF-16LE / GBK 并正确解码。 |
encoding_decode | 把已经乱码的文本(如 GBK 字节被当 latin1 误读)还原成正确中文。 |
0.2.0 破坏性变更:工具名由
run/decode_text改为encoding_run/encoding_decode(防撞名前缀)。0.1.0 已在 npm 标记废弃。
run / decode_text 工具。用干净的、未装插件的临时 profile(dsh --profile pmaudit --dump-config)验证:base 配置中没有任何同名工具行(内置工具是 tool-bash、tool-pwsh、tool-fs 等),官方 tools 参考文档也没有这两个工具。bash/pwsh 依然没有编码配置(shell 接口的 ShellExecRequest 无编码字段);在本环境用内置 pwsh 工具跑 GBK 输出命令,结果仍是乱码。本插件的立论前提成立。encoding_ 前缀,避免与内置或未来 dsh 工具撞名——注册表会拒绝同层重复名与保留名 run_code(官方 tools.md)。从 npm:
dsh plugin --profile <name> add dsh-encoding
从本地目录(本仓库):
dsh plugin --profile <name> add ./dsh-encoding
从 GitHub(纯 ESM JavaScript、无构建步骤,不需要 prepare 构建授权):
dsh plugin --profile <name> add github:Lostforest7/dsh-encoding
验证配置层已生效,然后启动:
dsh --profile <name> --dump-config # 能看到 "# == dsh-encoding" 层
dsh --profile <name>
encoding_run| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
command | string | 是 | — | 要执行的命令(Windows:cmd /d /s /c;POSIX:/bin/bash -c)。 |
workdir | string | 否 | — | 子进程工作目录。 |
timeoutMs | number | 否 | 120000 | 超时毫秒数,到期后杀掉整个进程树。 |
encoding | string | 否 | auto | auto 自动检测,或强制 utf-8 / utf-16le / gbk。 |
输出示例(Windows 上的 GBK 输出):
中文
[stderr]
...(如有 stderr)
[encoding: gbk/utf-8 (auto-detected)]
[exit code: 0]
最后一行固定是 [exit code: N]。当输出含 U+FFFD(�)时,会附加明确的警告行,而不是假装解码正确。
定位如实说明:
encoding_run是一个独立的新工具,不带内置bash工具的沙箱、审批与后台任务能力,并以 dsh 进程自身的权限执行命令。
encoding_decode| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
text | string | 是 | — | 要还原的乱码文本。 |
from | string | 否 | auto | 字符还原成字节的方式:latin1 / utf-16le / auto。 |
to | string | 否 | auto | 目标解码:gbk / utf-16le / auto。 |
经典"乱码还原"路径是 from=latin1, to=gbk:GBK 字节被当 latin1 误读(一个字符一个字节),工具把每个字符还原成一个字节,再按 GBK 解码。
auto 模式下自动判断误读方向:文本含 NUL → latin1 → utf-16le;含宽字符 → utf-16le → gbk;其余 → 经典 latin1 → gbk。
不可逆情况明确说明、不伪造结果:若输入里已经含 U+FFFD(�)——即字节早已在上游误解码中被毁掉——返回 ok: false 并附说明。
注意:
from=gbk会被明确拒绝并解释原因——Node.js 内置了 GBK 解码器(TextDecoder)但没有 GBK 编码器,本插件又坚持零依赖,因此无法把字符重新编码回 GBK 字节。to=gbk完全支持。
内置 bash 把 中文 显示成了 ÖÐÎÄ(GBK 字节被当 latin1 读):
encoding_decode,参数 {"text": "ÖÐÎÄ"} → 得到 中文,完成。encoding_run,参数 {"command": "chcp 936 >nul & echo 中文"} → 输出 中文,并附 [encoding: gbk (auto-detected)] [exit code: 0]。CLI 子命令保留短名(run / decode_text)——它们只是开发冒烟入口,不是注册的工具名:
node src/cli.js decode_text "ÖÐÎÄ" # -> 中文
node src/cli.js run "chcp 936 >nul & echo 中文" # GBK 输出自动解码
node src/cli.js run "echo hello"
node src/cli.js detect D6D0CEC4 # -> detected: gbk / decoded: 中文
零依赖——运行时与开发时都没有任何依赖;测试只用 Node 内置的 node:test / node:assert,无需 npm install、无需 DSH、无需构建:
node --test test/
结构:
dsh-encoding/
├── package.json # type: module,dsh.bundle.patch -> cordis.patch.yml
├── cordis.patch.yml # 插入一行 loader:id "encoding",name "dsh-encoding"
├── src/index.js # Cordis 入口(零依赖),注册 encoding_run 与 encoding_decode
├── src/encoding.js # 纯函数:检测 / 解码 / 乱码还原
├── src/exec.js # spawn 封装 + run 输出组装(spawnImpl 可注入)
├── src/cli.js # 手动冒烟(无需 DSH)
└── test/ # node:test 套件,mock child_process.spawn
src/encoding.js 与 src/exec.js 不 import 任何 @deepseek-ai/*;src/index.js 同样零依赖:它直接输出注册表形态的工具定义(与官方 defineTool 编译产物一致的 {type:'object', properties, required} + output.schema/render,由 test/index.test.js 的字面 schema 断言锁定,并已被 0.2.0-rc.2 真实注册表接受)。这是刻意的——当插件以本地目录方式安装(dsh plugin add ./path,即 pnpm link)时,包位于 profile 树之外,Node 的 ESM 解析无法从插件目录找到宿主的 @deepseek-ai/* 包(会以 ERR_MODULE_NOT_FOUND 失败,已在 0.2.0-rc.2 实测)。直接输出注册形态让插件在 npm、git、本地 link 三种安装方式下都能工作。
bash/pwsh、ctx.shell、dsh-subprocess-local——刻意超出范围(核心层改动版本脆弱)。本插件定位为"补充工具"。encoding_run 无沙箱集成、无审批、无后台任务。encoding 参数强制指定。taskkill /T /F;POSIX:进程组 SIGKILL)。dsh-plugin:Lostforest7/dsh-encodingdsh-encoding(确认未占用;已发布 0.1.0 → 0.2.0)npm publish --registry=https://registry.npmjs.org(国内镜像只读,务必用官方 registry 发布)awesome-dsh-plugin 列表与 dsh-plugin.org 市场(可选,尚未完成)MIT — see LICENSE.