@tokenzero/cli 0.2.0 → 0.2.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/bin/tokenzero.mjs +49 -2
- package/package.json +1 -1
package/bin/tokenzero.mjs
CHANGED
|
@@ -710,7 +710,7 @@ function canonical(obj) {
|
|
|
710
710
|
}
|
|
711
711
|
|
|
712
712
|
// cli/src/main.ts
|
|
713
|
-
var VERSION = "0.2.
|
|
713
|
+
var VERSION = "0.2.1";
|
|
714
714
|
var BAKED_URL = true ? "https://tokenzero.sh" : "__TOKENZERO_DEFAULT_URL__";
|
|
715
715
|
function parseArgs(argv) {
|
|
716
716
|
const a = { _: [], flags: {} };
|
|
@@ -730,7 +730,7 @@ function parseArgs(argv) {
|
|
|
730
730
|
}
|
|
731
731
|
return a;
|
|
732
732
|
}
|
|
733
|
-
var VALUE_FLAGS = /* @__PURE__ */ new Set(["url", "name", "key", "format", "diff", "fail-over", "env-file", "limit"]);
|
|
733
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set(["url", "name", "key", "format", "diff", "fail-over", "env-file", "limit", "window"]);
|
|
734
734
|
var tty = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
735
735
|
var c = (code2) => (s) => tty ? `\x1B[${code2}m${s}\x1B[0m` : s;
|
|
736
736
|
var bold = c("1");
|
|
@@ -1118,6 +1118,50 @@ ${bold(f.title)}
|
|
|
1118
1118
|
process.exitCode = 1;
|
|
1119
1119
|
}
|
|
1120
1120
|
}
|
|
1121
|
+
async function cmdMetrics(a) {
|
|
1122
|
+
const saved = loadCreds();
|
|
1123
|
+
const base = baseUrl(a) || saved?.url || "https://tokenzero.sh";
|
|
1124
|
+
const key = a.flags.key || process.env.TOKENZERO_KEY || saved?.api_key || "";
|
|
1125
|
+
const w = ["24h", "7d", "30d", "all"].includes(String(a.flags.window)) ? String(a.flags.window) : "30d";
|
|
1126
|
+
const demo = !!a.flags.demo || !key;
|
|
1127
|
+
const r = await api(base, `/v1/workspaces/me/metrics?${demo ? "demo=1" : "window=" + w}`, { headers: demo ? {} : { "x-tokenzero-key": key } });
|
|
1128
|
+
if (r.status !== 200) {
|
|
1129
|
+
err(red(`metrics: ${r.status} ${JSON.stringify(r.body).slice(0, 200)}`));
|
|
1130
|
+
process.exitCode = 1;
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
if (a.flags.json) {
|
|
1134
|
+
out(JSON.stringify(r.body, null, 2));
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
const m = r.body, c2 = m.cost_and_roi, e = m.by_engine, sp = m.speed_and_latency, q = m.quality_and_safety, rl = m.reliability_and_privacy;
|
|
1138
|
+
const $ = (n) => n == null ? "\u2014" : "$" + Number(n).toFixed(2);
|
|
1139
|
+
out(`${bold("tokenzero metrics")} \xB7 ${m.demo ? yellow("SAMPLE DATA") : m.workspace_id} \xB7 plan ${m.plan} \xB7 window ${m.window} \xB7 gateway v${m.version}`);
|
|
1140
|
+
if (m.demo) out(dim(" " + m.note));
|
|
1141
|
+
out(`
|
|
1142
|
+
${bold("Cost & ROI")} baseline ${$(c2.baseline_spend_usd)} actual ${$(c2.actual_spend_usd)} saved ${green($(c2.hard_savings_usd))} (${c2.savings_rate_pct}%) fee ${$(c2.estimated_fee_usd)}${c2.fee_waived_by_guarantee ? " (waived: 3x-ROI rule)" : ""} net ${$(c2.net_savings_after_fee_usd)} ROI ${c2.net_roi_multiple == null ? "\u221E (free tier)" : c2.net_roi_multiple + "x"} (floor ${c2.roi_guarantee_floor}x)`);
|
|
1143
|
+
out(`${bold("Engines")}`);
|
|
1144
|
+
out(` 1 prompt cache + CAPC ${num(e.engine1_prompt_cache_and_capc.requests_optimized)} formatted \xB7 ${num(e.engine1_prompt_cache_and_capc.capc_schemas_minified)} schemas minified \xB7 ${num(e.engine1_prompt_cache_and_capc.cached_input_tokens)} cached tokens \xB7 ${e.engine1_prompt_cache_and_capc.prompt_cache_hit_rate_pct}% hit \xB7 ${green($(e.engine1_prompt_cache_and_capc.savings_usd))} (${e.engine1_prompt_cache_and_capc.share_of_total_savings_pct}%)`);
|
|
1145
|
+
out(` 2 edge cache ${num(e.engine2_edge_cache.exact_hits)} exact + ${num(e.engine2_edge_cache.semantic_hits)} semantic hits (${e.engine2_edge_cache.total_hit_rate_pct}%) \xB7 ${num(e.engine2_edge_cache.tokens_avoided)} tokens avoided \xB7 ${green($(e.engine2_edge_cache.savings_usd))} (${e.engine2_edge_cache.share_of_total_savings_pct}%)`);
|
|
1146
|
+
out(` 3 cascade + reasoning mode ${e.engine3_cascade_and_reasoning.mode} \xB7 ${num(e.engine3_cascade_and_reasoning.auto_routed_count)} routed \xB7 ${num(e.engine3_cascade_and_reasoning.advised_count)} advised${e.engine3_cascade_and_reasoning.would_have_saved_usd ? " (would have saved " + $(e.engine3_cascade_and_reasoning.would_have_saved_usd) + ")" : ""} \xB7 ${num(e.engine3_cascade_and_reasoning.reasoning_capped_count)} reasoning caps \xB7 ${green($(e.engine3_cascade_and_reasoning.savings_usd))} (${e.engine3_cascade_and_reasoning.share_of_total_savings_pct}%)`);
|
|
1147
|
+
out(` 4 signed ledger ${num(e.engine4_cryptographic_ledger.receipts_signed)} receipts \xB7 chain head #${e.engine4_cryptographic_ledger.chain_head_seq} ${e.engine4_cryptographic_ledger.chain_head_hash ?? ""} \xB7 key ${e.engine4_cryptographic_ledger.signer_key_id}`);
|
|
1148
|
+
out(`${bold("Speed")} gateway overhead p50 +${sp.gateway_overhead_p50_ms ?? "\u2014"} ms \xB7 cache hit p50 ${sp.cache_hit_p50_ms ?? "\u2014"} ms \xB7 upstream p50 ${sp.upstream_p50_ms ?? "\u2014"} ms \xB7 effective p50 ${sp.effective_p50_ms ?? "\u2014"} ms \xB7 ${num(sp.total_wall_clock_ms_saved)} ms saved (${sp.avg_speedup_pct}% faster)`);
|
|
1149
|
+
out(`${bold("Quality")} shadow eval ${q.shadow_eval_enabled ? "on" : "off"} \xB7 ${num(q.samples_evaluated)} samples \xB7 agreement ${q.agreement_rate_pct ?? "\u2014"}% (floor ${q.sla_floor_pct}%) \xB7 UCB disagreement ${q.conformal_ucb_disagreement_pct ?? "\u2014"}% \xB7 breaker ${q.circuit_breaker_status}`);
|
|
1150
|
+
out(`${bold("Reliability")} ${num(rl.total_requests)} requests \xB7 ${rl.effective_availability_pct}% ok \xB7 ${num(rl.upstream_429_rescued)} 429 + ${num(rl.upstream_5xx_rescued)} 5xx rescued \xB7 ZDR ${rl.zdr_enabled ? "on" : "off"} (${num(rl.zdr_requests_count)} requests, ${rl.zdr_share_pct}%)`);
|
|
1151
|
+
if (m.by_model.length) {
|
|
1152
|
+
out(bold("By model"));
|
|
1153
|
+
for (const r2 of m.by_model.slice(0, 12)) out(` ${r2.model.padEnd(28)} ${String(r2.requests).padStart(7)} req baseline ${$(r2.baseline_usd).padStart(10)} actual ${$(r2.actual_usd).padStart(10)} saved ${green($(r2.saved_usd).padStart(9))} ${String(r2.savings_pct).padStart(5)}%`);
|
|
1154
|
+
}
|
|
1155
|
+
if (m.actionable_recommendations.length) {
|
|
1156
|
+
out(bold("Recommendations"));
|
|
1157
|
+
for (const rec of m.actionable_recommendations) out(` ${yellow("\u2192")} ${rec.title}${rec.estimated_extra_savings_usd ? " (~" + $(rec.estimated_extra_savings_usd) + " more)" : rec.estimated_extra_savings_range_pct ? " (+" + rec.estimated_extra_savings_range_pct + "%)" : ""}
|
|
1158
|
+
apply: curl -X POST ${base}/v1/workspaces/settings -H "X-TokenZero-Key: $TOKENZERO_KEY" -H "content-type: application/json" -d '${JSON.stringify(rec.setting_patch)}'`);
|
|
1159
|
+
}
|
|
1160
|
+
out(dim(` dashboard scorecard: ${m.links.dashboard}`));
|
|
1161
|
+
}
|
|
1162
|
+
function num(n) {
|
|
1163
|
+
return n == null ? "\u2014" : Number(n).toLocaleString("en-US");
|
|
1164
|
+
}
|
|
1121
1165
|
async function cmdDoctor(a) {
|
|
1122
1166
|
const saved = loadCreds();
|
|
1123
1167
|
const base = baseUrl(a) || saved?.url || "https://tokenzero.sh";
|
|
@@ -1298,6 +1342,7 @@ function help() {
|
|
|
1298
1342
|
Static token-waste audit. Runs locally; nothing is uploaded. --fail-over makes it a CI gate.
|
|
1299
1343
|
${bold("tokenzero usage")} [--json] Routed spend vs the free tier, savings, fee preview.
|
|
1300
1344
|
${bold("tokenzero doctor")} [--key K] [--json] Six-check connection and receipt doctor: gateway, signer, pricing, key, quota, settings.
|
|
1345
|
+
${bold("tokenzero metrics")} [--window 24h|7d|30d|all] [--key K] [--json] [--demo] Value scorecard: savings, ROI, engines, speed, parity, reliability, per-model, recommendations.
|
|
1301
1346
|
${bold("tokenzero verify")} <request_id> Verify a savings receipt's signature offline.
|
|
1302
1347
|
${bold("tokenzero verify --chain")} [--limit N] Verify the workspace's append-only receipt chain (signatures, seq, prev hashes).
|
|
1303
1348
|
${bold("tokenzero rotate-key")} [--yes] Issue a new workspace key; rewrites it in .env. Old key dies immediately.
|
|
@@ -1325,6 +1370,8 @@ async function main() {
|
|
|
1325
1370
|
return cmdUsage(a);
|
|
1326
1371
|
case "doctor":
|
|
1327
1372
|
return cmdDoctor(a);
|
|
1373
|
+
case "metrics":
|
|
1374
|
+
return cmdMetrics(a);
|
|
1328
1375
|
case "verify":
|
|
1329
1376
|
return cmdVerify(a);
|
|
1330
1377
|
case "rotate-key":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenzero/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "TokenZero CLI: connect a project to the TokenZero BYOK gateway, audit LLM token waste locally, check usage and verify signed savings receipts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|