sigrank 0.18.3 → 0.18.5
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/package.json +3 -2
- package/tools.mjs +161 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigrank",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5",
|
|
4
4
|
"author": "SunrisesIllNeverSee (https://github.com/SunrisesIllNeverSee)",
|
|
5
5
|
"description": "SigRank MCP server — the yield cascade + live leaderboard as MCP tools any agent can call",
|
|
6
6
|
"mcpName": "io.github.SunrisesIllNeverSee/sigrank-mcp",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"start": "node index.mjs",
|
|
27
|
-
"test": "node test.mjs && node sign.test.mjs && node --test __tests__/cascade.test.mjs __tests__/badges.test.mjs"
|
|
27
|
+
"test": "node test.mjs && node sign.test.mjs && node --test __tests__/cascade.test.mjs __tests__/badges.test.mjs",
|
|
28
|
+
"sync:platforms": "node scripts/sync-platforms.mjs"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
30
31
|
"index.mjs",
|
package/tools.mjs
CHANGED
|
@@ -1362,6 +1362,36 @@ export const TOOLS = [
|
|
|
1362
1362
|
},
|
|
1363
1363
|
},
|
|
1364
1364
|
},
|
|
1365
|
+
{
|
|
1366
|
+
name: "tokscale_breakdown",
|
|
1367
|
+
description:
|
|
1368
|
+
"Show a per-model breakdown of your token usage across all platforms detected by tokscale. Models under the threshold (default 1%) are lumped into 'other' to keep the display clean. Useful for seeing which models you actually use per platform (e.g. claude-opus-4-8 76%, claude-sonnet-4-6 11%, other 0.3%). Returns { platform: [{ model, input, output, cacheRead, cacheCreate, pct }] }.",
|
|
1369
|
+
annotations: {
|
|
1370
|
+
title: "Model breakdown",
|
|
1371
|
+
...ANNOTATIONS.readOnlyHint,
|
|
1372
|
+
...ANNOTATIONS.openWorldHint,
|
|
1373
|
+
},
|
|
1374
|
+
inputSchema: {
|
|
1375
|
+
type: "object",
|
|
1376
|
+
properties: {
|
|
1377
|
+
threshold: {
|
|
1378
|
+
type: "number",
|
|
1379
|
+
description:
|
|
1380
|
+
"Models below this fraction of their platform's total tokens are lumped into 'other'. Default 0.01 (1%). Set 0 to see every model.",
|
|
1381
|
+
default: 0.01,
|
|
1382
|
+
},
|
|
1383
|
+
},
|
|
1384
|
+
},
|
|
1385
|
+
outputSchema: {
|
|
1386
|
+
type: "object",
|
|
1387
|
+
properties: {
|
|
1388
|
+
platforms: {
|
|
1389
|
+
type: "object",
|
|
1390
|
+
description: "Map of platform name → array of { model, input, output, cacheRead, cacheCreate, pct }",
|
|
1391
|
+
},
|
|
1392
|
+
},
|
|
1393
|
+
},
|
|
1394
|
+
},
|
|
1365
1395
|
];
|
|
1366
1396
|
|
|
1367
1397
|
// tokenpull window key → the board's window_type enum.
|
|
@@ -1412,26 +1442,54 @@ async function _tokscaleDetectClients() {
|
|
|
1412
1442
|
? data
|
|
1413
1443
|
: [];
|
|
1414
1444
|
if (!entries.length) return [];
|
|
1415
|
-
//
|
|
1445
|
+
// Complete tokscale client → our platform name mapping.
|
|
1446
|
+
// Tokscale supports 40 clients (as of v3.1.0). We have native adapters for 16;
|
|
1447
|
+
// the rest map to "other" (user-supplied JSON via SIGRANK_OTHER_PATH).
|
|
1448
|
+
// Source: https://github.com/junhoyeo/tokscale
|
|
1416
1449
|
const TOKSCALE_CLIENT_MAP = {
|
|
1450
|
+
// Native adapters
|
|
1417
1451
|
claude: "claude",
|
|
1418
|
-
"devin-cli": "devin",
|
|
1419
1452
|
codex: "codex",
|
|
1420
|
-
|
|
1453
|
+
"devin-cli": "devin",
|
|
1454
|
+
"devin-desktop": "devin",
|
|
1421
1455
|
gemini: "gemini",
|
|
1422
1456
|
amp: "amp",
|
|
1423
1457
|
kimi: "kimi",
|
|
1424
1458
|
qwen: "qwen",
|
|
1425
1459
|
goose: "goose",
|
|
1426
1460
|
kilo: "kilo",
|
|
1461
|
+
kilocode: "kilo",
|
|
1427
1462
|
hermes: "hermes",
|
|
1428
1463
|
droid: "droid",
|
|
1429
1464
|
codebuff: "codebuff",
|
|
1465
|
+
copilot: "copilot",
|
|
1430
1466
|
opencode: "opencode",
|
|
1431
1467
|
openclaw: "openclaw",
|
|
1432
1468
|
pi: "pi",
|
|
1433
|
-
|
|
1434
|
-
|
|
1469
|
+
// No native adapter yet → "other"
|
|
1470
|
+
cursor: "other",
|
|
1471
|
+
roocode: "other",
|
|
1472
|
+
mux: "other",
|
|
1473
|
+
crush: "other",
|
|
1474
|
+
antigravity: "other",
|
|
1475
|
+
"antigravity-cli": "other",
|
|
1476
|
+
zed: "other",
|
|
1477
|
+
kiro: "other",
|
|
1478
|
+
trae: "other",
|
|
1479
|
+
warp: "other",
|
|
1480
|
+
cline: "other",
|
|
1481
|
+
gjc: "other",
|
|
1482
|
+
grok: "other",
|
|
1483
|
+
jcode: "other",
|
|
1484
|
+
commandcode: "other",
|
|
1485
|
+
micode: "other",
|
|
1486
|
+
junie: "other",
|
|
1487
|
+
zcode: "other",
|
|
1488
|
+
opencodereview: "other",
|
|
1489
|
+
codebuddy: "other",
|
|
1490
|
+
workbuddy: "other",
|
|
1491
|
+
// synthetic = re-attributed from other sources, skip
|
|
1492
|
+
synthetic: null,
|
|
1435
1493
|
};
|
|
1436
1494
|
const clients = new Set();
|
|
1437
1495
|
for (const e of entries) {
|
|
@@ -1440,12 +1498,102 @@ async function _tokscaleDetectClients() {
|
|
|
1440
1498
|
const input = Number(e.input) || 0;
|
|
1441
1499
|
const output = Number(e.output) || 0;
|
|
1442
1500
|
if (input + output === 0) continue;
|
|
1443
|
-
const platform = TOKSCALE_CLIENT_MAP[e.client]
|
|
1444
|
-
|
|
1501
|
+
const platform = TOKSCALE_CLIENT_MAP[e.client];
|
|
1502
|
+
if (platform === null) continue; // synthetic → skip
|
|
1503
|
+
clients.add(platform || "other");
|
|
1445
1504
|
}
|
|
1446
1505
|
return [...clients];
|
|
1447
1506
|
}
|
|
1448
1507
|
|
|
1508
|
+
/**
|
|
1509
|
+
* Run `tokscale models --json` and return a model-level breakdown per platform.
|
|
1510
|
+
* Models under `threshold` (default 1%) of their platform's total are lumped
|
|
1511
|
+
* into "other" to keep the display clean.
|
|
1512
|
+
*
|
|
1513
|
+
* Returns: { platform: [{ model, input, output, cacheRead, cacheCreate, pct }] }
|
|
1514
|
+
*/
|
|
1515
|
+
export async function tokscaleModelBreakdown(threshold = 0.01) {
|
|
1516
|
+
const raw = await execFileAsync("tokscale", ["models", "--json"], 60000);
|
|
1517
|
+
const data = JSON.parse(raw);
|
|
1518
|
+
const entries = Array.isArray(data?.entries)
|
|
1519
|
+
? data.entries
|
|
1520
|
+
: Array.isArray(data)
|
|
1521
|
+
? data
|
|
1522
|
+
: [];
|
|
1523
|
+
if (!entries.length) return {};
|
|
1524
|
+
|
|
1525
|
+
const TOKSCALE_CLIENT_MAP = {
|
|
1526
|
+
claude: "claude", codex: "codex", "devin-cli": "devin",
|
|
1527
|
+
"devin-desktop": "devin", gemini: "gemini", amp: "amp",
|
|
1528
|
+
kimi: "kimi", qwen: "qwen", goose: "goose", kilo: "kilo",
|
|
1529
|
+
kilocode: "kilo", hermes: "hermes", droid: "droid",
|
|
1530
|
+
codebuff: "codebuff", copilot: "copilot", opencode: "opencode",
|
|
1531
|
+
openclaw: "openclaw", pi: "pi",
|
|
1532
|
+
cursor: "other", roocode: "other", mux: "other", crush: "other",
|
|
1533
|
+
antigravity: "other", "antigravity-cli": "other", zed: "other",
|
|
1534
|
+
kiro: "other", trae: "other", warp: "other", cline: "other",
|
|
1535
|
+
gjc: "other", grok: "other", jcode: "other", commandcode: "other",
|
|
1536
|
+
micode: "other", junie: "other", zcode: "other",
|
|
1537
|
+
opencodereview: "other", codebuddy: "other", workbuddy: "other",
|
|
1538
|
+
synthetic: null,
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
// Group entries by our platform name
|
|
1542
|
+
const byPlatform = {};
|
|
1543
|
+
for (const e of entries) {
|
|
1544
|
+
if (!e || !e.client) continue;
|
|
1545
|
+
if (e.model === "<synthetic>" || e.model === "unknown") continue;
|
|
1546
|
+
const input = Number(e.input) || 0;
|
|
1547
|
+
const output = Number(e.output) || 0;
|
|
1548
|
+
if (input + output === 0) continue;
|
|
1549
|
+
const platform = TOKSCALE_CLIENT_MAP[e.client];
|
|
1550
|
+
if (platform === null) continue;
|
|
1551
|
+
const p = platform || "other";
|
|
1552
|
+
if (!byPlatform[p]) byPlatform[p] = [];
|
|
1553
|
+
byPlatform[p].push({
|
|
1554
|
+
model: e.model,
|
|
1555
|
+
input,
|
|
1556
|
+
output,
|
|
1557
|
+
cacheRead: Number(e.cacheRead) || 0,
|
|
1558
|
+
cacheCreate: Number(e.cacheWrite) || 0,
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// For each platform: sort by total tokens desc, lump small models into "other"
|
|
1563
|
+
const result = {};
|
|
1564
|
+
for (const [platform, models] of Object.entries(byPlatform)) {
|
|
1565
|
+
const total = models.reduce(
|
|
1566
|
+
(s, m) => s + m.input + m.output + m.cacheRead + m.cacheCreate,
|
|
1567
|
+
0,
|
|
1568
|
+
);
|
|
1569
|
+
if (total === 0) continue;
|
|
1570
|
+
const sorted = models.sort(
|
|
1571
|
+
(a, b) =>
|
|
1572
|
+
b.input + b.output + b.cacheRead + b.cacheCreate -
|
|
1573
|
+
(a.input + a.output + a.cacheRead + a.cacheCreate),
|
|
1574
|
+
);
|
|
1575
|
+
const big = [];
|
|
1576
|
+
const small = { model: "other", input: 0, output: 0, cacheRead: 0, cacheCreate: 0 };
|
|
1577
|
+
for (const m of sorted) {
|
|
1578
|
+
const t = m.input + m.output + m.cacheRead + m.cacheCreate;
|
|
1579
|
+
if (t / total < threshold) {
|
|
1580
|
+
small.input += m.input;
|
|
1581
|
+
small.output += m.output;
|
|
1582
|
+
small.cacheRead += m.cacheRead;
|
|
1583
|
+
small.cacheCreate += m.cacheCreate;
|
|
1584
|
+
} else {
|
|
1585
|
+
big.push({ ...m, pct: t / total });
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (small.input + small.output + small.cacheRead + small.cacheCreate > 0) {
|
|
1589
|
+
const t = small.input + small.output + small.cacheRead + small.cacheCreate;
|
|
1590
|
+
big.push({ ...small, pct: t / total });
|
|
1591
|
+
}
|
|
1592
|
+
result[platform] = big;
|
|
1593
|
+
}
|
|
1594
|
+
return result;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1449
1597
|
/** Pull a specific set of platforms in parallel, filter to active ones. */
|
|
1450
1598
|
async function _pullExplicit(platforms, opts = {}) {
|
|
1451
1599
|
const settled = await Promise.allSettled(
|
|
@@ -3354,6 +3502,12 @@ export async function callTool(name, args, opts = {}) {
|
|
|
3354
3502
|
};
|
|
3355
3503
|
}
|
|
3356
3504
|
|
|
3505
|
+
if (name === "tokscale_breakdown") {
|
|
3506
|
+
const threshold = Number(args?.threshold ?? 0.01);
|
|
3507
|
+
const platforms = await tokscaleModelBreakdown(threshold);
|
|
3508
|
+
return { platforms };
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3357
3511
|
throw new Error(`Unknown tool: ${name}`);
|
|
3358
3512
|
}
|
|
3359
3513
|
|