ccclub 0.3.7 → 0.3.9
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/dist/index.js +103 -75
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command, Option } from "commander";
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
8
8
|
import { stdin, stdout } from "process";
|
|
9
|
-
import
|
|
9
|
+
import chalk5 from "chalk";
|
|
10
10
|
import ora2 from "ora";
|
|
11
11
|
|
|
12
12
|
// src/config.ts
|
|
@@ -991,6 +991,7 @@ function aggregateSourceToBlocks(source, entries, humanTurns) {
|
|
|
991
991
|
let reasoningTokens = 0;
|
|
992
992
|
let totalTokens = 0;
|
|
993
993
|
let costUSD = 0;
|
|
994
|
+
let lastActivityMs = 0;
|
|
994
995
|
for (const entry of currentBlock) {
|
|
995
996
|
inputTokens += entry.inputTokens;
|
|
996
997
|
outputTokens += entry.outputTokens;
|
|
@@ -1011,11 +1012,14 @@ function aggregateSourceToBlocks(source, entries, humanTurns) {
|
|
|
1011
1012
|
entry.reasoningTokens || 0
|
|
1012
1013
|
);
|
|
1013
1014
|
}
|
|
1015
|
+
const entryMs = new Date(entry.timestamp).getTime();
|
|
1016
|
+
if (Number.isFinite(entryMs) && entryMs > lastActivityMs) lastActivityMs = entryMs;
|
|
1014
1017
|
}
|
|
1015
1018
|
blocks.push({
|
|
1016
1019
|
source,
|
|
1017
1020
|
blockStart: blockStart.toISOString(),
|
|
1018
1021
|
blockEnd: blockEnd.toISOString(),
|
|
1022
|
+
lastActivityAt: new Date(lastActivityMs || blockEnd.getTime()).toISOString(),
|
|
1019
1023
|
inputTokens,
|
|
1020
1024
|
outputTokens,
|
|
1021
1025
|
cacheCreationTokens,
|
|
@@ -1355,7 +1359,32 @@ function getLatestBlockStartBySource(blocks) {
|
|
|
1355
1359
|
|
|
1356
1360
|
// src/global-install.ts
|
|
1357
1361
|
import { exec as exec2 } from "child_process";
|
|
1362
|
+
import chalk4 from "chalk";
|
|
1363
|
+
|
|
1364
|
+
// src/theme.ts
|
|
1358
1365
|
import chalk3 from "chalk";
|
|
1366
|
+
var theme = {
|
|
1367
|
+
title: chalk3.hex("#F1EDE7").bold,
|
|
1368
|
+
text: chalk3.hex("#E8E4DE"),
|
|
1369
|
+
muted: chalk3.hex("#8A8480"),
|
|
1370
|
+
faint: chalk3.hex("#5A5550"),
|
|
1371
|
+
brand: chalk3.hex("#D4935E"),
|
|
1372
|
+
link: chalk3.hex("#7AB7C6").underline,
|
|
1373
|
+
linkText: chalk3.hex("#7AB7C6"),
|
|
1374
|
+
success: chalk3.hex("#63B486"),
|
|
1375
|
+
successBold: chalk3.hex("#63B486").bold,
|
|
1376
|
+
gold: chalk3.hex("#D6B56D"),
|
|
1377
|
+
goldBold: chalk3.hex("#D6B56D").bold,
|
|
1378
|
+
silver: chalk3.hex("#AEB7BF"),
|
|
1379
|
+
silverBold: chalk3.hex("#AEB7BF").bold,
|
|
1380
|
+
bronze: chalk3.hex("#C58A61"),
|
|
1381
|
+
bronzeBold: chalk3.hex("#C58A61"),
|
|
1382
|
+
warning: chalk3.hex("#D4A85C"),
|
|
1383
|
+
warningBold: chalk3.hex("#D4A85C").bold,
|
|
1384
|
+
danger: chalk3.hex("#D26A6A")
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
// src/global-install.ts
|
|
1359
1388
|
function run(cmd) {
|
|
1360
1389
|
return new Promise((resolve2) => {
|
|
1361
1390
|
exec2(cmd, (err, stdout5) => resolve2(err ? "" : stdout5.trim()));
|
|
@@ -1364,13 +1393,13 @@ function run(cmd) {
|
|
|
1364
1393
|
async function ensureGlobalInstall() {
|
|
1365
1394
|
const globalList = await run("npm list -g ccclub --depth=0");
|
|
1366
1395
|
if (globalList.includes("ccclub@")) return;
|
|
1367
|
-
console.log(
|
|
1396
|
+
console.log(chalk4.dim("\n Installing ccclub globally so you can run it directly..."));
|
|
1368
1397
|
const result = await run("npm install -g ccclub");
|
|
1369
1398
|
if (result) {
|
|
1370
|
-
console.log(
|
|
1399
|
+
console.log(theme.success(" Done!") + chalk4.dim(" You can now use ") + theme.text("ccclub") + chalk4.dim(" directly."));
|
|
1371
1400
|
} else {
|
|
1372
|
-
console.log(
|
|
1373
|
-
console.log(
|
|
1401
|
+
console.log(chalk4.dim(" Could not auto-install. Run manually:"));
|
|
1402
|
+
console.log(theme.text(" npm install -g ccclub"));
|
|
1374
1403
|
}
|
|
1375
1404
|
}
|
|
1376
1405
|
|
|
@@ -1378,28 +1407,28 @@ async function ensureGlobalInstall() {
|
|
|
1378
1407
|
async function initCommand() {
|
|
1379
1408
|
const existing = await loadConfig();
|
|
1380
1409
|
if (existing) {
|
|
1381
|
-
console.log(
|
|
1410
|
+
console.log(chalk5.yellow("Already initialized!"));
|
|
1382
1411
|
console.log(` User: ${existing.displayName}`);
|
|
1383
1412
|
console.log(` Groups: ${existing.groups.join(", ") || "(none)"}`);
|
|
1384
1413
|
if (!isHookInstalled()) {
|
|
1385
1414
|
const hookOk = await installHook();
|
|
1386
|
-
if (hookOk) console.log(
|
|
1415
|
+
if (hookOk) console.log(chalk5.green(" Auto-sync hook installed!"));
|
|
1387
1416
|
}
|
|
1388
1417
|
if (!isHeartbeatInstalled()) {
|
|
1389
1418
|
const heartbeatOk = await installHeartbeat();
|
|
1390
|
-
if (heartbeatOk) console.log(
|
|
1419
|
+
if (heartbeatOk) console.log(chalk5.green(" Background sync installed!"));
|
|
1391
1420
|
}
|
|
1392
|
-
console.log(
|
|
1421
|
+
console.log(chalk5.dim('\n Run "ccclub" to see the leaderboard'));
|
|
1393
1422
|
return;
|
|
1394
1423
|
}
|
|
1395
1424
|
const rl = createInterface2({ input: stdin, output: stdout });
|
|
1396
1425
|
try {
|
|
1397
1426
|
const defaultName = getDefaultDisplayName();
|
|
1398
|
-
const prompt = defaultName ?
|
|
1427
|
+
const prompt = defaultName ? chalk5.bold(`Your display name (${defaultName}): `) : chalk5.bold("Your display name: ");
|
|
1399
1428
|
const input = await rl.question(prompt);
|
|
1400
1429
|
const displayName = input.trim() || defaultName || "";
|
|
1401
1430
|
if (!displayName) {
|
|
1402
|
-
console.error(
|
|
1431
|
+
console.error(chalk5.red("Name cannot be empty"));
|
|
1403
1432
|
return;
|
|
1404
1433
|
}
|
|
1405
1434
|
const spinner = ora2("Setting up...").start();
|
|
@@ -1436,17 +1465,17 @@ async function initCommand() {
|
|
|
1436
1465
|
]);
|
|
1437
1466
|
spinner.succeed("ccclub initialized!");
|
|
1438
1467
|
if (!hookOk) {
|
|
1439
|
-
console.log(
|
|
1468
|
+
console.log(chalk5.dim(' Tip: run "ccclub hook" to set up auto-sync'));
|
|
1440
1469
|
}
|
|
1441
1470
|
if (!heartbeatOk) {
|
|
1442
|
-
console.log(
|
|
1471
|
+
console.log(chalk5.dim(' Tip: run "ccclub sync" manually to refresh non-Claude agent usage'));
|
|
1443
1472
|
}
|
|
1444
1473
|
console.log("");
|
|
1445
|
-
console.log(
|
|
1474
|
+
console.log(chalk5.bold(" Invite friends to compete:"));
|
|
1446
1475
|
console.log("");
|
|
1447
|
-
console.log(` ${
|
|
1476
|
+
console.log(` ${theme.link(`${apiUrl}/invite/${data.groupCode}`)}`);
|
|
1448
1477
|
console.log("");
|
|
1449
|
-
console.log(
|
|
1478
|
+
console.log(chalk5.dim(` or: npx ccclub join ${data.groupCode}`));
|
|
1450
1479
|
console.log("");
|
|
1451
1480
|
await doSync(true);
|
|
1452
1481
|
await ensureGlobalInstall();
|
|
@@ -1457,14 +1486,14 @@ async function initCommand() {
|
|
|
1457
1486
|
}
|
|
1458
1487
|
function printQuickStart() {
|
|
1459
1488
|
console.log("");
|
|
1460
|
-
console.log(
|
|
1489
|
+
console.log(chalk5.dim(" Run ") + theme.text("ccclub") + chalk5.dim(" to see the leaderboard. ") + theme.text("ccclub -h") + chalk5.dim(" for all commands."));
|
|
1461
1490
|
console.log("");
|
|
1462
1491
|
}
|
|
1463
1492
|
|
|
1464
1493
|
// src/commands/join.ts
|
|
1465
1494
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
1466
1495
|
import { stdin as stdin2, stdout as stdout2 } from "process";
|
|
1467
|
-
import
|
|
1496
|
+
import chalk6 from "chalk";
|
|
1468
1497
|
import ora3 from "ora";
|
|
1469
1498
|
async function joinCommand(inviteCode) {
|
|
1470
1499
|
let config = await loadConfig();
|
|
@@ -1478,11 +1507,11 @@ async function joinCommand(inviteCode) {
|
|
|
1478
1507
|
const rl = createInterface3({ input: stdin2, output: stdout2 });
|
|
1479
1508
|
try {
|
|
1480
1509
|
const defaultName = getDefaultDisplayName();
|
|
1481
|
-
const prompt = defaultName ?
|
|
1510
|
+
const prompt = defaultName ? chalk6.bold(`Your display name (${defaultName}): `) : chalk6.bold("Your display name: ");
|
|
1482
1511
|
const input = await rl.question(prompt);
|
|
1483
1512
|
displayName = input.trim() || defaultName || "";
|
|
1484
1513
|
if (!displayName) {
|
|
1485
|
-
console.error(
|
|
1514
|
+
console.error(chalk6.red("Name cannot be empty"));
|
|
1486
1515
|
return;
|
|
1487
1516
|
}
|
|
1488
1517
|
} finally {
|
|
@@ -1531,12 +1560,11 @@ async function joinCommand(inviteCode) {
|
|
|
1531
1560
|
await ensureGlobalInstall();
|
|
1532
1561
|
}
|
|
1533
1562
|
console.log("");
|
|
1534
|
-
console.log(
|
|
1563
|
+
console.log(chalk6.dim(" Run ") + chalk6.white("ccclub") + chalk6.dim(" to see the leaderboard. ") + chalk6.white("ccclub -h") + chalk6.dim(" for all commands."));
|
|
1535
1564
|
console.log("");
|
|
1536
1565
|
}
|
|
1537
1566
|
|
|
1538
1567
|
// src/commands/rank.ts
|
|
1539
|
-
import chalk6 from "chalk";
|
|
1540
1568
|
import Table from "cli-table3";
|
|
1541
1569
|
import ora4 from "ora";
|
|
1542
1570
|
|
|
@@ -1595,11 +1623,11 @@ async function rankCommand(options) {
|
|
|
1595
1623
|
Usage: ccclub -d <period>
|
|
1596
1624
|
|
|
1597
1625
|
Options:
|
|
1598
|
-
${
|
|
1599
|
-
${
|
|
1600
|
-
${
|
|
1601
|
-
${
|
|
1602
|
-
${
|
|
1626
|
+
${theme.text("ccclub -d 1")} Yesterday
|
|
1627
|
+
${theme.text("ccclub -d 7")} Last 7 days
|
|
1628
|
+
${theme.text("ccclub -d 30")} Last 30 days
|
|
1629
|
+
${theme.text("ccclub -d all")} All time
|
|
1630
|
+
${theme.text("ccclub")} Today (default)
|
|
1603
1631
|
`;
|
|
1604
1632
|
if (options.days) {
|
|
1605
1633
|
if (options.days === true) {
|
|
@@ -1609,7 +1637,7 @@ async function rankCommand(options) {
|
|
|
1609
1637
|
const DAYS_MAP = { "1": "yesterday", "7": "weekly", "30": "monthly", "all": "all-time" };
|
|
1610
1638
|
const mapped = DAYS_MAP[options.days];
|
|
1611
1639
|
if (!mapped) {
|
|
1612
|
-
console.log(
|
|
1640
|
+
console.log(theme.danger(`
|
|
1613
1641
|
Unknown value: -d ${options.days}`));
|
|
1614
1642
|
console.log(DAYS_HINT);
|
|
1615
1643
|
return;
|
|
@@ -1633,7 +1661,7 @@ async function rankCommand(options) {
|
|
|
1633
1661
|
codes = config.groups.length > 0 ? config.groups : [];
|
|
1634
1662
|
}
|
|
1635
1663
|
if (codes.length === 0) {
|
|
1636
|
-
console.log(
|
|
1664
|
+
console.log(theme.danger("No group found. Run 'ccclub init' or 'ccclub join <code>' first."));
|
|
1637
1665
|
return;
|
|
1638
1666
|
}
|
|
1639
1667
|
const localUsagePromise = fetchUsageLimits().catch(() => null);
|
|
@@ -1671,7 +1699,7 @@ async function rankCommand(options) {
|
|
|
1671
1699
|
for (let i = 0; i < groupResults.length; i++) {
|
|
1672
1700
|
const { code, rankData, activityData, range } = groupResults[i];
|
|
1673
1701
|
if (!rankData) {
|
|
1674
|
-
console.log(
|
|
1702
|
+
console.log(theme.danger(`
|
|
1675
1703
|
Couldn't load leaderboard for ${code}`));
|
|
1676
1704
|
continue;
|
|
1677
1705
|
}
|
|
@@ -1683,10 +1711,10 @@ async function rankCommand(options) {
|
|
|
1683
1711
|
if (activityData) renderActivity(activityData, range);
|
|
1684
1712
|
if (i < groupResults.length - 1) console.log("");
|
|
1685
1713
|
}
|
|
1686
|
-
console.log(
|
|
1714
|
+
console.log(theme.muted("\n Tokens = input + output + reasoning ") + theme.warning("(cache excluded)") + theme.muted(". Use ") + theme.text("--cache") + theme.muted(" to include cache tokens."));
|
|
1687
1715
|
const update = await getUpdateResult();
|
|
1688
1716
|
if (update) {
|
|
1689
|
-
console.log(
|
|
1717
|
+
console.log(theme.warningBold("\n Update available") + theme.muted(`: ${update.current} \u2192 ${update.latest} Run `) + theme.linkText("npm i -g ccclub@latest"));
|
|
1690
1718
|
}
|
|
1691
1719
|
} catch (err) {
|
|
1692
1720
|
spinner.fail(`Error: ${formatFetchError(err)}`);
|
|
@@ -1709,20 +1737,20 @@ function formatTokens(n) {
|
|
|
1709
1737
|
}
|
|
1710
1738
|
function printGroup(data, code, period, config, showCache = false, showAll = false) {
|
|
1711
1739
|
if (data.rankings.length === 0) {
|
|
1712
|
-
console.log(
|
|
1740
|
+
console.log(theme.title(`
|
|
1713
1741
|
${data.group.name}`));
|
|
1714
|
-
console.log(
|
|
1715
|
-
console.log(
|
|
1742
|
+
console.log(theme.warning(" No data for this period yet"));
|
|
1743
|
+
console.log(theme.muted(" Sync your data first: ccclub sync"));
|
|
1716
1744
|
return;
|
|
1717
1745
|
}
|
|
1718
|
-
console.log(
|
|
1746
|
+
console.log(theme.title(`
|
|
1719
1747
|
${data.group.name}`));
|
|
1720
1748
|
const periodLabel = { daily: "TODAY", yesterday: "YESTERDAY", weekly: "7 DAYS", monthly: "30 DAYS", "all-time": "ALL TIME" };
|
|
1721
1749
|
const now = Date.now();
|
|
1722
1750
|
const activeCount = data.rankings.filter((r) => r.lastSync && now - new Date(r.lastSync).getTime() < ACTIVE_THRESHOLD_MS).length;
|
|
1723
|
-
console.log(
|
|
1751
|
+
console.log(theme.muted(` ${periodLabel[period] || period.toUpperCase()} \xB7 ${data.start.slice(0, 10)} \u2192 ${data.end.slice(0, 10)} \xB7 ${data.group.memberCount} members`));
|
|
1724
1752
|
if (activeCount > 0) {
|
|
1725
|
-
console.log(
|
|
1753
|
+
console.log(theme.success(` ${activeCount} active`));
|
|
1726
1754
|
}
|
|
1727
1755
|
console.log("");
|
|
1728
1756
|
const activeRankings = showAll || data.rankings.length <= 15 ? data.rankings : data.rankings.filter((r) => r.costUSD > 0 || r.userId === config.userId);
|
|
@@ -1769,53 +1797,65 @@ function printGroup(data, code, period, config, showCache = false, showAll = fal
|
|
|
1769
1797
|
columnWidth("$/Turn", plainRows.map((r) => r.perTurn), 6, 7)
|
|
1770
1798
|
);
|
|
1771
1799
|
const table = new Table({
|
|
1772
|
-
head: head.map((h) =>
|
|
1773
|
-
style: { head: [], border: [] },
|
|
1800
|
+
head: head.map((h) => theme.linkText(h)),
|
|
1801
|
+
style: { head: [], border: ["gray"] },
|
|
1774
1802
|
colWidths: widths
|
|
1775
1803
|
});
|
|
1776
1804
|
for (const plain of plainRows) {
|
|
1777
1805
|
const { entry } = plain;
|
|
1778
1806
|
const isMe = entry.userId === config.userId;
|
|
1779
|
-
const
|
|
1780
|
-
const
|
|
1781
|
-
const
|
|
1782
|
-
const
|
|
1807
|
+
const rowStyle = isMe ? theme.success : podiumStyle(entry.rank);
|
|
1808
|
+
const nameStyle = isMe ? theme.successBold : podiumNameStyle(entry.rank);
|
|
1809
|
+
const rankStyle = podiumNameStyle(entry.rank);
|
|
1810
|
+
const marker = isMe ? theme.success("\u2192") : " ";
|
|
1783
1811
|
const nameWidth = Math.max(widths[1] - 2, 4);
|
|
1784
|
-
const displayName = plain.isActive ? `${
|
|
1812
|
+
const displayName = plain.isActive ? `${theme.success("\u25CF")} ${nameStyle(truncateDisplay(entry.displayName, Math.max(nameWidth - 2, 1)))}` : nameStyle(truncateDisplay(entry.displayName, nameWidth));
|
|
1785
1813
|
const row = [
|
|
1786
|
-
`${marker}${
|
|
1814
|
+
`${marker}${rankStyle(String(entry.rank))}`,
|
|
1787
1815
|
displayName
|
|
1788
1816
|
];
|
|
1789
1817
|
if (hasAgents) {
|
|
1790
1818
|
const agentWidth = Math.max(widths[2] - 2, 4);
|
|
1791
|
-
row.push(
|
|
1819
|
+
row.push(rowStyle(truncateDisplay(plain.agents, agentWidth)));
|
|
1792
1820
|
}
|
|
1793
|
-
row.push(
|
|
1821
|
+
row.push(rowStyle(plain.cost), rowStyle(plain.tokens));
|
|
1794
1822
|
if (hasPlan) {
|
|
1795
1823
|
row.push(colorRoi(plain.roi, entry));
|
|
1796
1824
|
}
|
|
1797
|
-
row.push(
|
|
1798
|
-
row.push(entry.chatCount > 0 ?
|
|
1825
|
+
row.push(rowStyle(plain.turns));
|
|
1826
|
+
row.push(entry.chatCount > 0 ? rowStyle(plain.perTurn) : theme.faint("\u2014"));
|
|
1799
1827
|
table.push(row);
|
|
1800
1828
|
}
|
|
1801
1829
|
console.log(table.toString());
|
|
1802
1830
|
if (hiddenCount > 0) {
|
|
1803
|
-
console.log(
|
|
1831
|
+
console.log(theme.muted(` ${hiddenCount} inactive member${hiddenCount > 1 ? "s" : ""} hidden \xB7 ccclub --all to show`));
|
|
1804
1832
|
}
|
|
1805
|
-
console.log(
|
|
1833
|
+
console.log(theme.muted(" Dashboard: ") + theme.link(`${config.apiUrl}/g/${code}`));
|
|
1806
1834
|
if (code !== "global") {
|
|
1807
|
-
console.log(
|
|
1835
|
+
console.log(theme.muted(" Invite: ") + theme.link(`${config.apiUrl}/invite/${code}`));
|
|
1808
1836
|
}
|
|
1809
1837
|
if (hasPlan) {
|
|
1810
1838
|
const me = data.rankings.find((r) => r.userId === config.userId);
|
|
1811
1839
|
if (me && !me.plan) {
|
|
1812
|
-
console.log(
|
|
1840
|
+
console.log(theme.muted(" Set your plan: ") + theme.text("ccclub profile --plan pro|max100|max200|api"));
|
|
1813
1841
|
}
|
|
1814
1842
|
}
|
|
1815
1843
|
}
|
|
1816
1844
|
function isEntryActive(entry, now) {
|
|
1817
1845
|
return Boolean(entry.lastSync && now - new Date(entry.lastSync).getTime() < ACTIVE_THRESHOLD_MS);
|
|
1818
1846
|
}
|
|
1847
|
+
function podiumStyle(rank) {
|
|
1848
|
+
if (rank === 1) return theme.gold;
|
|
1849
|
+
if (rank === 2) return theme.silver;
|
|
1850
|
+
if (rank === 3) return theme.bronze;
|
|
1851
|
+
return theme.text;
|
|
1852
|
+
}
|
|
1853
|
+
function podiumNameStyle(rank) {
|
|
1854
|
+
if (rank === 1) return theme.goldBold;
|
|
1855
|
+
if (rank === 2) return theme.silverBold;
|
|
1856
|
+
if (rank === 3) return theme.bronzeBold;
|
|
1857
|
+
return theme.text;
|
|
1858
|
+
}
|
|
1819
1859
|
function formatRoi(entry, hasPlan) {
|
|
1820
1860
|
if (!hasPlan) return "";
|
|
1821
1861
|
if (entry.plan && entry.plan !== "api") {
|
|
@@ -1832,9 +1872,9 @@ function colorRoi(roiStr, entry) {
|
|
|
1832
1872
|
const price = PLAN_PRICES[entry.plan];
|
|
1833
1873
|
const monthly = entry.monthlyCostUSD || 0;
|
|
1834
1874
|
const roi = price > 0 ? Math.round(monthly / price * 100) : 0;
|
|
1835
|
-
return roi >= 100 ?
|
|
1875
|
+
return roi >= 100 ? theme.successBold(roiStr) : roi >= 50 ? theme.warning(roiStr) : theme.faint(roiStr);
|
|
1836
1876
|
}
|
|
1837
|
-
return
|
|
1877
|
+
return theme.faint(roiStr);
|
|
1838
1878
|
}
|
|
1839
1879
|
function formatAgents(entry) {
|
|
1840
1880
|
if (entry.agentBreakdown && entry.agentBreakdown.length > 0) {
|
|
@@ -1908,7 +1948,7 @@ function renderActivity(data, range) {
|
|
|
1908
1948
|
}
|
|
1909
1949
|
}
|
|
1910
1950
|
if (globalMax === 0) globalMax = 1;
|
|
1911
|
-
console.log(
|
|
1951
|
+
console.log(theme.muted(`
|
|
1912
1952
|
Activity (${range})`));
|
|
1913
1953
|
for (let i = 0; i < active.length; i++) {
|
|
1914
1954
|
const user = active[i];
|
|
@@ -1920,22 +1960,10 @@ function renderActivity(data, range) {
|
|
|
1920
1960
|
return SPARK_CHARS[idx];
|
|
1921
1961
|
}).join("");
|
|
1922
1962
|
const total = user.blocks.reduce((s, b) => s + b.cost, 0);
|
|
1923
|
-
const displayWidth = [...user.displayName].reduce((w, ch) => w + (ch.charCodeAt(0) > 127 ? 2 : 1), 0);
|
|
1924
1963
|
const maxWidth = 12;
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
let cut = 0;
|
|
1929
|
-
for (const ch of name) {
|
|
1930
|
-
const cw = ch.charCodeAt(0) > 127 ? 2 : 1;
|
|
1931
|
-
if (w + cw > maxWidth) break;
|
|
1932
|
-
w += cw;
|
|
1933
|
-
cut++;
|
|
1934
|
-
}
|
|
1935
|
-
name = [...name].slice(0, cut).join("");
|
|
1936
|
-
}
|
|
1937
|
-
const pad = " ".repeat(Math.max(0, maxWidth - displayWidth));
|
|
1938
|
-
console.log(` ${chalk6.dim(name + pad)} ${spark} ${chalk6.dim("$" + total.toFixed(2))}`);
|
|
1964
|
+
const name = truncateDisplay(user.displayName, maxWidth);
|
|
1965
|
+
const pad = " ".repeat(Math.max(0, maxWidth - visualWidth(name)));
|
|
1966
|
+
console.log(` ${theme.muted(name + pad)} ${theme.brand(spark)} ${theme.muted("$" + total.toFixed(2))}`);
|
|
1939
1967
|
}
|
|
1940
1968
|
const axisArr = new Array(bucketCount).fill(" ");
|
|
1941
1969
|
if (range === "24h" || range === "yesterday") {
|
|
@@ -1958,7 +1986,7 @@ function renderActivity(data, range) {
|
|
|
1958
1986
|
for (let c = 0; c < label.length && b + c < bucketCount; c++) axisArr[b + c] = label[c];
|
|
1959
1987
|
}
|
|
1960
1988
|
}
|
|
1961
|
-
console.log(
|
|
1989
|
+
console.log(theme.faint(" " + " ".repeat(12) + " " + axisArr.join("")));
|
|
1962
1990
|
}
|
|
1963
1991
|
|
|
1964
1992
|
// src/commands/profile.ts
|
|
@@ -2128,7 +2156,7 @@ async function createGroupCommand() {
|
|
|
2128
2156
|
}
|
|
2129
2157
|
spinner.succeed(`Created "${data.groupName}"`);
|
|
2130
2158
|
console.log("");
|
|
2131
|
-
console.log(` ${
|
|
2159
|
+
console.log(` ${theme.link(`${config.apiUrl}/invite/${data.groupCode}`)}`);
|
|
2132
2160
|
console.log("");
|
|
2133
2161
|
console.log(chalk9.dim(` or: npx ccclub join ${data.groupCode}`));
|
|
2134
2162
|
} finally {
|
|
@@ -2228,7 +2256,7 @@ async function hookCommand() {
|
|
|
2228
2256
|
}
|
|
2229
2257
|
|
|
2230
2258
|
// src/index.ts
|
|
2231
|
-
var VERSION = "0.3.
|
|
2259
|
+
var VERSION = "0.3.9";
|
|
2232
2260
|
startUpdateCheck(VERSION);
|
|
2233
2261
|
var program = new Command();
|
|
2234
2262
|
if (process.argv.slice(2).includes("-v")) {
|