@slkiser/opencode-quota 2.7.1 → 2.9.1
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/README.md +182 -239
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api-key-resolver.d.ts +11 -0
- package/dist/lib/api-key-resolver.d.ts.map +1 -1
- package/dist/lib/api-key-resolver.js +17 -2
- package/dist/lib/api-key-resolver.js.map +1 -1
- package/dist/lib/chutes-config.d.ts +3 -3
- package/dist/lib/chutes-config.d.ts.map +1 -1
- package/dist/lib/chutes-config.js +9 -6
- package/dist/lib/chutes-config.js.map +1 -1
- package/dist/lib/chutes.d.ts.map +1 -1
- package/dist/lib/chutes.js +3 -2
- package/dist/lib/chutes.js.map +1 -1
- package/dist/lib/config.d.ts +7 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +80 -28
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/copilot.d.ts.map +1 -1
- package/dist/lib/copilot.js +4 -3
- package/dist/lib/copilot.js.map +1 -1
- package/dist/lib/cursor-detection.d.ts.map +1 -1
- package/dist/lib/cursor-detection.js +49 -5
- package/dist/lib/cursor-detection.js.map +1 -1
- package/dist/lib/cursor-pricing.d.ts +1 -0
- package/dist/lib/cursor-pricing.d.ts.map +1 -1
- package/dist/lib/cursor-pricing.js +8 -3
- package/dist/lib/cursor-pricing.js.map +1 -1
- package/dist/lib/display-sanitize.d.ts +10 -0
- package/dist/lib/display-sanitize.d.ts.map +1 -0
- package/dist/lib/display-sanitize.js +17 -0
- package/dist/lib/display-sanitize.js.map +1 -0
- package/dist/lib/entries.d.ts +1 -0
- package/dist/lib/entries.d.ts.map +1 -1
- package/dist/lib/env-template.d.ts +3 -2
- package/dist/lib/env-template.d.ts.map +1 -1
- package/dist/lib/env-template.js +6 -2
- package/dist/lib/env-template.js.map +1 -1
- package/dist/lib/firmware-config.d.ts +3 -3
- package/dist/lib/firmware-config.d.ts.map +1 -1
- package/dist/lib/firmware-config.js +9 -6
- package/dist/lib/firmware-config.js.map +1 -1
- package/dist/lib/firmware.d.ts.map +1 -1
- package/dist/lib/firmware.js +3 -11
- package/dist/lib/firmware.js.map +1 -1
- package/dist/lib/google-token-cache.js +2 -2
- package/dist/lib/google-token-cache.js.map +1 -1
- package/dist/lib/jsonc.d.ts +8 -1
- package/dist/lib/jsonc.d.ts.map +1 -1
- package/dist/lib/jsonc.js +12 -2
- package/dist/lib/jsonc.js.map +1 -1
- package/dist/lib/modelsdev-pricing.d.ts +8 -2
- package/dist/lib/modelsdev-pricing.d.ts.map +1 -1
- package/dist/lib/modelsdev-pricing.js +84 -29
- package/dist/lib/modelsdev-pricing.js.map +1 -1
- package/dist/lib/openai.d.ts.map +1 -1
- package/dist/lib/openai.js +3 -2
- package/dist/lib/openai.js.map +1 -1
- package/dist/lib/quota-stats-format.d.ts.map +1 -1
- package/dist/lib/quota-stats-format.js +30 -38
- package/dist/lib/quota-stats-format.js.map +1 -1
- package/dist/lib/quota-status.d.ts +2 -1
- package/dist/lib/quota-status.d.ts.map +1 -1
- package/dist/lib/quota-status.js +10 -1
- package/dist/lib/quota-status.js.map +1 -1
- package/dist/lib/types.d.ts +14 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +4 -0
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/zai.d.ts.map +1 -1
- package/dist/lib/zai.js +3 -2
- package/dist/lib/zai.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +303 -117
- package/dist/plugin.js.map +1 -1
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +3 -1
- package/dist/providers/cursor.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,24 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OpenCode Quota
|
|
2
2
|
|
|
3
3
|
`opencode-quota` gives you two things:
|
|
4
4
|
|
|
5
5
|
- Automatic quota toasts after assistant responses
|
|
6
|
-
- Manual `/quota
|
|
6
|
+
- Manual `/quota`, `/pricing_refresh`, and `/tokens_*` commands for deeper local reporting with zero context window pollution
|
|
7
|
+
|
|
8
|
+
**Quota providers**: GitHub Copilot, OpenAI (Plus/Pro), Cursor, Qwen Code, Alibaba Coding Plan, Chutes AI, Firmware AI, Google Antigravity, and Z.ai coding plan.
|
|
9
|
+
|
|
10
|
+
**Token reports**: All models and providers in [models.dev](https://models.dev), plus deterministic local pricing for Cursor Auto/Composer and Cursor model aliases that are not on models.dev.
|
|
11
|
+
|
|
12
|
+
<table>
|
|
13
|
+
<tr>
|
|
14
|
+
<td width="50%" align="center">Example of toast</td>
|
|
15
|
+
<td width="50%" align="center">Example of <code>/tokens_weekly</code></td>
|
|
16
|
+
</tr>
|
|
17
|
+
<tr>
|
|
18
|
+
<td width="50%">
|
|
19
|
+
<img src="https://github.com/slkiser/opencode-quota/blob/main/toasts.webp" alt="Image of opencode-quota toast" />
|
|
20
|
+
</td>
|
|
21
|
+
<td width="50%">
|
|
22
|
+
<img src="https://github.com/slkiser/opencode-quota/blob/main/tokens.webp" alt="Image of opencode-quota /tokens_weekly output" />
|
|
23
|
+
</td>
|
|
24
|
+
</tr>
|
|
25
|
+
</table>
|
|
7
26
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**Token provider supports**: All models and providers in [models.dev](https://models.dev), plus deterministic local pricing for Cursor Auto/Composer and Cursor model aliases that are not on models.dev.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-

|
|
14
|
-
|
|
15
|
-

|
|
27
|
+
Quota and `/tokens_*` output are computed from local OpenCode session history.
|
|
16
28
|
|
|
17
29
|
## Quick Start
|
|
18
30
|
|
|
19
|
-
OpenCode `>= 1.2.0` is required.
|
|
20
|
-
|
|
21
|
-
Add the plugin to your `opencode.json` or `opencode.jsonc`:
|
|
31
|
+
OpenCode `>= 1.2.0` is required. Add the plugin to your `opencode.json` or `opencode.jsonc`:
|
|
22
32
|
|
|
23
33
|
```jsonc
|
|
24
34
|
{
|
|
@@ -30,42 +40,93 @@ Then:
|
|
|
30
40
|
|
|
31
41
|
1. Restart or reload OpenCode.
|
|
32
42
|
2. Run `/quota_status` to confirm provider detection.
|
|
33
|
-
3. Run `/quota`
|
|
43
|
+
3. Run `/quota` or `/tokens_today`.
|
|
34
44
|
|
|
35
|
-
That is enough for most installs. Providers are auto-detected from your existing OpenCode setup.
|
|
45
|
+
That is enough for most installs. Providers are auto-detected from your existing OpenCode setup, and most providers work from your existing OpenCode auth. If a provider needs anything extra, use the setup table below.
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- Toasts after assistant responses, idle transitions, and compaction events
|
|
40
|
-
- `/quota` for a grouped manual quota report such as `[OpenAI] (Pro)` or `[Copilot] (business)`, with a local call timestamp in the heading
|
|
41
|
-
- `/tokens_*` commands backed by local OpenCode history and a local pricing snapshot, each with a local call timestamp in the heading
|
|
42
|
-
- No model calls to compute the toast or report output
|
|
47
|
+
<details>
|
|
48
|
+
<summary><strong>Example: Turn off auto-detection and choose providers</strong></summary>
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
```jsonc
|
|
51
|
+
{
|
|
52
|
+
"experimental": {
|
|
53
|
+
"quotaToast": {
|
|
54
|
+
"enabledProviders": ["copilot", "openai", "google-antigravity"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
45
59
|
|
|
46
|
-
|
|
60
|
+
</details>
|
|
47
61
|
|
|
48
|
-
|
|
62
|
+
<details>
|
|
63
|
+
<summary><strong>Example: Grouped toast layout instead of the default classic toast</strong></summary>
|
|
49
64
|
|
|
50
65
|
```jsonc
|
|
51
66
|
{
|
|
52
|
-
"
|
|
67
|
+
"experimental": {
|
|
68
|
+
"quotaToast": {
|
|
69
|
+
"toastStyle": "grouped"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
53
72
|
}
|
|
54
73
|
```
|
|
55
74
|
|
|
56
|
-
|
|
75
|
+
</details>
|
|
76
|
+
|
|
77
|
+
### Provider Setup At A Glance
|
|
57
78
|
|
|
58
|
-
|
|
79
|
+
| Provider | Auto setup | How it works |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| **GitHub Copilot** | Usually | OpenCode auth; PAT only for managed billing. |
|
|
82
|
+
| **OpenAI** | Yes | OpenCode auth. |
|
|
83
|
+
| **Cursor** | Needs [quick setup](#cursor-quick-setup) | Companion auth plugin + `provider.cursor`. |
|
|
84
|
+
| **Qwen Code** | Needs [quick setup](#qwen-code-quick-setup) | Companion auth plugin. |
|
|
85
|
+
| **Alibaba Coding Plan** | Yes | OpenCode auth + local request estimation. |
|
|
86
|
+
| **Firmware AI** | Usually | User/global OpenCode config or env; repo-local secrets ignored. |
|
|
87
|
+
| **Chutes AI** | Usually | User/global OpenCode config or env; repo-local secrets ignored. |
|
|
88
|
+
| **Google Antigravity** | Needs [quick setup](#google-antigravity-quick-setup) | Companion auth plugin. |
|
|
89
|
+
| **Z.ai** | Yes | OpenCode auth. |
|
|
90
|
+
|
|
91
|
+
<a id="cursor-quick-setup"></a>
|
|
92
|
+
<details>
|
|
93
|
+
<summary><strong>Quick setup: Cursor</strong></summary>
|
|
94
|
+
|
|
95
|
+
Cursor quota support requires the `opencode-cursor-oauth` [plugin](https://github.com/ephraimduncan/opencode-cursor):
|
|
59
96
|
|
|
60
97
|
```jsonc
|
|
61
98
|
{
|
|
62
|
-
"
|
|
99
|
+
"$schema": "https://opencode.ai/config.json",
|
|
100
|
+
"plugin": ["opencode-cursor-oauth", "@slkiser/opencode-quota"],
|
|
101
|
+
"provider": {
|
|
102
|
+
"cursor": {
|
|
103
|
+
"name": "Cursor"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"experimental": {
|
|
107
|
+
"quotaToast": {
|
|
108
|
+
"cursorPlan": "pro",
|
|
109
|
+
"cursorBillingCycleStartDay": 7
|
|
110
|
+
}
|
|
111
|
+
}
|
|
63
112
|
}
|
|
64
113
|
```
|
|
65
114
|
|
|
66
|
-
|
|
115
|
+
Then authenticate once:
|
|
67
116
|
|
|
68
|
-
|
|
117
|
+
```sh
|
|
118
|
+
opencode auth login --provider cursor
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For behavior details and troubleshooting, see [Cursor notes](#cursor-notes).
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
<a id="google-antigravity-quick-setup"></a>
|
|
126
|
+
<details>
|
|
127
|
+
<summary><strong>Quick setup: Google Antigravity</strong></summary>
|
|
128
|
+
|
|
129
|
+
Google quota support requires the `opencode-antigravity-auth` [plugin](https://github.com/NoeFabris/opencode-antigravity-auth):
|
|
69
130
|
|
|
70
131
|
```jsonc
|
|
71
132
|
{
|
|
@@ -73,9 +134,15 @@ Google quota support requires the `opencode-antigravity-auth` [companion auth pl
|
|
|
73
134
|
}
|
|
74
135
|
```
|
|
75
136
|
|
|
76
|
-
|
|
137
|
+
For behavior details and troubleshooting, see [Google Antigravity notes](#google-antigravity-notes).
|
|
138
|
+
|
|
139
|
+
</details>
|
|
140
|
+
|
|
141
|
+
<a id="qwen-code-quick-setup"></a>
|
|
142
|
+
<details>
|
|
143
|
+
<summary><strong>Quick setup: Qwen Code</strong></summary>
|
|
77
144
|
|
|
78
|
-
Qwen quota support requires the `opencode-qwencode-auth` [
|
|
145
|
+
Qwen quota support requires the `opencode-qwencode-auth` [plugin](https://github.com/gustavodiasdev/opencode-qwencode-auth):
|
|
79
146
|
|
|
80
147
|
```jsonc
|
|
81
148
|
{
|
|
@@ -83,7 +150,9 @@ Qwen quota support requires the `opencode-qwencode-auth` [companion auth plugin]
|
|
|
83
150
|
}
|
|
84
151
|
```
|
|
85
152
|
|
|
86
|
-
|
|
153
|
+
For behavior details and troubleshooting, see [Qwen Code notes](#qwen-code-notes).
|
|
154
|
+
|
|
155
|
+
</details>
|
|
87
156
|
|
|
88
157
|
## Commands
|
|
89
158
|
|
|
@@ -91,6 +160,7 @@ Quota and `/tokens_*` output are computed from local OpenCode session history.
|
|
|
91
160
|
| --- | --- |
|
|
92
161
|
| `/quota` | Manual grouped quota report with a local call timestamp |
|
|
93
162
|
| `/quota_status` | Concise diagnostics for config, provider availability, account detection, and pricing snapshot health |
|
|
163
|
+
| `/pricing_refresh` | Pull the local runtime pricing snapshot from `models.dev` on demand |
|
|
94
164
|
| `/tokens_today` | Tokens used today (calendar day) |
|
|
95
165
|
| `/tokens_daily` | Tokens used in the last 24 hours |
|
|
96
166
|
| `/tokens_weekly` | Tokens used in the last 7 days |
|
|
@@ -101,70 +171,21 @@ Quota and `/tokens_*` output are computed from local OpenCode session history.
|
|
|
101
171
|
|
|
102
172
|
There is no `/token` command. The reporting commands are the `/tokens_*` family.
|
|
103
173
|
|
|
104
|
-
## Minimal Config
|
|
105
|
-
|
|
106
|
-
You do not need extra config to get started. If you want to narrow the plugin to specific providers, use:
|
|
107
|
-
|
|
108
|
-
```jsonc
|
|
109
|
-
{
|
|
110
|
-
"experimental": {
|
|
111
|
-
"quotaToast": {
|
|
112
|
-
"enabledProviders": ["copilot", "openai", "google-antigravity"]
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
If you want grouped toast layout instead of the default classic toast:
|
|
119
|
-
|
|
120
|
-
```jsonc
|
|
121
|
-
{
|
|
122
|
-
"experimental": {
|
|
123
|
-
"quotaToast": {
|
|
124
|
-
"toastStyle": "grouped"
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
If Alibaba Coding Plan auth does not include a `tier`, you can set the fallback tier here:
|
|
131
|
-
|
|
132
|
-
```jsonc
|
|
133
|
-
{
|
|
134
|
-
"experimental": {
|
|
135
|
-
"quotaToast": {
|
|
136
|
-
"alibabaCodingPlanTier": "lite"
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
`/quota` already uses grouped formatting by default, even if toast style stays `classic`.
|
|
143
|
-
|
|
144
|
-
## Provider Setup At A Glance
|
|
145
|
-
|
|
146
|
-
| Provider | Works automatically | Extra setup when needed |
|
|
147
|
-
| --- | --- | --- |
|
|
148
|
-
| GitHub Copilot | Usually yes | Add `copilot-quota-token.json` only for managed org or enterprise billing |
|
|
149
|
-
| OpenAI | Yes | None |
|
|
150
|
-
| Cursor | Needs `opencode-cursor` | Optional `cursorPlan`, `cursorIncludedApiUsd`, and `cursorBillingCycleStartDay` for monthly API budget tracking |
|
|
151
|
-
| Qwen Code | Needs `opencode-qwencode-auth` | Local free-tier request estimation |
|
|
152
|
-
| Alibaba Coding Plan | Yes | Local request-count estimation |
|
|
153
|
-
| Firmware AI | Usually yes | Optional API key |
|
|
154
|
-
| Chutes AI | Usually yes | Optional API key |
|
|
155
|
-
| Google Antigravity | Needs `opencode-antigravity-auth` | Multi-account account file lives in OpenCode runtime config |
|
|
156
|
-
| Z.ai | Yes | None |
|
|
157
|
-
|
|
158
174
|
## Provider-Specific Notes
|
|
159
175
|
|
|
176
|
+
<a id="github-copilot-notes"></a>
|
|
160
177
|
<details>
|
|
161
178
|
<summary><strong>GitHub Copilot</strong></summary>
|
|
162
179
|
|
|
163
|
-
Personal
|
|
180
|
+
Personal quota works automatically when OpenCode is already signed in. Without `copilot-quota-token.json`, the plugin reads the OpenCode Copilot OAuth token from `~/.local/share/opencode/auth.json` and calls `GET https://api.github.com/copilot_internal/user`.
|
|
164
181
|
|
|
165
|
-
|
|
182
|
+
- Managed billing uses `copilot-quota-token.json` in the OpenCode runtime config directory (`opencode debug paths`). `business` requires `organization`; `enterprise` requires `enterprise` and can also filter by `organization` or `username`.
|
|
183
|
+
- `copilot-quota-token.json` takes precedence over OAuth. If the PAT config is invalid, the plugin reports that error and does not silently fall back.
|
|
184
|
+
- Output is labeled `[Copilot] (personal)` or `[Copilot] (business)`, and managed output includes the org or enterprise slug.
|
|
185
|
+
- Enterprise premium usage does not support fine-grained PATs or GitHub App tokens.
|
|
186
|
+
- Check `/quota_status` for `copilot_quota_auth`, `billing_mode`, `billing_scope`, `quota_api`, `effective_source`, and `billing_api_access_likely`.
|
|
166
187
|
|
|
167
|
-
|
|
188
|
+
Example `copilot-quota-token.json`:
|
|
168
189
|
|
|
169
190
|
```json
|
|
170
191
|
{
|
|
@@ -174,8 +195,6 @@ Organization example:
|
|
|
174
195
|
}
|
|
175
196
|
```
|
|
176
197
|
|
|
177
|
-
Enterprise example:
|
|
178
|
-
|
|
179
198
|
```json
|
|
180
199
|
{
|
|
181
200
|
"token": "ghp_...",
|
|
@@ -186,68 +205,21 @@ Enterprise example:
|
|
|
186
205
|
}
|
|
187
206
|
```
|
|
188
207
|
|
|
189
|
-
Behavior notes:
|
|
190
|
-
|
|
191
|
-
- Personal output is labeled `[Copilot] (personal)`.
|
|
192
|
-
- Managed organization and enterprise output is labeled `[Copilot] (business)`.
|
|
193
|
-
- Managed output includes the org or enterprise slug in the value line so the billing scope is still visible.
|
|
194
|
-
- If both OpenCode OAuth and `copilot-quota-token.json` exist, the PAT config wins.
|
|
195
|
-
- If no PAT config exists, OpenCode Copilot OAuth is treated as personal quota auth via `/copilot_internal/user`.
|
|
196
|
-
- If the PAT config is invalid, the plugin reports that error and does not silently fall back to OAuth.
|
|
197
|
-
- `business` requires `organization`.
|
|
198
|
-
- Enterprise premium usage does not support fine-grained PATs or GitHub App tokens. Use a supported enterprise token such as a classic PAT.
|
|
199
|
-
|
|
200
|
-
Useful checks:
|
|
201
|
-
|
|
202
|
-
- Run `/quota_status` and inspect `copilot_quota_auth`.
|
|
203
|
-
- Look for `billing_mode`, `billing_scope`, `quota_api`, `effective_source`, and `billing_api_access_likely`.
|
|
204
|
-
|
|
205
|
-
</details>
|
|
206
|
-
|
|
207
|
-
<details>
|
|
208
|
-
<summary><strong>OpenAI</strong></summary>
|
|
209
|
-
|
|
210
|
-
No extra setup is required if OpenCode already has OpenAI or ChatGPT auth configured.
|
|
211
|
-
|
|
212
208
|
</details>
|
|
213
209
|
|
|
210
|
+
<a id="cursor-notes"></a>
|
|
214
211
|
<details>
|
|
215
212
|
<summary><strong>Cursor</strong></summary>
|
|
216
213
|
|
|
217
|
-
Cursor
|
|
218
|
-
|
|
219
|
-
Recommended install path:
|
|
220
|
-
|
|
221
|
-
- Follow Option B from the upstream [`opencode-cursor` README](https://github.com/Nomadcxx/opencode-cursor).
|
|
222
|
-
- Keep the Cursor model list in sync with `cursor-agent models`.
|
|
223
|
-
|
|
224
|
-
Current behavior:
|
|
225
|
-
|
|
226
|
-
- Detects Cursor usage from OpenCode history when the current model or stored message model is `cursor-acp/*`
|
|
227
|
-
- `/tokens_*` maps Cursor API-pool models into official pricing and uses bundled static rates for `auto` and `composer*`
|
|
228
|
-
- `/quota` and toasts estimate the current billing-cycle spend from local OpenCode history
|
|
229
|
-
- Percentage remaining is shown only when you configure `cursorPlan` or `cursorIncludedApiUsd`
|
|
230
|
-
- Billing cycle defaults to the local calendar month unless you set `cursorBillingCycleStartDay`
|
|
214
|
+
See [Cursor quick setup](#cursor-quick-setup) for auth. Quota and token reporting stays local to OpenCode history and local pricing data.
|
|
231
215
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
- Session cookies and
|
|
235
|
-
-
|
|
236
|
-
|
|
237
|
-
Example config for a personal Pro account:
|
|
238
|
-
|
|
239
|
-
```jsonc
|
|
240
|
-
{
|
|
241
|
-
"experimental": {
|
|
242
|
-
"quotaToast": {
|
|
243
|
-
"cursorPlan": "pro",
|
|
244
|
-
"cursorBillingCycleStartDay": 7
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
```
|
|
216
|
+
- Detects Cursor usage when the provider is `cursor` or the stored/current model id is `cursor/*`.
|
|
217
|
+
- `/tokens_*` maps Cursor API-pool models to official pricing and uses bundled static pricing for `auto` and `composer*`.
|
|
218
|
+
- `/quota` and toasts estimate the current billing-cycle spend from local history only. Session cookies and team APIs are not required.
|
|
219
|
+
- Remaining percentage appears only when `experimental.quotaToast.cursorPlan` or `experimental.quotaToast.cursorIncludedApiUsd` is set. Billing cycle defaults to the local calendar month unless `experimental.quotaToast.cursorBillingCycleStartDay` is set.
|
|
220
|
+
- Legacy `cursor-acp/*` history remains readable. Unknown future Cursor model ids appear in `/quota_status` under Cursor diagnostics and `unknown_pricing`.
|
|
249
221
|
|
|
250
|
-
|
|
222
|
+
Example override:
|
|
251
223
|
|
|
252
224
|
```jsonc
|
|
253
225
|
{
|
|
@@ -262,49 +234,57 @@ If you need a custom included API budget, override it directly:
|
|
|
262
234
|
|
|
263
235
|
</details>
|
|
264
236
|
|
|
237
|
+
<a id="qwen-code-notes"></a>
|
|
265
238
|
<details>
|
|
266
239
|
<summary><strong>Qwen Code</strong></summary>
|
|
267
240
|
|
|
268
|
-
Qwen
|
|
269
|
-
|
|
270
|
-
Current behavior:
|
|
271
|
-
|
|
272
|
-
- Free tier only: 1000 requests per UTC day
|
|
273
|
-
- Free tier only: 60 requests per rolling minute
|
|
274
|
-
- Counters increment on successful question-tool completions while the current model is `qwen-code/*`
|
|
275
|
-
|
|
276
|
-
State file path:
|
|
241
|
+
See [Qwen Code quick setup](#qwen-code-quick-setup) for auth. Usage is local-only estimation for the free plan; the plugin does not call an Alibaba quota API.
|
|
277
242
|
|
|
278
|
-
-
|
|
279
|
-
|
|
280
|
-
|
|
243
|
+
- Free tier limits: `1000` requests per UTC day and `60` requests per rolling minute.
|
|
244
|
+
- Counters increment on successful question-tool completions while the current model is `qwen-code/*`.
|
|
245
|
+
- State file: `.../opencode/opencode-quota/qwen-local-quota.json`.
|
|
246
|
+
- Check `/quota_status` for auth detection, `qwen_local_plan`, and local counter state.
|
|
281
247
|
|
|
282
248
|
</details>
|
|
283
249
|
|
|
250
|
+
<a id="alibaba-coding-plan-notes"></a>
|
|
284
251
|
<details>
|
|
285
252
|
<summary><strong>Alibaba Coding Plan</strong></summary>
|
|
286
253
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
Supported tiers:
|
|
290
|
-
|
|
291
|
-
- `lite`: 1200 requests / 5 hours, 9000 / week, 18000 / month
|
|
292
|
-
- `pro`: 6000 requests / 5 hours, 45000 / week, 90000 / month
|
|
293
|
-
- If `tier` is missing from auth, the plugin uses `experimental.quotaToast.alibabaCodingPlanTier` and defaults that setting to `lite`
|
|
294
|
-
- Counters increment on successful question-tool completions while the current model is `alibaba/*` or `alibaba-cn/*`
|
|
254
|
+
Uses native OpenCode auth from `alibaba` or `alibaba-coding-plan`. Quota is local request-count estimation with rolling windows.
|
|
295
255
|
|
|
296
|
-
|
|
256
|
+
- `lite`: `1200 / 5h`, `9000 / week`, `18000 / month`
|
|
257
|
+
- `pro`: `6000 / 5h`, `45000 / week`, `90000 / month`
|
|
258
|
+
- If auth omits `tier`, the plugin uses `experimental.quotaToast.alibabaCodingPlanTier`, which defaults to `lite`.
|
|
259
|
+
- Counters increment on successful question-tool completions while the current model is `alibaba/*` or `alibaba-cn/*`.
|
|
260
|
+
- State file: `.../opencode/opencode-quota/alibaba-coding-plan-local-quota.json`.
|
|
261
|
+
- `/quota_status` shows auth detection, resolved tier, state-file path, and current 5h/weekly/monthly usage.
|
|
297
262
|
|
|
298
|
-
|
|
263
|
+
Example fallback tier:
|
|
299
264
|
|
|
300
|
-
|
|
265
|
+
```jsonc
|
|
266
|
+
{
|
|
267
|
+
"experimental": {
|
|
268
|
+
"quotaToast": {
|
|
269
|
+
"alibabaCodingPlanTier": "lite"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
301
274
|
|
|
302
275
|
</details>
|
|
303
276
|
|
|
277
|
+
<a id="firmware-ai-notes"></a>
|
|
304
278
|
<details>
|
|
305
279
|
<summary><strong>Firmware AI</strong></summary>
|
|
306
280
|
|
|
307
|
-
If OpenCode already has Firmware configured, it usually works automatically.
|
|
281
|
+
If OpenCode already has Firmware configured, it usually works automatically. Optional API key: `provider.firmware.options.apiKey`.
|
|
282
|
+
|
|
283
|
+
For security, provider secrets are read from environment variables or your user/global OpenCode config only. Repo-local `opencode.json` / `opencode.jsonc` is ignored for `provider.firmware.options.apiKey`.
|
|
284
|
+
|
|
285
|
+
Allowed env templates are limited to `{env:FIRMWARE_AI_API_KEY}` and `{env:FIRMWARE_API_KEY}`.
|
|
286
|
+
|
|
287
|
+
Example user/global config (`~/.config/opencode/opencode.jsonc` on Linux/macOS):
|
|
308
288
|
|
|
309
289
|
```jsonc
|
|
310
290
|
{
|
|
@@ -314,23 +294,23 @@ If OpenCode already has Firmware configured, it usually works automatically. You
|
|
|
314
294
|
"apiKey": "{env:FIRMWARE_API_KEY}"
|
|
315
295
|
}
|
|
316
296
|
}
|
|
317
|
-
},
|
|
318
|
-
"experimental": {
|
|
319
|
-
"quotaToast": {
|
|
320
|
-
"enabledProviders": ["firmware"]
|
|
321
|
-
}
|
|
322
297
|
}
|
|
323
298
|
}
|
|
324
299
|
```
|
|
325
300
|
|
|
326
|
-
`{env:VAR_NAME}` and direct keys are both supported.
|
|
327
|
-
|
|
328
301
|
</details>
|
|
329
302
|
|
|
303
|
+
<a id="chutes-ai-notes"></a>
|
|
330
304
|
<details>
|
|
331
305
|
<summary><strong>Chutes AI</strong></summary>
|
|
332
306
|
|
|
333
|
-
If OpenCode already has Chutes configured, it usually works automatically.
|
|
307
|
+
If OpenCode already has Chutes configured, it usually works automatically. Optional API key: `provider.chutes.options.apiKey`.
|
|
308
|
+
|
|
309
|
+
For security, provider secrets are read from environment variables or your user/global OpenCode config only. Repo-local `opencode.json` / `opencode.jsonc` is ignored for `provider.chutes.options.apiKey`.
|
|
310
|
+
|
|
311
|
+
Allowed env templates are limited to `{env:CHUTES_API_KEY}`.
|
|
312
|
+
|
|
313
|
+
Example user/global config (`~/.config/opencode/opencode.jsonc` on Linux/macOS):
|
|
334
314
|
|
|
335
315
|
```jsonc
|
|
336
316
|
{
|
|
@@ -340,30 +320,19 @@ If OpenCode already has Chutes configured, it usually works automatically. You c
|
|
|
340
320
|
"apiKey": "{env:CHUTES_API_KEY}"
|
|
341
321
|
}
|
|
342
322
|
}
|
|
343
|
-
},
|
|
344
|
-
"experimental": {
|
|
345
|
-
"quotaToast": {
|
|
346
|
-
"enabledProviders": ["chutes"]
|
|
347
|
-
}
|
|
348
323
|
}
|
|
349
324
|
}
|
|
350
325
|
```
|
|
351
326
|
|
|
352
327
|
</details>
|
|
353
328
|
|
|
329
|
+
<a id="google-antigravity-notes"></a>
|
|
354
330
|
<details>
|
|
355
331
|
<summary><strong>Google Antigravity</strong></summary>
|
|
356
332
|
|
|
357
|
-
|
|
333
|
+
See [Google Antigravity quick setup](#google-antigravity-quick-setup). Credentials live under the OpenCode runtime config directory.
|
|
358
334
|
|
|
359
|
-
If
|
|
360
|
-
|
|
361
|
-
</details>
|
|
362
|
-
|
|
363
|
-
<details>
|
|
364
|
-
<summary><strong>Z.ai</strong></summary>
|
|
365
|
-
|
|
366
|
-
No extra setup is required if OpenCode already has Z.ai configured.
|
|
335
|
+
If detection looks wrong, `/quota_status` prints the candidate paths checked for `antigravity-accounts.json`.
|
|
367
336
|
|
|
368
337
|
</details>
|
|
369
338
|
|
|
@@ -371,9 +340,11 @@ No extra setup is required if OpenCode already has Z.ai configured.
|
|
|
371
340
|
|
|
372
341
|
All plugin settings live under `experimental.quotaToast`.
|
|
373
342
|
|
|
343
|
+
Workspace-local config can still customize display/report behavior, but user/global config is authoritative for network-affecting settings such as `enabled`, `enabledProviders`, `minIntervalMs`, `pricingSnapshot`, `showOnIdle`, `showOnQuestion`, and `showOnCompact`.
|
|
344
|
+
|
|
374
345
|
| Option | Default | Meaning |
|
|
375
346
|
| --- | --- | --- |
|
|
376
|
-
| `enabled` | `true` | Master switch for the plugin. When `false`, `/quota`, `/quota_status`, and `/tokens_*` are no-ops. |
|
|
347
|
+
| `enabled` | `true` | Master switch for the plugin. When `false`, `/quota`, `/quota_status`, `/pricing_refresh`, and `/tokens_*` are no-ops. |
|
|
377
348
|
| `enableToast` | `true` | Show popup toasts |
|
|
378
349
|
| `toastStyle` | `classic` | Toast layout: `classic` or `grouped` |
|
|
379
350
|
| `enabledProviders` | `"auto"` | Auto-detect providers, or set an explicit provider list |
|
|
@@ -393,33 +364,26 @@ All plugin settings live under `experimental.quotaToast`.
|
|
|
393
364
|
| `cursorPlan` | `"none"` | Cursor included API budget preset: `none`, `pro`, `pro-plus`, `ultra` |
|
|
394
365
|
| `cursorIncludedApiUsd` | unset | Override Cursor monthly included API budget in USD |
|
|
395
366
|
| `cursorBillingCycleStartDay` | unset | Local billing-cycle anchor day `1..28`; when unset, Cursor usage resets on the local calendar month |
|
|
367
|
+
| `pricingSnapshot.source` | `"auto"` | Token pricing snapshot selection: `auto`, `bundled`, or `runtime` |
|
|
368
|
+
| `pricingSnapshot.autoRefresh` | `5` | Refresh stale local pricing data after this many days |
|
|
396
369
|
| `debug` | `false` | Include debug context in toast output |
|
|
397
370
|
|
|
398
371
|
## Token Pricing Snapshot
|
|
399
372
|
|
|
400
|
-
`/tokens_*` uses a local `models.dev` pricing snapshot
|
|
373
|
+
`/tokens_*` uses a local `models.dev` pricing snapshot. A bundled snapshot ships for offline use, and Cursor `auto` and `composer*` pricing stays bundled because those ids are not on `models.dev`.
|
|
401
374
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
- Cursor `auto` and `composer*` pricing is bundled in the plugin because those ids are not on `models.dev`.
|
|
408
|
-
|
|
409
|
-
Useful environment variables:
|
|
410
|
-
|
|
411
|
-
```sh
|
|
412
|
-
OPENCODE_QUOTA_PRICING_AUTO_REFRESH=0
|
|
413
|
-
OPENCODE_QUOTA_PRICING_MAX_AGE_DAYS=5
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
Maintainer refresh commands:
|
|
375
|
+
| `pricingSnapshot.source` | Active pricing behavior |
|
|
376
|
+
| --- | --- |
|
|
377
|
+
| `auto` | Newer runtime snapshot wins; otherwise bundled pricing stays active. |
|
|
378
|
+
| `bundled` | Packaged bundled snapshot stays active. |
|
|
379
|
+
| `runtime` | Runtime snapshot stays active when present; bundled pricing is fallback until one exists. |
|
|
417
380
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
381
|
+
- See [Configuration Reference](#configuration-reference) for option defaults.
|
|
382
|
+
- `pricingSnapshot.autoRefresh` controls how many days a runtime snapshot can age before background refresh.
|
|
383
|
+
- `/pricing_refresh` refreshes only the local runtime snapshot under the OpenCode cache directory. It never rewrites the packaged bundled snapshot.
|
|
384
|
+
- If `pricingSnapshot.source` is `bundled`, `/pricing_refresh` still updates the runtime cache, but active pricing stays bundled.
|
|
385
|
+
- Reports keep working if refresh fails.
|
|
386
|
+
- Pricing selection stays local and deterministic. There are no custom URLs or arbitrary pricing sources.
|
|
423
387
|
|
|
424
388
|
## Troubleshooting
|
|
425
389
|
|
|
@@ -429,42 +393,21 @@ If something is missing or looks wrong:
|
|
|
429
393
|
2. Confirm the expected provider appears in the detected provider list.
|
|
430
394
|
3. If token reports are empty, make sure OpenCode has already created `opencode.db`.
|
|
431
395
|
4. If Copilot managed billing is expected, confirm `copilot-quota-token.json` is present and valid.
|
|
432
|
-
5. If Google or Qwen
|
|
396
|
+
5. If provider setup looks wrong, check [Provider Setup At A Glance](#provider-setup-at-a-glance) and [Provider-Specific Notes](#provider-specific-notes). For Google Antigravity or Qwen Code, confirm the companion auth plugin is installed. For Alibaba Coding Plan, confirm OpenCode `alibaba` or `alibaba-coding-plan` auth is configured; `tier` may be `lite` or `pro`, and if it is missing the plugin falls back to `experimental.quotaToast.alibabaCodingPlanTier`.
|
|
433
397
|
|
|
434
398
|
If `opencode.db` is missing, start OpenCode once and let its local migration complete.
|
|
435
399
|
|
|
436
|
-
##
|
|
437
|
-
|
|
438
|
-
```sh
|
|
439
|
-
npm install
|
|
440
|
-
npm run typecheck
|
|
441
|
-
npm test
|
|
442
|
-
npm run build
|
|
443
|
-
```
|
|
400
|
+
## Contribution
|
|
444
401
|
|
|
445
402
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution workflow and repository policy.
|
|
446
403
|
|
|
447
|
-
## LLM Agent Installation Notes
|
|
448
|
-
|
|
449
|
-
If you are using an agent to install the plugin for you, the safe default is:
|
|
450
|
-
|
|
451
|
-
```jsonc
|
|
452
|
-
{
|
|
453
|
-
"plugin": ["@slkiser/opencode-quota"]
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
Then verify with `/quota_status`.
|
|
458
|
-
|
|
459
|
-
Only add explicit `enabledProviders` if you want to limit which providers are queried. Only add companion plugins when the user actually uses Google Antigravity or Qwen Code, and only add `@rama_nigg/open-cursor` when the user actually uses Cursor models in OpenCode.
|
|
460
|
-
|
|
461
404
|
## License
|
|
462
405
|
|
|
463
406
|
MIT
|
|
464
407
|
|
|
465
408
|
## Remarks
|
|
466
409
|
|
|
467
|
-
|
|
410
|
+
OpenCode Quota is not built by the OpenCode team and is not affiliated with OpenCode or any provider listed above.
|
|
468
411
|
|
|
469
412
|
## Star History
|
|
470
413
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
8
|
export { QuotaToastPlugin } from "./plugin.js";
|
|
9
|
-
export type { QuotaToastConfig, GoogleModelId, CopilotEnterpriseUsageResult, CopilotOrganizationUsageResult, CopilotQuotaResult, GoogleQuotaResult, GoogleModelQuota, } from "./lib/types.js";
|
|
9
|
+
export type { QuotaToastConfig, GoogleModelId, PricingSnapshotSource, CopilotEnterpriseUsageResult, CopilotOrganizationUsageResult, CopilotQuotaResult, GoogleQuotaResult, GoogleModelQuota, } from "./lib/types.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,4BAA4B,EAC5B,8BAA8B,EAC9B,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,4BAA4B,EAC5B,8BAA8B,EAC9B,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAc/C,yEAAyE;AACzE,wCAAwC;AAExC,6EAA6E;AAC7E,uFAAuF"}
|
|
@@ -16,6 +16,13 @@ export interface ConfigCandidate {
|
|
|
16
16
|
* Within each location, .jsonc takes precedence over .json.
|
|
17
17
|
*/
|
|
18
18
|
export declare function getOpencodeConfigCandidatePaths(): ConfigCandidate[];
|
|
19
|
+
/**
|
|
20
|
+
* Get trusted global-only candidate paths for opencode.json/opencode.jsonc files.
|
|
21
|
+
*
|
|
22
|
+
* Provider secrets must not be sourced from repo-local config because the
|
|
23
|
+
* current workspace may be untrusted.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getGlobalOpencodeConfigCandidatePaths(): ConfigCandidate[];
|
|
19
26
|
/**
|
|
20
27
|
* Read and parse an opencode config file.
|
|
21
28
|
*
|
|
@@ -50,6 +57,8 @@ export interface ResolveApiKeyConfig<Source extends string> {
|
|
|
50
57
|
extractFromAuth: (auth: unknown) => string | null;
|
|
51
58
|
/** Source label for auth.json */
|
|
52
59
|
authSource: Source;
|
|
60
|
+
/** Candidate config file paths to trust for provider-secret lookup. */
|
|
61
|
+
getConfigCandidates?: () => ConfigCandidate[];
|
|
53
62
|
}
|
|
54
63
|
/**
|
|
55
64
|
* Resolve an API key from multiple sources with consistent priority.
|
|
@@ -68,6 +77,8 @@ export interface DiagnosticsConfig<Source extends string> {
|
|
|
68
77
|
envVarNames: string[];
|
|
69
78
|
/** Resolver function to get the current key result */
|
|
70
79
|
resolve: () => Promise<ApiKeyResult<Source> | null>;
|
|
80
|
+
/** Candidate config file paths to report for provider-secret lookup. */
|
|
81
|
+
getConfigCandidates?: () => ConfigCandidate[];
|
|
71
82
|
}
|
|
72
83
|
/**
|
|
73
84
|
* Get diagnostic info about API key configuration.
|