Repository navigation
ThinkWatch Core 0.70.0
This release reads each upstream's balance: the money left on a key, the quota of a relay key and its time windows, a key's limit and spend on OpenRouter, or the usage and limits a ThinkWatch Enterprise gateway reports for a key. It also records which upstreams were written by signing in to a Z.ai or BigModel account.
Upgrade notes
- The control-plane protocol version (
CONTROL_API_VERSION) goes from 45 to 46. ThinkWatch Lite connects only to a core with the same protocol version: ThinkWatch Lite 2026.10.13 includes 0.69.0 (protocol 45) and does not connect to 0.70.0. A server used with it stays on 0.69.0 until the app is updated to a release that includes 0.70.0;sudo twcore upgrade --version 0.69.0 --restartswitches a server back. - The request store's schema is unchanged; nothing is cleared.
- Configuration: an upstream takes two new optional keys,
balance:andsigned_in:. Existing configurations load unchanged and read balances where the address is recognized. - New message codes:
control.balance_none,gw.balance.rejected,gw.balance.status,gw.balance.unrecognized,gw.balance.timeout,gw.balance.connect,gw.balance.request_failed. - Changed in the protocol:
ProviderViewgainsbalance(the latest reading),balance_setting(what the configuration says) andsigned_in;ProviderInputgainsbalance;ProviderTestResultgainsbalance.- New types
Balance,BalanceQuota,BalanceWindow,BalanceScope,Spent,SpentPeriod,BalanceSetting. - New event
balance_updatedand endpointPOST /providers/{name}/balance/refresh:404 control.balance_nonefor an upstream with no balance to read,502with the reason when the source could not be determined because a request failed.
Balances. An upstream's balance: says where its balance is read from, with the upstream's own key and proxy: openrouter, deepseek, moonshot, sub2api, newapi (New API and One API) or thinkwatch (a ThinkWatch Enterprise gateway); off reads nothing. The default, auto, recognizes OpenRouter, DeepSeek and Moonshot by their address; any other address, except Anthropic's, OpenAI's and Gemini's own, is asked once whether it is a Sub2API relay, a New API relay or a ThinkWatch Enterprise gateway, and the answer is kept in memory only. ChatGPT and Z.ai accounts and Bedrock upstreams have no balance; their quota windows are reported as before.
A reading is one or more of: money left on the key (a wallet, in its own currency), a total quota with what has been used of it, time windows with their limits, use and reset time, and the money already spent. Per source:
- OpenRouter: the key's own limit, if it has one, and what the key spent this month (or in total), with the key's expiry. The account's credits need a management key and are not read.
- DeepSeek and Moonshot: the account balance, in its currency.
- Sub2API: the key's quota and its 5-hour, daily and weekly windows, or its subscription's windows, or the wallet balance; what was spent today is the amount actually charged.
- New API and One API: the key's quota and use, in the unit the site displays (US dollars, yuan or tokens, read from the site's public status); a site that does not say is marked as an unknown unit rather than dollars.
- ThinkWatch Enterprise: the key's limits and usage when the key has limits of its own, otherwise the account's limits and its total over all of its keys, each limit saying which.
Balances are read at start, at most once a minute after requests through that upstream end, every ten minutes otherwise, and on request; Check connection also reads the balance and runs the recognition for auto, waiting at most five seconds for it. A failed read keeps the previous reading and says why; reading a balance never affects forwarding. Requests go only to the upstream's own address, through its proxy, and redirects are not followed.
Z.ai and BigModel sign-in. An upstream written by signing in to a Z.ai or BigModel account now carries signed_in: zai or signed_in: bigmodel, and ProviderView.signed_in says so, so an app can show it as an account sign-in. Signing in again sets it on upstreams written before this release. Saving the upstream with the same key keeps it; replacing or removing the key clears it.
Downloads
| Platform | Binary | Archive for server installation |
|---|---|---|
| Linux, x86_64 | twcore-x86_64-unknown-linux-gnu |
twcore-x86_64-unknown-linux-gnu.tar.gz |
| Linux, aarch64 | twcore-aarch64-unknown-linux-gnu |
twcore-aarch64-unknown-linux-gnu.tar.gz |
| macOS, Apple silicon | twcore-aarch64-apple-darwin |
— |
| Windows, x64 | twcore-x86_64-pc-windows-msvc.exe |
— |
| Windows, ARM64 | twcore-aarch64-pc-windows-msvc.exe |
— |
Each file is published with a .sha256 file beside it. A Linux archive contains twcore, the systemd unit twcore.service and LICENSE. ThinkWatch Lite includes its own copy of twcore; the files here are for running core separately, such as on a server.
Server installation
On Linux (x86_64 or aarch64), the install script sets up twcore as a systemd service. This installs 0.70.0:
curl -fsSL https://raw.githubusercontent.com/ThinkWatchProject/ThinkWatch-Core/main/scripts/install.sh | sudo sh -s -- --version 0.70.0An installation made with the script switches to 0.70.0 with:
sudo twcore upgrade --version 0.70.0 --restartConfiguration, the remote control port and connecting ThinkWatch Lite are described in docs/server.md.
Verifying a download
A .sha256 file holds the SHA-256 of the file followed by its name. With both files in the current directory, on Linux:
sha256sum -c twcore-x86_64-unknown-linux-gnu.tar.gz.sha256On macOS:
shasum -a 256 -c twcore-aarch64-apple-darwin.sha256On Windows, in PowerShell, the following prints True when the binary matches:
(Get-FileHash .\twcore-x86_64-pc-windows-msvc.exe).Hash -eq (Get-Content .\twcore-x86_64-pc-windows-msvc.exe.sha256).Split()[0]The install script and twcore upgrade check the SHA-256 themselves.
What's Changed
- feat(gateway): read each upstream's balance by @fylorn in #321
- Balance: say whose money the spent amount is by @fylorn in #322
- fix(gateway): balance review fixes before 0.70.0 by @fylorn in #323
- Mark upstreams whose key came from a Z.ai sign-in by @fylorn in #324
- v0.70.0 by @fylorn in #325
Full Changelog: v0.69.0...v0.70.0