@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.
Files changed (2) hide show
  1. package/bin/tokenzero.mjs +77 -25
  2. 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.4";
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: [![LLM spend verified by TokenZero](${base}/v1/badge/${wsId}.svg)](${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 = (base) => `npx -y ${base}/cli/tokenzero.tgz`;
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
- async function setupMcp(root, base, a) {
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("MCP")} ${dim("(audit_repo_token_waste, optimize_prompt_payload, calculate_model_arbitrage)")}`);
872
- out(` Claude Code: claude mcp add --transport http tokenzero ${base}/mcp`);
873
- const cursorDir = path2.join(root, ".cursor");
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
- try {
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 TokenZero to ${path2.relative(root, file)} for Cursor?`, a)) {
889
- cfg.mcpServers = { ...cfg.mcpServers ?? {}, tokenzero: { url: `${base}/mcp` } };
890
- fs2.mkdirSync(cursorDir, { recursive: true });
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.4",
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",