voyageai-cli 1.7.0 → 1.9.0

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.
@@ -0,0 +1,252 @@
1
+ 'use strict';
2
+
3
+ const { describe, it } = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+ const { Command } = require('commander');
6
+ const { registerBenchmark } = require('../../src/commands/benchmark');
7
+
8
+ describe('benchmark command', () => {
9
+ it('registers as benchmark with bench alias', () => {
10
+ const program = new Command();
11
+ registerBenchmark(program);
12
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
13
+ assert.ok(benchCmd, 'benchmark command should be registered');
14
+ assert.ok(benchCmd.aliases().includes('bench'), 'should have "bench" alias');
15
+ });
16
+
17
+ it('has embed subcommand', () => {
18
+ const program = new Command();
19
+ registerBenchmark(program);
20
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
21
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
22
+ assert.ok(embedSub, 'embed subcommand should be registered');
23
+ });
24
+
25
+ it('embed has --models option', () => {
26
+ const program = new Command();
27
+ registerBenchmark(program);
28
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
29
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
30
+ const optionNames = embedSub.options.map(o => o.long);
31
+ assert.ok(optionNames.includes('--models'), 'should have --models option');
32
+ });
33
+
34
+ it('embed has --rounds option', () => {
35
+ const program = new Command();
36
+ registerBenchmark(program);
37
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
38
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
39
+ const optionNames = embedSub.options.map(o => o.long);
40
+ assert.ok(optionNames.includes('--rounds'), 'should have --rounds option');
41
+ });
42
+
43
+ it('embed has --input option for custom text', () => {
44
+ const program = new Command();
45
+ registerBenchmark(program);
46
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
47
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
48
+ const optionNames = embedSub.options.map(o => o.long);
49
+ assert.ok(optionNames.includes('--input'), 'should have --input option');
50
+ });
51
+
52
+ it('embed has --file option', () => {
53
+ const program = new Command();
54
+ registerBenchmark(program);
55
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
56
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
57
+ const optionNames = embedSub.options.map(o => o.long);
58
+ assert.ok(optionNames.includes('--file'), 'should have --file option');
59
+ });
60
+
61
+ it('embed has --json and --quiet options', () => {
62
+ const program = new Command();
63
+ registerBenchmark(program);
64
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
65
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
66
+ const optionNames = embedSub.options.map(o => o.long);
67
+ assert.ok(optionNames.includes('--json'), 'should have --json option');
68
+ assert.ok(optionNames.includes('--quiet'), 'should have --quiet option');
69
+ });
70
+
71
+ it('embed has --dimensions option', () => {
72
+ const program = new Command();
73
+ registerBenchmark(program);
74
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
75
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
76
+ const optionNames = embedSub.options.map(o => o.long);
77
+ assert.ok(optionNames.includes('--dimensions'), 'should have --dimensions option');
78
+ });
79
+
80
+ it('has rerank subcommand', () => {
81
+ const program = new Command();
82
+ registerBenchmark(program);
83
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
84
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
85
+ assert.ok(rerankSub, 'rerank subcommand should be registered');
86
+ });
87
+
88
+ it('rerank has --models and --rounds options', () => {
89
+ const program = new Command();
90
+ registerBenchmark(program);
91
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
92
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
93
+ const optionNames = rerankSub.options.map(o => o.long);
94
+ assert.ok(optionNames.includes('--models'), 'should have --models option');
95
+ assert.ok(optionNames.includes('--rounds'), 'should have --rounds option');
96
+ });
97
+
98
+ it('rerank has --query option', () => {
99
+ const program = new Command();
100
+ registerBenchmark(program);
101
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
102
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
103
+ const optionNames = rerankSub.options.map(o => o.long);
104
+ assert.ok(optionNames.includes('--query'), 'should have --query option');
105
+ });
106
+
107
+ it('rerank has --documents-file and --top-k options', () => {
108
+ const program = new Command();
109
+ registerBenchmark(program);
110
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
111
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
112
+ const optionNames = rerankSub.options.map(o => o.long);
113
+ assert.ok(optionNames.includes('--documents-file'), 'should have --documents-file option');
114
+ assert.ok(optionNames.includes('--top-k'), 'should have --top-k option');
115
+ });
116
+
117
+ it('has similarity subcommand', () => {
118
+ const program = new Command();
119
+ registerBenchmark(program);
120
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
121
+ const simSub = benchCmd.commands.find(c => c.name() === 'similarity');
122
+ assert.ok(simSub, 'similarity subcommand should be registered');
123
+ });
124
+
125
+ it('similarity has --models, --query, --file, --top-k options', () => {
126
+ const program = new Command();
127
+ registerBenchmark(program);
128
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
129
+ const simSub = benchCmd.commands.find(c => c.name() === 'similarity');
130
+ const optionNames = simSub.options.map(o => o.long);
131
+ assert.ok(optionNames.includes('--models'), 'should have --models');
132
+ assert.ok(optionNames.includes('--query'), 'should have --query');
133
+ assert.ok(optionNames.includes('--file'), 'should have --file');
134
+ assert.ok(optionNames.includes('--top-k'), 'should have --top-k');
135
+ });
136
+
137
+ it('has cost subcommand', () => {
138
+ const program = new Command();
139
+ registerBenchmark(program);
140
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
141
+ const costSub = benchCmd.commands.find(c => c.name() === 'cost');
142
+ assert.ok(costSub, 'cost subcommand should be registered');
143
+ });
144
+
145
+ it('cost has --models, --tokens, --volumes options', () => {
146
+ const program = new Command();
147
+ registerBenchmark(program);
148
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
149
+ const costSub = benchCmd.commands.find(c => c.name() === 'cost');
150
+ const optionNames = costSub.options.map(o => o.long);
151
+ assert.ok(optionNames.includes('--models'), 'should have --models');
152
+ assert.ok(optionNames.includes('--tokens'), 'should have --tokens');
153
+ assert.ok(optionNames.includes('--volumes'), 'should have --volumes');
154
+ });
155
+
156
+ it('has batch subcommand', () => {
157
+ const program = new Command();
158
+ registerBenchmark(program);
159
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
160
+ const batchSub = benchCmd.commands.find(c => c.name() === 'batch');
161
+ assert.ok(batchSub, 'batch subcommand should be registered');
162
+ });
163
+
164
+ it('batch has --model, --batch-sizes, --rounds options', () => {
165
+ const program = new Command();
166
+ registerBenchmark(program);
167
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
168
+ const batchSub = benchCmd.commands.find(c => c.name() === 'batch');
169
+ const optionNames = batchSub.options.map(o => o.long);
170
+ assert.ok(optionNames.includes('--model'), 'should have --model');
171
+ assert.ok(optionNames.includes('--batch-sizes'), 'should have --batch-sizes');
172
+ assert.ok(optionNames.includes('--rounds'), 'should have --rounds');
173
+ });
174
+
175
+ it('all subcommands have --json output option', () => {
176
+ const program = new Command();
177
+ registerBenchmark(program);
178
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
179
+
180
+ for (const sub of benchCmd.commands) {
181
+ if (sub.name() === 'help') continue;
182
+ const optionNames = sub.options.map(o => o.long);
183
+ assert.ok(optionNames.includes('--json'), `${sub.name()} should have --json option`);
184
+ }
185
+ });
186
+
187
+ it('all subcommands have --quiet option', () => {
188
+ const program = new Command();
189
+ registerBenchmark(program);
190
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
191
+
192
+ for (const sub of benchCmd.commands) {
193
+ if (sub.name() === 'help') continue;
194
+ const optionNames = sub.options.map(o => o.long);
195
+ assert.ok(optionNames.includes('--quiet'), `${sub.name()} should have --quiet option`);
196
+ }
197
+ });
198
+
199
+ it('embed defaults models to voyage-4-large,voyage-4,voyage-4-lite', () => {
200
+ const program = new Command();
201
+ registerBenchmark(program);
202
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
203
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
204
+ const modelsOpt = embedSub.options.find(o => o.long === '--models');
205
+ assert.equal(modelsOpt.defaultValue, 'voyage-4-large,voyage-4,voyage-4-lite');
206
+ });
207
+
208
+ it('rerank defaults models to rerank-2.5,rerank-2.5-lite', () => {
209
+ const program = new Command();
210
+ registerBenchmark(program);
211
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
212
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
213
+ const modelsOpt = rerankSub.options.find(o => o.long === '--models');
214
+ assert.equal(modelsOpt.defaultValue, 'rerank-2.5,rerank-2.5-lite');
215
+ });
216
+
217
+ it('cost defaults volumes to 100,1000,10000,100000', () => {
218
+ const program = new Command();
219
+ registerBenchmark(program);
220
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
221
+ const costSub = benchCmd.commands.find(c => c.name() === 'cost');
222
+ const volOpt = costSub.options.find(o => o.long === '--volumes');
223
+ assert.equal(volOpt.defaultValue, '100,1000,10000,100000');
224
+ });
225
+
226
+ it('embed has --save option', () => {
227
+ const program = new Command();
228
+ registerBenchmark(program);
229
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
230
+ const embedSub = benchCmd.commands.find(c => c.name() === 'embed');
231
+ const optionNames = embedSub.options.map(o => o.long);
232
+ assert.ok(optionNames.includes('--save'), 'should have --save option');
233
+ });
234
+
235
+ it('rerank has --save option', () => {
236
+ const program = new Command();
237
+ registerBenchmark(program);
238
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
239
+ const rerankSub = benchCmd.commands.find(c => c.name() === 'rerank');
240
+ const optionNames = rerankSub.options.map(o => o.long);
241
+ assert.ok(optionNames.includes('--save'), 'should have --save option');
242
+ });
243
+
244
+ it('batch defaults batch-sizes to 1,5,10,25,50', () => {
245
+ const program = new Command();
246
+ registerBenchmark(program);
247
+ const benchCmd = program.commands.find(c => c.name() === 'benchmark');
248
+ const batchSub = benchCmd.commands.find(c => c.name() === 'batch');
249
+ const sizesOpt = batchSub.options.find(o => o.long === '--batch-sizes');
250
+ assert.equal(sizesOpt.defaultValue, '1,5,10,25,50');
251
+ });
252
+ });
@@ -14,6 +14,10 @@ describe('ping command', () => {
14
14
  let output;
15
15
  let errorOutput;
16
16
 
17
+ // Strip ANSI escape codes for reliable string assertions in CI
18
+ // (GitHub Actions sets FORCE_COLOR which adds ANSI codes via picocolors)
19
+ const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
20
+
17
21
  beforeEach(() => {
18
22
  originalLog = console.log;
19
23
  originalError = console.error;
@@ -70,7 +74,7 @@ describe('ping command', () => {
70
74
 
71
75
  await program.parseAsync(['node', 'test', 'ping']);
72
76
 
73
- const combined = output.join('\n');
77
+ const combined = stripAnsi(output.join('\n'));
74
78
  assert.ok(combined.includes('✓ Connected to Voyage AI API'), 'Should show success message');
75
79
  assert.ok(combined.includes('voyage-4-lite'), 'Should show model name');
76
80
  assert.ok(combined.includes('1024'), 'Should show dimensions');
@@ -101,7 +105,7 @@ describe('ping command', () => {
101
105
  );
102
106
 
103
107
  assert.equal(exitCode, 1);
104
- const combined = errorOutput.join('\n');
108
+ const combined = stripAnsi(errorOutput.join('\n'));
105
109
  assert.ok(combined.includes('Authentication failed'), 'Should show auth error');
106
110
  });
107
111
 
@@ -134,7 +138,7 @@ describe('ping command', () => {
134
138
  );
135
139
 
136
140
  assert.equal(exitCode, 1);
137
- const combined = errorOutput.join('\n');
141
+ const combined = stripAnsi(errorOutput.join('\n'));
138
142
  assert.ok(combined.includes('VOYAGE_API_KEY'), 'Should mention missing key');
139
143
  } finally {
140
144
  config.getConfigValue = origGetConfigValue;
@@ -17,6 +17,7 @@ describe('explanations', () => {
17
17
  'api-keys',
18
18
  'api-access',
19
19
  'batch-processing',
20
+ 'benchmarking',
20
21
  ];
21
22
 
22
23
  it('has all expected concepts', () => {