@slkiser/opencode-quota 4.1.0 → 4.3.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 (209) hide show
  1. package/README.md +85 -28
  2. package/dist/lib/api-key-resolver.d.ts +73 -22
  3. package/dist/lib/api-key-resolver.d.ts.map +1 -1
  4. package/dist/lib/api-key-resolver.js +102 -15
  5. package/dist/lib/api-key-resolver.js.map +1 -1
  6. package/dist/lib/chutes-config.d.ts.map +1 -1
  7. package/dist/lib/chutes-config.js +2 -4
  8. package/dist/lib/chutes-config.js.map +1 -1
  9. package/dist/lib/config.d.ts +1 -1
  10. package/dist/lib/config.d.ts.map +1 -1
  11. package/dist/lib/config.js +22 -0
  12. package/dist/lib/config.js.map +1 -1
  13. package/dist/lib/copilot.d.ts.map +1 -1
  14. package/dist/lib/copilot.js +82 -31
  15. package/dist/lib/copilot.js.map +1 -1
  16. package/dist/lib/deepseek-auth.d.ts.map +1 -1
  17. package/dist/lib/deepseek-auth.js +3 -7
  18. package/dist/lib/deepseek-auth.js.map +1 -1
  19. package/dist/lib/entries.d.ts +9 -4
  20. package/dist/lib/entries.d.ts.map +1 -1
  21. package/dist/lib/entries.js.map +1 -1
  22. package/dist/lib/glm-coding-plan.d.ts +18 -0
  23. package/dist/lib/glm-coding-plan.d.ts.map +1 -0
  24. package/dist/lib/glm-coding-plan.js +68 -0
  25. package/dist/lib/glm-coding-plan.js.map +1 -0
  26. package/dist/lib/google-agy-companion.d.ts +4 -25
  27. package/dist/lib/google-agy-companion.d.ts.map +1 -1
  28. package/dist/lib/google-agy-companion.js +47 -272
  29. package/dist/lib/google-agy-companion.js.map +1 -1
  30. package/dist/lib/google-agy.d.ts.map +1 -1
  31. package/dist/lib/google-agy.js +7 -25
  32. package/dist/lib/google-agy.js.map +1 -1
  33. package/dist/lib/google-antigravity-companion.d.ts +4 -25
  34. package/dist/lib/google-antigravity-companion.d.ts.map +1 -1
  35. package/dist/lib/google-antigravity-companion.js +44 -283
  36. package/dist/lib/google-antigravity-companion.js.map +1 -1
  37. package/dist/lib/google-companion-credentials.d.ts +70 -0
  38. package/dist/lib/google-companion-credentials.d.ts.map +1 -0
  39. package/dist/lib/google-companion-credentials.js +265 -0
  40. package/dist/lib/google-companion-credentials.js.map +1 -0
  41. package/dist/lib/google-gemini-cli-companion.d.ts +4 -25
  42. package/dist/lib/google-gemini-cli-companion.d.ts.map +1 -1
  43. package/dist/lib/google-gemini-cli-companion.js +47 -258
  44. package/dist/lib/google-gemini-cli-companion.js.map +1 -1
  45. package/dist/lib/google-gemini-cli.d.ts.map +1 -1
  46. package/dist/lib/google-gemini-cli.js +2 -20
  47. package/dist/lib/google-gemini-cli.js.map +1 -1
  48. package/dist/lib/google.d.ts.map +1 -1
  49. package/dist/lib/google.js +23 -45
  50. package/dist/lib/google.js.map +1 -1
  51. package/dist/lib/kimi-auth.d.ts +3 -26
  52. package/dist/lib/kimi-auth.d.ts.map +1 -1
  53. package/dist/lib/kimi-auth.js +24 -91
  54. package/dist/lib/kimi-auth.js.map +1 -1
  55. package/dist/lib/maintainer-announcements.js +2 -2
  56. package/dist/lib/maintainer-announcements.js.map +1 -1
  57. package/dist/lib/map-with-concurrency.d.ts +2 -0
  58. package/dist/lib/map-with-concurrency.d.ts.map +1 -0
  59. package/dist/lib/map-with-concurrency.js +17 -0
  60. package/dist/lib/map-with-concurrency.js.map +1 -0
  61. package/dist/lib/nanogpt-config.d.ts.map +1 -1
  62. package/dist/lib/nanogpt-config.js +2 -4
  63. package/dist/lib/nanogpt-config.js.map +1 -1
  64. package/dist/lib/openrouter.d.ts +13 -0
  65. package/dist/lib/openrouter.d.ts.map +1 -0
  66. package/dist/lib/openrouter.js +41 -0
  67. package/dist/lib/openrouter.js.map +1 -0
  68. package/dist/lib/provider-metadata.d.ts +11 -0
  69. package/dist/lib/provider-metadata.d.ts.map +1 -1
  70. package/dist/lib/provider-metadata.js +11 -0
  71. package/dist/lib/provider-metadata.js.map +1 -1
  72. package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
  73. package/dist/lib/quota-dialog-commands.js +3 -10
  74. package/dist/lib/quota-dialog-commands.js.map +1 -1
  75. package/dist/lib/quota-export.d.ts.map +1 -1
  76. package/dist/lib/quota-export.js +1 -0
  77. package/dist/lib/quota-export.js.map +1 -1
  78. package/dist/lib/quota-providers-remote.d.ts +0 -1
  79. package/dist/lib/quota-providers-remote.d.ts.map +1 -1
  80. package/dist/lib/quota-providers-remote.js +3 -16
  81. package/dist/lib/quota-providers-remote.js.map +1 -1
  82. package/dist/lib/quota-render-data.d.ts.map +1 -1
  83. package/dist/lib/quota-render-data.js +40 -15
  84. package/dist/lib/quota-render-data.js.map +1 -1
  85. package/dist/lib/quota-runtime-context.d.ts +2 -0
  86. package/dist/lib/quota-runtime-context.d.ts.map +1 -1
  87. package/dist/lib/quota-runtime-context.js +40 -0
  88. package/dist/lib/quota-runtime-context.js.map +1 -1
  89. package/dist/lib/quota-state.d.ts.map +1 -1
  90. package/dist/lib/quota-state.js +89 -5
  91. package/dist/lib/quota-state.js.map +1 -1
  92. package/dist/lib/quota-status.d.ts +7 -17
  93. package/dist/lib/quota-status.d.ts.map +1 -1
  94. package/dist/lib/quota-status.js +116 -1036
  95. package/dist/lib/quota-status.js.map +1 -1
  96. package/dist/lib/quota-telemetry.d.ts +45 -0
  97. package/dist/lib/quota-telemetry.d.ts.map +1 -0
  98. package/dist/lib/quota-telemetry.js +300 -0
  99. package/dist/lib/quota-telemetry.js.map +1 -0
  100. package/dist/lib/synthetic-config.d.ts.map +1 -1
  101. package/dist/lib/synthetic-config.js +2 -4
  102. package/dist/lib/synthetic-config.js.map +1 -1
  103. package/dist/lib/tui-runtime.d.ts.map +1 -1
  104. package/dist/lib/tui-runtime.js +10 -1
  105. package/dist/lib/tui-runtime.js.map +1 -1
  106. package/dist/lib/types.d.ts +17 -1
  107. package/dist/lib/types.d.ts.map +1 -1
  108. package/dist/lib/types.js +3 -0
  109. package/dist/lib/types.js.map +1 -1
  110. package/dist/lib/zai-auth.d.ts +3 -26
  111. package/dist/lib/zai-auth.d.ts.map +1 -1
  112. package/dist/lib/zai-auth.js +24 -94
  113. package/dist/lib/zai-auth.js.map +1 -1
  114. package/dist/lib/zai.d.ts +1 -8
  115. package/dist/lib/zai.d.ts.map +1 -1
  116. package/dist/lib/zai.js +11 -97
  117. package/dist/lib/zai.js.map +1 -1
  118. package/dist/lib/zhipu-auth.d.ts +3 -26
  119. package/dist/lib/zhipu-auth.d.ts.map +1 -1
  120. package/dist/lib/zhipu-auth.js +24 -94
  121. package/dist/lib/zhipu-auth.js.map +1 -1
  122. package/dist/lib/zhipu.d.ts +1 -8
  123. package/dist/lib/zhipu.d.ts.map +1 -1
  124. package/dist/lib/zhipu.js +10 -89
  125. package/dist/lib/zhipu.js.map +1 -1
  126. package/dist/plugin.d.ts.map +1 -1
  127. package/dist/plugin.js +4 -0
  128. package/dist/plugin.js.map +1 -1
  129. package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
  130. package/dist/providers/alibaba-coding-plan.js +33 -6
  131. package/dist/providers/alibaba-coding-plan.js.map +1 -1
  132. package/dist/providers/anthropic.d.ts.map +1 -1
  133. package/dist/providers/anthropic.js +35 -7
  134. package/dist/providers/anthropic.js.map +1 -1
  135. package/dist/providers/chutes.d.ts.map +1 -1
  136. package/dist/providers/chutes.js +10 -3
  137. package/dist/providers/chutes.js.map +1 -1
  138. package/dist/providers/copilot.d.ts.map +1 -1
  139. package/dist/providers/copilot.js +79 -29
  140. package/dist/providers/copilot.js.map +1 -1
  141. package/dist/providers/cursor.d.ts.map +1 -1
  142. package/dist/providers/cursor.js +34 -6
  143. package/dist/providers/cursor.js.map +1 -1
  144. package/dist/providers/deepseek.d.ts.map +1 -1
  145. package/dist/providers/deepseek.js +10 -3
  146. package/dist/providers/deepseek.js.map +1 -1
  147. package/dist/providers/glm-coding-plan-provider.d.ts +9 -0
  148. package/dist/providers/glm-coding-plan-provider.d.ts.map +1 -1
  149. package/dist/providers/glm-coding-plan-provider.js +24 -2
  150. package/dist/providers/glm-coding-plan-provider.js.map +1 -1
  151. package/dist/providers/google-agy.d.ts.map +1 -1
  152. package/dist/providers/google-agy.js +23 -6
  153. package/dist/providers/google-agy.js.map +1 -1
  154. package/dist/providers/google-antigravity.d.ts.map +1 -1
  155. package/dist/providers/google-antigravity.js +31 -6
  156. package/dist/providers/google-antigravity.js.map +1 -1
  157. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  158. package/dist/providers/google-gemini-cli.js +24 -6
  159. package/dist/providers/google-gemini-cli.js.map +1 -1
  160. package/dist/providers/kimi-code.d.ts.map +1 -1
  161. package/dist/providers/kimi-code.js +27 -8
  162. package/dist/providers/kimi-code.js.map +1 -1
  163. package/dist/providers/mimo.d.ts.map +1 -1
  164. package/dist/providers/mimo.js +12 -5
  165. package/dist/providers/mimo.js.map +1 -1
  166. package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
  167. package/dist/providers/minimax-coding-plan.js +37 -6
  168. package/dist/providers/minimax-coding-plan.js.map +1 -1
  169. package/dist/providers/nanogpt.d.ts.map +1 -1
  170. package/dist/providers/nanogpt.js +41 -4
  171. package/dist/providers/nanogpt.js.map +1 -1
  172. package/dist/providers/openai.d.ts.map +1 -1
  173. package/dist/providers/openai.js +20 -3
  174. package/dist/providers/openai.js.map +1 -1
  175. package/dist/providers/opencode-go.d.ts.map +1 -1
  176. package/dist/providers/opencode-go.js +33 -15
  177. package/dist/providers/opencode-go.js.map +1 -1
  178. package/dist/providers/opencode-zen.d.ts.map +1 -1
  179. package/dist/providers/opencode-zen.js +27 -22
  180. package/dist/providers/opencode-zen.js.map +1 -1
  181. package/dist/providers/openrouter.d.ts +6 -0
  182. package/dist/providers/openrouter.d.ts.map +1 -0
  183. package/dist/providers/openrouter.js +25 -0
  184. package/dist/providers/openrouter.js.map +1 -0
  185. package/dist/providers/quota-providers.js +2 -1
  186. package/dist/providers/quota-providers.js.map +1 -1
  187. package/dist/providers/qwen-code.d.ts.map +1 -1
  188. package/dist/providers/qwen-code.js +19 -5
  189. package/dist/providers/qwen-code.js.map +1 -1
  190. package/dist/providers/registry.d.ts.map +1 -1
  191. package/dist/providers/registry.js +2 -0
  192. package/dist/providers/registry.js.map +1 -1
  193. package/dist/providers/result-helpers.d.ts +29 -1
  194. package/dist/providers/result-helpers.d.ts.map +1 -1
  195. package/dist/providers/result-helpers.js +69 -0
  196. package/dist/providers/result-helpers.js.map +1 -1
  197. package/dist/providers/synthetic.d.ts.map +1 -1
  198. package/dist/providers/synthetic.js +10 -3
  199. package/dist/providers/synthetic.js.map +1 -1
  200. package/dist/providers/zai.d.ts.map +1 -1
  201. package/dist/providers/zai.js +2 -1
  202. package/dist/providers/zai.js.map +1 -1
  203. package/dist/providers/zhipu.d.ts.map +1 -1
  204. package/dist/providers/zhipu.js +2 -1
  205. package/dist/providers/zhipu.js.map +1 -1
  206. package/dist/tui.d.ts.map +1 -1
  207. package/dist/tui.js +4 -0
  208. package/dist/tui.tsx +5 -0
  209. package/package.json +10 -2
