xuzihao66/dsh-token-frugal ↗★ 0
dsh-token-frugal
Cut the input-token cost of long Harness sessions: structure-aware tool-output compression on tools/post-execute and per-agent tool-catalogue visibility on agent/created. 适合频繁调用工具、希望降低长会话输入Token成本的用户。
インストール
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:xuzihao66/dsh-token-frugalドキュメント
README 全文を読む ↗Configuration
Every tunable lives in the row's config in
cordis.patch.yml, so the effective policy reads in one
place and survives plugin upgrades. lib/defaults.js holds the same values as
plain JSON, and a unit test pins the patch, the field table, and those defaults
to each other.
- insert:
- id: token-frugal
name: dsh-token-frugal
config:
defaultMaxChars: 1500
toolBudgets: { read: 3000, pwsh: 1200, web_fetch: 4000 }
skipTools: []
recovery: spill
hiddenTools: []
The plugin declares no schemastery Config. A profile-installed bundle resolves
its imports from the profile's node_modules, where the Harness's own packages
do not exist, so importing @deepseek-ai/schemastery would make the row fail to
import — which is exactly what happened on the first install attempt. The plugin
therefore validates its own row config against the FIELD_KINDS table in
index.js: unknown fields and wrong-typed values fail activation with a message
naming the field. The one thing this gives up is a generated schema form in the
Plugin Manager; the fields are documented here instead.
The fields that matter most:
| Field | Meaning |
|---|---|
defaultMaxChars, toolBudgets | Character budget per tool. The defaults are the loosest profile measured to clear 40% with margin. |
errorBudgetFactor | Extra budget for failed calls (default 2). |
skipTools | Tools left byte-for-byte alone, whatever their size. |
transforms | Toggle each lossless transform. columns: false if a workflow depends on reading alignment-padded tables verbatim. |
minGainRatio | A rewrite must save at least this fraction or it is discarded, so trivia never churns the request prefix. |
structureAware | Keep middle lines matching error/warning patterns when eliding. |
recovery | spill (default) or none for lossless-only. |
hiddenTools | Tool names hidden from every agent. Empty by default: hiding a tool removes a capability, so it is opt-in. |
Measured budget profiles
Same corpus, same methodology; --budgets and --default-max-chars reproduce
each row:
| Profile | Prompt-token reduction |
|---|---|
recovery: none (lossless only, nothing dropped) | 1.87% |
Looser (read: 4000, pwsh: 2000, default 2500) | 38.74% |
Mid (read: 3200, pwsh: 1300, default 1600) | 41.09% |
Shipped defaults (read: 3000, pwsh: 1200, default 1500) | 41.76% |
Reduction is workload-dependent, so the aggregate is reported with its spread.
Per session in the same corpus: 66.1%, 56.9%, 37.4%, 32.9%. Sessions made
mostly of small tool results have little to elide and gain the least; sessions
dominated by fetched pages, terminal output, and re-read files gain the most.
The shipped defaults sit just above the loosest profile that still clears 40%
(read: 3200, pwsh: 1300), which is why they are tighter than they look.
Tool-catalogue visibility
The agent/created half is inert until hiddenTools names something, because
hiding a tool costs a capability. The measurement quantifies what it would buy
before you decide — on this corpus, of the recorded tool schemas (6,770 tokens
on every request), 14 were never called once, costing 2,846 tokens per
request, or 4.92% of the whole baseline:
workflow(852) subagent_fork(275) update_goal(250) present(199) job_output(158)
create_goal(149) send_message(136) exit_plan_mode(122) ...
Uncomment the example block at the end of cordis.patch.yml to drop the ones you
accept losing. Hiding is implemented as ctx.tools.restrict() on the agent's own
scoped context, so it stays aligned with schema presentation, lookup, and
execution, and unknown names are reported and ignored rather than throwing — an
agent/created listener that throws would roll back agent creation.