@evalgate/sdk 2.0.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 +638 -0
- package/README.md +398 -0
- package/dist/assertions.d.ts +189 -0
- package/dist/assertions.js +662 -0
- package/dist/batch.d.ts +68 -0
- package/dist/batch.js +179 -0
- package/dist/cache.d.ts +65 -0
- package/dist/cache.js +131 -0
- package/dist/cli/api.d.ts +108 -0
- package/dist/cli/api.js +132 -0
- package/dist/cli/baseline.d.ts +10 -0
- package/dist/cli/baseline.js +172 -0
- package/dist/cli/check.d.ts +73 -0
- package/dist/cli/check.js +355 -0
- package/dist/cli/ci-context.d.ts +6 -0
- package/dist/cli/ci-context.js +112 -0
- package/dist/cli/ci.d.ts +45 -0
- package/dist/cli/ci.js +192 -0
- package/dist/cli/config.d.ts +30 -0
- package/dist/cli/config.js +230 -0
- package/dist/cli/constants.d.ts +15 -0
- package/dist/cli/constants.js +18 -0
- package/dist/cli/diff.d.ts +173 -0
- package/dist/cli/diff.js +685 -0
- package/dist/cli/discover.d.ts +84 -0
- package/dist/cli/discover.js +419 -0
- package/dist/cli/doctor.d.ts +88 -0
- package/dist/cli/doctor.js +675 -0
- 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 +561 -0
- package/dist/cli/formatters/github.d.ts +8 -0
- package/dist/cli/formatters/github.js +135 -0
- package/dist/cli/formatters/human.d.ts +6 -0
- package/dist/cli/formatters/human.js +110 -0
- package/dist/cli/formatters/json.d.ts +6 -0
- package/dist/cli/formatters/json.js +10 -0
- package/dist/cli/formatters/pr-comment.d.ts +12 -0
- package/dist/cli/formatters/pr-comment.js +103 -0
- package/dist/cli/formatters/types.d.ts +103 -0
- package/dist/cli/formatters/types.js +8 -0
- package/dist/cli/gate.d.ts +21 -0
- package/dist/cli/gate.js +179 -0
- package/dist/cli/impact-analysis.d.ts +63 -0
- package/dist/cli/impact-analysis.js +252 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +332 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +292 -0
- package/dist/cli/manifest.d.ts +103 -0
- package/dist/cli/manifest.js +282 -0
- package/dist/cli/migrate.d.ts +41 -0
- package/dist/cli/migrate.js +349 -0
- package/dist/cli/policy-packs.d.ts +23 -0
- package/dist/cli/policy-packs.js +89 -0
- package/dist/cli/print-config.d.ts +29 -0
- package/dist/cli/print-config.js +270 -0
- package/dist/cli/profiles.d.ts +28 -0
- package/dist/cli/profiles.js +30 -0
- package/dist/cli/reason-codes.d.ts +17 -0
- package/dist/cli/reason-codes.js +19 -0
- package/dist/cli/regression-gate.d.ts +15 -0
- package/dist/cli/regression-gate.js +341 -0
- package/dist/cli/render/snippet.d.ts +5 -0
- package/dist/cli/render/snippet.js +15 -0
- package/dist/cli/render/sort.d.ts +10 -0
- package/dist/cli/render/sort.js +24 -0
- package/dist/cli/report/build-check-report.d.ts +19 -0
- package/dist/cli/report/build-check-report.js +132 -0
- package/dist/cli/run.d.ts +101 -0
- package/dist/cli/run.js +395 -0
- package/dist/cli/share.d.ts +17 -0
- package/dist/cli/share.js +91 -0
- package/dist/cli/upgrade.d.ts +15 -0
- package/dist/cli/upgrade.js +492 -0
- package/dist/cli/workspace.d.ts +31 -0
- package/dist/cli/workspace.js +68 -0
- package/dist/client.d.ts +368 -0
- package/dist/client.js +893 -0
- package/dist/client.request.test.d.ts +1 -0
- package/dist/client.request.test.js +232 -0
- package/dist/context.d.ts +134 -0
- package/dist/context.js +215 -0
- package/dist/errors.d.ts +82 -0
- package/dist/errors.js +298 -0
- package/dist/export.d.ts +195 -0
- package/dist/export.js +344 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +153 -0
- package/dist/integrations/anthropic.d.ts +91 -0
- package/dist/integrations/anthropic.js +163 -0
- package/dist/integrations/openai-eval.d.ts +57 -0
- package/dist/integrations/openai-eval.js +232 -0
- package/dist/integrations/openai.d.ts +92 -0
- package/dist/integrations/openai.js +160 -0
- package/dist/local.d.ts +39 -0
- package/dist/local.js +148 -0
- package/dist/logger.d.ts +128 -0
- package/dist/logger.js +227 -0
- package/dist/matchers/index.d.ts +1 -0
- package/dist/matchers/index.js +6 -0
- package/dist/matchers/to-pass-gate.d.ts +29 -0
- package/dist/matchers/to-pass-gate.js +35 -0
- package/dist/pagination.d.ts +74 -0
- package/dist/pagination.js +139 -0
- package/dist/regression.d.ts +100 -0
- package/dist/regression.js +44 -0
- package/dist/runtime/adapters/config-to-dsl.d.ts +33 -0
- package/dist/runtime/adapters/config-to-dsl.js +400 -0
- package/dist/runtime/adapters/testsuite-to-dsl.d.ts +63 -0
- package/dist/runtime/adapters/testsuite-to-dsl.js +276 -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 +244 -0
- package/dist/runtime/execution-mode.d.ts +80 -0
- package/dist/runtime/execution-mode.js +357 -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 +403 -0
- package/dist/runtime/run-report.d.ts +200 -0
- package/dist/runtime/run-report.js +222 -0
- package/dist/runtime/types.d.ts +356 -0
- package/dist/runtime/types.js +76 -0
- package/dist/snapshot.d.ts +176 -0
- package/dist/snapshot.js +322 -0
- package/dist/streaming.d.ts +173 -0
- package/dist/streaming.js +268 -0
- package/dist/testing.d.ts +273 -0
- package/dist/testing.js +317 -0
- package/dist/types.d.ts +754 -0
- package/dist/types.js +54 -0
- package/dist/utils/input-hash.d.ts +8 -0
- package/dist/utils/input-hash.js +41 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +10 -0
- package/dist/workflows.d.ts +389 -0
- package/dist/workflows.js +671 -0
- package/package.json +117 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT-204: Dual-path execution toggle
|
|
3
|
+
*
|
|
4
|
+
* Environment flag EVALGATE_RUNTIME=legacy|spec|auto
|
|
5
|
+
* Auto uses spec runtime if manifest/specs exist, else legacy
|
|
6
|
+
* Existing projects continue unchanged; new projects can use DSL only
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Execution mode types
|
|
10
|
+
*/
|
|
11
|
+
export type ExecutionMode = "legacy" | "spec" | "auto";
|
|
12
|
+
/**
|
|
13
|
+
* Execution mode configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface ExecutionModeConfig {
|
|
16
|
+
/** Current execution mode */
|
|
17
|
+
mode: ExecutionMode;
|
|
18
|
+
/** Whether spec runtime is available */
|
|
19
|
+
hasSpecRuntime: boolean;
|
|
20
|
+
/** Whether legacy runtime is available */
|
|
21
|
+
hasLegacyRuntime: boolean;
|
|
22
|
+
/** Project root path */
|
|
23
|
+
projectRoot: string;
|
|
24
|
+
/** Detected spec files */
|
|
25
|
+
specFiles: string[];
|
|
26
|
+
/** Detected legacy config */
|
|
27
|
+
legacyConfig?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get execution mode from environment or auto-detection
|
|
31
|
+
*/
|
|
32
|
+
export declare function getExecutionMode(projectRoot?: string): Promise<ExecutionModeConfig>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if project can run in spec mode
|
|
35
|
+
*/
|
|
36
|
+
export declare function canRunSpecMode(config: ExecutionModeConfig): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Check if project can run in legacy mode
|
|
39
|
+
*/
|
|
40
|
+
export declare function canRunLegacyMode(config: ExecutionModeConfig): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get recommended execution mode for project
|
|
43
|
+
*/
|
|
44
|
+
export declare function getRecommendedExecutionMode(config: ExecutionModeConfig): ExecutionMode;
|
|
45
|
+
/**
|
|
46
|
+
* Validate execution mode compatibility
|
|
47
|
+
*/
|
|
48
|
+
export declare function validateExecutionMode(config: ExecutionModeConfig): {
|
|
49
|
+
valid: boolean;
|
|
50
|
+
warnings: string[];
|
|
51
|
+
errors: string[];
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Print execution mode information
|
|
55
|
+
*/
|
|
56
|
+
export declare function printExecutionModeInfo(config: ExecutionModeConfig): void;
|
|
57
|
+
/**
|
|
58
|
+
* Environment variable helpers
|
|
59
|
+
*/
|
|
60
|
+
export declare const ENV_VARS: {
|
|
61
|
+
readonly EXECUTION_MODE: "EVALGATE_RUNTIME";
|
|
62
|
+
readonly POSSIBLE_VALUES: readonly ["legacy", "spec", "auto"];
|
|
63
|
+
readonly DEFAULT: "auto";
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Check if environment variable is set
|
|
67
|
+
*/
|
|
68
|
+
export declare function hasExecutionModeEnv(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get current environment variable value
|
|
71
|
+
*/
|
|
72
|
+
export declare function getExecutionModeEnv(): string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Set execution mode environment variable
|
|
75
|
+
*/
|
|
76
|
+
export declare function setExecutionModeEnv(mode: ExecutionMode): void;
|
|
77
|
+
/**
|
|
78
|
+
* Clear execution mode environment variable
|
|
79
|
+
*/
|
|
80
|
+
export declare function clearExecutionModeEnv(): void;
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* COMPAT-204: Dual-path execution toggle
|
|
4
|
+
*
|
|
5
|
+
* Environment flag EVALGATE_RUNTIME=legacy|spec|auto
|
|
6
|
+
* Auto uses spec runtime if manifest/specs exist, else legacy
|
|
7
|
+
* Existing projects continue unchanged; new projects can use DSL only
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.ENV_VARS = void 0;
|
|
44
|
+
exports.getExecutionMode = getExecutionMode;
|
|
45
|
+
exports.canRunSpecMode = canRunSpecMode;
|
|
46
|
+
exports.canRunLegacyMode = canRunLegacyMode;
|
|
47
|
+
exports.getRecommendedExecutionMode = getRecommendedExecutionMode;
|
|
48
|
+
exports.validateExecutionMode = validateExecutionMode;
|
|
49
|
+
exports.printExecutionModeInfo = printExecutionModeInfo;
|
|
50
|
+
exports.hasExecutionModeEnv = hasExecutionModeEnv;
|
|
51
|
+
exports.getExecutionModeEnv = getExecutionModeEnv;
|
|
52
|
+
exports.setExecutionModeEnv = setExecutionModeEnv;
|
|
53
|
+
exports.clearExecutionModeEnv = clearExecutionModeEnv;
|
|
54
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
55
|
+
const path = __importStar(require("node:path"));
|
|
56
|
+
/**
|
|
57
|
+
* Get execution mode from environment or auto-detection
|
|
58
|
+
*/
|
|
59
|
+
async function getExecutionMode(projectRoot = process.cwd()) {
|
|
60
|
+
// Check environment variable first
|
|
61
|
+
const envMode = process.env.EVALGATE_RUNTIME?.toLowerCase();
|
|
62
|
+
if (envMode === "legacy" || envMode === "spec" || envMode === "auto") {
|
|
63
|
+
return {
|
|
64
|
+
mode: envMode,
|
|
65
|
+
hasSpecRuntime: envMode !== "legacy",
|
|
66
|
+
hasLegacyRuntime: envMode !== "spec",
|
|
67
|
+
projectRoot,
|
|
68
|
+
specFiles: envMode !== "legacy" ? await findSpecFiles(projectRoot) : [],
|
|
69
|
+
legacyConfig: envMode !== "spec" ? await findLegacyConfig(projectRoot) : undefined,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Auto-detect mode
|
|
73
|
+
return await autoDetectExecutionMode(projectRoot);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Auto-detect execution mode based on project structure
|
|
77
|
+
*/
|
|
78
|
+
async function autoDetectExecutionMode(projectRoot) {
|
|
79
|
+
const specFiles = await findSpecFiles(projectRoot);
|
|
80
|
+
const legacyConfig = await findLegacyConfig(projectRoot);
|
|
81
|
+
const hasSpecRuntime = specFiles.length > 0;
|
|
82
|
+
const hasLegacyRuntime = !!legacyConfig;
|
|
83
|
+
let mode = "auto";
|
|
84
|
+
// If both are available, prefer spec runtime for new projects
|
|
85
|
+
if (hasSpecRuntime && hasLegacyRuntime) {
|
|
86
|
+
mode = "spec"; // Prefer spec for mixed projects
|
|
87
|
+
}
|
|
88
|
+
else if (hasSpecRuntime) {
|
|
89
|
+
mode = "spec";
|
|
90
|
+
}
|
|
91
|
+
else if (hasLegacyRuntime) {
|
|
92
|
+
mode = "legacy";
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
mode = "auto"; // Default to auto for empty projects
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
mode,
|
|
99
|
+
hasSpecRuntime,
|
|
100
|
+
hasLegacyRuntime,
|
|
101
|
+
projectRoot,
|
|
102
|
+
specFiles,
|
|
103
|
+
legacyConfig,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Find spec files in project
|
|
108
|
+
*/
|
|
109
|
+
async function findSpecFiles(projectRoot) {
|
|
110
|
+
const specPatterns = [
|
|
111
|
+
"eval/**/*.spec.ts",
|
|
112
|
+
"eval/**/*.spec.js",
|
|
113
|
+
"src/**/*.spec.ts",
|
|
114
|
+
"src/**/*.spec.js",
|
|
115
|
+
"tests/**/*.spec.ts",
|
|
116
|
+
"tests/**/*.spec.js",
|
|
117
|
+
"spec/**/*.ts",
|
|
118
|
+
"spec/**/*.js",
|
|
119
|
+
];
|
|
120
|
+
const foundFiles = [];
|
|
121
|
+
for (const pattern of specPatterns) {
|
|
122
|
+
try {
|
|
123
|
+
const files = await searchFiles(projectRoot, pattern, projectRoot);
|
|
124
|
+
foundFiles.push(...files);
|
|
125
|
+
}
|
|
126
|
+
catch (_error) {
|
|
127
|
+
// Ignore errors for non-existent paths
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Filter for files that contain defineEval calls
|
|
131
|
+
const specFilesWithDefineEval = [];
|
|
132
|
+
for (const file of foundFiles) {
|
|
133
|
+
try {
|
|
134
|
+
const content = await fs.readFile(file, "utf-8");
|
|
135
|
+
if (content.includes("defineEval")) {
|
|
136
|
+
specFilesWithDefineEval.push(file);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (_error) {
|
|
140
|
+
// Ignore read errors
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return specFilesWithDefineEval;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Simple file search (placeholder for proper glob implementation)
|
|
147
|
+
*/
|
|
148
|
+
async function searchFiles(dir, pattern, projectRoot) {
|
|
149
|
+
const results = [];
|
|
150
|
+
try {
|
|
151
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
152
|
+
for (let i = 0; i < entries.length; i++) {
|
|
153
|
+
const entry = entries[i];
|
|
154
|
+
const fullPath = path.join(dir, entry.name);
|
|
155
|
+
if (entry.isDirectory() && !entry.name.startsWith(".")) {
|
|
156
|
+
results.push(...(await searchFiles(fullPath, pattern, projectRoot)));
|
|
157
|
+
}
|
|
158
|
+
else if (entry.isFile()) {
|
|
159
|
+
// Simple pattern matching
|
|
160
|
+
if (matchesPattern(fullPath, pattern, projectRoot)) {
|
|
161
|
+
results.push(fullPath);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (_error) {
|
|
167
|
+
// Ignore permission errors
|
|
168
|
+
}
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Simple pattern matching (placeholder for proper glob)
|
|
173
|
+
*/
|
|
174
|
+
function matchesPattern(filePath, pattern, projectRoot) {
|
|
175
|
+
const _fileName = path.basename(filePath);
|
|
176
|
+
const _ext = path.extname(filePath);
|
|
177
|
+
const _dir = path.dirname(filePath);
|
|
178
|
+
// Convert glob pattern to regex
|
|
179
|
+
// Handle **/ and * patterns correctly
|
|
180
|
+
let regexPattern = pattern;
|
|
181
|
+
// Replace **/ with (?:.*/)? to match optional directory path
|
|
182
|
+
regexPattern = regexPattern.replace(/\*\*\//g, "(?:.*/)?");
|
|
183
|
+
// Replace remaining * with [^/]* (filename pattern)
|
|
184
|
+
regexPattern = regexPattern.replace(/\*/g, "[^/]*");
|
|
185
|
+
const relativePath = path.relative(projectRoot, filePath).replace(/\\/g, "/");
|
|
186
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
187
|
+
return regex.test(relativePath);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Find legacy config file
|
|
191
|
+
*/
|
|
192
|
+
async function findLegacyConfig(projectRoot) {
|
|
193
|
+
const configPaths = [
|
|
194
|
+
"evalai.config.json",
|
|
195
|
+
"evalai.config.js",
|
|
196
|
+
"evalai.config.ts",
|
|
197
|
+
".evalgaterc",
|
|
198
|
+
".evalgaterc.json",
|
|
199
|
+
];
|
|
200
|
+
for (const configPath of configPaths) {
|
|
201
|
+
const fullPath = path.join(projectRoot, configPath);
|
|
202
|
+
try {
|
|
203
|
+
await fs.access(fullPath);
|
|
204
|
+
return fullPath;
|
|
205
|
+
}
|
|
206
|
+
catch (_error) {
|
|
207
|
+
// File doesn't exist, continue
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if project can run in spec mode
|
|
214
|
+
*/
|
|
215
|
+
function canRunSpecMode(config) {
|
|
216
|
+
return config.hasSpecRuntime && config.specFiles.length > 0;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Check if project can run in legacy mode
|
|
220
|
+
*/
|
|
221
|
+
function canRunLegacyMode(config) {
|
|
222
|
+
return config.hasLegacyRuntime && !!config.legacyConfig;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Get recommended execution mode for project
|
|
226
|
+
*/
|
|
227
|
+
function getRecommendedExecutionMode(config) {
|
|
228
|
+
if (config.mode !== "auto") {
|
|
229
|
+
return config.mode;
|
|
230
|
+
}
|
|
231
|
+
if (canRunSpecMode(config) && canRunLegacyMode(config)) {
|
|
232
|
+
return "spec"; // Prefer spec for mixed projects
|
|
233
|
+
}
|
|
234
|
+
if (canRunSpecMode(config)) {
|
|
235
|
+
return "spec";
|
|
236
|
+
}
|
|
237
|
+
if (canRunLegacyMode(config)) {
|
|
238
|
+
return "legacy";
|
|
239
|
+
}
|
|
240
|
+
return "auto";
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Validate execution mode compatibility
|
|
244
|
+
*/
|
|
245
|
+
function validateExecutionMode(config) {
|
|
246
|
+
const warnings = [];
|
|
247
|
+
const errors = [];
|
|
248
|
+
// Check for mixed project
|
|
249
|
+
if (config.hasSpecRuntime && config.hasLegacyRuntime) {
|
|
250
|
+
warnings.push("Project contains both spec files and legacy config. " +
|
|
251
|
+
"Consider migrating legacy tests to spec format for consistency.");
|
|
252
|
+
}
|
|
253
|
+
// Check for no runtime
|
|
254
|
+
if (!config.hasSpecRuntime && !config.hasLegacyRuntime) {
|
|
255
|
+
warnings.push("No tests found. This appears to be an empty project. " +
|
|
256
|
+
"Use 'evalgate init' to create a new project.");
|
|
257
|
+
}
|
|
258
|
+
// Check for spec mode without spec files
|
|
259
|
+
if (config.mode === "spec" && !canRunSpecMode(config)) {
|
|
260
|
+
errors.push("Spec mode requested but no spec files found. " +
|
|
261
|
+
"Create spec files with defineEval() or use legacy mode.");
|
|
262
|
+
}
|
|
263
|
+
// Check for legacy mode without config
|
|
264
|
+
if (config.mode === "legacy" && !canRunLegacyMode(config)) {
|
|
265
|
+
errors.push("Legacy mode requested but no evalgate.config.json (or evalai.config.json) found. " +
|
|
266
|
+
"Create a config file or use spec mode.");
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
valid: errors.length === 0,
|
|
270
|
+
warnings,
|
|
271
|
+
errors,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Print execution mode information
|
|
276
|
+
*/
|
|
277
|
+
function printExecutionModeInfo(config) {
|
|
278
|
+
console.log(`🔧 EvalGate Execution Mode: ${config.mode.toUpperCase()}`);
|
|
279
|
+
console.log(`📁 Project root: ${config.projectRoot}`);
|
|
280
|
+
console.log(``);
|
|
281
|
+
if (config.hasSpecRuntime) {
|
|
282
|
+
console.log(`✅ Spec runtime available`);
|
|
283
|
+
console.log(` Found ${config.specFiles.length} spec file(s):`);
|
|
284
|
+
config.specFiles.slice(0, 5).forEach((file) => {
|
|
285
|
+
console.log(` - ${path.relative(config.projectRoot, file)}`);
|
|
286
|
+
});
|
|
287
|
+
if (config.specFiles.length > 5) {
|
|
288
|
+
console.log(` ... and ${config.specFiles.length - 5} more`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
console.log(`❌ No spec runtime found`);
|
|
293
|
+
}
|
|
294
|
+
console.log(``);
|
|
295
|
+
if (config.hasLegacyRuntime) {
|
|
296
|
+
console.log(`✅ Legacy runtime available`);
|
|
297
|
+
if (config.legacyConfig) {
|
|
298
|
+
console.log(` Config: ${path.relative(config.projectRoot, config.legacyConfig)}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
console.log(`❌ No legacy runtime found`);
|
|
303
|
+
}
|
|
304
|
+
console.log(``);
|
|
305
|
+
const validation = validateExecutionMode(config);
|
|
306
|
+
if (validation.warnings.length > 0) {
|
|
307
|
+
console.log(`⚠️ Warnings:`);
|
|
308
|
+
validation.warnings.forEach((warning) => {
|
|
309
|
+
console.log(` ${warning}`);
|
|
310
|
+
});
|
|
311
|
+
console.log(``);
|
|
312
|
+
}
|
|
313
|
+
if (validation.errors.length > 0) {
|
|
314
|
+
console.log(`❌ Errors:`);
|
|
315
|
+
validation.errors.forEach((error) => {
|
|
316
|
+
console.log(` ${error}`);
|
|
317
|
+
});
|
|
318
|
+
console.log(``);
|
|
319
|
+
}
|
|
320
|
+
const recommended = getRecommendedExecutionMode(config);
|
|
321
|
+
console.log(`💡 Recommended mode: ${recommended.toUpperCase()}`);
|
|
322
|
+
if (config.mode === "auto") {
|
|
323
|
+
console.log(`🔄 Auto mode will use: ${recommended.toUpperCase()}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Environment variable helpers
|
|
328
|
+
*/
|
|
329
|
+
exports.ENV_VARS = {
|
|
330
|
+
EXECUTION_MODE: "EVALGATE_RUNTIME",
|
|
331
|
+
POSSIBLE_VALUES: ["legacy", "spec", "auto"],
|
|
332
|
+
DEFAULT: "auto",
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Check if environment variable is set
|
|
336
|
+
*/
|
|
337
|
+
function hasExecutionModeEnv() {
|
|
338
|
+
return !!process.env.EVALGATE_RUNTIME;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get current environment variable value
|
|
342
|
+
*/
|
|
343
|
+
function getExecutionModeEnv() {
|
|
344
|
+
return process.env.EVALGATE_RUNTIME;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Set execution mode environment variable
|
|
348
|
+
*/
|
|
349
|
+
function setExecutionModeEnv(mode) {
|
|
350
|
+
process.env.EVALGATE_RUNTIME = mode;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Clear execution mode environment variable
|
|
354
|
+
*/
|
|
355
|
+
function clearExecutionModeEnv() {
|
|
356
|
+
delete process.env.EVALGATE_RUNTIME;
|
|
357
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EvalGate Local Executor - Layer 1 Foundation
|
|
3
|
+
*
|
|
4
|
+
* Local execution engine that runs specifications without database coupling.
|
|
5
|
+
* Implements the execution interface for the new programming model.
|
|
6
|
+
*/
|
|
7
|
+
import type { LocalExecutor } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* Create a new local executor
|
|
10
|
+
*/
|
|
11
|
+
export declare function createLocalExecutor(): LocalExecutor;
|
|
12
|
+
/**
|
|
13
|
+
* Default local executor instance
|
|
14
|
+
* For convenience in simple use cases
|
|
15
|
+
*/
|
|
16
|
+
export declare const defaultLocalExecutor: LocalExecutor;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* EvalGate Local Executor - Layer 1 Foundation
|
|
4
|
+
*
|
|
5
|
+
* Local execution engine that runs specifications without database coupling.
|
|
6
|
+
* Implements the execution interface for the new programming model.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.defaultLocalExecutor = void 0;
|
|
10
|
+
exports.createLocalExecutor = createLocalExecutor;
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
/**
|
|
13
|
+
* Local executor implementation
|
|
14
|
+
* Runs specifications in the current process without external dependencies
|
|
15
|
+
*/
|
|
16
|
+
class LocalExecutorImpl {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.type = "local";
|
|
19
|
+
this.capabilities = {
|
|
20
|
+
type: "local",
|
|
21
|
+
parallel: true,
|
|
22
|
+
maxParallel: 4, // Conservative default
|
|
23
|
+
supportedModels: ["*"], // Supports any model via executor function
|
|
24
|
+
costTracking: false, // No built-in cost tracking for local execution
|
|
25
|
+
streaming: false, // No streaming for local execution
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Execute a single specification with safe error boundaries
|
|
30
|
+
*/
|
|
31
|
+
async executeSpec(spec, input) {
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
let classification = "passed";
|
|
34
|
+
try {
|
|
35
|
+
// Create execution context
|
|
36
|
+
const context = {
|
|
37
|
+
input,
|
|
38
|
+
metadata: spec.metadata,
|
|
39
|
+
options: {
|
|
40
|
+
model: spec.config?.model,
|
|
41
|
+
budget: spec.config?.budget,
|
|
42
|
+
timeout: spec.config?.timeout,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
// Execute specification with timeout
|
|
46
|
+
const timeout = spec.config?.timeout || 30000; // 30 second default
|
|
47
|
+
const result = await this.executeWithTimeout(spec.executor, context, timeout);
|
|
48
|
+
// Add execution duration
|
|
49
|
+
result.durationMs = Date.now() - startTime;
|
|
50
|
+
// Determine classification
|
|
51
|
+
classification = result.pass ? "passed" : "failed";
|
|
52
|
+
return {
|
|
53
|
+
...result,
|
|
54
|
+
classification,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const duration = Date.now() - startTime;
|
|
59
|
+
let errorEnvelope;
|
|
60
|
+
if (error instanceof Error && error.name === "TimeoutError") {
|
|
61
|
+
classification = "timeout";
|
|
62
|
+
errorEnvelope = {
|
|
63
|
+
classification: "timeout_error",
|
|
64
|
+
code: "TIMEOUT",
|
|
65
|
+
message: `Specification execution timed out after ${duration}ms`,
|
|
66
|
+
stack: error.stack,
|
|
67
|
+
testId: spec.id,
|
|
68
|
+
filePath: spec.filePath,
|
|
69
|
+
position: spec.position,
|
|
70
|
+
timestamp: new Date().toISOString(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
classification = "error";
|
|
75
|
+
// Create EvalExecutionError wrapper
|
|
76
|
+
const execError = new types_1.EvalExecutionError(error instanceof Error ? error.message : String(error), {
|
|
77
|
+
testId: spec.id,
|
|
78
|
+
filePath: spec.filePath,
|
|
79
|
+
position: spec.position,
|
|
80
|
+
code: "EXECUTION_ERROR",
|
|
81
|
+
originalError: error instanceof Error ? error : undefined,
|
|
82
|
+
});
|
|
83
|
+
errorEnvelope = execError.toEnvelope();
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
pass: false,
|
|
87
|
+
score: 0,
|
|
88
|
+
error: error instanceof Error ? error.message : String(error),
|
|
89
|
+
durationMs: duration,
|
|
90
|
+
classification,
|
|
91
|
+
errorEnvelope,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Execute multiple specifications
|
|
97
|
+
*/
|
|
98
|
+
async executeSpecs(specs, inputs) {
|
|
99
|
+
if (specs.length !== inputs.length) {
|
|
100
|
+
throw new types_1.SpecExecutionError("Number of specs must match number of inputs", {
|
|
101
|
+
specCount: specs.length,
|
|
102
|
+
inputCount: inputs.length,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// For now, execute sequentially
|
|
106
|
+
// In Layer 3, we'll add parallel execution with worker pools
|
|
107
|
+
const results = [];
|
|
108
|
+
for (let i = 0; i < specs.length; i++) {
|
|
109
|
+
const result = await this.executeSpec(specs[i], inputs[i]);
|
|
110
|
+
results.push(result);
|
|
111
|
+
}
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get executor capabilities
|
|
116
|
+
*/
|
|
117
|
+
getCapabilities() {
|
|
118
|
+
return this.capabilities;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute with timeout protection
|
|
122
|
+
*/
|
|
123
|
+
async executeWithTimeout(fn, context, timeoutMs) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const timer = setTimeout(() => {
|
|
126
|
+
const error = new Error(`Execution timed out after ${timeoutMs}ms`);
|
|
127
|
+
error.name = "TimeoutError";
|
|
128
|
+
reject(error);
|
|
129
|
+
}, timeoutMs);
|
|
130
|
+
fn(context)
|
|
131
|
+
.then((result) => {
|
|
132
|
+
clearTimeout(timer);
|
|
133
|
+
resolve(result);
|
|
134
|
+
})
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
reject(error);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a new local executor
|
|
144
|
+
*/
|
|
145
|
+
function createLocalExecutor() {
|
|
146
|
+
return new LocalExecutorImpl();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Default local executor instance
|
|
150
|
+
* For convenience in simple use cases
|
|
151
|
+
*/
|
|
152
|
+
exports.defaultLocalExecutor = createLocalExecutor();
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EvalGate Runtime Registry - Layer 1 Foundation
|
|
3
|
+
*
|
|
4
|
+
* Scoped registry with proper lifecycle management.
|
|
5
|
+
* Prevents cross-run contamination and memory leaks.
|
|
6
|
+
*/
|
|
7
|
+
import type { EvalRuntime } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* Runtime interface with lifecycle management
|
|
10
|
+
* Ensures proper cleanup and prevents resource leaks
|
|
11
|
+
*/
|
|
12
|
+
export interface RuntimeHandle {
|
|
13
|
+
/** Runtime instance */
|
|
14
|
+
runtime: EvalRuntime;
|
|
15
|
+
/** defineEval function bound to this runtime */
|
|
16
|
+
defineEval: typeof import("./eval").defineEval;
|
|
17
|
+
/** Dispose runtime and clean up resources */
|
|
18
|
+
dispose(): void;
|
|
19
|
+
/** Create runtime snapshot for persistence */
|
|
20
|
+
snapshot(): RuntimeSnapshot;
|
|
21
|
+
/** Load runtime from snapshot */
|
|
22
|
+
load(snapshot: RuntimeSnapshot): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Runtime snapshot for persistence and recovery
|
|
26
|
+
*/
|
|
27
|
+
export interface RuntimeSnapshot {
|
|
28
|
+
/** Runtime metadata */
|
|
29
|
+
runtimeId: string;
|
|
30
|
+
namespace: string;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
/** Serialized specifications */
|
|
33
|
+
specs: SerializedSpec[];
|
|
34
|
+
/** Snapshot version for compatibility */
|
|
35
|
+
version: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Serialized specification for snapshot
|
|
39
|
+
*/
|
|
40
|
+
export interface SerializedSpec {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
filePath: string;
|
|
44
|
+
position: {
|
|
45
|
+
line: number;
|
|
46
|
+
column: number;
|
|
47
|
+
};
|
|
48
|
+
description?: string;
|
|
49
|
+
tags?: string[];
|
|
50
|
+
metadata?: Record<string, unknown>;
|
|
51
|
+
config?: {
|
|
52
|
+
timeout?: number;
|
|
53
|
+
retries?: number;
|
|
54
|
+
budget?: string;
|
|
55
|
+
model?: string | "auto";
|
|
56
|
+
};
|
|
57
|
+
/** Serialized executor function (placeholder) */
|
|
58
|
+
executorSerialized: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a new scoped runtime with lifecycle management
|
|
62
|
+
* Returns a handle for proper resource management
|
|
63
|
+
*/
|
|
64
|
+
export declare function createEvalRuntime(projectRoot?: string): RuntimeHandle;
|
|
65
|
+
/**
|
|
66
|
+
* Helper function for safe runtime execution with automatic cleanup
|
|
67
|
+
* Ensures runtime is disposed even if an exception is thrown
|
|
68
|
+
*/
|
|
69
|
+
export declare function withRuntime<T>(projectRoot: string, fn: (handle: RuntimeHandle) => Promise<T>): Promise<T>;
|
|
70
|
+
export declare function getActiveRuntime(): EvalRuntime;
|
|
71
|
+
/**
|
|
72
|
+
* Set the active runtime (for backward compatibility)
|
|
73
|
+
*/
|
|
74
|
+
export declare function setActiveRuntime(runtime: EvalRuntime): void;
|
|
75
|
+
/**
|
|
76
|
+
* Dispose the active runtime (for backward compatibility)
|
|
77
|
+
*/
|
|
78
|
+
export declare function disposeActiveRuntime(): void;
|