@slkiser/opencode-quota 2.5.1 → 2.6.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.
Files changed (47) hide show
  1. package/README.md +45 -10
  2. package/dist/lib/alibaba-auth.d.ts +21 -0
  3. package/dist/lib/alibaba-auth.d.ts.map +1 -0
  4. package/dist/lib/alibaba-auth.js +92 -0
  5. package/dist/lib/alibaba-auth.js.map +1 -0
  6. package/dist/lib/config.d.ts.map +1 -1
  7. package/dist/lib/config.js +4 -0
  8. package/dist/lib/config.js.map +1 -1
  9. package/dist/lib/copilot.d.ts +4 -4
  10. package/dist/lib/copilot.d.ts.map +1 -1
  11. package/dist/lib/copilot.js +177 -30
  12. package/dist/lib/copilot.js.map +1 -1
  13. package/dist/lib/entries.d.ts +1 -0
  14. package/dist/lib/entries.d.ts.map +1 -1
  15. package/dist/lib/provider-metadata.d.ts.map +1 -1
  16. package/dist/lib/provider-metadata.js +2 -0
  17. package/dist/lib/provider-metadata.js.map +1 -1
  18. package/dist/lib/quota-status.d.ts +1 -0
  19. package/dist/lib/quota-status.d.ts.map +1 -1
  20. package/dist/lib/quota-status.js +43 -6
  21. package/dist/lib/quota-status.js.map +1 -1
  22. package/dist/lib/qwen-auth.d.ts +10 -0
  23. package/dist/lib/qwen-auth.d.ts.map +1 -1
  24. package/dist/lib/qwen-auth.js +22 -5
  25. package/dist/lib/qwen-auth.js.map +1 -1
  26. package/dist/lib/qwen-local-quota.d.ts +41 -0
  27. package/dist/lib/qwen-local-quota.d.ts.map +1 -1
  28. package/dist/lib/qwen-local-quota.js +132 -20
  29. package/dist/lib/qwen-local-quota.js.map +1 -1
  30. package/dist/lib/types.d.ts +22 -6
  31. package/dist/lib/types.d.ts.map +1 -1
  32. package/dist/lib/types.js +1 -0
  33. package/dist/lib/types.js.map +1 -1
  34. package/dist/plugin.d.ts.map +1 -1
  35. package/dist/plugin.js +88 -28
  36. package/dist/plugin.js.map +1 -1
  37. package/dist/providers/alibaba-coding-plan.d.ts +3 -0
  38. package/dist/providers/alibaba-coding-plan.d.ts.map +1 -0
  39. package/dist/providers/alibaba-coding-plan.js +87 -0
  40. package/dist/providers/alibaba-coding-plan.js.map +1 -0
  41. package/dist/providers/qwen-code.d.ts.map +1 -1
  42. package/dist/providers/qwen-code.js +11 -10
  43. package/dist/providers/qwen-code.js.map +1 -1
  44. package/dist/providers/registry.d.ts.map +1 -1
  45. package/dist/providers/registry.js +2 -0
  46. package/dist/providers/registry.js.map +1 -1
  47. package/package.json +1 -1
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  - Automatic quota toasts after assistant responses
6
6
  - Manual `/quota` and `/tokens_*` commands for deeper local reporting with zero context window pollution
7
7
 
8
- **Quota provider supports**: GitHub Copilot, OpenAI (Plus/Pro), Qwen Code, Chutes AI, Firmware AI, Google Antigravity, and Z.ai coding plan.
8
+ **Quota provider supports**: GitHub Copilot, OpenAI (Plus/Pro), Qwen Code, Alibaba Coding Plan, Chutes AI, Firmware AI, Google Antigravity, and Z.ai coding plan.
9
9
 
10
10
  **Token provider supports**: All models and providers in [models.dev](https://models.dev).
11
11
 
@@ -115,15 +115,28 @@ If you want grouped toast layout instead of the default classic toast:
115
115
  }
