@slkiser/opencode-quota 3.1.0 → 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.
package/README.md CHANGED
@@ -537,9 +537,10 @@ If OpenCode already has Synthetic configured, it should work automatically. Opti
537
537
  For security, provider secrets are read from `SYNTHETIC_API_KEY`, your user/global OpenCode config, or `auth.json.synthetic` only. Repo-local `opencode.json` / `opencode.jsonc` is ignored for `provider.synthetic.options.apiKey`.
538
538
 
539
539
  - The plugin calls `GET https://api.synthetic.new/v2/quotas`.
540
- - It reads `subscription.limit`, `subscription.requests`, and `subscription.renewsAt`.
540
+ - It reads the documented subscription window fields `subscription.limit`, `subscription.requests`, and `subscription.renewsAt`.
541
541
  - Synthetic currently expects numeric JSON values for `subscription.limit` and `subscription.requests`; malformed or stringified values are treated as API-shape errors. Invalid `subscription.renewsAt` values are ignored.
542
- - `/quota`, toasts, and the sidebar show one Synthetic row with remaining percent plus the same compact `used/limit` summary used by other percent-based providers when that row data is available.
542
+ - `/quota`, toasts, and the sidebar currently expose the documented Synthetic subscription quota only. Grouped mode labels it as `5h:`; classic mode collapses it to one `Synthetic` row with the same compact `used/limit` summary used by other percent-based providers.
543
+ - Weekly credits and other billing-dashboard metrics are not shown unless Synthetic documents them in a public API response the plugin can verify.
543
544
  - `/quota_status` shows a `synthetic` section with API-key diagnostics only; it does not do a live Synthetic fetch there.
544
545
  - Allowed env templates are limited to `{env:SYNTHETIC_API_KEY}`.
545
546
 
@@ -3,5 +3,10 @@ export type GroupedRenderTarget = "toast" | "quota";
3
3
  export type NormalizedGroupedQuotaEntry = QuotaToastEntry & {
4
4
  group: string;
5
5
  };
6
+ export type QuotaEntryGroup = {
7
+ group: string;
8
+ entries: NormalizedGroupedQuotaEntry[];
9
+ };
10
+ export declare function groupQuotaEntries(entries: QuotaToastEntry[], target: GroupedRenderTarget): QuotaEntryGroup[];
6
11
  export declare function normalizeGroupedQuotaEntries(entries: QuotaToastEntry[], target: GroupedRenderTarget): NormalizedGroupedQuotaEntry[];
7
12
  //# sourceMappingURL=grouped-entry-normalization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"grouped-entry-normalization.d.ts","sourceRoot":"","sources":["../../src/lib/grouped-entry-normalization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpD,MAAM,MAAM,2BAA2B,GAAG,eAAe,GAAG;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAyFF,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,EAAE,mBAAmB,GAC1B,2BAA2B,EAAE,CAmC/B"}
1
+ {"version":3,"file":"grouped-entry-normalization.d.ts","sourceRoot":"","sources":["../../src/lib/grouped-entry-normalization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpD,MAAM,MAAM,2BAA2B,GAAG,eAAe,GAAG;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,2BAA2B,EAAE,CAAC;CACxC,CAAC;AAyFF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,EAAE,mBAAmB,GAC1B,eAAe,EAAE,CAqCnB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,EAAE,mBAAmB,GAC1B,2BAA2B,EAAE,CAE/B"}
@@ -72,7 +72,7 @@ function normalizeGroupedQuotaEntry(entry, target) {
72
72
  ...(target === "quota" ? { label: label ?? "Status:" } : {}),
73
73
  };
74
74
  }
