Skip to content
dsh.fish
Bundle

dsh-cost-gate

Spend gate for DeepSeek Harness: refuses over-budget model calls on the llm/stream waterfall, before they are billed. Auto-downgrade past a soft limit.

Source
frozo-ai
stars
1 stars
License
MIT
Updated
Updated 6 days ago

Readme

# dsh-cost-gate

**Spend enforcement for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — not another dashboard.**

The dsh ecosystem has plenty of cost plugins. Every one of them *measures*:
ledgers, statistics, heatmaps, balance widgets. They tell you what you spent
**after you spent it**.

This one **stops the call**.

```
        ┌─ over budget? ──> throw, before a single token is billed
llm/stream waterfall ─┼─ past 80%? ────> silently route to the cheap model
        └─ fine? ────────> pass through, then meter the usage chunk
```

`llm/stream` is a cordis **waterfall** — the decision happens *before* `next()`
runs, which is the only place enforcement can actually work.

## Install

```sh
dsh plugin --profile web add github:frozo-ai/dsh-budget   # npm: dsh-cost-gate
```

```yaml
- insert:
    - id: budget
      name: 'dsh-cost-gate/plugin'
      config:
        limitUsd: 50
        period: monthly          # daily | monthly | total
        softFraction: 0.8        # start downgrading at 80%
        downgradeModel: 'deepseek/deepseek-chat'
        storePath: '~/.dsh/spend.json'
        rates:                   # USD per MILLION tokens
          'deepseek/deepseek-chat': { input: 0.28, output: 0.42 }
          'anthropic/claude-3.5-sonnet': { input: 3, output: 15 }
```

Set `dryRun: true` to log decisions without blocking — roll out safely, then
turn it on.

## Design notes

**Integer micro-dollars.** Costs accumulate as integers, never floats. A test
runs 10,000 calls and asserts zero drift, because this decides whether people
get blocked.

**Cache tokens are disjoint.** Per dsh's `TokenUsage` contract, `cacheRead` and
`cacheWrite` are *not* included in `inputTokens`, so they're added at their own
rates rather than folded in.

**Atomic ledger writes.** Temp file plus rename — a torn write must not lose
budget state.

**UTC period boundaries**, so a daily budget resets at a time everyone agrees on.

**Fails open, deliberately.** No `limitUsd` means metering only. Enforcement is
opt-in: a budget plugin that accidentally blocks your whole team is worse than
one that doesn't block at all.

## Related work

[`PerryLink/dsh-budget`](https://github.com/PerryLink/dsh-budget) covers similar
ground — metering, caps, alerts, carbon estimates, a Settings tab. If you want
dashboards and reporting, look there first. This plugin is narrower on purpose:
it gates the `llm/stream` waterfall so an over-budget call is refused *before*
it is billed, and does little else.

## Attribution

```yaml
scopeBy: session          # deployment (default) | session | user
perScopeLimitUsd:
  'system:compaction': null    # unlimited — overhead must never block the agent
  'user:alice': 100
```

**`session`** uses `GenerateOptions.sessionId`, which dsh genuinely provides.

**`user`** needs a mapping dsh cannot supply — there is no user identity at the
llm seam. So it is given, never guessed:
- `userEnv: 'DSH_USER'` — one dsh instance per user
- `sessionUsers: { <sessionId>: 'alice' }` — an operator-supplied map

An unattributable call lands in `user:unattributed`. It is never charged to
whoever happens to be handy — a chargeback report that invents attributions is
worse than one that admits gaps.

**System overhead is separated.** Compaction and session-title calls carry a
`purpose` and are billed to `system:*`, so background work can never exhaust a
person's budget. Give them a `null` limit so they cannot be blocked.

## Known limitations
- **Per-user requires operator setup** — see Attribution above. dsh has no user
  concept at the llm seam, so nothing can infer it.
- **Unknown models price as $0** rather than crashing. Add them to `rates`.
- Pricing tables are yours to maintain; providers change rates.

## Test

```sh
npm test   # 29 checks: pricing, drift, periods, durability, decisions, attribution
```

MIT. Not affiliated with DeepSeek AI.

Install

dsh plugin --profile web add github:frozo-ai/dsh-budget

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source