xuzihao66/dsh-token-frugal ↗★ 0

dsh-token-frugal

通过压缩工具输出和控制工具可见性来节省Token 适合频繁调用工具、希望降低长会话输入Token成本的用户。

套件
dsh-token-frugal
相容性
待驗證
版本
1.0.0
授權
MIT
最近更新
2026年10月8日

安裝

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:xuzihao66/dsh-token-frugal

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:

FieldMeaning
defaultMaxChars, toolBudgetsCharacter budget per tool. The defaults are the loosest profile measured to clear 40% with margin.
errorBudgetFactorExtra budget for failed calls (default 2).
skipToolsTools left byte-for-byte alone, whatever their size.
transformsToggle each lossless transform. columns: false if a workflow depends on reading alignment-padded tables verbatim.
minGainRatioA rewrite must save at least this fraction or it is discarded, so trivia never churns the request prefix.
structureAwareKeep middle lines matching error/warning patterns when eliding.
recoveryspill (default) or none for lossless-only.
hiddenToolsTool 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:

ProfilePrompt-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.