@eigenpal/cli 0.20.2 → 0.20.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/CHANGELOG.md +6 -0
- package/dist/cli.js +349 -131
- package/dist/docs-bundle.json +24 -10
- package/dist/skill/SKILL.md +16 -2
- package/dist/skill/reference/cli/agents.md +52 -27
- package/dist/skill/reference/cli/surface.md +4 -2
- package/dist/skill/reference/cli/workflow.md +56 -31
- package/dist/skill/reference/dataset-format.md +35 -8
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -94280,7 +94280,7 @@ function cleanDoc(doc) {
|
|
|
94280
94280
|
return mapDoc(doc, (currentDoc) => cleanDocFn(currentDoc));
|
|
94281
94281
|
}
|
|
94282
94282
|
function replaceEndOfLine(doc, replacement = literalline) {
|
|
94283
|
-
return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ?
|
|
94283
|
+
return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join3(replacement, currentDoc.split(`
|
|
94284
94284
|
`)) : currentDoc);
|
|
94285
94285
|
}
|
|
94286
94286
|
function canBreakFn(doc) {
|
|
@@ -94360,7 +94360,7 @@ function indentIfBreak(contents, options) {
|
|
|
94360
94360
|
negate: options.negate
|
|
94361
94361
|
};
|
|
94362
94362
|
}
|
|
94363
|
-
function
|
|
94363
|
+
function join3(separator, docs) {
|
|
94364
94364
|
assertDoc(separator);
|
|
94365
94365
|
assertDocArray(docs);
|
|
94366
94366
|
const parts = [];
|
|
@@ -95071,7 +95071,7 @@ var init_doc = __esm(() => {
|
|
|
95071
95071
|
MODE_FLAT = Symbol("MODE_FLAT");
|
|
95072
95072
|
DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
|
|
95073
95073
|
builders = {
|
|
95074
|
-
join:
|
|
95074
|
+
join: join3,
|
|
95075
95075
|
line,
|
|
95076
95076
|
softline,
|
|
95077
95077
|
hardline,
|
|
@@ -183861,7 +183861,7 @@ function parse42(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
|
183861
183861
|
}
|
|
183862
183862
|
return res;
|
|
183863
183863
|
}
|
|
183864
|
-
async function
|
|
183864
|
+
async function readFile3(file) {
|
|
183865
183865
|
if (isUrlString(file)) {
|
|
183866
183866
|
file = new URL(file);
|
|
183867
183867
|
}
|
|
@@ -184752,7 +184752,7 @@ function defaultResolve(specifier, context = {}) {
|
|
|
184752
184752
|
format: defaultGetFormatWithoutErrors(url3, { parentURL })
|
|
184753
184753
|
};
|
|
184754
184754
|
}
|
|
184755
|
-
function
|
|
184755
|
+
function resolve22(specifier, parent) {
|
|
184756
184756
|
if (!parent) {
|
|
184757
184757
|
throw new Error("Please pass `parent`: `import-meta-resolve` cannot ponyfill that");
|
|
184758
184758
|
}
|
|
@@ -184767,7 +184767,7 @@ function resolve2(specifier, parent) {
|
|
|
184767
184767
|
}
|
|
184768
184768
|
}
|
|
184769
184769
|
function importFromFile(specifier, parent) {
|
|
184770
|
-
const url3 =
|
|
184770
|
+
const url3 = resolve22(specifier, pathToFileURL4(parent).href);
|
|
184771
184771
|
return import(url3);
|
|
184772
184772
|
}
|
|
184773
184773
|
function requireFromFile(id, parent) {
|
|
@@ -197655,7 +197655,7 @@ ${codeblock}`, options8);
|
|
|
197655
197655
|
"\\": "\\"
|
|
197656
197656
|
};
|
|
197657
197657
|
KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
197658
|
-
read_file_default =
|
|
197658
|
+
read_file_default = readFile3;
|
|
197659
197659
|
loadConfigFromPackageJson = process.versions.bun ? async function loadConfigFromBunPackageJson(file) {
|
|
197660
197660
|
const { prettier } = await readBunPackageJson(file);
|
|
197661
197661
|
return prettier;
|
|
@@ -206391,7 +206391,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
|
|
|
206391
206391
|
// package.json
|
|
206392
206392
|
var package_default = {
|
|
206393
206393
|
name: "@eigenpal/cli",
|
|
206394
|
-
version: "0.20.
|
|
206394
|
+
version: "0.20.4",
|
|
206395
206395
|
description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
|
|
206396
206396
|
keywords: [
|
|
206397
206397
|
"eigenpal",
|
|
@@ -206646,6 +206646,15 @@ class ApiClient {
|
|
|
206646
206646
|
});
|
|
206647
206647
|
return this.handleResponse(res, url);
|
|
206648
206648
|
}
|
|
206649
|
+
async patchFormData(path, formData) {
|
|
206650
|
+
const url = this.buildUrl(path);
|
|
206651
|
+
const res = await fetch(url, {
|
|
206652
|
+
method: "PATCH",
|
|
206653
|
+
headers: this.headers(),
|
|
206654
|
+
body: formData
|
|
206655
|
+
});
|
|
206656
|
+
return this.handleResponse(res, url);
|
|
206657
|
+
}
|
|
206649
206658
|
async delete(path) {
|
|
206650
206659
|
const url = this.buildUrl(path);
|
|
206651
206660
|
const res = await fetch(url, {
|
|
@@ -209914,6 +209923,10 @@ function zipSync(data, opts) {
|
|
|
209914
209923
|
import { existsSync as existsSync8, promises as fs3 } from "node:fs";
|
|
209915
209924
|
import path8 from "node:path";
|
|
209916
209925
|
|
|
209926
|
+
// src/commands/dataset-review-request.ts
|
|
209927
|
+
import { mkdir, readFile as readFile2, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
209928
|
+
import { basename, dirname as dirname2, isAbsolute, join as join2, relative, resolve } from "node:path";
|
|
209929
|
+
|
|
209917
209930
|
// src/commands/agents/shared.ts
|
|
209918
209931
|
init_src();
|
|
209919
209932
|
import { existsSync as existsSync6, promises as fs } from "node:fs";
|
|
@@ -210133,6 +210146,7 @@ function datasetReviewRequestItemsPath(automationId, reviewId, itemId) {
|
|
|
210133
210146
|
const base = `${datasetReviewRequestsPath(automationId, reviewId)}/items`;
|
|
210134
210147
|
return itemId ? `${base}/${itemId}` : base;
|
|
210135
210148
|
}
|
|
210149
|
+
var REVIEW_EDIT_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
210136
210150
|
function collectRepeatable(val2, prev) {
|
|
210137
210151
|
return [...prev, val2];
|
|
210138
210152
|
}
|
|
@@ -210146,7 +210160,7 @@ function formatProgress(progress) {
|
|
|
210146
210160
|
const total = progress.total ?? remaining;
|
|
210147
210161
|
return `${remaining}/${total} remaining`;
|
|
210148
210162
|
}
|
|
210149
|
-
function
|
|
210163
|
+
function parseApprovalDecision(opts, action) {
|
|
210150
210164
|
if (opts.clear) {
|
|
210151
210165
|
if (opts.decision !== undefined) {
|
|
210152
210166
|
throw new Error("pass either --clear or --decision, not both");
|
|
@@ -210154,7 +210168,7 @@ function parseFieldDecision(opts) {
|
|
|
210154
210168
|
return null;
|
|
210155
210169
|
}
|
|
210156
210170
|
if (opts.decision === undefined) {
|
|
210157
|
-
throw new Error(
|
|
210171
|
+
throw new Error(`--decision or --clear is required when --action ${action}`);
|
|
210158
210172
|
}
|
|
210159
210173
|
const normalized = opts.decision.trim().toLowerCase();
|
|
210160
210174
|
if (normalized === "null" || normalized === "clear") {
|
|
@@ -210165,6 +210179,12 @@ function parseFieldDecision(opts) {
|
|
|
210165
210179
|
}
|
|
210166
210180
|
throw new Error("--decision must be approved, rejected, null, or clear");
|
|
210167
210181
|
}
|
|
210182
|
+
function parseFieldDecision(opts) {
|
|
210183
|
+
return parseApprovalDecision(opts, "field-decision");
|
|
210184
|
+
}
|
|
210185
|
+
function parseFileDecision(opts) {
|
|
210186
|
+
return parseApprovalDecision(opts, "file-decision");
|
|
210187
|
+
}
|
|
210168
210188
|
function buildReviewItemPatchBody(action, opts) {
|
|
210169
210189
|
const body = {
|
|
210170
210190
|
action,
|
|
@@ -210174,6 +210194,8 @@ function buildReviewItemPatchBody(action, opts) {
|
|
|
210174
210194
|
body.comment = opts.comment;
|
|
210175
210195
|
if (opts.fieldPath !== undefined)
|
|
210176
210196
|
body.fieldPath = opts.fieldPath;
|
|
210197
|
+
if (opts.filePath !== undefined)
|
|
210198
|
+
body.filePath = opts.filePath;
|
|
210177
210199
|
if (action === "edit") {
|
|
210178
210200
|
if (opts.expectedJson === undefined) {
|
|
210179
210201
|
throw new Error("--expected-json is required when --action edit");
|
|
@@ -210188,10 +210210,91 @@ function buildReviewItemPatchBody(action, opts) {
|
|
|
210188
210210
|
}
|
|
210189
210211
|
body.decision = parseFieldDecision({ decision: opts.decision, clear: opts.clear });
|
|
210190
210212
|
} else if (opts.decision !== undefined || opts.clear) {
|
|
210191
|
-
|
|
210213
|
+
if (action !== "file-decision") {
|
|
210214
|
+
throw new Error("--decision / --clear are only valid with --action field-decision or file-decision");
|
|
210215
|
+
}
|
|
210216
|
+
}
|
|
210217
|
+
if (action === "file-decision") {
|
|
210218
|
+
if (!opts.filePath?.trim()) {
|
|
210219
|
+
throw new Error("--file-path is required when --action file-decision");
|
|
210220
|
+
}
|
|
210221
|
+
if (opts.fieldPath !== undefined) {
|
|
210222
|
+
throw new Error("--field-path is only valid with --action comment or field-decision");
|
|
210223
|
+
}
|
|
210224
|
+
if (opts.newPath !== undefined || opts.file !== undefined) {
|
|
210225
|
+
throw new Error("--new-path / --file are only valid with --action edit-file");
|
|
210226
|
+
}
|
|
210227
|
+
if (opts.decision !== undefined || opts.clear) {
|
|
210228
|
+
body.decision = parseFileDecision({ decision: opts.decision, clear: opts.clear });
|
|
210229
|
+
} else if (!opts.comment?.trim()) {
|
|
210230
|
+
throw new Error("pass --decision approved|rejected (or --clear) or a --comment note when --action file-decision");
|
|
210231
|
+
}
|
|
210232
|
+
} else if (opts.filePath !== undefined || opts.newPath !== undefined || opts.file !== undefined) {
|
|
210233
|
+
if (action !== "edit-file") {
|
|
210234
|
+
throw new Error("--file-path / --new-path / --file are only valid with --action file-decision or edit-file");
|
|
210235
|
+
}
|
|
210236
|
+
}
|
|
210237
|
+
if (action === "edit-file") {
|
|
210238
|
+
throw new Error("--action edit-file uploads bytes and needs multipart; use buildReviewItemFileFields");
|
|
210192
210239
|
}
|
|
210193
210240
|
return body;
|
|
210194
210241
|
}
|
|
210242
|
+
function buildReviewItemFileFields(opts) {
|
|
210243
|
+
const hasFilePath = !!opts.filePath?.trim();
|
|
210244
|
+
const hasNewPath = !!opts.newPath?.trim();
|
|
210245
|
+
if (hasFilePath === hasNewPath) {
|
|
210246
|
+
throw new Error("pass exactly one of --file-path (correct an existing expected file) or --new-path (upload a brand-new expected file) when --action edit-file");
|
|
210247
|
+
}
|
|
210248
|
+
if (!opts.file?.trim()) {
|
|
210249
|
+
throw new Error("--file <local path> is required when --action edit-file");
|
|
210250
|
+
}
|
|
210251
|
+
return {
|
|
210252
|
+
...hasFilePath ? { filePath: opts.filePath.trim() } : {},
|
|
210253
|
+
...hasNewPath ? { newPath: opts.newPath.trim() } : {},
|
|
210254
|
+
...opts.comment !== undefined ? { comment: opts.comment } : {},
|
|
210255
|
+
expectedUpdatedAt: opts.expectedUpdatedAt
|
|
210256
|
+
};
|
|
210257
|
+
}
|
|
210258
|
+
function encodeReviewFilePath(path) {
|
|
210259
|
+
const segments = path.replace(/^\/+/, "").split("/");
|
|
210260
|
+
for (const segment of segments) {
|
|
210261
|
+
if (!segment || segment === "." || segment === ".." || segment.includes("\\") || segment.includes("\x00")) {
|
|
210262
|
+
throw new Error(`refusing to download unsafe review file path: ${path}`);
|
|
210263
|
+
}
|
|
210264
|
+
}
|
|
210265
|
+
return segments.map((segment) => encodeURIComponent(segment)).join("/");
|
|
210266
|
+
}
|
|
210267
|
+
function assertSafeReviewExampleName(exampleName) {
|
|
210268
|
+
const segments = exampleName.split("/");
|
|
210269
|
+
for (const segment of segments) {
|
|
210270
|
+
if (!segment || segment === "." || segment === ".." || segment.includes("\\") || segment.includes("\x00")) {
|
|
210271
|
+
throw new Error(`refusing to materialize unsafe review example name: ${exampleName}`);
|
|
210272
|
+
}
|
|
210273
|
+
}
|
|
210274
|
+
return exampleName;
|
|
210275
|
+
}
|
|
210276
|
+
function formatReviewItemFiles(item) {
|
|
210277
|
+
const overlay = item.currentExpectedFiles;
|
|
210278
|
+
const files = overlay ?? item.snapshotManifest?.expectedFiles ?? null;
|
|
210279
|
+
if (!files || files.length === 0)
|
|
210280
|
+
return "-";
|
|
210281
|
+
const decisions = item.fileDecisions ?? {};
|
|
210282
|
+
let approved = 0;
|
|
210283
|
+
let rejected = 0;
|
|
210284
|
+
for (const file of files) {
|
|
210285
|
+
const key = file.path ?? file.name ?? "";
|
|
210286
|
+
const decision = decisions[key]?.decision;
|
|
210287
|
+
if (decision === "approved")
|
|
210288
|
+
approved += 1;
|
|
210289
|
+
else if (decision === "rejected")
|
|
210290
|
+
rejected += 1;
|
|
210291
|
+
}
|
|
210292
|
+
const total = files.length;
|
|
210293
|
+
const decided = approved + rejected;
|
|
210294
|
+
if (decided === 0)
|
|
210295
|
+
return `${total} file${total === 1 ? "" : "s"}, undecided`;
|
|
210296
|
+
return `${approved}/${total} approved${rejected ? `, ${rejected} rejected` : ""}`;
|
|
210297
|
+
}
|
|
210195
210298
|
function registerDatasetReviewRequestCommands(dataset, resolveAutomation) {
|
|
210196
210299
|
const reviewRequest = dataset.command("review-request").description("Review dataset ground truth with a human. Snapshot examples for review and poll progress until reviewers finish.").action(() => {
|
|
210197
210300
|
process.stderr.write("`dataset review-request` requires a subcommand. Run `dataset review-request --help`.\n");
|
|
@@ -210234,9 +210337,13 @@ Examples:
|
|
|
210234
210337
|
|
|
210235
210338
|
Agent loop: create with focus/ignore and per-example notes → poll \`get --json\`
|
|
210236
210339
|
until \`.progress.complete\` → record per-field decisions and per-example
|
|
210237
|
-
approve/reject with comments →
|
|
210238
|
-
|
|
210239
|
-
|
|
210340
|
+
approve/reject with comments → \`pull --out <dir>\` to fetch expected files
|
|
210341
|
+
(snapshot or reviewer-corrected) → correct bytes with
|
|
210342
|
+
\`item --action edit-file --file-path <path> --file <local>\` (or
|
|
210343
|
+
\`--new-path\` for brand-new files) → record per-file decisions with notes
|
|
210344
|
+
via \`item --action file-decision\` → read \`events\` → \`dataset pull\` and
|
|
210345
|
+
MANUAL per-example reconcile into the live dataset (no auto-apply exists by
|
|
210346
|
+
design; reviewers can err) → \`update --status closed\`.
|
|
210240
210347
|
|
|
210241
210348
|
\`reject\` is a recommendation only — nothing is deleted by any review endpoint.
|
|
210242
210349
|
Use \`--json\` from agents; API errors exit non-zero.
|
|
@@ -210283,7 +210390,7 @@ Use \`--json\` from agents; API errors exit non-zero.
|
|
|
210283
210390
|
const created = payload;
|
|
210284
210391
|
success(`Created review request ${ui.bold(created.id ?? "(unknown id)")}` + (created.status ? ` ${ui.dim(`(${created.status})`)}` : ""));
|
|
210285
210392
|
}));
|
|
210286
|
-
addJsonFlag(withBaseUrl(reviewRequest.command("get <automation-id> <review-id>"))).description("Fetch one dataset review request with items, progress, focus fields, ignored fields, and events.").action(action(async (automationRef, reviewId, opts) => {
|
|
210393
|
+
addJsonFlag(withBaseUrl(reviewRequest.command("get <automation-id> <review-id>"))).description("Fetch one dataset review request with items, progress, focus fields, ignored fields, expected files, file decisions, and events.").action(action(async (automationRef, reviewId, opts) => {
|
|
210287
210394
|
const { client, automationId } = await resolveAutomation(automationRef, opts);
|
|
210288
210395
|
const payload = await client.get(datasetReviewRequestsPath(automationId, reviewId));
|
|
210289
210396
|
if (opts.json)
|
|
@@ -210311,11 +210418,13 @@ Use \`--json\` from agents; API errors exit non-zero.
|
|
|
210311
210418
|
console.log(table(detail.items.map((item) => ({
|
|
210312
210419
|
exampleName: item.exampleName,
|
|
210313
210420
|
status: item.status,
|
|
210314
|
-
inputDrifted: item.inputDrifted ? "yes" : "no"
|
|
210421
|
+
inputDrifted: item.inputDrifted ? "yes" : "no",
|
|
210422
|
+
files: formatReviewItemFiles(item)
|
|
210315
210423
|
})), [
|
|
210316
210424
|
{ key: "exampleName", header: "example" },
|
|
210317
210425
|
{ key: "status", header: "status" },
|
|
210318
|
-
{ key: "inputDrifted", header: "inputDrifted" }
|
|
210426
|
+
{ key: "inputDrifted", header: "inputDrifted" },
|
|
210427
|
+
{ key: "files", header: "files" }
|
|
210319
210428
|
]));
|
|
210320
210429
|
}
|
|
210321
210430
|
}));
|
|
@@ -210374,11 +210483,13 @@ to the dataset — reconcile manually after \`dataset pull\`.
|
|
|
210374
210483
|
console.log(table(items.map((item) => ({
|
|
210375
210484
|
exampleName: item.exampleName,
|
|
210376
210485
|
status: item.status,
|
|
210377
|
-
inputDrifted: item.inputDrifted ? "yes" : "no"
|
|
210486
|
+
inputDrifted: item.inputDrifted ? "yes" : "no",
|
|
210487
|
+
files: formatReviewItemFiles(item)
|
|
210378
210488
|
})), [
|
|
210379
210489
|
{ key: "exampleName", header: "example" },
|
|
210380
210490
|
{ key: "status", header: "status" },
|
|
210381
|
-
{ key: "inputDrifted", header: "inputDrifted" }
|
|
210491
|
+
{ key: "inputDrifted", header: "inputDrifted" },
|
|
210492
|
+
{ key: "files", header: "files" }
|
|
210382
210493
|
]));
|
|
210383
210494
|
}));
|
|
210384
210495
|
addJsonFlag(withBaseUrl(reviewRequest.command("events <automation-id> <review-id>"))).description("List review activity, including example and field notes.").action(action(async (automationRef, reviewId, opts) => {
|
|
@@ -210401,7 +210512,7 @@ to the dataset — reconcile manually after \`dataset pull\`.
|
|
|
210401
210512
|
{ key: "createdAt", header: "createdAt" }
|
|
210402
210513
|
]));
|
|
210403
210514
|
}));
|
|
210404
|
-
addJsonFlag(withBaseUrl(reviewRequest.command("item <automation-id> <review-id> <item-id>"))).description("Approve, reject, reopen, comment, edit, or record a field-decision on one review item.").requiredOption("--action <approve|reject|reopen|comment|edit|field-decision>", "Item action").requiredOption("--expected-updated-at <iso>", "Item updatedAt the client last observed (optimistic concurrency)").option("--comment <text>", "Note stored on the item or
|
|
210515
|
+
addJsonFlag(withBaseUrl(reviewRequest.command("item <automation-id> <review-id> <item-id>"))).description("Approve, reject, reopen, comment, edit, or record a field- or file-decision on one review item. Upload corrected expected-file bytes with edit-file.").requiredOption("--action <approve|reject|reopen|comment|edit|field-decision|file-decision|edit-file>", "Item action").requiredOption("--expected-updated-at <iso>", "Item updatedAt the client last observed (optimistic concurrency)").option("--comment <text>", "Note stored on the item, field, or file").option("--field-path <path>", "Dotted expected-output path for comment or field-decision").option("--file-path <path>", "Expected-file path for file-decision or edit-file (correct)").option("--new-path <path>", "Expected-file path for edit-file uploads of brand-new reviewer files").option("--file <local path>", "Local file bytes to upload when --action edit-file").option("--decision <approved|rejected|null>", "Field or file decision for --action field-decision or file-decision (null/clear removes it)").option("--clear", "Clear a field or file decision (sends decision: null)", false).option("--expected-json <json>", "Replacement expected JSON when --action edit").addHelpText("after", `
|
|
210405
210516
|
Examples:
|
|
210406
210517
|
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210407
210518
|
--action field-decision --field-path vendor.iban --decision approved \\
|
|
@@ -210409,30 +210520,137 @@ Examples:
|
|
|
210409
210520
|
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210410
210521
|
--action field-decision --field-path vendor.iban --clear \\
|
|
210411
210522
|
--expected-updated-at 2026-01-01T00:00:00.000Z --json
|
|
210523
|
+
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210524
|
+
--action file-decision --file-path expected/report.pdf --decision approved \\
|
|
210525
|
+
--comment "totals match" --expected-updated-at 2026-01-01T00:00:00.000Z --json
|
|
210526
|
+
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210527
|
+
--action edit-file --file-path expected/report.pdf --file ./report-fixed.pdf \\
|
|
210528
|
+
--comment "fixed total" --expected-updated-at 2026-01-01T00:00:00.000Z --json
|
|
210529
|
+
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210530
|
+
--action edit-file --new-path expected/appendix.pdf --file ./appendix.pdf \\
|
|
210531
|
+
--expected-updated-at 2026-01-01T00:00:00.000Z --json
|
|
210412
210532
|
$ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
|
|
210413
210533
|
--action reject --comment "wrong vendor" \\
|
|
210414
210534
|
--expected-updated-at 2026-01-01T00:00:00.000Z --json
|
|
210415
210535
|
|
|
210416
210536
|
\`reject\` marks the example as not recommended for the dataset; it does not
|
|
210417
|
-
delete anything. \`--clear\` / \`--decision null\` removes a prior field
|
|
210418
|
-
decision (API: decision: null).
|
|
210419
|
-
|
|
210537
|
+
delete anything. \`--clear\` / \`--decision null\` removes a prior field or
|
|
210538
|
+
file decision (API: decision: null). A file-decision \`--comment\` without a
|
|
210539
|
+
decision is a note and needs an existing decision server-side. \`edit-file\`
|
|
210540
|
+
takes exactly one of \`--file-path\` (correct an existing expected file) or
|
|
210541
|
+
\`--new-path\` (upload a brand-new expected file) plus \`--file\` bytes
|
|
210542
|
+
(50MB cap); it replaces the item overlay entry, never the live dataset.
|
|
210543
|
+
Always pass \`--expected-updated-at\` from the item payload you last observed.
|
|
210420
210544
|
`).action(action(async (automationRef, reviewId, itemId, opts) => {
|
|
210421
210545
|
const { client, automationId } = await resolveAutomation(automationRef, opts);
|
|
210546
|
+
const itemPath = datasetReviewRequestItemsPath(automationId, reviewId, itemId);
|
|
210547
|
+
if (opts.action === "edit-file") {
|
|
210548
|
+
const fields = buildReviewItemFileFields({
|
|
210549
|
+
expectedUpdatedAt: opts.expectedUpdatedAt,
|
|
210550
|
+
filePath: opts.filePath,
|
|
210551
|
+
newPath: opts.newPath,
|
|
210552
|
+
file: opts.file,
|
|
210553
|
+
comment: opts.comment
|
|
210554
|
+
});
|
|
210555
|
+
const localPath = resolve(opts.file.trim());
|
|
210556
|
+
const fileStat = await stat(localPath);
|
|
210557
|
+
if (!fileStat.isFile()) {
|
|
210558
|
+
throw new Error(`--file is not a file: ${localPath}`);
|
|
210559
|
+
}
|
|
210560
|
+
if (fileStat.size > REVIEW_EDIT_FILE_MAX_BYTES) {
|
|
210561
|
+
throw new Error(`--file ${localPath} is ${(fileStat.size / 1024 / 1024).toFixed(1)}MB; the edit-file cap is 50MB`);
|
|
210562
|
+
}
|
|
210563
|
+
const bytes = await readFile2(localPath);
|
|
210564
|
+
const form = new FormData;
|
|
210565
|
+
form.set("action", "edit-file");
|
|
210566
|
+
form.set("file", new Blob([bytes], { type: "application/octet-stream" }), basename(localPath));
|
|
210567
|
+
if (fields.filePath !== undefined)
|
|
210568
|
+
form.set("filePath", fields.filePath);
|
|
210569
|
+
if (fields.newPath !== undefined)
|
|
210570
|
+
form.set("newPath", fields.newPath);
|
|
210571
|
+
if (fields.comment !== undefined)
|
|
210572
|
+
form.set("comment", fields.comment);
|
|
210573
|
+
form.set("expectedUpdatedAt", fields.expectedUpdatedAt);
|
|
210574
|
+
const payload = await client.patchFormData(itemPath, form);
|
|
210575
|
+
if (opts.json)
|
|
210576
|
+
return printJson2(payload);
|
|
210577
|
+
const item = payload.item;
|
|
210578
|
+
success(`Updated ${ui.bold(item?.exampleName ?? itemId)}` + (item?.status ? ` ${ui.dim(`(${item.status})`)}` : ""));
|
|
210579
|
+
return;
|
|
210580
|
+
}
|
|
210422
210581
|
const body = buildReviewItemPatchBody(opts.action, {
|
|
210423
210582
|
expectedUpdatedAt: opts.expectedUpdatedAt,
|
|
210424
210583
|
comment: opts.comment,
|
|
210425
210584
|
fieldPath: opts.fieldPath,
|
|
210585
|
+
filePath: opts.filePath,
|
|
210586
|
+
newPath: opts.newPath,
|
|
210587
|
+
file: opts.file,
|
|
210426
210588
|
decision: opts.decision,
|
|
210427
210589
|
clear: opts.clear,
|
|
210428
210590
|
expectedJson: opts.expectedJson
|
|
210429
210591
|
});
|
|
210430
|
-
const payload = await client.patch(
|
|
210592
|
+
const payload = await client.patch(itemPath, body);
|
|
210431
210593
|
if (opts.json)
|
|
210432
210594
|
return printJson2(payload);
|
|
210433
210595
|
const item = payload.item;
|
|
210434
210596
|
success(`Updated ${ui.bold(item?.exampleName ?? itemId)}` + (item?.status ? ` ${ui.dim(`(${item.status})`)}` : ""));
|
|
210435
210597
|
}));
|
|
210598
|
+
addJsonFlag(withBaseUrl(reviewRequest.command("pull <automation-id> <review-id>"))).description("Download review snapshots: per-example expected files (snapshot or reviewer-corrected) plus item JSON.").requiredOption("--out <dir>", "Local directory to materialize the review into").addHelpText("after", `
|
|
210599
|
+
Examples:
|
|
210600
|
+
$ eigenpal workflow dataset review-request pull wf_abc123 dsr_... --out ./review-dsr
|
|
210601
|
+
$ eigenpal workflow dataset review-request pull wf_abc123 dsr_... --out ./review-dsr --json
|
|
210602
|
+
|
|
210603
|
+
Layout (mirrors the dataset archive so reconcile is a copy):
|
|
210604
|
+
<out>/<example>/expected/<path> file bytes; reviewer-corrected when the
|
|
210605
|
+
item has an overlay entry, else the snapshot
|
|
210606
|
+
<out>/<example>/item.json full item payload (status, expected JSON,
|
|
210607
|
+
currentExpectedFiles, fileDecisions)
|
|
210608
|
+
|
|
210609
|
+
There is no write-back: copy approved/edited files and expected JSON into the
|
|
210610
|
+
live dataset example-by-example by hand (reviewers can err), then
|
|
210611
|
+
\`dataset push\`. \`reject\` is a recommendation only — nothing is deleted.
|
|
210612
|
+
`).action(action(async (automationRef, reviewId, opts) => {
|
|
210613
|
+
const { client, automationId } = await resolveAutomation(automationRef, opts);
|
|
210614
|
+
const detail = await client.get(datasetReviewRequestsPath(automationId, reviewId));
|
|
210615
|
+
const items = detail.items ?? [];
|
|
210616
|
+
const outDir = resolve(opts.out);
|
|
210617
|
+
const summary = [];
|
|
210618
|
+
let fileCount = 0;
|
|
210619
|
+
for (const item of items) {
|
|
210620
|
+
if (!item.id || !item.exampleName)
|
|
210621
|
+
continue;
|
|
210622
|
+
const exampleDir = join2(outDir, assertSafeReviewExampleName(item.exampleName));
|
|
210623
|
+
const expectedDir = join2(exampleDir, "expected");
|
|
210624
|
+
await mkdir(expectedDir, { recursive: true });
|
|
210625
|
+
await writeFile2(join2(exampleDir, "item.json"), JSON.stringify(item, null, 2));
|
|
210626
|
+
const paths = (item.currentExpectedFiles?.map((entry) => entry.path) ?? item.snapshotManifest?.expectedFiles?.map((entry) => entry.name) ?? []).filter((path) => !!path);
|
|
210627
|
+
const downloaded = [];
|
|
210628
|
+
for (const filePath of paths) {
|
|
210629
|
+
const encoded = encodeReviewFilePath(filePath);
|
|
210630
|
+
const res = await client.getStream(`${datasetReviewRequestItemsPath(automationId, reviewId, item.id)}/files/${encoded}?kind=expected`);
|
|
210631
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
210632
|
+
const dest = resolve(expectedDir, ...filePath.split("/"));
|
|
210633
|
+
const rel = relative(expectedDir, dest);
|
|
210634
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
210635
|
+
throw new Error(`refusing to write outside ${expectedDir}: ${filePath}`);
|
|
210636
|
+
}
|
|
210637
|
+
await mkdir(dirname2(dest), { recursive: true });
|
|
210638
|
+
await writeFile2(dest, bytes);
|
|
210639
|
+
downloaded.push(filePath);
|
|
210640
|
+
fileCount += 1;
|
|
210641
|
+
}
|
|
210642
|
+
summary.push({
|
|
210643
|
+
exampleName: item.exampleName,
|
|
210644
|
+
itemId: item.id,
|
|
210645
|
+
status: item.status,
|
|
210646
|
+
files: downloaded
|
|
210647
|
+
});
|
|
210648
|
+
}
|
|
210649
|
+
if (opts.json) {
|
|
210650
|
+
return printJson2({ out: outDir, examples: summary, fileCount });
|
|
210651
|
+
}
|
|
210652
|
+
success(`Pulled ${fileCount} expected file${fileCount === 1 ? "" : "s"} ` + `across ${summary.length} example${summary.length === 1 ? "" : "s"} ` + `to ${ui.bold(outDir)}`);
|
|
210653
|
+
}));
|
|
210436
210654
|
}
|
|
210437
210655
|
|
|
210438
210656
|
// src/commands/agents/validation.ts
|
|
@@ -239835,7 +240053,7 @@ function extractXlsxComparableText(filePath) {
|
|
|
239835
240053
|
|
|
239836
240054
|
// src/lib/execution-artifacts.ts
|
|
239837
240055
|
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
239838
|
-
import { join as
|
|
240056
|
+
import { join as join5 } from "path";
|
|
239839
240057
|
|
|
239840
240058
|
// src/lib/format.ts
|
|
239841
240059
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
@@ -239895,8 +240113,8 @@ function timestampFolderName(payload) {
|
|
|
239895
240113
|
}
|
|
239896
240114
|
async function writeExecutionArtifacts(client, exampleDir, payload) {
|
|
239897
240115
|
const folderName = timestampFolderName(payload);
|
|
239898
|
-
const executionsDir =
|
|
239899
|
-
const filesDir =
|
|
240116
|
+
const executionsDir = join5(exampleDir, "executions", folderName);
|
|
240117
|
+
const filesDir = join5(executionsDir, "files");
|
|
239900
240118
|
mkdirSync4(filesDir, { recursive: true });
|
|
239901
240119
|
const generatedFiles = [];
|
|
239902
240120
|
const resultArtifacts = await listResultArtifacts(client, payload.executionId);
|
|
@@ -239912,7 +240130,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
|
|
|
239912
240130
|
const disposition = res.headers.get("Content-Disposition");
|
|
239913
240131
|
const filename = filenameFromContentDisposition(disposition) ?? name;
|
|
239914
240132
|
const safe = safeFilename(filename, `file-${i}${filename.includes(".") ? "" : ".bin"}`);
|
|
239915
|
-
const destPath =
|
|
240133
|
+
const destPath = join5(filesDir, safe);
|
|
239916
240134
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
239917
240135
|
writeFileSync6(destPath, buf);
|
|
239918
240136
|
generatedFiles.push({
|
|
@@ -239938,7 +240156,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
|
|
|
239938
240156
|
const disposition = res.headers.get("Content-Disposition");
|
|
239939
240157
|
const filename = filenameFromContentDisposition(disposition) ?? fileId;
|
|
239940
240158
|
const safe = safeFilename(filename, `file-${i}${filename.includes(".") ? "" : ".bin"}`);
|
|
239941
|
-
const destPath =
|
|
240159
|
+
const destPath = join5(filesDir, safe);
|
|
239942
240160
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
239943
240161
|
writeFileSync6(destPath, buf);
|
|
239944
240162
|
generatedFiles.push({ fileId, stepName, filename: safe });
|
|
@@ -239951,7 +240169,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
|
|
|
239951
240169
|
...payload,
|
|
239952
240170
|
generatedFiles: generatedFiles.length > 0 ? generatedFiles : undefined
|
|
239953
240171
|
};
|
|
239954
|
-
const outputPath =
|
|
240172
|
+
const outputPath = join5(executionsDir, "output.json");
|
|
239955
240173
|
writeFileSync6(outputPath, JSON.stringify(output, null, 2) + `
|
|
239956
240174
|
`, "utf-8");
|
|
239957
240175
|
await formatFileIfAvailable(outputPath);
|
|
@@ -240019,11 +240237,11 @@ function gradeAgainstExpected(expected, actual) {
|
|
|
240019
240237
|
|
|
240020
240238
|
// src/lib/payload.ts
|
|
240021
240239
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
|
|
240022
|
-
import { join as
|
|
240240
|
+
import { join as join7 } from "path";
|
|
240023
240241
|
|
|
240024
240242
|
// src/lib/fs-helpers.ts
|
|
240025
240243
|
init_src();
|
|
240026
|
-
import { extname as extname3, join as
|
|
240244
|
+
import { extname as extname3, join as join6 } from "path";
|
|
240027
240245
|
function guessMimeType(filename) {
|
|
240028
240246
|
return mimeTypeForExtension(extname3(filename)) ?? "";
|
|
240029
240247
|
}
|
|
@@ -240031,7 +240249,7 @@ function guessMimeType(filename) {
|
|
|
240031
240249
|
// src/lib/payload.ts
|
|
240032
240250
|
var DATASET_EXAMPLES_DIR = ["dataset", "examples"];
|
|
240033
240251
|
function resolveEvalBaseDir(dir) {
|
|
240034
|
-
const candidates = [
|
|
240252
|
+
const candidates = [join7(dir, ...DATASET_EXAMPLES_DIR), join7(...DATASET_EXAMPLES_DIR)];
|
|
240035
240253
|
for (const candidate of candidates) {
|
|
240036
240254
|
if (existsSync11(candidate))
|
|
240037
240255
|
return candidate;
|
|
@@ -242772,7 +242990,7 @@ import {
|
|
|
242772
242990
|
statSync as statSync4,
|
|
242773
242991
|
writeFileSync as writeFileSync7
|
|
242774
242992
|
} from "node:fs";
|
|
242775
|
-
import { dirname as
|
|
242993
|
+
import { dirname as dirname5, join as join8, relative as relative3, resolve as resolve5 } from "node:path";
|
|
242776
242994
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
242777
242995
|
var TEMPLATE_NAMES = [
|
|
242778
242996
|
"blank",
|
|
@@ -242792,7 +243010,7 @@ function isValidProjectName(name) {
|
|
|
242792
243010
|
return /^[a-z0-9][a-z0-9-_]*$/.test(name) && name.length <= 60;
|
|
242793
243011
|
}
|
|
242794
243012
|
function resolveTemplatesRoot() {
|
|
242795
|
-
const here =
|
|
243013
|
+
const here = dirname5(fileURLToPath6(import.meta.url));
|
|
242796
243014
|
const srcCandidate = resolve5(here, "..", "..", "templates");
|
|
242797
243015
|
if (existsSync15(srcCandidate))
|
|
242798
243016
|
return srcCandidate;
|
|
@@ -242810,7 +243028,7 @@ async function init(name, opts) {
|
|
|
242810
243028
|
const target = resolve5(process.cwd(), opts.dir ?? name);
|
|
242811
243029
|
assertSafeTargetDir(target, opts.dir);
|
|
242812
243030
|
if (existsSync15(target) && readdirSync4(target).length > 0) {
|
|
242813
|
-
throw new Error(`Target directory ${
|
|
243031
|
+
throw new Error(`Target directory ${relative3(process.cwd(), target)} exists and is not empty.`);
|
|
242814
243032
|
}
|
|
242815
243033
|
let template;
|
|
242816
243034
|
if (opts.template) {
|
|
@@ -242823,12 +243041,12 @@ async function init(name, opts) {
|
|
|
242823
243041
|
} else {
|
|
242824
243042
|
template = await promptForTemplate();
|
|
242825
243043
|
}
|
|
242826
|
-
const sourceRoot =
|
|
243044
|
+
const sourceRoot = join8(resolveTemplatesRoot(), template);
|
|
242827
243045
|
if (!existsSync15(sourceRoot)) {
|
|
242828
243046
|
throw new Error(`Template directory missing on disk: ${sourceRoot}`);
|
|
242829
243047
|
}
|
|
242830
243048
|
const written = copyTemplate(sourceRoot, target, name);
|
|
242831
|
-
const targetDisplay =
|
|
243049
|
+
const targetDisplay = relative3(process.cwd(), target) || ".";
|
|
242832
243050
|
success(`Created ${written} files in ${ui.bold(`${targetDisplay}/`)}`);
|
|
242833
243051
|
console.log("");
|
|
242834
243052
|
info("Next steps:");
|
|
@@ -242867,15 +243085,15 @@ function copyTemplate(src, dst, projectName) {
|
|
|
242867
243085
|
while (stack.length > 0) {
|
|
242868
243086
|
const dir = stack.pop();
|
|
242869
243087
|
for (const entry of readdirSync4(dir)) {
|
|
242870
|
-
const sourcePath =
|
|
242871
|
-
const relativePath =
|
|
242872
|
-
const targetPath =
|
|
243088
|
+
const sourcePath = join8(dir, entry);
|
|
243089
|
+
const relativePath = relative3(src, sourcePath);
|
|
243090
|
+
const targetPath = join8(dst, relativePath);
|
|
242873
243091
|
const stats = statSync4(sourcePath);
|
|
242874
243092
|
if (stats.isDirectory()) {
|
|
242875
243093
|
stack.push(sourcePath);
|
|
242876
243094
|
continue;
|
|
242877
243095
|
}
|
|
242878
|
-
mkdirSync5(
|
|
243096
|
+
mkdirSync5(dirname5(targetPath), { recursive: true });
|
|
242879
243097
|
if (isTextFile(sourcePath)) {
|
|
242880
243098
|
const text = readFileSync15(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
|
|
242881
243099
|
writeFileSync7(targetPath, text);
|
|
@@ -242957,7 +243175,7 @@ import { promises as fs16 } from "node:fs";
|
|
|
242957
243175
|
// src/lib/upload-reusable-file.ts
|
|
242958
243176
|
import { randomUUID } from "node:crypto";
|
|
242959
243177
|
import { createReadStream } from "node:fs";
|
|
242960
|
-
import { stat as
|
|
243178
|
+
import { stat as stat3 } from "node:fs/promises";
|
|
242961
243179
|
import path17 from "node:path";
|
|
242962
243180
|
|
|
242963
243181
|
// src/lib/fetch-body.ts
|
|
@@ -243208,7 +243426,7 @@ async function uploadReusableFile(client, input) {
|
|
|
243208
243426
|
async function resolveUploadSource(input) {
|
|
243209
243427
|
const contentType = input.mimeType || guessMimeType(input.filename) || "application/octet-stream";
|
|
243210
243428
|
if ("filePath" in input && input.filePath) {
|
|
243211
|
-
const info = await
|
|
243429
|
+
const info = await stat3(input.filePath);
|
|
243212
243430
|
if (!info.isFile()) {
|
|
243213
243431
|
throw new Error(`Upload path is not a file: ${input.filePath}`);
|
|
243214
243432
|
}
|
|
@@ -243763,7 +243981,7 @@ function parseInputFileSpecs(inputFile) {
|
|
|
243763
243981
|
// src/lib/format-eigenpal.ts
|
|
243764
243982
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
243765
243983
|
import { existsSync as existsSync16, readFileSync as readFileSync16 } from "fs";
|
|
243766
|
-
import { join as
|
|
243984
|
+
import { join as join9, resolve as resolve6 } from "path";
|
|
243767
243985
|
var PRETTRC_NAMES = [
|
|
243768
243986
|
".prettierrc",
|
|
243769
243987
|
".prettierrc.json",
|
|
@@ -243776,11 +243994,11 @@ var PRETTRC_NAMES = [
|
|
|
243776
243994
|
];
|
|
243777
243995
|
function hasPrettierConfig(cwd) {
|
|
243778
243996
|
for (const name of PRETTRC_NAMES) {
|
|
243779
|
-
if (existsSync16(
|
|
243997
|
+
if (existsSync16(join9(cwd, name)))
|
|
243780
243998
|
return true;
|
|
243781
243999
|
}
|
|
243782
244000
|
try {
|
|
243783
|
-
const pkgPath =
|
|
244001
|
+
const pkgPath = join9(cwd, "package.json");
|
|
243784
244002
|
if (!existsSync16(pkgPath))
|
|
243785
244003
|
return false;
|
|
243786
244004
|
const raw = readFileSync16(pkgPath, "utf-8");
|
|
@@ -243930,73 +244148,73 @@ import {
|
|
|
243930
244148
|
unlinkSync as unlinkSync2,
|
|
243931
244149
|
writeFileSync as writeFileSync8
|
|
243932
244150
|
} from "node:fs";
|
|
243933
|
-
import { sep as PATH_SEP, dirname as
|
|
244151
|
+
import { sep as PATH_SEP, dirname as dirname6, join as join11, relative as relative4, resolve as resolve7 } from "node:path";
|
|
243934
244152
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
243935
244153
|
|
|
243936
244154
|
// src/commands/skill/tools.ts
|
|
243937
|
-
import { join as
|
|
244155
|
+
import { join as join10 } from "node:path";
|
|
243938
244156
|
var SKILL_NAME = "eigenpal";
|
|
243939
244157
|
var TOOLS = [
|
|
243940
244158
|
{
|
|
243941
244159
|
id: "claude",
|
|
243942
244160
|
label: "Claude Code",
|
|
243943
|
-
relativePath:
|
|
244161
|
+
relativePath: join10(".claude", "skills", SKILL_NAME),
|
|
243944
244162
|
detectPaths: [".claude", "CLAUDE.md"]
|
|
243945
244163
|
},
|
|
243946
244164
|
{
|
|
243947
244165
|
id: "cursor",
|
|
243948
244166
|
label: "Cursor",
|
|
243949
|
-
relativePath:
|
|
244167
|
+
relativePath: join10(".cursor", "skills", SKILL_NAME),
|
|
243950
244168
|
detectPaths: [".cursor", ".cursorrules"]
|
|
243951
244169
|
},
|
|
243952
244170
|
{
|
|
243953
244171
|
id: "codex",
|
|
243954
244172
|
label: "Codex",
|
|
243955
|
-
relativePath:
|
|
244173
|
+
relativePath: join10(".codex", "skills", SKILL_NAME),
|
|
243956
244174
|
detectPaths: [".codex"]
|
|
243957
244175
|
},
|
|
243958
244176
|
{
|
|
243959
244177
|
id: "gemini",
|
|
243960
244178
|
label: "Gemini CLI",
|
|
243961
|
-
relativePath:
|
|
244179
|
+
relativePath: join10(".gemini", "skills", SKILL_NAME),
|
|
243962
244180
|
detectPaths: [".gemini", "GEMINI.md"]
|
|
243963
244181
|
},
|
|
243964
244182
|
{
|
|
243965
244183
|
id: "antigravity",
|
|
243966
244184
|
label: "Antigravity",
|
|
243967
|
-
relativePath:
|
|
244185
|
+
relativePath: join10(".agent", "skills", SKILL_NAME),
|
|
243968
244186
|
detectPaths: [".agent"]
|
|
243969
244187
|
},
|
|
243970
244188
|
{
|
|
243971
244189
|
id: "opencode",
|
|
243972
244190
|
label: "OpenCode",
|
|
243973
|
-
relativePath:
|
|
244191
|
+
relativePath: join10(".opencode", "skills", SKILL_NAME),
|
|
243974
244192
|
detectPaths: [".opencode"]
|
|
243975
244193
|
},
|
|
243976
244194
|
{
|
|
243977
244195
|
id: "pi",
|
|
243978
244196
|
label: "Pi",
|
|
243979
|
-
relativePath:
|
|
244197
|
+
relativePath: join10(".pi", "skills", SKILL_NAME),
|
|
243980
244198
|
detectPaths: [".pi"]
|
|
243981
244199
|
},
|
|
243982
244200
|
{
|
|
243983
244201
|
id: "windsurf",
|
|
243984
244202
|
label: "Windsurf",
|
|
243985
|
-
relativePath:
|
|
244203
|
+
relativePath: join10(".windsurf", "skills", SKILL_NAME),
|
|
243986
244204
|
detectPaths: [".windsurf", ".windsurfrules"]
|
|
243987
244205
|
},
|
|
243988
244206
|
{
|
|
243989
244207
|
id: "github-copilot",
|
|
243990
244208
|
label: "GitHub Copilot",
|
|
243991
|
-
relativePath:
|
|
244209
|
+
relativePath: join10(".github", "skills", SKILL_NAME),
|
|
243992
244210
|
detectPaths: [
|
|
243993
|
-
|
|
243994
|
-
|
|
243995
|
-
|
|
243996
|
-
|
|
243997
|
-
|
|
243998
|
-
|
|
243999
|
-
|
|
244211
|
+
join10(".github", "copilot-instructions.md"),
|
|
244212
|
+
join10(".github", "instructions"),
|
|
244213
|
+
join10(".github", "prompts"),
|
|
244214
|
+
join10(".github", "agents"),
|
|
244215
|
+
join10(".github", "skills"),
|
|
244216
|
+
join10(".github", "workflows", "copilot-setup-steps.yml"),
|
|
244217
|
+
join10(".github", ".mcp.json")
|
|
244000
244218
|
]
|
|
244001
244219
|
}
|
|
244002
244220
|
];
|
|
@@ -244004,7 +244222,7 @@ var TOOLS = [
|
|
|
244004
244222
|
// src/commands/skill/index.ts
|
|
244005
244223
|
var MANIFEST_NAME = ".eigenpal-manifest.json";
|
|
244006
244224
|
function resolveSkillSource() {
|
|
244007
|
-
const here =
|
|
244225
|
+
const here = dirname6(fileURLToPath7(import.meta.url));
|
|
244008
244226
|
const srcCandidate = resolve7(here, "..", "..", "skill");
|
|
244009
244227
|
if (existsSync17(srcCandidate))
|
|
244010
244228
|
return srcCandidate;
|
|
@@ -244016,7 +244234,7 @@ function resolveSkillSource() {
|
|
|
244016
244234
|
${distCandidate}`);
|
|
244017
244235
|
}
|
|
244018
244236
|
function defaultClaudeTarget() {
|
|
244019
|
-
return
|
|
244237
|
+
return join11(process.cwd(), TOOLS[0].relativePath);
|
|
244020
244238
|
}
|
|
244021
244239
|
function resolveSkillTarget(opts) {
|
|
244022
244240
|
return opts.target ?? defaultClaudeTarget();
|
|
@@ -244044,12 +244262,12 @@ async function installSkill(opts) {
|
|
|
244044
244262
|
let skipped = 0;
|
|
244045
244263
|
let prompted = 0;
|
|
244046
244264
|
for (const relativePath of sourceFiles) {
|
|
244047
|
-
const sourcePath =
|
|
244048
|
-
const targetPath =
|
|
244265
|
+
const sourcePath = join11(source, relativePath);
|
|
244266
|
+
const targetPath = join11(target, relativePath);
|
|
244049
244267
|
const sourceBytes = templateSourceFile(relativePath, readFileSync17(sourcePath), cliVersion);
|
|
244050
244268
|
const sourceHash = sha256(sourceBytes);
|
|
244051
244269
|
if (!existsSync17(targetPath)) {
|
|
244052
|
-
mkdirSync6(
|
|
244270
|
+
mkdirSync6(dirname6(targetPath), { recursive: true });
|
|
244053
244271
|
writeFileSync8(targetPath, sourceBytes);
|
|
244054
244272
|
written += 1;
|
|
244055
244273
|
continue;
|
|
@@ -244085,7 +244303,7 @@ async function installSkill(opts) {
|
|
|
244085
244303
|
}
|
|
244086
244304
|
const manifestEntries = [];
|
|
244087
244305
|
for (const relativePath of sourceFiles) {
|
|
244088
|
-
const targetPath =
|
|
244306
|
+
const targetPath = join11(target, relativePath);
|
|
244089
244307
|
if (!existsSync17(targetPath))
|
|
244090
244308
|
continue;
|
|
244091
244309
|
manifestEntries.push({ path: relativePath, sha256: sha256(readFileSync17(targetPath)) });
|
|
@@ -244095,21 +244313,21 @@ async function installSkill(opts) {
|
|
|
244095
244313
|
installedAt: new Date().toISOString(),
|
|
244096
244314
|
files: manifestEntries
|
|
244097
244315
|
};
|
|
244098
|
-
writeFileSync8(
|
|
244316
|
+
writeFileSync8(join11(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
|
|
244099
244317
|
`);
|
|
244100
|
-
const displayTarget =
|
|
244318
|
+
const displayTarget = relative4(process.cwd(), target) || target;
|
|
244101
244319
|
success(`Installed skill at ${ui.bold(displayTarget)} — ${written} written, ${skipped} unchanged${prompted > 0 ? `, ${prompted} prompted` : ""}.`);
|
|
244102
244320
|
}
|
|
244103
244321
|
async function uninstallSkill(opts) {
|
|
244104
244322
|
const target = resolveSkillTarget(opts);
|
|
244105
244323
|
const manifest = readManifest(target);
|
|
244106
244324
|
if (!manifest) {
|
|
244107
|
-
error2(`No manifest found at ${
|
|
244325
|
+
error2(`No manifest found at ${join11(target, MANIFEST_NAME)}; nothing to uninstall.`);
|
|
244108
244326
|
process.exit(1);
|
|
244109
244327
|
}
|
|
244110
244328
|
if (!opts.yes && isInteractiveStdout()) {
|
|
244111
244329
|
const proceed = await ue({
|
|
244112
|
-
message: `Remove ${manifest.files.length} files from ${
|
|
244330
|
+
message: `Remove ${manifest.files.length} files from ${relative4(process.cwd(), target) || target}?`,
|
|
244113
244331
|
initialValue: false
|
|
244114
244332
|
});
|
|
244115
244333
|
if (q(proceed) || !proceed) {
|
|
@@ -244139,9 +244357,9 @@ async function uninstallSkill(opts) {
|
|
|
244139
244357
|
unlinkSync2(path);
|
|
244140
244358
|
removed += 1;
|
|
244141
244359
|
}
|
|
244142
|
-
rmSync2(
|
|
244360
|
+
rmSync2(join11(target, MANIFEST_NAME), { force: true });
|
|
244143
244361
|
pruneEmptyDirs(target);
|
|
244144
|
-
const displayTarget =
|
|
244362
|
+
const displayTarget = relative4(process.cwd(), target) || target;
|
|
244145
244363
|
success(`Uninstalled skill from ${ui.bold(displayTarget)} — ${removed} removed${kept > 0 ? `, ${kept} user-edited kept` : ""}.`);
|
|
244146
244364
|
}
|
|
244147
244365
|
async function installSkillTools(opts) {
|
|
@@ -244200,14 +244418,14 @@ async function installSkillTools(opts) {
|
|
|
244200
244418
|
for (const tool of toInstall) {
|
|
244201
244419
|
await installSkill({
|
|
244202
244420
|
source: opts.source,
|
|
244203
|
-
target:
|
|
244421
|
+
target: join11(cwd, tool.relativePath),
|
|
244204
244422
|
force: opts.force,
|
|
244205
244423
|
yes: opts.yes
|
|
244206
244424
|
});
|
|
244207
244425
|
}
|
|
244208
244426
|
for (const tool of toUninstall) {
|
|
244209
244427
|
await uninstallSkill({
|
|
244210
|
-
target:
|
|
244428
|
+
target: join11(cwd, tool.relativePath),
|
|
244211
244429
|
yes: true
|
|
244212
244430
|
});
|
|
244213
244431
|
}
|
|
@@ -244271,7 +244489,7 @@ async function uninstallSkillTools(opts) {
|
|
|
244271
244489
|
}
|
|
244272
244490
|
for (const tool of targets) {
|
|
244273
244491
|
await uninstallSkill({
|
|
244274
|
-
target:
|
|
244492
|
+
target: join11(cwd, tool.relativePath),
|
|
244275
244493
|
yes: true
|
|
244276
244494
|
});
|
|
244277
244495
|
}
|
|
@@ -244279,7 +244497,7 @@ async function uninstallSkillTools(opts) {
|
|
|
244279
244497
|
function listSkillTools(opts = {}) {
|
|
244280
244498
|
const cwd = process.cwd();
|
|
244281
244499
|
const rows = TOOLS.flatMap((tool) => {
|
|
244282
|
-
const targetDir =
|
|
244500
|
+
const targetDir = join11(cwd, tool.relativePath);
|
|
244283
244501
|
const manifest = readManifest(targetDir);
|
|
244284
244502
|
if (!manifest)
|
|
244285
244503
|
return [];
|
|
@@ -244332,10 +244550,10 @@ function hintFor(tool, installed, detected) {
|
|
|
244332
244550
|
return tool.relativePath;
|
|
244333
244551
|
}
|
|
244334
244552
|
function isInstalled(cwd, tool) {
|
|
244335
|
-
return existsSync17(
|
|
244553
|
+
return existsSync17(join11(cwd, tool.relativePath, MANIFEST_NAME));
|
|
244336
244554
|
}
|
|
244337
244555
|
function isProjectUsing(cwd, tool) {
|
|
244338
|
-
return tool.detectPaths.some((p) => existsSync17(
|
|
244556
|
+
return tool.detectPaths.some((p) => existsSync17(join11(cwd, p)));
|
|
244339
244557
|
}
|
|
244340
244558
|
function listFiles(root) {
|
|
244341
244559
|
const out = [];
|
|
@@ -244343,8 +244561,8 @@ function listFiles(root) {
|
|
|
244343
244561
|
while (stack.length > 0) {
|
|
244344
244562
|
const dir = stack.pop();
|
|
244345
244563
|
for (const entry of readdirSync5(dir)) {
|
|
244346
|
-
const full =
|
|
244347
|
-
const rel =
|
|
244564
|
+
const full = join11(dir, entry);
|
|
244565
|
+
const rel = relative4(root, full);
|
|
244348
244566
|
const stats = lstatSync(full);
|
|
244349
244567
|
if (stats.isDirectory()) {
|
|
244350
244568
|
stack.push(full);
|
|
@@ -244358,7 +244576,7 @@ function listFiles(root) {
|
|
|
244358
244576
|
return out.sort();
|
|
244359
244577
|
}
|
|
244360
244578
|
function readManifest(target) {
|
|
244361
|
-
const path =
|
|
244579
|
+
const path = join11(target, MANIFEST_NAME);
|
|
244362
244580
|
if (!existsSync17(path))
|
|
244363
244581
|
return null;
|
|
244364
244582
|
try {
|
|
@@ -244369,7 +244587,7 @@ function readManifest(target) {
|
|
|
244369
244587
|
}
|
|
244370
244588
|
function readCliVersion() {
|
|
244371
244589
|
try {
|
|
244372
|
-
const here =
|
|
244590
|
+
const here = dirname6(fileURLToPath7(import.meta.url));
|
|
244373
244591
|
const candidates = [
|
|
244374
244592
|
resolve7(here, "..", "..", "..", "package.json"),
|
|
244375
244593
|
resolve7(here, "..", "..", "package.json"),
|
|
@@ -244393,7 +244611,7 @@ function pruneEmptyDirs(root) {
|
|
|
244393
244611
|
const stack = [];
|
|
244394
244612
|
const collect = (dir) => {
|
|
244395
244613
|
for (const entry of readdirSync5(dir)) {
|
|
244396
|
-
const full =
|
|
244614
|
+
const full = join11(dir, entry);
|
|
244397
244615
|
if (lstatSync(full).isDirectory())
|
|
244398
244616
|
collect(full);
|
|
244399
244617
|
}
|
|
@@ -244408,7 +244626,7 @@ function pruneEmptyDirs(root) {
|
|
|
244408
244626
|
}
|
|
244409
244627
|
}
|
|
244410
244628
|
async function promptThreeWay(path, source, current) {
|
|
244411
|
-
const display =
|
|
244629
|
+
const display = relative4(process.cwd(), path) || path;
|
|
244412
244630
|
while (true) {
|
|
244413
244631
|
const choice = await Ee({
|
|
244414
244632
|
message: `${display} has been edited locally`,
|
|
@@ -245191,7 +245409,7 @@ import path19 from "node:path";
|
|
|
245191
245409
|
// src/lib/local-templates.ts
|
|
245192
245410
|
init_src();
|
|
245193
245411
|
import { existsSync as existsSync18, promises as fs18, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
|
|
245194
|
-
import { basename, dirname as
|
|
245412
|
+
import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute2, relative as relative5, resolve as resolve8, sep } from "node:path";
|
|
245195
245413
|
|
|
245196
245414
|
// src/lib/office-template.ts
|
|
245197
245415
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -245436,11 +245654,11 @@ function resolveWorkflowProjectRoot(workflowFile) {
|
|
|
245436
245654
|
if (!existsSync18(abs)) {
|
|
245437
245655
|
throw new Error(`Workflow file not found: ${abs}`);
|
|
245438
245656
|
}
|
|
245439
|
-
return
|
|
245657
|
+
return dirname7(realpathSync3(abs));
|
|
245440
245658
|
}
|
|
245441
245659
|
function isPathInsideRoot(root, target) {
|
|
245442
|
-
const rel =
|
|
245443
|
-
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !
|
|
245660
|
+
const rel = relative5(root, target);
|
|
245661
|
+
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
|
|
245444
245662
|
}
|
|
245445
245663
|
function assertInsideProject(projectRoot, templatePath, resolved) {
|
|
245446
245664
|
if (isPathInsideRoot(projectRoot, resolved))
|
|
@@ -245495,12 +245713,12 @@ async function loadLocalTemplatesForPush(workflowFile, parsedSteps, opts = {}) {
|
|
|
245495
245713
|
}
|
|
245496
245714
|
const absolutePath = resolveWorkflowTemplatePath(workflowFile, ref.templatePath, opts);
|
|
245497
245715
|
const bytes = await fs18.readFile(absolutePath);
|
|
245498
|
-
inspectOfficeTemplateBytes(bytes,
|
|
245716
|
+
inspectOfficeTemplateBytes(bytes, basename2(absolutePath));
|
|
245499
245717
|
const row = {
|
|
245500
245718
|
path: ref.templatePath,
|
|
245501
245719
|
fieldPath: ref.fieldPath,
|
|
245502
245720
|
absolutePath,
|
|
245503
|
-
filename:
|
|
245721
|
+
filename: basename2(absolutePath),
|
|
245504
245722
|
bytes,
|
|
245505
245723
|
sha256: sha256Hex(bytes)
|
|
245506
245724
|
};
|
|
@@ -245639,12 +245857,12 @@ function rewriteLocalTemplateYaml(yamlText, resolved) {
|
|
|
245639
245857
|
|
|
245640
245858
|
// src/commands/workflow/clear.ts
|
|
245641
245859
|
import { existsSync as existsSync19, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync6 } from "fs";
|
|
245642
|
-
import { basename as
|
|
245860
|
+
import { basename as basename3, join as join12 } from "path";
|
|
245643
245861
|
var EMPTY_REPORT = { removed: 0, kept: 0, touched: 0 };
|
|
245644
245862
|
function getDirectoryEntries(path) {
|
|
245645
245863
|
if (!existsSync19(path))
|
|
245646
245864
|
return [];
|
|
245647
|
-
return readdirSync6(path).filter((entry) => statSync6(
|
|
245865
|
+
return readdirSync6(path).filter((entry) => statSync6(join12(path, entry)).isDirectory()).sort();
|
|
245648
245866
|
}
|
|
245649
245867
|
function removeDirEntriesWithRetention(path, removeAll) {
|
|
245650
245868
|
const entries = getDirectoryEntries(path);
|
|
@@ -245657,7 +245875,7 @@ function removeDirEntriesWithRetention(path, removeAll) {
|
|
|
245657
245875
|
for (const entry of entries) {
|
|
245658
245876
|
if (keepSet.has(entry))
|
|
245659
245877
|
continue;
|
|
245660
|
-
rmSync3(
|
|
245878
|
+
rmSync3(join12(path, entry), { recursive: true, force: true });
|
|
245661
245879
|
removed++;
|
|
245662
245880
|
}
|
|
245663
245881
|
return { removed, kept: keepSet.size, touched: entries.length };
|
|
@@ -245684,7 +245902,7 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
|
|
|
245684
245902
|
kept++;
|
|
245685
245903
|
continue;
|
|
245686
245904
|
}
|
|
245687
|
-
rmSync3(
|
|
245905
|
+
rmSync3(join12(exampleDir, fileName), { force: true });
|
|
245688
245906
|
removed++;
|
|
245689
245907
|
}
|
|
245690
245908
|
return { removed, kept, touched: stampByFile.size };
|
|
@@ -245692,17 +245910,17 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
|
|
|
245692
245910
|
function getTargetExampleDirs(dir, exampleNames) {
|
|
245693
245911
|
const baseDir = resolveEvalBaseDir(dir);
|
|
245694
245912
|
if (!baseDir) {
|
|
245695
|
-
error2(`No dataset/examples directory at ${
|
|
245913
|
+
error2(`No dataset/examples directory at ${join12(dir, "dataset", "examples")}`);
|
|
245696
245914
|
process.exit(1);
|
|
245697
245915
|
}
|
|
245698
|
-
const all = readdirSync6(baseDir).filter((entry) => statSync6(
|
|
245916
|
+
const all = readdirSync6(baseDir).filter((entry) => statSync6(join12(baseDir, entry)).isDirectory());
|
|
245699
245917
|
if (exampleNames.length === 0)
|
|
245700
|
-
return all.map((name) =>
|
|
245918
|
+
return all.map((name) => join12(baseDir, name));
|
|
245701
245919
|
const matched = all.filter((name) => exampleNames.includes(name));
|
|
245702
245920
|
if (matched.length === 0) {
|
|
245703
245921
|
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).`);
|
|
245704
245922
|
}
|
|
245705
|
-
return matched.map((name) =>
|
|
245923
|
+
return matched.map((name) => join12(baseDir, name));
|
|
245706
245924
|
}
|
|
245707
245925
|
function runSection(args) {
|
|
245708
245926
|
let removed = 0;
|
|
@@ -245718,7 +245936,7 @@ function runSection(args) {
|
|
|
245718
245936
|
kept += report.kept;
|
|
245719
245937
|
touched += report.touched;
|
|
245720
245938
|
if (report.touched > 0) {
|
|
245721
|
-
const name =
|
|
245939
|
+
const name = basename3(exampleDir);
|
|
245722
245940
|
console.log(` ${ui.dim(`${name}:`)} removed ${ui.bold(String(report.removed))} ${args.perExampleNoun}, kept ${report.kept}`);
|
|
245723
245941
|
}
|
|
245724
245942
|
}
|
|
@@ -245734,8 +245952,8 @@ async function clearEvalOutputs(dir, exampleNames = [], options = {}) {
|
|
|
245734
245952
|
const exampleDirs = getTargetExampleDirs(dir, exampleNames);
|
|
245735
245953
|
runSection({
|
|
245736
245954
|
exampleDirs,
|
|
245737
|
-
clean: (exampleDir) => removeDirEntriesWithRetention(
|
|
245738
|
-
shouldCount: (exampleDir) => existsSync19(
|
|
245955
|
+
clean: (exampleDir) => removeDirEntriesWithRetention(join12(exampleDir, "executions"), removeAll),
|
|
245956
|
+
shouldCount: (exampleDir) => existsSync19(join12(exampleDir, "executions")),
|
|
245739
245957
|
successLabel: "Execution cleanup complete",
|
|
245740
245958
|
scannedLabel: "examples scanned:",
|
|
245741
245959
|
seenLabel: "runs seen: ",
|
|
@@ -246122,7 +246340,7 @@ function registerStepExecCommands(workflow) {
|
|
|
246122
246340
|
// src/commands/workflow/templates.ts
|
|
246123
246341
|
init_src();
|
|
246124
246342
|
import { existsSync as existsSync20, promises as fs20 } from "node:fs";
|
|
246125
|
-
import { basename as
|
|
246343
|
+
import { basename as basename4, resolve as resolve9 } from "node:path";
|
|
246126
246344
|
function buildClient5(opts) {
|
|
246127
246345
|
const config = resolveConfig(opts);
|
|
246128
246346
|
requireApiKey(config);
|
|
@@ -246190,7 +246408,7 @@ function registerTemplateCommands(parent) {
|
|
|
246190
246408
|
const client = buildClient5(opts);
|
|
246191
246409
|
const template = await uploadWorkspaceTemplate(client, {
|
|
246192
246410
|
bytes,
|
|
246193
|
-
filename:
|
|
246411
|
+
filename: basename4(filePath),
|
|
246194
246412
|
name: opts.name,
|
|
246195
246413
|
description: opts.description
|
|
246196
246414
|
});
|
|
@@ -246254,7 +246472,7 @@ function registerTemplateCommands(parent) {
|
|
|
246254
246472
|
const bytes = await fs20.readFile(filePath);
|
|
246255
246473
|
const client = buildClient5(opts);
|
|
246256
246474
|
const current = await getPublicTemplate(client, templateId);
|
|
246257
|
-
const nextInspection = inspectOfficeTemplateBytes(bytes,
|
|
246475
|
+
const nextInspection = inspectOfficeTemplateBytes(bytes, basename4(filePath));
|
|
246258
246476
|
if (current.currentRevision?.sha256 === nextInspection.sha256 || current.sha256 === nextInspection.sha256) {
|
|
246259
246477
|
if (opts.json) {
|
|
246260
246478
|
printJson5({ ...current, reused: true });
|
|
@@ -246266,7 +246484,7 @@ function registerTemplateCommands(parent) {
|
|
|
246266
246484
|
}
|
|
246267
246485
|
const template = await replaceWorkspaceTemplate(client, templateId, {
|
|
246268
246486
|
bytes,
|
|
246269
|
-
filename:
|
|
246487
|
+
filename: basename4(filePath)
|
|
246270
246488
|
});
|
|
246271
246489
|
if (opts.json) {
|
|
246272
246490
|
printJson5(template);
|
|
@@ -246306,7 +246524,7 @@ function registerTemplateCommands(parent) {
|
|
|
246306
246524
|
throw new Error(`Template file not found: ${filePath}. Pass a local .docx/.xlsx path or a tmpl_… id.`);
|
|
246307
246525
|
}
|
|
246308
246526
|
bytes = await fs20.readFile(filePath);
|
|
246309
|
-
filename =
|
|
246527
|
+
filename = basename4(filePath);
|
|
246310
246528
|
}
|
|
246311
246529
|
const rendered = renderLocalOfficeTemplate(bytes, filename, data);
|
|
246312
246530
|
const { unresolved, unusedDataKeys } = compareTemplateDataKeys(rendered.inspection.tokens, Object.keys(data));
|
|
@@ -246345,7 +246563,7 @@ function registerTemplateCommands(parent) {
|
|
|
246345
246563
|
// src/commands/workflow/validation.ts
|
|
246346
246564
|
init_src();
|
|
246347
246565
|
import { existsSync as existsSync22, readdirSync as readdirSync7, readFileSync as readFileSync19, statSync as statSync7 } from "fs";
|
|
246348
|
-
import { join as
|
|
246566
|
+
import { join as join13, resolve as resolve10 } from "path";
|
|
246349
246567
|
|
|
246350
246568
|
// src/lib/template-diagnostics.ts
|
|
246351
246569
|
init_src();
|
|
@@ -246752,19 +246970,19 @@ function validateDatasetFolder(root) {
|
|
|
246752
246970
|
if (!existsSync22(root)) {
|
|
246753
246971
|
return [{ field: root, message: "Folder not found." }];
|
|
246754
246972
|
}
|
|
246755
|
-
if (existsSync22(
|
|
246973
|
+
if (existsSync22(join13(root, "manifest.json"))) {
|
|
246756
246974
|
issues.push({
|
|
246757
246975
|
field: "manifest.json",
|
|
246758
246976
|
message: "Top-level manifest.json is the legacy format. Re-export the dataset using the folder convention."
|
|
246759
246977
|
});
|
|
246760
246978
|
}
|
|
246761
|
-
const examplesDir =
|
|
246979
|
+
const examplesDir = join13(root, "examples");
|
|
246762
246980
|
if (!existsSync22(examplesDir)) {
|
|
246763
246981
|
issues.push({ field: "examples/", message: "No examples/ directory found at dataset root." });
|
|
246764
246982
|
return issues;
|
|
246765
246983
|
}
|
|
246766
246984
|
for (const exampleName of readdirSync7(examplesDir)) {
|
|
246767
|
-
const exampleFolder =
|
|
246985
|
+
const exampleFolder = join13(examplesDir, exampleName);
|
|
246768
246986
|
if (!isDirSafe(exampleFolder, issues, `examples/${exampleName}`))
|
|
246769
246987
|
continue;
|
|
246770
246988
|
if (!NAME_RE.test(exampleName)) {
|
|
@@ -246774,7 +246992,7 @@ function validateDatasetFolder(root) {
|
|
|
246774
246992
|
});
|
|
246775
246993
|
continue;
|
|
246776
246994
|
}
|
|
246777
|
-
const inputJsonPath =
|
|
246995
|
+
const inputJsonPath = join13(exampleFolder, "input.json");
|
|
246778
246996
|
const hasInputJson = existsSync22(inputJsonPath);
|
|
246779
246997
|
if (!hasInputJson) {
|
|
246780
246998
|
issues.push({
|
|
@@ -246801,8 +247019,8 @@ function validateDatasetFolder(root) {
|
|
|
246801
247019
|
});
|
|
246802
247020
|
continue;
|
|
246803
247021
|
}
|
|
246804
|
-
const inputDir =
|
|
246805
|
-
if (existsSync22(
|
|
247022
|
+
const inputDir = join13(exampleFolder, "input");
|
|
247023
|
+
if (existsSync22(join13(inputDir, "arguments.json"))) {
|
|
246806
247024
|
issues.push({
|
|
246807
247025
|
field: `examples/${exampleName}/input/arguments.json`,
|
|
246808
247026
|
message: "Legacy input/arguments.json is no longer accepted. Use input.json instead."
|
|
@@ -246817,8 +247035,8 @@ function validateDatasetFolder(root) {
|
|
|
246817
247035
|
})) {
|
|
246818
247036
|
issues.push(issue);
|
|
246819
247037
|
}
|
|
246820
|
-
const expectedDir =
|
|
246821
|
-
const expectedJsonPath =
|
|
247038
|
+
const expectedDir = join13(exampleFolder, "expected");
|
|
247039
|
+
const expectedJsonPath = join13(exampleFolder, "expected.json");
|
|
246822
247040
|
if (existsSync22(expectedDir)) {
|
|
246823
247041
|
for (const entry of readdirSync7(expectedDir)) {
|
|
246824
247042
|
if (entry === "output.json" || entry === "error.json") {
|
|
@@ -246828,7 +247046,7 @@ function validateDatasetFolder(root) {
|
|
|
246828
247046
|
});
|
|
246829
247047
|
continue;
|
|
246830
247048
|
}
|
|
246831
|
-
const sub =
|
|
247049
|
+
const sub = join13(expectedDir, entry);
|
|
246832
247050
|
const field = `examples/${exampleName}/expected/${entry}`;
|
|
246833
247051
|
let isDir;
|
|
246834
247052
|
try {
|
|
@@ -246884,7 +247102,7 @@ function validateDatasetFolder(root) {
|
|
|
246884
247102
|
} else {
|
|
246885
247103
|
for (const issue of validateFileRefs2({
|
|
246886
247104
|
refs: collectDatasetFileRefs(parsed),
|
|
246887
|
-
filesRoot:
|
|
247105
|
+
filesRoot: join13(exampleFolder, "expected"),
|
|
246888
247106
|
root: "expected",
|
|
246889
247107
|
fieldPrefix: `examples/${exampleName}/expected.json`
|
|
246890
247108
|
})) {
|
|
@@ -246937,7 +247155,7 @@ function validateFileRefs2(args) {
|
|
|
246937
247155
|
});
|
|
246938
247156
|
continue;
|
|
246939
247157
|
}
|
|
246940
|
-
if (!existsSync22(
|
|
247158
|
+
if (!existsSync22(join13(args.filesRoot, relative))) {
|
|
246941
247159
|
issues.push({
|
|
246942
247160
|
field: `${args.fieldPrefix}:${ref.jsonPath}`,
|
|
246943
247161
|
message: `Referenced file does not exist: ${ref.path}.`
|
|
@@ -246969,24 +247187,24 @@ async function onlineInvokeIssues(yamlText, opts) {
|
|
|
246969
247187
|
}
|
|
246970
247188
|
function discoverWorkflowProjectRoots(rootPath) {
|
|
246971
247189
|
const root = resolve10(rootPath);
|
|
246972
|
-
if (existsSync22(
|
|
247190
|
+
if (existsSync22(join13(root, "workflow.yaml")))
|
|
246973
247191
|
return [root];
|
|
246974
247192
|
const candidates = [
|
|
246975
|
-
|
|
246976
|
-
|
|
246977
|
-
root.endsWith(
|
|
247193
|
+
join13(root, "eigenpal", "workflows"),
|
|
247194
|
+
join13(root, "workflows"),
|
|
247195
|
+
root.endsWith(join13("eigenpal", "workflows")) ? root : ""
|
|
246978
247196
|
].filter(Boolean);
|
|
246979
247197
|
for (const parent of candidates) {
|
|
246980
247198
|
if (!existsSync22(parent) || !statSync7(parent).isDirectory())
|
|
246981
247199
|
continue;
|
|
246982
|
-
const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync22(
|
|
247200
|
+
const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync22(join13(parent, entry.name, "workflow.yaml"))).map((entry) => join13(parent, entry.name)).sort();
|
|
246983
247201
|
if (projects.length > 0)
|
|
246984
247202
|
return projects;
|
|
246985
247203
|
}
|
|
246986
247204
|
return [];
|
|
246987
247205
|
}
|
|
246988
247206
|
async function validateProjectRoot(root, opts) {
|
|
246989
|
-
const wfFile =
|
|
247207
|
+
const wfFile = join13(root, "workflow.yaml");
|
|
246990
247208
|
const wfResult = validateWorkflowYaml(wfFile);
|
|
246991
247209
|
const wfPath = relPath(root, wfFile);
|
|
246992
247210
|
const wfOk = printIssues("workflow.yaml", wfPath, wfResult.issues);
|
|
@@ -246994,8 +247212,8 @@ async function validateProjectRoot(root, opts) {
|
|
|
246994
247212
|
printSchemaQualityWarnings(wfPath, wfResult.warnings);
|
|
246995
247213
|
printInvokeOnlineHint(wfResult.invokeStepCount, wfResult.templateStepCount, opts.online);
|
|
246996
247214
|
}
|
|
246997
|
-
const evOk = printIssues("evaluators.yaml", relPath(root,
|
|
246998
|
-
const dsOk = printIssues("dataset/", relPath(root,
|
|
247215
|
+
const evOk = printIssues("evaluators.yaml", relPath(root, join13(root, "evaluators.yaml")), validateEvaluatorsYaml(join13(root, "evaluators.yaml")));
|
|
247216
|
+
const dsOk = printIssues("dataset/", relPath(root, join13(root, "dataset")), validateDatasetFolder(join13(root, "dataset")));
|
|
246999
247217
|
const templateOk = wfOk && existsSync22(wfFile) ? await runTemplateDiagnostics(wfFile, wfResult.steps, opts) : true;
|
|
247000
247218
|
let onlineOk = true;
|
|
247001
247219
|
if (wfOk && opts.online && existsSync22(wfFile)) {
|