@workbench-ai/workbench 0.0.49 → 0.0.51
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/adapter-project.js +3 -3
- package/dist/benchmark-fingerprint.d.ts +1 -1
- package/dist/benchmark-fingerprint.d.ts.map +1 -1
- package/dist/benchmark-fingerprint.js +4 -6
- package/dist/command-model.d.ts.map +1 -1
- package/dist/command-model.js +95 -453
- package/dist/dev-open/client.css +42 -43
- package/dist/dev-open/client.js +145 -145
- package/dist/dev-open-server.d.ts +12 -22
- package/dist/dev-open-server.d.ts.map +1 -1
- package/dist/dev-open-server.js +82 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1758 -1245
- package/dist/init-scaffold.d.ts +4 -4
- package/dist/init-scaffold.d.ts.map +1 -1
- package/dist/init-scaffold.js +2 -2
- package/dist/init-template-pack.d.ts +4 -4
- package/dist/init-template-pack.d.ts.map +1 -1
- package/dist/init-template-pack.js +47 -59
- package/dist/local-archive.d.ts +15 -11
- package/dist/local-archive.d.ts.map +1 -1
- package/dist/local-archive.js +325 -83
- package/dist/project-source.d.ts +14 -17
- package/dist/project-source.d.ts.map +1 -1
- package/dist/project-source.js +80 -151
- package/package.json +4 -4
package/dist/project-source.js
CHANGED
|
@@ -2,16 +2,15 @@ import { promises as fs } from "node:fs";
|
|
|
2
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { BENCHMARK_SPEC_FILE, buildWorkbenchProjectSourceFiles, engineResolveInvocationForSpec, normalizeSurfaceFiles, parseWorkbenchSourceFiles, resolveWorkbenchResolvedSourceYaml, serializeWorkbenchResolvedSourceYaml, validateWorkbenchResolvedSourceYaml, } from "@workbench-ai/workbench-core";
|
|
5
|
+
import { BENCHMARK_SPEC_FILE, CANDIDATE_SPEC_FILE, buildWorkbenchProjectSourceFiles, engineResolveInvocationForSpec, normalizeSurfaceFiles, parseWorkbenchSourceFiles, resolveWorkbenchResolvedSourceYaml, serializeWorkbenchResolvedSourceYaml, validateWorkbenchResolvedSourceYaml, } from "@workbench-ai/workbench-core";
|
|
6
6
|
import { assertWorkbenchAdapterOperationSupport, assertWorkbenchAdapterOperationResultOk, collectWorkbenchAdapterInvocations, readWorkbenchAdapterOperationResult, workbenchAdapterOperationCommand, workbenchAdapterOperationResultPath, } from "@workbench-ai/workbench-protocol";
|
|
7
7
|
import { readSnapshotFiles, WorkspaceSnapshotError, } from "./workspace-snapshot.js";
|
|
8
8
|
import { defaultAdapterManifests, composeRuntimeDockerfileWithAdapters, resolveDefaultWorkbenchAdapter, resolveProjectAdapterSource, resolveWorkbenchAdaptersForProject, } from "./adapter-project.js";
|
|
9
9
|
import { createAdapterCommandEnv } from "./adapter-command-env.js";
|
|
10
10
|
import YAML from "yaml";
|
|
11
11
|
export const WORKBENCH_BENCHMARK_FILE = BENCHMARK_SPEC_FILE;
|
|
12
|
-
export const
|
|
13
|
-
export const
|
|
14
|
-
export const WORKBENCH_SUBJECT_FILE = "subject.yaml";
|
|
12
|
+
export const WORKBENCH_CANDIDATES_DIR = "candidates";
|
|
13
|
+
export const WORKBENCH_CANDIDATE_FILE = CANDIDATE_SPEC_FILE;
|
|
15
14
|
function rootAdapterInvocations(spec) {
|
|
16
15
|
return [
|
|
17
16
|
engineResolveInvocationForSpec(spec),
|
|
@@ -22,25 +21,20 @@ function rootAdapterInvocations(spec) {
|
|
|
22
21
|
}
|
|
23
22
|
export async function readLocalProjectSource(source, options = {}) {
|
|
24
23
|
const paths = await resolveLocalProjectSourcePaths(source, options);
|
|
25
|
-
const { dir, benchmarkPath,
|
|
24
|
+
const { dir, benchmarkPath, candidateSpecPath, candidateDir, } = paths;
|
|
26
25
|
const benchmarkSource = await readRequiredTextFile(benchmarkPath, WORKBENCH_BENCHMARK_FILE);
|
|
27
|
-
const
|
|
28
|
-
const optimizerSource = optimizerPath
|
|
29
|
-
? await readRequiredTextFile(optimizerPath, "optimizer YAML")
|
|
30
|
-
: undefined;
|
|
26
|
+
const candidateSource = await readRequiredTextFile(candidateSpecPath, "candidate YAML");
|
|
31
27
|
const normalizedSources = await normalizeSourceYamlForExecution({
|
|
32
28
|
dir,
|
|
33
29
|
benchmarkPath,
|
|
34
30
|
benchmarkSource,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
optimizerPath,
|
|
38
|
-
optimizerSource,
|
|
31
|
+
candidateSpecPath,
|
|
32
|
+
candidateSource,
|
|
39
33
|
});
|
|
40
34
|
const resolvedSource = parseWorkbenchSourceFiles({
|
|
41
35
|
benchmarkSource: normalizedSources.benchmarkSource,
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
candidateSource: normalizedSources.candidateSource,
|
|
37
|
+
runId: options.runId,
|
|
44
38
|
});
|
|
45
39
|
const specSource = serializeWorkbenchResolvedSourceYaml(resolvedSource);
|
|
46
40
|
const validation = validateWorkbenchResolvedSourceYaml(specSource);
|
|
@@ -60,10 +54,10 @@ export async function readLocalProjectSource(source, options = {}) {
|
|
|
60
54
|
];
|
|
61
55
|
const composedDockerfile = await composeRuntimeDockerfileWithAdapters(dockerfile, adapters);
|
|
62
56
|
const adapterFiles = adapterSourceFiles(adapters);
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
? normalizeSurfaceFiles(await readSnapshotFiles(
|
|
57
|
+
const absoluteCandidateFilesPath = resolveProjectPath(dir, spec.candidate.files.path);
|
|
58
|
+
const candidateFilesPath = absoluteCandidateFilesPath;
|
|
59
|
+
const candidateFiles = await directoryExists(absoluteCandidateFilesPath)
|
|
60
|
+
? normalizeSurfaceFiles(await readSnapshotFiles(absoluteCandidateFilesPath))
|
|
67
61
|
: [];
|
|
68
62
|
const rawEngineResolveFiles = engineResolveFilesFromBundles(normalizedSources.engineCases);
|
|
69
63
|
const engineResolveFiles = toHostedFiles(rawEngineResolveFiles);
|
|
@@ -79,19 +73,20 @@ export async function readLocalProjectSource(source, options = {}) {
|
|
|
79
73
|
spec,
|
|
80
74
|
benchmarkPath,
|
|
81
75
|
benchmarkSource,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
candidateName: path.basename(candidateDir),
|
|
77
|
+
candidateDir,
|
|
78
|
+
candidateFilesPath,
|
|
79
|
+
candidateSpecPath,
|
|
80
|
+
candidateSource,
|
|
81
|
+
candidateRunId: spec.candidate.selectedRunId,
|
|
82
|
+
candidateRunIds: Object.keys(spec.candidate.runs).sort(),
|
|
88
83
|
benchmarkAdapterSources: [...resolvedSource.benchmark.adapters],
|
|
89
84
|
benchmarkAdapterIds,
|
|
90
85
|
dockerfilePath,
|
|
91
86
|
dockerfile,
|
|
92
87
|
runtimeDockerfile: composedDockerfile,
|
|
93
88
|
dockerfileFiles: toHostedFiles(dockerfileSourceFiles(dockerfileSources)),
|
|
94
|
-
|
|
89
|
+
candidateFiles: toHostedFiles(candidateFiles),
|
|
95
90
|
engineResolveFiles,
|
|
96
91
|
adapters,
|
|
97
92
|
adapterFiles: toHostedFiles(adapterFiles),
|
|
@@ -105,13 +100,10 @@ export async function readLocalProjectSource(source, options = {}) {
|
|
|
105
100
|
sourceFiles: buildWorkbenchProjectSourceFiles({
|
|
106
101
|
specFiles: [
|
|
107
102
|
textSourceFile(toRootRelativePath(dir, benchmarkPath), benchmarkSource),
|
|
108
|
-
textSourceFile(toRootRelativePath(dir,
|
|
109
|
-
...(optimizerSource !== undefined && optimizerPath
|
|
110
|
-
? [textSourceFile(toRootRelativePath(dir, optimizerPath), optimizerSource)]
|
|
111
|
-
: []),
|
|
103
|
+
textSourceFile(toRootRelativePath(dir, candidateSpecPath), candidateSource),
|
|
112
104
|
],
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
candidateFilesPath: spec.candidate.files.path,
|
|
106
|
+
candidateFiles: candidateFiles,
|
|
115
107
|
engineResolveFilesPath: normalizedSources.engineResolveFingerprintPath,
|
|
116
108
|
engineResolveFiles: rawEngineResolveFiles,
|
|
117
109
|
adapterFiles,
|
|
@@ -120,16 +112,13 @@ export async function readLocalProjectSource(source, options = {}) {
|
|
|
120
112
|
};
|
|
121
113
|
}
|
|
122
114
|
export async function readLocalAuthoredProjectSource(source, options = {}) {
|
|
123
|
-
const { dir, benchmarkPath,
|
|
115
|
+
const { dir, benchmarkPath, candidateSpecPath, candidateDir, } = await resolveLocalProjectSourcePaths(source, options);
|
|
124
116
|
const benchmarkSource = await readRequiredTextFile(benchmarkPath, WORKBENCH_BENCHMARK_FILE);
|
|
125
|
-
const
|
|
126
|
-
const optimizerSource = optimizerPath
|
|
127
|
-
? await readRequiredTextFile(optimizerPath, "optimizer YAML")
|
|
128
|
-
: undefined;
|
|
117
|
+
const candidateSource = await readRequiredTextFile(candidateSpecPath, "candidate YAML");
|
|
129
118
|
const resolvedSource = parseWorkbenchSourceFiles({
|
|
130
119
|
benchmarkSource,
|
|
131
|
-
|
|
132
|
-
|
|
120
|
+
candidateSource,
|
|
121
|
+
runId: options.runId,
|
|
133
122
|
});
|
|
134
123
|
const specSource = serializeWorkbenchResolvedSourceYaml(resolvedSource);
|
|
135
124
|
return {
|
|
@@ -138,16 +127,12 @@ export async function readLocalAuthoredProjectSource(source, options = {}) {
|
|
|
138
127
|
specSource,
|
|
139
128
|
benchmarkPath,
|
|
140
129
|
benchmarkSource,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
...(optimizerPath && optimizerSource !== undefined ? { optimizerPath, optimizerSource } : {}),
|
|
130
|
+
candidateDir,
|
|
131
|
+
candidateSpecPath,
|
|
132
|
+
candidateSource,
|
|
145
133
|
sourceFiles: [
|
|
146
134
|
textSourceFile(toRootRelativePath(dir, benchmarkPath), benchmarkSource),
|
|
147
|
-
textSourceFile(toRootRelativePath(dir,
|
|
148
|
-
...(optimizerPath && optimizerSource !== undefined
|
|
149
|
-
? [textSourceFile(toRootRelativePath(dir, optimizerPath), optimizerSource)]
|
|
150
|
-
: []),
|
|
135
|
+
textSourceFile(toRootRelativePath(dir, candidateSpecPath), candidateSource),
|
|
151
136
|
],
|
|
152
137
|
};
|
|
153
138
|
}
|
|
@@ -156,105 +141,67 @@ async function resolveLocalProjectSourcePaths(source, options) {
|
|
|
156
141
|
const stat = await fs.stat(resolved).catch(() => null);
|
|
157
142
|
if (stat?.isFile()) {
|
|
158
143
|
const sourceRecord = await readYamlRecordFile(resolved);
|
|
159
|
-
if (
|
|
160
|
-
const
|
|
161
|
-
const dir =
|
|
144
|
+
if (isCandidateSourceRecord(sourceRecord)) {
|
|
145
|
+
const candidateDir = path.dirname(resolved);
|
|
146
|
+
const dir = projectRootForCandidateDir(candidateDir);
|
|
162
147
|
return {
|
|
163
148
|
dir,
|
|
164
149
|
benchmarkPath: path.join(dir, WORKBENCH_BENCHMARK_FILE),
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
optimizerPath: await resolveOptimizerPath(dir, options.optimizerPath, path.basename(subjectDir)),
|
|
150
|
+
candidateDir,
|
|
151
|
+
candidateSpecPath: resolved,
|
|
168
152
|
};
|
|
169
153
|
}
|
|
170
154
|
if (isBenchmarkSourceRecord(sourceRecord)) {
|
|
171
155
|
const dir = path.dirname(resolved);
|
|
172
|
-
const
|
|
156
|
+
const candidatePaths = await resolveCandidatePaths(dir);
|
|
173
157
|
return {
|
|
174
158
|
dir,
|
|
175
159
|
benchmarkPath: resolved,
|
|
176
|
-
...
|
|
177
|
-
optimizerPath: await resolveOptimizerPath(dir, options.optimizerPath, path.basename(subjectPaths.subjectDir)),
|
|
160
|
+
...candidatePaths,
|
|
178
161
|
};
|
|
179
162
|
}
|
|
180
|
-
if (isOptimizerSourceRecord(sourceRecord)) {
|
|
181
|
-
throw new WorkspaceSnapshotError(`Optimizer source must be passed with --optimizer; pass a source directory or subject YAML as SOURCE: ${resolved}`);
|
|
182
|
-
}
|
|
183
163
|
throw new WorkspaceSnapshotError(`Unsupported Workbench YAML source: ${resolved}`);
|
|
184
164
|
}
|
|
185
165
|
const dir = resolved;
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
188
|
-
return
|
|
189
|
-
...directorySubject,
|
|
190
|
-
optimizerPath: await resolveOptimizerPath(directorySubject.dir, options.optimizerPath, path.basename(directorySubject.subjectDir)),
|
|
191
|
-
};
|
|
166
|
+
const directoryCandidate = await candidatePathsForCandidateDirectory(dir);
|
|
167
|
+
if (directoryCandidate) {
|
|
168
|
+
return directoryCandidate;
|
|
192
169
|
}
|
|
193
|
-
const
|
|
170
|
+
const candidatePaths = await resolveCandidatePaths(dir);
|
|
194
171
|
return {
|
|
195
172
|
dir,
|
|
196
173
|
benchmarkPath: path.join(dir, WORKBENCH_BENCHMARK_FILE),
|
|
197
|
-
...
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
async function resolveSubjectPathsWithOptimizer(dir, explicitOptimizerPath) {
|
|
201
|
-
const subjectPaths = await resolveSubjectPaths(dir);
|
|
202
|
-
return {
|
|
203
|
-
...subjectPaths,
|
|
204
|
-
optimizerPath: await resolveOptimizerPath(dir, explicitOptimizerPath, path.basename(subjectPaths.subjectDir)),
|
|
174
|
+
...candidatePaths,
|
|
205
175
|
};
|
|
206
176
|
}
|
|
207
|
-
async function
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
if (
|
|
211
|
-
const
|
|
212
|
-
const
|
|
177
|
+
async function resolveCandidatePaths(dir) {
|
|
178
|
+
const candidatesDir = path.join(dir, WORKBENCH_CANDIDATES_DIR);
|
|
179
|
+
const candidates = await listCandidateManifestFiles(candidatesDir);
|
|
180
|
+
if (candidates.length === 1) {
|
|
181
|
+
const candidateSpecPath = candidates[0];
|
|
182
|
+
const candidateDir = path.dirname(candidateSpecPath);
|
|
213
183
|
return {
|
|
214
|
-
|
|
215
|
-
|
|
184
|
+
candidateDir,
|
|
185
|
+
candidateSpecPath,
|
|
216
186
|
};
|
|
217
187
|
}
|
|
218
|
-
if (
|
|
219
|
-
throw new WorkspaceSnapshotError(`Multiple
|
|
220
|
-
}
|
|
221
|
-
throw new WorkspaceSnapshotError(`No subject directories found under ${subjectsDir}; create subjects/NAME/subject.yaml with files.path.`);
|
|
222
|
-
}
|
|
223
|
-
async function resolveOptimizerPath(dir, explicit, subjectName) {
|
|
224
|
-
if (explicit) {
|
|
225
|
-
return path.resolve(dir, explicit);
|
|
226
|
-
}
|
|
227
|
-
if (subjectName) {
|
|
228
|
-
const named = path.join(dir, WORKBENCH_OPTIMIZERS_DIR, `${subjectName}.yaml`);
|
|
229
|
-
if (await fileExists(named)) {
|
|
230
|
-
return named;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
const optimizersDir = path.join(dir, WORKBENCH_OPTIMIZERS_DIR);
|
|
234
|
-
const optimizers = await listYamlFiles(optimizersDir);
|
|
235
|
-
if (optimizers.length === 1) {
|
|
236
|
-
return optimizers[0];
|
|
188
|
+
if (candidates.length > 1) {
|
|
189
|
+
throw new WorkspaceSnapshotError(`Multiple candidate directories found under ${candidatesDir}; pass candidates/NAME or candidates/NAME/candidate.yaml explicitly.`);
|
|
237
190
|
}
|
|
238
|
-
|
|
191
|
+
throw new WorkspaceSnapshotError(`No candidate directories found under ${candidatesDir}; create candidates/NAME/candidate.yaml with files.path.`);
|
|
239
192
|
}
|
|
240
193
|
async function normalizeSourceYamlForExecution(args) {
|
|
241
194
|
const benchmark = parseYamlRecord(args.benchmarkSource, args.benchmarkPath);
|
|
242
|
-
const
|
|
243
|
-
const optimizer = args.optimizerSource === undefined || args.optimizerPath === undefined
|
|
244
|
-
? undefined
|
|
245
|
-
: parseYamlRecord(args.optimizerSource, args.optimizerPath);
|
|
195
|
+
const candidate = parseYamlRecord(args.candidateSource, args.candidateSpecPath);
|
|
246
196
|
const benchmarkDir = path.dirname(args.benchmarkPath);
|
|
247
|
-
const
|
|
197
|
+
const candidateDir = path.dirname(args.candidateSpecPath);
|
|
248
198
|
normalizeAdapterSourcePaths(args.dir, benchmark, benchmarkDir);
|
|
249
|
-
normalizeAdapterSourcePaths(args.dir,
|
|
250
|
-
if (optimizer && args.optimizerPath) {
|
|
251
|
-
normalizeAdapterSourcePaths(args.dir, optimizer, path.dirname(args.optimizerPath));
|
|
252
|
-
}
|
|
199
|
+
normalizeAdapterSourcePaths(args.dir, candidate, candidateDir);
|
|
253
200
|
const engine = yamlRecord(benchmark.engine);
|
|
254
201
|
if (!engine || typeof engine.use !== "string" || !engine.use.trim()) {
|
|
255
202
|
throw new WorkspaceSnapshotError("benchmark.yaml engine must declare an adapter invocation with use.");
|
|
256
203
|
}
|
|
257
|
-
normalizeEngineForExecution(args.dir, benchmarkDir,
|
|
204
|
+
normalizeEngineForExecution(args.dir, benchmarkDir, candidateDir, benchmark, candidate);
|
|
258
205
|
const authoredEngineResolve = engineResolveInvocationFromRecord(engine);
|
|
259
206
|
const engineResolve = await resolveEngineResolveAdapter({
|
|
260
207
|
root: args.dir,
|
|
@@ -267,21 +214,18 @@ async function normalizeSourceYamlForExecution(args) {
|
|
|
267
214
|
applyEngineResolveEnvironment(benchmark, engineResolve.environment);
|
|
268
215
|
return {
|
|
269
216
|
benchmarkSource: YAML.stringify(benchmark).trimEnd() + "\n",
|
|
270
|
-
|
|
217
|
+
candidateSource: YAML.stringify(candidate).trimEnd() + "\n",
|
|
271
218
|
engineResolveFingerprintPath,
|
|
272
219
|
engineResolve: authoredEngineResolve,
|
|
273
220
|
...(engineResolve.environment ? { engineResolveEnvironment: engineResolve.environment } : {}),
|
|
274
221
|
engineCases: engineResolve.engineCases,
|
|
275
|
-
...(optimizer
|
|
276
|
-
? { optimizerSource: YAML.stringify(optimizer).trimEnd() + "\n" }
|
|
277
|
-
: {}),
|
|
278
222
|
};
|
|
279
223
|
}
|
|
280
|
-
function normalizeEngineForExecution(root, benchmarkDir,
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
224
|
+
function normalizeEngineForExecution(root, benchmarkDir, candidateDir, benchmark, candidate) {
|
|
225
|
+
const candidateFiles = yamlRecord(candidate.files);
|
|
226
|
+
if (candidateFiles && typeof candidateFiles.path === "string") {
|
|
227
|
+
candidateFiles.path = toRootRelativePath(root, resolveYamlReference(candidateDir, candidateFiles.path));
|
|
228
|
+
candidate.files = candidateFiles;
|
|
285
229
|
}
|
|
286
230
|
const engine = yamlRecord(benchmark.engine);
|
|
287
231
|
const engineConfig = yamlRecord(engine?.with) ?? {};
|
|
@@ -569,34 +513,31 @@ function isPathAdapterSource(source) {
|
|
|
569
513
|
function isBenchmarkSourceRecord(record) {
|
|
570
514
|
return record.engine !== undefined;
|
|
571
515
|
}
|
|
572
|
-
function
|
|
573
|
-
return record.
|
|
574
|
-
}
|
|
575
|
-
function isOptimizerSourceRecord(record) {
|
|
576
|
-
return record.edits !== undefined && record.improve !== undefined;
|
|
516
|
+
function isCandidateSourceRecord(record) {
|
|
517
|
+
return record.runs !== undefined;
|
|
577
518
|
}
|
|
578
519
|
async function readYamlRecordFile(filePath) {
|
|
579
520
|
return parseYamlRecord(await readRequiredTextFile(filePath, path.basename(filePath)), filePath);
|
|
580
521
|
}
|
|
581
|
-
async function
|
|
582
|
-
const
|
|
583
|
-
if (!(await fileExists(
|
|
522
|
+
async function candidatePathsForCandidateDirectory(sourceDir) {
|
|
523
|
+
const candidateSpecPath = path.join(sourceDir, WORKBENCH_CANDIDATE_FILE);
|
|
524
|
+
if (!(await fileExists(candidateSpecPath))) {
|
|
584
525
|
return null;
|
|
585
526
|
}
|
|
586
|
-
const dir =
|
|
527
|
+
const dir = projectRootForCandidateDir(sourceDir);
|
|
587
528
|
return {
|
|
588
529
|
dir,
|
|
589
530
|
benchmarkPath: path.join(dir, WORKBENCH_BENCHMARK_FILE),
|
|
590
|
-
|
|
591
|
-
|
|
531
|
+
candidateDir: sourceDir,
|
|
532
|
+
candidateSpecPath,
|
|
592
533
|
};
|
|
593
534
|
}
|
|
594
|
-
function
|
|
595
|
-
const parent = path.basename(path.dirname(
|
|
596
|
-
if (parent !==
|
|
597
|
-
throw new WorkspaceSnapshotError(`
|
|
535
|
+
function projectRootForCandidateDir(candidateDir) {
|
|
536
|
+
const parent = path.basename(path.dirname(candidateDir));
|
|
537
|
+
if (parent !== WORKBENCH_CANDIDATES_DIR) {
|
|
538
|
+
throw new WorkspaceSnapshotError(`Candidate directory must be under ${WORKBENCH_CANDIDATES_DIR}/NAME: ${candidateDir}`);
|
|
598
539
|
}
|
|
599
|
-
return path.dirname(path.dirname(
|
|
540
|
+
return path.dirname(path.dirname(candidateDir));
|
|
600
541
|
}
|
|
601
542
|
function parseYamlRecord(source, label) {
|
|
602
543
|
const parsed = YAML.parse(source);
|
|
@@ -632,7 +573,7 @@ async function fileExists(filePath) {
|
|
|
632
573
|
async function directoryExists(filePath) {
|
|
633
574
|
return await fs.stat(filePath).then((stat) => stat.isDirectory(), () => false);
|
|
634
575
|
}
|
|
635
|
-
async function
|
|
576
|
+
async function listCandidateManifestFiles(dir) {
|
|
636
577
|
const entries = await fs.readdir(dir, { withFileTypes: true }).catch((error) => {
|
|
637
578
|
if (error.code === "ENOENT") {
|
|
638
579
|
return [];
|
|
@@ -642,25 +583,13 @@ async function listSubjectManifestFiles(dir) {
|
|
|
642
583
|
const manifests = await Promise.all(entries
|
|
643
584
|
.filter((entry) => entry.isDirectory())
|
|
644
585
|
.map(async (entry) => {
|
|
645
|
-
const manifestPath = path.join(dir, entry.name,
|
|
586
|
+
const manifestPath = path.join(dir, entry.name, WORKBENCH_CANDIDATE_FILE);
|
|
646
587
|
return await fileExists(manifestPath) ? manifestPath : null;
|
|
647
588
|
}));
|
|
648
589
|
return manifests
|
|
649
590
|
.filter((entry) => Boolean(entry))
|
|
650
591
|
.sort((left, right) => left.localeCompare(right));
|
|
651
592
|
}
|
|
652
|
-
async function listYamlFiles(dir) {
|
|
653
|
-
const entries = await fs.readdir(dir, { withFileTypes: true }).catch((error) => {
|
|
654
|
-
if (error.code === "ENOENT") {
|
|
655
|
-
return [];
|
|
656
|
-
}
|
|
657
|
-
throw error;
|
|
658
|
-
});
|
|
659
|
-
return entries
|
|
660
|
-
.filter((entry) => entry.isFile() && /\.ya?ml$/iu.test(entry.name))
|
|
661
|
-
.map((entry) => path.join(dir, entry.name))
|
|
662
|
-
.sort((left, right) => left.localeCompare(right));
|
|
663
|
-
}
|
|
664
593
|
async function readRequiredTextFile(filePath, label) {
|
|
665
594
|
return await fs.readFile(filePath, "utf8").catch((error) => {
|
|
666
595
|
if (error.code === "ENOENT") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workbench-ai/workbench",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"yaml": "^2.8.2",
|
|
24
|
-
"@workbench-ai/workbench-
|
|
25
|
-
"@workbench-ai/workbench-protocol": "0.0.
|
|
26
|
-
"@workbench-ai/workbench-
|
|
24
|
+
"@workbench-ai/workbench-core": "0.0.51",
|
|
25
|
+
"@workbench-ai/workbench-protocol": "0.0.51",
|
|
26
|
+
"@workbench-ai/workbench-built-in-adapters": "0.0.51"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@tailwindcss/postcss": "^4.2.2",
|