75
- export function normalizeGroupedQuotaEntries(entries, target) {
75
+ export function groupQuotaEntries(entries, target) {
76
76
  const groupOrder = [];
77
77
  const groupedEntries = new Map();
78
78
  for (const [originalIndex, entry] of entries.entries()) {
@@ -90,9 +90,9 @@ export function normalizeGroupedQuotaEntries(entries, target) {
90
90
  groupOrder.push(normalizedEntry.group);
91
91
  groupedEntries.set(normalizedEntry.group, [rankedEntry]);
92
92
  }
93
- return groupOrder.flatMap((group) => {
93
+ return groupOrder.map((group) => {
94
94
  const rankedEntries = groupedEntries.get(group) ?? [];
95
- return rankedEntries
95
+ const entries = rankedEntries
96
96
  .slice()
97
97
  .sort((left, right) => {
98
98
  if (left.rank !== null && right.rank !== null && left.rank !== right.rank) {
@@ -105,6 +105,10 @@ export function normalizeGroupedQuotaEntries(entries, target) {
105
105
  return left.originalIndex - right.originalIndex;
106
106
  })
107
107
  .map(({ entry }) => entry);
108
+ return { group, entries };
108
109
  });
109
110
  }
111
+ export function normalizeGroupedQuotaEntries(entries, target) {
112
+ return groupQuotaEntries(entries, target).flatMap((group) => group.entries);
113
+ }
110
114
  //# sourceMappingURL=grouped-entry-normalization.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grouped-entry-normalization.js","sourceRoot":"","sources":["../../src/lib/grouped-entry-normalization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grouped-entry-normalization.js","sourceRoot":"","sources":["../../src/lib/grouped-entry-normalization.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"quota-command-format.d.ts","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsGxF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAOT"}
1
+ {"version":3,"file":"quota-command-format.d.ts","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAwGxF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAET"}
@@ -7,10 +7,11 @@
7
7
  * - Includes session token summary (input/output per model)
8
8
  */
9
9
  import { isValueEntry } from "./entries.js";
10
- import { bar, clampInt, padRight, renderCommandHeading } from "./format-utils.js";
10
+ import { bar, clampInt, padRight } from "./format-utils.js";
11
11
  import { formatGroupedHeader } from "./grouped-header-format.js";
12
- import { normalizeGroupedQuotaEntries } from "./grouped-entry-normalization.js";
13
- import { renderSessionTokensLines } from "./session-tokens-format.js";
12
+ import { groupQuotaEntries } from "./grouped-entry-normalization.js";
13
+ import { renderPlainTextReport } from "./report-document.js";
14
+ import { buildSessionTokenSectionModel } from "./session-tokens-format.js";
14
15
  /**
15
16
  * Format reset time in compact form (different from toast countdown).
16
17
  * Uses seconds/minutes/hours/days format for /quota command.
@@ -40,29 +41,14 @@ function getGroupedLeftText(entry) {
40
41
  const right = entry.right?.trim();
41
42
  return right ? `${label} ${right}` : label;
42
43
  }
43
- function formatQuotaCommandBody(params) {
44
- const entries = normalizeGroupedQuotaEntries(params.entries, "quota");
45
- const groupOrder = [];
46
- const groups = new Map();
47
- for (const e of entries) {
48
- const list = groups.get(e.group);
49
- if (list)
50
- list.push(e);
51
- else {
52
- groupOrder.push(e.group);
53
- groups.set(e.group, [e]);
54
- }
55
- }
56
- const lines = [];
44
+ function buildQuotaCommandDocument(params) {
45
+ const groups = groupQuotaEntries(params.entries, "quota");
46
+ const normalizedEntries = groups.flatMap((group) => group.entries);
57
47
  const barWidth = 18;
58
- const leftCol = Math.max(16, Math.min(30, entries.reduce((max, entry) => Math.max(max, getGroupedLeftText(entry).length), 0)));
59
- for (let i = 0; i < groupOrder.length; i++) {
60
- const g = groupOrder[i];
61
- const list = groups.get(g) ?? [];
62
- if (i > 0)
63
- lines.push("");
64
- lines.push(`→ ${formatGroupedHeader(g)}`);
65
- for (const row of list) {
48
+ const leftCol = Math.max(16, Math.min(30, normalizedEntries.reduce((max, entry) => Math.max(max, getGroupedLeftText(entry).length), 0)));
49
+ const sections = groups.map((group, index) => {
50
+ const lines = [];
51
+ for (const row of group.entries) {
66
52
  const leftText = getGroupedLeftText(row);
67
53
  const labelCol = padRight(leftText, leftCol);
68
54
  const suffix = formatResetsIn(row.resetTimeIso);
@@ -73,27 +59,40 @@ function formatQuotaCommandBody(params) {
73
59
  const pct = clampInt(row.percentRemaining, 0, 100);
74
60
  lines.push(` ${labelCol} ${bar(pct, barWidth)} ${pct}% left${suffix}`);
75
61
  }
76
- }
77
- // Add session token summary (if data available and non-empty)
78
- const tokenLines = renderSessionTokensLines(params.sessionTokens);
79
- if (tokenLines.length > 0) {
80
- lines.push("");
81
- lines.push(...tokenLines);
62
+ return {
63
+ id: `group-${index}`,
64
+ title: `→ ${formatGroupedHeader(group.group)}`,
65
+ blocks: [{ kind: "lines", lines }],
66
+ };
67
+ });
68
+ const tokenSection = buildSessionTokenSectionModel(params.sessionTokens);
69
+ if (tokenSection) {
70
+ sections.push({
71
+ id: "session-tokens",
72
+ title: tokenSection.heading,
73
+ blocks: [{ kind: "lines", lines: tokenSection.lines }],
74
+ });
82
75
  }
83
76
  if (params.errors.length > 0) {
84
- lines.push("");
85
- for (const err of params.errors) {
86
- lines.push(`${err.label}: ${err.message}`);
87
- }
77
+ sections.push({
78
+ id: "errors",
79
+ blocks: [
80
+ {
81
+ kind: "lines",
82
+ lines: params.errors.map((err) => `${err.label}: ${err.message}`),
83
+ },
84
+ ],
85
+ });
88
86
  }
89
- return lines.join("\n");
87
+ return {
88
+ heading: {
89
+ title: "Quota (/quota)",
90
+ generatedAtMs: params.generatedAtMs,
91
+ },
92
+ sections,
93
+ };
90
94
  }
91
95
  export function formatQuotaCommand(params) {
92
- const heading = renderCommandHeading({
93
- title: "Quota (/quota)",
94
- generatedAtMs: params.generatedAtMs,
95
- });
96
- const body = formatQuotaCommandBody(params);
97
- return body.length > 0 ? `${heading}\n\n${body}` : heading;
96
+ return renderPlainTextReport(buildQuotaCommandDocument(params));
98
97
  }
99
98
  //# sourceMappingURL=quota-command-format.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"quota-command-format.js","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quota-command-format.js","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"quota-stats-format.d.ts","sourceRoot":"","sources":["../../src/lib/quota-stats-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAgB,MAAM,kBAAkB,CAAC;AAcvF,KAAK,oBAAoB,GAAG,UAAU,GAAG,SAAS,GAAG,cAAc,CAAC;AA8GpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mGAAmG;IACnG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,WAAW,CAAC,EAAE;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,eAAe,EAAE,CAAC;KAC1B,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CA2RT"}
1
+ {"version":3,"file":"quota-stats-format.d.ts","sourceRoot":"","sources":["../../src/lib/quota-stats-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAgB,MAAM,kBAAkB,CAAC;AAcvF,KAAK,oBAAoB,GAAG,UAAU,GAAG,SAAS,GAAG,cAAc,CAAC;AA8GpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mGAAmG;IACnG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,WAAW,CAAC,EAAE;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,eAAe,EAAE,CAAC;KAC1B,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAuTT"}
@@ -1,5 +1,4 @@
1
- import { renderCommandHeading } from "./format-utils.js";
2
- import { renderMarkdownTable } from "./markdown-table.js";
1
+ import { renderMarkdownReport } from "./report-document.js";
3
2
  import { emptyTokenBuckets, totalTokenBuckets } from "./token-buckets.js";
4
3
  /** Use markdown-conceal for proper TUI alignment (strips markdown syntax for width calc) */
5
4
  const TABLE_WIDTH_MODE = "markdown-conceal";
@@ -140,57 +139,70 @@ export function formatQuotaStatsReport(params) {
140
139
  const combinedTokens = totalTokenBuckets(r.totals.priced) +
141
140
  totalTokenBuckets(r.totals.unknown) +
142
141
  totalTokenBuckets(r.totals.unpriced);
143
- const lines = [];
144
- lines.push(renderCommandHeading({
145
- title: params.title,
146
- generatedAtMs: params.generatedAtMs,
147
- }));
148
- lines.push("");
142
+ const sections = [];
149
143
  // Session-scoped reports use a compact summary without the time window column.
150
144
  if (sessionOnly) {
151
- lines.push(renderMarkdownTable({
152
- headers: ["Messages", "Tokens", "Cost"],
153
- aligns: ["right", "right", "right"],
154
- widthMode: TABLE_WIDTH_MODE,
155
- rows: [
156
- [
157
- fmtCompact(r.totals.messageCount),
158
- fmtCompact(combinedTokens),
159
- fmtUsd(r.totals.costUsd),
160
- ],
145
+ sections.push({
146
+ id: "summary",
147
+ blocks: [
148
+ {
149
+ kind: "table",
150
+ headers: ["Messages", "Tokens", "Cost"],
151
+ aligns: ["right", "right", "right"],
152
+ widthMode: TABLE_WIDTH_MODE,
153
+ rows: [
154
+ [
155
+ fmtCompact(r.totals.messageCount),
156
+ fmtCompact(combinedTokens),
157
+ fmtUsd(r.totals.costUsd),
158
+ ],
159
+ ],
160
+ },
161
161
  ],
162
- }));
162
+ });
163
163
  }
164
164
  else if (sessionTreeMode) {
165
- lines.push(renderMarkdownTable({
166
- headers: ["Messages", "Sessions", "Tokens", "Cost"],
167
- aligns: ["right", "right", "right", "right"],
168
- widthMode: TABLE_WIDTH_MODE,
169
- rows: [
170
- [
171
- fmtCompact(r.totals.messageCount),
172
- fmtCompact(sessionTree.nodes.length),
173
- fmtCompact(combinedTokens),
174
- fmtUsd(r.totals.costUsd),
175
- ],
165
+ sections.push({
166
+ id: "summary",
167
+ blocks: [
168
+ {
169
+ kind: "table",
170
+ headers: ["Messages", "Sessions", "Tokens", "Cost"],
171
+ aligns: ["right", "right", "right", "right"],
172
+ widthMode: TABLE_WIDTH_MODE,
173
+ rows: [
174
+ [
175
+ fmtCompact(r.totals.messageCount),
176
+ fmtCompact(sessionTree.nodes.length),
177
+ fmtCompact(combinedTokens),
178
+ fmtUsd(r.totals.costUsd),
179
+ ],
180
+ ],
181
+ },
176
182
  ],
177
- }));
183
+ });
178
184
  }
179
185
  else {
180
- lines.push(renderMarkdownTable({
181
- headers: ["Window", "Messages", "Sessions", "Tokens", "Cost"],
182
- aligns: ["left", "right", "right", "right", "right"],
183
- widthMode: TABLE_WIDTH_MODE,
184
- rows: [
185
- [
186
- fmtWindow(r.window),
187
- fmtCompact(r.totals.messageCount),
188
- fmtCompact(r.totals.sessionCount),
189
- fmtCompact(combinedTokens),
190
- fmtUsd(r.totals.costUsd),
191
- ],
186
+ sections.push({
187
+ id: "summary",
188
+ blocks: [
189
+ {
190
+ kind: "table",
191
+ headers: ["Window", "Messages", "Sessions", "Tokens", "Cost"],
192
+ aligns: ["left", "right", "right", "right", "right"],
193
+ widthMode: TABLE_WIDTH_MODE,
194
+ rows: [
195
+ [
196
+ fmtWindow(r.window),
197
+ fmtCompact(r.totals.messageCount),
198
+ fmtCompact(r.totals.sessionCount),
199
+ fmtCompact(combinedTokens),
200
+ fmtUsd(r.totals.costUsd),
201
+ ],
202
+ ],
203
+ },
192
204
  ],
193
- }));
205
+ });
194
206
  }
195
207
  const hasAnyReasoning = r.totals.priced.reasoning > 0 ||
196
208
  r.totals.unknown.reasoning > 0 ||
@@ -245,15 +257,21 @@ export function formatQuotaStatsReport(params) {
245
257
  }
246
258
  }
247
259
  if (rows.length > 0) {
248
- lines.push("");
249
- lines.push(`## Models`);
250
- lines.push("");
251
- lines.push(renderMarkdownTable({ headers, rows, aligns, widthMode: TABLE_WIDTH_MODE }));
260
+ sections.push({
261
+ id: "models",
262
+ title: "Models",
263
+ blocks: [
264
+ {
265
+ kind: "table",
266
+ headers,
267
+ rows,
268
+ aligns,
269
+ widthMode: TABLE_WIDTH_MODE,
270
+ },
271
+ ],
272
+ });
252
273
  }
253
274
  if (sessionTreeMode) {
254
- lines.push("");
255
- lines.push(`## Session Tree`);
256
- lines.push("");
257
275
  const sessionUsageByID = new Map(r.bySession.map((row) => [row.sessionID, row]));
258
276
  const sessionTreeRows = sessionTree.nodes.map((node) => {
259
277
  const usage = sessionUsageByID.get(node.sessionID);
@@ -267,18 +285,22 @@ export function formatQuotaStatsReport(params) {
267
285
  truncateTitle(node.title ?? usage?.title),
268
286
  ];
269
287
  });
270
- lines.push(renderMarkdownTable({
271
- headers: ["Relation", "Parent", "Session", "Cost", "Tokens", "Msgs", "Title"],
272
- aligns: ["left", "left", "left", "right", "right", "right", "left"],
273
- widthMode: TABLE_WIDTH_MODE,
274
- rows: sessionTreeRows,
275
- }));
288
+ sections.push({
289
+ id: "session-tree",
290
+ title: "Session Tree",
291
+ blocks: [
292
+ {
293
+ kind: "table",
294
+ headers: ["Relation", "Parent", "Session", "Cost", "Tokens", "Msgs", "Title"],
295
+ aligns: ["left", "left", "left", "right", "right", "right", "left"],
296
+ widthMode: TABLE_WIDTH_MODE,
297
+ rows: sessionTreeRows,
298
+ },
299
+ ],
300
+ });
276
301
  }
277
302
  // Skip Top Sessions for session-scoped reports (e.g., /tokens_session, /tokens_session_all).
278
303
  if (reportKind === "standard") {
279
- lines.push("");
280
- lines.push(`## Top Sessions`);
281
- lines.push("");
282
304
  const sessionRows = [];
283
305
  const visibleSessions = r.bySession.filter(hasRenderableSessionUsage);
284
306
  const focus = params.focusSessionID
@@ -307,71 +329,92 @@ export function formatQuotaStatsReport(params) {
307
329
  appendSessionRow(sessionRows, row);
308
330
  }
309
331
  }
310
- if (sessionRows.length > 0) {
311
- lines.push(renderMarkdownTable({
312
- headers: ["Current", "Session", "Cost", "Tokens", "Msgs", "Title"],
313
- aligns: ["left", "left", "right", "right", "right", "left"],
314
- widthMode: TABLE_WIDTH_MODE,
315
- rows: sessionRows,
316
- }));
317
- }
318
- else {
319
- lines.push("(no sessions)");
320
- }
332
+ sections.push({
333
+ id: "top-sessions",
334
+ title: "Top Sessions",
335
+ blocks: sessionRows.length > 0
336
+ ? [
337
+ {
338
+ kind: "table",
339
+ headers: ["Current", "Session", "Cost", "Tokens", "Msgs", "Title"],
340
+ aligns: ["left", "left", "right", "right", "right", "left"],
341
+ widthMode: TABLE_WIDTH_MODE,
342
+ rows: sessionRows,
343
+ },
344
+ ]
345
+ : [{ kind: "lines", lines: ["(no sessions)"] }],
346
+ });
321
347
  }
322
348
  if (r.unpriced.length > 0) {
323
- lines.push("");
324
- lines.push(`## Unpriced Models`);
325
- lines.push("");
326
- lines.push(renderMarkdownTable({
327
- headers: ["Source", "Model", "Mapped", "Reason", "Tokens", "Msgs"],
328
- aligns: ["left", "left", "left", "left", "right", "right"],
329
- widthMode: TABLE_WIDTH_MODE,
330
- rows: r.unpriced.slice(0, 20).map((u) => {
331
- const mapped = `${u.key.mappedProvider}/${u.key.mappedModel}`;
332
- return [
333
- normalizeSourceName(u.key.sourceProviderID),
334
- u.key.sourceModelID,
335
- mapped,
336
- u.key.reason,
337
- fmtCompact(totalTokenBuckets(u.tokens)),
338
- fmtCompact(u.messageCount),
339
- ];
340
- }),
341
- }));
349
+ sections.push({
350
+ id: "unpriced-models",
351
+ title: "Unpriced Models",
352
+ blocks: [
353
+ {
354
+ kind: "table",
355
+ headers: ["Source", "Model", "Mapped", "Reason", "Tokens", "Msgs"],
356
+ aligns: ["left", "left", "left", "left", "right", "right"],
357
+ widthMode: TABLE_WIDTH_MODE,
358
+ rows: r.unpriced.slice(0, 20).map((u) => {
359
+ const mapped = `${u.key.mappedProvider}/${u.key.mappedModel}`;
360
+ return [
361
+ normalizeSourceName(u.key.sourceProviderID),
362
+ u.key.sourceModelID,
363
+ mapped,
364
+ u.key.reason,
365
+ fmtCompact(totalTokenBuckets(u.tokens)),
366
+ fmtCompact(u.messageCount),
367
+ ];
368
+ }),
369
+ },
370
+ ],
371
+ });
342
372
  }
343
373
  if (r.unknown.length > 0) {
344
- lines.push("");
345
- lines.push(`## Unknown Pricing`);
346
- lines.push("");
347
- lines.push(renderMarkdownTable({
348
- headers: ["Source", "Model", "Mapped", "Tokens", "Msgs"],
349
- aligns: ["left", "left", "left", "right", "right"],
350
- widthMode: TABLE_WIDTH_MODE,
351
- rows: r.unknown.slice(0, 20).map((u) => {
352
- const mappedBase = u.key.mappedProvider && u.key.mappedModel
353
- ? `${u.key.mappedProvider}/${u.key.mappedModel}`
354
- : "-";
355
- const candidateSuffix = u.key.providerCandidates && u.key.providerCandidates.length > 0
356
- ? `candidates: ${u.key.providerCandidates.join(",")}`
357
- : "";
358
- const mapped = candidateSuffix.length > 0
359
- ? mappedBase === "-"
360
- ? candidateSuffix
361
- : `${mappedBase} (${candidateSuffix})`
362
- : mappedBase;
363
- return [
364
- normalizeSourceName(u.key.sourceProviderID),
365
- u.key.sourceModelID,
366
- mapped,
367
- fmtCompact(totalTokenBuckets(u.tokens)),
368
- fmtCompact(u.messageCount),
369
- ];
370
- }),
371
- }));
372
- lines.push("");
373
- lines.push(`Run /quota_status to see the full pricing diagnostics report.`);
374
+ sections.push({
375
+ id: "unknown-pricing",
376
+ title: "Unknown Pricing",
377
+ blocks: [
378
+ {
379
+ kind: "table",
380
+ headers: ["Source", "Model", "Mapped", "Tokens", "Msgs"],
381
+ aligns: ["left", "left", "left", "right", "right"],
382
+ widthMode: TABLE_WIDTH_MODE,
383
+ rows: r.unknown.slice(0, 20).map((u) => {
384
+ const mappedBase = u.key.mappedProvider && u.key.mappedModel
385
+ ? `${u.key.mappedProvider}/${u.key.mappedModel}`
386
+ : "-";
387
+ const candidateSuffix = u.key.providerCandidates && u.key.providerCandidates.length > 0
388
+ ? `candidates: ${u.key.providerCandidates.join(",")}`
389
+ : "";
390
+ const mapped = candidateSuffix.length > 0
391
+ ? mappedBase === "-"
392
+ ? candidateSuffix
393
+ : `${mappedBase} (${candidateSuffix})`
394
+ : mappedBase;
395
+ return [
396
+ normalizeSourceName(u.key.sourceProviderID),
397
+ u.key.sourceModelID,
398
+ mapped,
399
+ fmtCompact(totalTokenBuckets(u.tokens)),
400
+ fmtCompact(u.messageCount),
401
+ ];
402
+ }),
403
+ },
404
+ {
405
+ kind: "lines",
406
+ lines: ["Run /quota_status to see the full pricing diagnostics report."],
407
+ },
408
+ ],
409
+ });
374
410
  }
375
- return lines.join("\n");
411
+ const document = {
412
+ heading: {
413
+ title: params.title,
414
+ generatedAtMs: params.generatedAtMs,
415
+ },
416
+ sections,
417
+ };
418
+ return renderMarkdownReport(document);
376
419
  }
377
420
  //# sourceMappingURL=quota-stats-format.js.map