DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
R

dsh-runtime-tuning

Runtime Tuning

Tuning plugins inside DeepSeek Harness: tool execution, file tools, sandbox and credential protection, and chat UI fixes, each checked against real session data.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:herenfor/dsh-runtime-tuning#b3be48818efc24d59c183d58233c7d25ba10d737
READMECompatibilityVersions

Compatibility and provenance

Runtime Tuning is published as dsh-runtime-tuning and currently resolves to version 0.2.7. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
github
Registry updated
11/4/2026

Versions

0.2.7stable
11/4/2026
0.2.5stable
11/3/2026
0.2.4stable
11/2/2026
Show 5 more versionsCollapse versions
0.2.3stable
11/1/2026
0.2.1stable
10/31/2026
0.2.0stable
10/30/2026
0.1.1stable
10/30/2026
0.1.0stable
10/29/2026

Related plugins

Loading related plugins…

Latest
0.2.7
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
any
License
MIT
Source
github
GitHub
★ 1
Weekly downloads
0
Last push
11/4/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in developer-tools.

Web App@deepseek-ai/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)Sdk Minimal@deepseek-ai/dsh-sdk-minimalThe standalone minimal SDK profile bundle: JSON-RPC, one DeepSeek adapter, persistent shell, and JSONL sessionsSdk App@deepseek-ai/dsh-sdk-appThe dsh SDK profile bundle: stdio JSON-RPC serving and process lifecycle over dsh-baseExperimental Inspector@deepseek-ai/dsh-experimental-inspectorExperimental cross-realm CDP hub for Host debugging and Client Runtime inspection

README

DSH Runtime Tuning

DeepSeek Harness(DSH)主程序内部的调优插件:工具执行、文件工具、沙箱与凭据保护、聊天界面的修复和优化,每一项都用真实会话数据验证。任务提醒、托盘启动和崩溃防护在 dsh-sentinel。

这里既是一组可以安装的 DSH 插件,也是这个过程的记录。随着分析推进,插件会不断增加。

起点:一份 9.7 小时的会话

我把自己日常使用 DSH 的一份会话导出来,按事件逐条统计。这份会话有 119 轮对话、2347 次工具调用,跨度 9.7 小时,内容主要是一个项目的反复发行(测试、编译、归档、上传)。

时间大致花在这些地方:

去处时间备注
模型生成约 4.3 小时每步中位数约 6 秒
阻塞式等待后台任务(job_output wait: true)约 100 分钟152 次,最长一次 240 秒
等人审批约 58 分钟24 次,最长一次 44.7 分钟
提问后等人回答约 79 分钟这段时间模型什么也做不了
前台 sleep约 20 分钟33 次,比如 sleep 90; echo waited

几个值得注意的现象:

  • 有工具调用的步骤里,87% 只调用了一个工具。每多一步,就多一次重读上下文和生成。
  • 同一个后台任务被反复查询,最多一个查了 13 次。
  • 模型会从文件里 grep 出 GitHub 令牌,再用 curl 调 API,令牌因此出现在命令行和日志里。

发现一:机制都在,只是没人强制

读了 DSH 的源码之后发现,DSH 其实已经做得不错:

  • 后台任务结束时会通知模型:模型忙时插进下一步,空闲时直接开启新的一轮;
  • 前台命令超时后不会被杀掉,而是转到后台;
  • 系统提示词里明确写了"不要轮询、不要 sleep"。

问题在于模型并不总是照做:它还是会 wait: true 加上 120 到 600 秒的超时,或者直接前台 sleep 90。等待期间整轮对话被占住,用户插话只能排队。

所以第一个插件 wait-guard 做的事很简单:在工具执行前强制执行这条规则,拦截前台长 sleep 和顶层 agent 的长时间阻塞等待,并告诉模型应该怎么做。

装上第一版之后,同一个发行流程的对比:

改动前 A改动前 B装插件后
对话被占住22.1 分19.6 分4.6 分
阻塞等待13.0 分15.2 分0.2 分
自动唤醒0 次0 次3 次,都在任务结束的同一秒

