DLT
Manifest validDLT (DeepSeek Light Tool) - a permanent DeepSeek Harness (DSH) plugin: per-turn CNY cost, DeepSeek account balance, native PDF/Word/Excel/CSV read-write tools and right-sidebar previews, a hardcoded c
DLT — DeepSeek Light Tool
DSH(DeepSeek Harness)的永久插件。装一次,重启后常驻,出现在「设置 → 插件清单」。
- npm:
dsh-light-tool→ https://www.npmjs.com/package/dsh-light-tool - 仓库:https://github.com/LLYlab/DLT
六个模块,每个都能在设置页或配置里单独关掉(见「运行期开关」):
| # | 模块 | 做什么 |
|---|---|---|
| 1 | 人民币成本 | 每轮对话结束,在用量胶囊旁边显示这一轮花了多少元(可点开看 token 明细与会话累计) |
| 2 | 账户余额 | 右下角常驻显示 DeepSeek 账户余额,可拖动、可点击强制刷新 |
| 3 | 文档工具 | 让模型直接读写 PDF / Word / Excel / CSV,不用再写脚本;PDF 支持「转 Word 改完转回来」的往返链 |
| 4 | 右栏预览 | 点工作区里的 .docx / .xlsx / .csv,右栏直接看(PDF 由产品自带渲染器负责) |
| 5 | 环境表 | 把本机编译/运行工具链的绝对路径写死,并注入系统提示,模型不再自己探测 |
| 6 | 直接执行 | dlt_run / dlt_build:按环境名直接跑程序、编译工程,不用拼 vcvarsall 命令行 |
安装(已经装好的话跳过)
从 npm 装(推荐)
dsh plugin --profile web add dsh-light-tool
然后在 C:\Users\L2959\.dsh\profiles\web\cordis.patch.yml 里插一行,并重启 DSH:
- insert:
- id: dlt
name: 'dsh-light-tool'
config:
defaultSolution: 'C:\path\to\your.sln' # dlt_build 不传 target 时用它
文档引擎依赖本机 Python 3.12 与几个包,见文末「依赖」;Office COM / Edge 用本机已装的程序。
从源码挂载(本机开发用)
源码:C:\Users\L2959\.dsh\plugins\dlt
挂载:给包建自己的 node_modules → junction 到 profile 的 node_modules → 在 patch 层插一行。
第 0 步(最容易漏):DSH 按 Node 规则从插件的真实路径解析裸包名,而真实路径在 plugins\ 下,
祖先目录里没有 @deepseek-ai。所以插件包必须自带一份 node_modules(dbs/topo 包里也有),
用 junction 指向 profile 里已装的同一版本,版本天然一致、且是同一个真实文件:
$pkg = 'C:\Users\L2959\.dsh\plugins\dlt\node_modules\@deepseek-ai'
$pro = 'C:\Users\L2959\.dsh\profiles\node_modules\@deepseek-ai'
New-Item -ItemType Directory -Force -Path $pkg | Out-Null
foreach ($n in 'schemastery','dsh-typert-protocol','dsh-tools','dsh-llm','dsh-util-values','cordis','cosmokit','dsh-token-meter') {
New-Item -ItemType Junction -Path (Join-Path $pkg $n) -Target (Join-Path $pro $n)
}
第 1 步:让 profile 能解析到 dlt 包
New-Item -ItemType Junction -Path "C:\Users\L2959\.dsh\profiles\node_modules\dsh-light-tool" `
-Target "C:\Users\L2959\.dsh\plugins\dlt"
第 2 步:C:\Users\L2959\.dsh\profiles\web\cordis.patch.yml 里加:
- insert:
- id: dlt
name: 'dsh-light-tool'
config:
defaultSolution: 'C:\path\to\your.sln' # dlt_build 不传 target 时用它
第 3 步:重启 DSH(Host 与新的 Client bundle 都在启动时装载;组合里挂载的永久插件不需要 GUI 批准,那是动态插件 cordis_run 的流程)。
一步验证装载是否成功(不需要重启,用假服务把插件跑起来):
cd C:\Users\L2959\.dsh\profiles\web
node C:\Users\L2959\.dsh\plugins\dlt\tests\host.test.mjs
运行期开关(设置 → DLT 管理器)
设置里有一页 DLT 管理器:一个总开关 + 六个分模块开关(每轮成本 / 账户余额 / 文档工具 / 右栏预览 / 环境表 / 执行与编译)。
- 即时生效:改完立刻装卸 —— 总开关关掉,DLT 的 6 个模型工具(
dlt_env/dlt_run/dlt_build/dlt_doc_read/dlt_doc_write/dlt_doc_convert)与系统提示注入当场卸下,界面上的成本小签、余额卡、右栏预览当场撤下;端点对调用返回{ok:false, disabled:true}(status仍可用,但不再联网抓定价)。不用改 yml、不用重启。 - 持久化:状态写在
<DSH_HOME>/dlt/switch.json(默认C:\Users\L2959\.dsh\dlt\switch.json),重启后照旧;文件坏了/缺失就退回下面的config默认值并把原因显示在设置页里。 - 总开关关掉后,设置页里那个总开关仍然在 —— 它是把 DLT 重新打开的唯一入口。
- 端点:
switchGet(读开关状态)·switchSet({enabled?, modules?})(局部改开关)。
与
cordis.patch.yml的关系:patch 里的config只提供首次运行的默认值;一旦在设置页动过开关,就以switch.json为准(UI 上的选择不会被 patch 覆盖)。
配置项(cordis.patch.yml 的 config)
| 键 | 默认 | 说明 |
|---|---|---|
| enabled | true | 总开关默认值(只影响没有 switch.json 时;运行期开关见上一节) |
| cost / balance / documents / preview / environment / run | true | 六个模块的开关默认值(同上) |
| pythonEnv | python312 | 文档引擎用的解释器(见环境表) |
| cacheDir | <DSH_HOME>/dlt | 定价与余额快照目录 |
| pricingMaxAgeMs | 86400000 | 定价快照最长使用时间,超过就重抓官网 |
| balanceApiBase | https://api.deepseek.com | 余额接口基址 |
| balanceApiKeyEnv | DEEPSEEK_API_KEY | 凭据引用名(先走凭据 seam,再退回同名环境变量) |
| balanceCacheMs | 60000 | 余额缓存时长,浏览器按这个节奏轮询 |
| docTimeoutMs / runTimeoutMs | 300000 / 120000 | 默认超时 |
| maxOutputBytes | 262144 | 单次执行捕获的输出上限(超出保留首尾) |
| promptSection | true | 是否把环境表注入系统提示 |
| defaultSolution | 空 | dlt_build 的默认解决方案 |
| defaultConfiguration / defaultPlatform | Debug / x64 | dlt_build 默认值 |
模型工具
dlt_env— 看环境表(env=<id>看细节)。注意:环境表里的路径是硬编码的,换机器要改lib/core.js的ENVIRONMENTS。dlt_run(env, program, args, cwd, timeoutMs, stdin)— 在指定环境里执行程序,回 stdout/stderr/退出码。env=msvc-x64会先注入 vcvarsall,于是cl/link直接可用。dlt_build(target?, configuration?, platform?, rebuild?)— MSBuild 一条龙。dlt_doc_read(path, mode?, pages?, sheets?, range?, formulas?, maxRows?)— 读 PDF(逐页文本)/ Word(段落+表格)/ Excel(各表行列)/ CSV。dlt_doc_write(path, action?, ops?, spec?, out?, chain?, replacements?)— 改或建文档。- PDF
ops:delete_pages/extract/rotate/merge/insert_pdf/watermark/replace_text/set_metadata - Word
ops:replace_text/set_paragraph/add_paragraph/delete_paragraph/add_table/set_cell/add_table_row - Excel
ops:set_cell/set_range/append_row/insert_row/delete_row/add_sheet/rename_sheet/delete_sheet/set_number_format/set_column_width/set_style - PDF
chain=word:PDF →(pdf2docx)→ docx →(用 Word op 改)→ PDF(Word COM) - PDF
chain=html:PDF →(pymupdf)→ HTML →(文本替换)→ PDF(Edge 无头打印)
- PDF
dlt_doc_convert(path, to, ...)—to=docx|html(从 PDF)、to=pdf(从 Word/Excel/HTML)、to=png(PDF 某页出图,之后用read_image看)。
写操作一律先备份(同目录 .bak-YYYYmmdd-HHMMSS.<ext>);chain 往返链会额外备份原 PDF。
端点(供右栏 UI 调用)
connection.rpc.call('/api', 'dlt/<method>', { args: { args } }):
status · balance · cost({sessionId}) · office({path}) · pricingInfo({force}) · envs · switchGet · switchSet({enabled?, modules?})
依赖(本机已装,换机器需重装)
Python 3.12(C:\Users\L2959\AppData\Local\Programs\Python\Python312\python.exe):
pip install pymupdf pypdf python-docx openpyxl pdf2docx pywin32
国内网络下
pdf2docx会拖 opencv(约 40MB)而反复卡住,用镜像快很多:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pdf2docx另外 pdf2docx 缺失时 PDF→Word 不会失败:引擎会退回内置实现 (pymupdf 取文本块/表格 + python-docx 落盘),保真度略低但「PDF → 改字 → 转回 PDF」照样能跑。
Office(Word/Excel COM 导出 PDF)与 Edge(HTML→PDF)都用本机已装的程序。
测试
四套,全部可重复运行:
# 1) 文档引擎(Python CLI 层:创建/读取/编辑/渲染/转换/往返链)
node C:\Users\L2959\.dsh\plugins\dlt\tests\doc-engine.test.mjs
# 2) 核心层(环境表 / 定价抓取解析 / 高峰判定 / 成本计算 / MSVC 真编译 / Office COM / Edge)
node C:\Users\L2959\.dsh\plugins\dlt\tests\core.test.mjs
# 3) Host 半区(真 Cordis Context 装载插件,调它注册的工具与端点 + 运行期开关)
cd C:\Users\L2959\.dsh\profiles\web
node C:\Users\L2959\.dsh\plugins\dlt\tests\host.test.mjs
# 4) 开关持久层(纯 Node,不用起 Cordis:默认值 / 合并 / 落盘读回 / 文件损坏降级)
node C:\Users\L2959\.dsh\plugins\dlt\tests\switch.test.mjs
第 3 套必须从 profile 目录运行:ESM 按导入方的真实路径解析裸包名,只有从 profile 里
import('dsh-light-tool') 才能用上 junction;而且它会真起 cl.exe / Office COM / 联网抓价,
别在受限沙箱里跑(子进程管道会被拦,报 spawn EPERM)。
当前状态:doc-engine 22/22,core 28/28,host 29/29(含运行期开关 6 条),switch 7/7。
覆盖到的关键断言:flash/pro 六档单价与官网一致;高峰/空闲 9 个时间边界; 1M 未命中 + 1M 输出 @ 空闲恰好 5 元;旧模型名映射到 flash;未结算轮次不编造数据; MSVC 真正编译出 exe 并运行;超时能杀掉进程树;PDF↔Word 与 PDF↔HTML 两条往返链的文本可验证。
实现要点与踩过的坑(改代码前请先读)
- 工具不能直接回图片块。
ImageBlock需要 attachment 服务托管字节,且当前适配器声明为纯文本输出。所以dlt_doc_convert to=png是写文件 + 返回路径,再由模型调read_image去看。 - PowerShell 只有 5.1,且它按「无 BOM 就 ANSI」解码脚本。
py/dlt_office.ps1必须保存为带 BOM 的 UTF-8,否则中文注释会撑坏语法。改这个文件后务必确认前 3 字节是EF BB BF。 - Office COM 必须用 pywin32 的
DispatchEx,不要用 PowerShell 的New-Object -ComObject。 后者依赖 Office PIA 类型库,本机会TYPE_E_CANTLOADLIBRARY (0x80029C4A);DispatchEx走 IDispatch,并且强制新开独立进程 —— 这条更重要:依附用户正在用的 Word/Excel 会改到用户的东西。早期版本依附时设置了Visible=$false,直接把用户开着的 Word 窗口藏掉了。现在的口径是:只碰自己新建的实例;app.Quit()之后还会按「转换前后新增的 PID」做一次兜底清理,绝不碰别人的进程。 - 成本数据复用了产品自己的折叠逻辑。 Host 用
ctx.sessionQuery.readSession(id)取原始事件,按turn/start…turn/end分组,再把这些事件交给 dsh-token-meter 自带的deriveTurnTokenUsage(按文件 URL 动态 import)折叠 —— 这样算出来的 token 与 UI 用量胶囊完全一致,不会因为自己重写解析而对不上。取不到就整轮不显示,不猜。 - 高峰/空闲按「请求时刻」判定(北京时间 周一至周五 9:00–12:00、14:00–18:00),单价来自官网中文定价页,本地缓存每天刷新,抓不到就用旧快照并在 UI 上标注。
- 旧模型名会映射到计费模型:官网明确
deepseek-v4-flash/deepseek-v4-flash-vision-exp已下线、由 V4.1-Flash 服务并按 Flash 计费,所以别名表把它们都映射到deepseek-flash。 cacheWrite不单独计价(官网没有缓存写入档),只报数并提示已按未命中输入口径计入。formulas=false读 Excel 缓存值时,若文件是由 openpyxl 生成且从未被 Excel 打开过,公式单元格会返回null—— 这是 openpyxl 的既有行为,不是 bug。- 中文水印会嵌入约 1.7MB 的 CJK 字体,所以水印字体按内容选择:纯 ASCII 用内置
helv,含中文才用china-s。 - 改编译环境表只需改
lib/core.js顶部的ENVIRONMENTS;msvc类环境会自动生成一个临时.cmd(chcp 65001+call vcvarsall)来注入环境,避免命令行转义地狱。 - 相对路径按会话工作区解析。 工具通过
exec.agent.session.meta.cwd拿到当前会话的工作区根,所以模型写docs/a.docx能命中;预览端点则从dsh-resource://file/session/<sessionId>/<path>地址里取出 sessionId 再反查 cwd。绝对路径原样使用,没有会话信息才退回进程 cwd。 dsh-token-meter不是 dlt 的依赖,是动态解析的。 依次尝试:直接当包解析 → 从@deepseek-ai/cordis的位置推出同层的dsh-token-meter→createRequire。第二条是关键:它不依赖 dlt 自己的依赖声明,而且解析到的是同一个真实文件(Node 按 realpath 缓存模块),所以不会出现「两份 token-meter、两份状态」。ctx.plugin()返回的是 Fiber,不是 thenable。await ctx.plugin(...)不会等激活,必须await fiber.await();写测试时容易在这里踩空(表现为「插件好像没加载」)。同理ctx.get()返回的是getTraceable包过的代理,不要用===比较身份。- 运行期开关为什么落 JSON 文件,而不是宿主的 storage 域:DLT 的
node_modules/@deepseek-ai是 8 个 junction(只链它真正 import 的包),里面没有dsh-storage-domain;而且 storage 域用 zod schema,DLT 这边是 schemastery。所以开关落<DSH_HOME>/dlt/switch.json(与定价快照同目录):纯 Node 读写、坏了/缺了都能降级回config默认值,用户也能手改。 - 关总开关必须真的把工具卸下来。
dsh-tools的tools.register(def)返回 disposer(内部走ctx.effect),dsh-system-prompt的section(...)同理。所以DltService.applyRuntime()逐个登记这些 disposer、unloadRuntime()逐个撤下;不撤的话模型依然看得见dlt_run等工具(只是调用会失败),那就是「关了没关干净」。改了开关还要顺带改系统提示:提示里不能再教模型去调已经关掉的工具。
文件
plugins/dlt/
package.json # main=lib/index.js, exports ./client, dsh.client.platform=web
CHANGELOG.md # 版本变更(随 npm 包分发,也是 GitHub Release 的说明)
LICENSE # MIT
publish.ps1 # 一键发布(升版本 → commit/tag → push → npm publish → gh release)
lib/index.js # Host 半区(Cordis 插件:工具 + typert 端点 + 系统提示段 + 运行期开关)
lib/core.js # 纯逻辑:环境表 / 定价抓取解析 / 成本计算 / 进程执行器 / Office 桥
lib/switch.js # 运行期开关的持久层(<DSH_HOME>/dlt/switch.json)
lib/client.js # Client 半区(ModuleLoader bundle:成本小签 / 余额 / 文档预览 / DLT 管理器设置页)
py/dlt_docs.py # 文档引擎(pymupdf / pypdf / python-docx / openpyxl / pdf2docx / pywin32)
py/dlt_office.ps1 # Office COM 兜底桥(带 BOM 的 UTF-8!)
tests/doc-engine.test.mjs # 文档引擎回归测试
tests/core.test.mjs # 核心层回归测试(含真编译、真抓价)
tests/host.test.mjs # Host 半区回归测试(真 Cordis 上下文装载 + 运行期开关)
tests/switch.test.mjs # 开关持久层单测
node_modules/@deepseek-ai/* # 8 个 junction → profile 里同一版本的包(仅源码挂载方式需要,见安装第 0 步)
Similar plugins
by ZSeven-W
DeepSeek Harness (DSH) plugin: a read-only ledger for the plugins you already have installed — a capability inventory with file:line evidence, declared-vs-detected reconciliation, cross-profile versio
★ 24
↓ 44/wk
MIT
JavaScript
Sep 11, 2026
dsh plugin --profile web add @zseven-w/dsh-harborby zhtx2024
PDF parsing toolkit for DeepSeek Harness: pdf_info, pdf_extract_text, pdf_render_page with hybrid pdfjs/built-in engines and system-font rendering for non-embedded CJK PDFs.
★ 3
↓ 270/wk
MIT
JavaScript
Aug 20, 2026
dsh plugin --profile web add @zhtx2026/dsh-pdfby JoukoPuro
一个 DeepSeek Harness(DSH)插件: 在 Web 输入框的工具行中添加一个 ✨ 图标按钮。点击后选择打磨风格,已接入的大模型 会把你草稿中的提示词改写得更专业、更易被 AI 理解 。A DeepSeek Harness plugin: icon-only composer button that rewrites your prompt via the connected LLM
★ 4
↓ 87/wk
MIT
JavaScript
Aug 14, 2026
dsh plugin --profile web add dsh-prompt-polishby poiuyjie
DSH plugin: Auto-convert images to text for pure-text LLMs (DeepSeek etc.) via any vision model. No need to switch your main model.
★ 13
MIT
JavaScript
Sep 9, 2026
dsh plugin --profile web add dsh-vision-opencodeby Aik358
DSH Literature 文献侧窗插件:在 DeepSeek Harness 侧边栏识别 DOI/arXiv/标题、抓取元数据与全文、写入本地文献库或导出目录,内置 PDF 阅读器。
★ 4
↓ 888/wk
MIT
JavaScript
Sep 8, 2026
dsh plugin --profile web add @a9i5k4/dsh-literatureAdds a structured TextIn xParse tool and document parsing skill to DeepSeek Harness, supporting document parsing, cached-content navigation and durable multi-document tasks, with AppKey or Device OAut
★ 0
↓ 97/wk
dsh plugin --profile web add @intsig-xparse/dsh-xparse