llm-usage-metrics 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.js +459 -107
- package/dist/index.js.map +1 -1
- package/package.json +24 -18
package/dist/index.js
CHANGED
|
@@ -889,9 +889,6 @@ ${noData}
|
|
|
889
889
|
import { markdownTable } from "markdown-table";
|
|
890
890
|
import pc4 from "picocolors";
|
|
891
891
|
|
|
892
|
-
// src/render/report-header.ts
|
|
893
|
-
import pc from "picocolors";
|
|
894
|
-
|
|
895
892
|
// src/render/table-text-layout.ts
|
|
896
893
|
var ansiEscapePattern = new RegExp(String.raw`\u001B\[[0-9;]*m`, "gu");
|
|
897
894
|
var combiningMarkPattern = /\p{Mark}/u;
|
|
@@ -1065,7 +1062,30 @@ function wrapTableColumn(rows, options) {
|
|
|
1065
1062
|
});
|
|
1066
1063
|
}
|
|
1067
1064
|
|
|
1065
|
+
// src/render/markdown-safe-cell.ts
|
|
1066
|
+
var markdownSpecialCharacterPattern = /[\\`*_~[\]()!|]/gu;
|
|
1067
|
+
var bareUrlPattern = /\bhttps?:\/\/[^\s<]+|\bwww\.[^\s<]+/giu;
|
|
1068
|
+
var bareEmailPattern = /(^|[^\w.+-])([\w.+-]+@[\w.-]+\.[a-z]{2,})(?=$|[^\w.-])/giu;
|
|
1069
|
+
function escapeBareAutolinks(value) {
|
|
1070
|
+
const withoutBareUrls = value.replace(
|
|
1071
|
+
bareUrlPattern,
|
|
1072
|
+
(match) => match.startsWith("www.") ? match.replace("www.", "www\\.") : match.replace("://", "\\://")
|
|
1073
|
+
);
|
|
1074
|
+
return withoutBareUrls.replace(
|
|
1075
|
+
bareEmailPattern,
|
|
1076
|
+
(_, prefix, email) => `${prefix}${email.replace("@", "\\@")}`
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
function escapeMarkdownText(value) {
|
|
1080
|
+
const escapedMarkdownText = value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replace(markdownSpecialCharacterPattern, "\\$&");
|
|
1081
|
+
return escapeBareAutolinks(escapedMarkdownText);
|
|
1082
|
+
}
|
|
1083
|
+
function toMarkdownSafeCell(value) {
|
|
1084
|
+
return splitCellLines(value).map((line) => escapeMarkdownText(line)).join("<br>");
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1068
1087
|
// src/render/report-header.ts
|
|
1088
|
+
import pc from "picocolors";
|
|
1069
1089
|
function getBoxWidth(content) {
|
|
1070
1090
|
return visibleWidth(content) + 4;
|
|
1071
1091
|
}
|
|
@@ -1188,12 +1208,68 @@ var defaultTerminalStylePalette = {
|
|
|
1188
1208
|
dim: pc2.dim
|
|
1189
1209
|
};
|
|
1190
1210
|
var passthroughStyler = (text) => text;
|
|
1211
|
+
var periodColumnIndex = 0;
|
|
1212
|
+
var sourceColumnIndex = 1;
|
|
1213
|
+
var modelsColumnIndex = 2;
|
|
1214
|
+
var totalColumnIndex = 8;
|
|
1215
|
+
var packedModelStartPattern = /(^| {2,})(?=• )/gu;
|
|
1191
1216
|
function styleCellLines(cell, styler) {
|
|
1192
|
-
return cell
|
|
1217
|
+
return splitCellLines(cell).map((line) => line.length === 0 ? "" : styler(line)).join("\n");
|
|
1218
|
+
}
|
|
1219
|
+
function styleModelsCell(cell, palette, options = {}) {
|
|
1220
|
+
const emphasizePrimaryWhenSingleLine = options.emphasizePrimaryWhenSingleLine ?? false;
|
|
1221
|
+
const primaryStyler = options.primaryStyler ?? palette.bold;
|
|
1222
|
+
const secondaryStyler = options.secondaryStyler ?? passthroughStyler;
|
|
1223
|
+
const totalStyler = options.totalStyler ?? ((text) => palette.bold(palette.green(text)));
|
|
1224
|
+
const lines = splitCellLines(cell);
|
|
1225
|
+
const modelEntryCount = lines.reduce((count, line) => {
|
|
1226
|
+
if (line === "\u03A3 TOTAL") {
|
|
1227
|
+
return count;
|
|
1228
|
+
}
|
|
1229
|
+
const segmentStarts = [...line.matchAll(packedModelStartPattern)];
|
|
1230
|
+
return count + segmentStarts.length;
|
|
1231
|
+
}, 0);
|
|
1232
|
+
const shouldEmphasizePrimary = emphasizePrimaryWhenSingleLine || modelEntryCount > 1;
|
|
1233
|
+
let currentStyler = shouldEmphasizePrimary ? primaryStyler : passthroughStyler;
|
|
1234
|
+
let modelLineCount = 0;
|
|
1235
|
+
return lines.map((line) => {
|
|
1236
|
+
if (line.length === 0) {
|
|
1237
|
+
return "";
|
|
1238
|
+
}
|
|
1239
|
+
if (line === "\u03A3 TOTAL") {
|
|
1240
|
+
currentStyler = totalStyler;
|
|
1241
|
+
return totalStyler(line);
|
|
1242
|
+
}
|
|
1243
|
+
const segmentStarts = [...line.matchAll(packedModelStartPattern)].map((match) => match.index);
|
|
1244
|
+
if (segmentStarts.length === 0) {
|
|
1245
|
+
return currentStyler(line);
|
|
1246
|
+
}
|
|
1247
|
+
const prefix = segmentStarts[0] > 0 ? currentStyler(line.slice(0, segmentStarts[0])) : "";
|
|
1248
|
+
let nextContinuationStyler = currentStyler;
|
|
1249
|
+
const renderedSegments = segmentStarts.map((segmentStart, segmentIndex) => {
|
|
1250
|
+
const segmentStyler = modelLineCount === 0 && shouldEmphasizePrimary ? primaryStyler : secondaryStyler;
|
|
1251
|
+
modelLineCount += 1;
|
|
1252
|
+
nextContinuationStyler = segmentStyler;
|
|
1253
|
+
const segmentEnd = segmentStarts[segmentIndex + 1] ?? line.length;
|
|
1254
|
+
return segmentStyler(line.slice(segmentStart, segmentEnd));
|
|
1255
|
+
}).join("");
|
|
1256
|
+
currentStyler = nextContinuationStyler;
|
|
1257
|
+
return prefix + renderedSegments;
|
|
1258
|
+
}).join("\n");
|
|
1259
|
+
}
|
|
1260
|
+
function styleCellAtIndex(cells, index, styler) {
|
|
1261
|
+
if (index < 0 || index >= cells.length) {
|
|
1262
|
+
return cells;
|
|
1263
|
+
}
|
|
1264
|
+
const styledCells = [...cells];
|
|
1265
|
+
styledCells[index] = styleCellLines(styledCells[index], styler);
|
|
1266
|
+
return styledCells;
|
|
1193
1267
|
}
|
|
1194
1268
|
var sourceStylePolicies = /* @__PURE__ */ new Map([
|
|
1195
1269
|
["pi", (palette) => palette.cyan],
|
|
1196
1270
|
["codex", (palette) => palette.magenta],
|
|
1271
|
+
["gemini", (palette) => palette.yellow],
|
|
1272
|
+
["droid", (palette) => palette.green],
|
|
1197
1273
|
["opencode", (palette) => palette.blue]
|
|
1198
1274
|
]);
|
|
1199
1275
|
function resolveSourceStyler(source, palette = defaultTerminalStylePalette) {
|
|
@@ -1203,28 +1279,98 @@ function resolveSourceStyler(source, palette = defaultTerminalStylePalette) {
|
|
|
1203
1279
|
}
|
|
1204
1280
|
return stylePolicy(palette);
|
|
1205
1281
|
}
|
|
1282
|
+
function getTrailingColumnIndex(cells) {
|
|
1283
|
+
return cells.length === 0 ? void 0 : cells.length - 1;
|
|
1284
|
+
}
|
|
1206
1285
|
var rowTypeStylePolicies = {
|
|
1207
1286
|
period_source: (cells, palette) => {
|
|
1208
|
-
|
|
1209
|
-
const
|
|
1210
|
-
|
|
1287
|
+
let styledCells = [...cells];
|
|
1288
|
+
const trailingColumnIndex = getTrailingColumnIndex(styledCells);
|
|
1289
|
+
if (modelsColumnIndex < styledCells.length) {
|
|
1290
|
+
styledCells[modelsColumnIndex] = styleModelsCell(styledCells[modelsColumnIndex], palette, {
|
|
1291
|
+
secondaryStyler: palette.dim
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
styledCells = styleCellAtIndex(styledCells, totalColumnIndex, palette.green);
|
|
1295
|
+
if (trailingColumnIndex !== void 0) {
|
|
1296
|
+
styledCells = styleCellAtIndex(
|
|
1297
|
+
styledCells,
|
|
1298
|
+
trailingColumnIndex,
|
|
1299
|
+
(line) => palette.bold(palette.yellow(line))
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
return styledCells;
|
|
1303
|
+
},
|
|
1304
|
+
period_combined: (cells, palette) => {
|
|
1305
|
+
let styledCells = [...cells];
|
|
1306
|
+
const trailingColumnIndex = getTrailingColumnIndex(styledCells);
|
|
1307
|
+
styledCells = styleCellAtIndex(styledCells, periodColumnIndex, palette.white);
|
|
1308
|
+
styledCells = styleCellAtIndex(
|
|
1309
|
+
styledCells,
|
|
1310
|
+
sourceColumnIndex,
|
|
1311
|
+
(line) => palette.bold(palette.yellow(line))
|
|
1312
|
+
);
|
|
1313
|
+
if (modelsColumnIndex < styledCells.length) {
|
|
1314
|
+
styledCells[modelsColumnIndex] = styleModelsCell(styledCells[modelsColumnIndex], palette, {
|
|
1315
|
+
secondaryStyler: palette.dim
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
styledCells = styleCellAtIndex(
|
|
1319
|
+
styledCells,
|
|
1320
|
+
totalColumnIndex,
|
|
1321
|
+
(line) => palette.bold(palette.green(line))
|
|
1322
|
+
);
|
|
1323
|
+
if (trailingColumnIndex !== void 0) {
|
|
1324
|
+
styledCells = styleCellAtIndex(
|
|
1325
|
+
styledCells,
|
|
1326
|
+
trailingColumnIndex,
|
|
1327
|
+
(line) => palette.bold(palette.yellow(line))
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1211
1330
|
return styledCells;
|
|
1212
1331
|
},
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1332
|
+
grand_total: (cells, palette) => {
|
|
1333
|
+
const styledCells = cells.map((cell, cellIndex) => {
|
|
1334
|
+
if (cellIndex === modelsColumnIndex) {
|
|
1335
|
+
return cell;
|
|
1336
|
+
}
|
|
1337
|
+
return styleCellLines(cell, palette.bold);
|
|
1338
|
+
});
|
|
1339
|
+
if (periodColumnIndex < styledCells.length) {
|
|
1340
|
+
styledCells[periodColumnIndex] = styleCellLines(
|
|
1341
|
+
cells[periodColumnIndex],
|
|
1342
|
+
(line) => palette.bold(palette.white(line))
|
|
1343
|
+
);
|
|
1216
1344
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1345
|
+
if (sourceColumnIndex < styledCells.length) {
|
|
1346
|
+
styledCells[sourceColumnIndex] = styleCellLines(
|
|
1347
|
+
cells[sourceColumnIndex],
|
|
1348
|
+
(line) => palette.bold(palette.green(line))
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
if (modelsColumnIndex < styledCells.length) {
|
|
1352
|
+
styledCells[modelsColumnIndex] = styleModelsCell(styledCells[modelsColumnIndex], palette, {
|
|
1353
|
+
emphasizePrimaryWhenSingleLine: true,
|
|
1354
|
+
primaryStyler: (line) => palette.bold(palette.white(line)),
|
|
1355
|
+
secondaryStyler: palette.dim,
|
|
1356
|
+
totalStyler: (line) => palette.bold(palette.green(line))
|
|
1357
|
+
});
|
|
1222
1358
|
}
|
|
1223
|
-
if (
|
|
1224
|
-
|
|
1359
|
+
if (totalColumnIndex < styledCells.length) {
|
|
1360
|
+
styledCells[totalColumnIndex] = styleCellLines(
|
|
1361
|
+
cells[totalColumnIndex],
|
|
1362
|
+
(line) => palette.bold(palette.green(line))
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
const trailingColumnIndex = getTrailingColumnIndex(styledCells);
|
|
1366
|
+
if (trailingColumnIndex !== void 0) {
|
|
1367
|
+
styledCells[trailingColumnIndex] = styleCellLines(
|
|
1368
|
+
cells[trailingColumnIndex],
|
|
1369
|
+
(line) => palette.bold(palette.yellow(line))
|
|
1370
|
+
);
|
|
1225
1371
|
}
|
|
1226
|
-
return
|
|
1227
|
-
}
|
|
1372
|
+
return styledCells;
|
|
1373
|
+
}
|
|
1228
1374
|
};
|
|
1229
1375
|
function applyRowTypeStyle(rowType, cells, palette = defaultTerminalStylePalette) {
|
|
1230
1376
|
return rowTypeStylePolicies[rowType](cells, palette);
|
|
@@ -1244,8 +1390,9 @@ function colorizeUsageBodyRows(bodyRows, rows, options) {
|
|
|
1244
1390
|
}
|
|
1245
1391
|
const palette = options.palette ?? defaultTerminalStylePalette;
|
|
1246
1392
|
return rows.map((row, index) => {
|
|
1393
|
+
const bodyRow = bodyRows[index] ?? [];
|
|
1247
1394
|
const sourceStyler = row.rowType === "period_source" ? resolveSourceStyler(String(row.source), palette) : passthroughStyler;
|
|
1248
|
-
const baseStyledCells = applyBaseCellStyle(
|
|
1395
|
+
const baseStyledCells = row.rowType === "period_source" ? applyBaseCellStyle(bodyRow, palette, sourceStyler) : [...bodyRow];
|
|
1249
1396
|
return applyRowTypeStyle(row.rowType, baseStyledCells, palette);
|
|
1250
1397
|
});
|
|
1251
1398
|
}
|
|
@@ -1348,7 +1495,7 @@ function getColumnAlignment(columnIndex, multilineColumnIndex) {
|
|
|
1348
1495
|
return "right";
|
|
1349
1496
|
}
|
|
1350
1497
|
function getVerticalAlignment(columnIndex, layout, multilineColumnIndex) {
|
|
1351
|
-
if (columnIndex
|
|
1498
|
+
if (columnIndex <= multilineColumnIndex) {
|
|
1352
1499
|
return "top";
|
|
1353
1500
|
}
|
|
1354
1501
|
return layout === "top_aligned" ? "top" : "middle";
|
|
@@ -1406,7 +1553,7 @@ function shouldDrawBodySeparator(index, rowMetas) {
|
|
|
1406
1553
|
}
|
|
1407
1554
|
const previousRow = rowMetas[index];
|
|
1408
1555
|
const nextRow = rowMetas[index + 1];
|
|
1409
|
-
return previousRow.rowKind === "combined" || nextRow.rowKind === "total" || previousRow.periodKey !== nextRow.periodKey;
|
|
1556
|
+
return previousRow.rowKind === "detail" && (nextRow.rowKind === "detail" || nextRow.rowKind === "combined") && previousRow.periodKey === nextRow.periodKey || previousRow.rowKind === "combined" || nextRow.rowKind === "total" || previousRow.periodKey !== nextRow.periodKey;
|
|
1410
1557
|
}
|
|
1411
1558
|
function getRowKindWeight(rowKind) {
|
|
1412
1559
|
switch (rowKind) {
|
|
@@ -1566,9 +1713,10 @@ function renderUnicodeTable(options) {
|
|
|
1566
1713
|
}
|
|
1567
1714
|
|
|
1568
1715
|
// src/render/terminal-table.ts
|
|
1569
|
-
var
|
|
1716
|
+
var modelsColumnIndex2 = 2;
|
|
1570
1717
|
var defaultModelsColumnWidth = 32;
|
|
1571
1718
|
var minimumModelsColumnWidth = 12;
|
|
1719
|
+
var compactModelsColumnGap = 2;
|
|
1572
1720
|
function shouldUseColorByDefault() {
|
|
1573
1721
|
if (process.env.NO_COLOR !== void 0) {
|
|
1574
1722
|
return false;
|
|
@@ -1584,7 +1732,28 @@ function colorizeHeader(useColor) {
|
|
|
1584
1732
|
if (!useColor) {
|
|
1585
1733
|
return headerCells;
|
|
1586
1734
|
}
|
|
1587
|
-
return headerCells.map((header) =>
|
|
1735
|
+
return headerCells.map((header, index) => {
|
|
1736
|
+
switch (index) {
|
|
1737
|
+
case 1:
|
|
1738
|
+
return pc3.bold(pc3.cyan(header));
|
|
1739
|
+
case 2:
|
|
1740
|
+
return pc3.bold(pc3.magenta(header));
|
|
1741
|
+
case 3:
|
|
1742
|
+
case 6:
|
|
1743
|
+
return pc3.bold(pc3.blue(header));
|
|
1744
|
+
case 4:
|
|
1745
|
+
case 7:
|
|
1746
|
+
return pc3.bold(pc3.cyan(header));
|
|
1747
|
+
case 5:
|
|
1748
|
+
return pc3.bold(pc3.magenta(header));
|
|
1749
|
+
case 8:
|
|
1750
|
+
return pc3.bold(pc3.green(header));
|
|
1751
|
+
case 9:
|
|
1752
|
+
return pc3.bold(pc3.yellow(header));
|
|
1753
|
+
default:
|
|
1754
|
+
return pc3.bold(pc3.white(header));
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1588
1757
|
}
|
|
1589
1758
|
function isValidTerminalWidth(width) {
|
|
1590
1759
|
return typeof width === "number" && Number.isFinite(width) && width > 0;
|
|
@@ -1598,12 +1767,119 @@ function resolveTerminalWidth(override) {
|
|
|
1598
1767
|
function measureTableWidth(tableOutput) {
|
|
1599
1768
|
return tableOutput.trimEnd().split("\n").reduce((maxWidth, line) => Math.max(maxWidth, visibleWidth(line)), 0);
|
|
1600
1769
|
}
|
|
1601
|
-
function
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1770
|
+
function padVisibleEnd(value, width) {
|
|
1771
|
+
return `${value}${" ".repeat(Math.max(0, width - visibleWidth(value)))}`;
|
|
1772
|
+
}
|
|
1773
|
+
function formatCompactModelsCell(value, width) {
|
|
1774
|
+
const modelLines = splitCellLines(value);
|
|
1775
|
+
if (modelLines.length < 2) {
|
|
1776
|
+
return value;
|
|
1777
|
+
}
|
|
1778
|
+
const longestLineWidth = modelLines.reduce(
|
|
1779
|
+
(maxWidth, line) => Math.max(maxWidth, visibleWidth(line)),
|
|
1780
|
+
0
|
|
1781
|
+
);
|
|
1782
|
+
const maxColumnCount = Math.floor(
|
|
1783
|
+
(width + compactModelsColumnGap) / (longestLineWidth + compactModelsColumnGap)
|
|
1784
|
+
);
|
|
1785
|
+
if (maxColumnCount <= 1) {
|
|
1786
|
+
return value;
|
|
1787
|
+
}
|
|
1788
|
+
const columnCount = Math.min(modelLines.length, maxColumnCount);
|
|
1789
|
+
const rowCount = Math.ceil(modelLines.length / columnCount);
|
|
1790
|
+
const compactLines = [];
|
|
1791
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
|
|
1792
|
+
const rowStart = rowIndex * columnCount;
|
|
1793
|
+
const cells = modelLines.slice(rowStart, rowStart + columnCount);
|
|
1794
|
+
compactLines.push(
|
|
1795
|
+
cells.map(
|
|
1796
|
+
(cell, columnIndex) => columnIndex === cells.length - 1 ? cell : padVisibleEnd(cell, longestLineWidth)
|
|
1797
|
+
).join(" ".repeat(compactModelsColumnGap))
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
return compactLines.join("\n");
|
|
1801
|
+
}
|
|
1802
|
+
function layoutModelsColumn(bodyRows, tableLayout, modelsColumnWidth) {
|
|
1803
|
+
if (tableLayout !== "compact" || modelsColumnWidth <= defaultModelsColumnWidth) {
|
|
1804
|
+
return bodyRows.map((row) => [...row]);
|
|
1805
|
+
}
|
|
1806
|
+
return bodyRows.map((row) => {
|
|
1807
|
+
const nextRow = [...row];
|
|
1808
|
+
nextRow[modelsColumnIndex2] = formatCompactModelsCell(
|
|
1809
|
+
nextRow[modelsColumnIndex2],
|
|
1810
|
+
modelsColumnWidth
|
|
1811
|
+
);
|
|
1812
|
+
return nextRow;
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
function prepareWrappedBodyRows(bodyRows, tableLayout, modelsColumnWidth) {
|
|
1816
|
+
const laidOutRows = layoutModelsColumn(bodyRows, tableLayout, modelsColumnWidth);
|
|
1817
|
+
return wrapTableColumn(laidOutRows, {
|
|
1818
|
+
columnIndex: modelsColumnIndex2,
|
|
1605
1819
|
width: modelsColumnWidth
|
|
1606
1820
|
});
|
|
1821
|
+
}
|
|
1822
|
+
function measureCompactBodyHeight(bodyRows, modelsColumnWidth) {
|
|
1823
|
+
return prepareWrappedBodyRows(bodyRows, "compact", modelsColumnWidth).reduce(
|
|
1824
|
+
(totalHeight, row) => totalHeight + splitCellLines(row[modelsColumnIndex2] ?? "").length,
|
|
1825
|
+
0
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
function resolveExpandedModelsColumnWidth(bodyRows, tableLayout, currentWidth, maximumWidth) {
|
|
1829
|
+
if (maximumWidth <= currentWidth) {
|
|
1830
|
+
return currentWidth;
|
|
1831
|
+
}
|
|
1832
|
+
if (tableLayout === "per_model_columns") {
|
|
1833
|
+
const longestModelLineWidth = bodyRows.reduce((maxWidth, row) => {
|
|
1834
|
+
const cellMaxWidth = splitCellLines(row[modelsColumnIndex2] ?? "").reduce(
|
|
1835
|
+
(lineMaxWidth, line) => Math.max(lineMaxWidth, visibleWidth(line)),
|
|
1836
|
+
0
|
|
1837
|
+
);
|
|
1838
|
+
return Math.max(maxWidth, cellMaxWidth);
|
|
1839
|
+
}, currentWidth);
|
|
1840
|
+
const preferredWidth = Math.max(
|
|
1841
|
+
currentWidth,
|
|
1842
|
+
defaultModelsColumnWidth + 16,
|
|
1843
|
+
longestModelLineWidth
|
|
1844
|
+
);
|
|
1845
|
+
return Math.min(maximumWidth, preferredWidth);
|
|
1846
|
+
}
|
|
1847
|
+
const candidateWidths = /* @__PURE__ */ new Set([currentWidth]);
|
|
1848
|
+
for (const row of bodyRows) {
|
|
1849
|
+
const modelLines = splitCellLines(row[modelsColumnIndex2] ?? "");
|
|
1850
|
+
const longestLineWidth = modelLines.reduce(
|
|
1851
|
+
(maxLineWidth, line) => Math.max(maxLineWidth, visibleWidth(line)),
|
|
1852
|
+
0
|
|
1853
|
+
);
|
|
1854
|
+
if (longestLineWidth > currentWidth && longestLineWidth <= maximumWidth) {
|
|
1855
|
+
candidateWidths.add(longestLineWidth);
|
|
1856
|
+
}
|
|
1857
|
+
if (modelLines.length < 2) {
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
for (let columnCount = 2; columnCount <= modelLines.length; columnCount += 1) {
|
|
1861
|
+
const candidateWidth = columnCount * longestLineWidth + (columnCount - 1) * compactModelsColumnGap;
|
|
1862
|
+
if (candidateWidth > maximumWidth) {
|
|
1863
|
+
break;
|
|
1864
|
+
}
|
|
1865
|
+
if (candidateWidth > currentWidth) {
|
|
1866
|
+
candidateWidths.add(candidateWidth);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
let bestWidth = currentWidth;
|
|
1871
|
+
let bestHeight = measureCompactBodyHeight(bodyRows, currentWidth);
|
|
1872
|
+
for (const candidateWidth of Array.from(candidateWidths).sort((left, right) => left - right)) {
|
|
1873
|
+
const candidateHeight = measureCompactBodyHeight(bodyRows, candidateWidth);
|
|
1874
|
+
if (candidateHeight < bestHeight) {
|
|
1875
|
+
bestHeight = candidateHeight;
|
|
1876
|
+
bestWidth = candidateWidth;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
return bestWidth;
|
|
1880
|
+
}
|
|
1881
|
+
function renderTableWithModelsWidth(rows, uncoloredBodyRows, tableLayout, useColor, modelsColumnWidth) {
|
|
1882
|
+
const wrappedBodyRows = prepareWrappedBodyRows(uncoloredBodyRows, tableLayout, modelsColumnWidth);
|
|
1607
1883
|
const bodyRows = colorizeUsageBodyRows(wrappedBodyRows, rows, { useColor });
|
|
1608
1884
|
const rowMetas = rows.map((row) => ({
|
|
1609
1885
|
periodKey: row.periodKey,
|
|
@@ -1617,7 +1893,7 @@ function renderTableWithModelsWidth(rows, tableLayout, useColor, modelsColumnWid
|
|
|
1617
1893
|
measureBodyRows: wrappedBodyRows,
|
|
1618
1894
|
rowMetas,
|
|
1619
1895
|
layout: tableLayout === "per_model_columns" ? "top_aligned" : "compact",
|
|
1620
|
-
multilineColumnIndex:
|
|
1896
|
+
multilineColumnIndex: modelsColumnIndex2,
|
|
1621
1897
|
multilineColumnWidth: modelsColumnWidth
|
|
1622
1898
|
});
|
|
1623
1899
|
}
|
|
@@ -1626,8 +1902,15 @@ function renderTerminalTable(rows, options = {}) {
|
|
|
1626
1902
|
const tableLayout = options.tableLayout ?? "compact";
|
|
1627
1903
|
const hasExplicitTerminalWidth = isValidTerminalWidth(options.terminalWidth);
|
|
1628
1904
|
const terminalWidth = resolveTerminalWidth(options.terminalWidth);
|
|
1905
|
+
const uncoloredBodyRows = toUsageTableCells(rows, { layout: tableLayout });
|
|
1629
1906
|
let modelsColumnWidth = defaultModelsColumnWidth;
|
|
1630
|
-
let renderedTable = renderTableWithModelsWidth(
|
|
1907
|
+
let renderedTable = renderTableWithModelsWidth(
|
|
1908
|
+
rows,
|
|
1909
|
+
uncoloredBodyRows,
|
|
1910
|
+
tableLayout,
|
|
1911
|
+
useColor,
|
|
1912
|
+
modelsColumnWidth
|
|
1913
|
+
);
|
|
1631
1914
|
if (terminalWidth !== void 0) {
|
|
1632
1915
|
let renderedTableWidth = measureTableWidth(renderedTable);
|
|
1633
1916
|
while (renderedTableWidth > terminalWidth && modelsColumnWidth > minimumModelsColumnWidth) {
|
|
@@ -1640,9 +1923,35 @@ function renderTerminalTable(rows, options = {}) {
|
|
|
1640
1923
|
break;
|
|
1641
1924
|
}
|
|
1642
1925
|
modelsColumnWidth = nextModelsColumnWidth;
|
|
1643
|
-
renderedTable = renderTableWithModelsWidth(
|
|
1926
|
+
renderedTable = renderTableWithModelsWidth(
|
|
1927
|
+
rows,
|
|
1928
|
+
uncoloredBodyRows,
|
|
1929
|
+
tableLayout,
|
|
1930
|
+
useColor,
|
|
1931
|
+
modelsColumnWidth
|
|
1932
|
+
);
|
|
1644
1933
|
renderedTableWidth = measureTableWidth(renderedTable);
|
|
1645
1934
|
}
|
|
1935
|
+
if (renderedTableWidth < terminalWidth) {
|
|
1936
|
+
const maximumWidth = modelsColumnWidth + (terminalWidth - renderedTableWidth);
|
|
1937
|
+
const expandedWidth = resolveExpandedModelsColumnWidth(
|
|
1938
|
+
uncoloredBodyRows,
|
|
1939
|
+
tableLayout,
|
|
1940
|
+
modelsColumnWidth,
|
|
1941
|
+
maximumWidth
|
|
1942
|
+
);
|
|
1943
|
+
if (expandedWidth > modelsColumnWidth) {
|
|
1944
|
+
modelsColumnWidth = expandedWidth;
|
|
1945
|
+
renderedTable = renderTableWithModelsWidth(
|
|
1946
|
+
rows,
|
|
1947
|
+
uncoloredBodyRows,
|
|
1948
|
+
tableLayout,
|
|
1949
|
+
useColor,
|
|
1950
|
+
modelsColumnWidth
|
|
1951
|
+
);
|
|
1952
|
+
renderedTableWidth = measureTableWidth(renderedTable);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1646
1955
|
if (hasExplicitTerminalWidth && renderedTableWidth > terminalWidth) {
|
|
1647
1956
|
throw new Error(
|
|
1648
1957
|
`Configured terminal width (${terminalWidth}) is too narrow for table rendering (minimum ${renderedTableWidth}).`
|
|
@@ -1653,7 +1962,7 @@ function renderTerminalTable(rows, options = {}) {
|
|
|
1653
1962
|
}
|
|
1654
1963
|
|
|
1655
1964
|
// src/render/render-efficiency-report.ts
|
|
1656
|
-
var
|
|
1965
|
+
var periodColumnIndex2 = 0;
|
|
1657
1966
|
var minimumEfficiencyColumnWidth = 1;
|
|
1658
1967
|
var commitsColumnIndex = 1;
|
|
1659
1968
|
var linesAddedColumnIndex = 2;
|
|
@@ -1793,8 +2102,8 @@ function styleEfficiencyTerminalRows(rows, bodyRows, options) {
|
|
|
1793
2102
|
}
|
|
1794
2103
|
const row = rows[rowIndex];
|
|
1795
2104
|
const styledCells = [...cells];
|
|
1796
|
-
const periodCell = styledCells[
|
|
1797
|
-
styledCells[
|
|
2105
|
+
const periodCell = styledCells[periodColumnIndex2];
|
|
2106
|
+
styledCells[periodColumnIndex2] = row.rowType === "grand_total" ? pc4.bold(pc4.cyan(periodCell)) : pc4.bold(periodCell);
|
|
1798
2107
|
styledCells[commitsColumnIndex] = pc4.bold(styledCells[commitsColumnIndex]);
|
|
1799
2108
|
styledCells[linesAddedColumnIndex] = styleDeltaCell(
|
|
1800
2109
|
row.linesAdded,
|
|
@@ -1844,13 +2153,10 @@ function renderTerminalEfficiencyTable(rows, options) {
|
|
|
1844
2153
|
measureBodyRows: fittedCells.bodyRows,
|
|
1845
2154
|
rowMetas,
|
|
1846
2155
|
layout: "compact",
|
|
1847
|
-
multilineColumnIndex:
|
|
1848
|
-
multilineColumnWidth: fittedCells.widths[
|
|
2156
|
+
multilineColumnIndex: periodColumnIndex2,
|
|
2157
|
+
multilineColumnWidth: fittedCells.widths[periodColumnIndex2] ?? efficiencyTableHeaders[periodColumnIndex2].length
|
|
1849
2158
|
});
|
|
1850
2159
|
}
|
|
1851
|
-
function toMarkdownSafeCell(value) {
|
|
1852
|
-
return value.replace(/\r?\n/gu, "<br>");
|
|
1853
|
-
}
|
|
1854
2160
|
function renderMarkdownEfficiencyTable(rows) {
|
|
1855
2161
|
const bodyRows = toEfficiencyTableCells(rows).map(
|
|
1856
2162
|
(row) => row.map((cell) => toMarkdownSafeCell(cell))
|
|
@@ -1908,52 +2214,6 @@ var logger = {
|
|
|
1908
2214
|
}
|
|
1909
2215
|
};
|
|
1910
2216
|
|
|
1911
|
-
// src/domain/normalization.ts
|
|
1912
|
-
function normalizeNonNegativeInteger(value) {
|
|
1913
|
-
if (value === null || value === void 0) {
|
|
1914
|
-
return 0;
|
|
1915
|
-
}
|
|
1916
|
-
const parsed = typeof value === "number" ? value : Number(value);
|
|
1917
|
-
if (!Number.isFinite(parsed)) {
|
|
1918
|
-
return 0;
|
|
1919
|
-
}
|
|
1920
|
-
return Math.max(0, Math.trunc(parsed));
|
|
1921
|
-
}
|
|
1922
|
-
function normalizeUsdCost(value) {
|
|
1923
|
-
if (value === null || value === void 0) {
|
|
1924
|
-
return void 0;
|
|
1925
|
-
}
|
|
1926
|
-
if (typeof value === "string" && value.trim() === "") {
|
|
1927
|
-
return void 0;
|
|
1928
|
-
}
|
|
1929
|
-
const parsed = typeof value === "number" ? value : Number(value);
|
|
1930
|
-
if (!Number.isFinite(parsed)) {
|
|
1931
|
-
return void 0;
|
|
1932
|
-
}
|
|
1933
|
-
return Math.max(0, parsed);
|
|
1934
|
-
}
|
|
1935
|
-
function normalizeTimestamp(value) {
|
|
1936
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
1937
|
-
if (Number.isNaN(date.getTime())) {
|
|
1938
|
-
throw new Error(`Invalid timestamp: ${String(value)}`);
|
|
1939
|
-
}
|
|
1940
|
-
return date.toISOString();
|
|
1941
|
-
}
|
|
1942
|
-
function normalizeModelList(models) {
|
|
1943
|
-
const deduplicated = /* @__PURE__ */ new Set();
|
|
1944
|
-
for (const model of models) {
|
|
1945
|
-
if (!model) {
|
|
1946
|
-
continue;
|
|
1947
|
-
}
|
|
1948
|
-
const normalized = model.trim();
|
|
1949
|
-
if (!normalized) {
|
|
1950
|
-
continue;
|
|
1951
|
-
}
|
|
1952
|
-
deduplicated.add(normalized);
|
|
1953
|
-
}
|
|
1954
|
-
return [...deduplicated].sort(compareByCodePoint);
|
|
1955
|
-
}
|
|
1956
|
-
|
|
1957
2217
|
// src/utils/time-buckets.ts
|
|
1958
2218
|
var formatterCache = /* @__PURE__ */ new Map();
|
|
1959
2219
|
function getDateFormatter(timezone) {
|
|
@@ -2138,15 +2398,29 @@ function mergeModelTotals(targetModelTotals, sourceModelTotals) {
|
|
|
2138
2398
|
targetModelTotals.set(model, targetTotals);
|
|
2139
2399
|
}
|
|
2140
2400
|
}
|
|
2141
|
-
function
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
}
|
|
2401
|
+
function compareModelUsageBreakdown(left, right) {
|
|
2402
|
+
if (left.totalTokens !== right.totalTokens) {
|
|
2403
|
+
return right.totalTokens - left.totalTokens;
|
|
2404
|
+
}
|
|
2405
|
+
const leftCost = left.costUsd ?? Number.NEGATIVE_INFINITY;
|
|
2406
|
+
const rightCost = right.costUsd ?? Number.NEGATIVE_INFINITY;
|
|
2407
|
+
if (leftCost !== rightCost) {
|
|
2408
|
+
return rightCost - leftCost;
|
|
2409
|
+
}
|
|
2410
|
+
if (left.inputTokens !== right.inputTokens) {
|
|
2411
|
+
return right.inputTokens - left.inputTokens;
|
|
2412
|
+
}
|
|
2413
|
+
return compareByCodePoint(left.model, right.model);
|
|
2414
|
+
}
|
|
2415
|
+
function toRankedModelUsage(modelTotals) {
|
|
2416
|
+
const modelBreakdown = [...modelTotals.entries()].map(([model, totals]) => ({
|
|
2417
|
+
model,
|
|
2418
|
+
...totals
|
|
2419
|
+
})).sort(compareModelUsageBreakdown);
|
|
2420
|
+
return {
|
|
2421
|
+
models: modelBreakdown.map((modelUsage) => modelUsage.model),
|
|
2422
|
+
modelBreakdown
|
|
2423
|
+
};
|
|
2150
2424
|
}
|
|
2151
2425
|
function sourceSortComparator(left, right, sourceWeightMap) {
|
|
2152
2426
|
const leftWeight = sourceWeightMap.get(left) ?? Number.MAX_SAFE_INTEGER;
|
|
@@ -2190,12 +2464,13 @@ function aggregateUsage(events, options) {
|
|
|
2190
2464
|
if (!accumulator) {
|
|
2191
2465
|
continue;
|
|
2192
2466
|
}
|
|
2467
|
+
const rankedModelUsage = includeModelBreakdown && accumulator.modelTotals ? toRankedModelUsage(accumulator.modelTotals) : { models: [], modelBreakdown: [] };
|
|
2193
2468
|
const sourceRow = {
|
|
2194
2469
|
rowType: "period_source",
|
|
2195
2470
|
periodKey,
|
|
2196
2471
|
source,
|
|
2197
|
-
models:
|
|
2198
|
-
modelBreakdown:
|
|
2472
|
+
models: rankedModelUsage.models,
|
|
2473
|
+
modelBreakdown: rankedModelUsage.modelBreakdown,
|
|
2199
2474
|
...accumulator.totals
|
|
2200
2475
|
};
|
|
2201
2476
|
rows.push(sourceRow);
|
|
@@ -2207,24 +2482,26 @@ function aggregateUsage(events, options) {
|
|
|
2207
2482
|
}
|
|
2208
2483
|
}
|
|
2209
2484
|
if (sortedSources.length > 1) {
|
|
2485
|
+
const rankedCombinedModels = includeModelBreakdown ? toRankedModelUsage(periodCombinedModelTotals) : { models: [], modelBreakdown: [] };
|
|
2210
2486
|
const combinedRow = {
|
|
2211
2487
|
rowType: "period_combined",
|
|
2212
2488
|
periodKey,
|
|
2213
2489
|
source: "combined",
|
|
2214
|
-
models:
|
|
2215
|
-
modelBreakdown:
|
|
2490
|
+
models: rankedCombinedModels.models,
|
|
2491
|
+
modelBreakdown: rankedCombinedModels.modelBreakdown,
|
|
2216
2492
|
...periodCombinedTotals
|
|
2217
2493
|
};
|
|
2218
2494
|
rows.push(combinedRow);
|
|
2219
2495
|
}
|
|
2220
2496
|
}
|
|
2221
2497
|
const finalizedGrandTotals = events.length === 0 && grandTotals.costUsd === void 0 && grandTotals.costIncomplete !== true ? { ...grandTotals, costUsd: 0 } : grandTotals;
|
|
2498
|
+
const rankedGrandModels = includeModelBreakdown ? toRankedModelUsage(grandModelTotals) : { models: [], modelBreakdown: [] };
|
|
2222
2499
|
const grandTotalRow = {
|
|
2223
2500
|
rowType: "grand_total",
|
|
2224
2501
|
periodKey: "ALL",
|
|
2225
2502
|
source: "combined",
|
|
2226
|
-
models:
|
|
2227
|
-
modelBreakdown:
|
|
2503
|
+
models: rankedGrandModels.models,
|
|
2504
|
+
modelBreakdown: rankedGrandModels.modelBreakdown,
|
|
2228
2505
|
...finalizedGrandTotals
|
|
2229
2506
|
};
|
|
2230
2507
|
rows.push(grandTotalRow);
|
|
@@ -2858,6 +3135,38 @@ async function attributeUsageEventsToRepo(events, repoDir, resolveRepoRoot3 = re
|
|
|
2858
3135
|
};
|
|
2859
3136
|
}
|
|
2860
3137
|
|
|
3138
|
+
// src/domain/normalization.ts
|
|
3139
|
+
function normalizeNonNegativeInteger(value) {
|
|
3140
|
+
if (value === null || value === void 0) {
|
|
3141
|
+
return 0;
|
|
3142
|
+
}
|
|
3143
|
+
const parsed = typeof value === "number" ? value : Number(value);
|
|
3144
|
+
if (!Number.isFinite(parsed)) {
|
|
3145
|
+
return 0;
|
|
3146
|
+
}
|
|
3147
|
+
return Math.max(0, Math.trunc(parsed));
|
|
3148
|
+
}
|
|
3149
|
+
function normalizeUsdCost(value) {
|
|
3150
|
+
if (value === null || value === void 0) {
|
|
3151
|
+
return void 0;
|
|
3152
|
+
}
|
|
3153
|
+
if (typeof value === "string" && value.trim() === "") {
|
|
3154
|
+
return void 0;
|
|
3155
|
+
}
|
|
3156
|
+
const parsed = typeof value === "number" ? value : Number(value);
|
|
3157
|
+
if (!Number.isFinite(parsed)) {
|
|
3158
|
+
return void 0;
|
|
3159
|
+
}
|
|
3160
|
+
return Math.max(0, parsed);
|
|
3161
|
+
}
|
|
3162
|
+
function normalizeTimestamp(value) {
|
|
3163
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
3164
|
+
if (Number.isNaN(date.getTime())) {
|
|
3165
|
+
throw new Error(`Invalid timestamp: ${String(value)}`);
|
|
3166
|
+
}
|
|
3167
|
+
return date.toISOString();
|
|
3168
|
+
}
|
|
3169
|
+
|
|
2861
3170
|
// src/domain/provider-normalization.ts
|
|
2862
3171
|
var billingProviderAliases = /* @__PURE__ */ new Map([
|
|
2863
3172
|
["openai-codex", "openai"],
|
|
@@ -7529,9 +7838,6 @@ function toTableCells(optimizeData, options) {
|
|
|
7529
7838
|
return options.includeNotesColumn ? [...candidateCells, styleNotesCell(row.notes, notesCell, options.useColor)] : candidateCells;
|
|
7530
7839
|
});
|
|
7531
7840
|
}
|
|
7532
|
-
function toMarkdownSafeCell2(value) {
|
|
7533
|
-
return value.replace(/\r?\n/gu, "<br>");
|
|
7534
|
-
}
|
|
7535
7841
|
function toTableRowMeta2(row) {
|
|
7536
7842
|
return {
|
|
7537
7843
|
periodKey: row.periodKey,
|
|
@@ -7587,7 +7893,7 @@ function renderMarkdownOptimizeReport(optimizeData) {
|
|
|
7587
7893
|
const bodyRows = toTableCells(optimizeData, {
|
|
7588
7894
|
useColor: false,
|
|
7589
7895
|
includeNotesColumn
|
|
7590
|
-
}).map((row) => row.map((cell) =>
|
|
7896
|
+
}).map((row) => row.map((cell) => toMarkdownSafeCell(cell)));
|
|
7591
7897
|
const tableRows = [headerCells, ...bodyRows];
|
|
7592
7898
|
const alignment2 = headerCells.map((_, index) => index <= 1 ? "l" : "r");
|
|
7593
7899
|
return markdownTable2(tableRows, { align: alignment2 });
|
|
@@ -8916,13 +9222,59 @@ async function buildUsageData(granularity, options, deps = {}) {
|
|
|
8916
9222
|
// src/render/markdown-table.ts
|
|
8917
9223
|
import { markdownTable as markdownTable3 } from "markdown-table";
|
|
8918
9224
|
var alignment = ["l", "l", "l", "r", "r", "r", "r", "r", "r", "r"];
|
|
8919
|
-
function
|
|
8920
|
-
|
|
9225
|
+
function boldMarkdownText(value) {
|
|
9226
|
+
const safeValue = toMarkdownSafeCell(value);
|
|
9227
|
+
return safeValue.length === 0 ? safeValue : `**${safeValue}**`;
|
|
9228
|
+
}
|
|
9229
|
+
function emphasizeMarkdownModelsCell(value) {
|
|
9230
|
+
const lines = splitCellLines(value);
|
|
9231
|
+
return lines.map((line, index) => {
|
|
9232
|
+
if (line.length === 0) {
|
|
9233
|
+
return "";
|
|
9234
|
+
}
|
|
9235
|
+
if (line === "\u03A3 TOTAL") {
|
|
9236
|
+
return boldMarkdownText(line);
|
|
9237
|
+
}
|
|
9238
|
+
if (index === 0 && lines.length > 1) {
|
|
9239
|
+
return boldMarkdownText(line);
|
|
9240
|
+
}
|
|
9241
|
+
return toMarkdownSafeCell(line);
|
|
9242
|
+
}).join("<br>");
|
|
9243
|
+
}
|
|
9244
|
+
function emphasizeMarkdownSummaryMetricCell(value) {
|
|
9245
|
+
const lines = splitCellLines(value);
|
|
9246
|
+
if (lines.length <= 1) {
|
|
9247
|
+
return boldMarkdownText(value);
|
|
9248
|
+
}
|
|
9249
|
+
return lines.map(
|
|
9250
|
+
(line, index) => index === lines.length - 1 ? boldMarkdownText(line) : toMarkdownSafeCell(line)
|
|
9251
|
+
).join("<br>");
|
|
9252
|
+
}
|
|
9253
|
+
function emphasizeMarkdownRow(row, cells) {
|
|
9254
|
+
const styledCells = cells.map((cell) => toMarkdownSafeCell(cell));
|
|
9255
|
+
if (styledCells.length > 2) {
|
|
9256
|
+
styledCells[2] = emphasizeMarkdownModelsCell(cells[2]);
|
|
9257
|
+
}
|
|
9258
|
+
if (row.rowType !== "period_source") {
|
|
9259
|
+
if (styledCells.length > 1) {
|
|
9260
|
+
styledCells[1] = boldMarkdownText(cells[1]);
|
|
9261
|
+
}
|
|
9262
|
+
if (styledCells.length > 8) {
|
|
9263
|
+
styledCells[8] = emphasizeMarkdownSummaryMetricCell(cells[8]);
|
|
9264
|
+
}
|
|
9265
|
+
if (styledCells.length > 9) {
|
|
9266
|
+
styledCells[9] = emphasizeMarkdownSummaryMetricCell(cells[9]);
|
|
9267
|
+
}
|
|
9268
|
+
}
|
|
9269
|
+
if (row.rowType === "grand_total" && styledCells.length > 0) {
|
|
9270
|
+
styledCells[0] = boldMarkdownText(cells[0]);
|
|
9271
|
+
}
|
|
9272
|
+
return styledCells;
|
|
8921
9273
|
}
|
|
8922
9274
|
function renderMarkdownTable(rows, options = {}) {
|
|
8923
9275
|
const tableLayout = options.tableLayout ?? "compact";
|
|
8924
9276
|
const bodyRows = toUsageTableCells(rows, { layout: tableLayout }).map(
|
|
8925
|
-
(
|
|
9277
|
+
(cells, index) => emphasizeMarkdownRow(rows[index], cells)
|
|
8926
9278
|
);
|
|
8927
9279
|
const tableRows = [Array.from(usageTableHeaders), ...bodyRows];
|
|
8928
9280
|
return markdownTable3(tableRows, {
|