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

工具输出瘦身 unclecode/toolshrink

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

按含义裁剪智能体的大型工具输出,而不是按被截断的位置。

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

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

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add unclecode/toolshrink
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · chat
装得上吗
静态安装检查有提示项,装前建议看一眼 README
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 76 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包toolshrink(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/25 17:10:47

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件
查看扫描证据(共 8 处,展示前 8 条)
  • 写入本地文件
    adapters/harness/toolshrink.mjs:35
    if (config.log) appendFileSync(config.log, text + '\n')
  • 读取本地文件
    dist/pipeline.js:102
    for (const entry of readdirSync(dir).sort()) {
  • 写入本地文件
    dist/spill.js:21
    mkdirSync(this.dir, { recursive: true });
  • 写入本地文件
    dist/spill.js:28
    writeFileSync(join(this.dir, `${tool}-${hash}.txt`), text);
  • 读取本地文件
    dist/spill.js:36
    return readFileSync(join(this.dir, `${name}.txt`), 'utf8');
  • 读取本地文件
    dist/spill.js:46
    entries = readdirSync(this.dir);
  • 读取本地文件
    dist/spill.js:56
    if (statSync(path).mtimeMs < cutoff)
  • 删除本地文件
    dist/spill.js:57
    unlinkSync(path);
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

功能亮点

  • 按语义压缩工具输出
  • 内容感知精简器

按语义而非截断位置压缩智能体工具输出,含 13 个内容感知精简器和 DeepSeek Harness 插件。

README

由 DeepSeek 最新模型翻译生成
toolshrink 按含义裁剪智能体的大型工具输出,而不是按被截断的位置。 我每天都在用 Claude Code,一直想插手它管理上下文的方式。早期还能直接改会话 JSONL,后来这扇门关上了。 DeepSeek 开源 Harness 之后,我翻了进去——那里一切都是插件。工具输出按大小裁剪:留头、留尾、丢掉中间。我又读了 Codex 和 pi,做法一样。没有谁去看文本里到底装了什么。 这种做法的失败方式完全可以预料。你的测试套件打印 5,000 行通过,中间夹着 3 个失败。按大小裁剪会留下通过的行,扔掉失败的行。模型读完,信了这次运行,答错了。 于是我做了这个裁剪器,就是我一直希望 Claude Code 有的那个。
展开完整文档(README 剩余 1 节)
toolshrink

按含义裁剪智能体的大型工具输出,而不是按被截断的位置。

我每天都在用 Claude Code,一直想插手它管理上下文的方式。早期还能直接改会话 JSONL,后来这扇门关上了。

DeepSeek 开源 Harness 之后,我翻了进去——那里一切都是插件。工具输出按大小裁剪:留头、留尾、丢掉中间。我又读了 Codex 和 pi,做法一样。没有谁去看文本里到底装了什么。

这种做法的失败方式完全可以预料。你的测试套件打印 5,000 行通过,中间夹着 3 个失败。按大小裁剪会留下通过的行,扔掉失败的行。模型读完,信了这次运行,答错了。

于是我做了这个裁剪器,就是我一直希望 Claude Code 有的那个。它先读输出,认出它的形状,然后留下真正承载信息的那部分:

input: a vitest run, 31,958 chars, 805 lines, budget 2,000 chars

head+tail cut: 1,904 chars the model learns: the summary
toolshrink: 255 chars the model learns: which test failed,
why, at which line, and the summary

删掉的内容全部计入一个模型能读到的标记,完整原文连同定位信息一起存到磁盘。没有任何东西被悄悄丢掉。

裁剪器

每个裁剪器认一种文本形状。第一个认出输入的裁剪器负责执行。一个都没认出时,走按大小的兜底逻辑,所以结果总能塞进预算。

| 裁剪器 | 识别 | 保留 | 丢弃 |
| diff | git diff、补丁 | 变更行、文件和 hunk 头、每侧 1 行上下文 | 未变更的上下文 |
| json | 单个 JSON 值 | 结构、长数组每 3 个采样、宽对象每 5 个键、计数 | 重复记录 |
| tests | vitest、jest、pytest、cargo test、go test | 失败用例及其说明、摘要 | 通过的测试 |
| build | tsc、cargo、gcc、webpack、esbuild | 错误和警告及其代码框、摘要 | 构建进度 |
| stacktrace | node、Python、Java、Ruby 堆栈 | 消息和你代码里的栈帧 | 依赖栈帧,已计数 |
| log | 带时间戳的日志 | 错误和警告及其前面的行、结尾 | 常规行 |
| tree | find、ls -R、文件列表 | 结构、每个目录 8 个条目、计数 | 过于拥挤的目录 |
| repeat | 重试风暴、进度刷屏 | 每轮 2 个采样,外加「2,998 similar lines omitted」 | 连续近似相同的行 |
| lint | eslint、ruff、clippy | 每条规则及其计数和示例位置、问题最多的文件 | 同一规则的重复出现 |
| install | npm、pip、pnpm、cargo | 摘要、版本、弃用提示、漏洞、错误 | 拉取和下载进度 |
| csv | CSV、TSV、管道表格 | 表头、开头 5 行、结尾 2 行、行列计数 | 中间的行 |
| gitlog | git log,两种格式都支持 | 最新的 15 条提交、总数、作者及各自数量 | 更早的提交 |
| size | 全部内容(兜底) | bash:末尾 · grep/read:开头 · 未知:两端 | 其余部分,只计数 |

今天随包发布的有十三种裁剪。每一种都是一个普通文件,共用同一套接口,所以你想加自己的裁剪,只需写一个文件,不必 fork。

每种裁剪都遵守四条规则,取自我看过的那三个智能体:

- 绝不返回半行(来自 pi)
- 绝不拆开 UTF-16 代理对(来自 DeepSeek Harness)
- 明确说清删掉了多少:... 15,903 characters, 401 lines omitted ...(来自 Codex)
- 再跑一遍不会有任何变化

配合 DeepSeek Harness 使用

一条命令:

dsh plugin --profile web add github:unclecode/toolshrink

安装就这一步。包里带了 dsh.bundle 清单,所以下次启动时插件就会挂载,默认预算 50,000 字符。想改预算,在你自己的层里改,~/.dsh/cordis.patch.yml:

- id: toolshrink
config:
maxChars: 20000
log: /tmp/toolshrink.log

想直接改代码?克隆下来,npm install && npm run build,然后用 insert 行按路径挂载适配器文件(见下面的适配器配置)。

适配器配置

- insert:
- id: toolshrink
name: /path/to/toolshrink/adapters/harness/toolshrink.mjs
config:
maxChars: 50000 # cut above this many characters (default 50000)
maxLines: 2000 # or above this many lines (default 2000)
maxLineChars: 0 # cap single long lines, 0 = off (default 0)
disable: [json] # skip named cuts (default none)
spillDir: ~/.dsh-toolshrink # where full originals go
log: /tmp/toolshrink.log # one line per cut, omit for silence

日志行格式:bash 64151 -> 2942 via tree+size。

当库来用

import { shrink, FileSpillStore } from 'toolshrink'

const out = shrink(bigText, { tool: 'bash', command: 'npm test' }, {
budget: { maxChars: 20_000 },
spill: new FileSpillStore({ dir: '/tmp/spills' }), // optional
})

out.content // the text to give the model
out.reduced // false when the input already fit
out.strategy // "tests", "diff+size", "size:tail", "none", ...
out.note // one human-readable line about what happened
out.stats // inputChars, outputChars, keptLines, droppedLines, ...

hint(第二个参数)可选,能让路由更准:tool 决定裁剪方向,command 帮助识别测试运行和 diff,path 帮助识别 JSON 和日志。

写你自己的裁剪

一种裁剪就是一个文件,默认导出三个成员。文件名就是裁剪名。

// mycut.mjs
export default {
name: 'mycut',
// Cheap and certain. When unsure, return false: a wrong match is worse
// than the size fallback.
detect(text, hint) {
return hint.command?.startsWith('kubectl') ?? false
},
// Return null to decline after a closer look; the next cut then tries.
reduce(text, hint, budget) {
const content = text.slice(0, budget.maxChars) // your real logic here
return {
content,
reduced: true,
strategy: 'mycut',
note: 'kept the part I know matters',
stats: {
inputChars: text.length, inputLines: 0,
outputChars: content.length, outputLines: 0,
},
}
},
}

用法:

import { shrink, loadReducers } from 'toolshrink'

const mine = await loadReducers('/path/to/my-cuts') // reads the directory
shrink(text, hint, { extra: mine }) // tried BEFORE built-ins

也可以控制内置规则:{ only: ['tests', 'diff'] } 限定并排序,{ disable: ['json'] } 跳过。

Spill:什么都不丢

有了 spill 存储,任何裁剪之前都会先保存完整原文,裁剪后的文本末尾会带上:

[full output saved as spill:bash-d63d2aebb643: directories sampled to 8 entries each]

store.load('spill:bash-d63d2aebb643') 返回原文,逐字节一致。文件 24 小时后清理。存储是一个接口;默认实现写文件,宿主也可以接入自己的存储。

实际使用中我看到的情况

预算 3,000 字符时,智能体拿到一个 60,000 字符的 find 结果,被裁到只剩开头。它的回复开头是:「输出被截断了。让我按目录统计一下数量」——它看到了省略标记,改用聚合重新查询,最后用总共 4,000 字符就答对了,而不是 60,000。

这就是设计生效的样子:一个诚实的标记,把裁剪从静默的数据丢失变成模型会据此行动的信号。这是我一直想要的干预手段,现在它只是一行 YAML。

TODO:接下来想做的裁剪

每一个都是一份文件,接口相同。挑一个,发个 pull request。

| 裁剪 | 识别 | 会保留 |
| semantic | 任何内容,只要给出智能体当前目标 | 与目标最相关的片段。分两阶段:先做词法打分(BM25,不需要模型),再可选做嵌入打分,捕捉字面之外的语义 |
| sql | 查询结果、EXPLAIN 计划 | 计划里开销大的节点,抽样结果行 |
| docker | 构建与 compose 输出 | 失败的层、最终镜像,丢掉构建过程中的杂音 |

semantic 是最有意思的一个:上面每个裁剪都按形状判断,这个要按相关性判断。它需要多一个输入——一个描述智能体当前在做什么的查询,宿主适配器可以通过 hint 传进来。

其他智能体的适配器

这个库对任何智能体一无所知。Harness 适配器只有 70 行:捕获结果事件,调用 shrink,返回替换内容。

- pi(earendil-works/pi)有扩展 API,可以访问工具结果。
- Codex(openai/codex)在 codex-rs/core-plugins 里有插件系统。

两个适配器都还没人做。如果你写了一个,欢迎发 pull request。

许可证

MIT。随便用,随便改,不用问。

作者 @unclecode,也是 Crawl4AI 。
在 X 上关注我,看我接下来做什么:x.com/unclecode。
预览分享卡片长什么样 ↓unclecode/toolshrink
分享 · DeepSeek Harness Hub
unclecode/toolshrink

按含义裁剪智能体的大型工具输出,而不是按被截断的位置。

这是你的仓库?认领条目

回到顶部