@eigenpal/cli 0.10.14 → 0.10.16
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 +17 -0
- package/dist/cli.js +370 -396
- package/dist/skill/reference/cli/run.md +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @eigenpal/cli
|
|
2
2
|
|
|
3
|
+
## 0.10.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b1f0bca: `eigenpal run <workflow> --example <name>` now actually grades the example
|
|
8
|
+
instead of printing `PASS` whenever the run merely finished. It runs the
|
|
9
|
+
workflow's current published version on the server's stored dataset example, so
|
|
10
|
+
configured evaluators run automatically and the CLI surfaces the real weighted
|
|
11
|
+
score and per-evaluator pass/fail. Workflows with no evaluators fall back to a
|
|
12
|
+
structural diff of the output against the example's stored expected output. The
|
|
13
|
+
summary reports two separate signals: execution health (`ok`/`errored`) and
|
|
14
|
+
accuracy. Add `--fail-on-mismatch` to exit non-zero when a graded example fails.
|
|
15
|
+
|
|
16
|
+
Because the run uses the server-side example, push your latest dataset and
|
|
17
|
+
evaluators (`eigenpal workflow dataset push`, `eigenpal workflow evaluators
|
|
18
|
+
push`) before running `--example`.
|
|
19
|
+
|
|
3
20
|
## 0.10.9
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/cli.js
CHANGED
|
@@ -66143,7 +66143,7 @@ function partialMatch(expected, actual, path, mismatches) {
|
|
|
66143
66143
|
}
|
|
66144
66144
|
let allMatch = true;
|
|
66145
66145
|
for (let i = 0;i < expected.length; i++) {
|
|
66146
|
-
const childPath = path ? `${path}
|
|
66146
|
+
const childPath = path ? `${path}[${i}]` : `[${i}]`;
|
|
66147
66147
|
if (!partialMatch(expected[i], actual[i], childPath, mismatches)) {
|
|
66148
66148
|
allMatch = false;
|
|
66149
66149
|
}
|
|
@@ -66314,7 +66314,7 @@ function formatZodError(source) {
|
|
|
66314
66314
|
severity: "error"
|
|
66315
66315
|
}));
|
|
66316
66316
|
}
|
|
66317
|
-
var DATASET_NAME_PATTERN, DatasetNameSchema, DatasetMetaSchema, DatasetImportModeSchema, DatasetImportRequestSchema, EvaluatorsImportRequestSchema, EvalResultsExportFormatSchema, ExperimentExportQuerySchema, EvalResultsExportQuerySchema, EvalResultExportRowSchema, EvalResultsExportJsonSchema, ERROR_HINTS;
|
|
66317
|
+
var DATASET_NAME_PATTERN, DatasetNameSchema, DatasetMetaSchema, DatasetImportModeSchema, DatasetImportRequestSchema, EvaluatorsImportRequestSchema, EvalResultsExportFormatSchema, BooleanQueryFlagSchema, ExperimentExportBaseQuerySchema, ExperimentExportAllQuerySchema, ExperimentExportQuerySchema, EvalResultsExportQuerySchema, EvalResultExportRowSchema, EvalResultsExportJsonSchema, ERROR_HINTS;
|
|
66318
66318
|
var init_dataset_archive = __esm(() => {
|
|
66319
66319
|
init_zod();
|
|
66320
66320
|
DATASET_NAME_PATTERN = /^[a-z0-9][a-z0-9-_]*$/;
|
|
@@ -66332,9 +66332,14 @@ var init_dataset_archive = __esm(() => {
|
|
|
66332
66332
|
yaml: exports_external.string().min(1, "yaml content is required").max(1048576, "evaluator YAML exceeds 1 MB")
|
|
66333
66333
|
});
|
|
66334
66334
|
EvalResultsExportFormatSchema = exports_external.enum(["csv", "json"]);
|
|
66335
|
-
|
|
66335
|
+
BooleanQueryFlagSchema = exports_external.enum(["true", "false", "1", "0"]).optional().transform((value) => value === "true" || value === "1");
|
|
66336
|
+
ExperimentExportBaseQuerySchema = exports_external.object({
|
|
66336
66337
|
format: EvalResultsExportFormatSchema
|
|
66337
66338
|
});
|
|
66339
|
+
ExperimentExportAllQuerySchema = ExperimentExportBaseQuerySchema;
|
|
66340
|
+
ExperimentExportQuerySchema = ExperimentExportBaseQuerySchema.extend({
|
|
66341
|
+
includeTrace: BooleanQueryFlagSchema
|
|
66342
|
+
});
|
|
66338
66343
|
EvalResultsExportQuerySchema = ExperimentExportQuerySchema;
|
|
66339
66344
|
EvalResultExportRowSchema = exports_external.object({
|
|
66340
66345
|
executionId: exports_external.string().min(1),
|
|
@@ -68874,6 +68879,7 @@ __export(exports_src, {
|
|
|
68874
68879
|
ExtractInputSchema: () => ExtractInputSchema,
|
|
68875
68880
|
ExtractConfigSchema: () => ExtractConfigSchema,
|
|
68876
68881
|
ExperimentExportQuerySchema: () => ExperimentExportQuerySchema,
|
|
68882
|
+
ExperimentExportAllQuerySchema: () => ExperimentExportAllQuerySchema,
|
|
68877
68883
|
ExpectedOutputSchema: () => ExpectedOutputSchema,
|
|
68878
68884
|
ExpectedOutputFilesSchema: () => ExpectedOutputFilesSchema,
|
|
68879
68885
|
ExpectedErrorSchema: () => ExpectedErrorSchema,
|
|
@@ -183716,7 +183722,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
|
|
|
183716
183722
|
// package.json
|
|
183717
183723
|
var package_default = {
|
|
183718
183724
|
name: "@eigenpal/cli",
|
|
183719
|
-
version: "0.10.
|
|
183725
|
+
version: "0.10.16",
|
|
183720
183726
|
description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
|
|
183721
183727
|
keywords: [
|
|
183722
183728
|
"eigenpal",
|
|
@@ -184199,9 +184205,6 @@ function resolveProfileKey(name, profiles) {
|
|
|
184199
184205
|
|
|
184200
184206
|
// src/lib/ui.ts
|
|
184201
184207
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
184202
|
-
function isTTY() {
|
|
184203
|
-
return Boolean(process.stdout.isTTY);
|
|
184204
|
-
}
|
|
184205
184208
|
var ui = {
|
|
184206
184209
|
ok: import_picocolors.default.green,
|
|
184207
184210
|
err: import_picocolors.default.red,
|
|
@@ -190283,10 +190286,6 @@ function formatEigenpalDirIfAvailable(dir) {
|
|
|
190283
190286
|
});
|
|
190284
190287
|
}
|
|
190285
190288
|
|
|
190286
|
-
// src/commands/workflow/exec.ts
|
|
190287
|
-
init_src();
|
|
190288
|
-
import { join as join9 } from "path";
|
|
190289
|
-
|
|
190290
190289
|
// src/lib/execution-artifacts.ts
|
|
190291
190290
|
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
190292
190291
|
import { join as join7 } from "path";
|
|
@@ -190412,363 +190411,318 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
|
|
|
190412
190411
|
return executionsDir;
|
|
190413
190412
|
}
|
|
190414
190413
|
|
|
190415
|
-
// src/lib/
|
|
190416
|
-
|
|
190417
|
-
|
|
190418
|
-
|
|
190419
|
-
|
|
190420
|
-
|
|
190421
|
-
|
|
190422
|
-
|
|
190423
|
-
if (existsSync14(candidate))
|
|
190424
|
-
return candidate;
|
|
190414
|
+
// src/lib/grade-example.ts
|
|
190415
|
+
var MAX_VALUE_LEN = 60;
|
|
190416
|
+
function preview(value) {
|
|
190417
|
+
let text;
|
|
190418
|
+
try {
|
|
190419
|
+
text = typeof value === "string" ? value : JSON.stringify(value);
|
|
190420
|
+
} catch {
|
|
190421
|
+
text = String(value);
|
|
190425
190422
|
}
|
|
190426
|
-
|
|
190423
|
+
if (text === undefined)
|
|
190424
|
+
text = String(value);
|
|
190425
|
+
return text.length > MAX_VALUE_LEN ? `${text.slice(0, MAX_VALUE_LEN)}…` : text;
|
|
190427
190426
|
}
|
|
190428
|
-
function
|
|
190429
|
-
|
|
190430
|
-
if (!baseDir) {
|
|
190431
|
-
throw new Error(`No dataset/examples directory found at ${join8(dir, ...DATASET_EXAMPLES_DIR)}. Run \`eigenpal init workflow <name>\` to scaffold one.`);
|
|
190432
|
-
}
|
|
190433
|
-
const all = readdirSync4(baseDir).filter((name) => statSync4(join8(baseDir, name)).isDirectory() && existsSync14(join8(baseDir, name, "input.json"))).sort((a5, b8) => a5.localeCompare(b8, undefined, { numeric: true }));
|
|
190434
|
-
if (!exampleNamesFilter?.length)
|
|
190435
|
-
return all;
|
|
190436
|
-
return all.filter((n5) => exampleNamesFilter.includes(n5));
|
|
190427
|
+
function isPlainObject3(value) {
|
|
190428
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
190437
190429
|
}
|
|
190438
|
-
function
|
|
190439
|
-
|
|
190440
|
-
return readCanonicalInput(exampleDir, canonicalPath);
|
|
190430
|
+
function joinPath(path15, key2) {
|
|
190431
|
+
return path15 ? `${path15}.${key2}` : key2;
|
|
190441
190432
|
}
|
|
190442
|
-
function
|
|
190443
|
-
|
|
190444
|
-
|
|
190445
|
-
|
|
190446
|
-
|
|
190447
|
-
const scalars = {};
|
|
190448
|
-
const files = [];
|
|
190449
|
-
for (const [key2, value] of Object.entries(raw)) {
|
|
190450
|
-
const refs = topLevelFileRefs(value);
|
|
190451
|
-
if (refs.length === 0) {
|
|
190452
|
-
scalars[key2] = materializeNestedFileRefs(exampleDir, inputPath, value);
|
|
190453
|
-
continue;
|
|
190433
|
+
function walk2(expected, actual, path15, diffs) {
|
|
190434
|
+
if (Array.isArray(expected)) {
|
|
190435
|
+
if (!Array.isArray(actual)) {
|
|
190436
|
+
diffs.push(`${path15 || "(root)"}: expected array, got ${preview(actual)}`);
|
|
190437
|
+
return;
|
|
190454
190438
|
}
|
|
190455
|
-
|
|
190456
|
-
|
|
190457
|
-
if (!validation2.ok) {
|
|
190458
|
-
throw new Error(`${inputPath}: ${key2} must reference files under input/ without path traversal.`);
|
|
190459
|
-
}
|
|
190460
|
-
const relative3 = validation2.value.segments.slice(1).join("/");
|
|
190461
|
-
const filePath = join8(exampleDir, validation2.value.path);
|
|
190462
|
-
const filename = validation2.value.segments.at(-1) ?? relative3;
|
|
190463
|
-
files.push({
|
|
190464
|
-
argument: key2,
|
|
190465
|
-
filename,
|
|
190466
|
-
content: readFileSync13(filePath),
|
|
190467
|
-
mimeType: guessMimeType(filename)
|
|
190468
|
-
});
|
|
190439
|
+
if (expected.length !== actual.length) {
|
|
190440
|
+
diffs.push(`${path15 || "(root)"}: length ${expected.length} != ${actual.length}`);
|
|
190469
190441
|
}
|
|
190470
|
-
|
|
190471
|
-
|
|
190472
|
-
}
|
|
190473
|
-
function materializeNestedFileRefs(exampleDir, inputPath, value) {
|
|
190474
|
-
if (isScopedFileRef2(value)) {
|
|
190475
|
-
const validation2 = validateScopedArtifactPath(value.$file, { allowedRoots: ["input"] });
|
|
190476
|
-
if (!validation2.ok) {
|
|
190477
|
-
throw new Error(`${inputPath}: $file refs must reference files under input/.`);
|
|
190442
|
+
const overlap = Math.min(expected.length, actual.length);
|
|
190443
|
+
for (let i5 = 0;i5 < overlap; i5++) {
|
|
190444
|
+
walk2(expected[i5], actual[i5], `${path15}[${i5}]`, diffs);
|
|
190478
190445
|
}
|
|
190479
|
-
|
|
190480
|
-
const filePath = join8(exampleDir, validation2.value.path);
|
|
190481
|
-
return {
|
|
190482
|
-
$inline: {
|
|
190483
|
-
filename,
|
|
190484
|
-
mimeType: guessMimeType(filename) ?? "application/octet-stream",
|
|
190485
|
-
base64: readFileSync13(filePath).toString("base64")
|
|
190486
|
-
}
|
|
190487
|
-
};
|
|
190488
|
-
}
|
|
190489
|
-
if (Array.isArray(value)) {
|
|
190490
|
-
return value.map((item) => materializeNestedFileRefs(exampleDir, inputPath, item));
|
|
190446
|
+
return;
|
|
190491
190447
|
}
|
|
190492
|
-
if (
|
|
190493
|
-
if (
|
|
190494
|
-
|
|
190448
|
+
if (isPlainObject3(expected)) {
|
|
190449
|
+
if (!isPlainObject3(actual)) {
|
|
190450
|
+
diffs.push(`${path15 || "(root)"}: expected object, got ${preview(actual)}`);
|
|
190451
|
+
return;
|
|
190495
190452
|
}
|
|
190496
|
-
const
|
|
190497
|
-
|
|
190498
|
-
|
|
190453
|
+
for (const [key2, value] of Object.entries(expected)) {
|
|
190454
|
+
const childPath = joinPath(path15, key2);
|
|
190455
|
+
if (!(key2 in actual)) {
|
|
190456
|
+
diffs.push(`${childPath}: missing in output`);
|
|
190457
|
+
continue;
|
|
190458
|
+
}
|
|
190459
|
+
walk2(value, actual[key2], childPath, diffs);
|
|
190499
190460
|
}
|
|
190500
|
-
return
|
|
190501
|
-
}
|
|
190502
|
-
return value;
|
|
190503
|
-
}
|
|
190504
|
-
function topLevelFileRefs(value) {
|
|
190505
|
-
if (isScopedFileRef2(value))
|
|
190506
|
-
return [value.$file];
|
|
190507
|
-
if (hasFileKey(value)) {
|
|
190508
|
-
throw new Error('file refs must be exact { "$file": "input/..." } objects.');
|
|
190461
|
+
return;
|
|
190509
190462
|
}
|
|
190510
|
-
if (
|
|
190511
|
-
|
|
190512
|
-
if (Array.isArray(value) && value.some(hasFileKey)) {
|
|
190513
|
-
throw new Error('file arrays must contain only exact { "$file": "input/..." } entries.');
|
|
190463
|
+
if (!Object.is(expected, actual)) {
|
|
190464
|
+
diffs.push(`${path15 || "(root)"}: ${preview(expected)} != ${preview(actual)}`);
|
|
190514
190465
|
}
|
|
190515
|
-
return [];
|
|
190516
|
-
}
|
|
190517
|
-
function isScopedFileRef2(value) {
|
|
190518
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 1 && typeof value.$file === "string";
|
|
190519
190466
|
}
|
|
190520
|
-
function
|
|
190521
|
-
|
|
190467
|
+
function gradeAgainstExpected(expected, actual) {
|
|
190468
|
+
const diffs = [];
|
|
190469
|
+
walk2(expected, actual, "", diffs);
|
|
190470
|
+
return { matched: diffs.length === 0, diffs };
|
|
190522
190471
|
}
|
|
190523
|
-
|
|
190524
|
-
|
|
190525
|
-
|
|
190526
|
-
|
|
190527
|
-
|
|
190528
|
-
|
|
190529
|
-
|
|
190530
|
-
|
|
190472
|
+
|
|
190473
|
+
// src/lib/payload.ts
|
|
190474
|
+
import { existsSync as existsSync14, readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync4 } from "fs";
|
|
190475
|
+
import { join as join8 } from "path";
|
|
190476
|
+
var DATASET_EXAMPLES_DIR = ["dataset", "examples"];
|
|
190477
|
+
function resolveEvalBaseDir(dir) {
|
|
190478
|
+
const candidates = [join8(dir, ...DATASET_EXAMPLES_DIR), join8(...DATASET_EXAMPLES_DIR)];
|
|
190479
|
+
for (const candidate of candidates) {
|
|
190480
|
+
if (existsSync14(candidate))
|
|
190481
|
+
return candidate;
|
|
190531
190482
|
}
|
|
190532
190483
|
return null;
|
|
190533
190484
|
}
|
|
190534
|
-
function buildExamplePayload(exampleDir) {
|
|
190535
|
-
const { scalars, files } = readInput(exampleDir);
|
|
190536
|
-
return {
|
|
190537
|
-
scalars,
|
|
190538
|
-
files,
|
|
190539
|
-
overrides: readOverrides(exampleDir)
|
|
190540
|
-
};
|
|
190541
|
-
}
|
|
190542
190485
|
|
|
190543
|
-
// src/
|
|
190544
|
-
var
|
|
190545
|
-
var
|
|
190546
|
-
|
|
190547
|
-
|
|
190486
|
+
// src/commands/workflow/eval-example.ts
|
|
190487
|
+
var RUN_POLL_INTERVAL_MS = 2000;
|
|
190488
|
+
var RUN_MAX_WAIT_MS = 5 * 60 * 1000;
|
|
190489
|
+
var EVAL_GRACE_MS = 90 * 1000;
|
|
190490
|
+
var EVAL_POLL_INTERVAL_MS = 2000;
|
|
190491
|
+
var EXAMPLE_PAGE_SIZE = 100;
|
|
190492
|
+
var TERMINAL = new Set(["completed", "failed", "cancelled", "rejected", "timeout"]);
|
|
190493
|
+
function fmtScore(score) {
|
|
190494
|
+
return typeof score === "number" ? score.toFixed(2) : "n/a";
|
|
190548
190495
|
}
|
|
190549
|
-
function
|
|
190550
|
-
if (
|
|
190551
|
-
|
|
190496
|
+
function toNumberOrNull(value) {
|
|
190497
|
+
if (typeof value === "number")
|
|
190498
|
+
return Number.isFinite(value) ? value : null;
|
|
190499
|
+
if (typeof value === "string") {
|
|
190500
|
+
const parsed = Number(value);
|
|
190501
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
190502
|
+
}
|
|
190503
|
+
return null;
|
|
190552
190504
|
}
|
|
190553
|
-
function
|
|
190554
|
-
|
|
190555
|
-
process.stdout.write(`\x1B[${n5}B`);
|
|
190505
|
+
function runOutput(run) {
|
|
190506
|
+
return run.output !== undefined ? run.output : run.result?.output;
|
|
190556
190507
|
}
|
|
190557
|
-
function
|
|
190558
|
-
const
|
|
190559
|
-
|
|
190560
|
-
writeLineInPlace(text);
|
|
190561
|
-
cursorDown(up2);
|
|
190508
|
+
async function fetchHasEvaluators(client, workflowId) {
|
|
190509
|
+
const cfg = await client.get(`/api/v1/automations/${workflowId}/evaluators`);
|
|
190510
|
+
return Array.isArray(cfg.config?.evaluators) && cfg.config.evaluators.length > 0;
|
|
190562
190511
|
}
|
|
190563
|
-
function
|
|
190564
|
-
|
|
190565
|
-
|
|
190566
|
-
|
|
190567
|
-
|
|
190568
|
-
|
|
190569
|
-
|
|
190570
|
-
|
|
190571
|
-
|
|
190572
|
-
|
|
190573
|
-
|
|
190574
|
-
|
|
190575
|
-
|
|
190576
|
-
|
|
190577
|
-
|
|
190578
|
-
|
|
190579
|
-
|
|
190580
|
-
|
|
190581
|
-
}
|
|
190582
|
-
|
|
190583
|
-
|
|
190584
|
-
|
|
190585
|
-
|
|
190586
|
-
|
|
190587
|
-
process.stdout.write(`${label2} ${wait}
|
|
190588
|
-
`);
|
|
190589
|
-
}
|
|
190590
|
-
};
|
|
190591
|
-
const setRunning = (lineIndex, customLabel) => {
|
|
190592
|
-
if (!interactive)
|
|
190593
|
-
return;
|
|
190594
|
-
runningLabels.set(lineIndex, customLabel ?? runningLabel);
|
|
190595
|
-
if (spinnerInterval === null) {
|
|
190596
|
-
spinnerInterval = setInterval(() => {
|
|
190597
|
-
updateLock = updateLock.then(() => {
|
|
190598
|
-
if (runningLabels.size === 0) {
|
|
190599
|
-
if (spinnerInterval) {
|
|
190600
|
-
clearInterval(spinnerInterval);
|
|
190601
|
-
spinnerInterval = null;
|
|
190602
|
-
}
|
|
190603
|
-
return;
|
|
190604
|
-
}
|
|
190605
|
-
const frame = SPINNER_FRAMES[spinnerFrame++ % SPINNER_FRAMES.length];
|
|
190606
|
-
for (const [i5, label2] of runningLabels) {
|
|
190607
|
-
const lineLabel = lineLabels[i5] ?? "";
|
|
190608
|
-
updateLineAt(i5, totalLines, `${lineLabel} ${label2} ${spinnerStyle(frame)}`);
|
|
190609
|
-
}
|
|
190610
|
-
});
|
|
190611
|
-
}, SPINNER_INTERVAL_MS);
|
|
190512
|
+
async function resolveExample(client, workflowId, name) {
|
|
190513
|
+
let offset = 0;
|
|
190514
|
+
for (;; ) {
|
|
190515
|
+
const page = await client.get(`/api/v1/automations/${workflowId}/examples`, {
|
|
190516
|
+
limit: String(EXAMPLE_PAGE_SIZE),
|
|
190517
|
+
offset: String(offset)
|
|
190518
|
+
});
|
|
190519
|
+
const rows = page.data ?? [];
|
|
190520
|
+
const hit = rows.find((r5) => r5.name === name);
|
|
190521
|
+
if (hit)
|
|
190522
|
+
return { id: hit.id, expected: hit.expected };
|
|
190523
|
+
if (rows.length < EXAMPLE_PAGE_SIZE)
|
|
190524
|
+
return null;
|
|
190525
|
+
offset += rows.length;
|
|
190526
|
+
}
|
|
190527
|
+
}
|
|
190528
|
+
async function pollRunTerminal(client, runId) {
|
|
190529
|
+
const start = Date.now();
|
|
190530
|
+
const base = `/api/v1/runs/${encodeURIComponent(runId)}`;
|
|
190531
|
+
for (;; ) {
|
|
190532
|
+
const run = await client.get(base);
|
|
190533
|
+
const status = run.execution?.status ?? run.status;
|
|
190534
|
+
if (run.finished || status && TERMINAL.has(status)) {
|
|
190535
|
+
return await client.get(`${base}?expand=execution`);
|
|
190612
190536
|
}
|
|
190613
|
-
|
|
190614
|
-
|
|
190615
|
-
if (interactive) {
|
|
190616
|
-
runningLabels.delete(lineIndex);
|
|
190617
|
-
await scheduleUpdate(() => updateLineAt(lineIndex, totalLines, text));
|
|
190618
|
-
for (const line3 of extraLines)
|
|
190619
|
-
console.log(line3);
|
|
190620
|
-
} else {
|
|
190621
|
-
console.log(text);
|
|
190622
|
-
for (const line3 of extraLines)
|
|
190623
|
-
console.log(line3);
|
|
190537
|
+
if (Date.now() - start > RUN_MAX_WAIT_MS) {
|
|
190538
|
+
return { ...run, status: "timeout", execution: { status: "timeout" } };
|
|
190624
190539
|
}
|
|
190625
|
-
|
|
190626
|
-
|
|
190627
|
-
totalLines,
|
|
190628
|
-
start,
|
|
190629
|
-
setRunning,
|
|
190630
|
-
setDone
|
|
190631
|
-
};
|
|
190632
|
-
}
|
|
190633
|
-
|
|
190634
|
-
// src/commands/workflow/exec.ts
|
|
190635
|
-
var POLL_INTERVAL_MS = 2000;
|
|
190636
|
-
var MAX_POLL_MS = 5 * 60 * 1000;
|
|
190637
|
-
var DEFAULT_CONCURRENCY = 3;
|
|
190638
|
-
function runTerminalOutput(run) {
|
|
190639
|
-
return run.output !== undefined ? run.output : run.result?.output;
|
|
190640
|
-
}
|
|
190641
|
-
function runTerminalError(run) {
|
|
190642
|
-
const error52 = run.error !== undefined ? run.error : run.result?.error;
|
|
190643
|
-
return error52 ?? undefined;
|
|
190540
|
+
await new Promise((r5) => setTimeout(r5, RUN_POLL_INTERVAL_MS));
|
|
190541
|
+
}
|
|
190644
190542
|
}
|
|
190645
|
-
async function
|
|
190543
|
+
async function pollEvalRollup(client, runId) {
|
|
190646
190544
|
const start = Date.now();
|
|
190647
|
-
|
|
190648
|
-
const run = await client.get(`/api/v1/runs/${
|
|
190649
|
-
|
|
190650
|
-
|
|
190651
|
-
return {
|
|
190652
|
-
executionId: run.id,
|
|
190653
|
-
status: status ?? (run.error ? "failed" : "completed"),
|
|
190654
|
-
output: runTerminalOutput(run),
|
|
190655
|
-
error: runTerminalError(run)
|
|
190656
|
-
};
|
|
190545
|
+
for (;; ) {
|
|
190546
|
+
const run = await client.get(`/api/v1/runs/${encodeURIComponent(runId)}`);
|
|
190547
|
+
if (run.eval && run.eval.passed != null) {
|
|
190548
|
+
return { score: run.eval.score ?? null, passed: run.eval.passed };
|
|
190657
190549
|
}
|
|
190658
|
-
|
|
190550
|
+
if (Date.now() - start > EVAL_GRACE_MS)
|
|
190551
|
+
return null;
|
|
190552
|
+
await new Promise((r5) => setTimeout(r5, EVAL_POLL_INTERVAL_MS));
|
|
190659
190553
|
}
|
|
190660
|
-
return { executionId, status: "timeout", error: "Execution timed out" };
|
|
190661
190554
|
}
|
|
190662
|
-
function
|
|
190663
|
-
const
|
|
190555
|
+
async function fetchEvalRows(client, workflowId, batchId, runId) {
|
|
190556
|
+
const detail = await client.get(`/api/v1/automations/${workflowId}/experiments/${batchId}`);
|
|
190557
|
+
return detail.resultsByRun?.[runId] ?? [];
|
|
190558
|
+
}
|
|
190559
|
+
function toArtifactPayload(run, runId) {
|
|
190664
190560
|
return {
|
|
190665
|
-
executionId:
|
|
190666
|
-
status,
|
|
190561
|
+
executionId: runId,
|
|
190562
|
+
status: run.execution?.status ?? run.status ?? "unknown",
|
|
190667
190563
|
createdAt: run.timing?.createdAt ?? new Date().toISOString(),
|
|
190668
190564
|
completedAt: run.timing?.completedAt ?? null,
|
|
190669
190565
|
error: run.error !== undefined ? run.error : run.result?.error ?? null,
|
|
190670
|
-
output:
|
|
190671
|
-
stepExecutions:
|
|
190566
|
+
output: runOutput(run),
|
|
190567
|
+
stepExecutions: []
|
|
190672
190568
|
};
|
|
190673
190569
|
}
|
|
190674
|
-
async function
|
|
190675
|
-
const
|
|
190676
|
-
const
|
|
190677
|
-
|
|
190678
|
-
|
|
190679
|
-
const requested = options8.concurrencyOverride ?? DEFAULT_CONCURRENCY;
|
|
190680
|
-
const requestedValid = Number.isFinite(requested) && requested > 0 ? requested : DEFAULT_CONCURRENCY;
|
|
190681
|
-
const concurrency = Math.max(1, Math.min(requestedValid, names.length));
|
|
190570
|
+
async function runWorkflowExamplesWithEval(client, dir, workflowIdOrSlug, workflowId, exampleNames) {
|
|
190571
|
+
const hasEvaluators = await fetchHasEvaluators(client, workflowId);
|
|
190572
|
+
const mode = hasEvaluators ? "evaluators" : "diff";
|
|
190573
|
+
info(`Running ${ui.bold(`"${workflowIdOrSlug}"`)} ${ui.dim(`(${workflowId}, ${exampleNames.length} example(s))`)}`);
|
|
190574
|
+
dim(hasEvaluators ? "Server example run; grading with configured evaluators." : "Server example run; no evaluators configured, grading by structural diff vs expected.");
|
|
190682
190575
|
const evalBaseDir = resolveEvalBaseDir(dir);
|
|
190683
|
-
|
|
190684
|
-
|
|
190685
|
-
|
|
190686
|
-
dim("Using unified run endpoint.");
|
|
190687
|
-
const interactive = isTTY();
|
|
190688
|
-
const progress = createProgressLines({
|
|
190689
|
-
interactive,
|
|
190690
|
-
lineLabels: names,
|
|
190691
|
-
waitingLabel: "waiting",
|
|
190692
|
-
runningLabel: "running",
|
|
190693
|
-
dim: ui.dim,
|
|
190694
|
-
spinnerStyle: ui.info
|
|
190695
|
-
});
|
|
190696
|
-
progress.start();
|
|
190697
|
-
let passed = 0;
|
|
190698
|
-
let failed = 0;
|
|
190699
|
-
let nextIndex = 0;
|
|
190700
|
-
const reportDone = (index, label2) => {
|
|
190701
|
-
if (interactive)
|
|
190702
|
-
progress.setDone(index, label2);
|
|
190703
|
-
else
|
|
190704
|
-
console.log(label2);
|
|
190705
|
-
};
|
|
190706
|
-
const runOne = async () => {
|
|
190707
|
-
while (true) {
|
|
190708
|
-
const index = nextIndex++;
|
|
190709
|
-
if (index >= names.length)
|
|
190710
|
-
return;
|
|
190711
|
-
const name = names[index];
|
|
190712
|
-
const exampleDir = join9(evalBaseDir, name);
|
|
190713
|
-
try {
|
|
190714
|
-
const example = buildExamplePayload(exampleDir);
|
|
190715
|
-
if (interactive)
|
|
190716
|
-
progress.setRunning(index);
|
|
190717
|
-
else
|
|
190718
|
-
console.log(`${ui.dim("→")} ${name}`);
|
|
190719
|
-
const form = await buildRunFormData({
|
|
190720
|
-
target: runStartMultipartTarget({
|
|
190721
|
-
type: "workflow",
|
|
190722
|
-
id: workflowId,
|
|
190723
|
-
version: options8.version
|
|
190724
|
-
}),
|
|
190725
|
-
input: example.scalars,
|
|
190726
|
-
overrides: example.overrides,
|
|
190727
|
-
files: example.files.map((file2) => ({
|
|
190728
|
-
fieldName: file2.argument,
|
|
190729
|
-
content: file2.content,
|
|
190730
|
-
filename: file2.filename,
|
|
190731
|
-
mimeType: file2.mimeType
|
|
190732
|
-
}))
|
|
190733
|
-
});
|
|
190734
|
-
const res = await client.postFormData(runTargetApiPath({ type: "workflow", id: workflowId, version: options8.version }), form);
|
|
190735
|
-
if (typeof res?.id !== "string") {
|
|
190736
|
-
throw new Error("Run API did not return a run id");
|
|
190737
|
-
}
|
|
190738
|
-
const executionId = res.id;
|
|
190739
|
-
process.stderr.write(` ${ui.dim(`→ ${name}: ${executionId}`)}
|
|
190576
|
+
const results = [];
|
|
190577
|
+
for (const name of exampleNames) {
|
|
190578
|
+
process.stderr.write(`${ui.dim("→")} ${name}
|
|
190740
190579
|
`);
|
|
190741
|
-
|
|
190742
|
-
|
|
190743
|
-
|
|
190744
|
-
|
|
190745
|
-
|
|
190746
|
-
|
|
190747
|
-
|
|
190748
|
-
|
|
190749
|
-
|
|
190750
|
-
|
|
190751
|
-
|
|
190752
|
-
|
|
190753
|
-
|
|
190754
|
-
|
|
190580
|
+
try {
|
|
190581
|
+
const example = await resolveExample(client, workflowId, name);
|
|
190582
|
+
if (!example) {
|
|
190583
|
+
throw new Error(`example "${name}" not found in the server dataset for ${workflowId}. ` + `Push it first: eigenpal workflow dataset push ${workflowId}`);
|
|
190584
|
+
}
|
|
190585
|
+
const started = await client.post(`/api/v1/automations/${workflowId}/examples/${example.id}/run`, {});
|
|
190586
|
+
const runId = started.id;
|
|
190587
|
+
if (typeof runId !== "string")
|
|
190588
|
+
throw new Error("Example run did not return a run id");
|
|
190589
|
+
process.stderr.write(` ${ui.dim(`run: ${runId}`)}
|
|
190590
|
+
`);
|
|
190591
|
+
const run = await pollRunTerminal(client, runId);
|
|
190592
|
+
const status = run.execution?.status ?? run.status;
|
|
190593
|
+
const runOk = status === "completed";
|
|
190594
|
+
const result = {
|
|
190595
|
+
name,
|
|
190596
|
+
exampleId: example.id,
|
|
190597
|
+
executionId: runId,
|
|
190598
|
+
run: runOk ? "ok" : "error",
|
|
190599
|
+
runError: runOk ? undefined : run.error ?? status ?? "unknown",
|
|
190600
|
+
mode: "none"
|
|
190601
|
+
};
|
|
190602
|
+
if (runOk && hasEvaluators && started.batchId) {
|
|
190603
|
+
const rollup = await pollEvalRollup(client, runId);
|
|
190604
|
+
if (rollup) {
|
|
190605
|
+
const rows = await fetchEvalRows(client, workflowId, started.batchId, runId);
|
|
190606
|
+
result.mode = "evaluators";
|
|
190607
|
+
result.score = rollup.score;
|
|
190608
|
+
result.passed = rollup.passed;
|
|
190609
|
+
result.evaluators = rows.map((r5) => ({
|
|
190610
|
+
name: r5.evaluatorName ?? "evaluator",
|
|
190611
|
+
score: toNumberOrNull(r5.score),
|
|
190612
|
+
passed: r5.passed ?? null,
|
|
190613
|
+
weight: toNumberOrNull(r5.weight),
|
|
190614
|
+
error: r5.error ?? null
|
|
190615
|
+
}));
|
|
190616
|
+
} else {
|
|
190617
|
+
warn(` ${name}: no evaluator score after ${EVAL_GRACE_MS / 1000}s; grading by diff.`);
|
|
190618
|
+
gradeByDiff(result, example.expected, runOutput(run));
|
|
190755
190619
|
}
|
|
190756
|
-
}
|
|
190757
|
-
|
|
190758
|
-
|
|
190620
|
+
} else if (runOk) {
|
|
190621
|
+
gradeByDiff(result, example.expected, runOutput(run));
|
|
190622
|
+
}
|
|
190623
|
+
results.push(result);
|
|
190624
|
+
reportLine(result);
|
|
190625
|
+
if (evalBaseDir) {
|
|
190626
|
+
try {
|
|
190627
|
+
await writeExecutionArtifacts(client, `${evalBaseDir}/${name}`, toArtifactPayload(run, runId));
|
|
190628
|
+
} catch {}
|
|
190759
190629
|
}
|
|
190630
|
+
} catch (err2) {
|
|
190631
|
+
const result = {
|
|
190632
|
+
name,
|
|
190633
|
+
run: "error",
|
|
190634
|
+
runError: formatCliError(err2),
|
|
190635
|
+
mode: "none"
|
|
190636
|
+
};
|
|
190637
|
+
results.push(result);
|
|
190638
|
+
reportLine(result);
|
|
190760
190639
|
}
|
|
190761
|
-
}
|
|
190762
|
-
const
|
|
190763
|
-
|
|
190764
|
-
|
|
190765
|
-
|
|
190640
|
+
}
|
|
190641
|
+
const summary = summarize(workflowIdOrSlug, mode, results);
|
|
190642
|
+
process.stderr.write(`
|
|
190643
|
+
${formatEvalSummary(summary)}
|
|
190644
|
+
`);
|
|
190645
|
+
return summary;
|
|
190646
|
+
}
|
|
190647
|
+
function gradeByDiff(result, expected, output) {
|
|
190648
|
+
if (expected === undefined || expected === null) {
|
|
190649
|
+
result.mode = "none";
|
|
190650
|
+
return;
|
|
190651
|
+
}
|
|
190652
|
+
const graded = gradeAgainstExpected(expected, output);
|
|
190653
|
+
result.mode = "diff";
|
|
190654
|
+
result.matched = graded.matched;
|
|
190655
|
+
result.diffCount = graded.diffs.length;
|
|
190656
|
+
result.diffs = graded.diffs.length ? graded.diffs : undefined;
|
|
190657
|
+
}
|
|
190658
|
+
function formatExampleLines(result) {
|
|
190659
|
+
if (result.run === "error") {
|
|
190660
|
+
return `${result.name} ${ui.err(`err ${result.runError ?? ""}`.trimEnd())}`;
|
|
190661
|
+
}
|
|
190662
|
+
if (result.mode === "evaluators") {
|
|
190663
|
+
const verdict = result.passed === true ? ui.ok("PASS") : ui.err("FAIL");
|
|
190664
|
+
const head = `${result.name} ${ui.ok("ok")} score ${fmtScore(result.score)} ${verdict}`;
|
|
190665
|
+
const detail = (result.evaluators ?? []).map((e8) => {
|
|
190666
|
+
const mark = e8.error ? ui.warn("error") : e8.passed === true ? ui.ok("pass") : e8.passed === false ? ui.err("fail") : ui.dim("n/a");
|
|
190667
|
+
return ` ${e8.name} ${fmtScore(e8.score)} ${mark}`;
|
|
190668
|
+
});
|
|
190669
|
+
return [head, ...detail].join(`
|
|
190670
|
+
`);
|
|
190671
|
+
}
|
|
190672
|
+
if (result.mode === "diff") {
|
|
190673
|
+
const verdict = result.matched ? ui.ok("PASS") : ui.err(`FAIL (${result.diffCount} diff)`);
|
|
190674
|
+
return `${result.name} ${ui.ok("ok")} ${verdict}`;
|
|
190675
|
+
}
|
|
190676
|
+
return `${result.name} ${ui.ok("ok")} ${ui.dim("-")}`;
|
|
190677
|
+
}
|
|
190678
|
+
function reportLine(result) {
|
|
190679
|
+
process.stderr.write(`${formatExampleLines(result)}
|
|
190680
|
+
`);
|
|
190681
|
+
}
|
|
190682
|
+
function summarize(workflow2, mode, examples) {
|
|
190683
|
+
const ok2 = examples.filter((r5) => r5.run === "ok").length;
|
|
190684
|
+
const errored = examples.length - ok2;
|
|
190685
|
+
const gradedResults = examples.filter((r5) => r5.mode === "evaluators" || r5.mode === "diff");
|
|
190686
|
+
const passedCases = gradedResults.filter((r5) => r5.mode === "evaluators" ? r5.passed === true : r5.matched === true).length;
|
|
190687
|
+
const scores = gradedResults.filter((r5) => r5.mode === "evaluators" && typeof r5.score === "number").map((r5) => r5.score);
|
|
190766
190688
|
return {
|
|
190767
|
-
workflow:
|
|
190768
|
-
|
|
190769
|
-
|
|
190770
|
-
|
|
190771
|
-
|
|
190689
|
+
workflow: workflow2,
|
|
190690
|
+
mode,
|
|
190691
|
+
total: examples.length,
|
|
190692
|
+
ok: ok2,
|
|
190693
|
+
errored,
|
|
190694
|
+
graded: gradedResults.length,
|
|
190695
|
+
passedCases,
|
|
190696
|
+
failedCases: gradedResults.length - passedCases,
|
|
190697
|
+
ungraded: ok2 - gradedResults.length,
|
|
190698
|
+
weightedAvg: scores.length ? scores.reduce((s5, n5) => s5 + n5, 0) / scores.length : null,
|
|
190699
|
+
examples,
|
|
190700
|
+
passed: ok2,
|
|
190701
|
+
failed: errored
|
|
190702
|
+
};
|
|
190703
|
+
}
|
|
190704
|
+
function formatEvalSummary(summary) {
|
|
190705
|
+
const lines = [];
|
|
190706
|
+
let line3 = `${ui.bold("Ran")} ${summary.total}: ${ui.ok(`${summary.ok} ok`)}`;
|
|
190707
|
+
if (summary.errored > 0)
|
|
190708
|
+
line3 += `, ${ui.err(`${summary.errored} errored`)}`;
|
|
190709
|
+
if (summary.graded > 0) {
|
|
190710
|
+
const allPass = summary.failedCases === 0;
|
|
190711
|
+
if (summary.mode === "evaluators") {
|
|
190712
|
+
const cases = `${summary.passedCases}/${summary.graded} cases pass`;
|
|
190713
|
+
const weighted = summary.weightedAvg != null ? `weighted ${summary.weightedAvg.toFixed(2)}, ` : "";
|
|
190714
|
+
line3 += ` ${ui.dim("/")} ${weighted}${allPass ? ui.ok(cases) : ui.err(cases)}`;
|
|
190715
|
+
} else {
|
|
190716
|
+
const acc = `${summary.passedCases}/${summary.graded} matched`;
|
|
190717
|
+
line3 += ` ${ui.dim("/")} accuracy ${allPass ? ui.ok(acc) : ui.err(acc)}`;
|
|
190718
|
+
}
|
|
190719
|
+
}
|
|
190720
|
+
lines.push(line3);
|
|
190721
|
+
if (summary.ungraded > 0) {
|
|
190722
|
+
lines.push(ui.dim(` ${summary.ungraded} ungraded (no stored expected output)`));
|
|
190723
|
+
}
|
|
190724
|
+
return lines.join(`
|
|
190725
|
+
`);
|
|
190772
190726
|
}
|
|
190773
190727
|
|
|
190774
190728
|
// src/commands/workflow/execution.ts
|
|
@@ -190777,13 +190731,16 @@ async function runSavedWorkflowExamples(workflow2, examples, opts) {
|
|
|
190777
190731
|
try {
|
|
190778
190732
|
requireApiKey(config2);
|
|
190779
190733
|
const client = new ApiClient(config2);
|
|
190780
|
-
const
|
|
190781
|
-
|
|
190782
|
-
version
|
|
190783
|
-
}
|
|
190734
|
+
const workflowId = await resolveWorkflowId(client, workflow2);
|
|
190735
|
+
if (opts.version && !["latest", "current", "undefined"].includes(opts.version)) {
|
|
190736
|
+
warn(`--example runs the current published version; ignoring @${opts.version}.`);
|
|
190737
|
+
}
|
|
190738
|
+
const summary = await runWorkflowExamplesWithEval(client, config2.dir, workflow2, workflowId, examples);
|
|
190784
190739
|
if (opts.json)
|
|
190785
190740
|
console.log(JSON.stringify(summary, null, 2));
|
|
190786
|
-
if (summary.
|
|
190741
|
+
if (summary.errored > 0)
|
|
190742
|
+
process.exit(1);
|
|
190743
|
+
if (opts.failOnMismatch && summary.failedCases > 0)
|
|
190787
190744
|
process.exit(1);
|
|
190788
190745
|
} catch (err2) {
|
|
190789
190746
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
@@ -190796,7 +190753,23 @@ async function runSavedWorkflowExamples(workflow2, examples, opts) {
|
|
|
190796
190753
|
|
|
190797
190754
|
// src/commands/run.ts
|
|
190798
190755
|
function registerRunCommands(program2) {
|
|
190799
|
-
addJsonFlag(withBaseUrl(program2.command("run <target>"))).description("Start a workflow or agent run, e.g. workflows.extract-invoice.").option("--input-json <json>", "JSON input object").option("--input-file <field=path>", 'Input file to upload as multipart form-data. Repeat for multiple files; bare paths use field "file".', collectRepeated, []).option("--example <name>", "Run one persisted example by name").option("--dir <dir>", "Local eigenpal directory for workflow examples", undefined).option("--wait", "Poll until the run reaches a terminal status").option("--interval <seconds>", "Polling interval in seconds", intArg, 2).option("--max-wait <seconds>", "Maximum wait before exit code 2", intArg, 1800).action(action(runTarget))
|
|
190756
|
+
addJsonFlag(withBaseUrl(program2.command("run <target>"))).description("Start a workflow or agent run, e.g. workflows.extract-invoice.").option("--input-json <json>", "JSON input object").option("--input-file <field=path>", 'Input file to upload as multipart form-data. Repeat for multiple files; bare paths use field "file".', collectRepeated, []).option("--example <name>", "Run one persisted example by name").option("--dir <dir>", "Local eigenpal directory for workflow examples", undefined).option("--fail-on-mismatch", "For --example runs, exit non-zero when a graded example fails (evaluator fail, or output mismatch)").option("--wait", "Poll until the run reaches a terminal status").option("--interval <seconds>", "Polling interval in seconds", intArg, 2).option("--max-wait <seconds>", "Maximum wait before exit code 2", intArg, 1800).action(action(runTarget)).addHelpText("after", `
|
|
190757
|
+
Grading --example runs
|
|
190758
|
+
--example runs the workflow's CURRENT published version on the SERVER's stored
|
|
190759
|
+
dataset example, so push your latest dataset/evaluators first
|
|
190760
|
+
(eigenpal workflow dataset push / evaluators push).
|
|
190761
|
+
|
|
190762
|
+
If the workflow has evaluators configured, they run automatically and the CLI
|
|
190763
|
+
shows the real weighted score and per-evaluator pass/fail. If it has no
|
|
190764
|
+
evaluators, the output is graded by a structural diff against the example's
|
|
190765
|
+
stored expected output (every expected field must be present and equal; extra
|
|
190766
|
+
output fields are ignored, arrays match by index). The summary reports two
|
|
190767
|
+
separate signals: execution health ("ok"/"errored") and accuracy.
|
|
190768
|
+
|
|
190769
|
+
Exit codes
|
|
190770
|
+
1 a run errored (or, with --fail-on-mismatch, a graded example failed)
|
|
190771
|
+
By default a grading failure is informational and does not change the exit code.
|
|
190772
|
+
`);
|
|
190800
190773
|
addJsonFlag(withBaseUrl(program2.command("rerun <run-id>"))).description("Create a new run from a previous run's stored input snapshot.").option("--version <version>", "Version/source ref for the new run: latest, original, or an explicit ref", "latest").option("--wait", "Poll until the rerun reaches a terminal status").option("--interval <seconds>", "Polling interval in seconds", intArg, 2).option("--max-wait <seconds>", "Maximum wait before exit code 2", intArg, 1800).action(action(rerunTarget));
|
|
190801
190774
|
}
|
|
190802
190775
|
async function runTarget(target, opts) {
|
|
@@ -190814,7 +190787,8 @@ async function runTarget(target, opts) {
|
|
|
190814
190787
|
}
|
|
190815
190788
|
return runSavedWorkflowExamples(parsed.idOrSlug, [opts.example], {
|
|
190816
190789
|
...opts,
|
|
190817
|
-
version: String(parsed.requestedVersion)
|
|
190790
|
+
version: String(parsed.requestedVersion),
|
|
190791
|
+
failOnMismatch: opts.failOnMismatch
|
|
190818
190792
|
});
|
|
190819
190793
|
}
|
|
190820
190794
|
const client = buildClient(opts);
|
|
@@ -190859,73 +190833,73 @@ import {
|
|
|
190859
190833
|
unlinkSync as unlinkSync2,
|
|
190860
190834
|
writeFileSync as writeFileSync8
|
|
190861
190835
|
} from "node:fs";
|
|
190862
|
-
import { sep as PATH_SEP, dirname as dirname5, join as
|
|
190836
|
+
import { sep as PATH_SEP, dirname as dirname5, join as join10, relative as relative3, resolve as resolve5 } from "node:path";
|
|
190863
190837
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
190864
190838
|
|
|
190865
190839
|
// src/commands/skill/tools.ts
|
|
190866
|
-
import { join as
|
|
190840
|
+
import { join as join9 } from "node:path";
|
|
190867
190841
|
var SKILL_NAME = "eigenpal";
|
|
190868
190842
|
var TOOLS = [
|
|
190869
190843
|
{
|
|
190870
190844
|
id: "claude",
|
|
190871
190845
|
label: "Claude Code",
|
|
190872
|
-
relativePath:
|
|
190846
|
+
relativePath: join9(".claude", "skills", SKILL_NAME),
|
|
190873
190847
|
detectPaths: [".claude", "CLAUDE.md"]
|
|
190874
190848
|
},
|
|
190875
190849
|
{
|
|
190876
190850
|
id: "cursor",
|
|
190877
190851
|
label: "Cursor",
|
|
190878
|
-
relativePath:
|
|
190852
|
+
relativePath: join9(".cursor", "skills", SKILL_NAME),
|
|
190879
190853
|
detectPaths: [".cursor", ".cursorrules"]
|
|
190880
190854
|
},
|
|
190881
190855
|
{
|
|
190882
190856
|
id: "codex",
|
|
190883
190857
|
label: "Codex",
|
|
190884
|
-
relativePath:
|
|
190858
|
+
relativePath: join9(".codex", "skills", SKILL_NAME),
|
|
190885
190859
|
detectPaths: [".codex"]
|
|
190886
190860
|
},
|
|
190887
190861
|
{
|
|
190888
190862
|
id: "gemini",
|
|
190889
190863
|
label: "Gemini CLI",
|
|
190890
|
-
relativePath:
|
|
190864
|
+
relativePath: join9(".gemini", "skills", SKILL_NAME),
|
|
190891
190865
|
detectPaths: [".gemini", "GEMINI.md"]
|
|
190892
190866
|
},
|
|
190893
190867
|
{
|
|
190894
190868
|
id: "antigravity",
|
|
190895
190869
|
label: "Antigravity",
|
|
190896
|
-
relativePath:
|
|
190870
|
+
relativePath: join9(".agent", "skills", SKILL_NAME),
|
|
190897
190871
|
detectPaths: [".agent"]
|
|
190898
190872
|
},
|
|
190899
190873
|
{
|
|
190900
190874
|
id: "opencode",
|
|
190901
190875
|
label: "OpenCode",
|
|
190902
|
-
relativePath:
|
|
190876
|
+
relativePath: join9(".opencode", "skills", SKILL_NAME),
|
|
190903
190877
|
detectPaths: [".opencode"]
|
|
190904
190878
|
},
|
|
190905
190879
|
{
|
|
190906
190880
|
id: "pi",
|
|
190907
190881
|
label: "Pi",
|
|
190908
|
-
relativePath:
|
|
190882
|
+
relativePath: join9(".pi", "skills", SKILL_NAME),
|
|
190909
190883
|
detectPaths: [".pi"]
|
|
190910
190884
|
},
|
|
190911
190885
|
{
|
|
190912
190886
|
id: "windsurf",
|
|
190913
190887
|
label: "Windsurf",
|
|
190914
|
-
relativePath:
|
|
190888
|
+
relativePath: join9(".windsurf", "skills", SKILL_NAME),
|
|
190915
190889
|
detectPaths: [".windsurf", ".windsurfrules"]
|
|
190916
190890
|
},
|
|
190917
190891
|
{
|
|
190918
190892
|
id: "github-copilot",
|
|
190919
190893
|
label: "GitHub Copilot",
|
|
190920
|
-
relativePath:
|
|
190894
|
+
relativePath: join9(".github", "skills", SKILL_NAME),
|
|
190921
190895
|
detectPaths: [
|
|
190922
|
-
|
|
190923
|
-
|
|
190924
|
-
|
|
190925
|
-
|
|
190926
|
-
|
|
190927
|
-
|
|
190928
|
-
|
|
190896
|
+
join9(".github", "copilot-instructions.md"),
|
|
190897
|
+
join9(".github", "instructions"),
|
|
190898
|
+
join9(".github", "prompts"),
|
|
190899
|
+
join9(".github", "agents"),
|
|
190900
|
+
join9(".github", "skills"),
|
|
190901
|
+
join9(".github", "workflows", "copilot-setup-steps.yml"),
|
|
190902
|
+
join9(".github", ".mcp.json")
|
|
190929
190903
|
]
|
|
190930
190904
|
}
|
|
190931
190905
|
];
|
|
@@ -190945,7 +190919,7 @@ function resolveSkillSource() {
|
|
|
190945
190919
|
${distCandidate}`);
|
|
190946
190920
|
}
|
|
190947
190921
|
function defaultClaudeTarget() {
|
|
190948
|
-
return
|
|
190922
|
+
return join10(process.cwd(), TOOLS[0].relativePath);
|
|
190949
190923
|
}
|
|
190950
190924
|
function resolveSkillTarget(opts) {
|
|
190951
190925
|
return opts.target ?? defaultClaudeTarget();
|
|
@@ -190973,8 +190947,8 @@ async function installSkill(opts) {
|
|
|
190973
190947
|
let skipped = 0;
|
|
190974
190948
|
let prompted = 0;
|
|
190975
190949
|
for (const relativePath of sourceFiles) {
|
|
190976
|
-
const sourcePath =
|
|
190977
|
-
const targetPath =
|
|
190950
|
+
const sourcePath = join10(source2, relativePath);
|
|
190951
|
+
const targetPath = join10(target, relativePath);
|
|
190978
190952
|
const sourceBytes = templateSourceFile(relativePath, readFileSync14(sourcePath), cliVersion);
|
|
190979
190953
|
const sourceHash = sha2562(sourceBytes);
|
|
190980
190954
|
if (!existsSync15(targetPath)) {
|
|
@@ -191011,7 +190985,7 @@ async function installSkill(opts) {
|
|
|
191011
190985
|
}
|
|
191012
190986
|
const manifestEntries = [];
|
|
191013
190987
|
for (const relativePath of sourceFiles) {
|
|
191014
|
-
const targetPath =
|
|
190988
|
+
const targetPath = join10(target, relativePath);
|
|
191015
190989
|
if (!existsSync15(targetPath))
|
|
191016
190990
|
continue;
|
|
191017
190991
|
manifestEntries.push({ path: relativePath, sha256: sha2562(readFileSync14(targetPath)) });
|
|
@@ -191021,7 +190995,7 @@ async function installSkill(opts) {
|
|
|
191021
190995
|
installedAt: new Date().toISOString(),
|
|
191022
190996
|
files: manifestEntries
|
|
191023
190997
|
};
|
|
191024
|
-
writeFileSync8(
|
|
190998
|
+
writeFileSync8(join10(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
|
|
191025
190999
|
`);
|
|
191026
191000
|
const displayTarget = relative3(process.cwd(), target) || target;
|
|
191027
191001
|
success2(`Installed skill at ${ui.bold(displayTarget)} — ${written} written, ${skipped} unchanged${prompted > 0 ? `, ${prompted} prompted` : ""}.`);
|
|
@@ -191030,7 +191004,7 @@ async function uninstallSkill(opts) {
|
|
|
191030
191004
|
const target = resolveSkillTarget(opts);
|
|
191031
191005
|
const manifest = readManifest(target);
|
|
191032
191006
|
if (!manifest) {
|
|
191033
|
-
error51(`No manifest found at ${
|
|
191007
|
+
error51(`No manifest found at ${join10(target, MANIFEST_NAME)}; nothing to uninstall.`);
|
|
191034
191008
|
process.exit(1);
|
|
191035
191009
|
}
|
|
191036
191010
|
if (!opts.yes && process.stdin.isTTY) {
|
|
@@ -191063,7 +191037,7 @@ async function uninstallSkill(opts) {
|
|
|
191063
191037
|
unlinkSync2(path15);
|
|
191064
191038
|
removed += 1;
|
|
191065
191039
|
}
|
|
191066
|
-
rmSync2(
|
|
191040
|
+
rmSync2(join10(target, MANIFEST_NAME), { force: true });
|
|
191067
191041
|
pruneEmptyDirs(target);
|
|
191068
191042
|
const displayTarget = relative3(process.cwd(), target) || target;
|
|
191069
191043
|
success2(`Uninstalled skill from ${ui.bold(displayTarget)} — ${removed} removed${kept > 0 ? `, ${kept} user-edited kept` : ""}.`);
|
|
@@ -191124,14 +191098,14 @@ async function installSkillTools(opts) {
|
|
|
191124
191098
|
for (const tool of toInstall) {
|
|
191125
191099
|
await installSkill({
|
|
191126
191100
|
source: opts.source,
|
|
191127
|
-
target:
|
|
191101
|
+
target: join10(cwd, tool.relativePath),
|
|
191128
191102
|
force: opts.force,
|
|
191129
191103
|
yes: opts.yes
|
|
191130
191104
|
});
|
|
191131
191105
|
}
|
|
191132
191106
|
for (const tool of toUninstall) {
|
|
191133
191107
|
await uninstallSkill({
|
|
191134
|
-
target:
|
|
191108
|
+
target: join10(cwd, tool.relativePath),
|
|
191135
191109
|
yes: true
|
|
191136
191110
|
});
|
|
191137
191111
|
}
|
|
@@ -191194,7 +191168,7 @@ async function uninstallSkillTools(opts) {
|
|
|
191194
191168
|
}
|
|
191195
191169
|
for (const tool of targets) {
|
|
191196
191170
|
await uninstallSkill({
|
|
191197
|
-
target:
|
|
191171
|
+
target: join10(cwd, tool.relativePath),
|
|
191198
191172
|
yes: true
|
|
191199
191173
|
});
|
|
191200
191174
|
}
|
|
@@ -191202,7 +191176,7 @@ async function uninstallSkillTools(opts) {
|
|
|
191202
191176
|
function listSkillTools(opts = {}) {
|
|
191203
191177
|
const cwd = process.cwd();
|
|
191204
191178
|
const rows = TOOLS.flatMap((tool) => {
|
|
191205
|
-
const targetDir =
|
|
191179
|
+
const targetDir = join10(cwd, tool.relativePath);
|
|
191206
191180
|
const manifest = readManifest(targetDir);
|
|
191207
191181
|
if (!manifest)
|
|
191208
191182
|
return [];
|
|
@@ -191255,10 +191229,10 @@ function hintFor(tool, installed, detected) {
|
|
|
191255
191229
|
return tool.relativePath;
|
|
191256
191230
|
}
|
|
191257
191231
|
function isInstalled(cwd, tool) {
|
|
191258
|
-
return existsSync15(
|
|
191232
|
+
return existsSync15(join10(cwd, tool.relativePath, MANIFEST_NAME));
|
|
191259
191233
|
}
|
|
191260
191234
|
function isProjectUsing(cwd, tool) {
|
|
191261
|
-
return tool.detectPaths.some((p4) => existsSync15(
|
|
191235
|
+
return tool.detectPaths.some((p4) => existsSync15(join10(cwd, p4)));
|
|
191262
191236
|
}
|
|
191263
191237
|
function listFiles(root2) {
|
|
191264
191238
|
const out = [];
|
|
@@ -191266,7 +191240,7 @@ function listFiles(root2) {
|
|
|
191266
191240
|
while (stack2.length > 0) {
|
|
191267
191241
|
const dir = stack2.pop();
|
|
191268
191242
|
for (const entry of readdirSync5(dir)) {
|
|
191269
|
-
const full =
|
|
191243
|
+
const full = join10(dir, entry);
|
|
191270
191244
|
const rel = relative3(root2, full);
|
|
191271
191245
|
const stats = lstatSync(full);
|
|
191272
191246
|
if (stats.isDirectory()) {
|
|
@@ -191281,7 +191255,7 @@ function listFiles(root2) {
|
|
|
191281
191255
|
return out.sort();
|
|
191282
191256
|
}
|
|
191283
191257
|
function readManifest(target) {
|
|
191284
|
-
const path15 =
|
|
191258
|
+
const path15 = join10(target, MANIFEST_NAME);
|
|
191285
191259
|
if (!existsSync15(path15))
|
|
191286
191260
|
return null;
|
|
191287
191261
|
try {
|
|
@@ -191316,7 +191290,7 @@ function pruneEmptyDirs(root2) {
|
|
|
191316
191290
|
const stack2 = [];
|
|
191317
191291
|
const collect = (dir) => {
|
|
191318
191292
|
for (const entry of readdirSync5(dir)) {
|
|
191319
|
-
const full =
|
|
191293
|
+
const full = join10(dir, entry);
|
|
191320
191294
|
if (lstatSync(full).isDirectory())
|
|
191321
191295
|
collect(full);
|
|
191322
191296
|
}
|
|
@@ -191462,12 +191436,12 @@ import { createInterface as createInterface3 } from "node:readline/promises";
|
|
|
191462
191436
|
|
|
191463
191437
|
// src/commands/workflow/clear.ts
|
|
191464
191438
|
import { existsSync as existsSync16, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync5 } from "fs";
|
|
191465
|
-
import { basename, join as
|
|
191439
|
+
import { basename, join as join11 } from "path";
|
|
191466
191440
|
var EMPTY_REPORT = { removed: 0, kept: 0, touched: 0 };
|
|
191467
191441
|
function getDirectoryEntries(path15) {
|
|
191468
191442
|
if (!existsSync16(path15))
|
|
191469
191443
|
return [];
|
|
191470
|
-
return readdirSync6(path15).filter((entry) => statSync5(
|
|
191444
|
+
return readdirSync6(path15).filter((entry) => statSync5(join11(path15, entry)).isDirectory()).sort();
|
|
191471
191445
|
}
|
|
191472
191446
|
function removeDirEntriesWithRetention(path15, removeAll) {
|
|
191473
191447
|
const entries = getDirectoryEntries(path15);
|
|
@@ -191480,7 +191454,7 @@ function removeDirEntriesWithRetention(path15, removeAll) {
|
|
|
191480
191454
|
for (const entry of entries) {
|
|
191481
191455
|
if (keepSet.has(entry))
|
|
191482
191456
|
continue;
|
|
191483
|
-
rmSync3(
|
|
191457
|
+
rmSync3(join11(path15, entry), { recursive: true, force: true });
|
|
191484
191458
|
removed++;
|
|
191485
191459
|
}
|
|
191486
191460
|
return { removed, kept: keepSet.size, touched: entries.length };
|
|
@@ -191507,7 +191481,7 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
|
|
|
191507
191481
|
kept++;
|
|
191508
191482
|
continue;
|
|
191509
191483
|
}
|
|
191510
|
-
rmSync3(
|
|
191484
|
+
rmSync3(join11(exampleDir, fileName), { force: true });
|
|
191511
191485
|
removed++;
|
|
191512
191486
|
}
|
|
191513
191487
|
return { removed, kept, touched: stampByFile.size };
|
|
@@ -191515,17 +191489,17 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
|
|
|
191515
191489
|
function getTargetExampleDirs(dir, exampleNames) {
|
|
191516
191490
|
const baseDir = resolveEvalBaseDir(dir);
|
|
191517
191491
|
if (!baseDir) {
|
|
191518
|
-
error51(`No dataset/examples directory at ${
|
|
191492
|
+
error51(`No dataset/examples directory at ${join11(dir, "dataset", "examples")}`);
|
|
191519
191493
|
process.exit(1);
|
|
191520
191494
|
}
|
|
191521
|
-
const all = readdirSync6(baseDir).filter((entry) => statSync5(
|
|
191495
|
+
const all = readdirSync6(baseDir).filter((entry) => statSync5(join11(baseDir, entry)).isDirectory());
|
|
191522
191496
|
if (exampleNames.length === 0)
|
|
191523
|
-
return all.map((name) =>
|
|
191497
|
+
return all.map((name) => join11(baseDir, name));
|
|
191524
191498
|
const matched = all.filter((name) => exampleNames.includes(name));
|
|
191525
191499
|
if (matched.length === 0) {
|
|
191526
191500
|
warn(`None of [${exampleNames.join(", ")}] match an example under ./dataset/examples/. ` + `Heads up: the \`clear-local\` positional changed — it used to take a workflow slug, ` + `now it takes example names (or omit to clean every example).`);
|
|
191527
191501
|
}
|
|
191528
|
-
return matched.map((name) =>
|
|
191502
|
+
return matched.map((name) => join11(baseDir, name));
|
|
191529
191503
|
}
|
|
191530
191504
|
function runSection(args) {
|
|
191531
191505
|
let removed = 0;
|
|
@@ -191557,8 +191531,8 @@ async function clearEvalOutputs(dir, exampleNames = [], options8 = {}) {
|
|
|
191557
191531
|
const exampleDirs = getTargetExampleDirs(dir, exampleNames);
|
|
191558
191532
|
runSection({
|
|
191559
191533
|
exampleDirs,
|
|
191560
|
-
clean: (exampleDir) => removeDirEntriesWithRetention(
|
|
191561
|
-
shouldCount: (exampleDir) => existsSync16(
|
|
191534
|
+
clean: (exampleDir) => removeDirEntriesWithRetention(join11(exampleDir, "executions"), removeAll),
|
|
191535
|
+
shouldCount: (exampleDir) => existsSync16(join11(exampleDir, "executions")),
|
|
191562
191536
|
successLabel: "Execution cleanup complete",
|
|
191563
191537
|
scannedLabel: "examples scanned:",
|
|
191564
191538
|
seenLabel: "runs seen: ",
|
|
@@ -192133,7 +192107,7 @@ function looksLikeFreeform(prop) {
|
|
|
192133
192107
|
// src/commands/workflow/validation.ts
|
|
192134
192108
|
var import_yaml8 = __toESM(require_dist4(), 1);
|
|
192135
192109
|
import { existsSync as existsSync17, readdirSync as readdirSync7, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
|
|
192136
|
-
import { join as
|
|
192110
|
+
import { join as join12, resolve as resolve6 } from "path";
|
|
192137
192111
|
var NAME_RE = /^[a-z0-9][a-z0-9-_]*$/;
|
|
192138
192112
|
function isDirSafe(path15, issues, field) {
|
|
192139
192113
|
try {
|
|
@@ -192253,19 +192227,19 @@ function validateDatasetFolder(root2) {
|
|
|
192253
192227
|
if (!existsSync17(root2)) {
|
|
192254
192228
|
return [{ field: root2, message: "Folder not found." }];
|
|
192255
192229
|
}
|
|
192256
|
-
if (existsSync17(
|
|
192230
|
+
if (existsSync17(join12(root2, "manifest.json"))) {
|
|
192257
192231
|
issues.push({
|
|
192258
192232
|
field: "manifest.json",
|
|
192259
192233
|
message: "Top-level manifest.json is the legacy format. Re-export the dataset using the folder convention."
|
|
192260
192234
|
});
|
|
192261
192235
|
}
|
|
192262
|
-
const examplesDir =
|
|
192236
|
+
const examplesDir = join12(root2, "examples");
|
|
192263
192237
|
if (!existsSync17(examplesDir)) {
|
|
192264
192238
|
issues.push({ field: "examples/", message: "No examples/ directory found at dataset root." });
|
|
192265
192239
|
return issues;
|
|
192266
192240
|
}
|
|
192267
192241
|
for (const exampleName of readdirSync7(examplesDir)) {
|
|
192268
|
-
const exampleFolder =
|
|
192242
|
+
const exampleFolder = join12(examplesDir, exampleName);
|
|
192269
192243
|
if (!isDirSafe(exampleFolder, issues, `examples/${exampleName}`))
|
|
192270
192244
|
continue;
|
|
192271
192245
|
if (!NAME_RE.test(exampleName)) {
|
|
@@ -192275,7 +192249,7 @@ function validateDatasetFolder(root2) {
|
|
|
192275
192249
|
});
|
|
192276
192250
|
continue;
|
|
192277
192251
|
}
|
|
192278
|
-
const inputJsonPath =
|
|
192252
|
+
const inputJsonPath = join12(exampleFolder, "input.json");
|
|
192279
192253
|
const hasInputJson = existsSync17(inputJsonPath);
|
|
192280
192254
|
if (!hasInputJson) {
|
|
192281
192255
|
issues.push({
|
|
@@ -192302,8 +192276,8 @@ function validateDatasetFolder(root2) {
|
|
|
192302
192276
|
});
|
|
192303
192277
|
continue;
|
|
192304
192278
|
}
|
|
192305
|
-
const inputDir =
|
|
192306
|
-
if (existsSync17(
|
|
192279
|
+
const inputDir = join12(exampleFolder, "input");
|
|
192280
|
+
if (existsSync17(join12(inputDir, "arguments.json"))) {
|
|
192307
192281
|
issues.push({
|
|
192308
192282
|
field: `examples/${exampleName}/input/arguments.json`,
|
|
192309
192283
|
message: "Legacy input/arguments.json is no longer accepted. Use input.json instead."
|
|
@@ -192318,8 +192292,8 @@ function validateDatasetFolder(root2) {
|
|
|
192318
192292
|
})) {
|
|
192319
192293
|
issues.push(issue2);
|
|
192320
192294
|
}
|
|
192321
|
-
const expectedDir =
|
|
192322
|
-
const expectedJsonPath =
|
|
192295
|
+
const expectedDir = join12(exampleFolder, "expected");
|
|
192296
|
+
const expectedJsonPath = join12(exampleFolder, "expected.json");
|
|
192323
192297
|
if (existsSync17(expectedDir)) {
|
|
192324
192298
|
for (const entry of readdirSync7(expectedDir)) {
|
|
192325
192299
|
if (entry === "output.json" || entry === "error.json") {
|
|
@@ -192329,7 +192303,7 @@ function validateDatasetFolder(root2) {
|
|
|
192329
192303
|
});
|
|
192330
192304
|
continue;
|
|
192331
192305
|
}
|
|
192332
|
-
const sub =
|
|
192306
|
+
const sub = join12(expectedDir, entry);
|
|
192333
192307
|
const field = `examples/${exampleName}/expected/${entry}`;
|
|
192334
192308
|
let isDir;
|
|
192335
192309
|
try {
|
|
@@ -192385,7 +192359,7 @@ function validateDatasetFolder(root2) {
|
|
|
192385
192359
|
} else {
|
|
192386
192360
|
for (const issue2 of validateFileRefs({
|
|
192387
192361
|
refs: collectDatasetFileRefs(parsed),
|
|
192388
|
-
filesRoot:
|
|
192362
|
+
filesRoot: join12(exampleFolder, "expected"),
|
|
192389
192363
|
root: "expected",
|
|
192390
192364
|
fieldPrefix: `examples/${exampleName}/expected.json`
|
|
192391
192365
|
})) {
|
|
@@ -192438,7 +192412,7 @@ function validateFileRefs(args) {
|
|
|
192438
192412
|
});
|
|
192439
192413
|
continue;
|
|
192440
192414
|
}
|
|
192441
|
-
if (!existsSync17(
|
|
192415
|
+
if (!existsSync17(join12(args.filesRoot, relative4))) {
|
|
192442
192416
|
issues.push({
|
|
192443
192417
|
field: `${args.fieldPrefix}:${ref.jsonPath}`,
|
|
192444
192418
|
message: `Referenced file does not exist: ${ref.path}.`
|
|
@@ -192492,7 +192466,7 @@ Note
|
|
|
192492
192466
|
return;
|
|
192493
192467
|
}
|
|
192494
192468
|
const root2 = rootDir(opts);
|
|
192495
|
-
const wfFile =
|
|
192469
|
+
const wfFile = join12(root2, "workflow.yaml");
|
|
192496
192470
|
const wfResult = validateWorkflowYaml(wfFile);
|
|
192497
192471
|
const wfPath = relPath(root2, wfFile);
|
|
192498
192472
|
const wfOk = printIssues("workflow.yaml", wfPath, wfResult.issues);
|
|
@@ -192500,8 +192474,8 @@ Note
|
|
|
192500
192474
|
printSchemaQualityWarnings(wfPath, wfResult.warnings);
|
|
192501
192475
|
printInvokeOnlineHint(wfResult.invokeStepCount, opts.online);
|
|
192502
192476
|
}
|
|
192503
|
-
const evOk = printIssues("evaluators.yaml", relPath(root2,
|
|
192504
|
-
const dsOk = printIssues("dataset/", relPath(root2,
|
|
192477
|
+
const evOk = printIssues("evaluators.yaml", relPath(root2, join12(root2, "evaluators.yaml")), validateEvaluatorsYaml(join12(root2, "evaluators.yaml")));
|
|
192478
|
+
const dsOk = printIssues("dataset/", relPath(root2, join12(root2, "dataset")), validateDatasetFolder(join12(root2, "dataset")));
|
|
192505
192479
|
let onlineOk = true;
|
|
192506
192480
|
if (wfOk && opts.online && existsSync17(wfFile)) {
|
|
192507
192481
|
onlineOk = printIssues("invoke refs (server)", wfPath, await onlineInvokeIssues(readFileSync15(wfFile, "utf-8"), opts));
|
|
@@ -192581,7 +192555,7 @@ async function writeOrPrint(out, content) {
|
|
|
192581
192555
|
}
|
|
192582
192556
|
async function readDirAsZip2(dir) {
|
|
192583
192557
|
const tree = {};
|
|
192584
|
-
async function
|
|
192558
|
+
async function walk3(current, relPrefix) {
|
|
192585
192559
|
const entries = await fs17.readdir(current, { withFileTypes: true });
|
|
192586
192560
|
for (const e8 of entries) {
|
|
192587
192561
|
if (e8.name.startsWith(".") || e8.name === "node_modules")
|
|
@@ -192589,12 +192563,12 @@ async function readDirAsZip2(dir) {
|
|
|
192589
192563
|
const full = path15.join(current, e8.name);
|
|
192590
192564
|
const rel = relPrefix ? `${relPrefix}/${e8.name}` : e8.name;
|
|
192591
192565
|
if (e8.isDirectory())
|
|
192592
|
-
await
|
|
192566
|
+
await walk3(full, rel);
|
|
192593
192567
|
else if (e8.isFile())
|
|
192594
192568
|
tree[rel] = new Uint8Array(await fs17.readFile(full));
|
|
192595
192569
|
}
|
|
192596
192570
|
}
|
|
192597
|
-
await
|
|
192571
|
+
await walk3(dir, "");
|
|
192598
192572
|
if (Object.keys(tree).length === 0) {
|
|
192599
192573
|
throw new Error(`directory is empty: ${dir}`);
|
|
192600
192574
|
}
|
|
@@ -18,6 +18,7 @@ Start a workflow or agent run, e.g. workflows.extract-invoice.
|
|
|
18
18
|
| `--input-file <field=path>` | no | `[]` | Input file to upload as multipart form-data. Repeat for multiple files; bare paths use field "file". |
|
|
19
19
|
| `--example <name>` | no | | Run one persisted example by name |
|
|
20
20
|
| `--dir <dir>` | no | | Local eigenpal directory for workflow examples |
|
|
21
|
+
| `--fail-on-mismatch` | no | | For --example runs, exit non-zero when a graded example fails (evaluator fail, or output mismatch) |
|
|
21
22
|
| `--wait` | no | | Poll until the run reaches a terminal status |
|
|
22
23
|
| `--interval <seconds>` | no | `2` | Polling interval in seconds |
|
|
23
24
|
| `--max-wait <seconds>` | no | `1800` | Maximum wait before exit code 2 |
|