116
116
  ```
117
117
 
118
+ If Alibaba Coding Plan auth does not include a `tier`, you can set the fallback tier here:
119
+
120
+ ```jsonc
121
+ {
122
+ "experimental": {
123
+ "quotaToast": {
124
+ "alibabaCodingPlanTier": "lite"
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
118
130
  `/quota` already uses grouped formatting by default, even if toast style stays `classic`.
119
131
 
120
132
  ## Provider Setup At A Glance
121
133
 
122
134
  | Provider | Works automatically | Extra setup when needed |
123
135
  | --- | --- | --- |
124
- | GitHub Copilot | Personal usage via existing OpenCode auth | Add `copilot-quota-token.json` for managed org or enterprise billing |
136
+ | GitHub Copilot | Usually yes | Add `copilot-quota-token.json` only for managed org or enterprise billing |
125
137
  | OpenAI | Yes | None |
126
- | Qwen Code | Needs `opencode-qwencode-auth` | Local-only quota estimation, no remote Qwen quota API |
138
+ | Qwen Code | Needs `opencode-qwencode-auth` | Local free-tier request estimation |
139
+ | Alibaba Coding Plan | Yes | Local request-count estimation |
127
140
  | Firmware AI | Usually yes | Optional API key |
128
141
  | Chutes AI | Usually yes | Optional API key |
129
142
  | Google Antigravity | Needs `opencode-antigravity-auth` | Multi-account account file lives in OpenCode runtime config |
@@ -134,7 +147,7 @@ If you want grouped toast layout instead of the default classic toast:
134
147
  <details>
135
148
  <summary><strong>GitHub Copilot</strong></summary>
136
149
 
137
- Personal Copilot quota works automatically when OpenCode is already signed in.
150
+ Personal Copilot quota works automatically when OpenCode is already signed in. When no `copilot-quota-token.json` exists, the plugin reads the OpenCode Copilot OAuth token from `~/.local/share/opencode/auth.json` and queries `GET https://api.github.com/copilot_internal/user` with `Authorization: Bearer <access token>`.
138
151
 
139
152
  For managed billing, create `copilot-quota-token.json` under the OpenCode runtime config directory. You can find the directory with `opencode debug paths`.
140
153
 
@@ -166,6 +179,7 @@ Behavior notes:
166
179
  - Managed organization and enterprise output is labeled `[Copilot] (business)`.
167
180
  - Managed output includes the org or enterprise slug in the value line so the billing scope is still visible.
168
181
  - If both OpenCode OAuth and `copilot-quota-token.json` exist, the PAT config wins.
182
+ - If no PAT config exists, OpenCode Copilot OAuth is treated as personal quota auth via `/copilot_internal/user`.
169
183
  - If the PAT config is invalid, the plugin reports that error and does not silently fall back to OAuth.
170
184
  - `business` requires `organization`.
171
185
  - Enterprise premium usage does not support fine-grained PATs or GitHub App tokens. Use a supported enterprise token such as a classic PAT.
@@ -173,7 +187,7 @@ Behavior notes:
173
187
  Useful checks:
174
188
 
175
189
  - Run `/quota_status` and inspect `copilot_quota_auth`.
176
- - Look for `billing_mode`, `billing_scope`, `effective_source`, and `billing_api_access_likely`.
190
+ - Look for `billing_mode`, `billing_scope`, `quota_api`, `effective_source`, and `billing_api_access_likely`.
177
191
 
178
192
  </details>
179
193
 
@@ -187,19 +201,39 @@ No extra setup is required if OpenCode already has OpenAI or ChatGPT auth config
187
201
  <details>
188
202
  <summary><strong>Qwen Code</strong></summary>
189
203
 
190
- Qwen support is local-only estimation. The plugin does not call an Alibaba quota API.
204
+ Qwen support is local-only estimation for the free plan. The plugin does not call an Alibaba quota API.
191
205
 
192
206
  Current behavior:
193
207
 
194
- - 1000 requests per UTC day
195
- - 60 requests per rolling minute
208
+ - Free tier only: 1000 requests per UTC day
209
+ - Free tier only: 60 requests per rolling minute
196
210
  - Counters increment on successful question-tool completions while the current model is `qwen-code/*`
197
211
 
198
212
  State file path:
199
213
 
200
214
  - `.../opencode/opencode-quota/qwen-local-quota.json`
201
215
 
202
- Run `/quota_status` to verify auth detection and local counter status.
216
+ Run `/quota_status` to verify auth detection, `qwen_local_plan`, and local counter status.
217
+
218
+ </details>
219
+
220
+ <details>
221
+ <summary><strong>Alibaba Coding Plan</strong></summary>
222
+
223
+ Alibaba Coding Plan uses native OpenCode auth from either `alibaba` or `alibaba-coding-plan` in `auth.json`, instead of the Qwen companion plugin. Quota estimation is request-count based with rolling windows.
224
+
225
+ Supported tiers:
226
+
227
+ - `lite`: 1200 requests / 5 hours, 9000 / week, 18000 / month
228
+ - `pro`: 6000 requests / 5 hours, 45000 / week, 90000 / month
229
+ - If `tier` is missing from auth, the plugin uses `experimental.quotaToast.alibabaCodingPlanTier` and defaults that setting to `lite`
230
+ - Counters increment on successful question-tool completions while the current model is `alibaba/*` or `alibaba-cn/*`
231
+
232
+ State file path:
233
+
234
+ - `.../opencode/opencode-quota/alibaba-coding-plan-local-quota.json`
235
+
236
+ `/quota_status` shows whether Alibaba auth is configured, the resolved Alibaba coding-plan tier, the Alibaba state-file path, and the current 5h/weekly/monthly usage when this plan is active.
203
237
 
204
238
  </details>
205
239
 
@@ -291,6 +325,7 @@ All plugin settings live under `experimental.quotaToast`.
291
325
  | `layout.narrowAt` | `42` | Compact layout breakpoint |
292
326
  | `layout.tinyAt` | `32` | Tiny layout breakpoint |
293
327
  | `googleModels` | `["CLAUDE"]` | Google model keys: `CLAUDE`, `G3PRO`, `G3FLASH`, `G3IMAGE` |
328
+ | `alibabaCodingPlanTier` | `"lite"` | Fallback Alibaba Coding Plan tier when auth does not include `tier` |
294
329
  | `debug` | `false` | Include debug context in toast output |
295
330
 
296
331
  ## Token Pricing Snapshot
@@ -326,7 +361,7 @@ If something is missing or looks wrong:
326
361
  2. Confirm the expected provider appears in the detected provider list.
327
362
  3. If token reports are empty, make sure OpenCode has already created `opencode.db`.
328
363
  4. If Copilot managed billing is expected, confirm `copilot-quota-token.json` is present and valid.
329
- 5. If Google or Qwen support is expected, confirm the companion auth plugin is installed.
364
+ 5. If Google or Qwen support is expected, confirm the companion auth plugin is installed. If Alibaba Coding Plan support is expected, confirm OpenCode `alibaba` or `alibaba-coding-plan` auth is configured; `tier` may be `lite` or `pro`, and if it is missing the plugin falls back to `experimental.quotaToast.alibabaCodingPlanTier`.
330
365
 
331
366
  If `opencode.db` is missing, start OpenCode once and let its local migration complete.
332
367
 
@@ -0,0 +1,21 @@
1
+ import type { AlibabaCodingPlanTier, AuthData } from "./types.js";
2
+ export declare const DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS = 5000;
3
+ export type ResolvedAlibabaCodingPlanAuth = {
4
+ state: "none";
5
+ } | {
6
+ state: "configured";
7
+ apiKey: string;
8
+ tier: AlibabaCodingPlanTier;
9
+ } | {
10
+ state: "invalid";
11
+ error: string;
12
+ rawTier?: string;
13
+ };
14
+ export declare function resolveAlibabaCodingPlanAuth(auth: AuthData | null | undefined, fallbackTier?: AlibabaCodingPlanTier): ResolvedAlibabaCodingPlanAuth;
15
+ export declare function resolveAlibabaCodingPlanAuthCached(params?: {
16
+ maxAgeMs?: number;
17
+ fallbackTier?: AlibabaCodingPlanTier;
18
+ }): Promise<ResolvedAlibabaCodingPlanAuth>;
19
+ export declare function hasAlibabaAuth(auth: AuthData | null | undefined): boolean;
20
+ export declare function isAlibabaModelId(model?: string): boolean;
21
+ //# sourceMappingURL=alibaba-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alibaba-auth.d.ts","sourceRoot":"","sources":["../../src/lib/alibaba-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,qBAAqB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGnF,eAAO,MAAM,qCAAqC,OAAQ,CAAC;AAE3D,MAAM,MAAM,6BAA6B,GACrC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,qBAAqB,CAAA;CAAE,GACpE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA+C1D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EACjC,YAAY,GAAE,qBAAwD,GACrE,6BAA6B,CAkC/B;AAED,wBAAsB,kCAAkC,CAAC,MAAM,CAAC,EAAE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,qBAAqB,CAAC;CACtC,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAKzC;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEzE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAIxD"}
@@ -0,0 +1,92 @@
1
+ import { readAuthFileCached } from "./opencode-auth.js";
2
+ export const DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS = 5_000;
3
+ function getFirstString(obj, keys) {
4
+ for (const key of keys) {
5
+ const value = obj[key];
6
+ if (typeof value !== "string")
7
+ continue;
8
+ const trimmed = value.trim();
9
+ if (trimmed)
10
+ return trimmed;
11
+ }
12
+ return undefined;
13
+ }
14
+ function normalizeAlibabaTier(value) {
15
+ const normalized = value?.trim().toLowerCase();
16
+ if (!normalized)
17
+ return null;
18
+ if (normalized === "lite")
19
+ return "lite";
20
+ if (normalized === "pro" || normalized === "professional")
21
+ return "pro";
22
+ return null;
23
+ }
24
+ const DEFAULT_ALIBABA_CODING_PLAN_TIER = "lite";
25
+ function getAlibabaAuth(auth) {
26
+ for (const key of ["alibaba-coding-plan", "alibaba"]) {
27
+ const alibaba = auth?.[key];
28
+ if (!alibaba)
29
+ continue;
30
+ const credential = typeof alibaba.key === "string" && alibaba.key.trim()
31
+ ? alibaba.key.trim()
32
+ : typeof alibaba.access === "string" && alibaba.access.trim()
33
+ ? alibaba.access.trim()
34
+ : "";
35
+ if (!credential) {
36
+ continue;
37
+ }
38
+ return alibaba;
39
+ }
40
+ return null;
41
+ }
42
+ function getAlibabaCredential(auth) {
43
+ return (auth.key?.trim() || auth.access?.trim() || "");
44
+ }
45
+ export function resolveAlibabaCodingPlanAuth(auth, fallbackTier = DEFAULT_ALIBABA_CODING_PLAN_TIER) {
46
+ const alibaba = getAlibabaAuth(auth);
47
+ if (!alibaba) {
48
+ return { state: "none" };
49
+ }
50
+ const rawTier = getFirstString(alibaba, [
51
+ "tier",
52
+ "planTier",
53
+ "plan_tier",
54
+ "subscriptionTier",
55
+ ]);
56
+ const tier = normalizeAlibabaTier(rawTier);
57
+ if (!rawTier) {
58
+ return {
59
+ state: "configured",
60
+ apiKey: getAlibabaCredential(alibaba),
61
+ tier: fallbackTier,
62
+ };
63
+ }
64
+ if (!tier) {
65
+ return {
66
+ state: "invalid",
67
+ error: `Unsupported Alibaba Coding Plan tier: ${rawTier}`,
68
+ rawTier,
69
+ };
70
+ }
71
+ return {
72
+ state: "configured",
73
+ apiKey: getAlibabaCredential(alibaba),
74
+ tier,
75
+ };
76
+ }
77
+ export async function resolveAlibabaCodingPlanAuthCached(params) {
78
+ const auth = await readAuthFileCached({
79
+ maxAgeMs: Math.max(0, params?.maxAgeMs ?? DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS),
80
+ });
81
+ return resolveAlibabaCodingPlanAuth(auth, params?.fallbackTier);
82
+ }
83
+ export function hasAlibabaAuth(auth) {
84
+ return getAlibabaAuth(auth) !== null;
85
+ }
86
+ export function isAlibabaModelId(model) {
87
+ if (typeof model !== "string")
88
+ return false;
89
+ const normalized = model.toLowerCase();
90
+ return normalized.startsWith("alibaba/") || normalized.startsWith("alibaba-cn/");
91
+ }
92
+ //# sourceMappingURL=alibaba-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alibaba-auth.js","sourceRoot":"","sources":["../../src/lib/alibaba-auth.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,YAAY,CAAC;AAWlE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAgBD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IACN,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,YAAY,CAAC,EAAE;oBAAE,UAAU,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;iBAAE,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAC9F,CAAC;CACH,EACD,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA+K3B"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,YAAY,CAAC;AAWlE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAgBD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IACN,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,YAAY,CAAC,EAAE;oBAAE,UAAU,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;iBAAE,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAC9F,CAAC;CACH,EACD,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAoL3B"}
@@ -61,6 +61,10 @@ export async function loadConfig(client, meta) {
61
61
  googleModels: Array.isArray(quotaToastConfig.googleModels)
62
62
  ? quotaToastConfig.googleModels.filter(isValidGoogleModelId)
63
63
  : DEFAULT_CONFIG.googleModels,
64
+ alibabaCodingPlanTier: quotaToastConfig.alibabaCodingPlanTier === "lite" ||
65
+ quotaToastConfig.alibabaCodingPlanTier === "pro"
66
+ ? quotaToastConfig.alibabaCodingPlanTier
67
+ : DEFAULT_CONFIG.alibabaCodingPlanTier,
64
68
  showOnIdle: typeof quotaToastConfig.showOnIdle === "boolean"
65
69
  ? quotaToastConfig.showOnIdle
66
70
  : DEFAULT_CONFIG.showOnIdle,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,14 @@
1
1
  /**
2
2
  * GitHub Copilot premium request usage fetcher.
3
3
  *
4
- * The plugin only uses documented GitHub billing APIs:
5
- * - /users/{username}/settings/billing/premium_request/usage
6
- * - /organizations/{org}/settings/billing/premium_request/usage
7
- * - /enterprises/{enterprise}/settings/billing/premium_request/usage
4
+ * The plugin uses GitHub billing APIs for PAT-backed usage checks and
5
+ * `GET /copilot_internal/user` for OAuth-backed personal quota checks.
8
6
  */
9
7
  import type { AuthData, CopilotQuotaConfig, CopilotResult } from "./types.js";
10
8
  type CopilotAuthKeyName = "github-copilot" | "copilot" | "copilot-chat" | "github-copilot-chat";
11
9
  type CopilotPatTokenKind = "github_pat" | "ghp" | "ghu" | "ghs" | "other";
12
10
  type EffectiveCopilotAuthSource = "pat" | "oauth" | "none";
11
+ type CopilotQuotaApi = "github_billing_api" | "copilot_internal_user" | "none";
13
12
  type CopilotBillingMode = "user_quota" | "organization_usage" | "enterprise_usage" | "none";
14
13
  type CopilotRemainingTotalsState = "available" | "not_available_from_org_usage" | "not_available_from_enterprise_usage" | "unavailable";
15
14
  export type CopilotPatState = "absent" | "invalid" | "valid";
@@ -31,6 +30,7 @@ export interface CopilotQuotaAuthDiagnostics {
31
30
  };
32
31
  effectiveSource: EffectiveCopilotAuthSource;
33
32
  override: "pat_overrides_oauth" | "none";
33
+ quotaApi: CopilotQuotaApi;
34
34
  billingMode: CopilotBillingMode;
35
35
  billingScope: "user" | "organization" | "enterprise" | "none";
36
36
  billingApiAccessLikely: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/lib/copilot.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,QAAQ,EAIR,kBAAkB,EAElB,aAAa,EAGd,MAAM,YAAY,CAAC;AAWpB,KAAK,kBAAkB,GACnB,gBAAgB,GAChB,SAAS,GACT,cAAc,GACd,qBAAqB,CAAC;AAC1B,KAAK,mBAAmB,GAAG,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAC1E,KAAK,0BAA0B,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAC3D,KAAK,kBAAkB,GAAG,YAAY,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAC5F,KAAK,2BAA2B,GAC5B,WAAW,GACX,8BAA8B,GAC9B,qCAAqC,GACrC,aAAa,CAAC;AA4BlB,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,oBAAoB,CAAC;IAC1B,KAAK,EAAE;QACL,UAAU,EAAE,OAAO,CAAC;QACpB,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;QACnC,eAAe,EAAE,OAAO,CAAC;QACzB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,eAAe,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAAC;IACzC,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;IAC9D,sBAAsB,EAAE,OAAO,CAAC;IAChC,oBAAoB,EAAE,2BAA2B,CAAC;IAClD,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAiOD,wBAAgB,iCAAiC,IAAI,MAAM,EAAE,CAK5D;AA6DD,wBAAgB,uBAAuB,IAAI,oBAAoB,CAsC9D;AA0BD,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,2BAA2B,CA8CrG;AAqTD;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CAmFhE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CA0BvE"}
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/lib/copilot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,QAAQ,EAIR,kBAAkB,EAElB,aAAa,EAGd,MAAM,YAAY,CAAC;AAYpB,KAAK,kBAAkB,GACnB,gBAAgB,GAChB,SAAS,GACT,cAAc,GACd,qBAAqB,CAAC;AAC1B,KAAK,mBAAmB,GAAG,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAC1E,KAAK,0BAA0B,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAC3D,KAAK,eAAe,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,MAAM,CAAC;AAC/E,KAAK,kBAAkB,GAAG,YAAY,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAC5F,KAAK,2BAA2B,GAC5B,WAAW,GACX,8BAA8B,GAC9B,qCAAqC,GACrC,aAAa,CAAC;AA4BlB,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,oBAAoB,CAAC;IAC1B,KAAK,EAAE;QACL,UAAU,EAAE,OAAO,CAAC;QACpB,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;QACnC,eAAe,EAAE,OAAO,CAAC;QACzB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,eAAe,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAAC;IACzC,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;IAC9D,sBAAsB,EAAE,OAAO,CAAC;IAChC,oBAAoB,EAAE,2BAA2B,CAAC;IAClD,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAqSD,wBAAgB,iCAAiC,IAAI,MAAM,EAAE,CAK5D;AA6DD,wBAAgB,uBAAuB,IAAI,oBAAoB,CAsC9D;AA0BD,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,2BAA2B,CA0DrG;AA8YD;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CAyEhE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CA0BvE"}
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * GitHub Copilot premium request usage fetcher.
3
3
  *
4
- * The plugin only uses documented GitHub billing APIs:
5
- * - /users/{username}/settings/billing/premium_request/usage
6
- * - /organizations/{org}/settings/billing/premium_request/usage
7
- * - /enterprises/{enterprise}/settings/billing/premium_request/usage
4
+ * The plugin uses GitHub billing APIs for PAT-backed usage checks and
5
+ * `GET /copilot_internal/user` for OAuth-backed personal quota checks.
8
6
  */
9
7
  import { existsSync, readFileSync } from "fs";
10
8
  import { join } from "path";
@@ -12,9 +10,74 @@ import { fetchWithTimeout } from "./http.js";
12
10
  import { readAuthFile } from "./opencode-auth.js";
13
11
  import { getOpencodeRuntimeDirCandidates } from "./opencode-runtime-paths.js";
14
12
  const GITHUB_API_BASE_URL = "https://api.github.com";
13
+ const COPILOT_INTERNAL_USER_URL = `${GITHUB_API_BASE_URL}/copilot_internal/user`;
15
14
  const GITHUB_API_VERSION = "2022-11-28";
16
15
  const COPILOT_QUOTA_CONFIG_FILENAME = "copilot-quota-token.json";
17
16
  const USER_AGENT = "opencode-quota/copilot-billing";
17
+ function getNestedValue(source, path) {
18
+ let current = source;
19
+ for (const key of path) {
20
+ if (!current || typeof current !== "object" || !(key in current)) {
21
+ return undefined;
22
+ }
23
+ current = current[key];
24
+ }
25
+ return current;
26
+ }
27
+ function getFirstNestedValue(source, paths) {
28
+ for (const path of paths) {
29
+ const value = getNestedValue(source, path);
30
+ if (value !== undefined) {
31
+ return value;
32
+ }
33
+ }
34
+ return undefined;
35
+ }
36
+ function coerceFiniteNumber(value) {
37
+ if (typeof value === "number" && Number.isFinite(value)) {
38
+ return value;
39
+ }
40
+ if (typeof value === "string") {
41
+ const trimmed = value.trim();
42
+ if (!trimmed)
43
+ return undefined;
44
+ const parsed = Number(trimmed);
45
+ if (Number.isFinite(parsed)) {
46
+ return parsed;
47
+ }
48
+ }
49
+ return undefined;
50
+ }
51
+ function coerceNonEmptyString(value) {
52
+ if (typeof value !== "string") {
53
+ return undefined;
54
+ }
55
+ const trimmed = value.trim();
56
+ return trimmed || undefined;
57
+ }
58
+ function getFirstNestedNumber(source, paths) {
59
+ return coerceFiniteNumber(getFirstNestedValue(source, paths));
60
+ }
61
+ function getFirstNestedString(source, paths) {
62
+ return coerceNonEmptyString(getFirstNestedValue(source, paths));
63
+ }
64
+ function normalizeCopilotTier(value) {
65
+ const normalized = value?.trim().toLowerCase();
66
+ if (!normalized)
67
+ return undefined;
68
+ if (normalized === "free")
69
+ return "free";
70
+ if (normalized === "pro")
71
+ return "pro";
72
+ if (normalized === "pro+" || normalized === "pro_plus" || normalized === "pro-plus") {
73
+ return "pro+";
74
+ }
75
+ if (normalized === "business")
76
+ return "business";
77
+ if (normalized === "enterprise")
78
+ return "enterprise";
79
+ return undefined;
80
+ }
18
81
  const COPILOT_PLAN_LIMITS = {
19
82
  free: 50,
20
83
  pro: 300,
@@ -287,25 +350,36 @@ export function getCopilotQuotaAuthDiagnostics(authData) {
287
350
  effectiveSource = "pat";
288
351
  else if (auth)
289
352
  effectiveSource = "oauth";
290
- const billingTarget = pat.state === "valid" ? resolvedPatTarget.target : !patBlocksOAuth && auth ? { scope: "user" } : null;
353
+ const billingTarget = pat.state === "valid"
354
+ ? resolvedPatTarget.target
355
+ : !patBlocksOAuth && auth
356
+ ? { scope: "user" }
357
+ : null;
291
358
  const billingMode = getBillingModeForTarget(billingTarget);
359
+ const oauthHasAccessToken = Boolean(auth?.access?.trim());
360
+ const quotaApi = effectiveSource === "pat"
361
+ ? pat.state === "valid"
362
+ ? "github_billing_api"
363
+ : "none"
364
+ : effectiveSource === "oauth" && oauthHasAccessToken
365
+ ? "copilot_internal_user"
366
+ : "none";
292
367
  return {
293
368
  pat,
294
369
  oauth: {
295
370
  configured: Boolean(auth),
296
371
  keyName,
297
372
  hasRefreshToken: Boolean(auth?.refresh),
298
- hasAccessToken: Boolean(auth?.access),
373
+ hasAccessToken: oauthHasAccessToken,
299
374
  },
300
375
  effectiveSource,
301
376
  override: patBlocksOAuth && auth ? "pat_overrides_oauth" : "none",
377
+ quotaApi,
302
378
  billingMode,
303
379
  billingScope: getBillingScopeForTarget(billingTarget),
304
380
  billingApiAccessLikely: effectiveSource === "pat"
305
- ? Boolean(billingTarget) &&
306
- !resolvedPatTarget.error &&
307
- !tokenCompatibilityError
308
- : effectiveSource === "oauth",
381
+ ? Boolean(billingTarget) && !resolvedPatTarget.error && !tokenCompatibilityError
382
+ : quotaApi === "copilot_internal_user",
309
383
  remainingTotalsState: getRemainingTotalsStateForTarget(billingTarget),
310
384
  queryPeriod: billingTarget && billingTarget.scope !== "user"
311
385
  ? billingTarget.billingPeriod
@@ -428,6 +502,90 @@ async function fetchPremiumRequestUsage(params) {
428
502
  }
429
503
  throw new Error("Unable to fetch Copilot premium request usage");
430
504
  }
505
+ async function fetchCopilotInternalUser(token) {
506
+ const result = await fetchGitHubRestJsonOnce(COPILOT_INTERNAL_USER_URL, token, "bearer");
507
+ if (result.ok) {
508
+ return result.data;
509
+ }
510
+ throw new Error(`GitHub API error ${result.status}: ${result.message}`);
511
+ }
512
+ function toUserQuotaResultFromCopilotInternal(response) {
513
+ const totalPaths = [
514
+ ["quota", "limit"],
515
+ ["quota", "total"],
516
+ ["monthly_quota", "limit"],
517
+ ["monthly_quota", "total"],
518
+ ["monthly_premium_requests", "limit"],
519
+ ["monthly_premium_requests", "total"],
520
+ ["premium_requests", "limit"],
521
+ ["premium_requests", "total"],
522
+ ["limit"],
523
+ ["total"],
524
+ ["quota_limit"],
525
+ ["monthly_limit"],
526
+ ["included_premium_requests"],
527
+ ];
528
+ const usedPaths = [
529
+ ["quota", "used"],
530
+ ["monthly_quota", "used"],
531
+ ["monthly_premium_requests", "used"],
532
+ ["premium_requests", "used"],
533
+ ["used"],
534
+ ["quota_used"],
535
+ ["monthly_used"],
536
+ ["premium_requests_used"],
537
+ ];
538
+ const remainingPaths = [
539
+ ["quota", "remaining"],
540
+ ["monthly_quota", "remaining"],
541
+ ["monthly_premium_requests", "remaining"],
542
+ ["premium_requests", "remaining"],
543
+ ["remaining"],
544
+ ["quota_remaining"],
545
+ ["monthly_remaining"],
546
+ ["premium_requests_remaining"],
547
+ ];
548
+ const resetPaths = [
549
+ ["quota", "reset_at"],
550
+ ["monthly_quota", "reset_at"],
551
+ ["monthly_premium_requests", "reset_at"],
552
+ ["premium_requests", "reset_at"],
553
+ ["reset_at"],
554
+ ["quota_reset_at"],
555
+ ];
556
+ const tierPaths = [
557
+ ["plan", "type"],
558
+ ["plan", "name"],
559
+ ["plan"],
560
+ ["subscription_plan"],
561
+ ["sku"],
562
+ ];
563
+ let total = getFirstNestedNumber(response, totalPaths);
564
+ let used = getFirstNestedNumber(response, usedPaths);
565
+ const remaining = getFirstNestedNumber(response, remainingPaths);
566
+ const resetTimeIso = getFirstNestedString(response, resetPaths) ?? getApproxNextResetIso();
567
+ const tier = normalizeCopilotTier(getFirstNestedString(response, tierPaths));
568
+ if (total === undefined && used !== undefined && remaining !== undefined) {
569
+ total = used + remaining;
570
+ }
571
+ if (used === undefined && total !== undefined && remaining !== undefined) {
572
+ used = Math.max(0, total - remaining);
573
+ }
574
+ if (total === undefined && tier) {
575
+ total = COPILOT_PLAN_LIMITS[tier];
576
+ }
577
+ if (!Number.isFinite(total) || total === undefined || total <= 0 || used === undefined || used < 0) {
578
+ throw new Error("GitHub /copilot_internal/user response did not include usable personal quota fields.");
579
+ }
580
+ return {
581
+ success: true,
582
+ mode: "user_quota",
583
+ used,
584
+ total,
585
+ percentRemaining: computePercentRemainingFromUsed({ used, total }),
586
+ resetTimeIso,
587
+ };
588
+ }
431
589
  function getApproxNextResetIso(nowMs = Date.now()) {
432
590
  const now = new Date(nowMs);
433
591
  return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1)).toISOString();
@@ -529,9 +687,6 @@ function toEnterpriseUsageResultFromBilling(params) {
529
687
  resetTimeIso: getApproxNextResetIso(),
530
688
  };
531
689
  }
532
- function getOAuthTokenCandidates(auth) {
533
- return dedupeStrings([auth.access, auth.refresh]);
534
- }
535
690
  function toQuotaError(message) {
536
691
  return { success: false, error: message };
537
692
  }
@@ -587,25 +742,17 @@ export async function queryCopilotQuota() {
587
742
  if (!auth) {
588
743
  return null;
589
744
  }
590
- const tokenCandidates = getOAuthTokenCandidates(auth);
591
- if (tokenCandidates.length === 0) {
592
- return null;
745
+ const accessToken = auth.access?.trim();
746
+ if (!accessToken) {
747
+ return toQuotaError("Copilot OAuth auth is configured but missing an access token required for GitHub /copilot_internal/user.");
593
748
  }
594
- let lastError = null;
595
- for (const token of tokenCandidates) {
596
- try {
597
- const { response } = await fetchPremiumRequestUsage({
598
- token,
599
- target: { scope: "user" },
600
- });
601
- return toUserQuotaResultFromBilling(response);
602
- }
603
- catch (error) {
604
- lastError = error instanceof Error ? error.message : String(error);
605
- }
749
+ try {
750
+ const response = await fetchCopilotInternalUser(accessToken);
751
+ return toUserQuotaResultFromCopilotInternal(response);
752
+ }
753
+ catch (error) {
754
+ return toQuotaError(error instanceof Error ? error.message : String(error));
606
755
  }
607
- return toQuotaError(lastError ??
608
- "Copilot billing usage could not be fetched from OpenCode auth. Configure copilot-quota-token.json to provide an explicit tier and PAT.");
609
756
  }
610
757
  export function formatCopilotQuota(result) {
611
758
  if (!result || !result.success) {