@arandevcode/opencode-quota-extended 0.2.2 → 0.2.4
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-es.md +19 -13
- package/README.md +18 -12
- package/bin/quota.mjs +8 -1
- package/dist/lib/balance.d.ts +16 -0
- package/dist/lib/balance.d.ts.map +1 -0
- package/dist/lib/balance.js +45 -0
- package/dist/lib/balance.js.map +1 -0
- package/dist/lib/opencode-go-config.d.ts +6 -1
- package/dist/lib/opencode-go-config.d.ts.map +1 -1
- package/dist/lib/opencode-go-config.js +29 -3
- package/dist/lib/opencode-go-config.js.map +1 -1
- package/dist/lib/pace.d.ts +28 -0
- package/dist/lib/pace.d.ts.map +1 -0
- package/dist/lib/pace.js +46 -0
- package/dist/lib/pace.js.map +1 -0
- package/dist/lib/refresh-scheduler.d.ts +20 -0
- package/dist/lib/refresh-scheduler.d.ts.map +1 -0
- package/dist/lib/refresh-scheduler.js +57 -0
- package/dist/lib/refresh-scheduler.js.map +1 -0
- package/dist/lib/types.d.ts +19 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/providers/opencode-go.d.ts +8 -4
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +167 -43
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.tsx +58 -83
- package/dist/ui/SidebarPanel.d.ts.map +1 -1
- package/dist/ui/SidebarPanel.tsx +2 -13
- package/dist/ui/cards.d.ts.map +1 -1
- package/dist/ui/cards.tsx +24 -4
- package/images/opencode_quota_extended_cli.png +0 -0
- package/images/opencode_quota_extended_sidebar.png +0 -0
- package/package.json +7 -3
- package/scripts/clean.mjs +8 -0
- package/scripts/postbuild.mjs +56 -0
- package/scripts/setup.mjs +53 -0
- package/dist/lib/sanitize.d.ts +0 -10
- package/dist/lib/sanitize.d.ts.map +0 -1
- package/dist/lib/sanitize.js +0 -14
- package/dist/lib/sanitize.js.map +0 -1
- package/dist/lib/throttle.d.ts +0 -18
- package/dist/lib/throttle.d.ts.map +0 -1
- package/dist/lib/throttle.js +0 -26
- package/dist/lib/throttle.js.map +0 -1
- package/dist/lib/toast-format.d.ts +0 -24
- package/dist/lib/toast-format.d.ts.map +0 -1
- package/dist/lib/toast-format.js +0 -79
- package/dist/lib/toast-format.js.map +0 -1
package/README-es.md
CHANGED
|
@@ -121,7 +121,7 @@ Registra un plugin TUI que renderiza un panel `sidebar_content` en la posición
|
|
|
121
121
|
|---|---|---|
|
|
122
122
|
| **OpenAI** | 5h móvil, Semanal, Code Review | `auth.json` → entrada `openai` / `chatgpt` |
|
|
123
123
|
| **GitHub Copilot** | Solicitudes Premium (ventana única) | `auth.json` → entrada `github-copilot` |
|
|
124
|
-
| **OpenCode Go** | 5h, Semanal, Mensual |
|
|
124
|
+
| **OpenCode Go** | 5h, Semanal, Mensual + gasto | API key personal (o cookie de sesión legacy) |
|
|
125
125
|
|
|
126
126
|
Colores de semáforo: ≥50% `theme.success` (verde), 25-49% `theme.warning` (naranja), <25% `theme.error` (rojo).
|
|
127
127
|
|
|
@@ -129,38 +129,43 @@ Colores de semáforo: ≥50% `theme.success` (verde), 25-49% `theme.warning` (na
|
|
|
129
129
|
|
|
130
130
|
Lee credenciales del archivo de autenticación de OpenCode (`~/.local/share/opencode/auth.json`). **No** almacena, solicita ni distribuye secretos.
|
|
131
131
|
|
|
132
|
-
**OpenCode Go**
|
|
132
|
+
**OpenCode Go** usa una API key personal. El plugin llama al mismo endpoint del console que el dashboard y lee las tres ventanas de cuota, el gasto en dólares por ventana y el balance de crédito prepago.
|
|
133
133
|
|
|
134
134
|
Crea `~/.config/opencode/opencode-quota/opencode-go.json`:
|
|
135
135
|
|
|
136
136
|
```json
|
|
137
137
|
{
|
|
138
|
-
"
|
|
139
|
-
"authCookie": "Fe26.2..."
|
|
138
|
+
"apiKey": "oc_sk_..."
|
|
140
139
|
}
|
|
141
140
|
```
|
|
142
141
|
|
|
143
142
|
| Campo | Descripción | Cómo obtenerlo |
|
|
144
143
|
|---|---|---|
|
|
145
|
-
| `
|
|
146
|
-
| `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]` |
|
|
144
|
+
| `apiKey` | API key personal de OpenCode | Abre [opencode.ai/console](https://opencode.ai/console) → **Personal API keys** → crea una key con permisos **All**. Copia el valor `oc_sk_...`. No uses una service account: no puede leer billing. |
|
|
147
145
|
|
|
148
|
-
|
|
146
|
+
La key se guarda con permisos `600` y solo se envía a `opencode.ai`. Una key **All** muestra cuota, gasto y balance. Una key `read` no sirve para este plugin: no puede llamar a `go/status`.
|
|
147
|
+
|
|
148
|
+
**Múltiples workspaces/cuentas:** cualquier archivo `opencode-go-<sufijo>.json` en el mismo directorio añade una sección extra `Opencode GO (<sufijo>)` (p. ej. `opencode-go-work.json` → **Opencode GO (work)**). El `opencode-go.json` base siempre se muestra como **OpenCode Go**. Los archivos `opencode-go-<sufijo>-key.json` que mantiene el switch de cuentas los ignora el plugin de cuota.
|
|
149
149
|
|
|
150
150
|
```sh
|
|
151
|
-
# p. ej.
|
|
151
|
+
# p. ej. una segunda cuenta
|
|
152
152
|
cp ~/.config/opencode/opencode-quota/opencode-go.json \
|
|
153
153
|
~/.config/opencode/opencode-quota/opencode-go-work.json
|
|
154
|
-
# luego
|
|
154
|
+
# luego sustituye apiKey dentro de opencode-go-work.json
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
**Setup automatizado** (recomendado):
|
|
158
158
|
```sh
|
|
159
|
-
npm run setup
|
|
159
|
+
npm run setup # cuenta base -> opencode-go.json
|
|
160
|
+
npm run setup work # cuenta extra -> opencode-go-work.json
|
|
160
161
|
```
|
|
161
|
-
Te solicita
|
|
162
|
+
Te solicita la API key, escribe el archivo con permisos `600` e indica dónde crearla.
|
|
163
|
+
|
|
164
|
+
También puedes usar `OPENCODE_GO_API_KEY` en vez de un archivo.
|
|
165
|
+
|
|
166
|
+
**Legacy:** `{ "workspaceId": "wrk_...", "authCookie": "st_..." }` sigue aceptándose por compatibilidad, pero la cookie de sesión del navegador caduca. Mejor usa la API key.
|
|
162
167
|
|
|
163
|
-
**
|
|
168
|
+
**Migrar una cuenta existente:** si ya tienes `opencode-go-<Cuenta>.json`, sustituye todo su contenido por `{ "apiKey": "oc_sk_..." }`. No hacen falta `workspaceId` ni `authCookie`. `npm run setup <Cuenta>` respeta mayúsculas: el sufijo debe coincidir exactamente con el nombre del archivo.
|
|
164
169
|
|
|
165
170
|
### Relación con [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota)
|
|
166
171
|
|
|
@@ -169,7 +174,8 @@ Te solicita ambos valores y crea el archivo automáticamente. También muestra u
|
|
|
169
174
|
### Solución de problemas
|
|
170
175
|
|
|
171
176
|
- **El panel no aparece**: `grep '@arandevcode/opencode-quota-extended' ~/.local/share/opencode/log/*.log`
|
|
172
|
-
- **OpenCode Go muestra "skipped"**: confirma que el archivo sidecar o
|
|
177
|
+
- **OpenCode Go muestra "skipped"**: confirma que el archivo sidecar o `OPENCODE_GO_API_KEY` está configurado
|
|
178
|
+
- **OpenCode Go muestra 401/403**: la key no es válida, ha caducado o le faltan permisos; crea una key personal **All** (las service account no pueden leer billing)
|
|
173
179
|
- **Bug antiguo de pinning `@opentui/solid`**: usa `^0.4.1 || ^0.5.0` y reinstala limpio (`rm -rf node_modules && npm ci`)
|
|
174
180
|
|
|
175
181
|
### Desarrollo
|
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ Registers a TUI plugin that renders a `sidebar_content` panel at order 145, show
|
|
|
122
122
|
|---|---|---|
|
|
123
123
|
| **OpenAI** | 5h rolling, Weekly, Code Review | `auth.json` → `openai` / `chatgpt` entry |
|
|
124
124
|
| **GitHub Copilot** | Premium requests (single window) | `auth.json` → `github-copilot` entry |
|
|
125
|
-
| **OpenCode Go** | 5h, Weekly, Monthly |
|
|
125
|
+
| **OpenCode Go** | 5h, Weekly, Monthly + spend | Personal API key (or legacy session cookie) |
|
|
126
126
|
|
|
127
127
|
Traffic-light colors: ≥50% `theme.success` (green), 25-49% `theme.warning` (orange), <25% `theme.error` (red).
|
|
128
128
|
|
|
@@ -130,38 +130,43 @@ Traffic-light colors: ≥50% `theme.success` (green), 25-49% `theme.warning` (or
|
|
|
130
130
|
|
|
131
131
|
Reads credentials from OpenCode's runtime auth file (`~/.local/share/opencode/auth.json`). Does **not** store, prompt for, or distribute secrets.
|
|
132
132
|
|
|
133
|
-
**OpenCode Go**
|
|
133
|
+
**OpenCode Go** uses a personal API key. The plugin calls the same console endpoint as the dashboard and reads the three quota windows, the dollar spend per window, and the prepaid credit balance.
|
|
134
134
|
|
|
135
135
|
Create `~/.config/opencode/opencode-quota/opencode-go.json`:
|
|
136
136
|
|
|
137
137
|
```json
|
|
138
138
|
{
|
|
139
|
-
"
|
|
140
|
-
"authCookie": "Fe26.2..."
|
|
139
|
+
"apiKey": "oc_sk_..."
|
|
141
140
|
}
|
|
142
141
|
```
|
|
143
142
|
|
|
144
143
|
| Field | Description | How to get it |
|
|
145
144
|
|---|---|---|
|
|
146
|
-
| `
|
|
147
|
-
| `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]` |
|
|
145
|
+
| `apiKey` | Personal OpenCode API key | Open [opencode.ai/console](https://opencode.ai/console) → **Personal API keys** → create a key with **All** permissions. Copy the `oc_sk_...` value. Do not use a service-account key: service accounts cannot read billing. |
|
|
148
146
|
|
|
149
|
-
|
|
147
|
+
The key is stored with mode `600` and is only sent to `opencode.ai`. An **All** key shows quota, dollar spend and credit balance. A `read` key is not enough for this plugin: it cannot call `go/status`.
|
|
148
|
+
|
|
149
|
+
**Multiple workspaces/accounts:** any `opencode-go-<suffix>.json` file in the same directory adds an extra `Opencode GO (<suffix>)` section (e.g. `opencode-go-work.json` → **Opencode GO (work)**). The base `opencode-go.json` always renders as **OpenCode Go**. The `opencode-go-<suffix>-key.json` files maintained by the account switcher are ignored by the quota plugin.
|
|
150
150
|
|
|
151
151
|
```sh
|
|
152
152
|
# e.g. a second workspace
|
|
153
153
|
cp ~/.config/opencode/opencode-quota/opencode-go.json \
|
|
154
154
|
~/.config/opencode/opencode-quota/opencode-go-work.json
|
|
155
|
-
# then
|
|
155
|
+
# then replace apiKey inside opencode-go-work.json
|
|
156
156
|
```
|
|
157
157
|
|
|
158
158
|
**Automated setup** (recommended):
|
|
159
159
|
```sh
|
|
160
|
-
npm run setup
|
|
160
|
+
npm run setup # base account -> opencode-go.json
|
|
161
|
+
npm run setup work # extra account -> opencode-go-work.json
|
|
161
162
|
```
|
|
162
|
-
This prompts for
|
|
163
|
+
This prompts for the API key, writes the file with mode `600`, and prints where to create the key.
|
|
164
|
+
|
|
165
|
+
You can also use `OPENCODE_GO_API_KEY` instead of a file.
|
|
166
|
+
|
|
167
|
+
**Legacy:** `{ "workspaceId": "wrk_...", "authCookie": "st_..." }` is still accepted for backwards compatibility, but the browser session cookie expires. Prefer the API key.
|
|
163
168
|
|
|
164
|
-
**
|
|
169
|
+
**Migrating an existing account:** if you already have `opencode-go-<Account>.json`, replace its entire contents with `{ "apiKey": "oc_sk_..." }`. No `workspaceId` or `authCookie` needed. `npm run setup <Account>` is case-sensitive: the suffix must match the filename exactly.
|
|
165
170
|
|
|
166
171
|
### Relationship with [`@slkiser/opencode-quota`](https://github.com/slkiser/opencode-quota)
|
|
167
172
|
|
|
@@ -170,7 +175,8 @@ This prompts for both values and creates the file for you. It also prints a book
|
|
|
170
175
|
### Troubleshooting
|
|
171
176
|
|
|
172
177
|
- **Panel doesn't appear**: `grep '@arandevcode/opencode-quota-extended' ~/.local/share/opencode/log/*.log`
|
|
173
|
-
- **OpenCode Go shows "skipped"**: confirm sidecar file or
|
|
178
|
+
- **OpenCode Go shows "skipped"**: confirm the sidecar file or `OPENCODE_GO_API_KEY` is set
|
|
179
|
+
- **OpenCode Go shows 401/403**: the key is invalid, expired or lacks permissions; create a personal **All** key (service-account keys cannot read billing)
|
|
174
180
|
- **Old `@opentui/solid` pinning bug**: use `^0.4.1 || ^0.5.0` and clean-install (`rm -rf node_modules && npm ci`)
|
|
175
181
|
|
|
176
182
|
### Development
|
package/bin/quota.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { loadCardsConfig } from "../dist/config/loader.js";
|
|
|
6
6
|
import { collectSnapshot } from "../dist/providers/registry.js";
|
|
7
7
|
import { renderProgressBar, trafficLight } from "../dist/ui/progress-bar.js";
|
|
8
8
|
import { formatResetCombined } from "../dist/lib/reset-format.js";
|
|
9
|
+
import { formatBalance, formatWindowSpend } from "../dist/lib/balance.js";
|
|
9
10
|
|
|
10
11
|
const INDENT = 4;
|
|
11
12
|
|
|
@@ -13,6 +14,7 @@ const COLORS = {
|
|
|
13
14
|
ok: "\x1b[32m",
|
|
14
15
|
warning: "\x1b[33m",
|
|
15
16
|
error: "\x1b[31m",
|
|
17
|
+
accent: "\x1b[36m",
|
|
16
18
|
};
|
|
17
19
|
const RESET = "\x1b[0m";
|
|
18
20
|
const BOLD = "\x1b[1m";
|
|
@@ -74,7 +76,10 @@ async function main() {
|
|
|
74
76
|
continue;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
const credit = formatBalance(provider.balance);
|
|
80
|
+
console.log(
|
|
81
|
+
` ${BOLD}${provider.label}${RESET}${credit ? ` ${COLORS.accent}${credit}${RESET}` : ""}`,
|
|
82
|
+
);
|
|
78
83
|
|
|
79
84
|
for (const [i, win] of provider.windows.entries()) {
|
|
80
85
|
if (i > 0) console.log();
|
|
@@ -91,6 +96,8 @@ async function main() {
|
|
|
91
96
|
const leftStr = `${color}${pct}% left${RESET}`;
|
|
92
97
|
const rightStr = `${DIM}${usedPct(pct)}${RESET}`;
|
|
93
98
|
console.log(" ".repeat(INDENT) + padRight(leftStr, rightStr));
|
|
99
|
+
const spend = formatWindowSpend(win);
|
|
100
|
+
if (spend) console.log(" ".repeat(INDENT) + DIM + spend + RESET);
|
|
94
101
|
}
|
|
95
102
|
console.log();
|
|
96
103
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepaid credit balance formatting (OpenCode Go).
|
|
3
|
+
*
|
|
4
|
+
* The provider reports `availableMicroCents` as a decimal string because it can
|
|
5
|
+
* exceed the safe integer range; 1e8 microcents make one US dollar. Only the
|
|
6
|
+
* dollar amount and the auto-recharge flag are ever rendered — never the raw
|
|
7
|
+
* microcents, and never anything that came from the account credentials.
|
|
8
|
+
*/
|
|
9
|
+
import type { ProviderBalance, QuotaWindow } from "./types.js";
|
|
10
|
+
/** Available credit in dollars (2 decimals), or null when unreadable. */
|
|
11
|
+
export declare function balanceUsd(balance: ProviderBalance | undefined): number | null;
|
|
12
|
+
/** "$9.18 credit", plus a note when credits are drawn or auto-recharge is on. */
|
|
13
|
+
export declare function formatBalance(balance: ProviderBalance | undefined): string;
|
|
14
|
+
/** "$2.64 / $30.00" for a window that exposes both money fields. */
|
|
15
|
+
export declare function formatWindowSpend(window: QuotaWindow): string;
|
|
16
|
+
//# sourceMappingURL=balance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balance.d.ts","sourceRoot":"","sources":["../../src/lib/balance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM9E;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,CAO1E;AAcD,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAK7D"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Available credit in dollars (2 decimals), or null when unreadable. */
|
|
2
|
+
export function balanceUsd(balance) {
|
|
3
|
+
if (!balance)
|
|
4
|
+
return null;
|
|
5
|
+
const raw = balance.availableMicroCents;
|
|
6
|
+
const micro = typeof raw === "string" ? Number(raw.trim()) : raw;
|
|
7
|
+
if (typeof micro !== "number" || !Number.isFinite(micro))
|
|
8
|
+
return null;
|
|
9
|
+
return Math.round(micro / 1e6) / 100;
|
|
10
|
+
}
|
|
11
|
+
/** "$9.18 credit", plus a note when credits are drawn or auto-recharge is on. */
|
|
12
|
+
export function formatBalance(balance) {
|
|
13
|
+
const usd = balanceUsd(balance);
|
|
14
|
+
if (usd === null || !balance)
|
|
15
|
+
return "";
|
|
16
|
+
const parts = [`$${usd.toFixed(2)} credit`];
|
|
17
|
+
if (balance.useBalance === true)
|
|
18
|
+
parts.push("draws on credits");
|
|
19
|
+
if (balance.autoRecharge?.enabled)
|
|
20
|
+
parts.push("auto-recharge");
|
|
21
|
+
return parts.join(" · ");
|
|
22
|
+
}
|
|
23
|
+
/** Dollars from a microcents decimal string, using cents precision. */
|
|
24
|
+
function microCentsUsd(raw) {
|
|
25
|
+
if (typeof raw !== "string" || raw.trim() === "")
|
|
26
|
+
return null;
|
|
27
|
+
try {
|
|
28
|
+
const micro = BigInt(raw.trim());
|
|
29
|
+
if (micro < 0n)
|
|
30
|
+
return null;
|
|
31
|
+
return Number((micro + 500000n) / 1000000n) / 100;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** "$2.64 / $30.00" for a window that exposes both money fields. */
|
|
38
|
+
export function formatWindowSpend(window) {
|
|
39
|
+
const spent = microCentsUsd(window.spentMicroCents);
|
|
40
|
+
const limit = microCentsUsd(window.limitMicroCents);
|
|
41
|
+
if (spent === null || limit === null || limit <= 0)
|
|
42
|
+
return "";
|
|
43
|
+
return `$${spent.toFixed(2)} / $${limit.toFixed(2)}`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=balance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balance.js","sourceRoot":"","sources":["../../src/lib/balance.ts"],"names":[],"mappings":"AAUA,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,OAAoC;IAC7D,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,OAAoC;IAChE,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,YAAY,EAAE,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/D,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,uEAAuE;AACvE,SAAS,aAAa,CAAC,GAAuB;IAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QAC5B,OAAO,MAAM,CAAC,CAAC,KAAK,GAAG,OAAQ,CAAC,GAAG,QAAU,CAAC,GAAG,GAAG,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9D,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export type OpenCodeGoConfig = {
|
|
2
|
+
auth: "api-key";
|
|
3
|
+
apiKey: string;
|
|
4
|
+
} | {
|
|
5
|
+
auth: "cookie";
|
|
2
6
|
workspaceId: string;
|
|
3
7
|
authCookie: string;
|
|
4
8
|
};
|
|
9
|
+
export type OpenCodeGoMissingField = "apiKey" | "workspaceId" | "authCookie";
|
|
5
10
|
export type OpenCodeGoConfigResolution = {
|
|
6
11
|
state: "configured";
|
|
7
12
|
config: OpenCodeGoConfig;
|
|
@@ -9,7 +14,7 @@ export type OpenCodeGoConfigResolution = {
|
|
|
9
14
|
} | {
|
|
10
15
|
state: "incomplete";
|
|
11
16
|
source: string;
|
|
12
|
-
missing:
|
|
17
|
+
missing: OpenCodeGoMissingField;
|
|
13
18
|
} | {
|
|
14
19
|
state: "invalid";
|
|
15
20
|
source: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-go-config.d.ts","sourceRoot":"","sources":["../../src/lib/opencode-go-config.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"opencode-go-config.d.ts","sourceRoot":"","sources":["../../src/lib/opencode-go-config.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC;AAE7E,MAAM,MAAM,0BAA0B,GAClC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GACxE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AA2HD,gFAAgF;AAChF,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAInF;AAED,qDAAqD;AACrD,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,0BAA0B,CAAC,CAErC;AAED;;;;GAIG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA0BjF;AAKD,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAMzF;AAOD,wBAAsB,+BAA+B,CACnD,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,0BAA0B,CAAC,CAOrC;AAED,uEAAuE;AACvE,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD"}
|
|
@@ -37,12 +37,20 @@ function getInstanceCandidatePaths(id) {
|
|
|
37
37
|
return getSidecarDirCandidates().map((d) => join(d, `${EXTRA_PREFIX}${suffix}.json`));
|
|
38
38
|
}
|
|
39
39
|
function fromEnv() {
|
|
40
|
+
const apiKey = process.env.OPENCODE_GO_API_KEY?.trim();
|
|
41
|
+
if (apiKey) {
|
|
42
|
+
return { state: "configured", config: { auth: "api-key", apiKey }, source: "env" };
|
|
43
|
+
}
|
|
40
44
|
const workspaceId = process.env.OPENCODE_GO_WORKSPACE_ID?.trim();
|
|
41
45
|
const authCookie = process.env.OPENCODE_GO_AUTH_COOKIE?.trim();
|
|
42
46
|
if (!workspaceId && !authCookie)
|
|
43
47
|
return { state: "none" };
|
|
44
48
|
if (workspaceId && authCookie) {
|
|
45
|
-
return {
|
|
49
|
+
return {
|
|
50
|
+
state: "configured",
|
|
51
|
+
config: { auth: "cookie", workspaceId, authCookie },
|
|
52
|
+
source: "env",
|
|
53
|
+
};
|
|
46
54
|
}
|
|
47
55
|
return {
|
|
48
56
|
state: "incomplete",
|
|
@@ -79,19 +87,34 @@ async function readFileResolution(path) {
|
|
|
79
87
|
error: err instanceof Error ? err.message : String(err),
|
|
80
88
|
};
|
|
81
89
|
}
|
|
90
|
+
if (typeof parsed === "string") {
|
|
91
|
+
const apiKey = parsed.trim();
|
|
92
|
+
if (apiKey) {
|
|
93
|
+
return { state: "configured", config: { auth: "api-key", apiKey }, source: path };
|
|
94
|
+
}
|
|
95
|
+
return { state: "invalid", source: path, error: "Config key is empty" };
|
|
96
|
+
}
|
|
82
97
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
83
98
|
return { state: "invalid", source: path, error: "Config must be a JSON object" };
|
|
84
99
|
}
|
|
85
100
|
const obj = parsed;
|
|
101
|
+
const apiKey = typeof obj.apiKey === "string" ? obj.apiKey.trim() : "";
|
|
86
102
|
const workspaceId = typeof obj.workspaceId === "string" ? obj.workspaceId.trim() : "";
|
|
87
103
|
const authCookie = typeof obj.authCookie === "string" ? obj.authCookie.trim() : "";
|
|
104
|
+
if (apiKey) {
|
|
105
|
+
return { state: "configured", config: { auth: "api-key", apiKey }, source: path };
|
|
106
|
+
}
|
|
88
107
|
if (workspaceId && authCookie) {
|
|
89
|
-
return {
|
|
108
|
+
return {
|
|
109
|
+
state: "configured",
|
|
110
|
+
config: { auth: "cookie", workspaceId, authCookie },
|
|
111
|
+
source: path,
|
|
112
|
+
};
|
|
90
113
|
}
|
|
91
114
|
return {
|
|
92
115
|
state: "incomplete",
|
|
93
116
|
source: path,
|
|
94
|
-
missing: workspaceId ? "authCookie" : "workspaceId",
|
|
117
|
+
missing: workspaceId ? "authCookie" : authCookie ? "workspaceId" : "apiKey",
|
|
95
118
|
};
|
|
96
119
|
}
|
|
97
120
|
async function resolveFromPaths(paths) {
|
|
@@ -139,6 +162,9 @@ export async function discoverOpenCodeGoInstances() {
|
|
|
139
162
|
const suffix = name.slice(EXTRA_PREFIX.length, -".json".length);
|
|
140
163
|
if (!suffix || seen.has(suffix))
|
|
141
164
|
continue;
|
|
165
|
+
// Helper files maintained by the account switcher are not quota configs.
|
|
166
|
+
if (suffix === "active" || suffix.endsWith("-key"))
|
|
167
|
+
continue;
|
|
142
168
|
seen.add(suffix);
|
|
143
169
|
instances.push({
|
|
144
170
|
id: `${EXTRA_PREFIX}${suffix}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-go-config.js","sourceRoot":"","sources":["../../src/lib/opencode-go-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AACxC,MAAM,YAAY,GAAG,cAAc,CAAC;AACpC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AACzC,MAAM,UAAU,GAAG,aAAa,CAAC;AACjC,MAAM,aAAa,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"opencode-go-config.js","sourceRoot":"","sources":["../../src/lib/opencode-go-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota pace — how usage compares to the passage of time in a window.
|
|
3
|
+
*
|
|
4
|
+
* Every window resets on a known schedule (5h, weekly, monthly). When a window
|
|
5
|
+
* carries its reset time we can say whether the remaining share is ahead of or
|
|
6
|
+
* behind the clock: spending slower than time passes is margin, faster is
|
|
7
|
+
* "ahead". This is the same reading Jarvis shows, but text-only — no overlay on
|
|
8
|
+
* the progress bar, so it works at any terminal width.
|
|
9
|
+
*/
|
|
10
|
+
import type { QuotaWindow } from "./types.js";
|
|
11
|
+
export type QuotaPace = "buffer" | "on-pace" | "burn";
|
|
12
|
+
export interface QuotaPaceReading {
|
|
13
|
+
pace: QuotaPace;
|
|
14
|
+
/** Percentage-point gap between remaining quota and time left (rounded). */
|
|
15
|
+
deltaPercent: number;
|
|
16
|
+
/** The same gap expressed as time, in ms. */
|
|
17
|
+
deltaMs: number;
|
|
18
|
+
}
|
|
19
|
+
/** Window length when the id/label names a known schedule, else null. */
|
|
20
|
+
export declare function windowDurationMs(window: Pick<QuotaWindow, "id" | "label">): number | null;
|
|
21
|
+
/**
|
|
22
|
+
* Compare remaining quota to the time left in the window. Returns null when the
|
|
23
|
+
* schedule or reset time is unknown, or there is no reading to compare.
|
|
24
|
+
*/
|
|
25
|
+
export declare function quotaPace(window: QuotaWindow, now?: number): QuotaPaceReading | null;
|
|
26
|
+
/** One short line: "margin +6% · 3h 12m", "ahead -6% · 1d 2h" or "on pace". */
|
|
27
|
+
export declare function formatPace(window: QuotaWindow, now?: number): string;
|
|
28
|
+
//# sourceMappingURL=pace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pace.d.ts","sourceRoot":"","sources":["../../src/lib/pace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAMzF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,GAAE,MAAmB,GAAG,gBAAgB,GAAG,IAAI,CAUhG;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAWhF"}
|
package/dist/lib/pace.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { clampPercent, formatDuration } from "./reset-format.js";
|
|
2
|
+
const HOUR_MS = 60 * 60 * 1000;
|
|
3
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
4
|
+
/** Window length when the id/label names a known schedule, else null. */
|
|
5
|
+
export function windowDurationMs(window) {
|
|
6
|
+
const key = `${window.id} ${window.label}`.toLowerCase();
|
|
7
|
+
if (/\b5h\b|five[_ -]?hour/.test(key))
|
|
8
|
+
return 5 * HOUR_MS;
|
|
9
|
+
if (/weekly|seven[_ -]?day|\bweek\b/.test(key))
|
|
10
|
+
return 7 * DAY_MS;
|
|
11
|
+
if (/monthly|\bmonth\b/.test(key))
|
|
12
|
+
return 30 * DAY_MS;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Compare remaining quota to the time left in the window. Returns null when the
|
|
17
|
+
* schedule or reset time is unknown, or there is no reading to compare.
|
|
18
|
+
*/
|
|
19
|
+
export function quotaPace(window, now = Date.now()) {
|
|
20
|
+
const duration = windowDurationMs(window);
|
|
21
|
+
const resetAt = window.resetTimeIso ? Date.parse(window.resetTimeIso) : Number.NaN;
|
|
22
|
+
const remaining = window.percentRemaining;
|
|
23
|
+
if (duration == null || !Number.isFinite(resetAt) || !Number.isFinite(remaining))
|
|
24
|
+
return null;
|
|
25
|
+
const exactTimeLeft = Math.min(100, Math.max(0, ((resetAt - now) / duration) * 100));
|
|
26
|
+
const deltaPercent = clampPercent(remaining) - clampPercent(exactTimeLeft);
|
|
27
|
+
const pace = deltaPercent > 1 ? "buffer" : deltaPercent < -1 ? "burn" : "on-pace";
|
|
28
|
+
const deltaMs = Math.round((Math.abs(Math.min(100, Math.max(0, remaining)) - exactTimeLeft) / 100) * duration);
|
|
29
|
+
return { pace, deltaPercent, deltaMs };
|
|
30
|
+
}
|
|
31
|
+
/** One short line: "margin +6% · 3h 12m", "ahead -6% · 1d 2h" or "on pace". */
|
|
32
|
+
export function formatPace(window, now = Date.now()) {
|
|
33
|
+
const reading = quotaPace(window, now);
|
|
34
|
+
if (!reading)
|
|
35
|
+
return "";
|
|
36
|
+
const { pace, deltaPercent, deltaMs } = reading;
|
|
37
|
+
if (pace === "on-pace")
|
|
38
|
+
return "on pace";
|
|
39
|
+
const word = pace === "buffer" ? "margin" : "ahead";
|
|
40
|
+
const sign = deltaPercent > 0 ? "+" : "";
|
|
41
|
+
const gap = formatDuration(deltaMs);
|
|
42
|
+
return gap
|
|
43
|
+
? `${word} ${sign}${deltaPercent}% · ${gap}`
|
|
44
|
+
: `${word} ${sign}${deltaPercent}%`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=pace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pace.js","sourceRoot":"","sources":["../../src/lib/pace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type RefreshSchedulerOptions = {
|
|
2
|
+
refresh: () => void;
|
|
3
|
+
intervalMs: number;
|
|
4
|
+
activityDelayMs?: number;
|
|
5
|
+
minGapMs?: number;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
};
|
|
8
|
+
export type RefreshScheduler = {
|
|
9
|
+
start: () => void;
|
|
10
|
+
schedule: (delay?: number, force?: boolean) => void;
|
|
11
|
+
dispose: () => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Coalesces bursts of usage events into a single refresh and enforces a
|
|
15
|
+
* minimum gap between attempts. A streaming message can emit many
|
|
16
|
+
* `message.updated` events per second; without this every one of them would
|
|
17
|
+
* fan out to the provider APIs.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createRefreshScheduler(options: RefreshSchedulerOptions): RefreshScheduler;
|
|
20
|
+
//# sourceMappingURL=refresh-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-scheduler.d.ts","sourceRoot":"","sources":["../../src/lib/refresh-scheduler.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CAoDzF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coalesces bursts of usage events into a single refresh and enforces a
|
|
3
|
+
* minimum gap between attempts. A streaming message can emit many
|
|
4
|
+
* `message.updated` events per second; without this every one of them would
|
|
5
|
+
* fan out to the provider APIs.
|
|
6
|
+
*/
|
|
7
|
+
export function createRefreshScheduler(options) {
|
|
8
|
+
const { refresh, intervalMs, activityDelayMs = 1_500, minGapMs = 20_000, now = Date.now, } = options;
|
|
9
|
+
let interval = null;
|
|
10
|
+
let timer = null;
|
|
11
|
+
let lastRefreshAt = 0;
|
|
12
|
+
let disposed = false;
|
|
13
|
+
const run = () => {
|
|
14
|
+
if (disposed)
|
|
15
|
+
return;
|
|
16
|
+
lastRefreshAt = now();
|
|
17
|
+
refresh();
|
|
18
|
+
};
|
|
19
|
+
const schedule = (delay = activityDelayMs, force = false) => {
|
|
20
|
+
if (disposed || timer !== null)
|
|
21
|
+
return;
|
|
22
|
+
const wait = force
|
|
23
|
+
? delay
|
|
24
|
+
: Math.max(delay, minGapMs - (now() - lastRefreshAt));
|
|
25
|
+
timer = setTimeout(() => {
|
|
26
|
+
timer = null;
|
|
27
|
+
if (disposed)
|
|
28
|
+
return;
|
|
29
|
+
if (!force && now() - lastRefreshAt < minGapMs) {
|
|
30
|
+
schedule(0);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
run();
|
|
34
|
+
}, wait);
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
start() {
|
|
38
|
+
if (disposed || interval !== null)
|
|
39
|
+
return;
|
|
40
|
+
interval = setInterval(() => {
|
|
41
|
+
if (now() - lastRefreshAt >= minGapMs)
|
|
42
|
+
run();
|
|
43
|
+
}, intervalMs);
|
|
44
|
+
},
|
|
45
|
+
schedule,
|
|
46
|
+
dispose() {
|
|
47
|
+
disposed = true;
|
|
48
|
+
if (interval !== null)
|
|
49
|
+
clearInterval(interval);
|
|
50
|
+
if (timer !== null)
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
interval = null;
|
|
53
|
+
timer = null;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=refresh-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-scheduler.js","sourceRoot":"","sources":["../../src/lib/refresh-scheduler.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,EACJ,OAAO,EACP,UAAU,EACV,eAAe,GAAG,KAAK,EACvB,QAAQ,GAAG,MAAM,EACjB,GAAG,GAAG,IAAI,CAAC,GAAG,GACf,GAAG,OAAO,CAAC;IAEZ,IAAI,QAAQ,GAA0C,IAAI,CAAC;IAC3D,IAAI,KAAK,GAAyC,IAAI,CAAC;IACvD,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,GAAG,GAAG,GAAG,EAAE;QACf,IAAI,QAAQ;YAAE,OAAO;QACrB,aAAa,GAAG,GAAG,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,eAAe,EAAE,KAAK,GAAG,KAAK,EAAE,EAAE;QAC1D,IAAI,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO;QACvC,MAAM,IAAI,GAAG,KAAK;YAChB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC;QACxD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,KAAK,GAAG,IAAI,CAAC;YACb,IAAI,QAAQ;gBAAE,OAAO;YACrB,IAAI,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,aAAa,GAAG,QAAQ,EAAE,CAAC;gBAC/C,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,GAAG,EAAE,CAAC;QACR,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;YACH,IAAI,QAAQ,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO;YAC1C,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC1B,IAAI,GAAG,EAAE,GAAG,aAAa,IAAI,QAAQ;oBAAE,GAAG,EAAE,CAAC;YAC/C,CAAC,EAAE,UAAU,CAAC,CAAC;QACjB,CAAC;QACD,QAAQ;QACR,OAAO;YACL,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,QAAQ,KAAK,IAAI;gBAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,KAAK,KAAK,IAAI;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YACxC,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -24,9 +24,26 @@ export interface QuotaWindow {
|
|
|
24
24
|
used?: number;
|
|
25
25
|
/** Remaining quota for the window, if exposed by the provider. */
|
|
26
26
|
remaining?: number;
|
|
27
|
+
/** Money spent in this window, in microcents (1e8 microcents = 1 USD). */
|
|
28
|
+
spentMicroCents?: string;
|
|
29
|
+
/** Money limit for this window, in microcents (1e8 microcents = 1 USD). */
|
|
30
|
+
limitMicroCents?: string;
|
|
27
31
|
}
|
|
28
32
|
/** Status of a single provider fetch. */
|
|
29
33
|
export type ProviderStatus = "ok" | "no-auth" | "error" | "skipped" | "loading";
|
|
34
|
+
/** Prepaid credit balance of an account, when the provider exposes it (OpenCode Go). */
|
|
35
|
+
export interface ProviderBalance {
|
|
36
|
+
/** Available credit in microcents (1e8 microcents = 1 USD), as a decimal string. */
|
|
37
|
+
availableMicroCents: string;
|
|
38
|
+
/** Whether usage may draw on credits once a plan limit is reached; null if unknown. */
|
|
39
|
+
useBalance: boolean | null;
|
|
40
|
+
/** Auto-recharge settings, when readable. */
|
|
41
|
+
autoRecharge?: {
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
thresholdDollars?: number;
|
|
44
|
+
rechargeAmountDollars?: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
30
47
|
/** A single provider's quota result. */
|
|
31
48
|
export interface ProviderQuota {
|
|
32
49
|
/** Stable provider id, e.g. "openai", "github-copilot", "opencode-go". */
|
|
@@ -41,6 +58,8 @@ export interface ProviderQuota {
|
|
|
41
58
|
windows: QuotaWindow[];
|
|
42
59
|
/** Timestamp the snapshot was taken. */
|
|
43
60
|
fetchedAt: string;
|
|
61
|
+
/** Credit balance, when the provider exposes it and the lookup succeeded. */
|
|
62
|
+
balance?: ProviderBalance;
|
|
44
63
|
}
|
|
45
64
|
/** Aggregate snapshot used by the TUI sidebar and the server tool. */
|
|
46
65
|
export interface CardsSnapshot {
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uEAAuE;AACvE,MAAM,MAAM,QAAQ,GAChB,IAAI,GACJ,QAAQ,GACR,SAAS,GACT,aAAa,GACb,SAAS,CAAC;AAEd,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,EAAE,EAAE,QAAQ,CAAC;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,gBAAgB,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uEAAuE;AACvE,MAAM,MAAM,QAAQ,GAChB,IAAI,GACJ,QAAQ,GACR,SAAS,GACT,aAAa,GACb,SAAS,CAAC;AAEd,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,EAAE,EAAE,QAAQ,CAAC;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,gBAAgB,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,yCAAyC;AACzC,MAAM,MAAM,cAAc,GACtB,IAAI,GACJ,SAAS,GACT,OAAO,GACP,SAAS,GACT,SAAS,CAAC;AAEd,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uFAAuF;IACvF,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,6CAA6C;IAC7C,YAAY,CAAC,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,MAAM,EAAE,cAAc,CAAC;IACvB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B"}
|