dsh-rtk:给 DSH 加一层 rtk 命令改写与输出压缩

前言

DSH 跑久了,token 消耗的大头常在工具结果上:git status 打几十行、编译输出淹没在进度噪音里、grep 重复的文件名和行号反复出现。这些内容模型大多不需要,但都占上下文,而且每次调用都要重新读一遍。

dsh-rtk 就是针对这一层的插件。它由 wings1848 维护,包名 @wingsbutterfly/dsh-rtk,当前版本 0.1.2,MIT 许可。它做的事有两件:在命令派发前把它改写成语义等价的 rtk 命令;在工具输出进入模型上下文之前跑一条压缩管线。它是上游 pi-rtk-optimizer 移植到 DSH 插件模型上的实现。

需要先说明一点:dsh-rtk 是包在 rtk 外面的插件,不是 rtk 的替代品。PATH 上没有 rtk,插件就静默停摆,命令原样执行、输出不压缩。因此下文安装部分先装 rtk,再装插件。

工作原理

README 里给了一段最短的示例:

模型发出:  git status
实际执行:  rtk git status
模型看到:  Branch: main
            Modified: 2 files
              src/a.ts

改写和压缩分两路进行,覆盖面不完全一样:命令改写覆盖 bash、pwsh、ops_bash 三类 shell 工具;输出压缩覆盖 bash、read、grep、ops_bash、ops_grep 五类工具结果。

核心功能

命令改写

几个实现上的关键选择,来自 README:

  • 插件自身不带改写表,改写时调用 rtk rewrite 询问已安装的二进制。支持范围因此跟随你装的 rtk 版本,而不是另一个容易过期的清单。
  • 三种模式:off 全关;rewrite 直接替换命令;suggest 原样执行、只报告本可使用的等价命令。
  • 运行时守卫:无法确认 rtk 可用时按原命令执行,缺少优化器不会挡住工作。
  • 子进程环境脱敏:*_KEY、*_PASSWORD、*_SECRET、*_TOKEN 命名的变量与 DSH_* 一律不传给 rtk 外呼进程,PATH、locale、代理设置保留。
  • 被改写的命令默认不注入 RTK_DB_PATH,rtk 写它自己的用户级库;可用 historyDbPath 钉到指定位置,相对路径与目录会被拒绝。

输出压缩

压缩是一条多阶段管线:

阶段 作用
ANSI 剥离 去掉终端颜色与格式转义序列
构建过滤 提取编译错误与警告,丢弃进度噪音
测试聚合 折叠为 通过/失败/跳过 计数加失败摘录
Git 压缩 归纳 git status、git diff、git log
Linter 聚合 统计问题数并按规则与文件排序
搜索分组 把 grep 风格匹配按文件归组
read 压缩 readCompaction: minimal 删普通注释;aggressive 只留 import 与签名(默认关)
硬截断 最后兜底的字符预算

两条是硬约束。其一,DSH 的结果契约会存活:尾部状态标记 [exit code: N]、[stderr]、[timed out after …]、[sandbox: …] 先被摘出,正文重写后原样接回并保证在最后一行,Web UI 也解析同一行画退出状态。其二,压缩绝不把结果变大:某个技术若不能真正缩短文本,就保留原文且不上报收益。

另外,挂载 dsh-spill-policy 时插件会关掉自己的硬截断。原因是插件默认 12000 字符的阈值远低于 spill 的 50000 字节阈值,自己截断跑在 spill 前面,那份可恢复的落盘文件就永远没有机会生成。是否让位只看服务在不在,没有开关。

配置页与收益面板

Web 宿主的插件页上,rtk 行会有自己的配置控制。页面画日常字段、本地暂存编辑、通过宿主设置服务提交,被覆盖的字段带逐项恢复。表单下方是收益面板:20 格效率条、原始输出 / rtk 处理后 / 省下及占比、命令数与平均耗时,可在按天与按命令之间切换,并按工作区与时间窗切片。数据由宿主执行 rtk gain -d -f json 取得,经带鉴权的精确 Fetch 路由 POST /api/dsh-rtk/gain 送到浏览器;没有 Web connection 的部署会明确显示台账不可用,而不是渲染坏页面。

安装与启用

0. 前置:先装 rtk 二进制

