pi-deepseek-suite

DeepSeek cost suite for pi: time-of-day peak/off-peak re-pricing, a cross-session local ledger, and official account balance — with provider-name-agnostic model matching.

Packages

Package details

extension

Install pi-deepseek-suite from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-deepseek-suite
Package
pi-deepseek-suite
Version
0.1.1
Published
Sep 12, 2026
Downloads
329/mo · 329/wk
Author
npmjs2006
License
MIT
Types
extension
Size
59.4 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-deepseek-suite

English | 中文

DeepSeek cost accounting for pi, in one extension:

  1. Peak/off-peak re-pricing — every DeepSeek assistant message is charged at the official rate in effect at that message's own UTC timestamp, so pi's session totals, footer, and exports match what DeepSeek actually bills.
  2. Local ledger — one JSONL record per priced call, rolled up by day, model, and tier. Plain files you can query with jq.
  3. Account balance — the official balance endpoint, with a burn-rate runway and an optional low-balance warning.

No API calls beyond the balance lookup. No telemetry. Nothing about your conversation leaves the machine.

pi install npm:pi-deepseek-suite

Then /reload (or restart pi).


Why one extension instead of three

message_end handlers chain: a handler sees the replacement returned by an earlier handler, and the final replacement is what pi persists. If re-pricing and recording live in separate plugins, the ledger's correctness depends on their order in settings.json — put the recorder first and it logs the uncorrected cost forever, silently.

Here the corrected cost is computed once and used by both consumers, so there is no ordering to get wrong.

Why pricing matches on model id, not provider name

Several DeepSeek plugins key everything off provider === "deepseek". Provider names are local configuration: relay and router tools (cc-switch, new-api, one-api, …) generate models.json, pick their own provider name, and keep the key inline. On such a setup a provider-name check silently disables the whole plugin — the footer just never appears, with no error.

This extension matches on model id, and discovers the API key from DEEPSEEK_API_KEY, then auth.json, then any models.json provider whose baseUrl points at api.deepseek.com. So it works whether your provider is called deepseek, cc-switch-deep-seek, or anything else.

Commands

Command What it shows
/ds [Nd] Cost report from the ledger: total, calls, tokens, peak vs off-peak split, per-day and per-model breakdown. Defaults to today; /ds 7d, /ds 30d.
/ds-balance Account balance (CNY-aware), how usable the account is, average daily burn, and runway at that rate.
/ds-tier Current tier, the exact rates in effect for the current model, and the next switch.

The status line stays compact:

off-peak · $0.0340 today · ¥42.50

How pricing works

Source of truth: https://api-docs.deepseek.com/quick_start/pricing

  • Peak windows are 01:00–04:00 and 06:00–10:00 UTC, Monday–Friday. Everything else, weekends included, is off-peak.
  • Off-peak is exactly half of peak, so the built-in table stores the off-peak column only and multiplies during peak.
  • Cache writes are free for DeepSeek.

Off-peak rates (USD per 1M tokens) shipped in the built-in table:

Model id input output cacheRead cacheWrite
deepseek-flash 0.15 0.60 0.003 0
deepseek-v4-flash 0.15 0.60 0.003 0
deepseek-v4-flash-vision-exp 0.15 0.60 0.003 0
deepseek-v4-pro 0.66 1.98 0.022 0

deepseek-v4-flash and deepseek-v4-flash-vision-exp are retired ids that DeepSeek still accepts and bills at the current Flash price.

deepseek-v4-pro keeps its own rates. DeepSeek announced a 2026-09-14 retirement that would have re-routed Pro to Flash pricing and then reversed that decision — so no cutover is encoded. A plugin that still assumes the reversal never happened will under-report Pro usage by roughly 3–4× from that date onward.

Updating prices without waiting for a release

Set rates in the config file. It replaces the built-in table entirely, so include every model you need:

{
  "rates": {
    "deepseek-flash": { "input": 0.15, "output": 0.6, "cacheRead": 0.003, "cacheWrite": 0 },
    "some-new-model": { "input": 1, "output": 2, "cacheRead": 0.1, "cacheWrite": 0 }
  }
}

Rates are always the off-peak figures; peak is derived by multiplication.

Configuration

Global: ~/.pi/agent/deepseek-suite.json Project: <cwd>/.pi/deepseek-suite.json (honoured only for a trusted project)

Project values override global ones. Anything malformed is ignored rather than fatal. Both a flat object and a { "deepseekSuite": { ... } } wrapper are accepted.

Key Default Meaning
peakMultiplier 2 Multiplier applied during peak hours.
rates null Replaces the built-in table. Off-peak USD per 1M tokens.
reprice true Write the corrected cost back into the session.
ledger true Append one JSONL record per priced message.
status true Show the status-line entry.
currency null Prefer this currency when the account reports several.
lowBalanceThreshold null Warn below this balance. Re-arms after a top-up.
balanceRefreshSeconds 300 Balance poll interval.

Files

~/.pi/agent/deepseek-suite.json                    config (global)
~/.pi/agent/deepseek-suite/ledger/YYYY/MM/DD.jsonl  one line per priced call

A ledger record:

{
  "ts": 1789219121803,
  "provider": "cc-switch-deep-seek",
  "model": "deepseek-flash",
  "tier": "offPeak",
  "tokens": { "input": 134, "output": 2, "cacheRead": 4351, "cacheWrite": 0 },
  "cost": { "input": 0.0000201, "output": 0.0000012, "cacheRead": 0.000013053, "cacheWrite": 0, "total": 0.000034353 },
  "ratesSource": "official"
}

provider is recorded exactly as pi reports it — never rewritten. Pricing keys off model. tier is the tier that was in effect for that call, which is what makes "how much would this have cost off-peak" answerable later.

jq recipes:

# Today's total
jq -s 'map(.cost.total) | add' ~/.pi/agent/deepseek-suite/ledger/2026/09/12.jsonl

# Spend by tier this month
jq -s 'group_by(.tier) | map({tier: .[0].tier, total: map(.cost.total) | add})' \
  ~/.pi/agent/deepseek-suite/ledger/2026/09/*.jsonl

Scope and limitations

  • Only assistant messages are priced. Tool-result and compaction usage has no model of its own, so it is left to pi.
  • Models outside the table are left completely alone: pi's own cost is preserved rather than replaced with a guess.
  • Day boundaries in the ledger use local time; tier boundaries use UTC, because DeepSeek publishes them in UTC.
  • The ledger is append-only and never rewritten. Changing rates does not retroactively re-price history.
  • A balance lookup is the only network call, and only when a balance surface asks for it (session_start, model_select, the poll timer, or /ds-balance).

Requirements

  • pi @earendil-works/pi-coding-agent (any recent version; no hard floor)
  • Node 20+ (uses AbortSignal.timeout)

License

MIT