@@ -1,54 +1,18 @@
1
- import { readFile, stat } from "fs/promises";
2
- import { getAuthPath, getAuthPaths, readAuthFileCached } from "./opencode-auth.js";
1
+ import { stat } from "fs/promises";
2
+ import { getAuthPath, getAuthPaths } from "./opencode-auth.js";
3
3
  import { getOpencodeRuntimeDirs } from "./opencode-runtime-paths.js";
4
- import { getGoogleTokenCachePath } from "./google-token-cache.js";
5
- import { inspectAntigravityCompanionPresence } from "./google-antigravity-companion.js";
6
- import { inspectGeminiCliCompanionPresence } from "./google-gemini-cli-companion.js";
7
- import { inspectGeminiCliAuthPresence } from "./google-gemini-cli.js";
8
- import { inspectAntigravityAccountsPresence } from "./google.js";
9
- import { inspectAgyCompanionPresence } from "./google-agy-companion.js";
10
- import { inspectAgyAuthPresence } from "./google-agy.js";
11
- import { getAnthropicDiagnostics } from "./anthropic.js";
12
- import { getChutesKeyDiagnostics } from "./chutes.js";
13
- import { getNanoGptKeyDiagnostics, queryNanoGptQuota } from "./nanogpt.js";
14
- import { getDeepSeekKeyDiagnostics } from "./deepseek.js";
15
- import { getSyntheticKeyDiagnostics } from "./synthetic.js";
16
- import { getCopilotQuotaAuthDiagnostics } from "./copilot.js";
17
- import { ALIBABA_CODING_PLAN_STATE_VERSION, QWEN_LOCAL_QUOTA_STATE_VERSION, getAlibabaCodingPlanQuotaPath, getQwenLocalQuotaPath, } from "./qwen-local-quota.js";
18
- import { DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS, getAlibabaCodingPlanAuthDiagnostics, resolveAlibabaCodingPlanAuthCached, } from "./alibaba-auth.js";
19
- import { hasQwenOAuthAuth, resolveQwenLocalPlan } from "./qwen-auth.js";
20
- import { resolveOpenAIOAuth } from "./openai.js";
21
- import { DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS, getMiniMaxAuthDiagnostics, getMiniMaxChinaAuthDiagnostics, resolveMiniMaxAuthCached, resolveMiniMaxChinaAuthCached, } from "./minimax-auth.js";
22
- import { getMiniMaxQuotaEndpoint } from "./minimax-endpoints.js";
23
- import { DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS, getZaiAuthDiagnostics } from "./zai-auth.js";
24
- import { DEFAULT_ZHIPU_AUTH_CACHE_MAX_AGE_MS, getZhipuAuthDiagnostics } from "./zhipu-auth.js";
25
- import { DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS, getKimiAuthDiagnostics, } from "./kimi-auth.js";
26
- import { queryKimiQuota } from "./kimi.js";
27
4
  import { getPricingSnapshotHealth, getPricingRefreshPolicy, getPricingSnapshotMeta, getPricingSnapshotSource, getRuntimePricingRefreshStatePath, getRuntimePricingSnapshotPath, listProviders, getProviderModelCount, hasProvider as snapshotHasProvider, readPricingRefreshState, } from "./modelsdev-pricing.js";
28
5
  import { getProviders } from "../providers/registry.js";
29
6
  import { getPackageVersion } from "./version.js";
30
7
  import { getOpenCodeDbPath, getOpenCodeDbPathCandidates, getOpenCodeDbStats, } from "./opencode-storage.js";
31
8
  import { aggregateUsage } from "./quota-stats.js";
32
- import { fmtUsdAmount } from "./format-utils.js";
33
9
  import { renderPlainTextReport } from "./report-document.js";
34
10
  import { totalTokenBuckets } from "./token-buckets.js";
35
- import { CURSOR_CANONICAL_PLUGIN_PACKAGE, inspectCursorAuthPresence, inspectCursorOpenCodeIntegration, } from "./cursor-detection.js";
36
- import { getCurrentCursorUsageSummary } from "./cursor-usage.js";
37
- import { sanitizeSingleLineDisplaySnippet, sanitizeSingleLineDisplayText, sanitizeDisplayText, sanitizeQuotaProviderResult, } from "./display-sanitize.js";
11
+ import { sanitizeSingleLineDisplaySnippet, sanitizeSingleLineDisplayText, sanitizeQuotaProviderResult, } from "./display-sanitize.js";
38
12
  import { QUOTA_TOAST_SETTING_SOURCE_KEYS, } from "./config.js";
39
- import { getCursorPlanDisplayName, getEffectiveCursorIncludedApiUsd } from "./cursor-pricing.js";
40
13
  import { getQuotaProviderDisplayLabel } from "./provider-metadata.js";
41
14
  import { isMaintainedQuotaProviderTuning } from "./quota-providers.js";
42
- import { inspectLocalQuotaProviderState } from "./quota-providers-local.js";
43
15
  import { isValueEntry } from "./entries.js";
