okku000/dsh-ollama-quota

dsh-ollama-quota

DeepSeek Harness plugin: show the Ollama Cloud credit balance and recent usage as a Settings section, with an in-page API key editor.

Uncategorizeddeepseek-harnessdshollama

dsh-ollama-quota

DeepSeek Harness plugin that owns the provider quota dock at the sidebar foot: Ollama Cloud credit, ChatGPT Codex subscription quota, and the DeepSeek API balance with its peak/off-peak price phase. One package, one off-peak engine, one sidebar.footer.action cell that shows every provider on one line and opens into their full cards, plus the Ollama Settings section that carries the full rule, the usage report, and the API key editor.

The package name and the Ollama card predate the merge; the cards themselves are independent, so one provider can be read without the others (see Configuration).

Ollama moved the account to a credit model: GET https://ollama.com/api/usage no longer carries the old limits.session / limits.weekly windows (it answers a range/totals/buckets report instead), so readers built on that shape fail with "Could not parse the response · no limits object". The remaining credit now comes from GET https://ollama.com/api/balance, which is what this plugin reads.

Data sources

ProviderEndpointRole
Ollama CloudGET https://ollama.com/api/balanceprimary: included.balance_usd, included.allowance_usd, included.period, purchased.balance_usd
Ollama CloudGET https://ollama.com/api/usage?range=24h|7d|30dadvisory: totals (cost, requests, tokens) and daily buckets
DeepSeekGET https://api.deepseek.com/user/balanceis_available plus one balance_infos entry per currency, split into granted_balance and topped_up_balance
CodexPOST /api/codex-subscription/usagethe subscription plugin's own quota channel, called from the page over the Connection

Ollama endpoints take Authorization: Bearer <Ollama Cloud key>; DeepSeek takes the same with DEEPSEEK_API_KEY. A failure on the Ollama usage report never hides a healthy balance; it renders as an inline note inside the usage card. The usage report is re-read on its own slower interval (usageRefreshMs) because its wide window barely moves.

The Codex card never touches the ChatGPT OAuth grant: it reuses the channel dsh-codex-subscription publishes for its own UI, so the quota it shows is the same number that plugin would show, and the grant and its refresh stay owned by that plugin. Its only coupling is that channel's name and payload shape (verified against dsh-codex-subscription 2.5.9).

What it shows

RowSource
Remaining included creditincluded.balance_usd of included.allowance_usd
Used share barallowance - balance over allowance
Purchased creditpurchased.balance_usd
Allowance periodincluded.period.from → included.period.until
Spend, requests, input/cached/output tokensusage.totals over usageRange
Daily spend stripusage.buckets[].usage_usd (max 31 buckets)
Off-peak state and countdowncomputed from the browser clock: peak pricing runs weekdays 12:00–18:00 UTC, everything else is off-peak
Key sourcewhich credential reference resolved
API key editorremote.credentials.describe(refs) / set(ref, value) / unset(ref) over the DSH Remote (remote.credentials is a declared inject edge)

Per-model request counts are not shown: the endpoint stopped reporting them.

Sidebar widget

The plugin registers one sidebar.footer.action cell: a single line that stays visible at all times, not only while Settings is open. Collapsed, it lines up every provider on one row — a brand-coloured mark, an optional rate-phase dot, and one number each — so the state is readable without opening anything. There is no phase text: green dot = off-peak, red dot = peak.

TileShows while collapsedTitle (hover)
Ollamaremaining included credit, plus the phase dotremaining, phase, countdown to the next boundary
Codexthe highest used share of the subscription windowsthe provider name
DeepSeektotal balance, plus its own phase dotthe provider name and its phase

Pressing the row expands it in place into the full per-provider cards: the Ollama card (remaining credit, the 30-day spend, phase countdown, the 24h strip on the browser's local clock), the Codex card (each window's meter, reset credits, reset countdown) and the DeepSeek card (top-up vs granted credit, its own peak/off-peak phase and strip). Pressing it again collapses the row.

The marks are drawn inline (a letter in the provider's colour) so the bundle stays a single classic script with no image assets.

The collapsed 56px rail keeps the credit and a compact H:MM countdown.

Ollama applies off-peak pricing outside 12:00–18:00 UTC on weekdays and all day at weekends, so the peak window is the only interval whose end is a peak start.

The Settings section carries the same state as an additional card with the full rule text, the local peak window, the current local time, and both countdowns.

Install

dsh plugin --profile web add git+https://github.com/okku000/dsh-ollama-quota.git

While developing against a checkout, link the directory instead so edits are live:

dsh plugin --profile web add link:/path/to/dsh-ollama-quota

A Host change needs an application restart; the Client half needs a page refresh.

Configuration

The row reads these fields, all optional (cordis.patch.yml):

FieldDefaultMeaning
keyEnvs[OLLAMA_CLOUD_API_KEY, OLLAMA_API_KEY]credential references tried in order; the first is what the editor writes
apiBasehttps://ollama.comAPI origin
usageRange30dusage window, one of 24h, 7d, 30d
refreshMs60000balance refresh interval, minimum 5000
usageRefreshMs300000usage-report interval, minimum 60000; ?force=1 or a new key re-reads it
timeoutMs15000per-request timeout
deepseek.keyEnvs[DEEPSEEK_API_KEY]DeepSeek credential references tried in order
deepseek.apiBasehttps://api.deepseek.comDeepSeek API origin
deepseek.refreshMs60000how long one DeepSeek balance read is reused (15000–3600000)
deepseek.timeoutMs15000DeepSeek per-request timeout
deepseek.offPeakpublished scheduleenabled, discountPercent, holidayTimeZone, peakWindows ({ days: [1-7], from: 'HH:MM', to: 'HH:MM' }, UTC), holidays ({ from: 'YYYY-MM-DD', to: 'YYYY-MM-DD' })

The Host half serves GET /ollama-quota/snapshot for the Ollama card and GET /ollama-quota/deepseek for the DeepSeek card (add ?force=1 to either to refresh first). The snapshots carry amounts, counts, timestamps, error labels, the credential reference order, and the schedule — never a key.

A DeepSeek schedule change is Host code, so it reaches the browser after the Host reloads; without a reload the bundle's built-in copy stays in force. deepseek.offPeak.enabled: false removes the phase line while the balance stays.

Verify

node scripts/verify.mjs          # offline: fake Host context and fake browser runtime
node scripts/verify.mjs --live   # also drives the real endpoints with the stored key

--live reads OLLAMA_CLOUD_API_KEY and DEEPSEEK_API_KEY from $DSH_HOME/.credentials.yaml and drives both real endpoints.

License

MIT — see LICENSE.