🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

运行时调优 herenfor/dsh-runtime-tuning

DeepSeek Harness
herenfor5 天前有提交已提供中文文档扫描:含敏感能力

用真实会话数据找出智能体浪费时间的地方并修复

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add herenfor/dsh-runtime-tuning
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · tool
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件
查看扫描证据(共 20 处,展示前 20 条)
  • 读取本地文件
    plugins/chat-answer-fix.mjs:64
    try { if (readFileSync(file, 'utf8') === text) return } catch {}
  • 写入本地文件
    plugins/chat-answer-fix.mjs:65
    writeFileSync(file, text)
  • 读取本地文件
    plugins/chat-answer-fix.mjs:70
    const pkg = JSON.parse(readFileSync(join(officialDir, 'package.json'), 'utf8'))
  • 读取本地文件
    plugins/chat-answer-fix.mjs:71
    const { text, patched, settings } = patchClient(readFileSync(join(officialDir, entryOf(pkg.exports?.['./client'], './lib/client.js')), 'utf8'))
  • 写入本地文件
    plugins/fs-view.mjs:84
    mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    plugins/fs-view.mjs:86
    copyFileSync(path, copy)
  • 删除本地文件递归
    plugins/fs-view.mjs:98
    rmSync(join(copy, '..'), { recursive: true, force: true })
  • 写入本地文件
    plugins/log.mjs:15
    ready ??= mkdir(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    plugins/log.mjs:17
    .then(() => appendFile(join(dir, file), JSON.stringify({ time: new Date().toISOString(), ...entry }) + '\n', { mode: 0o600 }))
  • 写入本地文件
    plugins/secret-files.mjs:27
    mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    plugins/secret-files.mjs:29
    try { chmodSync(file, 0o600) } catch {}
  • 写入本地文件
    plugins/secret-files.mjs:30
    writeFileSync(file, NOTE_TEXT, { mode: 0o444 })
  • 写入本地文件
    plugins/secret-files.mjs:31
    chmodSync(file, 0o444)
  • 读取本地文件
    plugins/secret-files.mjs:64
    const users = windowsUsers ?? (() => { try { return readdirSync('/mnt/c/Users').filter((u) => !NOT_USERS.has(u)) } catch { return [] } })()
  • 读取本地文件
    plugins/session-tmp.mjs:92
    for (const entry of (() => { try { return readdirSync(base, { withFileTypes: true }) } catch { return [] } })()) {
  • 删除本地文件递归
    plugins/session-tmp.mjs:96
    if (now - statSync(dir).mtimeMs > staleHours * 3_600_000) { rmSync(dir, { recursive: true, force: true }); removed += 1 }
  • 读取本地文件
    plugins/session-tmp.mjs:96
    if (now - statSync(dir).mtimeMs > staleHours * 3_600_000) { rmSync(dir, { recursive: true, force: true }); removed += 1 }
  • 写入本地文件
    plugins/session-tmp.mjs:115
    mkdirSync(base, { recursive: true, mode: 0o700 })
  • 写入本地文件
    plugins/session-tmp.mjs:116
    mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 删除本地文件递归
    plugins/session-tmp.mjs:183
    for (const dir of created) rmSync(dir, { recursive: true, force: true })
扫描于 2026/11/3(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 运行时优化实验:从真实会话数据里找 agent 的时间浪费,再用插件修掉

README

由 DeepSeek 最新模型翻译生成
DSH 运行时调优 一个关于智能体运行时的长期实验:从 DeepSeek Harness(DSH)的真实会话记录里找出时间花在了哪里、哪些是白白浪费的,再尽量用插件把它修掉,并且每一项都用数据验证。 这里既是一组可以安装的 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% 只调用了一个工具。每多一步,就多一次重读上下文和生成。
展开完整文档(README 剩余 1 节)
DSH 运行时调优

一个关于智能体运行时的长期实验:从 DeepSeek Harness(DSH)的真实会话记录里找出时间花在了哪里、哪些是白白浪费的,再尽量用插件把它修掉,并且每一项都用数据验证。

这里既是一组可以安装的 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 和顶层智能体的长时间阻塞等待,并告诉模型应该怎么做。

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

| | 改动前 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,用户的回答之后作为插话送进来),但默认关闭,而且这个工具嵌在智能体 preset 内部,用户的配置补丁改不到它。具体的复现过程我发在了 DSH 讨论 #8547。

插件 ask-nonblocking 的绕法是:在每个顶层智能体创建时,用宿主里同一份官方模块在智能体自己的作用域里注册一个 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),省掉重复答复的那一步。机制有效,但模型经常不这么写;
- 做一个专用预设,把两段矛盾的提示合成一段。提示改写生效了,模型的行为没有明显变化,而且预设只对新会话有效,所以没有放进插件包;
- 最后的做法是换个思路:状态由 runtime 按事实判断,不靠模型声明。一轮结束时还有本次请求启动的后台任务在跑,就是在等;有提问没回答,就是在等用户。硬保底和 dsh-task-notify 的完成通知都按这个判断。task_status 降为可选,只在任务会跑超过 30 分钟、或者要标记服务时才需要。

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

顺带:时间到底花在哪

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

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

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

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

还在看的问题

| 问题 | 数据 | 状态 |
| 等人审批时没有提醒,人不在就一直停着 | 58 分钟,最长一次 44.7 分钟 | 已在 dsh-task-notify 里加上"需要审批 / 需要你回答"的提醒 |
| 令牌进入上下文 | 1 个令牌,73 条命令、74 条回复 | secret-guard |
| 前台命令设了过长的超时 | 139 条前台命令超时设到 5 分钟以上,但真正跑超过 1 分钟的只有 2 条 | 已评估,不做:插件只能拒绝、不能改参数,拒绝 139 次多花的时间比省下的还多 |
| 一步只调一个工具 | 87% 的步骤 | 只加了一句提示:每步省的只是一次请求延迟,收益小(见上一节) |
| 反复 tail 日志、重读同一文件 | 同一文档同轮最多重读 7 次 | 收益同上,暂缓 |
| 模型响应变慢 | 某天首字延迟中位数从 1.2 秒升到 8.3 秒,出字速度不变 | 服务端问题,插件能做的只有减少请求次数 |
| 审批会卡住整个 step | — | DSH 核心行为,插件做不到(#8916) |
| 插话打断不了正在运行的工具 | 插话排队最长 128 秒 | DSH 核心行为,插件做不到(#11005) |

目前包含的插件

| 插件 | 作用 |
| wait-guard | 拦截前台长 sleep 和长时间阻塞等待;后台任务没回报时兜底唤醒模型;可选的 task_status 工具 |
| ask-nonblocking | 让 ask_user_question 问完不阻塞 |
| secret-guard | 不让令牌进入模型的上下文 |

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

开发

npm test

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

许可证

MIT
预览分享卡片长什么样 ↓herenfor/dsh-runtime-tuning
分享 · DeepSeek Harness Hub
herenfor/dsh-runtime-tuning

用真实会话数据找出智能体浪费时间的地方并修复

这是你的仓库?认领条目

回到顶部