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.
Package details
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:
- 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.
- Local ledger — one JSONL record per priced call, rolled up by day, model,
and tier. Plain files you can query with
jq. - 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:00and06:00–10:00UTC, 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
ratesdoes 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