@hystudio/dsh-quota-pill 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +217 -0
- package/LICENSE +21 -0
- package/README.md +207 -2
- package/bin/quota-pill-server.js +3 -0
- package/client.js +1455 -0
- package/cordis.patch.yml +3 -0
- package/index.js +8 -0
- package/package.json +64 -4
- package/src/adapters-apikey.js +270 -0
- package/src/adapters-cliproxy.js +550 -0
- package/src/credentials.js +163 -0
- package/src/http.js +92 -0
- package/src/server.js +176 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Agent setup guide — dsh-quota-pill
|
|
2
|
+
|
|
3
|
+
This file is for **AI agents** helping a human install and configure the plugin.
|
|
4
|
+
Follow it top to bottom. It is written so that you can run the whole flow, asking
|
|
5
|
+
the human only for things only they can supply (an API key, an OAuth login).
|
|
6
|
+
|
|
7
|
+
> **Rule for the whole flow: never invent a quota number.** If a provider cannot
|
|
8
|
+
> be read, say so and explain what is missing. A wrong number is worse than "—".
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 0. What this plugin does
|
|
13
|
+
|
|
14
|
+
It shows how much quota is **left** for the LLM subscriptions the user has, in a
|
|
15
|
+
small pill in the DeepSeek Harness web GUI.
|
|
16
|
+
|
|
17
|
+
Architecture — two pieces, both required:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
DSH web GUI ──► client.js (the pill; renders JSON)
|
|
21
|
+
│
|
|
22
|
+
▼
|
|
23
|
+
sidecar (Node process; reads credentials + upstream APIs)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The pill shows nothing until the sidecar runs. That is by design: credentials
|
|
27
|
+
must never reach the browser.
|
|
28
|
+
|
|
29
|
+
There are **two credential families**, and this matters for every step:
|
|
30
|
+
|
|
31
|
+
| Family | Providers | What the user needs |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| API key | `kimi`, `opencode`, `commandcode` | a key pasted into `~/.dsh/.credentials.yaml` |
|
|
34
|
+
| OAuth via CLIProxyAPI | `xai`, `codex`, `agy` | **CLIProxyAPI installed and logged in once** |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 1. Verify the sidecar runs
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx @hystudio/dsh-quota-pill
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Expected first lines:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
[quota-pill] listening on http://127.0.0.1:8319
|
|
48
|
+
[quota-pill] credentials: /Users/<user>/.dsh/.credentials.yaml
|
|
49
|
+
[quota-pill] CLIProxyAPI: /Users/<user>/.cli-proxy-api ← or "not set up"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then, in another shell:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
curl -s http://127.0.0.1:8319/health
|
|
56
|
+
# {"ok":true,"port":8319,"providers":["kimi","opencode","commandcode","xai","codex","agy"]}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If `CLIProxyAPI: not set up`, the three OAuth providers will report "needs
|
|
60
|
+
CLIProxyAPI". That is expected on a fresh machine — tell the human that
|
|
61
|
+
`kimi` / `opencode` / `commandcode` work without it, and ask whether they want
|
|
62
|
+
the OAuth three as well.
|
|
63
|
+
|
|
64
|
+
**Keep it running.** Do not leave it in the foreground of a terminal the human
|
|
65
|
+
will close. Offer a background service (launchd on macOS, systemd on Linux):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# macOS: ~/Library/LaunchAgents/dev.quota-pill.plist
|
|
69
|
+
# ProgramArguments: ["/usr/bin/env","node","<abs path>/bin/quota-pill-server.js"]
|
|
70
|
+
# RunAtLoad: true
|
|
71
|
+
# KeepAlive: true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Ask before installing a service — that is a persistent change to their machine.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 2. Ask which providers the user actually has
|
|
79
|
+
|
|
80
|
+
Do **not** guess. Ask, in one message, listing the options with what each needs:
|
|
81
|
+
|
|
82
|
+
> I can read quota for six providers. Which do you have?
|
|
83
|
+
>
|
|
84
|
+
> - **Kimi Coding** — needs a `KIMI_CODING_API_KEY`
|
|
85
|
+
> - **OpenCode Go** — needs an `OPENCODE_GO_API_KEY`
|
|
86
|
+
> - **Command Code** — needs a `COMMANDCODE_API_KEY`
|
|
87
|
+
> - **xAI / Grok**, **Codex / ChatGPT Plus**, **Antigravity** — need CLIProxyAPI installed and logged in
|
|
88
|
+
>
|
|
89
|
+
> Tell me which ones, and paste the key for any of the first three.
|
|
90
|
+
|
|
91
|
+
If they have none of them: stop and say the plugin has nothing to show yet.
|
|
92
|
+
Do not install a fake provider to "make it look working".
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 3. Write the API keys
|
|
97
|
+
|
|
98
|
+
Keys live in `~/.dsh/.credentials.yaml` under `refs`. **Read the file first** —
|
|
99
|
+
it usually already exists and contains other credentials that must not be lost.
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
refs:
|
|
103
|
+
KIMI_CODING_API_KEY: sk-...
|
|
104
|
+
OPENCODE_GO_API_KEY: sk-...
|
|
105
|
+
COMMANDCODE_API_KEY: sk-...
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Rules:
|
|
109
|
+
|
|
110
|
+
- **Append or edit one line at a time.** Never rewrite the whole file from a
|
|
111
|
+
template — that would delete the user's other credentials.
|
|
112
|
+
- **Never echo a key back** into the chat, a log, or a commit. After writing,
|
|
113
|
+
verify only that the key is *present*, not what it is.
|
|
114
|
+
- If the file does not exist, create it with `chmod 600`.
|
|
115
|
+
|
|
116
|
+
Verify each one without printing it:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python3 - <<'PY'
|
|
120
|
+
import yaml, os
|
|
121
|
+
d = yaml.safe_load(open(os.path.expanduser('~/.dsh/.credentials.yaml')))
|
|
122
|
+
refs = d.get('refs') or {}
|
|
123
|
+
for k in ('KIMI_CODING_API_KEY','OPENCODE_GO_API_KEY','COMMANDCODE_API_KEY'):
|
|
124
|
+
print(f'{k}: ' + ('present' if refs.get(k) else 'MISSING'))
|
|
125
|
+
PY
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 4. Configure the OAuth three (only if asked for)
|
|
131
|
+
|
|
132
|
+
These read token files that **CLIProxyAPI** writes. This plugin never performs
|
|
133
|
+
the OAuth flow itself.
|
|
134
|
+
|
|
135
|
+
1. Check whether CLIProxyAPI is already there:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
ls ~/.cli-proxy-api/ 2>/dev/null
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
2. If the directory is missing, tell the human:
|
|
142
|
+
|
|
143
|
+
> xAI / Codex / Antigravity need CLIProxyAPI installed and logged in once.
|
|
144
|
+
> It writes tokens to `~/.cli-proxy-api/`, which is what I read.
|
|
145
|
+
> Install it, log into those services, then tell me — or skip them for now.
|
|
146
|
+
|
|
147
|
+
3. Once logged in, confirm the files appeared:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
ls ~/.cli-proxy-api/ | grep -E '^(xai|codex|antigravity)-'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
4. **Codex needs CLIProxyAPI to be *running***, not just installed. Codex quota
|
|
154
|
+
is read from CLIProxyAPI's management API (`/v0/management/auth-files`), which
|
|
155
|
+
reports the `X-Codex-*` headers CLIProxyAPI observed. Without it running, the
|
|
156
|
+
fallback hits `chatgpt.com`, which blocks non-browser TLS and returns 403.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 5. Verify end to end
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
curl -s 'http://127.0.0.1:8319/quota/all?fresh=1' | python3 -m json.tool | head -40
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
For each provider look at `kind`:
|
|
167
|
+
|
|
168
|
+
| `kind` | Meaning |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `subscription-quota` | working — `remainingPct` and `windows` are populated |
|
|
171
|
+
| `none` | not configured — the `error` field says exactly what to add |
|
|
172
|
+
| `probe-failed` | configured but the upstream call failed — see `error` |
|
|
173
|
+
| `payg` | metered billing with no ceiling; no percentage exists |
|
|
174
|
+
|
|
175
|
+
Cross-check one provider against its official dashboard if the human is unsure.
|
|
176
|
+
**The plugin reports remaining quota, not used.**
|
|
177
|
+
|
|
178
|
+
If a provider came back `none` with `no <REF>`, the key did not get written —
|
|
179
|
+
go back to step 3. Do not report success while any asked-for provider is `none`.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 6. Report back
|
|
184
|
+
|
|
185
|
+
Tell the human, per provider: how much is left and when it resets. Then state
|
|
186
|
+
plainly:
|
|
187
|
+
|
|
188
|
+
- which providers are working
|
|
189
|
+
- which are skipped, and the single action that would enable each
|
|
190
|
+
|
|
191
|
+
Do not paste raw JSON. Do not claim a provider works if it returned `none` or
|
|
192
|
+
`probe-failed`.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Troubleshooting
|
|
197
|
+
|
|
198
|
+
**Pill shows "quota service is not running"**
|
|
199
|
+
The sidecar is not up, or is on another port. Start it; if it must live on a
|
|
200
|
+
different port, set `window.__QUOTA_PILL_PORT__` or run with `QUOTA_PILL_PORT=…`
|
|
201
|
+
and set the same on the client side.
|
|
202
|
+
|
|
203
|
+
**`probe-failed` with http 403 / ECONNRESET**
|
|
204
|
+
Some upstreams (`chatgpt.com`, `googleapis`, `grok.com`) need either CLIProxyAPI
|
|
205
|
+
or a local proxy. Codex additionally needs CLIProxyAPI *running* for its
|
|
206
|
+
observed-headers route.
|
|
207
|
+
|
|
208
|
+
**`none` with "no … in ~/.dsh/.credentials.yaml"**
|
|
209
|
+
The key is missing. Steps above show the exact `refs.` name to add.
|
|
210
|
+
|
|
211
|
+
**Everything is `none` even though keys exist**
|
|
212
|
+
Check the sidecar's printed `credentials:` path — it may be reading a different
|
|
213
|
+
`DSH_HOME` than the one the user edited.
|
|
214
|
+
|
|
215
|
+
**Numbers look stale**
|
|
216
|
+
The sidecar caches for 60s. `?fresh=1` forces an upstream read. The pill does
|
|
217
|
+
this automatically when the session context changes.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 598934321
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,208 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-quota-pill
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A quota pill for the [DeepSeek Harness](https://github.com/deepseek-ai) web GUI:
|
|
4
|
+
**how much is left** on every LLM subscription you have, in one collapsible pill
|
|
5
|
+
next to the composer.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
It sits in the composer toolbar, shows the tightest window at a glance, and opens
|
|
10
|
+
into a per-provider breakdown with reset times. Switch sessions and it follows
|
|
11
|
+
the model — showing that provider's last reading while it refreshes, then easing
|
|
12
|
+
into the live number.
|
|
13
|
+
|
|
14
|
+
## What it reads
|
|
15
|
+
|
|
16
|
+
| Provider | Credential |
|
|
17
|
+
|---|---|
|
|
18
|
+
| **Kimi Coding** | `refs.KIMI_CODING_API_KEY` in `~/.dsh/.credentials.yaml` |
|
|
19
|
+
| **OpenCode Go** | `refs.OPENCODE_GO_API_KEY` |
|
|
20
|
+
| **Command Code** | `refs.COMMANDCODE_API_KEY` |
|
|
21
|
+
| **xAI (Grok)** | OAuth token from [CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) |
|
|
22
|
+
| **Codex (ChatGPT Plus)** | same — and CLIProxyAPI must be **running** |
|
|
23
|
+
| **Antigravity** | same |
|
|
24
|
+
|
|
25
|
+
The three API-key providers need nothing but the key. The three OAuth providers
|
|
26
|
+
need CLIProxyAPI installed and logged in, because that is what holds the tokens;
|
|
27
|
+
this plugin only reads them and never runs an OAuth flow itself.
|
|
28
|
+
|
|
29
|
+
Every provider is optional. Unconfigured ones say exactly what is missing instead
|
|
30
|
+
of showing a fake zero.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 1. the DSH plugin
|
|
36
|
+
dsh plugin add @hystudio/dsh-quota-pill
|
|
37
|
+
|
|
38
|
+
# 2. the sidecar (reads credentials, talks to upstream APIs)
|
|
39
|
+
npx @hystudio/dsh-quota-pill
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The pill shows **"quota service is not running"** with that exact command until
|
|
43
|
+
the sidecar is up. Keep it running in the background — see
|
|
44
|
+
[Running it as a service](#running-it-as-a-service).
|
|
45
|
+
|
|
46
|
+
Then add whichever keys you have:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
# ~/.dsh/.credentials.yaml
|
|
50
|
+
refs:
|
|
51
|
+
KIMI_CODING_API_KEY: sk-...
|
|
52
|
+
OPENCODE_GO_API_KEY: sk-...
|
|
53
|
+
COMMANDCODE_API_KEY: sk-...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Reload the DSH window. Done.
|
|
57
|
+
|
|
58
|
+
### Let an agent do it
|
|
59
|
+
|
|
60
|
+
The repo ships [`AGENTS.md`](AGENTS.md) — a step-by-step guide written for an AI
|
|
61
|
+
agent. Ask your agent to set the plugin up and it will detect what you already
|
|
62
|
+
have, ask only for what it cannot know (your keys), write them safely, and verify
|
|
63
|
+
each provider end to end.
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Read AGENTS.md in this repo and set up dsh-quota-pill for me.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Running it as a service
|
|
70
|
+
|
|
71
|
+
`npx` in a terminal dies with the terminal. Pick one:
|
|
72
|
+
|
|
73
|
+
**macOS (launchd)** — `~/Library/LaunchAgents/dev.quota-pill.plist`
|
|
74
|
+
|
|
75
|
+
```xml
|
|
76
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
77
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
78
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
79
|
+
<plist version="1.0"><dict>
|
|
80
|
+
<key>Label</key><string>dev.quota-pill</string>
|
|
81
|
+
<key>ProgramArguments</key>
|
|
82
|
+
<array>
|
|
83
|
+
<string>/usr/bin/env</string><string>node</string>
|
|
84
|
+
<string>/absolute/path/to/bin/quota-pill-server.js</string>
|
|
85
|
+
</array>
|
|
86
|
+
<key>RunAtLoad</key><true/>
|
|
87
|
+
<key>KeepAlive</key><true/>
|
|
88
|
+
</dict></plist>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
launchctl load ~/Library/LaunchAgents/dev.quota-pill.plist
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Linux (systemd)** — `~/.config/systemd/user/quota-pill.service`
|
|
96
|
+
|
|
97
|
+
```ini
|
|
98
|
+
[Unit]
|
|
99
|
+
Description=dsh-quota-pill sidecar
|
|
100
|
+
|
|
101
|
+
[Service]
|
|
102
|
+
ExecStart=/usr/bin/env node /absolute/path/to/bin/quota-pill-server.js
|
|
103
|
+
Restart=always
|
|
104
|
+
|
|
105
|
+
[Install]
|
|
106
|
+
WantedBy=default.target
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
systemctl --user enable --now quota-pill
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## How it works
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
DSH web GUI
|
|
117
|
+
└─ client.js renders the pill; never sees a credential
|
|
118
|
+
│ HTTP (localhost)
|
|
119
|
+
▼
|
|
120
|
+
sidecar reads ~/.dsh/.credentials.yaml and ~/.cli-proxy-api/*.json,
|
|
121
|
+
calls each provider's quota endpoint, caches 60s
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Two processes because credentials must never reach the browser, and because
|
|
125
|
+
upstream calls need real timeouts and a TLS stack Node's `fetch` does not have
|
|
126
|
+
for some hosts.
|
|
127
|
+
|
|
128
|
+
### Endpoints
|
|
129
|
+
|
|
130
|
+
| Path | Purpose |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `GET /health` | liveness + provider list |
|
|
133
|
+
| `GET /quota?model=<id>` | one provider's reading, selected by model prefix |
|
|
134
|
+
| `GET /quota/all` | every provider, concurrently |
|
|
135
|
+
| `GET /setup` | what each provider still needs |
|
|
136
|
+
|
|
137
|
+
`?fresh=1` bypasses the 60-second cache.
|
|
138
|
+
|
|
139
|
+
### Response
|
|
140
|
+
|
|
141
|
+
```jsonc
|
|
142
|
+
{
|
|
143
|
+
"kind": "subscription-quota", // subscription-quota | payg | none | probe-failed
|
|
144
|
+
"provider": "opencode",
|
|
145
|
+
"displayName": "OpenCode Go",
|
|
146
|
+
"remainingPct": 17, // remaining, never used
|
|
147
|
+
"window": "monthly", // the binding window
|
|
148
|
+
"resetAt": "2026-11-12T00:00:00.000Z",
|
|
149
|
+
"products": { "rolling": 9, "weekly": 67, "monthly": 83 }, // per-window used%
|
|
150
|
+
"windows": [ // one row each in the UI
|
|
151
|
+
{ "key": "monthly", "remainPct": 17, "resetAt": "..." }
|
|
152
|
+
],
|
|
153
|
+
"cached": false,
|
|
154
|
+
"at": 1792500000000
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`kind` is meant to be exhaustive so the UI never has to guess:
|
|
159
|
+
|
|
160
|
+
- `subscription-quota` — a real percentage exists
|
|
161
|
+
- `payg` — metered billing, no ceiling (shows spend, not a percentage)
|
|
162
|
+
- `none` — not configured; `error` names the missing credential
|
|
163
|
+
- `probe-failed` — configured but the upstream call failed
|
|
164
|
+
|
|
165
|
+
## Notes on specific providers
|
|
166
|
+
|
|
167
|
+
**Codex** is read through CLIProxyAPI's management API, which reports the
|
|
168
|
+
`X-Codex-*` headers CLIProxyAPI observed while proxying real traffic. The direct
|
|
169
|
+
`chatgpt.com/backend-api/codex/usage` endpoint sits behind Cloudflare and rejects
|
|
170
|
+
non-browser TLS fingerprints, so it only works as a fallback. CLIProxyAPI must be
|
|
171
|
+
*running*, not merely installed.
|
|
172
|
+
|
|
173
|
+
**xAI** has three account generations: grandfathered plans report a percentage
|
|
174
|
+
directly, current plans only reveal allowance in `x-ratelimit-*` response headers
|
|
175
|
+
of a one-token completion, and unified-billing accounts have no ceiling at all
|
|
176
|
+
(reported as `payg`).
|
|
177
|
+
|
|
178
|
+
**Antigravity** shares one quota pool across all Gemini models, so it reports a
|
|
179
|
+
single aggregate row — per-model rows would all be the same number and the label
|
|
180
|
+
would flicker between models you do not even have configured.
|
|
181
|
+
|
|
182
|
+
**Command Code** does not expose a monthly ceiling. The adapter derives it from
|
|
183
|
+
`monthlyCap = weekly.cap × 2`, an identity verified against two different plans
|
|
184
|
+
(31.6 + 38.4 = 70 with `weekly.cap` 35; 0.225 + 9.775 = 10 with `weekly.cap` 6).
|
|
185
|
+
|
|
186
|
+
## Privacy
|
|
187
|
+
|
|
188
|
+
- Credentials are read from disk, used for the upstream call, and never logged.
|
|
189
|
+
- The sidecar binds `127.0.0.1` only.
|
|
190
|
+
- Nothing is sent anywhere except the provider's own quota endpoint.
|
|
191
|
+
- The client shows no credential, and the sidecar's JSON carries no token.
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
git clone https://github.com/598934321/dsh-quota-pill
|
|
197
|
+
cd dsh-quota-pill
|
|
198
|
+
npm test # 26 tests, offline
|
|
199
|
+
npm start # sidecar on :8319
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Tests are offline by design: they point the credential layer at a nonexistent
|
|
203
|
+
directory so they never touch a live account. Fixtures in `test/fixtures.js` are
|
|
204
|
+
synthetic — no real emails, account ids, or balances.
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|