@slkiser/opencode-quota 3.0.2 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +207 -143
  2. package/dist/lib/anthropic.d.ts +4 -5
  3. package/dist/lib/anthropic.d.ts.map +1 -1
  4. package/dist/lib/anthropic.js +230 -18
  5. package/dist/lib/anthropic.js.map +1 -1
  6. package/dist/lib/api-key-resolver.d.ts +1 -1
  7. package/dist/lib/api-key-resolver.d.ts.map +1 -1
  8. package/dist/lib/api-key-resolver.js +11 -13
  9. package/dist/lib/api-key-resolver.js.map +1 -1
  10. package/dist/lib/config.d.ts.map +1 -1
  11. package/dist/lib/config.js +6 -0
  12. package/dist/lib/config.js.map +1 -1
  13. package/dist/lib/cursor-detection.d.ts.map +1 -1
  14. package/dist/lib/cursor-detection.js +14 -5
  15. package/dist/lib/cursor-detection.js.map +1 -1
  16. package/dist/lib/cursor-usage.d.ts.map +1 -1
  17. package/dist/lib/cursor-usage.js +18 -14
  18. package/dist/lib/cursor-usage.js.map +1 -1
  19. package/dist/lib/entries.d.ts +1 -1
  20. package/dist/lib/entries.d.ts.map +1 -1
  21. package/dist/lib/entries.js.map +1 -1
  22. package/dist/lib/format-utils.d.ts +8 -0
  23. package/dist/lib/format-utils.d.ts.map +1 -1
  24. package/dist/lib/format-utils.js +13 -0
  25. package/dist/lib/format-utils.js.map +1 -1
  26. package/dist/lib/format.d.ts +2 -0
  27. package/dist/lib/format.d.ts.map +1 -1
  28. package/dist/lib/format.js +14 -9
  29. package/dist/lib/format.js.map +1 -1
  30. package/dist/lib/grouped-entry-normalization.d.ts +5 -0
  31. package/dist/lib/grouped-entry-normalization.d.ts.map +1 -1
  32. package/dist/lib/grouped-entry-normalization.js +7 -3
  33. package/dist/lib/grouped-entry-normalization.js.map +1 -1
  34. package/dist/lib/init-installer.d.ts +1 -0
  35. package/dist/lib/init-installer.d.ts.map +1 -1
  36. package/dist/lib/init-installer.js +15 -0
  37. package/dist/lib/init-installer.js.map +1 -1
  38. package/dist/lib/kimi-auth.d.ts +38 -0
  39. package/dist/lib/kimi-auth.d.ts.map +1 -0
  40. package/dist/lib/kimi-auth.js +104 -0
  41. package/dist/lib/kimi-auth.js.map +1 -0
  42. package/dist/lib/kimi.d.ts +3 -0
  43. package/dist/lib/kimi.d.ts.map +1 -0
  44. package/dist/lib/kimi.js +206 -0
  45. package/dist/lib/kimi.js.map +1 -0
  46. package/dist/lib/opencode-sqlite.d.ts.map +1 -1
  47. package/dist/lib/opencode-sqlite.js +9 -12
  48. package/dist/lib/opencode-sqlite.js.map +1 -1
  49. package/dist/lib/opencode-storage.d.ts.map +1 -1
  50. package/dist/lib/opencode-storage.js +9 -5
  51. package/dist/lib/opencode-storage.js.map +1 -1
  52. package/dist/lib/provider-metadata.d.ts +1 -1
  53. package/dist/lib/provider-metadata.d.ts.map +1 -1
  54. package/dist/lib/provider-metadata.js +17 -4
  55. package/dist/lib/provider-metadata.js.map +1 -1
  56. package/dist/lib/quota-command-format.d.ts.map +1 -1
  57. package/dist/lib/quota-command-format.js +41 -42
  58. package/dist/lib/quota-command-format.js.map +1 -1
  59. package/dist/lib/quota-render-data.d.ts.map +1 -1
  60. package/dist/lib/quota-render-data.js +1 -4
  61. package/dist/lib/quota-render-data.js.map +1 -1
  62. package/dist/lib/quota-stats-format.d.ts.map +1 -1
  63. package/dist/lib/quota-stats-format.js +164 -121
  64. package/dist/lib/quota-stats-format.js.map +1 -1
  65. package/dist/lib/quota-status.d.ts.map +1 -1
  66. package/dist/lib/quota-status.js +590 -265
  67. package/dist/lib/quota-status.js.map +1 -1
  68. package/dist/lib/report-document.d.ts +36 -0
  69. package/dist/lib/report-document.d.ts.map +1 -0
  70. package/dist/lib/report-document.js +109 -0
  71. package/dist/lib/report-document.js.map +1 -0
  72. package/dist/lib/session-tokens-format.d.ts +8 -0
  73. package/dist/lib/session-tokens-format.d.ts.map +1 -1
  74. package/dist/lib/session-tokens-format.js +36 -20
  75. package/dist/lib/session-tokens-format.js.map +1 -1
  76. package/dist/lib/synthetic-config.d.ts +41 -0
  77. package/dist/lib/synthetic-config.d.ts.map +1 -0
  78. package/dist/lib/synthetic-config.js +57 -0
  79. package/dist/lib/synthetic-config.js.map +1 -0
  80. package/dist/lib/synthetic.d.ts +17 -0
  81. package/dist/lib/synthetic.d.ts.map +1 -0
  82. package/dist/lib/synthetic.js +94 -0
  83. package/dist/lib/synthetic.js.map +1 -0
  84. package/dist/lib/toast-format-grouped.d.ts +2 -0
  85. package/dist/lib/toast-format-grouped.d.ts.map +1 -1
  86. package/dist/lib/toast-format-grouped.js +9 -6
  87. package/dist/lib/toast-format-grouped.js.map +1 -1
  88. package/dist/lib/tui-config-diagnostics.d.ts.map +1 -1
  89. package/dist/lib/tui-config-diagnostics.js +13 -9
  90. package/dist/lib/tui-config-diagnostics.js.map +1 -1
  91. package/dist/lib/tui-panel-state.d.ts.map +1 -1
  92. package/dist/lib/tui-panel-state.js +10 -5
  93. package/dist/lib/tui-panel-state.js.map +1 -1
  94. package/dist/lib/tui-sidebar-format.d.ts +1 -1
  95. package/dist/lib/tui-sidebar-format.d.ts.map +1 -1
  96. package/dist/lib/tui-sidebar-format.js +1 -0
  97. package/dist/lib/tui-sidebar-format.js.map +1 -1
  98. package/dist/lib/types.d.ts +42 -4
  99. package/dist/lib/types.d.ts.map +1 -1
  100. package/dist/lib/types.js +1 -0
  101. package/dist/lib/types.js.map +1 -1
  102. package/dist/plugin.d.ts.map +1 -1
  103. package/dist/plugin.js +1 -0
  104. package/dist/plugin.js.map +1 -1
  105. package/dist/providers/anthropic.js +1 -1
  106. package/dist/providers/anthropic.js.map +1 -1
  107. package/dist/providers/copilot.d.ts.map +1 -1
  108. package/dist/providers/copilot.js +2 -1
  109. package/dist/providers/copilot.js.map +1 -1
  110. package/dist/providers/cursor.d.ts.map +1 -1
  111. package/dist/providers/cursor.js +2 -1
  112. package/dist/providers/cursor.js.map +1 -1
  113. package/dist/providers/google-antigravity.d.ts.map +1 -1
  114. package/dist/providers/google-antigravity.js +2 -1
  115. package/dist/providers/google-antigravity.js.map +1 -1
  116. package/dist/providers/kimi-code.d.ts +3 -0
  117. package/dist/providers/kimi-code.d.ts.map +1 -0
  118. package/dist/providers/kimi-code.js +71 -0
  119. package/dist/providers/kimi-code.js.map +1 -0
  120. package/dist/providers/registry.d.ts.map +1 -1
  121. package/dist/providers/registry.js +4 -2
  122. package/dist/providers/registry.js.map +1 -1
  123. package/dist/providers/synthetic.d.ts +6 -0
  124. package/dist/providers/synthetic.d.ts.map +1 -0
  125. package/dist/providers/synthetic.js +57 -0
  126. package/dist/providers/synthetic.js.map +1 -0
  127. package/package.json +2 -2
  128. package/dist/lib/firmware-config.d.ts +0 -41
  129. package/dist/lib/firmware-config.d.ts.map +0 -1
  130. package/dist/lib/firmware-config.js +0 -60
  131. package/dist/lib/firmware-config.js.map +0 -1
  132. package/dist/lib/firmware.d.ts +0 -22
  133. package/dist/lib/firmware.d.ts.map +0 -1
  134. package/dist/lib/firmware.js +0 -62
  135. package/dist/lib/firmware.js.map +0 -1
  136. package/dist/providers/firmware.d.ts +0 -6
  137. package/dist/providers/firmware.d.ts.map +0 -1
  138. package/dist/providers/firmware.js +0 -45
  139. package/dist/providers/firmware.js.map +0 -1
@@ -5,9 +5,9 @@ import { getGoogleTokenCachePath } from "./google-token-cache.js";
5
5
  import { inspectAntigravityCompanionPresence } from "./google-antigravity-companion.js";
6
6
  import { inspectAntigravityAccountsPresence } from "./google.js";
7
7
  import { getAnthropicDiagnostics } from "./anthropic.js";
8
- import { getFirmwareKeyDiagnostics } from "./firmware.js";
9
8
  import { getChutesKeyDiagnostics } from "./chutes.js";
10
9
  import { getNanoGptKeyDiagnostics, queryNanoGptQuota } from "./nanogpt.js";
10
+ import { getSyntheticKeyDiagnostics } from "./synthetic.js";
11
11
  import { getCopilotQuotaAuthDiagnostics } from "./copilot.js";
12
12
  import { computeAlibabaCodingPlanQuota, computeQwenQuota, getAlibabaCodingPlanQuotaPath, getQwenLocalQuotaPath, readAlibabaCodingPlanQuotaState, readQwenLocalQuotaState, } from "./qwen-local-quota.js";
13
13
  import { DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS, getAlibabaCodingPlanAuthDiagnostics, resolveAlibabaCodingPlanAuthCached, } from "./alibaba-auth.js";
@@ -15,12 +15,15 @@ import { hasQwenOAuthAuth, resolveQwenLocalPlan } from "./qwen-auth.js";
15
15
  import { resolveOpenAIOAuth } from "./openai.js";
16
16
  import { DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS, getMiniMaxAuthDiagnostics, resolveMiniMaxAuthCached, } from "./minimax-auth.js";
17
17
  import { DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS, getZaiAuthDiagnostics } from "./zai-auth.js";
18
+ import { DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS, getKimiAuthDiagnostics, } from "./kimi-auth.js";
19
+ import { queryKimiQuota } from "./kimi.js";
18
20
  import { getPricingSnapshotHealth, getPricingRefreshPolicy, getPricingSnapshotMeta, getPricingSnapshotSource, getRuntimePricingRefreshStatePath, getRuntimePricingSnapshotPath, listProviders, getProviderModelCount, hasProvider as snapshotHasProvider, readPricingRefreshState, } from "./modelsdev-pricing.js";
19
21
  import { getProviders } from "../providers/registry.js";
20
22
  import { getPackageVersion } from "./version.js";
21
23
  import { getOpenCodeDbPath, getOpenCodeDbPathCandidates, getOpenCodeDbStats, } from "./opencode-storage.js";
