DeepSeek Harness(DSH)实用小插件合集。三个插件各自独立、零依赖或近零依赖,按需取用:
| 插件 | 文件 | 作用 |
|---|---|---|
| ytdlp | plugins/ytdlp.mjs + plugins/ytdlp_cli.py |
视频/音频查询与下载工具(yt-dlp 桥接) |
| reasoning-effort-auto | plugins/reasoning-effort-auto.mjs |
模型推理强度(reasoning effort)跨 Provider 自动适配 |
| preflight | plugins/preflight.mjs |
插件源码预检:BOM / UTF-8 / mojibake / 语法检查 |
三个插件都通过 cordis.patch.yml 挂载,注册的工具对所有会话(Web GUI、飞书/Lark 等)可用。
DSH 会话中经常需要「查一下这个视频是什么 / 下载这段视频发给用户」,但:
- 让模型直接拼 shell 命令调 yt-dlp 非常危险:URL 与格式串会经过 shell 命令行,存在注入风险, 且参数一多就容易出错;
- yt-dlp 输出大、格式杂,原始 stdout 灌给模型既浪费 token 又难以结构化消费;
- 下载目标目录缺少边界校验,模型可能把文件写到任意位置。
注册两个工具(全会话可用):
video_info:不下载,仅查询链接元信息——标题、上传者、时长、清晰度(最高分辨率)、 可用格式数、播放列表条目数等。下载前先确认链接有效与内容。video_download:下载视频或提取音频,返回本地文件路径(可与飞书[lark-file:]标记 配合直接发送给用户)。支持播放列表、音频提取(mp3/m4a/opus)、cookies、代理。
安全设计:
- stdin/stdout JSON 桥接:URL、格式串、输出路径一律不经过 shell 命令行(无注入面);
- 路径越界校验:
output_dir必须落在下载根目录内,否则拒绝; - 格式白名单化:
format拒绝以-开头的选项串、拒绝超长输入; - URL 校验:仅接受 http/https,长度上限 8KB;
- 支持 1000+ 站点(YouTube、Bilibili 等,由 yt-dlp 项目提供)。
- insert:
- id: ytdlp
name: ./plugins/ytdlp.mjs
config:
# cliPath: 可选,ytdlp_cli.py 的绝对路径(默认:与插件同目录的 ytdlp_cli.py)
# pythonBin: 可选,Python 解释器(默认 "python")
# downloadDir: 可选,下载根目录;绝对路径原样使用,
# 相对路径相对工作目录解析(默认 "downloads")把 ytdlp.mjs 与 ytdlp_cli.py 放在同一目录(ytdlp_cli.py 会被自动找到)。依赖:Python 3 +
yt-dlp(pip install yt-dlp);音频提取与格式合并需要 ffmpeg(缺省时纯音频按原始流下载)。
video_download 返回 { ok, filepath, title, duration, download_dir, ... },可直接用
[lark-file: <filepath>] 发到飞书会话。
DSH 在多个模型供应商之间切换时,各家的「推理强度」档位并不一致,例如:
- DeepSeek 路由(
deepseek-v4-flash):支持off | high | max - MiMo Token Plan 路由(
mimo-*):只支持off | minimal | low | medium | high
若某个会话/插件固定请求 max(例如飞书任务会话默认请求最高强度),切到 MiMo 路由后请求会
直接失败:UNSUPPORTED_REASONING_EFFORT。用户只切换了模型,会话却创建不出来。
注册一个宿主服务 ctx.reasoningEffortAuto.clamp(selection, desired):
- 查询目标 provider/model 实际支持的能力(
ctx.llm.resolveModelInfo), - 若
desired已被支持则原样返回;否则向下收敛到支持列表里最强的档位 (如max → high), - 能力查询失败时保持原值返回——宁可让下游按原档位请求,也不因本服务导致会话创建失败。
任何插件(如 lark-channel)在组合新会话的模型选择时调用 clamp;本插件未挂载时请求原样透传。
- insert:
- id: reasoning-effort-auto
name: ./plugins/reasoning-effort-auto.mjs依赖:DSH 宿主的 llm 服务(ctx.llm.resolveModelInfo)。需在依赖它的插件(如
lark-channel)之前挂载。
Windows 上编辑/部署 DSH 插件文件时有一套经典的「编码三连坑」,会直接导致 DSH 启动失败:
- PowerShell 5.1 的
Get-Content默认按 ANSI/GBK 读 UTF-8 文件 → 内容变成乱码; Set-Content -Encoding UTF8写出带 BOM 的文件(Node ESM 通常能容忍 BOM,但叠加 第 1 条时内容已经坏了);- 两者叠加 → 插件文件变成「带 BOM + 内容错乱」(mojibake)→ DSH 启动时
SyntaxError, 日志却可能一片空白,静默宕机、无人知道为什么。
双模式复用:
- CLI:
node preflight.mjs [--fix] [--no-syntax] <file...>— 检查并报告 (--fix自动剥离 BOM);exit 0 = 全部通过 / 已修复,exit 1 = 存在不可自动修复的问题, 调用方应拒绝启动。输出为纯 ASCII JSON,避免 PowerShell 按 ANSI 读取输出时二次乱码。 - import:
checkText(text, { name })(检查字符串源码)、checkFile(path, { fix, syntax })(检查单个文件)、checkFiles(paths, opts)(批量检查),供其他工具(如 dsh-sim-restart-tester)复用。
检查项:
| 检查项 | 判定 |
|---|---|
| UTF-8 BOM(EF BB BF) | 检出即告警;--fix 自动剥离 |
| 非法 UTF-8(GBK/ANSI 或损坏) | 拒绝(启动必失败) |
| 解码替换符 U+FFFD | 拒绝 |
| GBK 二次编码(mojibake 特征字) | 命中特征字即拒绝,提示用 UTF-8 重新保存 |
| 语法检查 | .mjs / .js 执行 node --check,失败给出前 3 行错误 |
无需挂载为插件(无运行时副作用),适合作为启动前预检脚本或集成进其他插件:
node preflight.mjs --fix plugins/*.mjs
dsh-utility-plugins/
├── plugins/
│ ├── ytdlp.mjs 视频下载工具(宿主插件)
│ ├── ytdlp_cli.py yt-dlp 桥接 CLI(stdin JSON -> stdout JSON)
│ ├── reasoning-effort-auto.mjs 推理强度适配服务(宿主插件)
│ └── preflight.mjs 源码预检模块(CLI + import 双模式)
├── LICENSE
├── package.json
└── README.md
MIT License,见 LICENSE。