要说清楚一点:收益是"不占住对话",不是"更快"。这次总耗时也变短了,但主要是因为那次编译本身快。以前的阻塞等待在任务结束时也会立刻返回,并没有"白等"。真正的变化是编译期间用户随时可以插话,而不是对着一个卡住的对话。

发现二:通知没来怎么办

让模型结束一轮去等通知,就要回答一个问题:如果任务卡死,通知永远不来呢?

wait-guard 为此加了一个 task_status 工具。模型在一轮的最后声明自己是 done、waiting(在等后台任务,附上预计时间)还是 asking(在等用户回答)。声明 waiting 的一轮正常结束后,插件开始计时;超过两倍预计时间还没有新一轮,就主动唤醒模型去检查。

几个边界是刻意设计的:

  • 最多连续唤醒 2 次,用户发消息后重新计数,避免无人值守时无限循环;
  • 用户按停止结束的一轮不计时:用户叫停的事,插件不应该再拉起来;
  • 实测:一个 sleep 300 的任务,模型预计 1 分钟,插件在第 2 分钟准时唤醒。模型看了一眼输出,重新声明预计 3 分钟;任务结束后模型被正常唤醒并声明完成,兜底计时随之取消。

后来在一次真实发行里发现,模型并不总会声明:它把编译放进后台就直接结束了一轮,没有调 task_status,兜底计时也就没开。于是加了一道硬保底:只要一轮结束时后台还有任务在跑,又没有声明 waiting,就按默认 30 分钟计时,到点唤醒模型去检查。开发服务器这类故意留着的任务,模型可以在 services 里列出来,它们不计时。下一节会讲到,这道硬保底最后成了主角。

发现三:提问会把模型卡住

ask_user_question 默认是阻塞的:问出去之后,在用户回答之前,模型什么也做不了,哪怕手上还有不依赖这个回答的事。

DSH 其实已经实现了非阻塞的 timed 模式(超时返回 pending,用户的回答之后作为插话送进来),但默认关闭,而且这个工具嵌在 agent preset 内部,用户的配置补丁改不到它。具体的复现过程我发在了 DSH 讨论 #8547。

插件 ask-nonblocking 的绕法是:在每个顶层 agent 创建时,用宿主里同一份官方模块在 agent 自己的作用域里注册一个 timed 版本,遮蔽掉 preset 里的阻塞版。实测提问约 1 秒后放行,72 秒后的回答作为新的一轮送了进来。

这个绕法依赖 DSH 的内部接口,所以失败时只写日志、退回阻塞版,不影响任务。

发现四:令牌是模型自己要来的

同一份会话里,同一个 GitHub 令牌出现在 73 条命令(共 83 处)和 74 条模型回复里。往回找它第一次出现的地方,是模型用 ask_user_question 让用户把令牌贴进来,还承诺"会存到权限 0600 的本地文件里"。可令牌一旦作为回答进入对话,就已经在上下文里了:之后每次请求都会把它发给模型服务商,它也会永久留在会话记录里,模型再把它直接写进 curl -H "Authorization: …"。

插件 secret-guard 分三道防线:

  • 拒绝向用户索要令牌、密码、API key 的提问,引导改用已经登录好的 gh,或者请用户自己运行 gh auth login。这一道最关键:在非阻塞提问下,用户迟到的回答是以插话送进来的,后面的打码管不到;
  • 拒绝参数里带完整令牌的工具调用,以及 gh auth token;
  • 工具结果交给模型之前,把其中格式明确的凭据替换成 [REDACTED:…]。

管不到的是用户直接在聊天框里粘贴的令牌:那不是工具结果。

发现五:别靠模型自己报告状态

task_status 的设计前提是模型会照做。数据说明它不会:

会话调用 task_status 的轮次备注
日常使用的长会话0 / 9工具和提示词都在系统提示里,模型照样不调
新会话3 / 3但每次都多一步:先调 task_status,再请求一次模型把答复重复一遍
新会话,加上"答复和声明写在同一条回复里"1 / 3那一次确实省了一步
新会话,换成提示词统一的专用预设2 / 3两次都单独占一步

