@pauly4010/evalai-sdk 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.
- package/CHANGELOG.md +124 -0
- package/README.md +42 -1
- package/dist/cli/check.js +15 -0
- package/dist/cli/ci.d.ts +45 -0
- package/dist/cli/ci.js +192 -0
- package/dist/cli/diff.d.ts +173 -0
- package/dist/cli/diff.js +680 -0
- package/dist/cli/discover.d.ts +84 -0
- package/dist/cli/discover.js +408 -0
- package/dist/cli/doctor.d.ts +80 -3
- package/dist/cli/doctor.js +583 -41
- package/dist/cli/env.d.ts +21 -0
- package/dist/cli/env.js +42 -0
- package/dist/cli/explain.d.ts +58 -0
- package/dist/cli/explain.js +535 -0
- package/dist/cli/formatters/github.js +5 -0
- package/dist/cli/formatters/types.d.ts +3 -0
- package/dist/cli/formatters/types.js +3 -0
- package/dist/cli/impact-analysis.d.ts +63 -0
- package/dist/cli/impact-analysis.js +251 -0
- package/dist/cli/index.js +214 -4
- package/dist/cli/init.js +16 -4
- package/dist/cli/manifest.d.ts +105 -0
- package/dist/cli/manifest.js +275 -0
- package/dist/cli/migrate.d.ts +41 -0
- package/dist/cli/migrate.js +349 -0
- package/dist/cli/print-config.d.ts +29 -0
- package/dist/cli/print-config.js +255 -0
- package/dist/cli/report/build-check-report.d.ts +1 -1
- package/dist/cli/report/build-check-report.js +2 -0
- package/dist/cli/run.d.ts +101 -0
- package/dist/cli/run.js +389 -0
- package/dist/cli/workspace.d.ts +28 -0
- package/dist/cli/workspace.js +58 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +30 -5
- package/dist/runtime/adapters/config-to-dsl.d.ts +33 -0
- package/dist/runtime/adapters/config-to-dsl.js +391 -0
- package/dist/runtime/adapters/testsuite-to-dsl.d.ts +63 -0
- package/dist/runtime/adapters/testsuite-to-dsl.js +271 -0
- package/dist/runtime/context.d.ts +26 -0
- package/dist/runtime/context.js +74 -0
- package/dist/runtime/eval.d.ts +46 -0
- package/dist/runtime/eval.js +237 -0
- package/dist/runtime/execution-mode.d.ts +80 -0
- package/dist/runtime/execution-mode.js +353 -0
- package/dist/runtime/executor.d.ts +16 -0
- package/dist/runtime/executor.js +152 -0
- package/dist/runtime/registry.d.ts +78 -0
- package/dist/runtime/registry.js +416 -0
- package/dist/runtime/run-report.d.ts +202 -0
- package/dist/runtime/run-report.js +220 -0
- package/dist/runtime/types.d.ts +356 -0
- package/dist/runtime/types.js +76 -0
- package/dist/testing.d.ts +65 -0
- package/dist/testing.js +42 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* COMPAT-203: Config → DSL migration generator (file-based)
|
|
4
|
+
*
|
|
5
|
+
* CLI command: evalai migrate config --in evalai.config.json --out eval/legacy.spec.ts
|
|
6
|
+
* Generates defineEval() calls with comments and TODOs for manual completion
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.migrateConfig = migrateConfig;
|
|
43
|
+
exports.createMigrateCommand = createMigrateCommand;
|
|
44
|
+
exports.validateConfigFile = validateConfigFile;
|
|
45
|
+
exports.previewMigration = previewMigration;
|
|
46
|
+
const commander_1 = require("commander");
|
|
47
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const testsuite_to_dsl_1 = require("../runtime/adapters/testsuite-to-dsl");
|
|
50
|
+
const testing_1 = require("../testing");
|
|
51
|
+
/**
|
|
52
|
+
* Read and parse evalai.config.json
|
|
53
|
+
*/
|
|
54
|
+
async function readConfigFile(filePath) {
|
|
55
|
+
try {
|
|
56
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
57
|
+
return JSON.parse(content);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new Error(`Failed to read config file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract TestSuite data from config
|
|
65
|
+
*/
|
|
66
|
+
function extractTestSuitesFromConfig(config) {
|
|
67
|
+
const suites = [];
|
|
68
|
+
// Handle different config structures
|
|
69
|
+
if (config.tests) {
|
|
70
|
+
// Direct tests array
|
|
71
|
+
const suite = (0, testing_1.createTestSuite)("config-tests", {
|
|
72
|
+
cases: config.tests,
|
|
73
|
+
executor: config.executor,
|
|
74
|
+
timeout: config.timeout,
|
|
75
|
+
parallel: config.parallel,
|
|
76
|
+
stopOnFailure: config.stopOnFailure,
|
|
77
|
+
retries: config.retries,
|
|
78
|
+
});
|
|
79
|
+
suites.push({ name: "config-tests", suite });
|
|
80
|
+
}
|
|
81
|
+
if (config.suites) {
|
|
82
|
+
// Multiple named suites
|
|
83
|
+
for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {
|
|
84
|
+
const suite = (0, testing_1.createTestSuite)(suiteName, suiteConfig);
|
|
85
|
+
suites.push({ name: suiteName, suite });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (config.testSuites) {
|
|
89
|
+
// Alternative property name
|
|
90
|
+
for (const [suiteName, suiteConfig] of Object.entries(config.testSuites)) {
|
|
91
|
+
const suite = (0, testing_1.createTestSuite)(suiteName, suiteConfig);
|
|
92
|
+
suites.push({ name: suiteName, suite });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return suites;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Generate DSL file header
|
|
99
|
+
*/
|
|
100
|
+
function generateFileHeader(config, options) {
|
|
101
|
+
const timestamp = new Date().toISOString();
|
|
102
|
+
const inputPath = path.resolve(options.input);
|
|
103
|
+
const outputPath = path.resolve(options.output);
|
|
104
|
+
return [
|
|
105
|
+
`/**`,
|
|
106
|
+
` * Auto-generated EvalAI DSL from configuration`,
|
|
107
|
+
` * `,
|
|
108
|
+
` * Generated at: ${timestamp}`,
|
|
109
|
+
` * Source config: ${inputPath}`,
|
|
110
|
+
` * Output file: ${outputPath}`,
|
|
111
|
+
` * `,
|
|
112
|
+
` * This file contains defineEval() specifications migrated from evalai.config.json`,
|
|
113
|
+
` * `,
|
|
114
|
+
` * ⚠️ IMPORTANT: This is a best-effort migration. Manual review and completion required.`,
|
|
115
|
+
` * `,
|
|
116
|
+
` * Migration notes:`,
|
|
117
|
+
` * - Executors have been converted to async functions`,
|
|
118
|
+
` * - Assertions have been converted where possible`,
|
|
119
|
+
` * - Complex logic may need manual adaptation`,
|
|
120
|
+
` * - Review TODO comments for items requiring attention`,
|
|
121
|
+
` */`,
|
|
122
|
+
``,
|
|
123
|
+
`import { defineEval, createResult } from '@pauly4010/evalai-sdk';`,
|
|
124
|
+
``,
|
|
125
|
+
].join("\n");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate helper functions for the entire file
|
|
129
|
+
*/
|
|
130
|
+
function generateGlobalHelpers(config, options) {
|
|
131
|
+
const helpers = [];
|
|
132
|
+
// Add executor helper if config has executor
|
|
133
|
+
if (config.executor) {
|
|
134
|
+
helpers.push([
|
|
135
|
+
`/**`,
|
|
136
|
+
` * Legacy executor function from config`,
|
|
137
|
+
` * TODO: Replace with actual executor implementation`,
|
|
138
|
+
` */`,
|
|
139
|
+
`async function legacyExecutor(input: string): Promise<string> {`,
|
|
140
|
+
` // Original executor was: ${config.executor.toString()}`,
|
|
141
|
+
` // TODO: Implement actual executor logic here`,
|
|
142
|
+
` return input; // Placeholder`,
|
|
143
|
+
`}`,
|
|
144
|
+
``,
|
|
145
|
+
].join("\n"));
|
|
146
|
+
}
|
|
147
|
+
// Add assertion helpers
|
|
148
|
+
helpers.push([
|
|
149
|
+
`/**`,
|
|
150
|
+
` * Helper function for legacy assertion evaluation`,
|
|
151
|
+
` * TODO: Implement actual assertion logic based on original config`,
|
|
152
|
+
` */`,
|
|
153
|
+
`function evaluateAssertions(output: string, expected?: string): boolean {`,
|
|
154
|
+
` if (expected !== undefined) {`,
|
|
155
|
+
` return output === expected;`,
|
|
156
|
+
` }`,
|
|
157
|
+
` return output.length > 0;`,
|
|
158
|
+
`}`,
|
|
159
|
+
``,
|
|
160
|
+
].join("\n"));
|
|
161
|
+
// Add evaluation helper
|
|
162
|
+
helpers.push([
|
|
163
|
+
`/**`,
|
|
164
|
+
` * Legacy test evaluation function`,
|
|
165
|
+
` * TODO: Adapt based on your original test logic`,
|
|
166
|
+
` */`,
|
|
167
|
+
`async function evaluateLegacyTest(input: string, expected?: string): Promise<any> {`,
|
|
168
|
+
` const output = await legacyExecutor(input);`,
|
|
169
|
+
` const passed = evaluateAssertions(output, expected);`,
|
|
170
|
+
` `,
|
|
171
|
+
` return createResult({`,
|
|
172
|
+
` pass: passed,`,
|
|
173
|
+
` score: passed ? 100 : 0,`,
|
|
174
|
+
` metadata: { input, expected },`,
|
|
175
|
+
` });`,
|
|
176
|
+
`}`,
|
|
177
|
+
``,
|
|
178
|
+
].join("\n"));
|
|
179
|
+
return helpers.join("\n");
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Generate DSL content for a single suite
|
|
183
|
+
*/
|
|
184
|
+
function generateSuiteDSL(suiteName, suite, options) {
|
|
185
|
+
const dslCode = (0, testsuite_to_dsl_1.generateDefineEvalCode)(suite, {
|
|
186
|
+
generateHelpers: options.helpers,
|
|
187
|
+
preserveIds: options.preserveIds,
|
|
188
|
+
includeProvenance: options.provenance,
|
|
189
|
+
});
|
|
190
|
+
// Add suite-specific comments
|
|
191
|
+
const header = [
|
|
192
|
+
`/**`,
|
|
193
|
+
` * Test suite: ${suiteName}`,
|
|
194
|
+
` * Migrated from evalai.config.json`,
|
|
195
|
+
` * `,
|
|
196
|
+
` * TODO items for this suite:`,
|
|
197
|
+
` * - Review executor implementation`,
|
|
198
|
+
` * - Verify assertion logic`,
|
|
199
|
+
` * - Test with actual data`,
|
|
200
|
+
` */`,
|
|
201
|
+
``,
|
|
202
|
+
].join("\n");
|
|
203
|
+
return header + dslCode;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Generate migration summary
|
|
207
|
+
*/
|
|
208
|
+
function generateSummary(suites, options) {
|
|
209
|
+
const totalTests = suites.reduce((sum, { suite }) => sum + suite.getTests().length, 0);
|
|
210
|
+
const totalSuites = suites.length;
|
|
211
|
+
return [
|
|
212
|
+
`/**`,
|
|
213
|
+
` * Migration Summary`,
|
|
214
|
+
` * =================`,
|
|
215
|
+
` * `,
|
|
216
|
+
` * Total suites migrated: ${totalSuites}`,
|
|
217
|
+
` * Total tests migrated: ${totalTests}`,
|
|
218
|
+
` * `,
|
|
219
|
+
` * Migration options used:`,
|
|
220
|
+
` * - Include helpers: ${options.helpers}`,
|
|
221
|
+
` * - Preserve IDs: ${options.preserveIds}`,
|
|
222
|
+
` * - Include provenance: ${options.provenance}`,
|
|
223
|
+
` * `,
|
|
224
|
+
` * Next steps:`,
|
|
225
|
+
` * 1. Review all TODO comments in this file`,
|
|
226
|
+
` * 2. Implement actual executor logic`,
|
|
227
|
+
` * 3. Adapt complex assertions`,
|
|
228
|
+
` * 4. Test with real data`,
|
|
229
|
+
` * 5. Remove evalai.config.json when satisfied`,
|
|
230
|
+
` * `,
|
|
231
|
+
` * For help with migration, see: https://github.com/pauly7610/ai-evaluation-platform/docs/MIGRATION.md`,
|
|
232
|
+
` */`,
|
|
233
|
+
``,
|
|
234
|
+
].join("\n");
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Main migration function
|
|
238
|
+
*/
|
|
239
|
+
async function migrateConfig(options) {
|
|
240
|
+
try {
|
|
241
|
+
// Read input config
|
|
242
|
+
const config = await readConfigFile(options.input);
|
|
243
|
+
// Extract test suites
|
|
244
|
+
const suites = extractTestSuitesFromConfig(config);
|
|
245
|
+
if (suites.length === 0) {
|
|
246
|
+
throw new Error("No test suites found in config file. Check config structure.");
|
|
247
|
+
}
|
|
248
|
+
// Generate DSL content
|
|
249
|
+
const content = [
|
|
250
|
+
generateFileHeader(config, options),
|
|
251
|
+
generateGlobalHelpers(config, options),
|
|
252
|
+
...suites.map(({ name, suite }) => generateSuiteDSL(name, suite, options)),
|
|
253
|
+
generateSummary(suites, options),
|
|
254
|
+
].join("\n");
|
|
255
|
+
// Ensure output directory exists
|
|
256
|
+
const outputDir = path.dirname(options.output);
|
|
257
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
258
|
+
// Write output file
|
|
259
|
+
await fs.writeFile(options.output, content, "utf-8");
|
|
260
|
+
console.log(`✅ Migration complete!`);
|
|
261
|
+
console.log(`📁 Output written to: ${path.resolve(options.output)}`);
|
|
262
|
+
console.log(`📊 Migrated ${suites.length} suites with ${suites.reduce((sum, { suite }) => sum + suite.getTests().length, 0)} tests`);
|
|
263
|
+
console.log(`\n⚠️ Remember to review TODO comments and test the migration!`);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
console.error(`❌ Migration failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* CLI command definition
|
|
272
|
+
*/
|
|
273
|
+
function createMigrateCommand() {
|
|
274
|
+
const command = new commander_1.Command("migrate")
|
|
275
|
+
.description("Migrate legacy configuration to new DSL format")
|
|
276
|
+
.command("config")
|
|
277
|
+
.description("Migrate evalai.config.json to defineEval() specifications")
|
|
278
|
+
.requiredOption("-i, --in <path>", "Input config file path")
|
|
279
|
+
.requiredOption("-o, --out <path>", "Output DSL file path")
|
|
280
|
+
.option("-v, --verbose", "Include detailed comments and logging", false)
|
|
281
|
+
.option("--no-helpers", "Don't generate helper functions")
|
|
282
|
+
.option("--no-preserve-ids", "Don't preserve original test IDs")
|
|
283
|
+
.option("--no-provenance", "Don't include provenance metadata")
|
|
284
|
+
.action(async (options) => {
|
|
285
|
+
const migrateOptions = {
|
|
286
|
+
input: options.in,
|
|
287
|
+
output: options.out,
|
|
288
|
+
verbose: options.verbose,
|
|
289
|
+
helpers: options.helpers !== false,
|
|
290
|
+
preserveIds: options.preserveIds !== false,
|
|
291
|
+
provenance: options.provenance !== false,
|
|
292
|
+
};
|
|
293
|
+
await migrateConfig(migrateOptions);
|
|
294
|
+
});
|
|
295
|
+
return command;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Validate config file structure
|
|
299
|
+
*/
|
|
300
|
+
async function validateConfigFile(filePath) {
|
|
301
|
+
try {
|
|
302
|
+
const config = await readConfigFile(filePath);
|
|
303
|
+
// Basic validation
|
|
304
|
+
if (!config || typeof config !== "object") {
|
|
305
|
+
throw new Error("Config file must contain a valid JSON object");
|
|
306
|
+
}
|
|
307
|
+
// Check for test data
|
|
308
|
+
const hasTests = config.tests || config.suites || config.testSuites;
|
|
309
|
+
if (!hasTests) {
|
|
310
|
+
throw new Error("Config file must contain 'tests', 'suites', or 'testSuites' property");
|
|
311
|
+
}
|
|
312
|
+
console.log(`✅ Config file ${filePath} appears valid for migration`);
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
console.error(`❌ Config validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Show migration preview without writing files
|
|
322
|
+
*/
|
|
323
|
+
async function previewMigration(filePath) {
|
|
324
|
+
try {
|
|
325
|
+
const config = await readConfigFile(filePath);
|
|
326
|
+
const suites = extractTestSuitesFromConfig(config);
|
|
327
|
+
console.log(`📋 Migration preview for: ${filePath}`);
|
|
328
|
+
console.log(``);
|
|
329
|
+
console.log(`Found ${suites.length} test suites:`);
|
|
330
|
+
console.log(``);
|
|
331
|
+
for (const { name, suite } of suites) {
|
|
332
|
+
const tests = suite.getTests();
|
|
333
|
+
console.log(` 📁 ${name}: ${tests.length} tests`);
|
|
334
|
+
if (tests.length > 0) {
|
|
335
|
+
console.log(` Tests: ${tests
|
|
336
|
+
.slice(0, 3)
|
|
337
|
+
.map((t) => t.id)
|
|
338
|
+
.join(", ")}${tests.length > 3 ? "..." : ""}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
console.log(``);
|
|
342
|
+
console.log(`Total tests to migrate: ${suites.reduce((sum, { suite }) => sum + suite.getTests().length, 0)}`);
|
|
343
|
+
console.log(``);
|
|
344
|
+
console.log(`To migrate, run: evalai migrate config --in ${filePath} --out eval/migrated.spec.ts`);
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
console.error(`❌ Preview failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* evalai print-config — Show resolved configuration with source-of-truth annotations.
|
|
3
|
+
*
|
|
4
|
+
* Prints every config field, where it came from (file, env, default, CLI arg),
|
|
5
|
+
* and redacts secrets. Useful for debugging "why is it using this baseUrl?"
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* evalai print-config
|
|
9
|
+
* evalai print-config --format json
|
|
10
|
+
*
|
|
11
|
+
* Exit codes:
|
|
12
|
+
* 0 — Always (informational only)
|
|
13
|
+
*/
|
|
14
|
+
type Source = "file" | "env" | "default" | "profile" | "arg";
|
|
15
|
+
interface ResolvedField {
|
|
16
|
+
key: string;
|
|
17
|
+
value: string | number | boolean | null;
|
|
18
|
+
source: Source;
|
|
19
|
+
raw?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface PrintConfigOutput {
|
|
22
|
+
cliVersion: string;
|
|
23
|
+
configFile: string | null;
|
|
24
|
+
cwd: string;
|
|
25
|
+
resolved: ResolvedField[];
|
|
26
|
+
env: Record<string, string | null>;
|
|
27
|
+
}
|
|
28
|
+
export declare function runPrintConfig(argv: string[]): number;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* evalai print-config — Show resolved configuration with source-of-truth annotations.
|
|
4
|
+
*
|
|
5
|
+
* Prints every config field, where it came from (file, env, default, CLI arg),
|
|
6
|
+
* and redacts secrets. Useful for debugging "why is it using this baseUrl?"
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* evalai print-config
|
|
10
|
+
* evalai print-config --format json
|
|
11
|
+
*
|
|
12
|
+
* Exit codes:
|
|
13
|
+
* 0 — Always (informational only)
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.runPrintConfig = runPrintConfig;
|
|
50
|
+
const path = __importStar(require("node:path"));
|
|
51
|
+
const version_1 = require("../version");
|
|
52
|
+
const config_1 = require("./config");
|
|
53
|
+
const profiles_1 = require("./profiles");
|
|
54
|
+
function parseFlags(argv) {
|
|
55
|
+
const raw = {};
|
|
56
|
+
for (let i = 0; i < argv.length; i++) {
|
|
57
|
+
const arg = argv[i];
|
|
58
|
+
if (arg.startsWith("--")) {
|
|
59
|
+
const key = arg.slice(2);
|
|
60
|
+
const next = argv[i + 1];
|
|
61
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
62
|
+
raw[key] = next;
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
raw[key] = "true";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
format: raw.format === "json" ? "json" : "human",
|
|
72
|
+
evaluationId: raw.evaluationId,
|
|
73
|
+
baseUrl: raw.baseUrl,
|
|
74
|
+
apiKey: raw.apiKey,
|
|
75
|
+
baseline: raw.baseline,
|
|
76
|
+
profile: raw.profile,
|
|
77
|
+
minScore: raw.minScore,
|
|
78
|
+
maxDrop: raw.maxDrop,
|
|
79
|
+
warnDrop: raw.warnDrop,
|
|
80
|
+
minN: raw.minN,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ── Helpers ──
|
|
84
|
+
function redact(value) {
|
|
85
|
+
if (!value)
|
|
86
|
+
return null;
|
|
87
|
+
if (value.length > 8)
|
|
88
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
89
|
+
return "****";
|
|
90
|
+
}
|
|
91
|
+
// ── Build resolved config ──
|
|
92
|
+
function buildResolvedConfig(cwd, flags) {
|
|
93
|
+
const configPath = (0, config_1.findConfigPath)(cwd);
|
|
94
|
+
const fileConfig = (0, config_1.loadConfig)(cwd);
|
|
95
|
+
// Build CLI args object (only what was explicitly passed)
|
|
96
|
+
const cliArgs = {};
|
|
97
|
+
if (flags.evaluationId)
|
|
98
|
+
cliArgs.evaluationId = flags.evaluationId;
|
|
99
|
+
if (flags.baseUrl)
|
|
100
|
+
cliArgs.baseUrl = flags.baseUrl;
|
|
101
|
+
if (flags.baseline)
|
|
102
|
+
cliArgs.baseline = flags.baseline;
|
|
103
|
+
if (flags.profile)
|
|
104
|
+
cliArgs.profile = flags.profile;
|
|
105
|
+
if (flags.minScore)
|
|
106
|
+
cliArgs.minScore = flags.minScore;
|
|
107
|
+
if (flags.maxDrop)
|
|
108
|
+
cliArgs.maxDrop = flags.maxDrop;
|
|
109
|
+
if (flags.warnDrop)
|
|
110
|
+
cliArgs.warnDrop = flags.warnDrop;
|
|
111
|
+
if (flags.minN)
|
|
112
|
+
cliArgs.minN = flags.minN;
|
|
113
|
+
const merged = (0, config_1.mergeConfigWithArgs)(fileConfig, cliArgs);
|
|
114
|
+
// Determine source of each field
|
|
115
|
+
const fields = [];
|
|
116
|
+
// evaluationId
|
|
117
|
+
const evalIdSource = flags.evaluationId
|
|
118
|
+
? "arg"
|
|
119
|
+
: fileConfig?.evaluationId
|
|
120
|
+
? "file"
|
|
121
|
+
: "default";
|
|
122
|
+
fields.push({
|
|
123
|
+
key: "evaluationId",
|
|
124
|
+
value: merged.evaluationId ?? null,
|
|
125
|
+
source: evalIdSource,
|
|
126
|
+
});
|
|
127
|
+
// baseUrl
|
|
128
|
+
const envBaseUrl = process.env.EVALAI_BASE_URL;
|
|
129
|
+
const baseUrlSource = flags.baseUrl
|
|
130
|
+
? "arg"
|
|
131
|
+
: envBaseUrl
|
|
132
|
+
? "env"
|
|
133
|
+
: fileConfig?.baseUrl
|
|
134
|
+
? "file"
|
|
135
|
+
: "default";
|
|
136
|
+
fields.push({
|
|
137
|
+
key: "baseUrl",
|
|
138
|
+
value: flags.baseUrl || envBaseUrl || fileConfig?.baseUrl || "http://localhost:3000",
|
|
139
|
+
source: baseUrlSource,
|
|
140
|
+
});
|
|
141
|
+
// apiKey (always redacted)
|
|
142
|
+
const envApiKey = process.env.EVALAI_API_KEY;
|
|
143
|
+
const rawApiKey = flags.apiKey || envApiKey || "";
|
|
144
|
+
const apiKeySource = flags.apiKey ? "arg" : envApiKey ? "env" : "default";
|
|
145
|
+
fields.push({
|
|
146
|
+
key: "apiKey",
|
|
147
|
+
value: redact(rawApiKey) ?? "(not set)",
|
|
148
|
+
source: apiKeySource,
|
|
149
|
+
raw: rawApiKey ? "(redacted)" : undefined,
|
|
150
|
+
});
|
|
151
|
+
// profile
|
|
152
|
+
const profileName = (flags.profile || fileConfig?.profile);
|
|
153
|
+
const profileSource = flags.profile ? "arg" : fileConfig?.profile ? "file" : "default";
|
|
154
|
+
fields.push({
|
|
155
|
+
key: "profile",
|
|
156
|
+
value: profileName ?? null,
|
|
157
|
+
source: profileSource,
|
|
158
|
+
});
|
|
159
|
+
// Numeric gate fields: minScore, maxDrop, warnDrop, minN, allowWeakEvidence
|
|
160
|
+
const numericFields = [
|
|
161
|
+
{ key: "minScore" },
|
|
162
|
+
{ key: "maxDrop" },
|
|
163
|
+
{ key: "warnDrop" },
|
|
164
|
+
{ key: "minN" },
|
|
165
|
+
{ key: "allowWeakEvidence" },
|
|
166
|
+
];
|
|
167
|
+
for (const { key } of numericFields) {
|
|
168
|
+
const argVal = cliArgs[key];
|
|
169
|
+
const fileVal = fileConfig?.[key];
|
|
170
|
+
const profileVal = profileName && profileName in profiles_1.PROFILES
|
|
171
|
+
? profiles_1.PROFILES[profileName][key]
|
|
172
|
+
: undefined;
|
|
173
|
+
const source = argVal !== undefined
|
|
174
|
+
? "arg"
|
|
175
|
+
: fileVal !== undefined
|
|
176
|
+
? "file"
|
|
177
|
+
: profileVal !== undefined
|
|
178
|
+
? "profile"
|
|
179
|
+
: "default";
|
|
180
|
+
fields.push({
|
|
181
|
+
key,
|
|
182
|
+
value: merged[key] ?? null,
|
|
183
|
+
source,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// baseline
|
|
187
|
+
const baselineSource = flags.baseline ? "arg" : fileConfig?.baseline ? "file" : "default";
|
|
188
|
+
fields.push({
|
|
189
|
+
key: "baseline",
|
|
190
|
+
value: merged.baseline ?? "published",
|
|
191
|
+
source: baselineSource,
|
|
192
|
+
});
|
|
193
|
+
// Environment variables summary
|
|
194
|
+
const envVars = {
|
|
195
|
+
EVALAI_API_KEY: redact(envApiKey),
|
|
196
|
+
EVALAI_BASE_URL: envBaseUrl ?? null,
|
|
197
|
+
OPENAI_API_KEY: redact(process.env.OPENAI_API_KEY),
|
|
198
|
+
ANTHROPIC_API_KEY: redact(process.env.ANTHROPIC_API_KEY),
|
|
199
|
+
AZURE_OPENAI_API_KEY: redact(process.env.AZURE_OPENAI_API_KEY),
|
|
200
|
+
GITHUB_ACTIONS: process.env.GITHUB_ACTIONS ?? null,
|
|
201
|
+
CI: process.env.CI ?? null,
|
|
202
|
+
};
|
|
203
|
+
return {
|
|
204
|
+
cliVersion: version_1.SDK_VERSION,
|
|
205
|
+
configFile: configPath ? path.relative(cwd, configPath) : null,
|
|
206
|
+
cwd,
|
|
207
|
+
resolved: fields,
|
|
208
|
+
env: envVars,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
// ── Output formatting ──
|
|
212
|
+
function printHuman(output) {
|
|
213
|
+
console.log("\n evalai print-config\n");
|
|
214
|
+
console.log(` CLI version: ${output.cliVersion}`);
|
|
215
|
+
console.log(` Config file: ${output.configFile ?? "(none found)"}`);
|
|
216
|
+
console.log(` Working dir: ${output.cwd}`);
|
|
217
|
+
console.log("");
|
|
218
|
+
console.log(" Resolved configuration:");
|
|
219
|
+
console.log("");
|
|
220
|
+
const maxKeyLen = Math.max(...output.resolved.map((f) => f.key.length));
|
|
221
|
+
for (const field of output.resolved) {
|
|
222
|
+
const val = field.value === null ? "(not set)" : String(field.value);
|
|
223
|
+
const pad = " ".repeat(maxKeyLen - field.key.length);
|
|
224
|
+
const sourceTag = `[${field.source}]`;
|
|
225
|
+
console.log(` ${field.key}${pad} ${val} ${sourceTag}`);
|
|
226
|
+
}
|
|
227
|
+
console.log("");
|
|
228
|
+
console.log(" Environment variables:");
|
|
229
|
+
console.log("");
|
|
230
|
+
for (const [key, val] of Object.entries(output.env)) {
|
|
231
|
+
if (val !== null) {
|
|
232
|
+
console.log(` ${key} = ${val}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const unsetEnv = Object.entries(output.env)
|
|
236
|
+
.filter(([, v]) => v === null)
|
|
237
|
+
.map(([k]) => k);
|
|
238
|
+
if (unsetEnv.length > 0) {
|
|
239
|
+
console.log(` (not set: ${unsetEnv.join(", ")})`);
|
|
240
|
+
}
|
|
241
|
+
console.log("");
|
|
242
|
+
}
|
|
243
|
+
// ── Main ──
|
|
244
|
+
function runPrintConfig(argv) {
|
|
245
|
+
const flags = parseFlags(argv);
|
|
246
|
+
const cwd = process.cwd();
|
|
247
|
+
const output = buildResolvedConfig(cwd, flags);
|
|
248
|
+
if (flags.format === "json") {
|
|
249
|
+
console.log(JSON.stringify(output, null, 2));
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
printHuman(output);
|
|
253
|
+
}
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { QualityLatestData, RunDetailsData } from "../api";
|
|
6
6
|
import type { CheckArgs } from "../check";
|
|
7
|
-
import type
|
|
7
|
+
import { type CheckReport } from "../formatters/types";
|
|
8
8
|
import type { GateResult } from "../gate";
|
|
9
9
|
export type BuildReportInput = {
|
|
10
10
|
args: CheckArgs;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.buildCheckReport = buildCheckReport;
|
|
8
|
+
const types_1 = require("../formatters/types");
|
|
8
9
|
const snippet_1 = require("../render/snippet");
|
|
9
10
|
const sort_1 = require("../render/sort");
|
|
10
11
|
const TOP_N = 3;
|
|
@@ -69,6 +70,7 @@ function buildCheckReport(input) {
|
|
|
69
70
|
: (gateResult.reasonMessage ?? undefined);
|
|
70
71
|
const verdict = gateResult.reasonCode === "WARN_REGRESSION" ? "warn" : gateResult.passed ? "pass" : "fail";
|
|
71
72
|
const report = {
|
|
73
|
+
schemaVersion: types_1.CHECK_REPORT_SCHEMA_VERSION,
|
|
72
74
|
evaluationId: args.evaluationId,
|
|
73
75
|
runId: evaluationRunId,
|
|
74
76
|
verdict,
|