opencode-quotas 0.0.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 +344 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +42 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +9 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +15 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/defaults.d.ts +3 -0
- package/dist/src/defaults.d.ts.map +1 -0
- package/dist/src/defaults.js +52 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +265 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +197 -0
- package/dist/src/interfaces.d.ts.map +1 -0
- package/dist/src/interfaces.js +2 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/logger.d.ts +14 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +44 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/plugin-state.d.ts +20 -0
- package/dist/src/plugin-state.d.ts.map +1 -0
- package/dist/src/plugin-state.js +53 -0
- package/dist/src/plugin-state.js.map +1 -0
- package/dist/src/providers/antigravity/auth.d.ts +12 -0
- package/dist/src/providers/antigravity/auth.d.ts.map +1 -0
- package/dist/src/providers/antigravity/auth.js +109 -0
- package/dist/src/providers/antigravity/auth.js.map +1 -0
- package/dist/src/providers/antigravity/index.d.ts +2 -0
- package/dist/src/providers/antigravity/index.d.ts.map +1 -0
- package/dist/src/providers/antigravity/index.js +2 -0
- package/dist/src/providers/antigravity/index.js.map +1 -0
- package/dist/src/providers/antigravity/provider.d.ts +34 -0
- package/dist/src/providers/antigravity/provider.d.ts.map +1 -0
- package/dist/src/providers/antigravity/provider.js +216 -0
- package/dist/src/providers/antigravity/provider.js.map +1 -0
- package/dist/src/providers/codex.d.ts +4 -0
- package/dist/src/providers/codex.d.ts.map +1 -0
- package/dist/src/providers/codex.js +242 -0
- package/dist/src/providers/codex.js.map +1 -0
- package/dist/src/providers/github.d.ts +4 -0
- package/dist/src/providers/github.d.ts.map +1 -0
- package/dist/src/providers/github.js +139 -0
- package/dist/src/providers/github.js.map +1 -0
- package/dist/src/quota-cache.d.ts +26 -0
- package/dist/src/quota-cache.d.ts.map +1 -0
- package/dist/src/quota-cache.js +107 -0
- package/dist/src/quota-cache.js.map +1 -0
- package/dist/src/registry.d.ts +3 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +23 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/services/aggregation-service.d.ts +34 -0
- package/dist/src/services/aggregation-service.d.ts.map +1 -0
- package/dist/src/services/aggregation-service.js +89 -0
- package/dist/src/services/aggregation-service.js.map +1 -0
- package/dist/src/services/config-loader.d.ts +25 -0
- package/dist/src/services/config-loader.d.ts.map +1 -0
- package/dist/src/services/config-loader.js +105 -0
- package/dist/src/services/config-loader.js.map +1 -0
- package/dist/src/services/history-service.d.ts +15 -0
- package/dist/src/services/history-service.d.ts.map +1 -0
- package/dist/src/services/history-service.js +99 -0
- package/dist/src/services/history-service.js.map +1 -0
- package/dist/src/services/prediction-engine.d.ts +47 -0
- package/dist/src/services/prediction-engine.d.ts.map +1 -0
- package/dist/src/services/prediction-engine.js +94 -0
- package/dist/src/services/prediction-engine.js.map +1 -0
- package/dist/src/services/quota-service.d.ts +41 -0
- package/dist/src/services/quota-service.d.ts.map +1 -0
- package/dist/src/services/quota-service.js +257 -0
- package/dist/src/services/quota-service.js.map +1 -0
- package/dist/src/tools/quotas.d.ts +11 -0
- package/dist/src/tools/quotas.d.ts.map +1 -0
- package/dist/src/tools/quotas.js +62 -0
- package/dist/src/tools/quotas.js.map +1 -0
- package/dist/src/ui/progress-bar.d.ts +20 -0
- package/dist/src/ui/progress-bar.d.ts.map +1 -0
- package/dist/src/ui/progress-bar.js +150 -0
- package/dist/src/ui/progress-bar.js.map +1 -0
- package/dist/src/ui/quota-table.d.ts +15 -0
- package/dist/src/ui/quota-table.d.ts.map +1 -0
- package/dist/src/ui/quota-table.js +136 -0
- package/dist/src/ui/quota-table.js.map +1 -0
- package/dist/src/utils/debug.d.ts +1 -0
- package/dist/src/utils/debug.d.ts.map +1 -0
- package/dist/src/utils/debug.js +3 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/paths.d.ts +7 -0
- package/dist/src/utils/paths.d.ts.map +1 -0
- package/dist/src/utils/paths.js +37 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/time.d.ts +3 -0
- package/dist/src/utils/time.d.ts.map +1 -0
- package/dist/src/utils/time.js +38 -0
- package/dist/src/utils/time.js.map +1 -0
- package/dist/src/utils/validation.d.ts +6 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +66 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/package.json +42 -0
- package/src/cli.ts +53 -0
- package/src/constants.ts +17 -0
- package/src/defaults.ts +53 -0
- package/src/index.ts +338 -0
- package/src/interfaces.ts +258 -0
- package/src/logger.ts +55 -0
- package/src/plugin-state.ts +65 -0
- package/src/providers/antigravity/auth.ts +163 -0
- package/src/providers/antigravity/index.ts +1 -0
- package/src/providers/antigravity/provider.ts +337 -0
- package/src/providers/codex.ts +327 -0
- package/src/providers/github.ts +161 -0
- package/src/quota-cache.ts +157 -0
- package/src/registry.ts +30 -0
- package/src/services/aggregation-service.ts +116 -0
- package/src/services/config-loader.ts +124 -0
- package/src/services/history-service.ts +116 -0
- package/src/services/prediction-engine.ts +133 -0
- package/src/services/quota-service.ts +343 -0
- package/src/tools/quotas.ts +78 -0
- package/src/ui/progress-bar.ts +204 -0
- package/src/ui/quota-table.ts +173 -0
- package/src/utils/debug.ts +1 -0
- package/src/utils/paths.ts +41 -0
- package/src/utils/time.ts +40 -0
- package/src/utils/validation.ts +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# OpenCode Quotas Plugin
|
|
2
|
+
|
|
3
|
+
**The ultimate usage dashboard plugin for your AI coding assistants.**
|
|
4
|
+
|
|
5
|
+
**OpenCode Quotas** is an OpenCode.ai plugin that aggregates usage data from Antigravity, Codex, and GitHub Copilot into a single, beautiful dashboard injected directly into your OpenCode chat footer. Never hit a rate limit unexpectedly again.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
> **Note**: This is a community-developed plugin and is not officially affiliated with OpenCode.ai.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Unified Dashboard**: See all your AI quotas (Antigravity, Codex, Copilot) in one place.
|
|
14
|
+
- **Smart Predictions**: Uses linear regression on usage history to predict when you'll exhaust your quota.
|
|
15
|
+
- **Visual Progress Bars**: ANSI-colored bars that change from green to yellow to red as you approach limits.
|
|
16
|
+
- **Context Aware**: Optionally filter quotas to show only those relevant to the active model.
|
|
17
|
+
- **Resilient**: Provider failures are isolated and won't break your chat experience.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### 1. Clone & Build
|
|
22
|
+
Clone the repository into your OpenCode plugins directory and build it:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Clone into your plugins directory
|
|
26
|
+
git clone https://github.com/your-org/opencode-quotas ~/.opencode/plugins/opencode-quotas
|
|
27
|
+
|
|
28
|
+
# Build the plugin
|
|
29
|
+
cd ~/.opencode/plugins/opencode-quotas
|
|
30
|
+
bun install
|
|
31
|
+
npm run build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Register the Plugin
|
|
35
|
+
Add `opencode-quotas` to your OpenCode configuration file (typically `~/.opencode/config.json`) under the `plugins` array:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"plugin": [
|
|
40
|
+
"opencode-antigravity-auth",
|
|
41
|
+
"opencode-quotas"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
Once installed and registered, a live quota summary is automatically appended to every assistant message footer in OpenCode. No further action is required.
|
|
49
|
+
|
|
50
|
+
### CLI Mode (Optional)
|
|
51
|
+
|
|
52
|
+
You can also use OpenCode Quotas as a standalone CLI tool to check quotas directly from your terminal:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Show all quotas
|
|
56
|
+
opencode-quotas
|
|
57
|
+
|
|
58
|
+
# Filter by model (simulates what the plugin does automatically)
|
|
59
|
+
opencode-quotas --provider google --model antigravity-gemini-3-flash
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **Tip**: During development, use `bun run opencode-quotas` to run without building.
|
|
63
|
+
|
|
64
|
+
## Supported Providers
|
|
65
|
+
|
|
66
|
+
| Provider | Raw Quota IDs | Aggregated IDs | Description |
|
|
67
|
+
| :--- | :--- | :--- | :--- |
|
|
68
|
+
| **Antigravity** | `ag-raw-*` | `ag-flash`, `ag-pro`, `ag-premium` | Raw model quotas aggregated by pattern into Flash, Pro, and Premium tiers. |
|
|
69
|
+
| **Codex** | `codex-primary`, `codex-secondary` | `codex-smart` | Rate limits aggregated using most-critical strategy. |
|
|
70
|
+
| **GitHub Copilot** | — | — | ⚠️ Not yet implemented. |
|
|
71
|
+
|
|
72
|
+
> **Note**: Quota IDs are used in configuration options like `disabled` and `modelMapping`.
|
|
73
|
+
|
|
74
|
+
## Column Reference
|
|
75
|
+
|
|
76
|
+
| Column | Description |
|
|
77
|
+
| :--- | :--- |
|
|
78
|
+
| `status` | Health indicator: `OK` (normal), `WRN` (warning), `ERR` (at/over limit) |
|
|
79
|
+
| `name` | Display name of the quota (e.g., "Antigravity Flash") |
|
|
80
|
+
| `bar` | Visual progress bar showing utilization |
|
|
81
|
+
| `percent` | Numeric percentage of quota used |
|
|
82
|
+
| `reset` | Time until the quota resets (e.g., "23m", "1h 30m") |
|
|
83
|
+
| `ettl` | **E**stimated **T**ime **T**o **L**imit - predicted time until quota exhaustion based on usage trends |
|
|
84
|
+
| `value` | Raw used/limit values (e.g., "150/500 credits") |
|
|
85
|
+
| `window` | Rate limit window duration (e.g., "5h window") |
|
|
86
|
+
| `info` | Additional info or alerts (e.g., "unlimited", "!!") |
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
All configuration is done via `.opencode/quotas.json` in your project root. Settings apply to both the CLI and plugin.
|
|
91
|
+
|
|
92
|
+
### Model Filtering
|
|
93
|
+
|
|
94
|
+
By default, `filterByCurrentModel` is enabled, showing only quotas relevant to the active model.
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"filterByCurrentModel": true
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**How it works**: The plugin extracts tokens from the model ID (e.g., `antigravity-gemini-3-flash` becomes `["antigravity", "gemini", "3", "flash"]`) and scores each quota by how many tokens match its ID or name. The highest-scoring quotas are displayed.
|
|
103
|
+
|
|
104
|
+
**Before filtering (all quotas):**
|
|
105
|
+
```text
|
|
106
|
+
ST QUOTA NAME USED UTILIZATION RESET ETTL
|
|
107
|
+
--- ------------------- ---- -------------------- ------ -----
|
|
108
|
+
OK Antigravity Flash 20% ████░░░░░░░░░░░░░░░░ 28m 13m
|
|
109
|
+
OK Antigravity Premium 40% ████████░░░░░░░░░░░░ 56m 1h 0m
|
|
110
|
+
ERR Codex Usage 100% ████████████████████ 13h 9m -
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**After filtering (model: `google/antigravity-gemini-3-flash`):**
|
|
114
|
+
```text
|
|
115
|
+
ST QUOTA NAME USED UTILIZATION RESET ETTL
|
|
116
|
+
--- ----------------- ---- -------------------- ----- ----
|
|
117
|
+
OK Antigravity Flash 20% ████░░░░░░░░░░░░░░░░ 28m 13m
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Explicit Model Mapping
|
|
121
|
+
|
|
122
|
+
For precise control, map model IDs directly to quota IDs:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"modelMapping": {
|
|
127
|
+
"google/antigravity-gemini-3-flash": ["ag-flash"],
|
|
128
|
+
"google/antigravity-gemini-3-pro": ["ag-pro"],
|
|
129
|
+
"github-copilot/gpt-4o": ["codex-smart"]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> **Note**: Model IDs must match the format from `opencode models` (e.g., `provider/model-name`).
|
|
135
|
+
|
|
136
|
+
### Hide Specific Quotas
|
|
137
|
+
|
|
138
|
+
Permanently hide quotas you don't care about:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"disabled": ["ag-pro", "codex-smart"]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Smart Aggregation
|
|
147
|
+
|
|
148
|
+
Combine multiple quotas into a single display row using explicit sources or pattern matching.
|
|
149
|
+
|
|
150
|
+
**Pattern-based aggregation** (matches raw quota IDs/names):
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"aggregatedGroups": [
|
|
154
|
+
{
|
|
155
|
+
"id": "ag-flash",
|
|
156
|
+
"name": "Antigravity Flash",
|
|
157
|
+
"patterns": ["flash"],
|
|
158
|
+
"providerId": "antigravity",
|
|
159
|
+
"strategy": "most_critical"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Explicit source aggregation** (specify exact quota IDs):
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"aggregatedGroups": [
|
|
169
|
+
{
|
|
170
|
+
"id": "codex-unified",
|
|
171
|
+
"name": "Codex Usage",
|
|
172
|
+
"sources": ["codex-primary", "codex-secondary"],
|
|
173
|
+
"strategy": "most_critical"
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Aggregation options:**
|
|
180
|
+
| Option | Type | Description |
|
|
181
|
+
| :--- | :--- | :--- |
|
|
182
|
+
| `id` | string | Unique identifier for the aggregated quota |
|
|
183
|
+
| `name` | string | Display name |
|
|
184
|
+
| `sources` | string[] | Explicit quota IDs to include |
|
|
185
|
+
| `patterns` | string[] | Patterns to match against raw quota IDs/names |
|
|
186
|
+
| `providerId` | string | Limit pattern matching to a specific provider |
|
|
187
|
+
| `strategy` | string | Aggregation strategy (see below) |
|
|
188
|
+
|
|
189
|
+
**Aggregation strategies:**
|
|
190
|
+
| Strategy | Description |
|
|
191
|
+
| :--- | :--- |
|
|
192
|
+
| `most_critical` | Shows the quota predicted to hit its limit soonest (requires usage history) |
|
|
193
|
+
| `max` | Shows the quota with highest current usage percentage |
|
|
194
|
+
| `min` | Shows the quota with lowest current usage percentage |
|
|
195
|
+
| `mean` | Displays average usage across all sources |
|
|
196
|
+
| `median` | Displays median usage across all sources |
|
|
197
|
+
|
|
198
|
+
## Output Customization
|
|
199
|
+
|
|
200
|
+
All options below work in both CLI and plugin output. ANSI colors only render in terminal environments.
|
|
201
|
+
|
|
202
|
+
### Select Columns
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"table": {
|
|
207
|
+
"columns": ["name", "bar", "percent"]
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
QUOTA NAME UTILIZATION USED
|
|
214
|
+
------------------- -------------------- ----
|
|
215
|
+
Antigravity Flash ████░░░░░░░░░░░░░░░░ 20%
|
|
216
|
+
Antigravity Premium ████████░░░░░░░░░░░░ 40%
|
|
217
|
+
Codex Usage ████████████████████ 100%
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Progress Bar Style
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"progressBar": {
|
|
225
|
+
"filledChar": "=",
|
|
226
|
+
"emptyChar": "-",
|
|
227
|
+
"width": 10
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
ST QUOTA NAME USED UTILIZATION RESET
|
|
234
|
+
--- ------------------- ---- ----------- ------
|
|
235
|
+
OK Antigravity Flash 20% ==-------- 23m
|
|
236
|
+
OK Antigravity Premium 40% ====------ 51m
|
|
237
|
+
ERR Codex Usage 100% ========== 13h 4m
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Show Remaining Capacity
|
|
241
|
+
|
|
242
|
+
Switch from "used" (default) to "available" mode. This inverts the display—useful if you prefer seeing how much is left:
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"progressBar": {
|
|
247
|
+
"show": "available"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
ST QUOTA NAME USED UTILIZATION RESET
|
|
254
|
+
--- ------------------- ---- -------------------- ------
|
|
255
|
+
WRN Antigravity Flash 80% ████████████████░░░░ 23m
|
|
256
|
+
OK Codex Usage 0% ░░░░░░░░░░░░░░░░░░░░ 13h 4m
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
> **Note**: In "available" mode, the percentage shows remaining capacity, and status thresholds are inverted.
|
|
260
|
+
|
|
261
|
+
### Hide Table Header
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"table": {
|
|
266
|
+
"header": false
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
OK Antigravity Flash 20% ████░░░░░░░░░░░░░░░░ 23m 5h 52m
|
|
273
|
+
OK Antigravity Premium 40% ████████░░░░░░░░░░░░ 51m 1h 2m
|
|
274
|
+
ERR Codex Usage 100% ████████████████████ 13h 4m -
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Disable Colors
|
|
278
|
+
|
|
279
|
+
For plain text output (logging, CI, or non-TTY environments):
|
|
280
|
+
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"progressBar": {
|
|
284
|
+
"color": false
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Custom Color Thresholds
|
|
290
|
+
|
|
291
|
+
Define when colors change based on usage percentage:
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"progressBar": {
|
|
296
|
+
"color": true,
|
|
297
|
+
"gradients": [
|
|
298
|
+
{ "threshold": 0.5, "color": "green" },
|
|
299
|
+
{ "threshold": 0.8, "color": "yellow" },
|
|
300
|
+
{ "threshold": 1.0, "color": "red" }
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Available colors: `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `gray`
|
|
307
|
+
|
|
308
|
+
## Full Configuration Reference
|
|
309
|
+
|
|
310
|
+
See [schemas/quotas.schema.json](schemas/quotas.schema.json) for the complete JSON Schema.
|
|
311
|
+
|
|
312
|
+
| Option | Type | Default | Description |
|
|
313
|
+
| :--- | :--- | :--- | :--- |
|
|
314
|
+
| `footer` | boolean | `true` | Show quotas in chat footer |
|
|
315
|
+
| `filterByCurrentModel` | boolean | `true` | Filter quotas by active model |
|
|
316
|
+
| `modelMapping` | object | (see defaults) | Explicit model-to-quota mappings |
|
|
317
|
+
| `disabled` | string[] | `[]` | Quota IDs to hide |
|
|
318
|
+
| `progressBar.color` | boolean | `true` | Enable ANSI colors |
|
|
319
|
+
| `progressBar.width` | number | `20` | Progress bar character width |
|
|
320
|
+
| `progressBar.show` | string | `"used"` | `"used"` or `"available"` |
|
|
321
|
+
| `table.columns` | string[] | (auto) | Columns to display |
|
|
322
|
+
| `table.header` | boolean | `true` | Show column headers |
|
|
323
|
+
| `aggregatedGroups` | array | (see defaults) | Quota aggregation with patterns or sources |
|
|
324
|
+
| `pollingInterval` | number | `60000` | Refresh interval in ms |
|
|
325
|
+
| `debug` | boolean | `false` | Enable debug logging |
|
|
326
|
+
|
|
327
|
+
## Security
|
|
328
|
+
|
|
329
|
+
Your credentials remain safe. This plugin uses standard local OAuth flows and stores tokens securely on your machine (`~/.config/opencode/`). No data is sent to third-party servers other than the quota providers themselves.
|
|
330
|
+
|
|
331
|
+
## Development
|
|
332
|
+
|
|
333
|
+
Built with **Bun** for speed.
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
bun install # Install dependencies
|
|
337
|
+
bun test # Run tests
|
|
338
|
+
npm run build # Build for production
|
|
339
|
+
bun run opencode-quotas # Run CLI in dev mode
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## License
|
|
343
|
+
|
|
344
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,eAAe,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { QuotaService } from "./services/quota-service";
|
|
3
|
+
import { HistoryService } from "./services/history-service";
|
|
4
|
+
import { renderQuotaTable } from "./ui/quota-table";
|
|
5
|
+
async function main() {
|
|
6
|
+
if (process.argv.includes("--no-color")) {
|
|
7
|
+
process.env.OPENCODE_QUOTAS_NO_COLOR = "1";
|
|
8
|
+
}
|
|
9
|
+
const historyService = new HistoryService();
|
|
10
|
+
await historyService.init();
|
|
11
|
+
const quotaService = new QuotaService();
|
|
12
|
+
await quotaService.init(process.cwd(), historyService);
|
|
13
|
+
const config = quotaService.getConfig();
|
|
14
|
+
// Parse arguments for provider and model filtering
|
|
15
|
+
let providerId;
|
|
16
|
+
let modelId;
|
|
17
|
+
const providerIdx = process.argv.indexOf("--provider");
|
|
18
|
+
if (providerIdx !== -1 && providerIdx + 1 < process.argv.length) {
|
|
19
|
+
providerId = process.argv[providerIdx + 1];
|
|
20
|
+
}
|
|
21
|
+
const modelIdx = process.argv.indexOf("--model");
|
|
22
|
+
if (modelIdx !== -1 && modelIdx + 1 < process.argv.length) {
|
|
23
|
+
modelId = process.argv[modelIdx + 1];
|
|
24
|
+
}
|
|
25
|
+
const filteredResults = await quotaService.getQuotas({ providerId, modelId });
|
|
26
|
+
if (filteredResults.length === 0) {
|
|
27
|
+
console.log("No active quotas found.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log(""); // Empty line
|
|
31
|
+
console.log("📊 OpenCode Quotas");
|
|
32
|
+
console.log("------------------");
|
|
33
|
+
renderQuotaTable(filteredResults, {
|
|
34
|
+
progressBarConfig: config.progressBar,
|
|
35
|
+
tableConfig: config.table,
|
|
36
|
+
}).forEach((row) => {
|
|
37
|
+
console.log(row.line);
|
|
38
|
+
});
|
|
39
|
+
console.log(""); // Empty line
|
|
40
|
+
}
|
|
41
|
+
main().catch(console.error);
|
|
42
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,KAAK,UAAU,IAAI;IACf,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,GAAG,CAAC;IAC/C,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC5C,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;IAE5B,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IACxC,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IAEvD,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC;IAExC,mDAAmD;IACnD,IAAI,UAA8B,CAAC;IACnC,IAAI,OAA2B,CAAC;IAEhC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,WAAW,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9D,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACxD,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IAE9E,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO;IACX,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa;IAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAElC,gBAAgB,CAAC,eAAe,EAAE;QAC9B,iBAAiB,EAAE,MAAM,CAAC,WAAW;QACrC,WAAW,EAAE,MAAM,CAAC,KAAK;KAC5B,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const PLUGIN_FOOTER_SIGNATURE = "_Opencode Quotas";
|
|
2
|
+
export declare const REASONING_PATTERNS: RegExp[];
|
|
3
|
+
export declare const DEBUG_LOG_FILENAME = "quotas-debug.log";
|
|
4
|
+
export declare const SKIP_REASONS: {
|
|
5
|
+
REASONING: string;
|
|
6
|
+
SUBAGENT: string;
|
|
7
|
+
FOOTER_PRESENT: string;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAG1D,eAAO,MAAM,kBAAkB,UAI9B,CAAC;AAGF,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAErD,eAAO,MAAM,YAAY;;;;CAIxB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const PLUGIN_FOOTER_SIGNATURE = "_Opencode Quotas";
|
|
2
|
+
// Heuristic patterns for detecting reasoning/thinking blocks
|
|
3
|
+
export const REASONING_PATTERNS = [
|
|
4
|
+
/^<thinking>/i,
|
|
5
|
+
/^<antThinking>/i,
|
|
6
|
+
/^(Thinking|Reasoning|Analysis):\s*(\n|$)/i
|
|
7
|
+
];
|
|
8
|
+
// File paths
|
|
9
|
+
export const DEBUG_LOG_FILENAME = "quotas-debug.log";
|
|
10
|
+
export const SKIP_REASONS = {
|
|
11
|
+
REASONING: "skip:reasoning",
|
|
12
|
+
SUBAGENT: "skip:subagent",
|
|
13
|
+
FOOTER_PRESENT: "skip:footer_present",
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAE1D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAC9B,cAAc;IACd,iBAAiB;IACjB,2CAA2C;CAC9C,CAAC;AAEF,aAAa;AACb,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,SAAS,EAAE,gBAAgB;IAC3B,QAAQ,EAAE,eAAe;IACzB,cAAc,EAAE,qBAAqB;CACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,eAAO,MAAM,cAAc,EAAE,WAiD5B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Default configuration for quota rendering and grouping
|
|
2
|
+
export const DEFAULT_CONFIG = {
|
|
3
|
+
displayMode: "simple",
|
|
4
|
+
footer: true,
|
|
5
|
+
showFooterTitle: true,
|
|
6
|
+
debug: false,
|
|
7
|
+
progressBar: {
|
|
8
|
+
color: false,
|
|
9
|
+
gradients: [
|
|
10
|
+
{ threshold: 0.5, color: "green" },
|
|
11
|
+
{ threshold: 0.8, color: "yellow" },
|
|
12
|
+
{ threshold: 1.0, color: "red" },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
table: {
|
|
16
|
+
header: true,
|
|
17
|
+
},
|
|
18
|
+
filterByCurrentModel: false,
|
|
19
|
+
showUnaggregated: false,
|
|
20
|
+
aggregatedGroups: [
|
|
21
|
+
{
|
|
22
|
+
id: "ag-flash",
|
|
23
|
+
name: "Antigravity Flash",
|
|
24
|
+
patterns: ["flash"],
|
|
25
|
+
providerId: "antigravity",
|
|
26
|
+
strategy: "most_critical",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "ag-pro",
|
|
30
|
+
name: "Antigravity Pro",
|
|
31
|
+
patterns: ["pro", "gemini"],
|
|
32
|
+
providerId: "antigravity",
|
|
33
|
+
strategy: "most_critical",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "ag-premium",
|
|
37
|
+
name: "Antigravity Premium",
|
|
38
|
+
patterns: ["claude", "gpt", "o1"],
|
|
39
|
+
providerId: "antigravity",
|
|
40
|
+
strategy: "most_critical",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "codex-smart",
|
|
44
|
+
name: "Codex Usage",
|
|
45
|
+
sources: ["codex-primary", "codex-secondary"],
|
|
46
|
+
strategy: "most_critical",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
historyMaxAgeHours: 24,
|
|
50
|
+
pollingInterval: 60_000,
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAEA,yDAAyD;AACzD,MAAM,CAAC,MAAM,cAAc,GAAgB;IACvC,WAAW,EAAE,QAAQ;IACrB,MAAM,EAAE,IAAI;IACZ,eAAe,EAAE,IAAI;IACrB,KAAK,EAAE,KAAK;IACZ,WAAW,EAAE;QACT,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE;YACP,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE;YACnC,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;SACnC;KACJ;IACD,KAAK,EAAE;QACH,MAAM,EAAE,IAAI;KACf;IACD,oBAAoB,EAAE,KAAK;IAC3B,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE;QACd;YACI,EAAE,EAAE,UAAU;YACd,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,UAAU,EAAE,aAAa;YACzB,QAAQ,EAAE,eAAe;SAC5B;QACD;YACI,EAAE,EAAE,QAAQ;YACZ,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;YAC3B,UAAU,EAAE,aAAa;YACzB,QAAQ,EAAE,eAAe;SAC5B;QACD;YACI,EAAE,EAAE,YAAY;YAChB,IAAI,EAAE,qBAAqB;YAC3B,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC;YACjC,UAAU,EAAE,aAAa;YACzB,QAAQ,EAAE,eAAe;SAC5B;QACD;YACI,EAAE,EAAE,aAAa;YACjB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,CAAC,eAAe,EAAE,iBAAiB,CAAC;YAC7C,QAAQ,EAAE,eAAe;SAC5B;KACJ;IACD,kBAAkB,EAAE,EAAE;IACtB,eAAe,EAAE,MAAM;CAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,qBAAqB,CAAC;AAkC9D;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MA4S5B,CAAC"}
|