44
- import { queryMiniMaxQuota } from "../providers/minimax-coding-plan.js";
45
- import { queryZaiQuota } from "./zai.js";
46
- import { queryZhipuQuota } from "./zhipu.js";
47
- import { getOpenCodeGoConfigDiagnostics, resolveOpenCodeGoConfigCached, DEFAULT_OPENCODE_GO_CONFIG_CACHE_MAX_AGE_MS, } from "./opencode-go-config.js";
48
- import { queryOpenCodeGoQuota } from "./opencode-go.js";
49
- import { DEFAULT_OPENCODE_ZEN_CONFIG_CACHE_MAX_AGE_MS, getOpenCodeZenConfigDiagnostics, resolveOpenCodeZenConfigCached, } from "./opencode-zen-config.js";
50
- import { OPENCODE_ZEN_BILLING_UNITS_PER_DOLLAR, queryOpenCodeZenQuota } from "./opencode-zen.js";
51
- import { getMimoConfigDiagnostics } from "./mimo-config.js";
52
16
  async function pathExists(path) {
53
17
  try {
54
18
  await stat(path);
@@ -58,37 +22,6 @@ async function pathExists(path) {
58
22
  return false;
59
23
  }
60
24
  }
61
- async function inspectGeneratedCounterFile(path, expectedVersion) {
62
- try {
63
- const parsed = JSON.parse(await readFile(path, "utf8"));
64
- const record = parsed && typeof parsed === "object" && !Array.isArray(parsed)
65
- ? parsed
66
- : null;
67
- const version = typeof record?.version === "number" ? record.version : null;
68
- const updatedAt = typeof record?.updatedAt === "number" && Number.isFinite(record.updatedAt)
69
- ? record.updatedAt
70
- : null;
71
- return {
72
- exists: true,
73
- health: !record || version === null || updatedAt === null
74
- ? "malformed"
75
- : version === expectedVersion
76
- ? "healthy"
77
- : "version_mismatch",
78
- version,
79
- lastUpdatedAt: updatedAt,
80
- };
81
- }
82
- catch (error) {
83
- if (error &&
84
- typeof error === "object" &&
85
- "code" in error &&
86
- String(error.code) === "ENOENT") {
87
- return { exists: false, health: "missing", version: null, lastUpdatedAt: null };
88
- }
89
- return { exists: true, health: "malformed", version: null, lastUpdatedAt: null };
90
- }
91
- }
92
25
  function fmtInt(n) {
93
26
  return Math.trunc(n).toLocaleString("en-US");
94
27
  }
@@ -96,31 +29,9 @@ const STATUS_SAMPLE_LIMIT = 5;
96
29
  const STATUS_LIVE_ENTRY_LIMIT = 2;
97
30
  const STATUS_LIVE_ERROR_LIMIT = 2;
98
31
  const STATUS_LIVE_ROW_MAX_LENGTH = 120;
99
- const OPENCODE_GO_STATUS_WINDOW_ORDER = ["rolling", "weekly", "monthly"];
100
- const OPENCODE_GO_STATUS_WINDOW_FIELDS = {
101
- rolling: "rollingUsage",
102
- weekly: "weeklyUsage",
103
- monthly: "monthlyUsage",
104
- };
105
32
  function joinOrNone(values) {
106
33
  return values.length > 0 ? values.join(" | ") : "(none)";
107
34
  }
108
- function formatOpenCodeGoWindowSelection(windows) {
109
- return windows.join(",");
110
- }
111
- function isDefaultOpenCodeGoStatusWindowSelection(windows) {
112
- const selected = new Set(windows);
113
- return (selected.size === OPENCODE_GO_STATUS_WINDOW_ORDER.length &&
114
- OPENCODE_GO_STATUS_WINDOW_ORDER.every((window) => selected.has(window)));
115
- }
116
- function formatOpenCodeGoMissingWindows(windows) {
117
- return windows
118
- .map((window) => `${window} (${OPENCODE_GO_STATUS_WINDOW_FIELDS[window]})`)
119
- .join(", ");
120
- }
121
- function formatOpenCodeGoUsage(window) {
122
- return `percent_used=${window.usagePercent} percent_remaining=${window.percentRemaining} reset_in_sec=${window.resetInSec} reset_at=${window.resetTimeIso}`;
123
- }
124
35
  function formatSettingSources(sources) {
125
36
  if (!sources)
126
37
  return "(none)";
@@ -139,24 +50,6 @@ function getConfigPrecedenceLabel(configSource) {
139
50
  return configSource;
140
51
  }
141
52
  }
142
- function getDefaultBasicApiKeyDiagnostics() {
143
- return {
144
- configured: false,
145
- source: null,
146
- checkedPaths: [],
147
- };
148
- }
149
- async function readBasicApiKeyDiagnostics(read) {
150
- try {
151
- return await read();
152
- }
153
- catch {
154
- return getDefaultBasicApiKeyDiagnostics();
155
- }
156
- }
157
- function formatInlineApiKeyDiagnosticsValue(diagnostics) {
158
- return `configured=${diagnostics.configured ? "true" : "false"}${diagnostics.source ? ` source=${diagnostics.source}` : ""}${diagnostics.checkedPaths.length > 0 ? ` checked=${diagnostics.checkedPaths.join(" | ")}` : ""}`;
159
- }
160
53
  function createKvSection(id, title, rows) {
161
54
  return {
162
55
  id,
@@ -186,6 +79,20 @@ function isRedundantLiveProbeDescriptor(providerId, value) {
186
79
  function findProviderLiveProbe(providerId, probes) {
187
80
  return probes?.find((probe) => probe.providerId === providerId);
188
81
  }
82
+ function getProviderStatusDetails(providerId, probes) {
83
+ const probe = findProviderLiveProbe(providerId, probes);
84
+ return probe ? sanitizeQuotaProviderResult(probe.result).statusDetails : undefined;
85
+ }
86
+ function appendProviderStatusDetailRows(rows, providerId, probes, keys) {
87
+ for (const detail of getProviderStatusDetails(providerId, probes) ?? []) {
88
+ if (!keys || keys.has(detail.key)) {
89
+ rows.push({ key: detail.key, value: detail.value });
90
+ }
91
+ }
92
+ }
93
+ function findProviderStatusDetail(providerId, key, probes) {
94
+ return getProviderStatusDetails(providerId, probes)?.find((detail) => detail.key === key)?.value;
95
+ }
189
96
  function getLiveProbeState(probe) {
190
97
  if (!probe)
191
98
  return "unavailable";
@@ -197,10 +104,16 @@ function getLiveProbeState(probe) {
197
104
  return "error";
198
105
  return "no_data";
199
106
  }
200
- function appendProviderCompactLiveProbeRows(rows, providerId, probes) {
107
+ function appendProviderCompactLiveProbeRows(rows, providerId, probes, availability) {
108
+ const provider = availability.find((item) => item.id === providerId);
109
+ if (!provider?.enabled || !provider.available)
110
+ return;
201
111
  appendCompactLiveProbeRows(rows, providerId, findProviderLiveProbe(providerId, probes));
202
112
  }
203
113
  function createCompactLiveProbeOnlySection(params) {
114
+ const provider = params.availability.find((item) => item.id === params.providerId);
115
+ if (!provider?.enabled || !provider.available)
116
+ return null;
204
117
  const probe = findProviderLiveProbe(params.providerId, params.probes);
205
118
  if (!probe) {
206
119
  return null;
@@ -209,6 +122,14 @@ function createCompactLiveProbeOnlySection(params) {
209
122
  appendCompactLiveProbeRows(rows, params.providerId, probe);
210
123
  return createKvSection(params.id, params.title, rows);
211
124
  }
125
+ function createProviderStatusSection(params) {
126
+ const rows = [];
127
+ if (params.includeDetails !== false) {
128
+ appendProviderStatusDetailRows(rows, params.providerId, params.probes);
129
+ }
130
+ appendProviderCompactLiveProbeRows(rows, params.providerId, params.probes, params.availability);
131
+ return createKvSection(params.id, params.title, rows);
132
+ }
212
133
  function getCompactLiveProbeDescriptor(providerId, entry) {
213
134
  const candidates = [entry.label, entry.name, entry.group];
214
135
  for (const candidate of candidates) {
@@ -265,7 +186,7 @@ function getQuotaProviderCredentialCategory(source) {
265
186
  return "none";
266
187
  }
267
188
  }
268
- async function createQuotaProvidersSection(params) {
189
+ function createQuotaProvidersSection(params) {
269
190
  if (params.definitions.length === 0)
270
191
  return null;
271
192
  const diagnostics = findProviderLiveProbe("quota-providers", params.probes)?.result.diagnostics ?? [];
@@ -275,17 +196,12 @@ async function createQuotaProvidersSection(params) {
275
196
  const diagnostic = diagnosticsBySource.get(definition.id);
276
197
  const coverage = definition.modelIds ? definition.modelIds.join(",") : "all_models";
277
198
  if (definition.mode === "local-estimate" && isMaintainedQuotaProviderTuning(definition)) {
278
- const maintained = definition.id === "qwen-code"
279
- ? {
280
- path: getQwenLocalQuotaPath(),
281
- version: QWEN_LOCAL_QUOTA_STATE_VERSION,
282
- }
283
- : {
284
- path: getAlibabaCodingPlanQuotaPath(),
285
- version: ALIBABA_CODING_PLAN_STATE_VERSION,
286
- };
287
- const state = await inspectGeneratedCounterFile(maintained.path, maintained.version);
288
199
  const probe = findProviderLiveProbe(definition.id, params.probes);
200
+ const statePath = findProviderStatusDetail(definition.id, "local_state_path", params.probes);
201
+ const stateExists = findProviderStatusDetail(definition.id, "local_state_exists", params.probes);
202
+ const stateHealth = findProviderStatusDetail(definition.id, "local_state_health", params.probes);
203
+ const stateVersion = findProviderStatusDetail(definition.id, "local_state_version", params.probes);
204
+ const stateLastUpdate = findProviderStatusDetail(definition.id, "local_state_last_update", params.probes);
289
205
  rows.push({
290
206
  key: `provider_${definition.id}`,
291
207
  value: [
@@ -294,11 +210,11 @@ async function createQuotaProvidersSection(params) {
294
210
  `coverage=${coverage}`,
295
211
  `outcome=${getLiveProbeState(probe)}`,
296
212
  `limits=${definition.windows.map((window) => `${window.id}:${window.requestLimit}`).join(",")}`,
297
- `state_path=${maintained.path}`,
298
- `state_exists=${state.exists ? "true" : "false"}`,
299
- `state_health=${state.health}`,
300
- `state_version=${state.version ?? "(none)"}`,
301
- `state_last_update=${state.lastUpdatedAt === null ? "(none)" : new Date(state.lastUpdatedAt).toISOString()}`,
213
+ `state_path=${statePath ?? "(none)"}`,
214
+ `state_exists=${stateExists ?? "false"}`,
215
+ `state_health=${stateHealth ?? "missing"}`,
216
+ `state_version=${stateVersion ?? "(none)"}`,
217
+ `state_last_update=${stateLastUpdate ?? "(none)"}`,
302
218
  ]
303
219
  .map((part) => sanitizeSingleLineDisplayText(part))
304
220
  .join(" "),
@@ -306,7 +222,7 @@ async function createQuotaProvidersSection(params) {
306
222
  continue;
307
223
  }
308
224
  if (definition.mode === "local-estimate") {
309
- const state = await inspectLocalQuotaProviderState(definition);
225
+ const stateHealth = diagnostic?.stateHealth ?? "missing";
310
226
  rows.push({
311
227
  key: `provider_${definition.id}`,
312
228
  value: [
@@ -314,11 +230,11 @@ async function createQuotaProvidersSection(params) {
314
230
  "mode=local-estimate",
315
231
  `coverage=${coverage}`,
316
232
  `outcome=${diagnostic?.outcome ?? "unavailable"}`,
317
- `state_path=${state.path}`,
318
- `state_exists=${state.exists ? "true" : "false"}`,
319
- `state_health=${state.health}`,
320
- `state_version=${state.version ?? "(none)"}`,
321
- `state_last_update=${state.lastUpdatedAt === null ? "(none)" : new Date(state.lastUpdatedAt).toISOString()}`,
233
+ `state_path=${diagnostic?.statePath ?? "(none)"}`,
234
+ `state_exists=${diagnostic?.statePath && stateHealth !== "missing" ? "true" : "false"}`,
235
+ `state_health=${stateHealth}`,
236
+ `state_version=${diagnostic?.stateVersion ?? "(none)"}`,
237
+ `state_last_update=${diagnostic?.stateLastUpdatedAt == null ? "(none)" : new Date(diagnostic.stateLastUpdatedAt).toISOString()}`,
322
238
  ]
323
239
  .map((part) => sanitizeSingleLineDisplayText(part))
324
240
  .join(" "),
@@ -381,27 +297,6 @@ function appendCompactLiveProbeRows(rows, providerId, probe) {
381
297
  });
382
298
  }
383
299
  }
384
- function getDefaultApiKeyDiagnosticsWithAuthPaths() {
385
- return {
386
- ...getDefaultBasicApiKeyDiagnostics(),
387
- authPaths: [],
388
- };
389
- }
390
- async function readApiKeyDiagnosticsWithAuthPaths(read) {
391
- try {
392
- return await read();
393
- }
394
- catch {
395
- return getDefaultApiKeyDiagnosticsWithAuthPaths();
396
- }
397
- }
398
- function fmtNanoGptMetric(value) {
399
- if (!Number.isFinite(value))
400
- return "0";
401
- if (Number.isInteger(value))
402
- return String(Math.trunc(value));
403
- return value.toFixed(2).replace(/\.?0+$/, "");
404
- }
405
300
  function computePricingCoverageFromAgg(agg) {
406
301
  const byProvider = new Map();
407
302
  let pricedKeysSeen = 0;
@@ -609,7 +504,7 @@ export async function buildQuotaStatusReport(params) {
609
504
  toastLines.push(` - ${p.id}: ${bits.join(" ")}`);
610
505
  }
611
506
  sections.push(createLinesSection("toast", "toast:", toastLines));
612
- const quotaProvidersSection = await createQuotaProvidersSection({
507
+ const quotaProvidersSection = createQuotaProvidersSection({
613
508
  definitions: params.quotaProviders ?? [],
614
509
  probes: params.providerLiveProbes,
615
510
  });
@@ -651,247 +546,41 @@ export async function buildQuotaStatusReport(params) {
651
546
  key: "auth.json",
652
547
  value: `preferred=${getAuthPath()} present=${joinOrNone(authPresent)} candidates=${joinOrNone(authCandidates)}`,
653
548
  });
654
- const authData = await readAuthFileCached({ maxAgeMs: 5_000 });
655
- const qwenAuthConfigured = hasQwenOAuthAuth(authData);
656
- const qwenLocalPlan = resolveQwenLocalPlan(authData);
657
- const openaiAuth = resolveOpenAIOAuth(authData);
658
- const alibabaAuthDiagnostics = await getAlibabaCodingPlanAuthDiagnostics({
659
- maxAgeMs: DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS,
660
- fallbackTier: "lite",
661
- });
662
- const alibabaCodingPlanAuth = await resolveAlibabaCodingPlanAuthCached({
663
- maxAgeMs: DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS,
664
- fallbackTier: "lite",
665
- });
666
- pathsRows.push({
667
- key: "qwen oauth auth configured",
668
- value: qwenAuthConfigured ? "true" : "false",
669
- });
670
- pathsRows.push({
671
- key: "qwen_oauth_source",
672
- value: qwenLocalPlan.state === "qwen_free" ? qwenLocalPlan.sourceKey : "(none)",
673
- });
674
- pathsRows.push({
675
- key: "qwen_local_plan",
676
- value: qwenLocalPlan.state === "qwen_free" ? "qwen-code/free" : "(none)",
677
- });
678
- pathsRows.push({
679
- key: "alibaba auth configured",
680
- value: alibabaAuthDiagnostics.state === "none" ? "false" : "true",
681
- });
682
- pathsRows.push({
683
- key: "alibaba_api_key_source",
684
- value: alibabaAuthDiagnostics.source ?? "(none)",
685
- });
686
- pathsRows.push({
687
- key: "alibaba_api_key_checked_paths",
688
- value: joinOrNone(alibabaAuthDiagnostics.checkedPaths),
689
- });
690
- pathsRows.push({
691
- key: "alibaba_api_key_auth_paths",
692
- value: joinOrNone(alibabaAuthDiagnostics.authPaths),
693
- });
694
- pathsRows.push({
695
- key: "alibaba_coding_plan",
696
- value: alibabaAuthDiagnostics.state === "configured"
697
- ? alibabaAuthDiagnostics.tier
698
- : alibabaAuthDiagnostics.state === "invalid"
699
- ? "invalid"
700
- : "(none)",
701
- });
702
- if (alibabaAuthDiagnostics.state === "invalid") {
703
- pathsRows.push({
704
- key: "alibaba_auth_error",
705
- value: sanitizeDisplayText(alibabaAuthDiagnostics.error),
706
- });
707
- }
549
+ appendProviderStatusDetailRows(pathsRows, "qwen-code", params.providerLiveProbes, new Set(["qwen oauth auth configured", "qwen_oauth_source", "qwen_local_plan"]));
550
+ appendProviderStatusDetailRows(pathsRows, "alibaba-coding-plan", params.providerLiveProbes, new Set([
551
+ "alibaba auth configured",
552
+ "alibaba_api_key_source",
553
+ "alibaba_api_key_checked_paths",
554
+ "alibaba_api_key_auth_paths",
555
+ "alibaba_coding_plan",
556
+ "alibaba_auth_error",
557
+ ]));
708
558
  sections.push(createKvSection("paths", "paths:", pathsRows));
709
- // === openai ===
710
- const openaiRows = [
711
- { key: "auth_configured", value: openaiAuth.state === "configured" ? "true" : "false" },
712
- {
713
- key: "auth_source",
714
- value: openaiAuth.state === "configured" ? openaiAuth.sourceKey : "(none)",
715
- },
716
- ];
717
- const openaiTokenStatus = openaiAuth.state !== "configured"
718
- ? "(none)"
719
- : openaiAuth.expiresAt && openaiAuth.expiresAt < Date.now()
720
- ? "expired"
721
- : "valid";
722
- openaiRows.push({ key: "token_status", value: openaiTokenStatus });
723
- openaiRows.push({
724
- key: "token_expires_at",
725
- value: openaiAuth.state === "configured" && openaiAuth.expiresAt
726
- ? new Date(openaiAuth.expiresAt).toISOString()
727
- : "(none)",
728
- });
729
- openaiRows.push({
730
- key: "account_email",
731
- value: openaiAuth.state === "configured" && openaiAuth.email
732
- ? sanitizeDisplayText(openaiAuth.email)
733
- : "(none)",
734
- });
735
- openaiRows.push({
736
- key: "account_id",
737
- value: openaiAuth.state === "configured" && openaiAuth.accountId
738
- ? sanitizeDisplayText(openaiAuth.accountId)
739
- : "(none)",
740
- });
741
- appendProviderCompactLiveProbeRows(openaiRows, "openai", params.providerLiveProbes);
742
- sections.push(createKvSection("openai", "openai:", openaiRows));
743
- // === anthropic ===
744
- const anthropicRows = [];
745
- try {
746
- const anthropicDiagnostics = await getAnthropicDiagnostics({
747
- binaryPath: params.anthropicBinaryPath,
748
- });
749
- anthropicRows.push({
750
- key: "cli_installed",
751
- value: anthropicDiagnostics.installed ? "true" : "false",
752
- });
753
- anthropicRows.push({ key: "cli_version", value: anthropicDiagnostics.version ?? "(none)" });
754
- anthropicRows.push({ key: "auth_status", value: anthropicDiagnostics.authStatus });
755
- anthropicRows.push({
756
- key: "quota_supported",
757
- value: anthropicDiagnostics.quotaSupported ? "true" : "false",
758
- });
759
- anthropicRows.push({
760
- key: "quota_source",
761
- value: anthropicDiagnostics.quotaSource === "none" ? "(none)" : anthropicDiagnostics.quotaSource,
762
- });
763
- anthropicRows.push({
764
- key: "checked_commands",
765
- value: anthropicDiagnostics.checkedCommands.length > 0
766
- ? anthropicDiagnostics.checkedCommands.join(" | ")
767
- : "(none)",
768
- });
769
- if (anthropicDiagnostics.message) {
770
- anthropicRows.push({ key: "message", value: anthropicDiagnostics.message });
771
- }
772
- if (anthropicDiagnostics.quotaSupported && anthropicDiagnostics.quota) {
773
- anthropicRows.push({
774
- key: "five_hour_remaining",
775
- value: `${anthropicDiagnostics.quota.five_hour.percentRemaining}% reset_at=${anthropicDiagnostics.quota.five_hour.resetTimeIso ?? "(none)"}`,
776
- });
777
- anthropicRows.push({
778
- key: "seven_day_remaining",
779
- value: `${anthropicDiagnostics.quota.seven_day.percentRemaining}% reset_at=${anthropicDiagnostics.quota.seven_day.resetTimeIso ?? "(none)"}`,
780
- });
781
- }
782
- }
783
- catch (err) {
784
- anthropicRows.push({ key: "cli_installed", value: "false" });
785
- anthropicRows.push({
786
- key: "message",
787
- value: `failed to probe Claude CLI${err ? `: ${sanitizeDisplayText(err instanceof Error ? err.message : String(err))}` : ""}`,
788
- });
559
+ for (const [id, providerId] of [
560
+ ["openai", "openai"],
561
+ ["anthropic", "anthropic"],
562
+ ]) {
563
+ sections.push(createProviderStatusSection({
564
+ id,
565
+ title: `${id}:`,
566
+ providerId,
567
+ probes: params.providerLiveProbes,
568
+ availability: params.providerAvailability,
569
+ }));
789
570
  }
790
- appendProviderCompactLiveProbeRows(anthropicRows, "anthropic", params.providerLiveProbes);
791
- sections.push(createKvSection("anthropic", "anthropic:", anthropicRows));
792
571
  // === cursor ===
793
- const cursorPlanLabel = getCursorPlanDisplayName(params.cursorPlan);
794
- const cursorIncludedApiUsd = getEffectiveCursorIncludedApiUsd({
795
- plan: params.cursorPlan,
796
- overrideUsd: params.cursorIncludedApiUsd,
797
- });
798
- const cursorAuth = await inspectCursorAuthPresence();
799
- const cursorIntegration = await inspectCursorOpenCodeIntegration();
800
- const cursorRows = [
801
- { key: "plan", value: cursorPlanLabel ?? "none" },
802
- {
803
- key: "included_api_usd",
804
- value: typeof cursorIncludedApiUsd === "number" ? fmtUsdAmount(cursorIncludedApiUsd) : "(none)",
805
- },
806
- {
807
- key: "billing_cycle_start_day",
808
- value: typeof params.cursorBillingCycleStartDay === "number"
809
- ? String(params.cursorBillingCycleStartDay)
810
- : "(calendar month)",
811
- },
812
- { key: "auth_state", value: cursorAuth.state },
813
- { key: "auth_selected_path", value: cursorAuth.selectedPath ?? "(none)" },
814
- { key: "auth_present_paths", value: joinOrNone(cursorAuth.presentPaths) },
815
- { key: "auth_candidate_paths", value: joinOrNone(cursorAuth.candidatePaths) },
816
- ];
817
- if (cursorAuth.error) {
818
- cursorRows.push({ key: "auth_error", value: cursorAuth.error });
819
- }
820
- cursorRows.push({
821
- key: "plugin_enabled",
822
- value: cursorIntegration.pluginEnabled ? "true" : "false",
823
- });
824
- cursorRows.push({ key: "canonical_plugin_package", value: CURSOR_CANONICAL_PLUGIN_PACKAGE });
825
- cursorRows.push({
826
- key: "provider_configured",
827
- value: cursorIntegration.providerConfigured ? "true" : "false",
828
- });
829
- cursorRows.push({ key: "config_matches", value: joinOrNone(cursorIntegration.matchedPaths) });
830
- cursorRows.push({
831
- key: "config_checked_paths",
832
- value: joinOrNone(cursorIntegration.checkedPaths),
833
- });
834
- try {
835
- const cursorUsage = await getCurrentCursorUsageSummary({
836
- billingCycleStartDay: params.cursorBillingCycleStartDay,
837
- });
838
- cursorRows.push({ key: "cycle_source", value: cursorUsage.window.source });
839
- cursorRows.push({ key: "cycle_reset_at", value: cursorUsage.window.resetTimeIso });
840
- cursorRows.push({
841
- key: "api_usage",
842
- value: `${fmtUsdAmount(cursorUsage.api.costUsd)} across ${fmtInt(cursorUsage.api.messageCount)} messages`,
843
- });
844
- cursorRows.push({
845
- key: "auto_composer_usage",
846
- value: `${fmtUsdAmount(cursorUsage.autoComposer.costUsd)} across ${fmtInt(cursorUsage.autoComposer.messageCount)} messages`,
847
- });
848
- cursorRows.push({
849
- key: "total_cursor_usage",
850
- value: `${fmtUsdAmount(cursorUsage.total.costUsd)} across ${fmtInt(cursorUsage.total.messageCount)} messages`,
851
- });
852
- cursorRows.push({
853
- key: "unknown_cursor_models",
854
- value: fmtInt(cursorUsage.unknownModels.length),
855
- });
856
- }
857
- catch (err) {
858
- const msg = err instanceof Error ? err.message : String(err);
859
- cursorRows.push({ key: "usage_error", value: msg });
860
- }
861
- const qwenLocalQuotaPath = getQwenLocalQuotaPath();
862
- const qwenCounter = await inspectGeneratedCounterFile(qwenLocalQuotaPath, QWEN_LOCAL_QUOTA_STATE_VERSION);
863
- cursorRows.push({
864
- key: "qwen free local quota",
865
- value: [
866
- `path=${qwenLocalQuotaPath}`,
867
- `exists=${qwenCounter.exists ? "true" : "false"}`,
868
- `health=${qwenCounter.health}`,
869
- `version=${qwenCounter.version ?? "(none)"}`,
870
- `last_update=${qwenCounter.lastUpdatedAt === null ? "(none)" : new Date(qwenCounter.lastUpdatedAt).toISOString()}`,
871
- ].join(" "),
872
- });
873
- const alibabaLocalQuotaPath = getAlibabaCodingPlanQuotaPath();
874
- const alibabaCounter = await inspectGeneratedCounterFile(alibabaLocalQuotaPath, ALIBABA_CODING_PLAN_STATE_VERSION);
875
- cursorRows.push({
876
- key: "alibaba coding plan local quota",
877
- value: [
878
- `path=${alibabaLocalQuotaPath}`,
879
- `exists=${alibabaCounter.exists ? "true" : "false"}`,
880
- `health=${alibabaCounter.health}`,
881
- `version=${alibabaCounter.version ?? "(none)"}`,
882
- `last_update=${alibabaCounter.lastUpdatedAt === null ? "(none)" : new Date(alibabaCounter.lastUpdatedAt).toISOString()}`,
883
- ].join(" "),
884
- });
885
- if (alibabaCodingPlanAuth.state === "invalid") {
886
- cursorRows.push({ key: "alibaba coding plan error", value: alibabaCodingPlanAuth.error });
887
- }
888
- appendProviderCompactLiveProbeRows(cursorRows, "cursor", params.providerLiveProbes);
572
+ const cursorRows = [];
573
+ appendProviderStatusDetailRows(cursorRows, "cursor", params.providerLiveProbes);
574
+ appendProviderStatusDetailRows(cursorRows, "qwen-code", params.providerLiveProbes, new Set(["qwen free local quota"]));
575
+ appendProviderStatusDetailRows(cursorRows, "alibaba-coding-plan", params.providerLiveProbes, new Set(["alibaba coding plan local quota", "alibaba coding plan error"]));
576
+ appendProviderCompactLiveProbeRows(cursorRows, "cursor", params.providerLiveProbes, params.providerAvailability);
889
577
  sections.push(createKvSection("cursor", "cursor:", cursorRows));
890
578
  const qwenCodeLiveProbeSection = createCompactLiveProbeOnlySection({
891
579
  id: "qwen_code",
892
580
  title: "qwen_code:",
893
581
  providerId: "qwen-code",
894
582
  probes: params.providerLiveProbes,
583
+ availability: params.providerAvailability,
895
584
  });
896
585
  if (qwenCodeLiveProbeSection) {
897
586
  sections.push(qwenCodeLiveProbeSection);
@@ -901,579 +590,42 @@ export async function buildQuotaStatusReport(params) {
901
590
  title: "alibaba_coding_plan:",
902
591
  providerId: "alibaba-coding-plan",
903
592
  probes: params.providerLiveProbes,
593
+ availability: params.providerAvailability,
904
594
  });
905
595
  if (alibabaCodingPlanLiveProbeSection) {
906
596
  sections.push(alibabaCodingPlanLiveProbeSection);
907
597
  }
908
- async function appendMiniMaxSection(section) {
909
- const minimaxRows = [];
910
- const minimaxAuth = await section.getDiagnostics({
911
- maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
912
- });
913
- minimaxRows.push({ key: "auth_state", value: minimaxAuth.state });
914
- minimaxRows.push({
915
- key: "api_key_configured",
916
- value: minimaxAuth.state === "configured" ? "true" : "false",
917
- });
918
- minimaxRows.push({ key: "api_key_source", value: minimaxAuth.source ?? "(none)" });
919
- if (minimaxAuth.state === "configured") {
920
- const endpoint = getMiniMaxQuotaEndpoint(minimaxAuth.endpoint);
921
- minimaxRows.push({ key: "api_endpoint", value: endpoint.id });
922
- minimaxRows.push({ key: "api_base_url", value: endpoint.apiBaseUrl });
923
- }
924
- minimaxRows.push({ key: "api_key_checked_paths", value: joinOrNone(minimaxAuth.checkedPaths) });
925
- minimaxRows.push({ key: "api_key_auth_paths", value: joinOrNone(minimaxAuth.authPaths) });
926
- if (minimaxAuth.state === "invalid") {
927
- minimaxRows.push({ key: "auth_error", value: sanitizeDisplayText(minimaxAuth.error) });
928
- }
929
- if (minimaxAuth.state === "configured") {
930
- const resolvedMiniMaxAuth = await section.resolveAuth({
931
- maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
932
- });
933
- if (resolvedMiniMaxAuth.state !== "configured") {
934
- minimaxRows.push({
935
- key: "live_fetch_error",
936
- value: `${section.label} API key became unavailable before fetch`,
937
- });
938
- }
939
- else {
940
- const minimaxQuota = await queryMiniMaxQuota(resolvedMiniMaxAuth.apiKey, {
941
- endpoint: resolvedMiniMaxAuth.endpoint,
942
- label: section.label,
943
- });
944
- if (!minimaxQuota.success) {
945
- minimaxRows.push({ key: "live_fetch_error", value: minimaxQuota.error });
946
- }
947
- else {
948
- const fiveHourEntry = minimaxQuota.entries.find((entry) => entry.window === "five_hour");
949
- const weeklyEntry = minimaxQuota.entries.find((entry) => entry.window === "weekly");
950
- if (fiveHourEntry) {
951
- minimaxRows.push({
952
- key: "five_hour_usage",
953
- value: `${fiveHourEntry.right ?? "(none)"} percent_remaining=${fiveHourEntry.percentRemaining} reset_at=${fiveHourEntry.resetTimeIso ?? "(none)"}`,
954
- });
955
- }
956
- if (weeklyEntry) {
957
- minimaxRows.push({
958
- key: "weekly_usage",
959
- value: `${weeklyEntry.right ?? "(none)"} percent_remaining=${weeklyEntry.percentRemaining} reset_at=${weeklyEntry.resetTimeIso ?? "(none)"}`,
960
- });
961
- }
962
- if (!fiveHourEntry && !weeklyEntry) {
963
- minimaxRows.push({ key: "live_state", value: `no reportable ${section.label} quota` });
964
- }
965
- }
966
- }
967
- }
968
- appendProviderCompactLiveProbeRows(minimaxRows, section.providerId, params.providerLiveProbes);
969
- sections.push(createKvSection(section.id, section.title, minimaxRows));
970
- }
971
- // === minimax ===
972
- await appendMiniMaxSection({
973
- id: "minimax",
974
- title: "minimax:",
975
- providerId: "minimax-coding-plan",
976
- label: "MiniMax Coding Plan",
977
- getDiagnostics: getMiniMaxAuthDiagnostics,
978
- resolveAuth: resolveMiniMaxAuthCached,
979
- });
980
- await appendMiniMaxSection({
981
- id: "minimax_china",
982
- title: "minimax_china:",
983
- providerId: "minimax-china-coding-plan",
984
- label: "MiniMax Coding Plan (CN)",
985
- getDiagnostics: getMiniMaxChinaAuthDiagnostics,
986
- resolveAuth: resolveMiniMaxChinaAuthCached,
987
- });
988
- // === kimi ===
989
- const kimiRows = [];
990
- const kimiAuth = await getKimiAuthDiagnostics({
991
- maxAgeMs: DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS,
992
- });
993
- kimiRows.push({ key: "auth_state", value: kimiAuth.state });
994
- kimiRows.push({
995
- key: "api_key_configured",
996
- value: kimiAuth.state === "configured" ? "true" : "false",
997
- });
998
- kimiRows.push({ key: "api_key_source", value: kimiAuth.source ?? "(none)" });
999
- kimiRows.push({ key: "api_key_checked_paths", value: joinOrNone(kimiAuth.checkedPaths) });
1000
- kimiRows.push({ key: "api_key_auth_paths", value: joinOrNone(kimiAuth.authPaths) });
1001
- if (kimiAuth.state === "invalid") {
1002
- kimiRows.push({ key: "auth_error", value: sanitizeDisplayText(kimiAuth.error) });
1003
- }
1004
- if (kimiAuth.state === "configured") {
1005
- const kimiQuota = await queryKimiQuota();
1006
- if (!kimiQuota) {
1007
- kimiRows.push({
1008
- key: "live_fetch_error",
1009
- value: "Kimi API key became unavailable before fetch",
1010
- });
1011
- }
1012
- else if (!kimiQuota.success) {
1013
- kimiRows.push({ key: "live_fetch_error", value: kimiQuota.error });
1014
- }
1015
- else {
1016
- for (const window of kimiQuota.windows) {
1017
- kimiRows.push({
1018
- key: window.label.toLowerCase().replace(/\s+/g, "_"),
1019
- value: `used=${window.used}/${window.limit} percent_remaining=${window.percentRemaining} reset_at=${window.resetTimeIso ?? "(none)"}`,
1020
- });
1021
- }
1022
- if (kimiQuota.windows.length === 0) {
1023
- kimiRows.push({ key: "live_state", value: "no reportable Kimi quota" });
1024
- }
1025
- }
1026
- }
1027
- appendProviderCompactLiveProbeRows(kimiRows, "kimi-for-coding", params.providerLiveProbes);
1028
- sections.push(createKvSection("kimi", "kimi:", kimiRows));
1029
- // === opencode_go ===
1030
- const openCodeGoRows = [];
1031
- const openCodeGoDiag = await getOpenCodeGoConfigDiagnostics();
1032
- openCodeGoRows.push({ key: "config_state", value: openCodeGoDiag.state });
1033
- openCodeGoRows.push({ key: "config_source", value: openCodeGoDiag.source ?? "(none)" });
1034
- if (openCodeGoDiag.missing) {
1035
- openCodeGoRows.push({ key: "config_missing", value: openCodeGoDiag.missing });
1036
- }
1037
- if (openCodeGoDiag.error) {
1038
- openCodeGoRows.push({ key: "config_error", value: sanitizeDisplayText(openCodeGoDiag.error) });
1039
- }
1040
- openCodeGoRows.push({
1041
- key: "config_checked_paths",
1042
- value: joinOrNone(openCodeGoDiag.checkedPaths),
1043
- });
1044
- const openCodeGoSelectedWindows = params.opencodeGoWindows ?? OPENCODE_GO_STATUS_WINDOW_ORDER;
1045
- openCodeGoRows.push({
1046
- key: "selected_windows",
1047
- value: formatOpenCodeGoWindowSelection(openCodeGoSelectedWindows),
1048
- });
1049
- if (openCodeGoDiag.state === "configured") {
1050
- const openCodeGoConfig = await resolveOpenCodeGoConfigCached({
1051
- maxAgeMs: DEFAULT_OPENCODE_GO_CONFIG_CACHE_MAX_AGE_MS,
1052
- });
1053
- if (openCodeGoConfig.state !== "configured") {
1054
- openCodeGoRows.push({
1055
- key: "live_fetch_error",
1056
- value: "OpenCode Go config became unavailable before fetch",
1057
- });
1058
- }
1059
- else {
1060
- const openCodeGoQuota = await queryOpenCodeGoQuota(openCodeGoConfig.config.workspaceId, openCodeGoConfig.config.authCookie);
1061
- if (!openCodeGoQuota) {
1062
- openCodeGoRows.push({ key: "live_fetch_error", value: "OpenCode Go returned null" });
1063
- }
1064
- else if (!openCodeGoQuota.success) {
1065
- openCodeGoRows.push({ key: "live_fetch_error", value: openCodeGoQuota.error });
1066
- }
1067
- else {
1068
- for (const window of OPENCODE_GO_STATUS_WINDOW_ORDER) {
1069
- const usage = openCodeGoQuota[window];
1070
- if (!usage)
1071
- continue;
1072
- openCodeGoRows.push({
1073
- key: `${window}_usage`,
1074
- value: formatOpenCodeGoUsage(usage),
1075
- });
1076
- }
1077
- const missingSelectedWindows = openCodeGoSelectedWindows.filter((window) => !openCodeGoQuota[window]);
1078
- if (missingSelectedWindows.length > 0 &&
1079
- !isDefaultOpenCodeGoStatusWindowSelection(openCodeGoSelectedWindows)) {
1080
- openCodeGoRows.push({
1081
- key: "live_fetch_error",
1082
- value: `Selected OpenCode Go dashboard window(s) missing: ${formatOpenCodeGoMissingWindows(missingSelectedWindows)}`,
1083
- });
1084
- }
1085
- }
1086
- }
1087
- }
1088
- appendProviderCompactLiveProbeRows(openCodeGoRows, "opencode-go", params.providerLiveProbes);
1089
- sections.push(createKvSection("opencode_go", "opencode_go:", openCodeGoRows));
1090
- // === opencode_zen ===
1091
- const openCodeZenRows = [];
1092
- const openCodeZenDiag = await getOpenCodeZenConfigDiagnostics();
1093
- openCodeZenRows.push({ key: "config_state", value: openCodeZenDiag.state });
1094
- openCodeZenRows.push({ key: "config_source", value: openCodeZenDiag.source ?? "(none)" });
1095
- if (openCodeZenDiag.missing) {
1096
- openCodeZenRows.push({ key: "config_missing", value: openCodeZenDiag.missing });
1097
- }
1098
- if (openCodeZenDiag.error) {
1099
- openCodeZenRows.push({
1100
- key: "config_error",
1101
- value: sanitizeDisplayText(openCodeZenDiag.error),
1102
- });
1103
- }
1104
- openCodeZenRows.push({
1105
- key: "config_checked_paths",
1106
- value: joinOrNone(openCodeZenDiag.checkedPaths),
1107
- });
1108
- const openCodeZenLiveProbe = findProviderLiveProbe("opencode", params.providerLiveProbes);
1109
- if (openCodeZenLiveProbe?.result.statusDetails) {
1110
- openCodeZenRows.push(...openCodeZenLiveProbe.result.statusDetails.map((detail) => ({
1111
- key: detail.key,
1112
- value: detail.value,
1113
- })));
1114
- }
1115
- const openCodeZenIsInScope = params.providerAvailability === undefined ||
1116
- params.providerAvailability.some((provider) => provider.id === "opencode" && provider.enabled && provider.available);
1117
- if (openCodeZenDiag.state === "configured" && !openCodeZenLiveProbe && openCodeZenIsInScope) {
1118
- const openCodeZenConfig = await resolveOpenCodeZenConfigCached({
1119
- maxAgeMs: DEFAULT_OPENCODE_ZEN_CONFIG_CACHE_MAX_AGE_MS,
1120
- });
1121
- if (openCodeZenConfig.state !== "configured") {
1122
- openCodeZenRows.push({
1123
- key: "live_fetch_error",
1124
- value: "OpenCode Zen config became unavailable before fetch",
1125
- });
1126
- }
1127
- else {
1128
- const openCodeZenQuota = await queryOpenCodeZenQuota(openCodeZenConfig.config.workspaceId, openCodeZenConfig.config.authCookie);
1129
- if (!openCodeZenQuota.success) {
1130
- openCodeZenRows.push({ key: "live_fetch_error", value: openCodeZenQuota.error });
1131
- }
1132
- else {
1133
- const data = openCodeZenQuota.data;
1134
- openCodeZenRows.push({
1135
- key: "balance_usd",
1136
- value: `$${(data.balance / OPENCODE_ZEN_BILLING_UNITS_PER_DOLLAR).toFixed(2)}`,
1137
- });
1138
- openCodeZenRows.push({
1139
- key: "monthly_limit_usd",
1140
- value: data.monthlyLimit === null ? "(none)" : `$${data.monthlyLimit.toFixed(2)}`,
1141
- });
1142
- openCodeZenRows.push({
1143
- key: "last_payment_usd",
1144
- value: data.lastPayment === null ? "(none)" : `$${data.lastPayment.toFixed(2)}`,
1145
- });
1146
- }
1147
- }
1148
- }
1149
- appendProviderCompactLiveProbeRows(openCodeZenRows, "opencode", params.providerLiveProbes);
1150
- sections.push(createKvSection("opencode_zen", "opencode_zen:", openCodeZenRows));
1151
- // === xiaomi ===
1152
- const xiaomiRows = [];
1153
- const xiaomiDiag = await getMimoConfigDiagnostics();
1154
- xiaomiRows.push({ key: "config_state", value: xiaomiDiag.state });
1155
- xiaomiRows.push({ key: "config_source", value: xiaomiDiag.source ?? "(none)" });
1156
- if (xiaomiDiag.error) {
1157
- xiaomiRows.push({ key: "config_error", value: sanitizeDisplayText(xiaomiDiag.error) });
1158
- }
1159
- xiaomiRows.push({
1160
- key: "config_checked_paths",
1161
- value: joinOrNone(xiaomiDiag.checkedPaths),
1162
- });
1163
- appendProviderCompactLiveProbeRows(xiaomiRows, "xiaomi", params.providerLiveProbes);
1164
- sections.push(createKvSection("xiaomi", "xiaomi:", xiaomiRows));
1165
- // === zai ===
1166
- const zaiRows = [];
1167
- const zaiAuth = await getZaiAuthDiagnostics({
1168
- maxAgeMs: DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS,
1169
- });
1170
- zaiRows.push({ key: "auth_state", value: zaiAuth.state });
1171
- zaiRows.push({
1172
- key: "api_key_configured",
1173
- value: zaiAuth.state === "configured" ? "true" : "false",
1174
- });
1175
- zaiRows.push({ key: "api_key_source", value: zaiAuth.source ?? "(none)" });
1176
- zaiRows.push({ key: "api_key_checked_paths", value: joinOrNone(zaiAuth.checkedPaths) });
1177
- zaiRows.push({ key: "api_key_auth_paths", value: joinOrNone(zaiAuth.authPaths) });
1178
- if (zaiAuth.state === "invalid") {
1179
- zaiRows.push({ key: "auth_error", value: sanitizeDisplayText(zaiAuth.error) });
1180
- }
1181
- if (zaiAuth.state === "configured") {
1182
- const zaiQuota = await queryZaiQuota();
1183
- if (!zaiQuota) {
1184
- zaiRows.push({
1185
- key: "live_fetch_error",
1186
- value: "Z.ai API key became unavailable before fetch",
1187
- });
1188
- }
1189
- else if (!zaiQuota.success) {
1190
- zaiRows.push({ key: "live_fetch_error", value: zaiQuota.error });
1191
- }
1192
- else {
1193
- if (zaiQuota.windows.fiveHour) {
1194
- zaiRows.push({
1195
- key: "five_hour_remaining",
1196
- value: `${zaiQuota.windows.fiveHour.percentRemaining}% reset_at=${zaiQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`,
1197
- });
1198
- }
1199
- if (zaiQuota.windows.weekly) {
1200
- zaiRows.push({
1201
- key: "weekly_remaining",
1202
- value: `${zaiQuota.windows.weekly.percentRemaining}% reset_at=${zaiQuota.windows.weekly.resetTimeIso ?? "(none)"}`,
1203
- });
1204
- }
1205
- if (zaiQuota.windows.mcp) {
1206
- zaiRows.push({
1207
- key: "mcp_remaining",
1208
- value: `${zaiQuota.windows.mcp.percentRemaining}% reset_at=${zaiQuota.windows.mcp.resetTimeIso ?? "(none)"}`,
1209
- });
1210
- }
1211
- if (!zaiQuota.windows.fiveHour && !zaiQuota.windows.weekly && !zaiQuota.windows.mcp) {
1212
- zaiRows.push({ key: "live_state", value: "no reportable Z.ai quota windows" });
1213
- }
1214
- }
1215
- }
1216
- appendProviderCompactLiveProbeRows(zaiRows, "zai", params.providerLiveProbes);
1217
- sections.push(createKvSection("zai", "zai:", zaiRows));
1218
- // === zhipu ===
1219
- const zhipuRows = [];
1220
- const zhipuAuth = await getZhipuAuthDiagnostics({
1221
- maxAgeMs: DEFAULT_ZHIPU_AUTH_CACHE_MAX_AGE_MS,
1222
- });
1223
- zhipuRows.push({ key: "auth_state", value: zhipuAuth.state });
1224
- zhipuRows.push({
1225
- key: "api_key_configured",
1226
- value: zhipuAuth.state === "configured" ? "true" : "false",
1227
- });
1228
- zhipuRows.push({ key: "api_key_source", value: zhipuAuth.source ?? "(none)" });
1229
- zhipuRows.push({ key: "api_key_checked_paths", value: joinOrNone(zhipuAuth.checkedPaths) });
1230
- zhipuRows.push({ key: "api_key_auth_paths", value: joinOrNone(zhipuAuth.authPaths) });
1231
- if (zhipuAuth.state === "invalid") {
1232
- zhipuRows.push({ key: "auth_error", value: sanitizeDisplayText(zhipuAuth.error) });
1233
- }
1234
- if (zhipuAuth.state === "configured") {
1235
- const zhipuQuota = await queryZhipuQuota();
1236
- if (!zhipuQuota) {
1237
- zhipuRows.push({
1238
- key: "live_fetch_error",
1239
- value: "Zhipu API key became unavailable before fetch",
1240
- });
1241
- }
1242
- else if (!zhipuQuota.success) {
1243
- zhipuRows.push({ key: "live_fetch_error", value: zhipuQuota.error });
1244
- }
1245
- else {
1246
- if (zhipuQuota.windows.fiveHour) {
1247
- zhipuRows.push({
1248
- key: "five_hour_remaining",
1249
- value: `${zhipuQuota.windows.fiveHour.percentRemaining}% reset_at=${zhipuQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`,
1250
- });
1251
- }
1252
- if (zhipuQuota.windows.weekly) {
1253
- zhipuRows.push({
1254
- key: "weekly_remaining",
1255
- value: `${zhipuQuota.windows.weekly.percentRemaining}% reset_at=${zhipuQuota.windows.weekly.resetTimeIso ?? "(none)"}`,
1256
- });
1257
- }
1258
- if (zhipuQuota.windows.mcp) {
1259
- zhipuRows.push({
1260
- key: "mcp_remaining",
1261
- value: `${zhipuQuota.windows.mcp.percentRemaining}% reset_at=${zhipuQuota.windows.mcp.resetTimeIso ?? "(none)"}`,
1262
- });
1263
- }
1264
- if (!zhipuQuota.windows.fiveHour && !zhipuQuota.windows.weekly && !zhipuQuota.windows.mcp) {
1265
- zhipuRows.push({ key: "live_state", value: "no reportable Zhipu quota windows" });
1266
- }
1267
- }
1268
- }
1269
- appendProviderCompactLiveProbeRows(zhipuRows, "zhipu", params.providerLiveProbes);
1270
- sections.push(createKvSection("zhipu", "zhipu:", zhipuRows));
1271
- // === simple API key sections ===
1272
- const syntheticDiag = await readBasicApiKeyDiagnostics(getSyntheticKeyDiagnostics);
1273
- const syntheticRows = [
598
+ for (const section of [
599
+ { id: "minimax", title: "minimax:", providerId: "minimax-coding-plan" },
1274
600
  {
1275
- key: "synthetic api key",
1276
- value: formatInlineApiKeyDiagnosticsValue(syntheticDiag),
601
+ id: "minimax_china",
602
+ title: "minimax_china:",
603
+ providerId: "minimax-china-coding-plan",
1277
604
  },
1278
- ];
1279
- appendProviderCompactLiveProbeRows(syntheticRows, "synthetic", params.providerLiveProbes);
1280
- sections.push(createKvSection("synthetic", "synthetic:", syntheticRows));
1281
- const chutesDiag = await readBasicApiKeyDiagnostics(getChutesKeyDiagnostics);
1282
- const chutesRows = [
605
+ { id: "kimi", title: "kimi:", providerId: "kimi-for-coding" },
606
+ { id: "opencode_go", title: "opencode_go:", providerId: "opencode-go" },
607
+ { id: "opencode_zen", title: "opencode_zen:", providerId: "opencode" },
608
+ { id: "xiaomi", title: "xiaomi:", providerId: "xiaomi" },
609
+ { id: "zai", title: "zai:", providerId: "zai" },
610
+ { id: "zhipu", title: "zhipu:", providerId: "zhipu" },
611
+ { id: "synthetic", title: "synthetic:", providerId: "synthetic" },
612
+ { id: "chutes", title: "chutes:", providerId: "chutes" },
613
+ { id: "deepseek", title: "deepseek:", providerId: "deepseek" },
614
+ { id: "xai", title: "xai:", providerId: "xai", includeDetails: false },
615
+ { id: "nanogpt", title: "nanogpt:", providerId: "nanogpt" },
1283
616
  {
1284
- key: "chutes api key",
1285
- value: formatInlineApiKeyDiagnosticsValue(chutesDiag),
617
+ id: "copilot_quota_auth",
618
+ title: "copilot_quota_auth:",
619
+ providerId: "copilot",
1286
620
  },
1287
- ];
1288
- appendProviderCompactLiveProbeRows(chutesRows, "chutes", params.providerLiveProbes);
1289
- sections.push(createKvSection("chutes", "chutes:", chutesRows));
1290
- const deepSeekDiag = await readApiKeyDiagnosticsWithAuthPaths(getDeepSeekKeyDiagnostics);
1291
- const deepSeekRows = [
1292
- { key: "api_key_configured", value: deepSeekDiag.configured ? "true" : "false" },
1293
- { key: "api_key_source", value: deepSeekDiag.source ?? "(none)" },
1294
- { key: "api_key_checked_paths", value: joinOrNone(deepSeekDiag.checkedPaths) },
1295
- { key: "api_key_auth_paths", value: joinOrNone(deepSeekDiag.authPaths) },
1296
- ];
1297
- appendProviderCompactLiveProbeRows(deepSeekRows, "deepseek", params.providerLiveProbes);
1298
- sections.push(createKvSection("deepseek", "deepseek:", deepSeekRows));
1299
- // === xai ===
1300
- const xaiRows = [];
1301
- appendProviderCompactLiveProbeRows(xaiRows, "xai", params.providerLiveProbes);
1302
- sections.push(createKvSection("xai", "xai:", xaiRows));
1303
- // === nanogpt ===
1304
- const nanoGptDiag = await readApiKeyDiagnosticsWithAuthPaths(getNanoGptKeyDiagnostics);
1305
- const nanoGptRows = [
1306
- { key: "api_key_configured", value: nanoGptDiag.configured ? "true" : "false" },
1307
- { key: "api_key_source", value: nanoGptDiag.source ?? "(none)" },
1308
- { key: "api_key_checked_paths", value: joinOrNone(nanoGptDiag.checkedPaths) },
1309
- { key: "api_key_auth_paths", value: joinOrNone(nanoGptDiag.authPaths) },
1310
- ];
1311
- if (nanoGptDiag.configured) {
1312
- try {
1313
- const nanoGptQuota = await queryNanoGptQuota();
1314
- if (!nanoGptQuota) {
1315
- nanoGptRows.push({
1316
- key: "live_fetch_error",
1317
- value: "NanoGPT API key became unavailable before fetch",
1318
- });
1319
- }
1320
- else if (!nanoGptQuota.success) {
1321
- nanoGptRows.push({ key: "live_fetch_error", value: nanoGptQuota.error });
1322
- }
1323
- else {
1324
- if (nanoGptQuota.subscription) {
1325
- nanoGptRows.push({
1326
- key: "subscription_active",
1327
- value: nanoGptQuota.subscription.active ? "true" : "false",
1328
- });
1329
- nanoGptRows.push({ key: "subscription_state", value: nanoGptQuota.subscription.state });
1330
- nanoGptRows.push({
1331
- key: "enforce_daily_limit",
1332
- value: nanoGptQuota.subscription.enforceDailyLimit ? "true" : "false",
1333
- });
1334
- if (nanoGptQuota.subscription.daily) {
1335
- const daily = nanoGptQuota.subscription.daily;
1336
- nanoGptRows.push({
1337
- key: "daily_usage",
1338
- value: `${fmtNanoGptMetric(daily.used)}/${fmtNanoGptMetric(daily.limit)} remaining=${fmtNanoGptMetric(daily.remaining)} percent_remaining=${daily.percentRemaining} reset_at=${daily.resetTimeIso ?? "(none)"}`,
1339
- });
1340
- }
1341
- if (nanoGptQuota.subscription.monthly) {
1342
- const monthly = nanoGptQuota.subscription.monthly;
1343
- nanoGptRows.push({
1344
- key: "monthly_usage",
1345
- value: `${fmtNanoGptMetric(monthly.used)}/${fmtNanoGptMetric(monthly.limit)} remaining=${fmtNanoGptMetric(monthly.remaining)} percent_remaining=${monthly.percentRemaining} reset_at=${monthly.resetTimeIso ?? "(none)"}`,
1346
- });
1347
- }
1348
- nanoGptRows.push({
1349
- key: "billing_period_end",
1350
- value: nanoGptQuota.subscription.currentPeriodEndIso ?? "(none)",
1351
- });
1352
- if (nanoGptQuota.subscription.graceUntilIso) {
1353
- nanoGptRows.push({
1354
- key: "grace_until",
1355
- value: nanoGptQuota.subscription.graceUntilIso,
1356
- });
1357
- }
1358
- }
1359
- nanoGptRows.push({
1360
- key: "balance_usd",
1361
- value: typeof nanoGptQuota.balance?.usdBalance === "number"
1362
- ? fmtUsdAmount(nanoGptQuota.balance.usdBalance)
1363
- : "(none)",
1364
- });
1365
- nanoGptRows.push({
1366
- key: "balance_nano",
1367
- value: nanoGptQuota.balance?.nanoBalanceRaw ?? "(none)",
1368
- });
1369
- for (const entry of nanoGptQuota.endpointErrors ?? []) {
1370
- nanoGptRows.push({ key: `live_error_${entry.endpoint}`, value: entry.message });
1371
- }
1372
- }
1373
- }
1374
- catch (err) {
1375
- const msg = err instanceof Error ? err.message : String(err);
1376
- nanoGptRows.push({ key: "live_fetch_error", value: msg });
1377
- }
1378
- }
1379
- appendProviderCompactLiveProbeRows(nanoGptRows, "nanogpt", params.providerLiveProbes);
1380
- sections.push(createKvSection("nanogpt", "nanogpt:", nanoGptRows));
1381
- // === copilot auth ===
1382
- const copilotDiag = getCopilotQuotaAuthDiagnostics(authData);
1383
- const copilotRows = [{ key: "pat_state", value: copilotDiag.pat.state }];
1384
- if (copilotDiag.pat.selectedPath) {
1385
- copilotRows.push({ key: "pat_path", value: copilotDiag.pat.selectedPath });
1386
- }
1387
- if (copilotDiag.pat.tokenKind) {
1388
- copilotRows.push({ key: "pat_token_kind", value: copilotDiag.pat.tokenKind });
1389
- }
1390
- if (copilotDiag.pat.config?.tier) {
1391
- copilotRows.push({ key: "pat_tier", value: copilotDiag.pat.config.tier });
1392
- }
1393
- if (copilotDiag.billingModel) {
1394
- copilotRows.push({ key: "billing_model", value: copilotDiag.billingModel });
1395
- }
1396
- if (copilotDiag.pat.config?.organization) {
1397
- copilotRows.push({ key: "pat_organization", value: copilotDiag.pat.config.organization });
1398
- }
1399
- if (copilotDiag.pat.config?.enterprise) {
1400
- copilotRows.push({ key: "pat_enterprise", value: copilotDiag.pat.config.enterprise });
1401
- }
1402
- copilotRows.push({ key: "deployment", value: copilotDiag.deployment });
1403
- copilotRows.push({ key: "api_host", value: copilotDiag.apiHost ?? "(none)" });
1404
- copilotRows.push({ key: "enterprise_host_source", value: copilotDiag.enterpriseHostSource });
1405
- if (copilotDiag.enterpriseHostError) {
1406
- copilotRows.push({ key: "enterprise_host_error", value: copilotDiag.enterpriseHostError });
1407
- }
1408
- copilotRows.push({ key: "billing_mode", value: copilotDiag.billingMode });
1409
- copilotRows.push({ key: "billing_scope", value: copilotDiag.billingScope });
1410
- copilotRows.push({ key: "quota_api", value: copilotDiag.quotaApi });
1411
- copilotRows.push({ key: "budget_api", value: copilotDiag.budgetApi });
1412
- copilotRows.push({
1413
- key: "billing_api_access_likely",
1414
- value: copilotDiag.billingApiAccessLikely ? "true" : "false",
1415
- });
1416
- copilotRows.push({ key: "remaining_totals_state", value: copilotDiag.remainingTotalsState });
1417
- if (copilotDiag.queryPeriod) {
1418
- copilotRows.push({
1419
- key: "billing_period",
1420
- value: `${copilotDiag.queryPeriod.year}-${String(copilotDiag.queryPeriod.month).padStart(2, "0")}`,
1421
- });
1422
- }
1423
- if (copilotDiag.usernameFilter) {
1424
- copilotRows.push({ key: "username_filter", value: copilotDiag.usernameFilter });
1425
- }
1426
- if (copilotDiag.billingMode === "organization_usage") {
1427
- copilotRows.push({
1428
- key: "billing_usage_note",
1429
- value: "organization AI Credit usage for the current UTC calendar month",
1430
- });
1431
- copilotRows.push({
1432
- key: "remaining_quota_note",
1433
- value: "the usage report exposes included-pool consumption and billed usage, but no included-pool denominator; percentages require a real budget",
1434
- });
1435
- }
1436
- if (copilotDiag.billingMode === "enterprise_usage") {
1437
- copilotRows.push({
1438
- key: "billing_usage_note",
1439
- value: "enterprise AI Credit usage for the current UTC calendar month",
1440
- });
1441
- copilotRows.push({
1442
- key: "remaining_quota_note",
1443
- value: "the usage report exposes included-pool consumption and billed usage, but no included-pool denominator; percentages require a real budget",
1444
- });
1445
- }
1446
- if (copilotDiag.billingTargetError) {
1447
- copilotRows.push({ key: "billing_target_error", value: copilotDiag.billingTargetError });
621
+ ]) {
622
+ sections.push(createProviderStatusSection({
623
+ ...section,
624
+ probes: params.providerLiveProbes,
625
+ availability: params.providerAvailability,
626
+ }));
1448
627
  }
1449
- if (copilotDiag.tokenCompatibilityError) {
1450
- copilotRows.push({
1451
- key: "token_compatibility_error",
1452
- value: copilotDiag.tokenCompatibilityError,
1453
- });
1454
- }
1455
- if (copilotDiag.pat.error) {
1456
- copilotRows.push({ key: "pat_error", value: copilotDiag.pat.error });
1457
- }
1458
- copilotRows.push({
1459
- key: "pat_checked_paths",
1460
- value: copilotDiag.pat.checkedPaths.length
1461
- ? copilotDiag.pat.checkedPaths.join(" | ")
1462
- : "(none)",
1463
- });
1464
- copilotRows.push({
1465
- key: "oauth_configured",
1466
- value: `${copilotDiag.oauth.configured ? "true" : "false"} key=${copilotDiag.oauth.keyName ?? "(none)"} refresh=${copilotDiag.oauth.hasRefreshToken ? "true" : "false"} access=${copilotDiag.oauth.hasAccessToken ? "true" : "false"} enterprise_host=${copilotDiag.oauth.hasEnterpriseUrl ? "true" : "false"}`,
1467
- });
1468
- copilotRows.push({ key: "effective_source", value: copilotDiag.effectiveSource });
1469
- copilotRows.push({ key: "oauth_accounting_state", value: copilotDiag.oauthAccountingState });
1470
- copilotRows.push({ key: "override", value: copilotDiag.override });
1471
- appendProviderCompactLiveProbeRows(copilotRows, "copilot", params.providerLiveProbes);
1472
- sections.push(createKvSection("copilot_quota_auth", "copilot_quota_auth:", copilotRows));
1473
628
  // === google antigravity + db path ===
1474
- const googleTokenCachePath = getGoogleTokenCachePath();
1475
- const googleAuthPresence = await inspectAntigravityAccountsPresence();
1476
- const googleCompanionPresence = await inspectAntigravityCompanionPresence();
1477
629
  const dbCandidates = getOpenCodeDbPathCandidates();
1478
630
  const dbSelected = getOpenCodeDbPath();
1479
631
  const dbPresent = [];
@@ -1481,98 +633,26 @@ export async function buildQuotaStatusReport(params) {
1481
633
  if (await pathExists(p))
1482
634
  dbPresent.push(p);
1483
635
  }));
1484
- const googleRows = [
1485
- { key: "auth_state", value: googleAuthPresence.state },
1486
- { key: "selected_accounts_path", value: googleAuthPresence.selectedPath ?? "(none)" },
1487
- { key: "present_accounts_paths", value: joinOrNone(googleAuthPresence.presentPaths) },
1488
- { key: "candidate_accounts_paths", value: joinOrNone(googleAuthPresence.candidatePaths) },
1489
- { key: "account_count", value: String(googleAuthPresence.accountCount) },
1490
- { key: "valid_account_count", value: String(googleAuthPresence.validAccountCount) },
1491
- { key: "companion_package_state", value: googleCompanionPresence.state },
1492
- {
1493
- key: "companion_package_path",
1494
- value: googleCompanionPresence.state === "present" || googleCompanionPresence.state === "invalid"
1495
- ? (googleCompanionPresence.resolvedPath ?? "(none)")
1496
- : "(none)",
1497
- },
1498
- ];
1499
- if (googleCompanionPresence.state !== "present") {
1500
- googleRows.push({
1501
- key: "companion_error",
1502
- value: sanitizeDisplayText(googleCompanionPresence.error),
1503
- });
1504
- }
1505
- googleRows.push({
1506
- key: "token_cache_path",
1507
- value: `${googleTokenCachePath} exists=${(await pathExists(googleTokenCachePath)) ? "true" : "false"}`,
1508
- });
1509
- if (googleAuthPresence.state === "invalid" && googleAuthPresence.error) {
1510
- googleRows.push({ key: "auth_error", value: sanitizeDisplayText(googleAuthPresence.error) });
1511
- }
636
+ const googleRows = [];
637
+ appendProviderStatusDetailRows(googleRows, "google-antigravity", params.providerLiveProbes);
1512
638
  googleRows.push({
1513
639
  key: "opencode db",
1514
640
  value: `preferred=${dbSelected} present=${joinOrNone(dbPresent)} candidates=${joinOrNone(dbCandidates)}`,
1515
641
  });
1516
- appendProviderCompactLiveProbeRows(googleRows, "google-antigravity", params.providerLiveProbes);
642
+ appendProviderCompactLiveProbeRows(googleRows, "google-antigravity", params.providerLiveProbes, params.providerAvailability);
1517
643
  sections.push(createKvSection("google_antigravity", "google_antigravity:", googleRows));
1518
- // === google gemini cli ===
1519
- const geminiCliAuthPresence = await inspectGeminiCliAuthPresence(params.geminiCliClient);
1520
- const geminiCliCompanionPresence = await inspectGeminiCliCompanionPresence();
1521
- const geminiCliRows = [
1522
- { key: "auth_state", value: geminiCliAuthPresence.state },
1523
- { key: "auth_source", value: geminiCliAuthPresence.sourceKey ?? "(none)" },
1524
- { key: "account_count", value: String(geminiCliAuthPresence.accountCount) },
1525
- { key: "valid_account_count", value: String(geminiCliAuthPresence.validAccountCount) },
1526
- { key: "companion_package_state", value: geminiCliCompanionPresence.state },
1527
- {
1528
- key: "companion_package_path",
1529
- value: geminiCliCompanionPresence.state === "present" ||
1530
- geminiCliCompanionPresence.state === "invalid"
1531
- ? (geminiCliCompanionPresence.resolvedPath ?? "(none)")
1532
- : "(none)",
1533
- },
1534
- ];
1535
- if (geminiCliAuthPresence.state === "invalid") {
1536
- geminiCliRows.push({
1537
- key: "auth_error",
1538
- value: sanitizeDisplayText(geminiCliAuthPresence.error),
1539
- });
1540
- }
1541
- if (geminiCliCompanionPresence.state !== "present") {
1542
- geminiCliRows.push({
1543
- key: "companion_error",
1544
- value: sanitizeDisplayText(geminiCliCompanionPresence.error),
1545
- });
1546
- }
1547
- appendProviderCompactLiveProbeRows(geminiCliRows, "google-gemini-cli", params.providerLiveProbes);
1548
- sections.push(createKvSection("google_gemini_cli", "google_gemini_cli:", geminiCliRows));
1549
- // Google AGY
1550
- const agyAuthPresence = await inspectAgyAuthPresence(params.agyClient);
1551
- const agyCompanionPresence = await inspectAgyCompanionPresence();
1552
- const agyRows = [
1553
- { key: "auth_state", value: agyAuthPresence.state },
1554
- { key: "auth_source", value: agyAuthPresence.sourceKey ?? "(none)" },
1555
- { key: "account_count", value: String(agyAuthPresence.accountCount) },
1556
- { key: "valid_account_count", value: String(agyAuthPresence.validAccountCount) },
1557
- { key: "companion_package_state", value: agyCompanionPresence.state },
1558
- {
1559
- key: "companion_package_path",
1560
- value: agyCompanionPresence.state === "present" || agyCompanionPresence.state === "invalid"
1561
- ? (agyCompanionPresence.resolvedPath ?? "(none)")
1562
- : "(none)",
1563
- },
1564
- ];
1565
- if (agyAuthPresence.state === "invalid") {
1566
- agyRows.push({ key: "auth_error", value: sanitizeDisplayText(agyAuthPresence.error) });
1567
- }
1568
- if (agyCompanionPresence.state !== "present") {
1569
- agyRows.push({
1570
- key: "companion_error",
1571
- value: sanitizeDisplayText(agyCompanionPresence.error),
1572
- });
644
+ for (const [id, providerId] of [
645
+ ["google_gemini_cli", "google-gemini-cli"],
646
+ ["google_agy", "google-agy"],
647
+ ]) {
648
+ sections.push(createProviderStatusSection({
649
+ id,
650
+ title: `${id}:`,
651
+ providerId,
652
+ probes: params.providerLiveProbes,
653
+ availability: params.providerAvailability,
654
+ }));
1573
655
  }
1574
- appendProviderCompactLiveProbeRows(agyRows, "google-agy", params.providerLiveProbes);
1575
- sections.push(createKvSection("google_agy", "google_agy:", agyRows));
1576
656
  if (params.googleRefresh?.attempted) {
1577
657
  const googleRefreshRows = [];
1578
658
  if (typeof params.googleRefresh.total === "number" &&