@tokenzero/cli 0.1.4 → 0.1.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/bin/tokenzero.mjs +77 -25
- package/package.json +1 -1
package/bin/tokenzero.mjs
CHANGED
|
@@ -69,7 +69,18 @@ var PRICES = {
|
|
|
69
69
|
"gemini-3-flash": P("gemini", "fast", 0.5, 3, 0.05),
|
|
70
70
|
"gemini-2.5-pro": P("gemini", "frontier", 1.25, 10, 0.125, void 0, { longCtxAt: 2e5, longCtx: { input: 2.5, output: 15, cachedInput: 0.25 } }),
|
|
71
71
|
"gemini-2.5-flash": P("gemini", "fast", 0.3, 2.5, 0.03),
|
|
72
|
-
"gemini-2.5-flash-lite": P("gemini", "fast", 0.1, 0.4, 0.01)
|
|
72
|
+
"gemini-2.5-flash-lite": P("gemini", "fast", 0.1, 0.4, 0.01),
|
|
73
|
+
// ---- xAI Grok ----
|
|
74
|
+
"grok-4": P("xai", "frontier", 3, 15, 0.75),
|
|
75
|
+
"grok-4-fast": P("xai", "fast", 0.2, 0.8, 0.05),
|
|
76
|
+
"grok-4-mini": P("xai", "fast", 0.2, 0.8, 0.05),
|
|
77
|
+
"grok-3": P("xai", "mid", 3, 15, 0.75),
|
|
78
|
+
"grok-3-mini": P("xai", "fast", 0.3, 0.5, 0.075),
|
|
79
|
+
// ---- DeepSeek ----
|
|
80
|
+
"deepseek-v3": P("deepseek", "fast", 0.27, 1.1, 0.07),
|
|
81
|
+
"deepseek-chat": P("deepseek", "fast", 0.27, 1.1, 0.07),
|
|
82
|
+
"deepseek-r1": P("deepseek", "mid", 0.55, 2.19, 0.14),
|
|
83
|
+
"deepseek-reasoner": P("deepseek", "mid", 0.55, 2.19, 0.14)
|
|
73
84
|
};
|
|
74
85
|
var CASCADE_TARGET = {
|
|
75
86
|
"gpt-6-astra": "gpt-6.1-sol",
|
|
@@ -100,13 +111,19 @@ var CASCADE_TARGET = {
|
|
|
100
111
|
"gemini-3.1-pro": "gemini-3.8-flash",
|
|
101
112
|
"gemini-3.8-flash": "gemini-3.5-flash-lite",
|
|
102
113
|
"gemini-2.5-pro": "gemini-2.5-flash",
|
|
103
|
-
"gemini-2.5-flash": "gemini-2.5-flash-lite"
|
|
114
|
+
"gemini-2.5-flash": "gemini-2.5-flash-lite",
|
|
115
|
+
"grok-4": "grok-4-fast",
|
|
116
|
+
"grok-3": "grok-3-mini",
|
|
117
|
+
"deepseek-r1": "deepseek-v3",
|
|
118
|
+
"deepseek-reasoner": "deepseek-chat"
|
|
104
119
|
};
|
|
105
120
|
var KEYS_BY_LENGTH = Object.keys(PRICES).sort((a, b) => b.length - a.length);
|
|
106
121
|
function normalizeModel(model) {
|
|
107
122
|
if (typeof model !== "string" || !model) return null;
|
|
108
123
|
let m = model.toLowerCase().trim();
|
|
109
|
-
m = m.replace(/^(openai|anthropic|google|models|vertex_ai)\//, "");
|
|
124
|
+
m = m.replace(/^(openai|anthropic|google|gemini|x-ai|xai|deepseek|bedrock|models|vertex_ai)\//, "");
|
|
125
|
+
m = m.replace(/^(?:us\.|eu\.|apac\.)?anthropic\./, "");
|
|
126
|
+
m = m.replace(/-v\d+:\d+$/, "");
|
|
110
127
|
m = m.replace(/@\d{8}$/, "");
|
|
111
128
|
m = m.replace(/-(\d{8}|\d{4}-\d{2}-\d{2})$/, "");
|
|
112
129
|
m = m.replace(/-(latest|preview|customtools|thinking)$/, "");
|
|
@@ -649,7 +666,7 @@ function canonical(obj) {
|
|
|
649
666
|
}
|
|
650
667
|
|
|
651
668
|
// cli/src/main.ts
|
|
652
|
-
var VERSION = "0.1.
|
|
669
|
+
var VERSION = "0.1.5";
|
|
653
670
|
var BAKED_URL = true ? "https://tokenzero.sh" : "__TOKENZERO_DEFAULT_URL__";
|
|
654
671
|
function parseArgs(argv) {
|
|
655
672
|
const a = { _: [], flags: {} };
|
|
@@ -856,42 +873,77 @@ ${bold("Your code")}`);
|
|
|
856
873
|
if (sn) out(` ${s.padEnd(10)} ${sn}`);
|
|
857
874
|
}
|
|
858
875
|
}
|
|
876
|
+
if (a.flags["github-action"]) await setupGithubAction(root, a);
|
|
859
877
|
if (a.flags.mcp) await setupMcp(root, base, a);
|
|
860
878
|
out(`
|
|
861
879
|
${bold("Next")}`);
|
|
862
880
|
if (wsId) out(` dashboard ${base}/dashboard?workspace=${wsId}`);
|
|
863
881
|
out(` usage ${selfCmd(base)} usage`);
|
|
864
882
|
if (wsId) out(` badge turn on public stats in the dashboard, then: [](${base}/dashboard?workspace=${wsId})`);
|
|
883
|
+
if (!a.flags["github-action"]) out(` PR checks ${selfCmd(base)} init --github-action`);
|
|
865
884
|
if (!a.flags.mcp) out(` coding agents: ${selfCmd(base)} init --mcp`);
|
|
866
885
|
}
|
|
867
|
-
var selfCmd = (
|
|
886
|
+
var selfCmd = (_base) => "npx -y @tokenzero/cli";
|
|
868
887
|
var redactKey = (s, key) => key ? s.replace(key, key.slice(0, 12) + "\u2026" + key.slice(-4)) : s;
|
|
869
|
-
|
|
888
|
+
var GH_ACTION_YAML = `name: TokenZero LLM Cost Check
|
|
889
|
+
on: [pull_request]
|
|
890
|
+
permissions:
|
|
891
|
+
contents: read
|
|
892
|
+
pull-requests: write
|
|
893
|
+
jobs:
|
|
894
|
+
cost-audit:
|
|
895
|
+
runs-on: ubuntu-latest
|
|
896
|
+
steps:
|
|
897
|
+
- uses: actions/checkout@v4
|
|
898
|
+
with:
|
|
899
|
+
fetch-depth: 0
|
|
900
|
+
- uses: tokenzero-ai/tokenzero/action@v0
|
|
901
|
+
with:
|
|
902
|
+
github-token: \${{ secrets.GITHUB_TOKEN }}
|
|
903
|
+
`;
|
|
904
|
+
async function setupGithubAction(root, a) {
|
|
870
905
|
out(`
|
|
871
|
-
${bold("
|
|
872
|
-
|
|
873
|
-
const
|
|
874
|
-
const file = path2.join(cursorDir, "mcp.json");
|
|
875
|
-
let cfg = {};
|
|
906
|
+
${bold("GitHub Action")} ${dim("(PR token-waste & model-arbitrage check)")}`);
|
|
907
|
+
const wfDir = path2.join(root, ".github", "workflows");
|
|
908
|
+
const file = path2.join(wfDir, "tokenzero.yml");
|
|
876
909
|
if (fs2.existsSync(file)) {
|
|
877
|
-
|
|
878
|
-
cfg = JSON.parse(fs2.readFileSync(file, "utf8"));
|
|
879
|
-
} catch {
|
|
880
|
-
out(yellow(` ! ${file} is not valid JSON; not touching it`));
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
if (cfg?.mcpServers?.tokenzero?.url === `${base}/mcp`) {
|
|
885
|
-
out(dim(" Cursor: already configured"));
|
|
910
|
+
out(dim(` ${path2.relative(root, file)} already exists`));
|
|
886
911
|
return;
|
|
887
912
|
}
|
|
888
|
-
if (await confirm(` Add
|
|
889
|
-
|
|
890
|
-
fs2.
|
|
891
|
-
fs2.writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n");
|
|
913
|
+
if (await confirm(` Add ${path2.relative(root, file)} to audit every PR?`, a)) {
|
|
914
|
+
fs2.mkdirSync(wfDir, { recursive: true });
|
|
915
|
+
fs2.writeFileSync(file, GH_ACTION_YAML);
|
|
892
916
|
out(green(` \u2713 wrote ${path2.relative(root, file)}`));
|
|
893
917
|
}
|
|
894
918
|
}
|
|
919
|
+
async function setupMcp(root, base, a) {
|
|
920
|
+
out(`
|
|
921
|
+
${bold("MCP")} ${dim("(audit_repo_token_waste, optimize_prompt_payload, calculate_model_arbitrage)")}`);
|
|
922
|
+
out(` Claude Code: claude mcp add --transport http tokenzero ${base}/mcp`);
|
|
923
|
+
out(` Local stdio: npx -y @tokenzero/mcp`);
|
|
924
|
+
for (const rel of [path2.join(".cursor", "mcp.json"), ".mcp.json"]) {
|
|
925
|
+
const file = path2.join(root, rel);
|
|
926
|
+
let cfg = {};
|
|
927
|
+
if (fs2.existsSync(file)) {
|
|
928
|
+
try {
|
|
929
|
+
cfg = JSON.parse(fs2.readFileSync(file, "utf8"));
|
|
930
|
+
} catch {
|
|
931
|
+
out(yellow(` ! ${file} is not valid JSON; not touching it`));
|
|
932
|
+
continue;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
if (cfg?.mcpServers?.tokenzero?.url === `${base}/mcp`) {
|
|
936
|
+
out(dim(` ${rel}: already configured`));
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
if (await confirm(` Add TokenZero to ${rel}?`, a)) {
|
|
940
|
+
cfg.mcpServers = { ...cfg.mcpServers ?? {}, tokenzero: { url: `${base}/mcp` } };
|
|
941
|
+
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
942
|
+
fs2.writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n");
|
|
943
|
+
out(green(` \u2713 wrote ${rel}`));
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
895
947
|
async function cmdAudit(a) {
|
|
896
948
|
const root = path2.resolve(a._[1] ?? ".");
|
|
897
949
|
let report;
|
|
@@ -1007,7 +1059,7 @@ async function cmdVerify(a) {
|
|
|
1007
1059
|
function help() {
|
|
1008
1060
|
out(`${bold("tokenzero")} v${VERSION} \u2014 cut your LLM bill with a BYOK gateway
|
|
1009
1061
|
|
|
1010
|
-
${bold("tokenzero init")} [dir] [--url URL] [--name NAME] [--yes] [--no-env] [--mcp]
|
|
1062
|
+
${bold("tokenzero init")} [dir] [--url URL] [--name NAME] [--yes] [--no-env] [--mcp] [--github-action]
|
|
1011
1063
|
Audit locally, create a workspace, point OPENAI_BASE_URL / ANTHROPIC_BASE_URL at the gateway.
|
|
1012
1064
|
${bold("tokenzero audit")} [dir] [--json | --format markdown] [--diff file|-] [--fail-over PCT]
|
|
1013
1065
|
Static token-waste audit. Runs locally; nothing is uploaded. --fail-over makes it a CI gate.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenzero/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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",
|