长会话里一次都不调,可能是因为它前面一百多轮都没有调用的先例,模型更倾向于沿用自己历史里的做法,而不是系统提示里的一句话。另外,官方提示词要求"给最终答复前收齐所有后台任务",和"任务还在跑时可以结束这一轮"互相矛盾。

试过的几种办法:

  • 让 task_status 和最终答复写在同一条回复里时直接结束这一轮(DSH 的 concludeTurn),省掉重复答复的那一步。机制有效,但模型经常不这么写;而且 DSH 的聊天界面只把不带工具调用的最后一步当作回答,这样结束的一轮,答复会被收进折叠里,用户得点开才看得到。所以插件包带了一个聊天界面的小修复(chat-answer-fix),修复生效时才这样结束;
  • 做一个专用预设,把两段矛盾的提示合成一段。提示改写生效了,模型的行为没有明显变化,而且预设只对新会话有效,所以没有放进插件包;
  • 最后的做法是换个思路:状态由 runtime 按事实判断,不靠模型声明。一轮结束时还有本次请求启动的后台任务在跑,就是在等;有提问没回答,就是在等用户。硬保底和 dsh-task-notify 的完成通知都按这个判断。task_status 降为可选,只在任务会跑超过 30 分钟、或者要标记服务时才需要。

验证:同样启动一个 60 秒的后台任务,模型没有调用 task_status,结束那一轮没有发通知,硬保底照常计时;任务结束、模型回复输出后,才收到一次"本轮已完成"。

发现六:沙箱里看不见的东西

一次真实任务里(主代理加 3 个子代理做批量检索),模型在命令里用 ps 找自己启动的后台扫描,没找到,就以为扫描已经退出,重新跑了一遍。旧的那个其实还活着,空转了将近 40 分钟,直到硬保底在最后一轮结束 30 分钟后把模型唤醒,模型才用 job_list 和 job_kill 两步处理掉。

原因在 DSH 的 Linux 沙箱:每条命令都单独起一个 bwrap,带 --unshare-pid 和 --tmpfs /tmp。所以:

  • 命令里的 ps 只能看到这条命令自己,看不到任何后台任务;
  • 上一条命令写进 /tmp 的文件,下一条就没了。翻了 90 个会话,有 25 个出现过这种报错,共 54 次。

模型更相信自己看到的 ps,而不是 runtime 的任务表。所以这次的思路是:把任务表里的事实放到模型眼前,并要求它对每个后台任务做出选择,有点像"写文件之前必须先读":

  • 收尾清点:一轮结束时还有没认领的后台任务,1 秒后唤醒一次,列出任务 id、已运行时间和命令,要求逐个选择:在等、是服务,还是 job_kill;
  • 任务事实:查进程、重复启动同一个脚本、没有新输出还在查时,在结果后面附上任务表里的事实;
  • session-tmp:把每条命令的 --tmpfs /tmp 换成同一个对话专用的目录,子代理跟着父对话走。别的对话和宿主的 /tmp 仍然看不到。

ps 看不到后台任务这件事本身没有改:要让同一个对话的命令共用一个进程命名空间,需要改 DSH 核心(非特权的 bwrap 不能加入已有的 PID 命名空间),插件做不到。

验证(DSH 0.2.1-rc.5):模型执行 ps 后,回复里写的是"每个命令在独立沙箱中运行,看不到其他后台任务;任务表中该任务仍在运行";故意不表态就结束一轮,1 秒后被唤醒,回复一句话交代了任务的去向;子代理能读到父对话写进 /tmp 的文件。第一次实测还发现,附加给模型的上下文必须是一条完整的消息,传字符串会让这一轮报错中断,单元测试没有测出来。

顺带:时间到底花在哪

为了判断"一步只调一个工具"值不值得优化,用 4 个小任务(大量独立读取、发行前检查、先找后读、后台任务加并行工作)在 standard 和 ptc 两种预设下各跑一遍,共 8 次:

