evaliphy 1.0.1-beta.2 → 1.0.1-beta.4

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/dist/bin.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- import fs, { existsSync, readFileSync } from "node:fs";
3
+ import fs, { existsSync } from "node:fs";
4
4
  import path, { join } from "node:path";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { pino } from "pino";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { program } from "commander";
9
- import fs$1 from "fs";
10
9
  import path$1 from "path";
11
- import { execSync } from "child_process";
10
+ import { fileURLToPath as fileURLToPath$1 } from "url";
12
11
  import fg from "fast-glob";
12
+ import fs$1 from "fs";
13
13
  import fs$2 from "node:fs/promises";
14
14
  //#region \0rolldown/runtime.js
15
15
  var __create = Object.create;
@@ -3744,7 +3744,14 @@ var ConfigLoader = class ConfigLoader {
3744
3744
  const configPath = this.findConfigFile(cwd);
3745
3745
  if (!configPath) {
3746
3746
  this.configLogger.debug("No config file found, using defaults if applicable");
3747
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, "Provided config file is not correct or does not exist.");
3747
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Could not load configuration. Please check the following:
3748
+
3749
+ - Does "evaliphy.config.ts" exist in your project root?
3750
+ - Is the path correct if you specified a custom config location?
3751
+ - Does the config file export a default defineConfig({}) call?
3752
+
3753
+ Expected location: ${process.cwd()}/evaliphy.config.ts
3754
+ Visit https://evaliphy.com/docs/configuration for more details.`);
3748
3755
  }
3749
3756
  if (!this.cachedConfig) {
3750
3757
  this.configLogger.debug({ configPath }, "Loading base configuration from file");
@@ -3757,7 +3764,10 @@ var ConfigLoader = class ConfigLoader {
3757
3764
  error: parsed.error,
3758
3765
  configPath
3759
3766
  }, "Configuration validation failed");
3760
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}: ${parsed.error.message}`);
3767
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}
3768
+
3769
+ Please check your evaliphy.config.ts and fix the above fields.
3770
+ Docs: https://evaliphy.com/docs/configuration`);
3761
3771
  }
3762
3772
  this.cachedConfig = mergeConfigs(parsed.data, {}, this.cliOverrides);
3763
3773
  this.cachedConfig.configFile = configPath;
@@ -3767,7 +3777,11 @@ var ConfigLoader = class ConfigLoader {
3767
3777
  configPath
3768
3778
  }, "Error loading configuration");
3769
3779
  if (error instanceof EvaliphyError) throw error;
3770
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}`);
3780
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}
3781
+
3782
+ Please check your evaliphy.config.ts and fix the above fields.
3783
+ Docs: https://evaliphy.com/docs/configuration
3784
+ `);
3771
3785
  }
3772
3786
  }
3773
3787
  const finalConfig = mergeConfigs(this.cachedConfig, transientOverrides, {});
@@ -4005,48 +4019,100 @@ function handleFatalError(err) {
4005
4019
  }
4006
4020
  //#endregion
4007
4021
  //#region packages/cli/src/initProject/createFolderStructure.ts