22
24
  import { aggregateUsage } from "./quota-stats.js";
23
- import { fmtUsdAmount, renderCommandHeading } from "./format-utils.js";
25
+ import { fmtUsdAmount } from "./format-utils.js";
26
+ import { renderPlainTextReport } from "./report-document.js";
24
27
  import { totalTokenBuckets } from "./token-buckets.js";
25
28
  import { CURSOR_CANONICAL_PLUGIN_PACKAGE, inspectCursorAuthPresence, inspectCursorOpenCodeIntegration, } from "./cursor-detection.js";
26
29
  import { getCurrentCursorUsageSummary } from "./cursor-usage.js";
@@ -80,13 +83,30 @@ async function readBasicApiKeyDiagnostics(read) {
80
83
  return getDefaultBasicApiKeyDiagnostics();
81
84
  }
82
85
  }
83
- function formatInlineApiKeyDiagnostics(label, diagnostics) {
84
- return `- ${label}: configured=${diagnostics.configured ? "true" : "false"}${diagnostics.source ? ` source=${diagnostics.source}` : ""}${diagnostics.checkedPaths.length > 0 ? ` checked=${diagnostics.checkedPaths.join(" | ")}` : ""}`;
86
+ function formatInlineApiKeyDiagnosticsValue(diagnostics) {
87
+ return `configured=${diagnostics.configured ? "true" : "false"}${diagnostics.source ? ` source=${diagnostics.source}` : ""}${diagnostics.checkedPaths.length > 0 ? ` checked=${diagnostics.checkedPaths.join(" | ")}` : ""}`;
85
88
  }
86
- function appendBasicApiKeySection(params) {
87
- params.lines.push("");
88
- params.lines.push(params.section);
89
- params.lines.push(formatInlineApiKeyDiagnostics(params.label, params.diagnostics));
89
+ function createKvSection(id, title, rows) {
90
+ return {
91
+ id,
92
+ title,
93
+ blocks: [{ kind: "kv", rows }],
94
+ };
95
+ }
96
+ function createLinesSection(id, title, lines) {
97
+ return {
98
+ id,
99
+ title,
100
+ blocks: [{ kind: "lines", lines }],
101
+ };
102
+ }
103
+ function buildBasicApiKeySection(params) {
104
+ return createKvSection(params.id, params.section, [
105
+ {
106
+ key: params.label,
107
+ value: formatInlineApiKeyDiagnosticsValue(params.diagnostics),
108
+ },
109
+ ]);
90
110
  }
91
111
  function getDefaultNanoGptApiKeyDiagnostics() {
92
112
  return {
@@ -102,14 +122,6 @@ async function readNanoGptApiKeyDiagnostics(read) {
102
122
  return getDefaultNanoGptApiKeyDiagnostics();
103
123
  }
104
124
  }
105
- function appendNanoGptApiKeySection(lines, diagnostics) {
106
- lines.push("");
107
- lines.push("nanogpt:");
108
- lines.push(`- api_key_configured: ${diagnostics.configured ? "true" : "false"}`);
109
- lines.push(`- api_key_source: ${diagnostics.source ?? "(none)"}`);
110
- lines.push(`- api_key_checked_paths: ${joinOrNone(diagnostics.checkedPaths)}`);
111
- lines.push(`- api_key_auth_paths: ${joinOrNone(diagnostics.authPaths)}`);
112
- }
113
125
  function fmtNanoGptMetric(value) {
114
126
  if (!Number.isFinite(value))
115
127
  return "0";
@@ -164,11 +176,11 @@ function computePricingCoverageFromAgg(agg) {
164
176
  }
165
177
  function supportedProviderPricingRow(params) {
166
178
  const id = params.id;
167
- if (id === "firmware") {
179
+ if (id === "synthetic") {
168
180
  return {
169
181
  id,
170
182
  pricing: "no",
171
- notes: "credits-based quota (not token-priced)",
183
+ notes: "subscription request quota (not token-priced)",
172
184
  };
173
185
  }
174
186
  if (id === "qwen-code") {
@@ -206,6 +218,13 @@ function supportedProviderPricingRow(params) {
206
218
  notes: "subscription percentage quota via dashboard scraping (not token-priced)",
207
219
  };
208
220
  }
221
+ if (id === "kimi-code") {
222
+ return {
223
+ id,
224
+ pricing: "no",
225
+ notes: "request quota via Kimi Code API (not token-priced)",
226
+ };
227
+ }
209
228
  // Providers that correspond directly to models.dev providers.
210
229
  if (params.snapshotProviders.includes(id)) {
211
230
  return { id, pricing: "yes", notes: "models.dev snapshot provider" };
@@ -247,20 +266,8 @@ function supportedProviderPricingRow(params) {
247
266
  };
248
267
  }
249
268
  export async function buildQuotaStatusReport(params) {
250
- const lines = [];
251
269
  const version = await getPackageVersion();
252
270
  const v = version ?? "unknown";
253
- lines.push(renderCommandHeading({
254
- title: `Quota Status (opencode-quota v${v}) (/quota_status)`,
255
- generatedAtMs: params.generatedAtMs,
256
- }));
257
- lines.push("");
258
- // === toast diagnostics ===
259
- lines.push("toast:");
260
- lines.push(`- configSource: ${params.configSource}${params.configPaths.length ? ` (${params.configPaths.join(" | ")})` : ""}`);
261
- lines.push(`- network_setting_sources: ${formatNetworkSettingSources(params.networkSettingSources)}`);
262
- lines.push(`- enabledProviders: ${params.enabledProviders === "auto" ? "(auto)" : params.enabledProviders.length ? params.enabledProviders.join(",") : "(none)"}`);
263
- lines.push(`- onlyCurrentModel: ${params.onlyCurrentModel ? "true" : "false"}`);
264
271
  const modelDisplay = params.currentModel
265
272
  ? params.currentModel
266
273
  : params.sessionModelLookup === "not_found"
@@ -268,18 +275,26 @@ export async function buildQuotaStatusReport(params) {
268
275
  : params.sessionModelLookup === "no_session"
269
276
  ? "(no session available)"
270
277
  : "(unknown)";
271
- lines.push(`- currentModel: ${modelDisplay}`);
278
+ const sections = [];
279
+ // === toast diagnostics ===
280
+ const toastLines = [
281
+ `- configSource: ${params.configSource}${params.configPaths.length ? ` (${params.configPaths.join(" | ")})` : ""}`,
282
+ `- network_setting_sources: ${formatNetworkSettingSources(params.networkSettingSources)}`,
283
+ `- enabledProviders: ${params.enabledProviders === "auto" ? "(auto)" : params.enabledProviders.length ? params.enabledProviders.join(",") : "(none)"}`,
284
+ `- onlyCurrentModel: ${params.onlyCurrentModel ? "true" : "false"}`,
285
+ `- currentModel: ${modelDisplay}`,
286
+ ];
272
287
  if (params.tuiDiagnostics) {
273
- lines.push("");
274
- lines.push("tui:");
275
- lines.push(`- config_configured: ${params.tuiDiagnostics.configured ? "true" : "false"}`);
276
- lines.push(`- inferred_selected_config_path: ${params.tuiDiagnostics.inferredSelectedPath ?? "(none)"}`);
277
- lines.push(`- present_config_paths: ${joinOrNone(params.tuiDiagnostics.presentPaths)}`);
278
- lines.push(`- candidate_config_paths: ${joinOrNone(params.tuiDiagnostics.candidatePaths)}`);
279
- lines.push(`- quota_plugin_configured: ${params.tuiDiagnostics.quotaPluginConfigured ? "true" : "false"}`);
280
- lines.push(`- quota_plugin_paths: ${joinOrNone(params.tuiDiagnostics.quotaPluginConfigPaths)}`);
281
- }
282
- lines.push("- providers:");
288
+ toastLines.push("");
289
+ toastLines.push("tui:");
290
+ toastLines.push(`- config_configured: ${params.tuiDiagnostics.configured ? "true" : "false"}`);
291
+ toastLines.push(`- inferred_selected_config_path: ${params.tuiDiagnostics.inferredSelectedPath ?? "(none)"}`);
292
+ toastLines.push(`- present_config_paths: ${joinOrNone(params.tuiDiagnostics.presentPaths)}`);
293
+ toastLines.push(`- candidate_config_paths: ${joinOrNone(params.tuiDiagnostics.candidatePaths)}`);
294
+ toastLines.push(`- quota_plugin_configured: ${params.tuiDiagnostics.quotaPluginConfigured ? "true" : "false"}`);
295
+ toastLines.push(`- quota_plugin_paths: ${joinOrNone(params.tuiDiagnostics.quotaPluginConfigPaths)}`);
296
+ }
297
+ toastLines.push("- providers:");
283
298
  for (const p of params.providerAvailability) {
284
299
  const bits = [];
285
300
  bits.push(p.enabled ? "enabled" : "disabled");
@@ -287,12 +302,16 @@ export async function buildQuotaStatusReport(params) {
287
302
  if (p.matchesCurrentModel !== undefined) {
288
303
  bits.push(`matchesCurrentModel=${p.matchesCurrentModel ? "yes" : "no"}`);
289
304
  }
290
- lines.push(` - ${p.id}: ${bits.join(" ")}`);
305
+ toastLines.push(` - ${p.id}: ${bits.join(" ")}`);
291
306
  }
292
- lines.push("");
293
- lines.push("paths:");
307
+ sections.push(createLinesSection("toast", "toast:", toastLines));
308
+ // === paths ===
309
+ const pathsRows = [];
294
310
  const runtime = getOpencodeRuntimeDirs();
295
- lines.push(`- opencode_dirs: data=${runtime.dataDir} config=${runtime.configDir} cache=${runtime.cacheDir} state=${runtime.stateDir}`);
311
+ pathsRows.push({
312
+ key: "opencode_dirs",
313
+ value: `data=${runtime.dataDir} config=${runtime.configDir} cache=${runtime.cacheDir} state=${runtime.stateDir}`,
314
+ });
296
315
  const authCandidates = getAuthPaths();
297
316
  const authPresent = [];
298
317
  await Promise.all(authCandidates.map(async (p) => {
@@ -304,7 +323,10 @@ export async function buildQuotaStatusReport(params) {
304
323
  // ignore missing/unreadable
305
324
  }
306
325
  }));
307
- lines.push(`- auth.json: preferred=${getAuthPath()} present=${joinOrNone(authPresent)} candidates=${joinOrNone(authCandidates)}`);
326
+ pathsRows.push({
327
+ key: "auth.json",
328
+ value: `preferred=${getAuthPath()} present=${joinOrNone(authPresent)} candidates=${joinOrNone(authCandidates)}`,
329
+ });
308
330
  const authData = await readAuthFileCached({ maxAgeMs: 5_000 });
309
331
  const qwenAuthConfigured = hasQwenOAuthAuth(authData);
310
332
  const qwenLocalPlan = resolveQwenLocalPlan(authData);
@@ -317,55 +339,129 @@ export async function buildQuotaStatusReport(params) {
317
339
  maxAgeMs: DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS,
318
340
  fallbackTier: params.alibabaCodingPlanTier,
319
341
  });
320
- lines.push(`- qwen oauth auth configured: ${qwenAuthConfigured ? "true" : "false"}`);
321
- lines.push(`- qwen_oauth_source: ${qwenLocalPlan.state === "qwen_free" ? qwenLocalPlan.sourceKey : "(none)"}`);
322
- lines.push(`- qwen_local_plan: ${qwenLocalPlan.state === "qwen_free" ? "qwen-code/free" : "(none)"}`);
323
- lines.push(`- alibaba auth configured: ${alibabaAuthDiagnostics.state === "none" ? "false" : "true"}`);
324
- lines.push(`- alibaba_api_key_source: ${alibabaAuthDiagnostics.source ?? "(none)"}`);
325
- lines.push(`- alibaba_api_key_checked_paths: ${joinOrNone(alibabaAuthDiagnostics.checkedPaths)}`);
326
- lines.push(`- alibaba_api_key_auth_paths: ${joinOrNone(alibabaAuthDiagnostics.authPaths)}`);
327
- lines.push(`- alibaba coding plan fallback tier: ${params.alibabaCodingPlanTier}`);
328
- lines.push(`- alibaba_coding_plan: ${alibabaAuthDiagnostics.state === "configured" ? alibabaAuthDiagnostics.tier : alibabaAuthDiagnostics.state === "invalid" ? "invalid" : "(none)"}`);
342
+ pathsRows.push({ key: "qwen oauth auth configured", value: qwenAuthConfigured ? "true" : "false" });
343
+ pathsRows.push({
344
+ key: "qwen_oauth_source",
345
+ value: qwenLocalPlan.state === "qwen_free" ? qwenLocalPlan.sourceKey : "(none)",
346
+ });
347
+ pathsRows.push({
348
+ key: "qwen_local_plan",
349
+ value: qwenLocalPlan.state === "qwen_free" ? "qwen-code/free" : "(none)",
350
+ });
351
+ pathsRows.push({
352
+ key: "alibaba auth configured",
353
+ value: alibabaAuthDiagnostics.state === "none" ? "false" : "true",
354
+ });
355
+ pathsRows.push({ key: "alibaba_api_key_source", value: alibabaAuthDiagnostics.source ?? "(none)" });
356
+ pathsRows.push({
357
+ key: "alibaba_api_key_checked_paths",
358
+ value: joinOrNone(alibabaAuthDiagnostics.checkedPaths),
359
+ });
360
+ pathsRows.push({
361
+ key: "alibaba_api_key_auth_paths",
362
+ value: joinOrNone(alibabaAuthDiagnostics.authPaths),
363
+ });
364
+ pathsRows.push({
365
+ key: "alibaba coding plan fallback tier",
366
+ value: params.alibabaCodingPlanTier,
367
+ });
368
+ pathsRows.push({
369
+ key: "alibaba_coding_plan",
370
+ value: alibabaAuthDiagnostics.state === "configured"
371
+ ? alibabaAuthDiagnostics.tier
372
+ : alibabaAuthDiagnostics.state === "invalid"
373
+ ? "invalid"
374
+ : "(none)",
375
+ });
329
376
  if (alibabaAuthDiagnostics.state === "invalid") {
330
- lines.push(`- alibaba_auth_error: ${sanitizeDisplayText(alibabaAuthDiagnostics.error)}`);
377
+ pathsRows.push({
378
+ key: "alibaba_auth_error",
379
+ value: sanitizeDisplayText(alibabaAuthDiagnostics.error),
380
+ });
331
381
  }
332
- lines.push("");
333
- lines.push("openai:");
334
- lines.push(`- auth_configured: ${openaiAuth.state === "configured" ? "true" : "false"}`);
335
- lines.push(`- auth_source: ${openaiAuth.state === "configured" ? openaiAuth.sourceKey : "(none)"}`);
382
+ sections.push(createKvSection("paths", "paths:", pathsRows));
383
+ // === openai ===
384
+ const openaiRows = [
385
+ { key: "auth_configured", value: openaiAuth.state === "configured" ? "true" : "false" },
386
+ {
387
+ key: "auth_source",
388
+ value: openaiAuth.state === "configured" ? openaiAuth.sourceKey : "(none)",
389
+ },
390
+ ];
336
391
  const openaiTokenStatus = openaiAuth.state !== "configured"
337
392
  ? "(none)"
338
393
  : openaiAuth.expiresAt && openaiAuth.expiresAt < Date.now()
339
394
  ? "expired"
340
395
  : "valid";
341
- lines.push(`- token_status: ${openaiTokenStatus}`);
342
- lines.push(`- token_expires_at: ${openaiAuth.state === "configured" && openaiAuth.expiresAt ? new Date(openaiAuth.expiresAt).toISOString() : "(none)"}`);
343
- lines.push(`- account_email: ${openaiAuth.state === "configured" && openaiAuth.email ? sanitizeDisplayText(openaiAuth.email) : "(none)"}`);
344
- lines.push(`- account_id: ${openaiAuth.state === "configured" && openaiAuth.accountId ? sanitizeDisplayText(openaiAuth.accountId) : "(none)"}`);
345
- lines.push("");
346
- lines.push("anthropic:");
396
+ openaiRows.push({ key: "token_status", value: openaiTokenStatus });
397
+ openaiRows.push({
398
+ key: "token_expires_at",
399
+ value: openaiAuth.state === "configured" && openaiAuth.expiresAt
400
+ ? new Date(openaiAuth.expiresAt).toISOString()
401
+ : "(none)",
402
+ });
403
+ openaiRows.push({
404
+ key: "account_email",
405
+ value: openaiAuth.state === "configured" && openaiAuth.email
406
+ ? sanitizeDisplayText(openaiAuth.email)
407
+ : "(none)",
408
+ });
409
+ openaiRows.push({
410
+ key: "account_id",
411
+ value: openaiAuth.state === "configured" && openaiAuth.accountId
412
+ ? sanitizeDisplayText(openaiAuth.accountId)
413
+ : "(none)",
414
+ });
415
+ sections.push(createKvSection("openai", "openai:", openaiRows));
416
+ // === anthropic ===
417
+ const anthropicRows = [];
347
418
  try {
348
419
  const anthropicDiagnostics = await getAnthropicDiagnostics({
349
420
  binaryPath: params.anthropicBinaryPath,
350
421
  });
351
- lines.push(`- cli_installed: ${anthropicDiagnostics.installed ? "true" : "false"}`);
352
- lines.push(`- cli_version: ${anthropicDiagnostics.version ?? "(none)"}`);
353
- lines.push(`- auth_status: ${anthropicDiagnostics.authStatus}`);
354
- lines.push(`- quota_supported: ${anthropicDiagnostics.quotaSupported ? "true" : "false"}`);
355
- lines.push(`- quota_source: ${anthropicDiagnostics.quotaSource === "none" ? "(none)" : anthropicDiagnostics.quotaSource}`);
356
- lines.push(`- checked_commands: ${anthropicDiagnostics.checkedCommands.length > 0 ? anthropicDiagnostics.checkedCommands.join(" | ") : "(none)"}`);
422
+ anthropicRows.push({
423
+ key: "cli_installed",
424
+ value: anthropicDiagnostics.installed ? "true" : "false",
425
+ });
426
+ anthropicRows.push({ key: "cli_version", value: anthropicDiagnostics.version ?? "(none)" });
427
+ anthropicRows.push({ key: "auth_status", value: anthropicDiagnostics.authStatus });
428
+ anthropicRows.push({
429
+ key: "quota_supported",
430
+ value: anthropicDiagnostics.quotaSupported ? "true" : "false",
431
+ });
432
+ anthropicRows.push({
433
+ key: "quota_source",
434
+ value: anthropicDiagnostics.quotaSource === "none" ? "(none)" : anthropicDiagnostics.quotaSource,
435
+ });
436
+ anthropicRows.push({
437
+ key: "checked_commands",
438
+ value: anthropicDiagnostics.checkedCommands.length > 0
439
+ ? anthropicDiagnostics.checkedCommands.join(" | ")
440
+ : "(none)",
441
+ });
357
442
  if (anthropicDiagnostics.message) {
358
- lines.push(`- message: ${anthropicDiagnostics.message}`);
443
+ anthropicRows.push({ key: "message", value: anthropicDiagnostics.message });
359
444
  }
360
445
  if (anthropicDiagnostics.quotaSupported && anthropicDiagnostics.quota) {
361
- lines.push(`- five_hour_remaining: ${anthropicDiagnostics.quota.five_hour.percentRemaining}% reset_at=${anthropicDiagnostics.quota.five_hour.resetTimeIso ?? "(none)"}`);
362
- lines.push(`- seven_day_remaining: ${anthropicDiagnostics.quota.seven_day.percentRemaining}% reset_at=${anthropicDiagnostics.quota.seven_day.resetTimeIso ?? "(none)"}`);
446
+ anthropicRows.push({
447
+ key: "five_hour_remaining",
448
+ value: `${anthropicDiagnostics.quota.five_hour.percentRemaining}% reset_at=${anthropicDiagnostics.quota.five_hour.resetTimeIso ?? "(none)"}`,
449
+ });
450
+ anthropicRows.push({
451
+ key: "seven_day_remaining",
452
+ value: `${anthropicDiagnostics.quota.seven_day.percentRemaining}% reset_at=${anthropicDiagnostics.quota.seven_day.resetTimeIso ?? "(none)"}`,
453
+ });
363
454
  }
364
455
  }
365
456
  catch (err) {
366
- lines.push("- cli_installed: false");
367
- lines.push(`- message: failed to probe Claude CLI${err ? `: ${sanitizeDisplayText(err instanceof Error ? err.message : String(err))}` : ""}`);
457
+ anthropicRows.push({ key: "cli_installed", value: "false" });
458
+ anthropicRows.push({
459
+ key: "message",
460
+ value: `failed to probe Claude CLI${err ? `: ${sanitizeDisplayText(err instanceof Error ? err.message : String(err))}` : ""}`,
461
+ });
368
462
  }
463
+ sections.push(createKvSection("anthropic", "anthropic:", anthropicRows));
464
+ // === cursor ===
369
465
  const cursorPlanLabel = getCursorPlanDisplayName(params.cursorPlan);
370
466
  const cursorIncludedApiUsd = getEffectiveCursorIncludedApiUsd({
371
467
  plan: params.cursorPlan,
@@ -373,54 +469,83 @@ export async function buildQuotaStatusReport(params) {
373
469
  });
374
470
  const cursorAuth = await inspectCursorAuthPresence();
375
471
  const cursorIntegration = await inspectCursorOpenCodeIntegration();
376
- lines.push("");
377
- lines.push("cursor:");
378
- lines.push(`- plan: ${cursorPlanLabel ?? "none"}`);
379
- lines.push(`- included_api_usd: ${typeof cursorIncludedApiUsd === "number" ? fmtUsdAmount(cursorIncludedApiUsd) : "(none)"}`);
380
- lines.push(`- billing_cycle_start_day: ${typeof params.cursorBillingCycleStartDay === "number" ? params.cursorBillingCycleStartDay : "(calendar month)"}`);
381
- lines.push(`- auth_state: ${cursorAuth.state}`);
382
- lines.push(`- auth_selected_path: ${cursorAuth.selectedPath ?? "(none)"}`);
383
- lines.push(`- auth_present_paths: ${joinOrNone(cursorAuth.presentPaths)}`);
384
- lines.push(`- auth_candidate_paths: ${joinOrNone(cursorAuth.candidatePaths)}`);
472
+ const cursorRows = [
473
+ { key: "plan", value: cursorPlanLabel ?? "none" },
474
+ {
475
+ key: "included_api_usd",
476
+ value: typeof cursorIncludedApiUsd === "number" ? fmtUsdAmount(cursorIncludedApiUsd) : "(none)",
477
+ },
478
+ {
479
+ key: "billing_cycle_start_day",
480
+ value: typeof params.cursorBillingCycleStartDay === "number"
481
+ ? String(params.cursorBillingCycleStartDay)
482
+ : "(calendar month)",
483
+ },
484
+ { key: "auth_state", value: cursorAuth.state },
485
+ { key: "auth_selected_path", value: cursorAuth.selectedPath ?? "(none)" },
486
+ { key: "auth_present_paths", value: joinOrNone(cursorAuth.presentPaths) },
487
+ { key: "auth_candidate_paths", value: joinOrNone(cursorAuth.candidatePaths) },
488
+ ];
385
489
  if (cursorAuth.error) {
386
- lines.push(`- auth_error: ${cursorAuth.error}`);
490
+ cursorRows.push({ key: "auth_error", value: cursorAuth.error });
387
491
  }
388
- lines.push(`- plugin_enabled: ${cursorIntegration.pluginEnabled ? "true" : "false"}`);
389
- lines.push(`- canonical_plugin_package: ${CURSOR_CANONICAL_PLUGIN_PACKAGE}`);
390
- lines.push(`- provider_configured: ${cursorIntegration.providerConfigured ? "true" : "false"}`);
391
- lines.push(`- config_matches: ${joinOrNone(cursorIntegration.matchedPaths)}`);
392
- lines.push(`- config_checked_paths: ${joinOrNone(cursorIntegration.checkedPaths)}`);
492
+ cursorRows.push({ key: "plugin_enabled", value: cursorIntegration.pluginEnabled ? "true" : "false" });
493
+ cursorRows.push({ key: "canonical_plugin_package", value: CURSOR_CANONICAL_PLUGIN_PACKAGE });
494
+ cursorRows.push({
495
+ key: "provider_configured",
496
+ value: cursorIntegration.providerConfigured ? "true" : "false",
497
+ });
498
+ cursorRows.push({ key: "config_matches", value: joinOrNone(cursorIntegration.matchedPaths) });
499
+ cursorRows.push({ key: "config_checked_paths", value: joinOrNone(cursorIntegration.checkedPaths) });
393
500
  try {
394
501
  const cursorUsage = await getCurrentCursorUsageSummary({
395
502
  billingCycleStartDay: params.cursorBillingCycleStartDay,
396
503
  });
397
- lines.push(`- cycle_source: ${cursorUsage.window.source}`);
398
- lines.push(`- cycle_reset_at: ${cursorUsage.window.resetTimeIso}`);
399
- lines.push(`- api_usage: ${fmtUsdAmount(cursorUsage.api.costUsd)} across ${fmtInt(cursorUsage.api.messageCount)} messages`);
400
- lines.push(`- auto_composer_usage: ${fmtUsdAmount(cursorUsage.autoComposer.costUsd)} across ${fmtInt(cursorUsage.autoComposer.messageCount)} messages`);
401
- lines.push(`- total_cursor_usage: ${fmtUsdAmount(cursorUsage.total.costUsd)} across ${fmtInt(cursorUsage.total.messageCount)} messages`);
402
- lines.push(`- unknown_cursor_models: ${fmtInt(cursorUsage.unknownModels.length)}`);
504
+ cursorRows.push({ key: "cycle_source", value: cursorUsage.window.source });
505
+ cursorRows.push({ key: "cycle_reset_at", value: cursorUsage.window.resetTimeIso });
506
+ cursorRows.push({
507
+ key: "api_usage",
508
+ value: `${fmtUsdAmount(cursorUsage.api.costUsd)} across ${fmtInt(cursorUsage.api.messageCount)} messages`,
509
+ });
510
+ cursorRows.push({
511
+ key: "auto_composer_usage",
512
+ value: `${fmtUsdAmount(cursorUsage.autoComposer.costUsd)} across ${fmtInt(cursorUsage.autoComposer.messageCount)} messages`,
513
+ });
514
+ cursorRows.push({
515
+ key: "total_cursor_usage",
516
+ value: `${fmtUsdAmount(cursorUsage.total.costUsd)} across ${fmtInt(cursorUsage.total.messageCount)} messages`,
517
+ });
518
+ cursorRows.push({ key: "unknown_cursor_models", value: fmtInt(cursorUsage.unknownModels.length) });
403
519
  }
404
520
  catch (err) {
405
521
  const msg = err instanceof Error ? err.message : String(err);
406
- lines.push(`- usage_error: ${msg}`);
522
+ cursorRows.push({ key: "usage_error", value: msg });
407
523
  }
408
524
  const qwenLocalQuotaPath = getQwenLocalQuotaPath();
409
525
  const qwenLocalQuotaExists = await pathExists(qwenLocalQuotaPath);
410
- lines.push(`- qwen free local quota: path=${qwenLocalQuotaPath} exists=${qwenLocalQuotaExists ? "true" : "false"}`);
526
+ cursorRows.push({
527
+ key: "qwen free local quota",
528
+ value: `path=${qwenLocalQuotaPath} exists=${qwenLocalQuotaExists ? "true" : "false"}`,
529
+ });
411
530
  try {
412
531
  const qwenState = await readQwenLocalQuotaState();
413
532
  const qwenQuota = computeQwenQuota({ state: qwenState });
414
533
  const qwenUsageSuffix = qwenLocalQuotaExists ? "" : " (default state)";
415
- lines.push(`- qwen free local usage: daily=${qwenQuota.day.used}/${qwenQuota.day.limit} rpm=${qwenQuota.rpm.used}/${qwenQuota.rpm.limit}${qwenUsageSuffix}`);
534
+ cursorRows.push({
535
+ key: "qwen free local usage",
536
+ value: `daily=${qwenQuota.day.used}/${qwenQuota.day.limit} rpm=${qwenQuota.rpm.used}/${qwenQuota.rpm.limit}${qwenUsageSuffix}`,
537
+ });
416
538
  }
417
539
  catch (err) {
418
540
  const msg = err instanceof Error ? err.message : String(err);
419
- lines.push(`- qwen free local usage: error (${msg})`);
541
+ cursorRows.push({ key: "qwen free local usage", value: `error (${msg})` });
420
542
  }
421
543
  const alibabaLocalQuotaPath = getAlibabaCodingPlanQuotaPath();
422
544
  const alibabaLocalQuotaExists = await pathExists(alibabaLocalQuotaPath);
423
- lines.push(`- alibaba coding plan local quota: path=${alibabaLocalQuotaPath} exists=${alibabaLocalQuotaExists ? "true" : "false"}`);
545
+ cursorRows.push({
546
+ key: "alibaba coding plan local quota",
547
+ value: `path=${alibabaLocalQuotaPath} exists=${alibabaLocalQuotaExists ? "true" : "false"}`,
548
+ });
424
549
  if (alibabaCodingPlanAuth.state === "configured") {
425
550
  try {
426
551
  const alibabaState = await readAlibabaCodingPlanQuotaState();
@@ -429,250 +554,366 @@ export async function buildQuotaStatusReport(params) {
429
554
  tier: alibabaCodingPlanAuth.tier,
430
555
  });
431
556
  const alibabaUsageSuffix = alibabaLocalQuotaExists ? "" : " (default state)";
432
- lines.push(`- alibaba coding plan usage: tier=${alibabaCodingPlanAuth.tier} 5h=${alibabaQuota.fiveHour.used}/${alibabaQuota.fiveHour.limit} weekly=${alibabaQuota.weekly.used}/${alibabaQuota.weekly.limit} monthly=${alibabaQuota.monthly.used}/${alibabaQuota.monthly.limit}${alibabaUsageSuffix}`);
557
+ cursorRows.push({
558
+ key: "alibaba coding plan usage",
559
+ value: `tier=${alibabaCodingPlanAuth.tier} 5h=${alibabaQuota.fiveHour.used}/${alibabaQuota.fiveHour.limit} weekly=${alibabaQuota.weekly.used}/${alibabaQuota.weekly.limit} monthly=${alibabaQuota.monthly.used}/${alibabaQuota.monthly.limit}${alibabaUsageSuffix}`,
560
+ });
433
561
  }
434
562
  catch (err) {
435
563
  const msg = err instanceof Error ? err.message : String(err);
436
- lines.push(`- alibaba coding plan usage: error (${msg})`);
564
+ cursorRows.push({ key: "alibaba coding plan usage", value: `error (${msg})` });
437
565
  }
438
566
  }
439
567
  else if (alibabaCodingPlanAuth.state === "invalid") {
440
- lines.push(`- alibaba coding plan error: ${alibabaCodingPlanAuth.error}`);
568
+ cursorRows.push({ key: "alibaba coding plan error", value: alibabaCodingPlanAuth.error });
441
569
  }
442
- lines.push("");
443
- lines.push("minimax:");
570
+ sections.push(createKvSection("cursor", "cursor:", cursorRows));
571
+ // === minimax ===
572
+ const minimaxRows = [];
444
573
  const minimaxAuth = await getMiniMaxAuthDiagnostics({
445
574
  maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
446
575
  });
447
- lines.push(`- auth_state: ${minimaxAuth.state}`);
448
- lines.push(`- api_key_configured: ${minimaxAuth.state === "configured" ? "true" : "false"}`);
449
- lines.push(`- api_key_source: ${minimaxAuth.source ?? "(none)"}`);
450
- lines.push(`- api_key_checked_paths: ${joinOrNone(minimaxAuth.checkedPaths)}`);
451
- lines.push(`- api_key_auth_paths: ${joinOrNone(minimaxAuth.authPaths)}`);
576
+ minimaxRows.push({ key: "auth_state", value: minimaxAuth.state });
577
+ minimaxRows.push({
578
+ key: "api_key_configured",
579
+ value: minimaxAuth.state === "configured" ? "true" : "false",
580
+ });
581
+ minimaxRows.push({ key: "api_key_source", value: minimaxAuth.source ?? "(none)" });
582
+ minimaxRows.push({ key: "api_key_checked_paths", value: joinOrNone(minimaxAuth.checkedPaths) });
583
+ minimaxRows.push({ key: "api_key_auth_paths", value: joinOrNone(minimaxAuth.authPaths) });
452
584
  if (minimaxAuth.state === "invalid") {
453
- lines.push(`- auth_error: ${sanitizeDisplayText(minimaxAuth.error)}`);
585
+ minimaxRows.push({ key: "auth_error", value: sanitizeDisplayText(minimaxAuth.error) });
454
586
  }
455
587
  if (minimaxAuth.state === "configured") {
456
588
  const resolvedMiniMaxAuth = await resolveMiniMaxAuthCached({
457
589
  maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
458
590
  });
459
591
  if (resolvedMiniMaxAuth.state !== "configured") {
460
- lines.push("- live_fetch_error: MiniMax API key became unavailable before fetch");
592
+ minimaxRows.push({
593
+ key: "live_fetch_error",
594
+ value: "MiniMax API key became unavailable before fetch",
595
+ });
461
596
  }
462
597
  else {
463
598
  const minimaxQuota = await queryMiniMaxQuota(resolvedMiniMaxAuth.apiKey);
464
599
  if (!minimaxQuota.success) {
465
- lines.push(`- live_fetch_error: ${minimaxQuota.error}`);
600
+ minimaxRows.push({ key: "live_fetch_error", value: minimaxQuota.error });
466
601
  }
467
602
  else {
468
603
  const fiveHourEntry = minimaxQuota.entries.find((entry) => entry.window === "five_hour");
469
604
  const weeklyEntry = minimaxQuota.entries.find((entry) => entry.window === "weekly");
470
605
  if (fiveHourEntry) {
471
- lines.push(`- five_hour_usage: ${fiveHourEntry.right ?? "(none)"} percent_remaining=${fiveHourEntry.percentRemaining} reset_at=${fiveHourEntry.resetTimeIso ?? "(none)"}`);
606
+ minimaxRows.push({
607
+ key: "five_hour_usage",
608
+ value: `${fiveHourEntry.right ?? "(none)"} percent_remaining=${fiveHourEntry.percentRemaining} reset_at=${fiveHourEntry.resetTimeIso ?? "(none)"}`,
609
+ });
472
610
  }
473
611
  if (weeklyEntry) {
474
- lines.push(`- weekly_usage: ${weeklyEntry.right ?? "(none)"} percent_remaining=${weeklyEntry.percentRemaining} reset_at=${weeklyEntry.resetTimeIso ?? "(none)"}`);
612
+ minimaxRows.push({
613
+ key: "weekly_usage",
614
+ value: `${weeklyEntry.right ?? "(none)"} percent_remaining=${weeklyEntry.percentRemaining} reset_at=${weeklyEntry.resetTimeIso ?? "(none)"}`,
615
+ });
475
616
  }
476
617
  if (!fiveHourEntry && !weeklyEntry) {
477
- lines.push("- live_state: no reportable MiniMax Coding Plan quota");
618
+ minimaxRows.push({ key: "live_state", value: "no reportable MiniMax Coding Plan quota" });
478
619
  }
479
620
  }
480
621
  }
481
622
  }
482
- lines.push("");
483
- lines.push("opencode_go:");
623
+ sections.push(createKvSection("minimax", "minimax:", minimaxRows));
624
+ // === kimi ===
625
+ const kimiRows = [];
626
+ const kimiAuth = await getKimiAuthDiagnostics({
627
+ maxAgeMs: DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS,
628
+ });
629
+ kimiRows.push({ key: "auth_state", value: kimiAuth.state });
630
+ kimiRows.push({
631
+ key: "api_key_configured",
632
+ value: kimiAuth.state === "configured" ? "true" : "false",
633
+ });
634
+ kimiRows.push({ key: "api_key_source", value: kimiAuth.source ?? "(none)" });
635
+ kimiRows.push({ key: "api_key_checked_paths", value: joinOrNone(kimiAuth.checkedPaths) });
636
+ kimiRows.push({ key: "api_key_auth_paths", value: joinOrNone(kimiAuth.authPaths) });
637
+ if (kimiAuth.state === "invalid") {
638
+ kimiRows.push({ key: "auth_error", value: sanitizeDisplayText(kimiAuth.error) });
639
+ }
640
+ if (kimiAuth.state === "configured") {
641
+ const kimiQuota = await queryKimiQuota();
642
+ if (!kimiQuota) {
643
+ kimiRows.push({
644
+ key: "live_fetch_error",
645
+ value: "Kimi API key became unavailable before fetch",
646
+ });
647
+ }
648
+ else if (!kimiQuota.success) {
649
+ kimiRows.push({ key: "live_fetch_error", value: kimiQuota.error });
650
+ }
651
+ else {
652
+ for (const window of kimiQuota.windows) {
653
+ kimiRows.push({
654
+ key: window.label.toLowerCase().replace(/\s+/g, "_"),
655
+ value: `used=${window.used}/${window.limit} percent_remaining=${window.percentRemaining} reset_at=${window.resetTimeIso ?? "(none)"}`,
656
+ });
657
+ }
658
+ if (kimiQuota.windows.length === 0) {
659
+ kimiRows.push({ key: "live_state", value: "no reportable Kimi quota" });
660
+ }
661
+ }
662
+ }
663
+ sections.push(createKvSection("kimi", "kimi:", kimiRows));
664
+ // === opencode_go ===
665
+ const openCodeGoRows = [];
484
666
  const openCodeGoDiag = await getOpenCodeGoConfigDiagnostics();
485
- lines.push(`- config_state: ${openCodeGoDiag.state}`);
486
- lines.push(`- config_source: ${openCodeGoDiag.source ?? "(none)"}`);
667
+ openCodeGoRows.push({ key: "config_state", value: openCodeGoDiag.state });
668
+ openCodeGoRows.push({ key: "config_source", value: openCodeGoDiag.source ?? "(none)" });
487
669
  if (openCodeGoDiag.missing) {
488
- lines.push(`- config_missing: ${openCodeGoDiag.missing}`);
670
+ openCodeGoRows.push({ key: "config_missing", value: openCodeGoDiag.missing });
489
671
  }
490
672
  if (openCodeGoDiag.error) {
491
- lines.push(`- config_error: ${sanitizeDisplayText(openCodeGoDiag.error)}`);
673
+ openCodeGoRows.push({ key: "config_error", value: sanitizeDisplayText(openCodeGoDiag.error) });
492
674
  }
493
- lines.push(`- config_checked_paths: ${joinOrNone(openCodeGoDiag.checkedPaths)}`);
675
+ openCodeGoRows.push({ key: "config_checked_paths", value: joinOrNone(openCodeGoDiag.checkedPaths) });
494
676
  if (openCodeGoDiag.state === "configured") {
495
677
  const openCodeGoConfig = await resolveOpenCodeGoConfigCached({
496
678
  maxAgeMs: DEFAULT_OPENCODE_GO_CONFIG_CACHE_MAX_AGE_MS,
497
679
  });
498
680
  if (openCodeGoConfig.state !== "configured") {
499
- lines.push("- live_fetch_error: OpenCode Go config became unavailable before fetch");
681
+ openCodeGoRows.push({
682
+ key: "live_fetch_error",
683
+ value: "OpenCode Go config became unavailable before fetch",
684
+ });
500
685
  }
501
686
  else {
502
687
  const openCodeGoQuota = await queryOpenCodeGoQuota(openCodeGoConfig.config.workspaceId, openCodeGoConfig.config.authCookie);
503
688
  if (!openCodeGoQuota) {
504
- lines.push("- live_fetch_error: OpenCode Go returned null");
689
+ openCodeGoRows.push({ key: "live_fetch_error", value: "OpenCode Go returned null" });
505
690
  }
506
691
  else if (!openCodeGoQuota.success) {
507
- lines.push(`- live_fetch_error: ${openCodeGoQuota.error}`);
692
+ openCodeGoRows.push({ key: "live_fetch_error", value: openCodeGoQuota.error });
508
693
  }
509
694
  else {
510
- lines.push(`- monthly_usage: percent_used=${openCodeGoQuota.usagePercent} percent_remaining=${openCodeGoQuota.percentRemaining} reset_in_sec=${openCodeGoQuota.resetInSec} reset_at=${openCodeGoQuota.resetTimeIso}`);
695
+ openCodeGoRows.push({
696
+ key: "monthly_usage",
697
+ value: `percent_used=${openCodeGoQuota.usagePercent} percent_remaining=${openCodeGoQuota.percentRemaining} reset_in_sec=${openCodeGoQuota.resetInSec} reset_at=${openCodeGoQuota.resetTimeIso}`,
698
+ });
511
699
  }
512
700
  }
513
701
  }
514
- lines.push("");
515
- lines.push("zai:");
702
+ sections.push(createKvSection("opencode_go", "opencode_go:", openCodeGoRows));
703
+ // === zai ===
704
+ const zaiRows = [];
516
705
  const zaiAuth = await getZaiAuthDiagnostics({
517
706
  maxAgeMs: DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS,
518
707
  });
519
- lines.push(`- auth_state: ${zaiAuth.state}`);
520
- lines.push(`- api_key_configured: ${zaiAuth.state === "configured" ? "true" : "false"}`);
521
- lines.push(`- api_key_source: ${zaiAuth.source ?? "(none)"}`);
522
- lines.push(`- api_key_checked_paths: ${joinOrNone(zaiAuth.checkedPaths)}`);
523
- lines.push(`- api_key_auth_paths: ${joinOrNone(zaiAuth.authPaths)}`);
708
+ zaiRows.push({ key: "auth_state", value: zaiAuth.state });
709
+ zaiRows.push({
710
+ key: "api_key_configured",
711
+ value: zaiAuth.state === "configured" ? "true" : "false",
712
+ });
713
+ zaiRows.push({ key: "api_key_source", value: zaiAuth.source ?? "(none)" });
714
+ zaiRows.push({ key: "api_key_checked_paths", value: joinOrNone(zaiAuth.checkedPaths) });
715
+ zaiRows.push({ key: "api_key_auth_paths", value: joinOrNone(zaiAuth.authPaths) });
524
716
  if (zaiAuth.state === "invalid") {
525
- lines.push(`- auth_error: ${sanitizeDisplayText(zaiAuth.error)}`);
717
+ zaiRows.push({ key: "auth_error", value: sanitizeDisplayText(zaiAuth.error) });
526
718
  }
527
719
  if (zaiAuth.state === "configured") {
528
720
  const zaiQuota = await queryZaiQuota();
529
721
  if (!zaiQuota) {
530
- lines.push("- live_fetch_error: Z.ai API key became unavailable before fetch");
722
+ zaiRows.push({ key: "live_fetch_error", value: "Z.ai API key became unavailable before fetch" });
531
723
  }
532
724
  else if (!zaiQuota.success) {
533
- lines.push(`- live_fetch_error: ${zaiQuota.error}`);
725
+ zaiRows.push({ key: "live_fetch_error", value: zaiQuota.error });
534
726
  }
535
727
  else {
536
728
  if (zaiQuota.windows.fiveHour) {
537
- lines.push(`- five_hour_remaining: ${zaiQuota.windows.fiveHour.percentRemaining}% reset_at=${zaiQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`);
729
+ zaiRows.push({
730
+ key: "five_hour_remaining",
731
+ value: `${zaiQuota.windows.fiveHour.percentRemaining}% reset_at=${zaiQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`,
732
+ });
538
733
  }
539
734
  if (zaiQuota.windows.weekly) {
540
- lines.push(`- weekly_remaining: ${zaiQuota.windows.weekly.percentRemaining}% reset_at=${zaiQuota.windows.weekly.resetTimeIso ?? "(none)"}`);
735
+ zaiRows.push({
736
+ key: "weekly_remaining",
737
+ value: `${zaiQuota.windows.weekly.percentRemaining}% reset_at=${zaiQuota.windows.weekly.resetTimeIso ?? "(none)"}`,
738
+ });
541
739
  }
542
740
  if (zaiQuota.windows.mcp) {
543
- lines.push(`- mcp_remaining: ${zaiQuota.windows.mcp.percentRemaining}% reset_at=${zaiQuota.windows.mcp.resetTimeIso ?? "(none)"}`);
741
+ zaiRows.push({
742
+ key: "mcp_remaining",
743
+ value: `${zaiQuota.windows.mcp.percentRemaining}% reset_at=${zaiQuota.windows.mcp.resetTimeIso ?? "(none)"}`,
744
+ });
544
745
  }
545
746
  if (!zaiQuota.windows.fiveHour && !zaiQuota.windows.weekly && !zaiQuota.windows.mcp) {
546
- lines.push("- live_state: no reportable Z.ai quota windows");
747
+ zaiRows.push({ key: "live_state", value: "no reportable Z.ai quota windows" });
547
748
  }
548
749
  }
549
750
  }
550
- const firmwareDiag = await readBasicApiKeyDiagnostics(getFirmwareKeyDiagnostics);
551
- appendBasicApiKeySection({
552
- lines,
553
- section: "firmware:",
554
- label: "firmware api key",
555
- diagnostics: firmwareDiag,
556
- });
751
+ sections.push(createKvSection("zai", "zai:", zaiRows));
752
+ // === simple API key sections ===
753
+ const syntheticDiag = await readBasicApiKeyDiagnostics(getSyntheticKeyDiagnostics);
754
+ sections.push(buildBasicApiKeySection({
755
+ id: "synthetic",
756
+ section: "synthetic:",
757
+ label: "synthetic api key",
758
+ diagnostics: syntheticDiag,
759
+ }));
557
760
  const chutesDiag = await readBasicApiKeyDiagnostics(getChutesKeyDiagnostics);
558
- appendBasicApiKeySection({
559
- lines,
761
+ sections.push(buildBasicApiKeySection({
762
+ id: "chutes",
560
763
  section: "chutes:",
561
764
  label: "chutes api key",
562
765
  diagnostics: chutesDiag,
563
- });
766
+ }));
767
+ // === nanogpt ===
564
768
  const nanoGptDiag = await readNanoGptApiKeyDiagnostics(getNanoGptKeyDiagnostics);
565
- appendNanoGptApiKeySection(lines, nanoGptDiag);
769
+ const nanoGptRows = [
770
+ { key: "api_key_configured", value: nanoGptDiag.configured ? "true" : "false" },
771
+ { key: "api_key_source", value: nanoGptDiag.source ?? "(none)" },
772
+ { key: "api_key_checked_paths", value: joinOrNone(nanoGptDiag.checkedPaths) },
773
+ { key: "api_key_auth_paths", value: joinOrNone(nanoGptDiag.authPaths) },
774
+ ];
566
775
  if (nanoGptDiag.configured) {
567
776
  try {
568
777
  const nanoGptQuota = await queryNanoGptQuota();
569
778
  if (!nanoGptQuota) {
570
- lines.push("- live_fetch_error: NanoGPT API key became unavailable before fetch");
779
+ nanoGptRows.push({
780
+ key: "live_fetch_error",
781
+ value: "NanoGPT API key became unavailable before fetch",
782
+ });
571
783
  }
572
784
  else if (!nanoGptQuota.success) {
573
- lines.push(`- live_fetch_error: ${nanoGptQuota.error}`);
785
+ nanoGptRows.push({ key: "live_fetch_error", value: nanoGptQuota.error });
574
786
  }
575
787
  else {
576
788
  if (nanoGptQuota.subscription) {
577
- lines.push(`- subscription_active: ${nanoGptQuota.subscription.active ? "true" : "false"}`);
578
- lines.push(`- subscription_state: ${nanoGptQuota.subscription.state}`);
579
- lines.push(`- enforce_daily_limit: ${nanoGptQuota.subscription.enforceDailyLimit ? "true" : "false"}`);
789
+ nanoGptRows.push({
790
+ key: "subscription_active",
791
+ value: nanoGptQuota.subscription.active ? "true" : "false",
792
+ });
793
+ nanoGptRows.push({ key: "subscription_state", value: nanoGptQuota.subscription.state });
794
+ nanoGptRows.push({
795
+ key: "enforce_daily_limit",
796
+ value: nanoGptQuota.subscription.enforceDailyLimit ? "true" : "false",
797
+ });
580
798
  if (nanoGptQuota.subscription.daily) {
581
799
  const daily = nanoGptQuota.subscription.daily;
582
- lines.push(`- daily_usage: ${fmtNanoGptMetric(daily.used)}/${fmtNanoGptMetric(daily.limit)} remaining=${fmtNanoGptMetric(daily.remaining)} percent_remaining=${daily.percentRemaining} reset_at=${daily.resetTimeIso ?? "(none)"}`);
800
+ nanoGptRows.push({
801
+ key: "daily_usage",
802
+ value: `${fmtNanoGptMetric(daily.used)}/${fmtNanoGptMetric(daily.limit)} remaining=${fmtNanoGptMetric(daily.remaining)} percent_remaining=${daily.percentRemaining} reset_at=${daily.resetTimeIso ?? "(none)"}`,
803
+ });
583
804
  }
584
805
  if (nanoGptQuota.subscription.monthly) {
585
806
  const monthly = nanoGptQuota.subscription.monthly;
586
- lines.push(`- monthly_usage: ${fmtNanoGptMetric(monthly.used)}/${fmtNanoGptMetric(monthly.limit)} remaining=${fmtNanoGptMetric(monthly.remaining)} percent_remaining=${monthly.percentRemaining} reset_at=${monthly.resetTimeIso ?? "(none)"}`);
807
+ nanoGptRows.push({
808
+ key: "monthly_usage",
809
+ value: `${fmtNanoGptMetric(monthly.used)}/${fmtNanoGptMetric(monthly.limit)} remaining=${fmtNanoGptMetric(monthly.remaining)} percent_remaining=${monthly.percentRemaining} reset_at=${monthly.resetTimeIso ?? "(none)"}`,
810
+ });
587
811
  }
588
- lines.push(`- billing_period_end: ${nanoGptQuota.subscription.currentPeriodEndIso ?? "(none)"}`);
812
+ nanoGptRows.push({
813
+ key: "billing_period_end",
814
+ value: nanoGptQuota.subscription.currentPeriodEndIso ?? "(none)",
815
+ });
589
816
  if (nanoGptQuota.subscription.graceUntilIso) {
590
- lines.push(`- grace_until: ${nanoGptQuota.subscription.graceUntilIso}`);
817
+ nanoGptRows.push({ key: "grace_until", value: nanoGptQuota.subscription.graceUntilIso });
591
818
  }
592
819
  }
593
- lines.push(`- balance_usd: ${typeof nanoGptQuota.balance?.usdBalance === "number" ? fmtUsdAmount(nanoGptQuota.balance.usdBalance) : "(none)"}`);
594
- lines.push(`- balance_nano: ${nanoGptQuota.balance?.nanoBalanceRaw ?? "(none)"}`);
820
+ nanoGptRows.push({
821
+ key: "balance_usd",
822
+ value: typeof nanoGptQuota.balance?.usdBalance === "number"
823
+ ? fmtUsdAmount(nanoGptQuota.balance.usdBalance)
824
+ : "(none)",
825
+ });
826
+ nanoGptRows.push({ key: "balance_nano", value: nanoGptQuota.balance?.nanoBalanceRaw ?? "(none)" });
595
827
  for (const entry of nanoGptQuota.endpointErrors ?? []) {
596
- lines.push(`- live_error_${entry.endpoint}: ${entry.message}`);
828
+ nanoGptRows.push({ key: `live_error_${entry.endpoint}`, value: entry.message });
597
829
  }
598
830
  }
599
831
  }
600
832
  catch (err) {
601
833
  const msg = err instanceof Error ? err.message : String(err);
602
- lines.push(`- live_fetch_error: ${msg}`);
834
+ nanoGptRows.push({ key: "live_fetch_error", value: msg });
603
835
  }
604
836
  }
837
+ sections.push(createKvSection("nanogpt", "nanogpt:", nanoGptRows));
838
+ // === copilot auth ===
605
839
  const copilotDiag = getCopilotQuotaAuthDiagnostics(authData);
606
- lines.push("");
607
- lines.push("copilot_quota_auth:");
608
- lines.push(`- pat_state: ${copilotDiag.pat.state}`);
840
+ const copilotRows = [{ key: "pat_state", value: copilotDiag.pat.state }];
609
841
  if (copilotDiag.pat.selectedPath) {
610
- lines.push(`- pat_path: ${copilotDiag.pat.selectedPath}`);
842
+ copilotRows.push({ key: "pat_path", value: copilotDiag.pat.selectedPath });
611
843
  }
612
844
  if (copilotDiag.pat.tokenKind) {
613
- lines.push(`- pat_token_kind: ${copilotDiag.pat.tokenKind}`);
845
+ copilotRows.push({ key: "pat_token_kind", value: copilotDiag.pat.tokenKind });
614
846
  }
615
847
  if (copilotDiag.pat.config?.tier) {
616
- lines.push(`- pat_tier: ${copilotDiag.pat.config.tier}`);
848
+ copilotRows.push({ key: "pat_tier", value: copilotDiag.pat.config.tier });
617
849
  }
618
850
  if (copilotDiag.pat.config?.organization) {
619
- lines.push(`- pat_organization: ${copilotDiag.pat.config.organization}`);
851
+ copilotRows.push({ key: "pat_organization", value: copilotDiag.pat.config.organization });
620
852
  }
621
853
  if (copilotDiag.pat.config?.enterprise) {
622
- lines.push(`- pat_enterprise: ${copilotDiag.pat.config.enterprise}`);
623
- }
624
- lines.push(`- billing_mode: ${copilotDiag.billingMode}`);
625
- lines.push(`- billing_scope: ${copilotDiag.billingScope}`);
626
- lines.push(`- quota_api: ${copilotDiag.quotaApi}`);
627
- lines.push(`- billing_api_access_likely: ${copilotDiag.billingApiAccessLikely ? "true" : "false"}`);
628
- lines.push(`- remaining_totals_state: ${copilotDiag.remainingTotalsState}`);
854
+ copilotRows.push({ key: "pat_enterprise", value: copilotDiag.pat.config.enterprise });
855
+ }
856
+ copilotRows.push({ key: "billing_mode", value: copilotDiag.billingMode });
857
+ copilotRows.push({ key: "billing_scope", value: copilotDiag.billingScope });
858
+ copilotRows.push({ key: "quota_api", value: copilotDiag.quotaApi });
859
+ copilotRows.push({
860
+ key: "billing_api_access_likely",
861
+ value: copilotDiag.billingApiAccessLikely ? "true" : "false",
862
+ });
863
+ copilotRows.push({ key: "remaining_totals_state", value: copilotDiag.remainingTotalsState });
629
864
  if (copilotDiag.queryPeriod) {
630
- lines.push(`- billing_period: ${copilotDiag.queryPeriod.year}-${String(copilotDiag.queryPeriod.month).padStart(2, "0")}`);
865
+ copilotRows.push({
866
+ key: "billing_period",
867
+ value: `${copilotDiag.queryPeriod.year}-${String(copilotDiag.queryPeriod.month).padStart(2, "0")}`,
868
+ });
631
869
  }
632
870
  if (copilotDiag.usernameFilter) {
633
- lines.push(`- username_filter: ${copilotDiag.usernameFilter}`);
871
+ copilotRows.push({ key: "username_filter", value: copilotDiag.usernameFilter });
634
872
  }
635
873
  if (copilotDiag.billingMode === "organization_usage") {
636
- lines.push("- billing_usage_note: organization premium usage for the current billing period");
637
- lines.push("- remaining_quota_note: valid PAT access can query billing usage, but pooled org usage does not provide a true per-user remaining quota");
874
+ copilotRows.push({
875
+ key: "billing_usage_note",
876
+ value: "organization premium usage for the current billing period",
877
+ });
878
+ copilotRows.push({
879
+ key: "remaining_quota_note",
880
+ value: "valid PAT access can query billing usage, but pooled org usage does not provide a true per-user remaining quota",
881
+ });
638
882
  }
639
883
  if (copilotDiag.billingMode === "enterprise_usage") {
640
- lines.push("- billing_usage_note: enterprise premium usage for the current billing period");
641
- lines.push("- remaining_quota_note: valid enterprise billing access can query pooled enterprise usage, but it does not provide a true per-user remaining quota");
884
+ copilotRows.push({
885
+ key: "billing_usage_note",
886
+ value: "enterprise premium usage for the current billing period",
887
+ });
888
+ copilotRows.push({
889
+ key: "remaining_quota_note",
890
+ value: "valid enterprise billing access can query pooled enterprise usage, but it does not provide a true per-user remaining quota",
891
+ });
642
892
  }
643
893
  if (copilotDiag.billingTargetError) {
644
- lines.push(`- billing_target_error: ${copilotDiag.billingTargetError}`);
894
+ copilotRows.push({ key: "billing_target_error", value: copilotDiag.billingTargetError });
645
895
  }
646
896
  if (copilotDiag.tokenCompatibilityError) {
647
- lines.push(`- token_compatibility_error: ${copilotDiag.tokenCompatibilityError}`);
897
+ copilotRows.push({ key: "token_compatibility_error", value: copilotDiag.tokenCompatibilityError });
648
898
  }
649
899
  if (copilotDiag.pat.error) {
650
- lines.push(`- pat_error: ${copilotDiag.pat.error}`);
900
+ copilotRows.push({ key: "pat_error", value: copilotDiag.pat.error });
651
901
  }
652
- lines.push(`- pat_checked_paths: ${copilotDiag.pat.checkedPaths.length ? copilotDiag.pat.checkedPaths.join(" | ") : "(none)"}`);
653
- lines.push(`- oauth_configured: ${copilotDiag.oauth.configured ? "true" : "false"} key=${copilotDiag.oauth.keyName ?? "(none)"} refresh=${copilotDiag.oauth.hasRefreshToken ? "true" : "false"} access=${copilotDiag.oauth.hasAccessToken ? "true" : "false"}`);
654
- lines.push(`- effective_source: ${copilotDiag.effectiveSource}`);
655
- lines.push(`- override: ${copilotDiag.override}`);
902
+ copilotRows.push({
903
+ key: "pat_checked_paths",
904
+ value: copilotDiag.pat.checkedPaths.length ? copilotDiag.pat.checkedPaths.join(" | ") : "(none)",
905
+ });
906
+ copilotRows.push({
907
+ key: "oauth_configured",
908
+ value: `${copilotDiag.oauth.configured ? "true" : "false"} key=${copilotDiag.oauth.keyName ?? "(none)"} refresh=${copilotDiag.oauth.hasRefreshToken ? "true" : "false"} access=${copilotDiag.oauth.hasAccessToken ? "true" : "false"}`,
909
+ });
910
+ copilotRows.push({ key: "effective_source", value: copilotDiag.effectiveSource });
911
+ copilotRows.push({ key: "override", value: copilotDiag.override });
912
+ sections.push(createKvSection("copilot_quota_auth", "copilot_quota_auth:", copilotRows));
913
+ // === google antigravity + db path ===
656
914
  const googleTokenCachePath = getGoogleTokenCachePath();
657
915
  const googleAuthPresence = await inspectAntigravityAccountsPresence();
658
916
  const googleCompanionPresence = await inspectAntigravityCompanionPresence();
659
- lines.push("");
660
- lines.push("google_antigravity:");
661
- lines.push(`- auth_state: ${googleAuthPresence.state}`);
662
- lines.push(`- selected_accounts_path: ${googleAuthPresence.selectedPath ?? "(none)"}`);
663
- lines.push(`- present_accounts_paths: ${joinOrNone(googleAuthPresence.presentPaths)}`);
664
- lines.push(`- candidate_accounts_paths: ${joinOrNone(googleAuthPresence.candidatePaths)}`);
665
- lines.push(`- account_count: ${googleAuthPresence.accountCount}`);
666
- lines.push(`- valid_account_count: ${googleAuthPresence.validAccountCount}`);
667
- lines.push(`- companion_package_state: ${googleCompanionPresence.state}`);
668
- lines.push(`- companion_package_path: ${googleCompanionPresence.state === "present" || googleCompanionPresence.state === "invalid" ? googleCompanionPresence.resolvedPath ?? "(none)" : "(none)"}`);
669
- if (googleCompanionPresence.state !== "present") {
670
- lines.push(`- companion_error: ${sanitizeDisplayText(googleCompanionPresence.error)}`);
671
- }
672
- lines.push(`- token_cache_path: ${googleTokenCachePath} exists=${(await pathExists(googleTokenCachePath)) ? "true" : "false"}`);
673
- if (googleAuthPresence.state === "invalid" && googleAuthPresence.error) {
674
- lines.push(`- auth_error: ${sanitizeDisplayText(googleAuthPresence.error)}`);
675
- }
676
917
  const dbCandidates = getOpenCodeDbPathCandidates();
677
918
  const dbSelected = getOpenCodeDbPath();
678
919
  const dbPresent = [];
@@ -680,41 +921,75 @@ export async function buildQuotaStatusReport(params) {
680
921
  if (await pathExists(p))
681
922
  dbPresent.push(p);
682
923
  }));
683
- lines.push(`- opencode db: preferred=${dbSelected} present=${joinOrNone(dbPresent)} candidates=${joinOrNone(dbCandidates)}`);
924
+ const googleRows = [
925
+ { key: "auth_state", value: googleAuthPresence.state },
926
+ { key: "selected_accounts_path", value: googleAuthPresence.selectedPath ?? "(none)" },
927
+ { key: "present_accounts_paths", value: joinOrNone(googleAuthPresence.presentPaths) },
928
+ { key: "candidate_accounts_paths", value: joinOrNone(googleAuthPresence.candidatePaths) },
929
+ { key: "account_count", value: String(googleAuthPresence.accountCount) },
930
+ { key: "valid_account_count", value: String(googleAuthPresence.validAccountCount) },
931
+ { key: "companion_package_state", value: googleCompanionPresence.state },
932
+ {
933
+ key: "companion_package_path",
934
+ value: googleCompanionPresence.state === "present" || googleCompanionPresence.state === "invalid"
935
+ ? googleCompanionPresence.resolvedPath ?? "(none)"
936
+ : "(none)",
937
+ },
938
+ ];
939
+ if (googleCompanionPresence.state !== "present") {
940
+ googleRows.push({
941
+ key: "companion_error",
942
+ value: sanitizeDisplayText(googleCompanionPresence.error),
943
+ });
944
+ }
945
+ googleRows.push({
946
+ key: "token_cache_path",
947
+ value: `${googleTokenCachePath} exists=${(await pathExists(googleTokenCachePath)) ? "true" : "false"}`,
948
+ });
949
+ if (googleAuthPresence.state === "invalid" && googleAuthPresence.error) {
950
+ googleRows.push({ key: "auth_error", value: sanitizeDisplayText(googleAuthPresence.error) });
951
+ }
952
+ googleRows.push({
953
+ key: "opencode db",
954
+ value: `preferred=${dbSelected} present=${joinOrNone(dbPresent)} candidates=${joinOrNone(dbCandidates)}`,
955
+ });
956
+ sections.push(createKvSection("google_antigravity", "google_antigravity:", googleRows));
684
957
  if (params.googleRefresh?.attempted) {
685
- lines.push("");
686
- lines.push("google_token_refresh:");
958
+ const googleRefreshRows = [];
687
959
  if (typeof params.googleRefresh.total === "number" &&
688
960
  typeof params.googleRefresh.successCount === "number") {
689
- lines.push(`- refreshed: ${params.googleRefresh.successCount}/${params.googleRefresh.total}`);
961
+ googleRefreshRows.push({
962
+ key: "refreshed",
963
+ value: `${params.googleRefresh.successCount}/${params.googleRefresh.total}`,
964
+ });
690
965
  }
691
966
  else {
692
- lines.push("- attempted");
967
+ googleRefreshRows.push({ key: "attempted" });
693
968
  }
694
969
  for (const f of params.googleRefresh.failures ?? []) {
695
- lines.push(`- ${f.email ?? "Unknown"}: ${f.error}`);
970
+ googleRefreshRows.push({ key: f.email ?? "Unknown", value: f.error });
696
971
  }
972
+ sections.push(createKvSection("google_token_refresh", "google_token_refresh:", googleRefreshRows));
697
973
  }
698
974
  // === session token errors ===
699
975
  if (params.sessionTokenError) {
700
- lines.push("");
701
- lines.push("session_tokens_error:");
702
- lines.push(`- session_id: ${params.sessionTokenError.sessionID}`);
703
- lines.push(`- error: ${params.sessionTokenError.error}`);
976
+ const sessionTokenErrorRows = [
977
+ { key: "session_id", value: params.sessionTokenError.sessionID },
978
+ { key: "error", value: params.sessionTokenError.error },
979
+ ];
704
980
  if (params.sessionTokenError.checkedPath) {
705
- lines.push(`- checked_path: ${params.sessionTokenError.checkedPath}`);
981
+ sessionTokenErrorRows.push({ key: "checked_path", value: params.sessionTokenError.checkedPath });
706
982
  }
983
+ sections.push(createKvSection("session_tokens_error", "session_tokens_error:", sessionTokenErrorRows));
707
984
  }
708
985
  // === storage scan ===
709
986
  const dbStats = await getOpenCodeDbStats();
710
- lines.push("");
711
- lines.push("storage:");
712
- lines.push(`- sessions_in_db: ${fmtInt(dbStats.sessionCount)}`);
713
- lines.push(`- messages_in_db: ${fmtInt(dbStats.messageCount)}`);
714
- lines.push(`- assistant_messages_in_db: ${fmtInt(dbStats.assistantMessageCount)}`);
987
+ sections.push(createKvSection("storage", "storage:", [
988
+ { key: "sessions_in_db", value: fmtInt(dbStats.sessionCount) },
989
+ { key: "messages_in_db", value: fmtInt(dbStats.messageCount) },
990
+ { key: "assistant_messages_in_db", value: fmtInt(dbStats.assistantMessageCount) },
991
+ ]));
715
992
  // === pricing snapshot ===
716
- // We intentionally compute all-time usage once so that pricing coverage and unknown_pricing
717
- // are consistent and do not require multiple storage scans.
718
993
  const agg = await aggregateUsage({});
719
994
  const meta = getPricingSnapshotMeta();
720
995
  const providers = listProviders();
@@ -728,73 +1003,113 @@ export async function buildQuotaStatusReport(params) {
728
1003
  const runtimeSnapshotPath = getRuntimePricingSnapshotPath();
729
1004
  const refreshStatePath = getRuntimePricingRefreshStatePath();
730
1005
  const pricingRefreshState = await readPricingRefreshState();
731
- lines.push("");
732
- lines.push("pricing_snapshot:");
733
- lines.push(`- pricing: source=${meta.source} active_source=${snapshotSource} generated_at=${new Date(meta.generatedAt).toISOString()} units=${meta.units}`);
734
- lines.push(`- selection: configured=${params.pricingSnapshotSource} active=${snapshotSource}`);
1006
+ const pricingRows = [
1007
+ {
1008
+ key: "pricing",
1009
+ value: `source=${meta.source} active_source=${snapshotSource} generated_at=${new Date(meta.generatedAt).toISOString()} units=${meta.units}`,
1010
+ },
1011
+ {
1012
+ key: "selection",
1013
+ value: `configured=${params.pricingSnapshotSource} active=${snapshotSource}`,
1014
+ },
1015
+ ];
735
1016
  if (params.pricingSnapshotSource === "bundled") {
736
- lines.push("- selection_note: bundled config pins the packaged snapshot and ignores runtime refresh for active pricing");
1017
+ pricingRows.push({
1018
+ key: "selection_note",
1019
+ value: "bundled config pins the packaged snapshot and ignores runtime refresh for active pricing",
1020
+ });
737
1021
  }
738
1022
  else if (params.pricingSnapshotSource === "runtime" && snapshotSource !== "runtime") {
739
- lines.push("- selection_note: runtime config requested the local runtime snapshot, but bundled fallback is active because no valid runtime snapshot is available");
1023
+ pricingRows.push({
1024
+ key: "selection_note",
1025
+ value: "runtime config requested the local runtime snapshot, but bundled fallback is active because no valid runtime snapshot is available",
1026
+ });
740
1027
  }
741
- lines.push(`- runtime_paths: snapshot=${runtimeSnapshotPath} refresh_state=${refreshStatePath}`);
742
- lines.push(`- staleness: age_ms=${fmtInt(health.ageMs)} max_age_ms=${fmtInt(health.maxAgeMs)} stale=${health.stale ? "true" : "false"}`);
743
- lines.push(`- refresh_policy: auto_refresh_days=${fmtInt(autoRefreshDays)}`);
1028
+ pricingRows.push({
1029
+ key: "runtime_paths",
1030
+ value: `snapshot=${runtimeSnapshotPath} refresh_state=${refreshStatePath}`,
1031
+ });
1032
+ pricingRows.push({
1033
+ key: "staleness",
1034
+ value: `age_ms=${fmtInt(health.ageMs)} max_age_ms=${fmtInt(health.maxAgeMs)} stale=${health.stale ? "true" : "false"}`,
1035
+ });
1036
+ pricingRows.push({
1037
+ key: "refresh_policy",
1038
+ value: `auto_refresh_days=${fmtInt(autoRefreshDays)}`,
1039
+ });
744
1040
  if (pricingRefreshState) {
745
- lines.push(`- refresh: last_attempt_at=${pricingRefreshState.lastAttemptAt ? new Date(pricingRefreshState.lastAttemptAt).toISOString() : "(none)"} last_success_at=${pricingRefreshState.lastSuccessAt ? new Date(pricingRefreshState.lastSuccessAt).toISOString() : "(none)"} last_failure_at=${pricingRefreshState.lastFailureAt ? new Date(pricingRefreshState.lastFailureAt).toISOString() : "(none)"} last_result=${pricingRefreshState.lastResult ?? "(none)"}`);
1041
+ pricingRows.push({
1042
+ key: "refresh",
1043
+ value: `last_attempt_at=${pricingRefreshState.lastAttemptAt ? new Date(pricingRefreshState.lastAttemptAt).toISOString() : "(none)"} last_success_at=${pricingRefreshState.lastSuccessAt ? new Date(pricingRefreshState.lastSuccessAt).toISOString() : "(none)"} last_failure_at=${pricingRefreshState.lastFailureAt ? new Date(pricingRefreshState.lastFailureAt).toISOString() : "(none)"} last_result=${pricingRefreshState.lastResult ?? "(none)"}`,
1044
+ });
746
1045
  if (pricingRefreshState.lastError) {
747
- lines.push(`- refresh_error: ${pricingRefreshState.lastError}`);
1046
+ pricingRows.push({ key: "refresh_error", value: pricingRefreshState.lastError });
748
1047
  }
749
1048
  }
750
1049
  else {
751
- lines.push("- refresh: (no runtime refresh state yet)");
1050
+ pricingRows.push({ key: "refresh", value: "(no runtime refresh state yet)" });
752
1051
  }
753
- lines.push(`- providers: ${providers.join(",")}`);
754
- lines.push(`- coverage_seen: priced_keys=${fmtInt(coverage.totals.pricedKeysSeen)} mapped_but_missing=${fmtInt(coverage.totals.mappedMissingKeysSeen)} unpriced_keys=${fmtInt(coverage.totals.unpricedKeysSeen)}`);
1052
+ pricingRows.push({ key: "providers", value: providers.join(",") });
1053
+ pricingRows.push({
1054
+ key: "coverage_seen",
1055
+ value: `priced_keys=${fmtInt(coverage.totals.pricedKeysSeen)} mapped_but_missing=${fmtInt(coverage.totals.mappedMissingKeysSeen)} unpriced_keys=${fmtInt(coverage.totals.unpricedKeysSeen)}`,
1056
+ });
755
1057
  for (const p of providers) {
756
1058
  const c = coverage.byProvider.get(p) ?? {
757
1059
  pricedKeysSeen: 0,
758
1060
  mappedMissingKeysSeen: 0,
759
1061
  unpricedKeysSeen: 0,
760
1062
  };
761
- lines.push(` - ${p}: models=${fmtInt(getProviderModelCount(p))} priced_models_seen=${fmtInt(c.pricedKeysSeen)} mapped_but_missing_models_seen=${fmtInt(c.mappedMissingKeysSeen)} unpriced_models_seen=${fmtInt(c.unpricedKeysSeen)}`);
1063
+ pricingRows.push({
1064
+ key: p,
1065
+ value: `models=${fmtInt(getProviderModelCount(p))} priced_models_seen=${fmtInt(c.pricedKeysSeen)} mapped_but_missing_models_seen=${fmtInt(c.mappedMissingKeysSeen)} unpriced_models_seen=${fmtInt(c.unpricedKeysSeen)}`,
1066
+ indent: 1,
1067
+ });
762
1068
  }
1069
+ sections.push(createKvSection("pricing_snapshot", "pricing_snapshot:", pricingRows));
763
1070
  // === supported providers pricing ===
764
1071
  const supported = getProviders().map((p) => p.id);
765
- lines.push("");
766
- lines.push("supported_providers_pricing:");
767
- for (const id of supported) {
1072
+ const supportedRows = supported.map((id) => {
768
1073
  const row = supportedProviderPricingRow({ id, agg, snapshotProviders: providers });
769
- lines.push(`- ${row.id}: pricing=${row.pricing} (${row.notes})`);
770
- }
1074
+ return {
1075
+ key: row.id,
1076
+ value: `pricing=${row.pricing} (${row.notes})`,
1077
+ };
1078
+ });
1079
+ sections.push(createKvSection("supported_providers_pricing", "supported_providers_pricing:", supportedRows));
771
1080
  // === unpriced models ===
772
- // Mapped keys that are deterministically not token-priced by our snapshot.
773
- lines.push("");
774
- lines.push("unpriced_models:");
1081
+ const unpricedRows = [];
775
1082
  if (agg.unpriced.length === 0) {
776
- lines.push("- none");
1083
+ unpricedRows.push({ key: "none" });
777
1084
  }
778
1085
  else {
779
- lines.push(`- keys: ${fmtInt(agg.unpriced.length)} tokens_total=${fmtInt(totalTokenBuckets(agg.totals.unpriced))}`);
1086
+ unpricedRows.push({
1087
+ key: "keys",
1088
+ value: `${fmtInt(agg.unpriced.length)} tokens_total=${fmtInt(totalTokenBuckets(agg.totals.unpriced))}`,
1089
+ });
780
1090
  for (const row of agg.unpriced.slice(0, STATUS_SAMPLE_LIMIT)) {
781
1091
  const src = `${row.key.sourceProviderID}/${row.key.sourceModelID}`;
782
1092
  const mapped = `${row.key.mappedProvider}/${row.key.mappedModel}`;
783
- lines.push(`- ${src} mapped=${mapped} tokens=${fmtInt(totalTokenBuckets(row.tokens))} msgs=${fmtInt(row.messageCount)} reason=${row.key.reason}`);
1093
+ unpricedRows.push({
1094
+ key: src,
1095
+ value: `mapped=${mapped} tokens=${fmtInt(totalTokenBuckets(row.tokens))} msgs=${fmtInt(row.messageCount)} reason=${row.key.reason}`,
1096
+ });
784
1097
  }
785
1098
  if (agg.unpriced.length > STATUS_SAMPLE_LIMIT) {
786
- lines.push(`- ... (${fmtInt(agg.unpriced.length - STATUS_SAMPLE_LIMIT)} more)`);
1099
+ unpricedRows.push({ key: `... (${fmtInt(agg.unpriced.length - STATUS_SAMPLE_LIMIT)} more)` });
787
1100
  }
788
1101
  }
1102
+ sections.push(createKvSection("unpriced_models", "unpriced_models:", unpricedRows));
789
1103
  // === unknown pricing ===
790
- // We intentionally report unknowns for *all time* so users can see what needs mapping.
791
- lines.push("");
792
- lines.push("unknown_pricing:");
1104
+ const unknownRows = [];
793
1105
  if (agg.unknown.length === 0) {
794
- lines.push("- none");
1106
+ unknownRows.push({ key: "none" });
795
1107
  }
796
1108
  else {
797
- lines.push(`- keys: ${fmtInt(agg.unknown.length)} tokens_total=${fmtInt(totalTokenBuckets(agg.totals.unknown))}`);
1109
+ unknownRows.push({
1110
+ key: "keys",
1111
+ value: `${fmtInt(agg.unknown.length)} tokens_total=${fmtInt(totalTokenBuckets(agg.totals.unknown))}`,
1112
+ });
798
1113
  for (const row of agg.unknown.slice(0, STATUS_SAMPLE_LIMIT)) {
799
1114
  const src = `${row.key.sourceProviderID}/${row.key.sourceModelID}`;
800
1115
  const mappedBase = row.key.mappedProvider && row.key.mappedModel
@@ -803,12 +1118,22 @@ export async function buildQuotaStatusReport(params) {
803
1118
  const candidates = row.key.providerCandidates && row.key.providerCandidates.length > 0
804
1119
  ? ` candidates=${row.key.providerCandidates.join(",")}`
805
1120
  : "";
806
- lines.push(`- ${src} mapped=${mappedBase}${candidates} tokens=${fmtInt(totalTokenBuckets(row.tokens))} msgs=${fmtInt(row.messageCount)}`);
1121
+ unknownRows.push({
1122
+ key: src,
1123
+ value: `mapped=${mappedBase}${candidates} tokens=${fmtInt(totalTokenBuckets(row.tokens))} msgs=${fmtInt(row.messageCount)}`,
1124
+ });
807
1125
  }
808
1126
  if (agg.unknown.length > STATUS_SAMPLE_LIMIT) {
809
- lines.push(`- ... (${fmtInt(agg.unknown.length - STATUS_SAMPLE_LIMIT)} more)`);
1127
+ unknownRows.push({ key: `... (${fmtInt(agg.unknown.length - STATUS_SAMPLE_LIMIT)} more)` });
810
1128
  }
811
1129
  }
812
- return lines.join("\n");
1130
+ sections.push(createKvSection("unknown_pricing", "unknown_pricing:", unknownRows));
1131
+ return renderPlainTextReport({
1132
+ heading: {
1133
+ title: `Quota Status (opencode-quota v${v}) (/quota_status)`,
1134
+ generatedAtMs: params.generatedAtMs,
1135
+ },
1136
+ sections,
1137
+ });
813
1138
  }
814
1139
  //# sourceMappingURL=quota-status.js.map