去处占比
等模型开始出字44%
模型出字52%
工具执行4%

工具本身很快,时间几乎都在模型请求上。少一步只省一次"等开始出字",正常时约 2 秒,服务端慢的时候约 8 秒。所以只在提示词里加了一句"互不依赖的读取、检查、修改放进同一条回复并行调用",不再单独为它写机制。

DSH 自带的 ptc 预设(模型写脚本、在脚本里调工具)在这些任务上总步数从 17 步降到 15 步,但被占住的时间和输入 token 反而略多,因为脚本跑完模型还是要再请求一次去读结果。它适合大量重复查询、需要在中间过滤结果的任务,日常任务里看不出收益。插件的钩子在 ptc 下照样生效:脚本里调用的每个工具都会经过 DSH 的执行前后钩子。

还在看的问题

问题数据状态
等人审批时没有提醒,人不在就一直停着58 分钟,最长一次 44.7 分钟已在 dsh-task-notify(现为 dsh-sentinel)里加上"需要审批 / 需要你回答"的提醒
令牌进入上下文1 个令牌,73 条命令、74 条回复secret-guard
前台命令设了过长的超时139 条前台命令超时设到 5 分钟以上,但真正跑超过 1 分钟的只有 2 条一开始以为插件只能拒绝、不能改参数,拒绝 139 次多花的时间比省下的还多,所以没做;后来发现 tools/execute 阶段可以改参数,改成了静默封顶到 30 秒(到点转入后台),不多花一步
一步只调一个工具87% 的步骤只加了一句提示:每步省的只是一次请求延迟,收益小(见上一节)
反复 tail 日志、重读同一文件同一文档同轮最多重读 7 次收益同上,暂缓
模型响应变慢某天首字延迟中位数从 1.2 秒升到 8.3 秒,出字速度不变服务端问题,插件能做的只有减少请求次数
回答输出一个词后不再出内容,界面一直停在"思考"服务端降级时一次连续 10 分钟,期间每 10 秒左右一个心跳官方的流空闲超时把心跳当成活动,永远不触发,重试也就不启动。stream-stall 按"没有新内容"判断,断开后官方自动重试
审批会卡住整个 step—DSH 核心行为,插件做不到(#8916)
插话打断不了正在运行的工具插话排队最长 128 秒DSH 核心行为,插件做不到(#11005)

目前包含的插件

插件作用
wait-guard拦截前台长 sleep 和长时间阻塞等待;一轮结束时要求模型对还在跑的后台任务逐个表态,没回报时兜底唤醒;在结果后附上任务表里的事实(沙箱里 ps 看不到的后台任务、重复启动、无效轮询);可选的 task_status 工具
ask-nonblocking让 ask_user_question 问完不阻塞
secret-guard不让令牌进入模型的上下文
secret-files沙箱里的命令和文件工具都读不到凭据文件(云服务密钥、DSH 的 API key 等)
session-tmpLinux 上让同一个对话(包括子代理)的命令共用一个 /tmp,文件工具读写 /tmp 时看到的也是同一个
fs-viewedit 前文件没用 read 读过、或读后被 shell 改过时,按当前版本照常替换(原文对不上照样失败),省掉"读一遍再重试";read_image 按文件头认格式
chat-answer-fix带着工具调用结束的一轮,答复照常显示,不被收进折叠里(替换聊天界面里的一个判定)
调优预设 tuned(默认关闭)一份固定的预设:去掉日常编码用不到的工具,加一段用好工具的规则(能一起拿的一起拿、能一步改完的一步改完),不限制思考,用来和 standard 对比把活干完的总耗时
net-log连不上模型服务时记下底层原因(DSH 自己的日志里只有一句 transport failed)
stream-stall模型回答开始输出后只剩心跳、不再出内容时,断开这次请求,交给官方重试(官方的空闲超时会被心跳重置,永远等下去)

安装、配置项、日志和卸载见 docs/configuration.md。

开发

npm test

测试只用 Node.js 自带的 node:test,不需要安装依赖。

许可证

MIT