4022
+ const require$1 = createRequire(import.meta.url);
4023
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
4024
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
4025
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
4026
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
4008
4027
  function createProject(projectName) {
4009
- const rootPath = path$1.join(process.cwd(), projectName);
4010
- if (fs$1.existsSync(rootPath)) {
4011
- console.error("Folder already exists.");
4028
+ const __filename = fileURLToPath(import.meta.url);
4029
+ const __dirname = path.dirname(__filename);
4030
+ const { version } = require$1(path.join(__dirname, "../package.json"));
4031
+ if (!/^[a-z0-9-_]+$/i.test(projectName)) {
4032
+ console.error(red(`\n ✗ Invalid project name "${projectName}".`));
4033
+ console.error(dim(" Use only letters, numbers, hyphens and underscores.\n"));
4034
+ process.exit(1);
4035
+ }
4036
+ const rootPath = path.join(process.cwd(), projectName);
4037
+ if (fs.existsSync(rootPath)) {
4038
+ console.error(red(`\n ✗ Directory "${projectName}" already exists.`));
4039
+ console.error(dim(` Choose a different name or remove the existing directory.\n`));
4012
4040
  process.exit(1);
4013
4041
  }
4014
- fs$1.mkdirSync(rootPath, { recursive: true });
4015
- createStructure(rootPath, {
4016
- evals: { "example.eval.ts": `
4017
- import { evaluate } from 'evaliphy';
4042
+ console.log(`\n Creating project ${bold(projectName)}...\n`);
4043
+ const structure = {
4044
+ evals: { "example.eval.ts": `import { evaluate, expect } from 'evaliphy';
4045
+
4046
+ /**
4047
+ * Example evaluation — replace this with your own RAG endpoint and samples.
4048
+ * Docs: https://evaliphy.com/docs/quick-start
4049
+ */
4050
+ evaluate("context handling: multiple chunks", async ({ httpClient }) => {
4051
+ const query = "What are the support hours?";
4052
+ const context = [
4053
+ "Support is available 24/7 via email.",
4054
+ "Live chat support is open from 9 AM to 5 PM EST.",
4055
+ "Phone support is currently unavailable."
4056
+ ];
4057
+
4058
+ const res = await httpClient.post("/api/generate", { prompt: query });
4059
+ const data = await res.json();
4018
4060
 
4019
- evaluate('basic test', async ({ httpClient }) => {
4020
- // add your evaluate code
4061
+ await expect({
4062
+ query,
4063
+ response: data.content,
4064
+ context,
4065
+ }).toBeFaithful({ threshold: 0.7 });
4021
4066
  });
4022
4067
  ` },
4023
- utils: {},
4024
- "evaliphy.config.ts": `
4025
- import { defineConfig } from 'evaliphy';
4068
+ ".env.example": `# Copy this file to .env and fill in your values
4069
+ OPENAI_API_KEY=your-api-key-here
4070
+ `,
4071
+ ".gitignore": `.env
4072
+ node_modules
4073
+ dist
4074
+ results
4075
+ `,
4076
+ "evaliphy.config.ts": `import { defineConfig } from 'evaliphy';
4026
4077
 
4027
4078
  export default defineConfig({
4028
- baseUrl: 'http://localhost:8080',
4029
- testDir: './evals',
4079
+ http: {
4080
+ baseUrl: "http://localhost:8080",
4081
+ timeout: 10_000,
4082
+ },
4083
+ evalDir: './evals',
4030
4084
  llmAsJudgeConfig: {
4031
4085
  model: 'gpt-4o-mini',
4032
4086
  provider: {
4033
- type: 'gateway',
4034
- url: 'https://openrouter.ai/api/v1',
4035
- apiKey: process.env.OPENROUTER_API_KEY,
4087
+ type: 'openai',
4088
+ apiKey: process.env.OPENAI_API_KEY,
4036
4089
  },
4037
- promptsDir: './prompts',
4038
- temperature: 0
4090
+ temperature: 0,
4039
4091
  },
4040
4092
  });
4041
4093
  `,
4042
- "tsconfig.json": JSON.stringify({ compilerOptions: {
4043
- target: "ES2020",
4044
- module: "CommonJS",
4045
- strict: true,
4046
- esModuleInterop: true,
4047
- skipLibCheck: true
4048
- } }, null, 2)
4049
- });
4094
+ "tsconfig.json": JSON.stringify({
4095
+ compilerOptions: {
4096
+ target: "ES2020",
4097
+ module: "ESNext",
4098
+ moduleResolution: "bundler",
4099
+ strict: true,
4100
+ esModuleInterop: true,
4101
+ skipLibCheck: true,
4102
+ outDir: "./dist"
4103
+ },
4104
+ include: ["**/*.ts"],
4105
+ exclude: ["node_modules", "dist"]
4106
+ }, null, 2)
4107
+ };
4108
+ try {
4109
+ fs.mkdirSync(rootPath, { recursive: true });
4110
+ createStructure(rootPath, structure);
4111
+ } catch (err) {
4112
+ console.error(red("\n ✗ Failed to create project files."));
4113
+ console.error(dim(` ${err.message}\n`));
4114
+ process.exit(1);
4115
+ }
4050
4116
  const pkg = {
4051
4117
  name: projectName,
4052
4118
  version: "1.0.0",
@@ -4057,29 +4123,46 @@ export default defineConfig({
4057
4123
  build: "tsc"
4058
4124
  },
4059
4125
  devDependencies: {
4060
- "evaliphy": "^1.0.0",
4061
- "typescript": "^5.0.0"
4126
+ "evaliphy": `^${version}`,
4127
+ typescript: "^5.0.0"
4062
4128
  }
4063
4129
  };
4064
- fs$1.writeFileSync(path$1.join(rootPath, "package.json"), JSON.stringify(pkg, null, 2));
4065
4130
  try {
4066
- console.log("📦 Installing dependencies...");
4067
- execSync("npm install", {
4068
- cwd: rootPath,
4069
- stdio: "inherit"
4070
- });
4131
+ fs.writeFileSync(path.join(rootPath, "package.json"), JSON.stringify(pkg, null, 2));
4071
4132
  } catch (err) {
4072
- console.error("Failed to install dependencies");
4133
+ console.error(red("\n ✗ Failed to write package.json."));
4134
+ console.error(dim(` ${err.message}\n`));
4135
+ process.exit(1);
4073
4136
  }
4074
- console.log(`\n✅ Project "${projectName}" is ready!`);
4137
+ console.log(` ${green("✓")} evaliphy.config.ts`);
4138
+ console.log(` ${green("✓")} evals/example.eval.ts`);
4139
+ console.log(` ${green("✓")} .env.example`);
4140
+ console.log(` ${green("✓")} .gitignore`);
4141
+ console.log(` ${green("✓")} tsconfig.json`);
4142
+ console.log(` ${green("✓")} package.json`);
4143
+ console.log(`
4144
+ ${green("✓")} ${bold(`Project "${projectName}" created successfully!`)}
4145
+
4146
+ ${bold("Next steps:")}
4147
+ ${dim("$")} Ensuer you have Node JS either v24.0.0 or higher.
4148
+ ${dim("$")} cd ${projectName}
4149
+ ${dim("$")} cp .env.example .env ${dim("← add your OPENAI_API_KEY")}
4150
+ ${dim("$")} npm install
4151
+ ${dim("$")} npm test
4152
+
4153
+ ${dim(`Docs → https://evaliphy.com/docs`)}
4154
+ ${dim(`Examples → https://evaliphy.com/docs/examples`)}
4155
+ `);
4075
4156
  }
4076
4157
  function createStructure(basePath, structure) {
4077
- for (const name in structure) {
4078
- const fullPath = path$1.join(basePath, name);
4079
- if (typeof structure[name] === "string") fs$1.writeFileSync(fullPath, structure[name]);
4080
- else {
4081
- fs$1.mkdirSync(fullPath, { recursive: true });
4082
- createStructure(fullPath, structure[name]);
4158
+ for (const [name, content] of Object.entries(structure)) {
4159
+ const fullPath = path.join(basePath, name);
4160
+ if (typeof content === "string") {
4161
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
4162
+ fs.writeFileSync(fullPath, content, "utf8");
4163
+ } else {
4164
+ fs.mkdirSync(fullPath, { recursive: true });
4165
+ createStructure(fullPath, content);
4083
4166
  }
4084
4167
  }
4085
4168
  }
@@ -31260,9 +31343,10 @@ var ConsoleReporter = class {
31260
31343
  const duration = this.formatDuration(payload.duration);
31261
31344
  console.log("\n" + this.getSeparator());
31262
31345
  [
31263
- import_picocolors.default.bold("Tests: ") + (payload.failed > 0 ? import_picocolors.default.red(`${payload.failed} failed`) + import_picocolors.default.dim(", ") : "") + import_picocolors.default.green(`${payload.passed} passed`) + import_picocolors.default.dim(`, ${total} total`),
31264
- import_picocolors.default.bold("Time: ") + import_picocolors.default.white(duration),
31265
- import_picocolors.default.bold("Run ID: ") + import_picocolors.default.dim(payload.runId)
31346
+ import_picocolors.default.bold("Tests: ") + (payload.failed > 0 ? import_picocolors.default.red(`${payload.failed} failed`) + import_picocolors.default.dim(", ") : "") + import_picocolors.default.green(`${payload.passed} passed`) + import_picocolors.default.dim(`, ${total} total`),
31347
+ import_picocolors.default.bold("Time: ") + import_picocolors.default.white(duration),
31348
+ import_picocolors.default.bold("Run ID: ") + import_picocolors.default.dim(payload.runId),
31349
+ import_picocolors.default.bold("HTML Report: ") + import_picocolors.default.dim("report/report-" + payload.runId + ".html")
31266
31350
  ].forEach((line) => console.log(` ${line}`));
31267
31351
  console.log(this.getSeparator() + "\n");
31268
31352
  if (payload.failed > 0) console.log(` ${import_picocolors.default.red(import_picocolors.default.bold("FAIL"))} ${import_picocolors.default.red("Run failed")}\n`);
@@ -32131,8 +32215,9 @@ async function runRegistry(explicitFile) {
32131
32215
  }
32132
32216
  //#endregion
32133
32217
  //#region packages/cli/src/bin.ts
32134
- const packageJsonPath = join(fileURLToPath(new URL(".", import.meta.url)), "../package.json");
32135
- const { version } = JSON.parse(readFileSync(packageJsonPath, "utf8"));
32218
+ const __filename = fileURLToPath$1(import.meta.url);
32219
+ const __dirname = path$1.dirname(__filename);
32220
+ const { version } = __require(path$1.join(__dirname, "../package.json"));
32136
32221
  program.name("evaliphy").version(version).description("Evaliphy — eval runner for LLM pipelines");
32137
32222
  program.command("init <project-name>").description("Create project structure as recommended by Evaliphy.").action((projectName) => {
32138
32223
  createProject(projectName);
package/dist/index.cjs CHANGED
@@ -183,7 +183,14 @@ var ConfigLoader = class ConfigLoader {
183
183
  const configPath = this.findConfigFile(cwd);
184
184
  if (!configPath) {
185
185
  this.configLogger.debug("No config file found, using defaults if applicable");
186
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, "Provided config file is not correct or does not exist.");
186
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Could not load configuration. Please check the following:
187
+
188
+ - Does "evaliphy.config.ts" exist in your project root?
189
+ - Is the path correct if you specified a custom config location?
190
+ - Does the config file export a default defineConfig({}) call?
191
+
192
+ Expected location: ${process.cwd()}/evaliphy.config.ts
193
+ Visit https://evaliphy.com/docs/configuration for more details.`);
187
194
  }
188
195
  if (!this.cachedConfig) {
189
196
  this.configLogger.debug({ configPath }, "Loading base configuration from file");
@@ -196,7 +203,10 @@ var ConfigLoader = class ConfigLoader {
196
203
  error: parsed.error,
197
204
  configPath
198
205
  }, "Configuration validation failed");
199
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}: ${parsed.error.message}`);
206
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}
207
+
208
+ Please check your evaliphy.config.ts and fix the above fields.
209
+ Docs: https://evaliphy.com/docs/configuration`);
200
210
  }
201
211
  this.cachedConfig = mergeConfigs(parsed.data, {}, this.cliOverrides);
202
212
  this.cachedConfig.configFile = configPath;
@@ -206,7 +216,11 @@ var ConfigLoader = class ConfigLoader {
206
216
  configPath
207
217
  }, "Error loading configuration");
