@arandevcode/opencode-quota-extended 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/LICENSE +21 -0
- package/README-es.md +153 -0
- package/README.md +154 -0
- package/bin/quota.mjs +105 -0
- package/dist/config/defaults.d.ts +16 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +15 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.html +26 -0
- package/dist/config/loader.d.ts +10 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +89 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +16 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +28 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.html +29 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth.d.ts +45 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +68 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/http.d.ts +15 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +30 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/index.html +46 -0
- package/dist/lib/opencode-go-config.d.ts +22 -0
- package/dist/lib/opencode-go-config.d.ts.map +1 -0
- package/dist/lib/opencode-go-config.js +92 -0
- package/dist/lib/opencode-go-config.js.map +1 -0
- package/dist/lib/reset-format.d.ts +9 -0
- package/dist/lib/reset-format.d.ts.map +1 -0
- package/dist/lib/reset-format.js +83 -0
- package/dist/lib/reset-format.js.map +1 -0
- package/dist/lib/sanitize.d.ts +10 -0
- package/dist/lib/sanitize.d.ts.map +1 -0
- package/dist/lib/sanitize.js +14 -0
- package/dist/lib/sanitize.js.map +1 -0
- package/dist/lib/throttle.d.ts +18 -0
- package/dist/lib/throttle.d.ts.map +1 -0
- package/dist/lib/throttle.js +26 -0
- package/dist/lib/throttle.js.map +1 -0
- package/dist/lib/toast-format.d.ts +24 -0
- package/dist/lib/toast-format.d.ts.map +1 -0
- package/dist/lib/toast-format.js +79 -0
- package/dist/lib/toast-format.js.map +1 -0
- package/dist/lib/types.d.ts +50 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +10 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/providers/copilot.d.ts +3 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/copilot.js +303 -0
- package/dist/providers/copilot.js.map +1 -0
- package/dist/providers/index.html +34 -0
- package/dist/providers/openai.d.ts +10 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +152 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/opencode-go.d.ts +12 -0
- package/dist/providers/opencode-go.d.ts.map +1 -0
- package/dist/providers/opencode-go.js +102 -0
- package/dist/providers/opencode-go.js.map +1 -0
- package/dist/providers/registry.d.ts +20 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +76 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +27 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +4 -0
- package/dist/server.js.map +1 -0
- package/dist/tui.d.ts +7 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.tsx +121 -0
- package/dist/ui/SidebarPanel.d.ts +10 -0
- package/dist/ui/SidebarPanel.d.ts.map +1 -0
- package/dist/ui/SidebarPanel.tsx +36 -0
- package/dist/ui/cards.d.ts +13 -0
- package/dist/ui/cards.d.ts.map +1 -0
- package/dist/ui/cards.tsx +117 -0
- package/dist/ui/index.html +24 -0
- package/dist/ui/progress-bar.d.ts +27 -0
- package/dist/ui/progress-bar.d.ts.map +1 -0
- package/dist/ui/progress-bar.js +48 -0
- package/dist/ui/progress-bar.js.map +1 -0
- package/images/opencode_quota_extended_cli.png +0 -0
- package/images/opencode_quota_extended_sidebar.png +0 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 arandevcode
|
|
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-es.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="images/opencode_quota_extended_sidebar.png" alt="Barra lateral TUI" width="420">
|
|
3
|
+
<br>
|
|
4
|
+
<sub><em>-sidebar example-</em></sub>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# @arandevcode/opencode-quota-extended
|
|
8
|
+
|
|
9
|
+
> 🇬🇧 Also available in [English](README.md)
|
|
10
|
+
|
|
11
|
+
Tarjetas de uso de cuota para la barra lateral TUI — barras de progreso por ventana con colores de semáforo para OpenAI, GitHub Copilot y OpenCode Go.
|
|
12
|
+
|
|
13
|
+
- Barra de progreso para cada ventana de cuota (5h móvil, semanal, mensual, code review...)
|
|
14
|
+
- Muestra cuándo se reinicia — tiempo restante y fecha exacta
|
|
15
|
+
- Indicador de salud por colores (verde = ok, naranja = advertencia, rojo = crítico)
|
|
16
|
+
- OpenCode Go capable!
|
|
17
|
+
|
|
18
|
+
Inspirado por [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota). Ambos coexisten sin conflicto.
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
<p align="center">🐟 <em>“Quien quiera peces que se moje el culo”</em> <sub>— para mi padre, que me enseñó a arremangarme y hacer que las cosas pasen</sub>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<a href="https://buymeacoffee.com/arandevcode"><strong>☕ Invítame un café</strong></a>
|
|
26
|
+
<br>
|
|
27
|
+
<sub><a href="https://github.com/sponsors/arandevcode">❤️ Sponsor en GitHub</a></sub>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
## Instalación
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
opencode plugin @arandevcode/opencode-quota-extended
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
O instala desde GitHub para seguir el desarrollo más reciente:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
// ~/.config/opencode/opencode.json
|
|
40
|
+
{
|
|
41
|
+
"plugin": [
|
|
42
|
+
"https://github.com/arandevcode/opencode-plugins/tree/main/opencode-quota-extended"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## CLI
|
|
48
|
+
|
|
49
|
+
Visualiza la cuota desde la terminal sin abrir el TUI:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
npx opencode-quota # ejecutar vía npm (sin instalar)
|
|
53
|
+
opencode-quota # si está instalado globalmente
|
|
54
|
+
node bin/quota.mjs # desde el directorio del repo (sin build)
|
|
55
|
+
npm run quota # desde el directorio del repo
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="images/opencode_quota_extended_cli.png" alt="Salida CLI" width="620">
|
|
60
|
+
<br>
|
|
61
|
+
<sub><em>-cli example-</em></sub>
|
|
62
|
+
</p>
|
|
63
|
+
|
|
64
|
+
Colores de semáforo: verde (ok), naranja (advertencia), rojo (error).
|
|
65
|
+
|
|
66
|
+
## Configuración
|
|
67
|
+
|
|
68
|
+
Archivo sidecar opcional en `~/.config/opencode/opencode-quota-extended.json`:
|
|
69
|
+
|
|
70
|
+
| Campo | Tipo | Por defecto | Descripción |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| `enabledProviders` | string[] | `["openai","github-copilot","opencode-go"]` | Proveedores a consultar |
|
|
73
|
+
| `refreshIntervalMs` | int | `60000` | Intervalo de sondeo |
|
|
74
|
+
| `cardsSidebar.order` | int | `145` | Posición en la barra lateral (menor = más arriba) |
|
|
75
|
+
|
|
76
|
+
## Más Información
|
|
77
|
+
|
|
78
|
+
### Cómo funciona
|
|
79
|
+
|
|
80
|
+
Registra un plugin TUI que renderiza un panel `sidebar_content` en la posición 145, mostrando tarjetas de cuota para cada proveedor activo. Cada proveedor obtiene datos de cuota independientemente desde su propia API.
|
|
81
|
+
|
|
82
|
+
| Proveedor | Ventanas | Fuente de autenticación |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| **OpenAI** | 5h móvil, Semanal, Code Review | `auth.json` → entrada `openai` / `chatgpt` |
|
|
85
|
+
| **GitHub Copilot** | Solicitudes Premium (ventana única) | `auth.json` → entrada `github-copilot` |
|
|
86
|
+
| **OpenCode Go** | 5h, Semanal, Mensual | Archivo de configuración o vars de entorno |
|
|
87
|
+
|
|
88
|
+
Colores de semáforo: ≥50% verde (`accent`), 25-49% amarillo (`warning`), <25% rojo (`error`).
|
|
89
|
+
|
|
90
|
+
### Autenticación
|
|
91
|
+
|
|
92
|
+
Lee credenciales del archivo de autenticación de OpenCode (`~/.local/share/opencode/auth.json`). **No** almacena, solicita ni distribuye secretos.
|
|
93
|
+
|
|
94
|
+
**OpenCode Go** requiere configuración adicional — es un poco tricky porque no hay API oficial todavía.
|
|
95
|
+
|
|
96
|
+
Crea `~/.config/opencode/opencode-quota/opencode-go.json`:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"workspaceId": "wrk_abc123...",
|
|
101
|
+
"authCookie": "Fe26.2..."
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
| Campo | Descripción | Cómo obtenerlo |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `workspaceId` | ID de tu workspace en OpenCode | Entra en [opencode.ai/go](https://opencode.ai/go). La URL es `https://opencode.ai/workspace/wrk_XXX/go` — copia la parte `wrk_XXX`. |
|
|
108
|
+
| `authCookie` | Cookie de sesión para autenticación | Abre DevTools (F12) → Application → Cookies → `opencode.ai` → busca la cookie `auth` (empieza con `Fe26.2...`). O ejecuta en la consola: `document.cookie.match(/(?:^\|;\s*)auth=([^;]+)/)?.[1]` |
|
|
109
|
+
|
|
110
|
+
**Setup automatizado** (recomendado):
|
|
111
|
+
```sh
|
|
112
|
+
npm run setup
|
|
113
|
+
```
|
|
114
|
+
Te solicita ambos valores y crea el archivo automáticamente. También muestra un bookmarklet que puedes arrastrar a la barra de favoritos y pinchar en opencode.ai para extraer la auth cookie con un clic.
|
|
115
|
+
|
|
116
|
+
**Consejo:** mantén una pestaña del navegador con sesión iniciada en opencode.ai mientras usas este plugin — la auth cookie puede expirar.
|
|
117
|
+
|
|
118
|
+
### Relación con [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota)
|
|
119
|
+
|
|
120
|
+
**Sin dependencia.** Ambos plugins obtienen cuota independientemente y renderizan sus propios paneles laterales. Puedes tener uno, ambos o ninguno — no interfieren.
|
|
121
|
+
|
|
122
|
+
### Solución de problemas
|
|
123
|
+
|
|
124
|
+
- **El panel no aparece**: `grep '@arandevcode/opencode-quota-extended' ~/.local/share/opencode/log/*.log`
|
|
125
|
+
- **OpenCode Go muestra "skipped"**: confirma que el archivo sidecar o vars de entorno están configurados
|
|
126
|
+
- **Bug antiguo de pinning `@opentui/solid`**: actualiza a `^0.4.1` y reinstala limpio (`rm -rf node_modules && npm ci`)
|
|
127
|
+
|
|
128
|
+
### Desarrollo
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
npm run build # compilar TS + copiar assets TUI
|
|
132
|
+
npm run build:watch # modo watch
|
|
133
|
+
npm test # vitest
|
|
134
|
+
npm run typecheck # type-check sin emitir
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Estructura del proyecto
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
src/
|
|
141
|
+
index.ts # Plugin module (entrada server)
|
|
142
|
+
server.ts # Plugin server (mínimo, sin herramientas)
|
|
143
|
+
tui.tsx # Plugin TUI: slot sidebar_content
|
|
144
|
+
config/ # defaults, schema, loader
|
|
145
|
+
lib/ # types, auth, http, formatting, credential resolver
|
|
146
|
+
providers/ # openai.ts, copilot.ts, opencode-go.ts, registry.ts
|
|
147
|
+
ui/ # SidebarPanel, cards, progress-bar
|
|
148
|
+
tests/ # tests unitarios vitest
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Licencia
|
|
152
|
+
|
|
153
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="images/opencode_quota_extended_sidebar.png" alt="TUI sidebar" width="420">
|
|
3
|
+
<br>
|
|
4
|
+
<sub><em>-sidebar example-</em></sub>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# @arandevcode/opencode-quota-extended
|
|
8
|
+
|
|
9
|
+
> 🇪🇸 Also available in [Spanish](README-es.md)
|
|
10
|
+
|
|
11
|
+
Quota usage cards for the TUI sidebar — per-window progress bars with traffic-light colors for OpenAI, GitHub Copilot, and OpenCode Go.
|
|
12
|
+
|
|
13
|
+
- Progress bar for each quota window (5h rolling, weekly, monthly, code review...)
|
|
14
|
+
- Shows when it resets — time remaining and exact date
|
|
15
|
+
- Color-coded health indication (green = ok, orange = warning, red = critical)
|
|
16
|
+
- OpenCode Go capable!
|
|
17
|
+
|
|
18
|
+
Heavily inspired by [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota). Both coexist without conflict.
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
<p align="center">🐟 <em>“Quien quiera peces que se moje el culo”</em> >
|
|
22
|
+
<em>“If you want fish, get your ass wet”</em> <sub>— for my father, who taught me to roll up my sleeves and get it done</sub>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="https://buymeacoffee.com/arandevcode"><strong>☕ Buy me a coffee</strong></a>
|
|
27
|
+
<br>
|
|
28
|
+
<sub><a href="https://github.com/sponsors/arandevcode">❤️ Sponsor on GitHub</a></sub>
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
opencode plugin @arandevcode/opencode-quota-extended
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or install from GitHub source to follow latest development:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
// ~/.config/opencode/opencode.json
|
|
41
|
+
{
|
|
42
|
+
"plugin": [
|
|
43
|
+
"https://github.com/arandevcode/opencode-plugins/tree/main/opencode-quota-extended"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## CLI
|
|
49
|
+
|
|
50
|
+
View quota from the terminal without opening the TUI:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx opencode-quota # run via npm (no install)
|
|
54
|
+
opencode-quota # if installed globally
|
|
55
|
+
node bin/quota.mjs # from the repo directory (no build needed)
|
|
56
|
+
npm run quota # from the repo directory
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
<p align="center">
|
|
60
|
+
<img src="images/opencode_quota_extended_cli.png" alt="CLI output" width="620">
|
|
61
|
+
<br>
|
|
62
|
+
<sub><em>-cli example-</em></sub>
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
Traffic-light colors: green (ok), orange (warning), red (error).
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
Optional sidecar at `~/.config/opencode/opencode-quota-extended.json`:
|
|
70
|
+
|
|
71
|
+
| Field | Type | Default | Description |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `enabledProviders` | string[] | `["openai","github-copilot","opencode-go"]` | Providers to fetch |
|
|
74
|
+
| `refreshIntervalMs` | int | `60000` | Polling interval |
|
|
75
|
+
| `cardsSidebar.order` | int | `145` | Sidebar position (lower = higher) |
|
|
76
|
+
|
|
77
|
+
## More Information
|
|
78
|
+
|
|
79
|
+
### How it works
|
|
80
|
+
|
|
81
|
+
Registers a TUI plugin that renders a `sidebar_content` panel at order 145, showing quota cards for every enabled provider. Each provider fetches quota data independently from its own API.
|
|
82
|
+
|
|
83
|
+
| Provider | Windows | Auth source |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| **OpenAI** | 5h rolling, Weekly, Code Review | `auth.json` → `openai` / `chatgpt` entry |
|
|
86
|
+
| **GitHub Copilot** | Premium requests (single window) | `auth.json` → `github-copilot` entry |
|
|
87
|
+
| **OpenCode Go** | 5h, Weekly, Monthly | Config file or env vars |
|
|
88
|
+
|
|
89
|
+
Traffic-light colors: ≥50% green (`accent`), 25-49% yellow (`warning`), <25% red (`error`).
|
|
90
|
+
|
|
91
|
+
### Authentication
|
|
92
|
+
|
|
93
|
+
Reads credentials from OpenCode's runtime auth file (`~/.local/share/opencode/auth.json`). Does **not** store, prompt for, or distribute secrets.
|
|
94
|
+
|
|
95
|
+
**OpenCode Go** requires additional setup — it's a bit tricky because there's no official API yet.
|
|
96
|
+
|
|
97
|
+
Create `~/.config/opencode/opencode-quota/opencode-go.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"workspaceId": "wrk_abc123...",
|
|
102
|
+
"authCookie": "Fe26.2..."
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Field | Description | How to get it |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `workspaceId` | Your OpenCode workspace ID | Log in at [opencode.ai/go](https://opencode.ai/go). The URL is `https://opencode.ai/workspace/wrk_XXX/go` — copy the `wrk_XXX` part. |
|
|
109
|
+
| `authCookie` | Session cookie for auth | Open DevTools (F12) → Application → Cookies → `opencode.ai` → find the `auth` cookie (starts with `Fe26.2...`). Or run this in the console: `document.cookie.match(/(?:^\|;\s*)auth=([^;]+)/)?.[1]` |
|
|
110
|
+
|
|
111
|
+
**Automated setup** (recommended):
|
|
112
|
+
```sh
|
|
113
|
+
npm run setup
|
|
114
|
+
```
|
|
115
|
+
This prompts for both values and creates the file for you. It also prints a bookmarklet you can drag to your bookmarks bar and click while on opencode.ai to extract the auth cookie with one click.
|
|
116
|
+
|
|
117
|
+
**Tip:** keep a browser tab logged into opencode.ai while using this plugin — the auth cookie may expire.
|
|
118
|
+
|
|
119
|
+
### Relationship with [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota)
|
|
120
|
+
|
|
121
|
+
**No dependency.** Both plugins fetch quota independently and render their own sidebar panels. You can have one, both, or none — they do not interfere.
|
|
122
|
+
|
|
123
|
+
### Troubleshooting
|
|
124
|
+
|
|
125
|
+
- **Panel doesn't appear**: `grep '@arandevcode/opencode-quota-extended' ~/.local/share/opencode/log/*.log`
|
|
126
|
+
- **OpenCode Go shows "skipped"**: confirm sidecar file or env vars are set
|
|
127
|
+
- **Old `@opentui/solid` pinning bug**: update to `^0.4.1` and clean-install (`rm -rf node_modules && npm ci`)
|
|
128
|
+
|
|
129
|
+
### Development
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
npm run build # compile TS + copy TUI assets
|
|
133
|
+
npm run build:watch # watch mode
|
|
134
|
+
npm test # vitest
|
|
135
|
+
npm run typecheck # type-check without emitting
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Project structure
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
src/
|
|
142
|
+
index.ts # Plugin module (server entry)
|
|
143
|
+
server.ts # Server plugin (minimal, no tools)
|
|
144
|
+
tui.tsx # TUI plugin: sidebar_content slot
|
|
145
|
+
config/ # defaults, schema, loader
|
|
146
|
+
lib/ # types, auth, http, formatting, credential resolver
|
|
147
|
+
providers/ # openai.ts, copilot.ts, opencode-go.ts, registry.ts
|
|
148
|
+
ui/ # SidebarPanel, cards, progress-bar
|
|
149
|
+
tests/ # vitest unit tests
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
package/bin/quota.mjs
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { dirname } from "path";
|
|
5
|
+
import { loadCardsConfig } from "../dist/config/loader.js";
|
|
6
|
+
import { collectSnapshot } from "../dist/providers/registry.js";
|
|
7
|
+
import { renderProgressBar, trafficLight } from "../dist/ui/progress-bar.js";
|
|
8
|
+
import { formatResetCombined } from "../dist/lib/reset-format.js";
|
|
9
|
+
|
|
10
|
+
const INDENT = 4;
|
|
11
|
+
|
|
12
|
+
const COLORS = {
|
|
13
|
+
ok: "\x1b[38;2;107;131;35m",
|
|
14
|
+
warning: "\x1b[38;2;255;165;0m",
|
|
15
|
+
error: "\x1b[38;2;255;107;107m",
|
|
16
|
+
};
|
|
17
|
+
const RESET = "\x1b[0m";
|
|
18
|
+
const BOLD = "\x1b[1m";
|
|
19
|
+
const DIM = "\x1b[2m";
|
|
20
|
+
|
|
21
|
+
function stripAnsi(s) {
|
|
22
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
23
|
+
}
|
|
24
|
+
function cols() {
|
|
25
|
+
return process.stdout.columns ?? 80;
|
|
26
|
+
}
|
|
27
|
+
function usedPct(pct) {
|
|
28
|
+
return `${Math.round(100 - pct)}% used`;
|
|
29
|
+
}
|
|
30
|
+
function windowLabel(window) {
|
|
31
|
+
if (
|
|
32
|
+
typeof window.remaining === "number" &&
|
|
33
|
+
typeof window.total === "number" &&
|
|
34
|
+
Number.isFinite(window.remaining) &&
|
|
35
|
+
Number.isFinite(window.total)
|
|
36
|
+
) {
|
|
37
|
+
return `${window.remaining}/${window.total}`;
|
|
38
|
+
}
|
|
39
|
+
return window.label;
|
|
40
|
+
}
|
|
41
|
+
function padRight(left, right) {
|
|
42
|
+
const gap = Math.max(2, cols() - INDENT - stripAnsi(left).length - stripAnsi(right).length);
|
|
43
|
+
return left + " ".repeat(gap) + right;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function main() {
|
|
47
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
48
|
+
|
|
49
|
+
const loadResult = await loadCardsConfig();
|
|
50
|
+
const config = loadResult.config;
|
|
51
|
+
const barWidth = cols() - INDENT;
|
|
52
|
+
|
|
53
|
+
console.log(`\n${BOLD}Quota${RESET}\n`);
|
|
54
|
+
|
|
55
|
+
const snapshot = await collectSnapshot(config);
|
|
56
|
+
|
|
57
|
+
for (const provider of snapshot.providers) {
|
|
58
|
+
if (provider.status === "skipped") continue;
|
|
59
|
+
|
|
60
|
+
if (provider.status === "no-auth") {
|
|
61
|
+
console.log(` ${BOLD}${provider.label}${RESET} ${DIM}no auth${RESET}`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (provider.status === "error") {
|
|
66
|
+
console.log(
|
|
67
|
+
` ${BOLD}${provider.label}${RESET} ${COLORS.error}${provider.error ?? "error"}${RESET}`,
|
|
68
|
+
);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (provider.windows.length === 0) {
|
|
73
|
+
console.log(` ${BOLD}${provider.label}${RESET} ${DIM}no data${RESET}`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(` ${BOLD}${provider.label}${RESET}`);
|
|
78
|
+
|
|
79
|
+
for (const [i, win] of provider.windows.entries()) {
|
|
80
|
+
if (i > 0) console.log();
|
|
81
|
+
const pct = win.percentRemaining;
|
|
82
|
+
const light = trafficLight(pct);
|
|
83
|
+
const color = COLORS[light];
|
|
84
|
+
const bar = renderProgressBar(pct, barWidth);
|
|
85
|
+
const resetT = formatResetCombined(win.resetTimeIso);
|
|
86
|
+
const resetStyle = resetT ? (light === "error" ? `${color}${resetT}${RESET}` : `${DIM}${resetT}${RESET}`) : "";
|
|
87
|
+
|
|
88
|
+
const labelStr = windowLabel(win);
|
|
89
|
+
console.log(" ".repeat(INDENT) + padRight(labelStr, resetStyle));
|
|
90
|
+
console.log(" ".repeat(INDENT) + color + bar.filled + bar.empty + RESET);
|
|
91
|
+
const combined = `${usedPct(pct)} / `;
|
|
92
|
+
const leftStr = `${pct}% left`;
|
|
93
|
+
const pad = Math.max(0, cols() - INDENT - stripAnsi(combined + leftStr).length);
|
|
94
|
+
console.log(" ".repeat(INDENT + pad) + combined + color + leftStr + RESET);
|
|
95
|
+
}
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(`${DIM}Generated at: ${snapshot.generatedAt}${RESET}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main().catch((err) => {
|
|
103
|
+
console.error("Error:", err.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface CardsPluginConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
enabledProviders: Array<"openai" | "github-copilot" | "opencode-go">;
|
|
4
|
+
refreshIntervalMs: number;
|
|
5
|
+
requestTimeoutMs: number;
|
|
6
|
+
opencodeGoTimeoutMs: number;
|
|
7
|
+
showOnlyMultiWindow: boolean;
|
|
8
|
+
cardsSidebar: {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
order: number;
|
|
11
|
+
};
|
|
12
|
+
opencodeGoWindows: Array<"5h" | "weekly" | "monthly">;
|
|
13
|
+
}
|
|
14
|
+
export declare const DEFAULT_CONFIG: CardsPluginConfig;
|
|
15
|
+
export declare const SIDECAR_FILENAME = "opencode-quota-extended.json";
|
|
16
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,KAAK,CAAC,QAAQ,GAAG,gBAAgB,GAAG,aAAa,CAAC,CAAC;IACrE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,YAAY,EAAE;QACZ,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,iBAAiB,EAAE,KAAK,CAAC,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,cAAc,EAAE,iBAY5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const DEFAULT_CONFIG = {
|
|
2
|
+
enabled: true,
|
|
3
|
+
enabledProviders: ["openai", "github-copilot", "opencode-go"],
|
|
4
|
+
refreshIntervalMs: 60_000,
|
|
5
|
+
requestTimeoutMs: 8_000,
|
|
6
|
+
opencodeGoTimeoutMs: 10_000,
|
|
7
|
+
showOnlyMultiWindow: false,
|
|
8
|
+
cardsSidebar: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
order: 145,
|
|
11
|
+
},
|
|
12
|
+
opencodeGoWindows: ["5h", "weekly", "monthly"],
|
|
13
|
+
};
|
|
14
|
+
export const SIDECAR_FILENAME = "opencode-quota-extended.json";
|
|
15
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,OAAO,EAAE,IAAI;IACb,gBAAgB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAC7D,iBAAiB,EAAE,MAAM;IACzB,gBAAgB,EAAE,KAAK;IACvB,mBAAmB,EAAE,MAAM;IAC3B,mBAAmB,EAAE,KAAK;IAC1B,YAAY,EAAE;QACZ,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,GAAG;KACX;IACD,iBAAiB,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE HTML>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Directory listing for /opencode-personal-projects/opencode-quota-extended/dist/config/</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Directory listing for /opencode-personal-projects/opencode-quota-extended/dist/config/</h1>
|
|
9
|
+
<hr>
|
|
10
|
+
<ul>
|
|
11
|
+
<li><a href="defaults.d.ts">defaults.d.ts</a></li>
|
|
12
|
+
<li><a href="defaults.d.ts.map">defaults.d.ts.map</a></li>
|
|
13
|
+
<li><a href="defaults.js">defaults.js</a></li>
|
|
14
|
+
<li><a href="defaults.js.map">defaults.js.map</a></li>
|
|
15
|
+
<li><a href="loader.d.ts">loader.d.ts</a></li>
|
|
16
|
+
<li><a href="loader.d.ts.map">loader.d.ts.map</a></li>
|
|
17
|
+
<li><a href="loader.js">loader.js</a></li>
|
|
18
|
+
<li><a href="loader.js.map">loader.js.map</a></li>
|
|
19
|
+
<li><a href="schema.d.ts">schema.d.ts</a></li>
|
|
20
|
+
<li><a href="schema.d.ts.map">schema.d.ts.map</a></li>
|
|
21
|
+
<li><a href="schema.js">schema.js</a></li>
|
|
22
|
+
<li><a href="schema.js.map">schema.js.map</a></li>
|
|
23
|
+
</ul>
|
|
24
|
+
<hr>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type CardsPluginConfig } from "./defaults.js";
|
|
2
|
+
export type LoadConfigSource = "defaults" | "cwd" | "opencode-config" | "xdg-config" | "xdg-config-fallback" | "env-override";
|
|
3
|
+
export interface LoadConfigResult {
|
|
4
|
+
config: CardsPluginConfig;
|
|
5
|
+
source: LoadConfigSource;
|
|
6
|
+
path: string | null;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadCardsConfig(): Promise<LoadConfigResult>;
|
|
10
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAC;AAGvB,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,KAAK,GACL,iBAAiB,GACjB,YAAY,GACZ,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8CD,wBAAsB,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAsDjE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { access, readFile } from "fs/promises";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { xdgConfig } from "xdg-basedir";
|
|
5
|
+
import { DEFAULT_CONFIG, SIDECAR_FILENAME, } from "./defaults.js";
|
|
6
|
+
import { parseCardsConfig } from "./schema.js";
|
|
7
|
+
function getOpencodeConfigDir() {
|
|
8
|
+
if (process.env.OPENCODE_CONFIG_DIR) {
|
|
9
|
+
return process.env.OPENCODE_CONFIG_DIR;
|
|
10
|
+
}
|
|
11
|
+
if (xdgConfig) {
|
|
12
|
+
return join(xdgConfig, "opencode");
|
|
13
|
+
}
|
|
14
|
+
return join(homedir(), ".config", "opencode");
|
|
15
|
+
}
|
|
16
|
+
async function fileExists(filePath) {
|
|
17
|
+
try {
|
|
18
|
+
await access(filePath);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function tryLoad(filePath, source) {
|
|
26
|
+
try {
|
|
27
|
+
const raw = await readFile(filePath, "utf8");
|
|
28
|
+
const parsed = JSON.parse(raw);
|
|
29
|
+
const config = parseCardsConfig(parsed);
|
|
30
|
+
return { ok: true, result: { config, source, path: filePath } };
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34
|
+
return { ok: false, error: `${source}: ${message}` };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function loadCardsConfig() {
|
|
38
|
+
const errors = [];
|
|
39
|
+
const candidates = [];
|
|
40
|
+
const envPath = process.env.OPENCODE_QUOTA_CARDS_CONFIG;
|
|
41
|
+
if (envPath) {
|
|
42
|
+
candidates.push({ path: envPath, source: "env-override" });
|
|
43
|
+
}
|
|
44
|
+
candidates.push({
|
|
45
|
+
path: join(process.cwd(), SIDECAR_FILENAME),
|
|
46
|
+
source: "cwd",
|
|
47
|
+
});
|
|
48
|
+
const opencodeConfigDir = getOpencodeConfigDir();
|
|
49
|
+
if (opencodeConfigDir) {
|
|
50
|
+
candidates.push({
|
|
51
|
+
path: join(opencodeConfigDir, SIDECAR_FILENAME),
|
|
52
|
+
source: "opencode-config",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (xdgConfig) {
|
|
56
|
+
candidates.push({
|
|
57
|
+
path: join(xdgConfig, SIDECAR_FILENAME),
|
|
58
|
+
source: "xdg-config",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
candidates.push({
|
|
63
|
+
path: join(homedir(), ".config", SIDECAR_FILENAME),
|
|
64
|
+
source: "xdg-config-fallback",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
for (const candidate of candidates) {
|
|
68
|
+
if (!(await fileExists(candidate.path)))
|
|
69
|
+
continue;
|
|
70
|
+
const attempt = await tryLoad(candidate.path, candidate.source);
|
|
71
|
+
if (attempt.ok) {
|
|
72
|
+
if (errors.length > 0) {
|
|
73
|
+
return { ...attempt.result, error: errors.join("; ") };
|
|
74
|
+
}
|
|
75
|
+
return attempt.result;
|
|
76
|
+
}
|
|
77
|
+
errors.push(attempt.error);
|
|
78
|
+
}
|
|
79
|
+
if (errors.length > 0) {
|
|
80
|
+
return {
|
|
81
|
+
config: DEFAULT_CONFIG,
|
|
82
|
+
source: "defaults",
|
|
83
|
+
path: null,
|
|
84
|
+
error: errors.join("; "),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return { config: DEFAULT_CONFIG, source: "defaults", path: null };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for validating the plugin sidecar configuration file.
|
|
3
|
+
*
|
|
4
|
+
* The root schema `cardsConfigSchema` uses `.passthrough()` to allow
|
|
5
|
+
* documentation keys prefixed with `_` (e.g. `_comment`).
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import type { CardsPluginConfig } from "./defaults.js";
|
|
9
|
+
export declare const WindowIdForOpenCodeGo: z.ZodEnum<{
|
|
10
|
+
"5h": "5h";
|
|
11
|
+
weekly: "weekly";
|
|
12
|
+
monthly: "monthly";
|
|
13
|
+
}>;
|
|
14
|
+
export declare const cardsConfigSchema: z.ZodType<CardsPluginConfig>;
|
|
15
|
+
export declare function parseCardsConfig(input: unknown): CardsPluginConfig;
|
|
16
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAIvD,eAAO,MAAM,qBAAqB;;;;EAAsC,CAAC;AAkBzE,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CACU,CAAC;AAEtE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAElE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for validating the plugin sidecar configuration file.
|
|
3
|
+
*
|
|
4
|
+
* The root schema `cardsConfigSchema` uses `.passthrough()` to allow
|
|
5
|
+
* documentation keys prefixed with `_` (e.g. `_comment`).
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
const providerIdSchema = z.enum(["openai", "github-copilot", "opencode-go"]);
|
|
9
|
+
export const WindowIdForOpenCodeGo = z.enum(["5h", "weekly", "monthly"]);
|
|
10
|
+
const cardsSidebarSchema = z.object({
|
|
11
|
+
enabled: z.boolean(),
|
|
12
|
+
order: z.number().int(),
|
|
13
|
+
});
|
|
14
|
+
const cardsConfigBaseSchema = z.object({
|
|
15
|
+
enabled: z.boolean(),
|
|
16
|
+
enabledProviders: z.array(providerIdSchema).min(1),
|
|
17
|
+
refreshIntervalMs: z.coerce.number().int().positive(),
|
|
18
|
+
requestTimeoutMs: z.coerce.number().int().positive(),
|
|
19
|
+
opencodeGoTimeoutMs: z.coerce.number().int().positive(),
|
|
20
|
+
showOnlyMultiWindow: z.boolean(),
|
|
21
|
+
cardsSidebar: cardsSidebarSchema,
|
|
22
|
+
opencodeGoWindows: z.array(WindowIdForOpenCodeGo).min(1),
|
|
23
|
+
});
|
|
24
|
+
export const cardsConfigSchema = cardsConfigBaseSchema.passthrough();
|
|
25
|
+
export function parseCardsConfig(input) {
|
|
26
|
+
return cardsConfigSchema.parse(input);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAEzE,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;CACxB,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrD,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACpD,mBAAmB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACvD,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE;IAChC,YAAY,EAAE,kBAAkB;IAChC,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACzD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,qBAAqB,CAAC,WAAW,EAAkC,CAAC;AAEtE,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC"}
|