@bytevion/cli 0.5.0 → 0.5.2

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.
@@ -41,6 +41,42 @@ const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : Number(v)
41
41
  const usd = (v) => `$${num(v).toFixed(6)}`;
42
42
  const tokensOf = (m) => num(m?.tokens_in) + num(m?.tokens_out);
43
43
  const pad = (s, n) => s.padEnd(n);
44
+ const QUALITY_PASS = new Set(['quality_held', 'quality_improved', 'passed_verification']);
45
+ // The gateway scores each lane's quality in isolation; a soft "failed_verification" means
46
+ // an automated claim check was inconclusive, not that the answer is wrong or worse than
47
+ // direct. Render it as unverified rather than a scary raw state.
48
+ const qualityLabel = (s) => {
49
+ switch (s) {
50
+ case 'quality_held':
51
+ case 'quality_improved':
52
+ case 'passed_verification':
53
+ return 'held';
54
+ case 'failed_verification':
55
+ return 'unverified (auto-check inconclusive)';
56
+ case 'review':
57
+ return 'needs review';
58
+ case 'failed_guard':
59
+ return 'failed — output unusable';
60
+ case 'not_measured':
61
+ return 'not measured';
62
+ default:
63
+ return s;
64
+ }
65
+ };
66
+ const verdictLine = (dominance, quality, savingsPct, latencySaved) => {
67
+ const cheaper = savingsPct > 0;
68
+ const faster = latencySaved > 0;
69
+ const held = QUALITY_PASS.has(quality);
70
+ if (dominance === 'dominant')
71
+ return ui.theme.ok('Byte wins — cheaper, faster, quality held');
72
+ if (dominance === 'regressed')
73
+ return ui.theme.bad('Regressed — direct was the better choice here');
74
+ if (cheaper || faster) {
75
+ const wins = [cheaper ? `${savingsPct.toFixed(0)}% cheaper` : '', faster ? `${Math.abs(latencySaved)}ms faster` : ''].filter(Boolean).join(', ');
76
+ return ui.theme.ok(`Byte wins — ${wins}`) + (held ? '' : ui.theme.muted(' · quality unverified'));
77
+ }
78
+ return ui.theme.muted('Neutral — no clear difference');
79
+ };
44
80
  class Compare extends base_1.BaseCommand {
45
81
  static description = 'Prove the win: run a prompt direct vs through Byte and compare cost, latency, and quality.';
46
82
  static examples = [
@@ -94,9 +130,8 @@ class Compare extends base_1.BaseCommand {
94
130
  const sign = latencySaved >= 0 ? '−' : '+';
95
131
  this.log(` Savings ${usd(savings)} (${savingsPct.toFixed(1)}%)`);
96
132
  this.log(` Latency ${sign}${Math.abs(latencySaved)} ms`);
97
- this.log(` Quality ${quality}`);
98
- const verdict = dominance === 'dominant' ? ui.theme.ok('Byte wins (dominant)') : ui.theme.warn(dominance);
99
- this.log(` Verdict ${verdict}`);
133
+ this.log(` Quality ${qualityLabel(quality)}`);
134
+ this.log(` Verdict ${verdictLine(dominance, quality, savingsPct, latencySaved)}`);
100
135
  this.log('');
101
136
  return { direct, byte, summary };
102
137
  }
@@ -6,7 +6,10 @@ export default class Connect extends BaseCommand {
6
6
  model: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
7
  preset: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
8
  only: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ all: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ write: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
11
  yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
12
  };
11
13
  run(): Promise<unknown>;
14
+ private smokeTest;
12
15
  }
@@ -7,22 +7,26 @@ class Connect extends base_1.BaseCommand {
7
7
  static description = 'Detect installed coding agents and wire every one Byte can auto-configure — in one shot.';
8
8
  static examples = [
9
9
  '<%= config.bin %> connect',
10
- '<%= config.bin %> connect --model byte-2-deepseek-v4-flash',
10
+ '<%= config.bin %> connect --all --write',
11
11
  '<%= config.bin %> connect --only opencode,codex',
12
12
  ];
13
13
  static flags = {
14
- model: core_1.Flags.string({ description: 'Model id (byte alias) to wire (default byte-default)' }),
14
+ model: core_1.Flags.string({ description: 'Model to wire (default: auto — Byte routes to your enabled model)' }),
15
15
  preset: core_1.Flags.string({
16
16
  description: 'Optimization preset to apply before wiring',
17
17
  options: ['maximum', 'balanced', 'max_savings', 'lowest_latency', 'reliability_first'],
18
18
  }),
19
19
  only: core_1.Flags.string({ description: 'Comma-separated subset of tool keys to wire' }),
20
+ all: core_1.Flags.boolean({ description: 'Wire every detected auto-configurable tool (this is the default)' }),
21
+ write: core_1.Flags.boolean({ description: 'Write tool config files (the default for connect)' }),
20
22
  yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation prompts' }),
21
23
  };
22
24
  async run() {
23
25
  const { flags } = await this.parse(Connect);
24
26
  // A Byte key is what gets written into each tool's config, so require one up front.
25
- this.requireByteKey(flags);
27
+ const byteKey = this.requireByteKey(flags);
28
+ const model = flags.model || 'auto';
29
+ const bin = this.config.bin;
26
30
  const only = flags.only ? new Set(flags.only.split(',').map((s) => s.trim()).filter(Boolean)) : null;
27
31
  const detected = (0, detect_1.detectTools)().filter((d) => d.installed && (!only || only.has(d.key)));
28
32
  const targets = detected.filter((d) => d.canAutoWrite);
@@ -31,34 +35,61 @@ class Connect extends base_1.BaseCommand {
31
35
  if (!this.jsonEnabled()) {
32
36
  this.log('No auto-configurable coding agents detected.');
33
37
  if (manual.length)
34
- this.log(`Installed but manual: ${manual.join(', ')} — run \`byte integrate <tool>\`.`);
38
+ this.log(`Installed but manual: ${manual.join(', ')} — run \`${bin} integrate <tool>\`.`);
35
39
  else
36
- this.log('Install one (e.g. opencode) or wire manually with `byte integrate --list`.');
40
+ this.log(`Install one (e.g. opencode) or wire manually with \`${bin} integrate --list\`.`);
37
41
  }
38
42
  return { wired: [], manual };
39
43
  }
40
44
  const wired = [];
41
45
  for (const target of targets) {
42
- const argv = [
43
- target.key,
44
- '--write',
45
- '--yes',
46
- ...(flags.model ? ['--model', flags.model] : []),
47
- ...(flags.preset ? ['--preset', flags.preset] : []),
48
- ];
46
+ const argv = [target.key, '--write', '--yes', '--model', model, ...(flags.preset ? ['--preset', flags.preset] : [])];
49
47
  // sequential keeps config writes + their backups ordered and surfaces the first failure clearly
50
48
  // eslint-disable-next-line no-await-in-loop
51
49
  await this.config.runCommand('integrate', argv);
52
50
  wired.push(target.key);
53
51
  }
54
- if (!this.jsonEnabled()) {
55
- this.log('');
56
- this.log(`Connected ${wired.length} tool(s): ${wired.join(', ')}.`);
57
- if (manual.length)
58
- this.log(`Manual setup needed for: ${manual.join(', ')} run \`byte integrate <tool>\`.`);
59
- this.log('Export the Byte key in your shell (see `byte env`) and start coding.');
52
+ // Real smoke test of the shared gateway every config points at: list models, then send a
53
+ // model=auto completion. Only claim "connected" if both pass.
54
+ const probe = await this.smokeTest(byteKey, flags);
55
+ if (this.jsonEnabled())
56
+ return { wired, manual, model, verified: probe.ok, probe };
57
+ this.log('');
58
+ if (probe.ok) {
59
+ this.log(`Connected ${wired.length} tool(s): ${wired.join(', ')} ✓ gateway verified (model: ${model}).`);
60
+ }
61
+ else {
62
+ this.log(`Wired ${wired.length} tool(s): ${wired.join(', ')} — gateway smoke test did not pass: ${probe.reason}.`);
63
+ this.log(`Resolve that, then confirm with \`${bin} run "hi"\` or \`${bin} doctor\`.`);
64
+ }
65
+ if (manual.length)
66
+ this.log(`Manual setup needed for: ${manual.join(', ')} — run \`${bin} integrate <tool>\`.`);
67
+ this.log(`Export the Byte key in your shell (see \`${bin} env\`) and start coding.`);
68
+ return { wired, manual, model, verified: probe.ok };
69
+ }
70
+ // GET /v1/models then POST /v1/chat/completions model=auto, both with the Byte key. Returns
71
+ // a clear reason on failure so connect never prints "connected" for a wiring that won't work.
72
+ async smokeTest(byteKey, flags) {
73
+ const api = this.api(flags);
74
+ try {
75
+ await api.models(byteKey);
76
+ }
77
+ catch (err) {
78
+ const e = err;
79
+ return { ok: false, reason: `GET /v1/models failed (${e?.code || e?.message || 'unreachable'})` };
80
+ }
81
+ try {
82
+ const res = (await api.chat(byteKey, { model: 'auto', max_tokens: 1, messages: [{ role: 'user', content: 'ping' }] }));
83
+ if (res?.choices?.length || res?.id)
84
+ return { ok: true, reason: '' };
85
+ return { ok: false, reason: 'chat returned no choices' };
86
+ }
87
+ catch (err) {
88
+ const e = err;
89
+ const code = String(e?.code || e?.message || 'error');
90
+ const reason = code.includes('NOT_CONFIGURED') ? `no model enabled yet — run \`${this.config.bin} setup\` or enable a model` : `POST /v1/chat/completions model=auto failed (${code})`;
91
+ return { ok: false, reason };
60
92
  }
61
- return { wired, manual };
62
93
  }
63
94
  }
64
95
  exports.default = Connect;
@@ -64,7 +64,7 @@ class Integrate extends base_1.BaseCommand {
64
64
  write: core_1.Flags.boolean({ description: 'Write tool config files (a timestamped .bak is kept)' }),
65
65
  yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation prompts' }),
66
66
  key: core_1.Flags.string({ description: 'Byte API key to use (defaults to the saved profile key)' }),
67
- model: core_1.Flags.string({ description: 'Model id (byte alias) to wire (default byte-default)' }),
67
+ model: core_1.Flags.string({ description: 'Model to wire (default: auto — Byte routes to your enabled model)' }),
68
68
  preset: core_1.Flags.string({
69
69
  description: 'Apply this optimization preset to the org before wiring',
70
70
  options: ['balanced', 'max_savings', 'lowest_latency', 'reliability_first'],
@@ -90,11 +90,11 @@ class Integrate extends base_1.BaseCommand {
90
90
  }
91
91
  const integ = (0, integrations_1.findIntegration)(target);
92
92
  if (!integ)
93
- return this.error(`Unknown target "${target}". Run \`byte integrate --list\`.`, { exit: 2 });
93
+ return this.error(`Unknown target "${target}". Run \`${this.config.bin} integrate --list\`.`, { exit: 2 });
94
94
  const byteKey = flags.key || this.requireByteKey(flags);
95
95
  const base = this.baseUrlFrom(flags);
96
96
  const shell = (0, shell_1.detectShell)(flags.shell);
97
- const modelAlias = flags.model || 'byte-default';
97
+ const modelAlias = flags.model || 'auto';
98
98
  if (flags.preset) {
99
99
  this.requireToken(flags);
100
100
  await this.api(flags).optPatch({ default_mode: flags.preset });
@@ -191,7 +191,7 @@ class Integrate extends base_1.BaseCommand {
191
191
  const rows = (0, detect_1.detectTools)().map((d) => {
192
192
  let wired = false;
193
193
  const integ = (0, integrations_1.findIntegration)(d.key);
194
- const file = integ?.build({ baseUrl: base, byteKey, modelAlias: 'byte-default' }).settingsFile;
194
+ const file = integ?.build({ baseUrl: base, byteKey, modelAlias: 'auto' }).settingsFile;
195
195
  if (file && (0, node_fs_1.existsSync)(file.path)) {
196
196
  try {
197
197
  wired = (0, node_fs_1.readFileSync)(file.path, 'utf8').toLowerCase().includes('byte');
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../base';
2
+ export default class Metrics extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<unknown>;
9
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../base");
5
+ const output_1 = require("../lib/output");
6
+ const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : Number(v) || 0);
7
+ const pad = (s) => s.padEnd(12);
8
+ class Metrics extends base_1.BaseCommand {
9
+ static description = 'Full cost / latency / quality breakdown for a single request.';
10
+ static examples = ['<%= config.bin %> metrics 1429', '<%= config.bin %> requests # to find an id'];
11
+ static args = {
12
+ id: core_1.Args.string({ description: 'Request id (from the requests list or the dashboard)', required: true }),
13
+ };
14
+ async run() {
15
+ const { args, flags } = await this.parse(Metrics);
16
+ this.requireToken(flags);
17
+ const d = await this.api(flags).requestDetail(args.id);
18
+ if (this.jsonEnabled())
19
+ return d;
20
+ const cost = d.cost ?? {};
21
+ const tok = d.tokens ?? {};
22
+ const lat = d.latency ?? {};
23
+ const cache = d.cache ?? {};
24
+ const routedFrom = d.requested_model && d.requested_model !== d.routed_model ? ` (routed from: ${d.requested_model})` : '';
25
+ const layers = Array.isArray(d.layers) ? d.layers : [];
26
+ this.log('');
27
+ this.log(` ${pad('Model')}${d.routed_model ?? d.selected_alias ?? '-'}${routedFrom}`);
28
+ this.log(` ${pad('Cost')}direct ${(0, output_1.fmtUsd)(cost.raw_usd)} → byte ${(0, output_1.fmtUsd)(cost.byte_usd)} save ${num(cost.savings_pct).toFixed(1)}%`);
29
+ this.log(` ${pad('Tokens')}in ${num(tok.in)} out ${num(tok.out)}${num(tok.cached_in) ? ` (cached in ${num(tok.cached_in)})` : ''}`);
30
+ this.log(` ${pad('Latency')}${num(lat.total_ms)}ms · ttft ${num(lat.ttft_ms)}ms${num(lat.saved_ms) ? ` · saved ${num(lat.saved_ms)}ms` : ''}`);
31
+ this.log(` ${pad('Cache')}tier=${cache.layer ?? 'miss'} · quality=${d.quality_gate_state || 'n/a'}`);
32
+ if (layers.length)
33
+ this.log(` ${pad('Layers')}${layers.map((l) => `${l.layer}(${(0, output_1.fmtUsd)(l.savings_usd)})`).join(' ')}`);
34
+ this.log(` ${pad('Verdict')}${d.dominance_status || '-'}`);
35
+ this.log('');
36
+ return d;
37
+ }
38
+ }
39
+ exports.default = Metrics;
@@ -4,6 +4,7 @@ export default class Sync extends BaseCommand {
4
4
  static examples: string[];
5
5
  static flags: {
6
6
  model: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ all: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
8
  yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
9
  };
9
10
  run(): Promise<unknown>;
@@ -7,7 +7,8 @@ class Sync extends base_1.BaseCommand {
7
7
  static description = 'Re-apply your current Byte key/model to every wired coding agent (run after rotating a key or switching model).';
8
8
  static examples = ['<%= config.bin %> sync', '<%= config.bin %> sync --model byte-2-deepseek-v4-flash'];
9
9
  static flags = {
10
- model: core_1.Flags.string({ description: 'Model id (byte alias) to wire (defaults to the last wired model)' }),
10
+ model: core_1.Flags.string({ description: 'Model to wire (default: the last wired model, or auto)' }),
11
+ all: core_1.Flags.boolean({ description: 'Re-apply to every wired tool (this is the default)' }),
11
12
  yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation prompts' }),
12
13
  };
13
14
  async run() {
@@ -18,10 +19,10 @@ class Sync extends base_1.BaseCommand {
18
19
  const tools = wiring.tools || [];
19
20
  if (!tools.length) {
20
21
  if (!this.jsonEnabled())
21
- this.log('No wired tools yet. Run `byte connect` first.');
22
+ this.log(`No wired tools yet. Run \`${this.config.bin} connect\` first.`);
22
23
  return { synced: [] };
23
24
  }
24
- const model = flags.model || wiring.model;
25
+ const model = flags.model || wiring.model || 'auto';
25
26
  if (flags.model)
26
27
  (0, wiring_1.setSelectedModel)(profile, flags.model);
27
28
  const synced = [];
package/dist/lib/api.d.ts CHANGED
@@ -34,6 +34,7 @@ export declare class ByteApi {
34
34
  usage(granularity: string): Promise<any>;
35
35
  dashboard(): Promise<any>;
36
36
  requests(): Promise<any>;
37
+ requestDetail(id: string | number): Promise<any>;
37
38
  cacheStats(): Promise<any>;
38
39
  costs(): Promise<any>;
39
40
  health(): Promise<any>;
package/dist/lib/api.js CHANGED
@@ -138,6 +138,9 @@ class ByteApi {
138
138
  requests() {
139
139
  return this.request('GET', '/api/v1/requests');
140
140
  }
141
+ requestDetail(id) {
142
+ return this.request('GET', `/api/v1/requests/${encodeURIComponent(String(id))}`);
143
+ }
141
144
  cacheStats() {
142
145
  return this.request('GET', '/api/v1/cache/stats');
143
146
  }
package/dist/lib/home.js CHANGED
@@ -68,7 +68,13 @@ async function loadHomeData(api, byteKey, fallbackId) {
68
68
  providers: conns.length || undefined,
69
69
  models: models || undefined,
70
70
  byteKey,
71
- gateway: health ? (health.status === 'ok' || health.ok ? 'healthy' : 'down') : 'unknown',
71
+ // The control plane reports a ready gateway as status:"ready" (and mirrors it in
72
+ // health.gateway). Accept "ready"/"ok"/ok so a healthy gateway is never shown as down.
73
+ gateway: health
74
+ ? health.status === 'ready' || health.status === 'ok' || health.gateway === 'ready' || health.gateway === 'ok' || health.ok
75
+ ? 'healthy'
76
+ : 'down'
77
+ : 'unknown',
72
78
  savingsSeries: series.map((p) => num(p.savings_usd)),
73
79
  savedTotal: series.reduce((a, p) => a + num(p.savings_usd), 0),
74
80
  tokensTotal: series.reduce((a, p) => a + num(p.tokens_in) + num(p.tokens_out), 0),
@@ -68,7 +68,7 @@
68
68
  "description": "Detect installed coding agents and wire every one Byte can auto-configure — in one shot.",
69
69
  "examples": [
70
70
  "<%= config.bin %> connect",
71
- "<%= config.bin %> connect --model byte-2-deepseek-v4-flash",
71
+ "<%= config.bin %> connect --all --write",
72
72
  "<%= config.bin %> connect --only opencode,codex"
73
73
  ],
74
74
  "flags": {
@@ -96,7 +96,7 @@
96
96
  "type": "option"
97
97
  },
98
98
  "model": {
99
- "description": "Model id (byte alias) to wire (default byte-default)",
99
+ "description": "Model to wire (default: auto — Byte routes to your enabled model)",
100
100
  "name": "model",
101
101
  "hasDynamicHelp": false,
102
102
  "multiple": false,
@@ -123,6 +123,18 @@
123
123
  "multiple": false,
124
124
  "type": "option"
125
125
  },
126
+ "all": {
127
+ "description": "Wire every detected auto-configurable tool (this is the default)",
128
+ "name": "all",
129
+ "allowNo": false,
130
+ "type": "boolean"
131
+ },
132
+ "write": {
133
+ "description": "Write tool config files (the default for connect)",
134
+ "name": "write",
135
+ "allowNo": false,
136
+ "type": "boolean"
137
+ },
126
138
  "yes": {
127
139
  "char": "y",
128
140
  "description": "Skip confirmation prompts",
@@ -479,7 +491,7 @@
479
491
  "type": "option"
480
492
  },
481
493
  "model": {
482
- "description": "Model id (byte alias) to wire (default byte-default)",
494
+ "description": "Model to wire (default: auto — Byte routes to your enabled model)",
483
495
  "name": "model",
484
496
  "hasDynamicHelp": false,
485
497
  "multiple": false,
@@ -612,6 +624,60 @@
612
624
  "logout.js"
613
625
  ]
614
626
  },
627
+ "metrics": {
628
+ "aliases": [],
629
+ "args": {
630
+ "id": {
631
+ "description": "Request id (from the requests list or the dashboard)",
632
+ "name": "id",
633
+ "required": true
634
+ }
635
+ },
636
+ "description": "Full cost / latency / quality breakdown for a single request.",
637
+ "examples": [
638
+ "<%= config.bin %> metrics 1429",
639
+ "<%= config.bin %> requests # to find an id"
640
+ ],
641
+ "flags": {
642
+ "json": {
643
+ "description": "Format output as json.",
644
+ "helpGroup": "GLOBAL",
645
+ "name": "json",
646
+ "allowNo": false,
647
+ "type": "boolean"
648
+ },
649
+ "profile": {
650
+ "description": "Configuration profile to use",
651
+ "env": "BYTE_PROFILE",
652
+ "name": "profile",
653
+ "hasDynamicHelp": false,
654
+ "multiple": false,
655
+ "type": "option"
656
+ },
657
+ "base-url": {
658
+ "description": "Override the API base URL",
659
+ "env": "BYTE_BASE_URL",
660
+ "name": "base-url",
661
+ "hasDynamicHelp": false,
662
+ "multiple": false,
663
+ "type": "option"
664
+ }
665
+ },
666
+ "hasDynamicHelp": false,
667
+ "hiddenAliases": [],
668
+ "id": "metrics",
669
+ "pluginAlias": "@bytevion/cli",
670
+ "pluginName": "@bytevion/cli",
671
+ "pluginType": "core",
672
+ "strict": true,
673
+ "enableJsonFlag": true,
674
+ "isESM": false,
675
+ "relativePath": [
676
+ "dist",
677
+ "commands",
678
+ "metrics.js"
679
+ ]
680
+ },
615
681
  "run": {
616
682
  "aliases": [],
617
683
  "args": {
@@ -874,12 +940,18 @@
874
940
  "type": "option"
875
941
  },
876
942
  "model": {
877
- "description": "Model id (byte alias) to wire (defaults to the last wired model)",
943
+ "description": "Model to wire (default: the last wired model, or auto)",
878
944
  "name": "model",
879
945
  "hasDynamicHelp": false,
880
946
  "multiple": false,
881
947
  "type": "option"
882
948
  },
949
+ "all": {
950
+ "description": "Re-apply to every wired tool (this is the default)",
951
+ "name": "all",
952
+ "allowNo": false,
953
+ "type": "boolean"
954
+ },
883
955
  "yes": {
884
956
  "char": "y",
885
957
  "description": "Skip confirmation prompts",
@@ -2200,5 +2272,5 @@
2200
2272
  ]
2201
2273
  }
2202
2274
  },
2203
- "version": "0.5.0"
2275
+ "version": "0.5.2"
2204
2276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytevion/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Byte — control your LLM optimization gateway from the terminal.",
5
5
  "author": "Byte",
6
6
  "license": "UNLICENSED",