PATH 上找不到 rtk 时,插件静默停摆,整个会话只多一行 [rtk] rtk not found; rewriting is off,夹在工具输出里很容易漏看。所以先装 rtk:

brew install rtk                        # macOS / Linux(Homebrew,推荐)
winget install rtk-ai.rtk               # Windows
curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
cargo install --git https://github.com/rtk-ai/rtk

不要执行不带 --git 的 cargo install rtk,crates.io 上同名的另一个 crate 不是这个工具。

装完验一下,必须能打印版本号:

rtk --version

1. 安装插件包

dsh plugin --profile web add @wingsbutterfly/dsh-rtk

插件声明了 dsh.bundle,所以这条命令既安装又挂载,插件管理器把包名追加进 dsh.profile.bundles。装完需重启宿主,profile 行只在启动时挂载。

版本要求:支持 dsh 0.1.5、0.1.7、0.2.0、0.2.1(逐条实测,证据见仓库 docs/verification.md);Node ≥ 22.18。

2. 检查配置

所有字段可选,以下是默认值:

- id: rtk
  name: '@wingsbutterfly/dsh-rtk'
  config:
    mode: rewrite                    # off | rewrite | suggest
    compact: true                    # 是否压缩工具输出
    maxChars: 12000                  # 字符预算(1000–200000)
    readCompaction: none             # none | budget | minimal | aggressive
    rtkExecutable: rtk               # 名字或绝对路径,空串表示自动探测
    historyDbPath: ''                # '' = rtk 自己的库;或绝对/~ 路径,或 `isolated`

rtkExecutable 会自动探测:加载时先在 PATH 里查,Windows 上还会查 WinGet、cargo、Scoop 的常见安装目录,每个候选都用 --version 验一遍。手填过的值不会被覆盖。

也可以在 DSH 设置文档里实时改,改完无需重启:dsh 0.1.7 及以上是独立的设置条目,名字取组合行的 id;0.1.5 是 dsh-rtk 命名空间。/rtk path 会报告插件实际看到的是哪一层配置。

注意行放在哪一层的约束:放在家目录 patch(~/.dsh/cordis.patch.yml)里的行是只读的,在线写入会被拒绝,/rtk reset 会如实报告。要保留在线编辑,请把行放进某个 profile 的组合。

典型用法

会话内的几条命令:

  • /rtk verify:检查 rtk 是否可用,失败时直接打印安装方式。
  • /rtk stats:报告本次会话里压缩省下多少字符,按工具和按技术分别统计。
  • /rtk gain [flags]:显示 rtk 为插件改写过的那些命令实际收回了多少。
  • /rtk path:报告插件实际读到的配置与台账层。

运行时验证过的一条现象(宿主 0.2.1-rc.2,记录见 docs/verification.md):模型发出 ls,实际执行 rtk ls;cat 实际执行 rtk read,台账位置跟随 rtk 自己的库。

适用场景与注意事项

适合在 DSH 上跑大量 shell 工具调用、又被长输出反复占用上下文的开发者。命令改写和压缩在 host 平面行上生效,覆盖该 profile 下的每个 agent、preset、子智能体,不是只作用于单个会话。要收窄范围,用行自己的开关:mode: off 全关,mode: suggest 只报告不改写。不希望覆盖全 profile 时,README 另给了把包装成普通依赖、手工把行加进目标 preset 插件列表的做法,此时不要在 bundle 里重复挂载。

安装前应当检查源码与许可证。插件以当前 dsh 进程的权限运行,会读取环境变量并派生子进程;如前所述外呼做了脱敏处理,但这意味着它能看到你在这个宿主里执行的命令,生产环境按你对待其他第三方插件的同一标准评估。

另外,readCompaction 默认是 none。README 给出的理由:过滤或截断 read 结果会让模型手里的副本与磁盘文件不一致,而编辑正是对着那份副本写的。需要可读性上的压缩时,用 minimal,并接受这个前提。

小结

dsh-rtk 的作用是把 rtk 的改写和压缩接进 DSH 的工具调用路径,让长输出在进入模型之前就短一截,并保持 DSH 的结果标记不变。它是在 rtk 之上的薄层,收益取决于 rtk 本身的能力。

目录页:https://www.skillhub.cn/plugins/wings1848/dsh-rtk
GitHub:https://github.com/wings1848/dsh-rtk

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