@velum-labs/routekit-eval-service 1.0.18 → 1.0.20

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/service.js CHANGED
@@ -145,14 +145,38 @@ const enforceSpendLimit = (request, manifest) => {
145
145
  }
146
146
  return Effect.void;
147
147
  };
148
+ const EXECUTION_MANIFEST_NAME = "routekit.eval-manifest.json";
149
+ const discoverExecutionManifests = Effect.fnUntraced(function* (root) {
150
+ const fs = yield* FileSystem.FileSystem;
151
+ const paths = yield* Path.Path;
152
+ const directories = [root];
153
+ const manifests = [];
154
+ while (directories.length > 0) {
155
+ const directory = directories.pop();
156
+ const entries = yield* fs.readDirectory(directory);
157
+ for (const entry of entries) {
158
+ const entryPath = paths.join(directory, entry);
159
+ if (entry === EXECUTION_MANIFEST_NAME) {
160
+ manifests.push(entryPath);
161
+ continue;
162
+ }
163
+ const isSymbolicLink = yield* fs.readLink(entryPath).pipe(Effect.match({
164
+ onFailure: () => false,
165
+ onSuccess: () => true
166
+ }));
167
+ if (isSymbolicLink)
168
+ continue;
169
+ const info = yield* fs.stat(entryPath);
170
+ if (info.type === "Directory")
171
+ directories.push(entryPath);
172
+ }
173
+ }
174
+ return manifests;
175
+ });
148
176
  const loadExecutionManifest = Effect.fn("EvalService.loadExecutionManifest")(function* (validation, request) {
149
177
  const fs = yield* FileSystem.FileSystem;
150
178
  const paths = yield* Path.Path;
151
- const manifests = yield* fs
152
- .glob("**/routekit.eval-manifest.json", {
153
- root: validation.workingDirectory
154
- })
155
- .pipe(Effect.mapError((cause) => new EvalServiceValidationError({
179
+ const manifests = yield* discoverExecutionManifests(validation.workingDirectory).pipe(Effect.mapError((cause) => new EvalServiceValidationError({
156
180
  operation: "discover the comparison manifest",
157
181
  detail: detailOf(cause),
158
182
  cause
@@ -1,12 +1,12 @@
1
1
  import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { after, test } from "node:test";
6
6
  import { layer as NodeServicesLayer } from "@effect/platform-node/NodeServices";
7
7
  import { EvalEngine } from "@velum-labs/routekit-eval-engine";
8
- import { Effect, Fiber, Layer } from "effect";
9
- import { EvalService, makeEvalServiceLayer } from "../service.js";
8
+ import { Effect, Fiber, FileSystem, Layer, Path } from "effect";
9
+ import { EvalService, makeEvalService, makeEvalServiceLayer } from "../service.js";
10
10
  const roots = [];
11
11
  after(async () => Promise.all(roots.map((root) => rm(root, { recursive: true, force: true }))));
12
12
  const dimensions = [
@@ -97,6 +97,58 @@ const qualification = (root) => ({
97
97
  maximumUnknownWeight: 0.2,
98
98
  suites: suites(root)
99
99
  });
100
+ test("manifest discovery does not call FileSystem.glob when Node glob is unavailable", async () => {
101
+ const root = await mkdtemp(path.join(os.tmpdir(), "routekit-manifest-no-glob-"));
102
+ roots.push(root);
103
+ const suiteDirectory = path.join(root, "nested", "suite");
104
+ const suitePath = path.join(suiteDirectory, "nested.eval.ts");
105
+ await mkdir(suiteDirectory, { recursive: true });
106
+ await writeFile(suitePath, 'import { test } from "node:test"; test("case", () => {});\n');
107
+ await symlink(root, path.join(suiteDirectory, "routekit-link"), "dir");
108
+ await writeFile(path.join(suiteDirectory, "routekit.eval-manifest.json"), `${JSON.stringify({
109
+ version: 1,
110
+ profileId: "nested",
111
+ candidateModels: ["openai/cheap", "anthropic/strong"],
112
+ judgeModel: "openai/judge",
113
+ caseCount: 1,
114
+ caseIds: ["case-1"],
115
+ maxOutputTokens: 256,
116
+ expectedCallCount: 4
117
+ })}\n`);
118
+ let globCalls = 0;
119
+ const inspection = await Effect.runPromise(Effect.gen(function* () {
120
+ const fs = yield* FileSystem.FileSystem;
121
+ const paths = yield* Path.Path;
122
+ const fileSystemWithoutNodeGlob = {
123
+ ...fs,
124
+ glob: () => {
125
+ globCalls += 1;
126
+ return Effect.die(new TypeError("Function.prototype.apply was called on undefined"));
127
+ }
128
+ };
129
+ const service = yield* makeEvalService().pipe(Effect.provideService(EvalEngine, EvalEngine.of({
130
+ discover: () => Effect.die("unexpected discover"),
131
+ validate: () => Effect.succeed({
132
+ searchRoot: suitePath,
133
+ workingDirectory: root,
134
+ files: [suitePath],
135
+ suiteDigest: "suite-nested"
136
+ }),
137
+ runComparison: () => Effect.die("unexpected comparison")
138
+ })), Effect.provideService(FileSystem.FileSystem, fileSystemWithoutNodeGlob), Effect.provideService(Path.Path, paths));
139
+ return yield* service.inspect({
140
+ version: 1,
141
+ profileId: "nested",
142
+ suitePath,
143
+ candidateModels: ["openai/cheap", "anthropic/strong"],
144
+ judgeModel: "openai/judge",
145
+ gatewayUrl: "http://127.0.0.1:8080/v1"
146
+ });
147
+ }).pipe(Effect.provide(NodeServicesLayer)));
148
+ assert.equal(inspection.suiteDigest, "suite-nested");
149
+ assert.equal(inspection.manifest.profileId, "nested");
150
+ assert.equal(globCalls, 0);
151
+ });
100
152
  test("dimension matrix qualification inspects every manifest before publishing one activation", async () => {
101
153
  const root = await mkdtemp(path.join(os.tmpdir(), "routekit-dimension-matrix-"));
102
154
  roots.push(root);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@velum-labs/routekit-eval-service",
3
3
  "private": false,
4
- "version": "1.0.18",
4
+ "version": "1.0.20",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/velum-labs/routekit.git",
@@ -32,10 +32,10 @@
32
32
  "dependencies": {
33
33
  "@effect/platform-node": "4.0.0-rc.108",
34
34
  "effect": "4.0.0-rc.108",
35
- "@velum-labs/routekit-eval-contracts": "1.0.18",
36
- "@velum-labs/routekit-eval-engine": "1.0.18",
37
- "@velum-labs/routekit-eval-store": "1.0.18",
38
- "@velum-labs/routekit-registry": "1.0.18"
35
+ "@velum-labs/routekit-eval-contracts": "1.0.20",
36
+ "@velum-labs/routekit-eval-engine": "1.0.20",
37
+ "@velum-labs/routekit-eval-store": "1.0.20",
38
+ "@velum-labs/routekit-registry": "1.0.20"
39
39
  },
40
40
  "devDependencies": {
41
41
  "typescript": "7.0.2"