208
218
  if (error instanceof EvaliphyError) throw error;
209
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}`);
219
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}
220
+
221
+ Please check your evaliphy.config.ts and fix the above fields.
222
+ Docs: https://evaliphy.com/docs/configuration
223
+ `);
210
224
  }
211
225
  }
212
226
  const finalConfig = mergeConfigs(this.cachedConfig, transientOverrides, {});
package/dist/index.mjs CHANGED
@@ -180,7 +180,14 @@ var ConfigLoader = class ConfigLoader {
180
180
  const configPath = this.findConfigFile(cwd);
181
181
  if (!configPath) {
182
182
  this.configLogger.debug("No config file found, using defaults if applicable");
183
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, "Provided config file is not correct or does not exist.");
183
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Could not load configuration. Please check the following:
184
+
185
+ - Does "evaliphy.config.ts" exist in your project root?
186
+ - Is the path correct if you specified a custom config location?
187
+ - Does the config file export a default defineConfig({}) call?
188
+
189
+ Expected location: ${process.cwd()}/evaliphy.config.ts
190
+ Visit https://evaliphy.com/docs/configuration for more details.`);
184
191
  }
185
192
  if (!this.cachedConfig) {
186
193
  this.configLogger.debug({ configPath }, "Loading base configuration from file");
@@ -193,7 +200,10 @@ var ConfigLoader = class ConfigLoader {
193
200
  error: parsed.error,
194
201
  configPath
195
202
  }, "Configuration validation failed");
196
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}: ${parsed.error.message}`);
203
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Invalid configuration in ${configPath}
204
+
205
+ Please check your evaliphy.config.ts and fix the above fields.
206
+ Docs: https://evaliphy.com/docs/configuration`);
197
207
  }
198
208
  this.cachedConfig = mergeConfigs(parsed.data, {}, this.cliOverrides);
199
209
  this.cachedConfig.configFile = configPath;
@@ -203,7 +213,11 @@ var ConfigLoader = class ConfigLoader {
203
213
  configPath
204
214
  }, "Error loading configuration");
205
215
  if (error instanceof EvaliphyError) throw error;
206
- throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}`);
216
+ throw new EvaliphyError(EvaliphyErrorCode.INVALID_CONFIG, `Failed to load config from ${configPath}: ${error.message}
217
+
218
+ Please check your evaliphy.config.ts and fix the above fields.
219
+ Docs: https://evaliphy.com/docs/configuration
220
+ `);
207
221
  }
208
222
  }
209
223
  const finalConfig = mergeConfigs(this.cachedConfig, transientOverrides, {});