@eigenpal/cli 0.4.17 → 0.5.2
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 +1 -0
- package/dist/cli.js +802 -123
- package/dist/skill/SKILL.md +264 -444
- package/dist/skill/reference/cli/agent.md +536 -98
- package/dist/skill/reference/cli/auth.md +5 -5
- package/dist/skill/reference/cli/skill.md +5 -5
- package/dist/skill/reference/cli/workflow.md +76 -76
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1019,7 +1019,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1019
1019
|
this._exitCallback = (err) => {
|
|
1020
1020
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
1021
1021
|
throw err;
|
|
1022
|
-
}
|
|
1022
|
+
}
|
|
1023
1023
|
};
|
|
1024
1024
|
}
|
|
1025
1025
|
return this;
|
|
@@ -20343,7 +20343,7 @@ function finalize(ctx, schema) {
|
|
|
20343
20343
|
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
20344
20344
|
} else if (ctx.target === "draft-04") {
|
|
20345
20345
|
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
20346
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
20346
|
+
} else if (ctx.target === "openapi-3.0") {}
|
|
20347
20347
|
if (ctx.external?.uri) {
|
|
20348
20348
|
const id = ctx.external.registry.get(schema)?.id;
|
|
20349
20349
|
if (!id)
|
|
@@ -20604,7 +20604,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
20604
20604
|
if (val === undefined) {
|
|
20605
20605
|
if (ctx.unrepresentable === "throw") {
|
|
20606
20606
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
20607
|
-
}
|
|
20607
|
+
}
|
|
20608
20608
|
} else if (typeof val === "bigint") {
|
|
20609
20609
|
if (ctx.unrepresentable === "throw") {
|
|
20610
20610
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -27388,7 +27388,7 @@ var require_tracestate_impl = __commonJS((exports) => {
|
|
|
27388
27388
|
const value = listMember.slice(i + 1, part.length);
|
|
27389
27389
|
if ((0, tracestate_validators_1.validateKey)(key) && (0, tracestate_validators_1.validateValue)(value)) {
|
|
27390
27390
|
agg.set(key, value);
|
|
27391
|
-
}
|
|
27391
|
+
}
|
|
27392
27392
|
}
|
|
27393
27393
|
return agg;
|
|
27394
27394
|
}, new Map);
|
|
@@ -67182,72 +67182,6 @@ var init_workflow = __esm(() => {
|
|
|
67182
67182
|
});
|
|
67183
67183
|
});
|
|
67184
67184
|
|
|
67185
|
-
// ../types/src/workflow/eval-config.ts
|
|
67186
|
-
function parseEvalConfig(raw) {
|
|
67187
|
-
return EvalConfigSchema.parse(raw ?? {});
|
|
67188
|
-
}
|
|
67189
|
-
function parseEvalConfigForForm(raw) {
|
|
67190
|
-
return EvalConfigFormSchema.parse(raw ?? {});
|
|
67191
|
-
}
|
|
67192
|
-
function isValidJudgeModel(model) {
|
|
67193
|
-
return JUDGE_MODEL_IDS.includes(model);
|
|
67194
|
-
}
|
|
67195
|
-
function resolveConcurrency(value, defaultNum) {
|
|
67196
|
-
const clamp = (n) => Math.min(MAX_CONCURRENCY, Math.max(1, n));
|
|
67197
|
-
if (value == null) {
|
|
67198
|
-
const d2 = clamp(defaultNum);
|
|
67199
|
-
return { executions: d2, judge: d2 };
|
|
67200
|
-
}
|
|
67201
|
-
if (typeof value === "number") {
|
|
67202
|
-
const d2 = clamp(value);
|
|
67203
|
-
return { executions: d2, judge: d2 };
|
|
67204
|
-
}
|
|
67205
|
-
return {
|
|
67206
|
-
executions: clamp(value.executions ?? defaultNum),
|
|
67207
|
-
judge: clamp(value.judge ?? defaultNum)
|
|
67208
|
-
};
|
|
67209
|
-
}
|
|
67210
|
-
var JUDGE_MODEL_IDS, JudgeModelSchema, DEFAULT_JUDGE_MODEL = "gpt-5.2", DEFAULT_CONCURRENCY = 3, ConcurrencySchema, JudgeConfigSchema, JudgeConfigFormSchema, EvalConfigSchema, EvalConfigFormSchema, MAX_CONCURRENCY = 50, EVAL_CONFIG_FORM_KEYS, EVAL_CONFIG_FIELD_DEFINITIONS;
|
|
67211
|
-
var init_eval_config = __esm(() => {
|
|
67212
|
-
init_zod();
|
|
67213
|
-
JUDGE_MODEL_IDS = ["gpt-4o", "gpt-4o-mini", "gpt-5.2"];
|
|
67214
|
-
JudgeModelSchema = exports_external.enum(JUDGE_MODEL_IDS);
|
|
67215
|
-
ConcurrencySchema = exports_external.union([
|
|
67216
|
-
exports_external.number().int().min(1),
|
|
67217
|
-
exports_external.object({
|
|
67218
|
-
executions: exports_external.number().int().min(1),
|
|
67219
|
-
judge: exports_external.number().int().min(1)
|
|
67220
|
-
})
|
|
67221
|
-
]);
|
|
67222
|
-
JudgeConfigSchema = exports_external.object({
|
|
67223
|
-
prompt: exports_external.string().default(""),
|
|
67224
|
-
model: JudgeModelSchema.default(DEFAULT_JUDGE_MODEL),
|
|
67225
|
-
run: exports_external.boolean().default(true)
|
|
67226
|
-
});
|
|
67227
|
-
JudgeConfigFormSchema = exports_external.object({
|
|
67228
|
-
prompt: exports_external.string().default(""),
|
|
67229
|
-
model: exports_external.string().default(DEFAULT_JUDGE_MODEL),
|
|
67230
|
-
run: exports_external.boolean().default(true)
|
|
67231
|
-
});
|
|
67232
|
-
EvalConfigSchema = exports_external.object({
|
|
67233
|
-
concurrency: ConcurrencySchema.default(DEFAULT_CONCURRENCY),
|
|
67234
|
-
judge: JudgeConfigSchema.prefault({}),
|
|
67235
|
-
defaultOverrides: exports_external.array(exports_external.string()).default([])
|
|
67236
|
-
});
|
|
67237
|
-
EvalConfigFormSchema = exports_external.object({
|
|
67238
|
-
concurrency: ConcurrencySchema.default(DEFAULT_CONCURRENCY),
|
|
67239
|
-
judge: JudgeConfigFormSchema.prefault({}),
|
|
67240
|
-
defaultOverrides: exports_external.array(exports_external.string()).default([])
|
|
67241
|
-
});
|
|
67242
|
-
EVAL_CONFIG_FORM_KEYS = ["judge"];
|
|
67243
|
-
EVAL_CONFIG_FIELD_DEFINITIONS = {
|
|
67244
|
-
judge: {
|
|
67245
|
-
label: "AI review",
|
|
67246
|
-
description: "Optional automated check: an AI compares each run to the expected result using your instructions."
|
|
67247
|
-
}
|
|
67248
|
-
};
|
|
67249
|
-
});
|
|
67250
|
-
|
|
67251
67185
|
// ../types/src/workflow/expected-output.ts
|
|
67252
67186
|
var ExpectedDocumentRefSchema, ExpectedDocumentsValueSchema, ExpectedOutputSchema, ExpectedOutputFilesSchema;
|
|
67253
67187
|
var init_expected_output = __esm(() => {
|
|
@@ -67464,7 +67398,6 @@ var init_workflow2 = __esm(() => {
|
|
|
67464
67398
|
init_actions();
|
|
67465
67399
|
init_steps();
|
|
67466
67400
|
init_workflow();
|
|
67467
|
-
init_eval_config();
|
|
67468
67401
|
init_expected_output();
|
|
67469
67402
|
init_local_meta();
|
|
67470
67403
|
init_email_trigger();
|
|
@@ -68378,12 +68311,9 @@ __export(exports_src, {
|
|
|
68378
68311
|
runInputKey: () => runInputKey,
|
|
68379
68312
|
rootS3Path: () => rootS3Path,
|
|
68380
68313
|
resolveEffectiveMimeType: () => resolveEffectiveMimeType,
|
|
68381
|
-
resolveConcurrency: () => resolveConcurrency,
|
|
68382
68314
|
requiresSpecializedParser: () => requiresSpecializedParser,
|
|
68383
68315
|
parseStepType: () => parseStepType,
|
|
68384
68316
|
parseFileKey: () => parseFileKey,
|
|
68385
|
-
parseEvalConfigForForm: () => parseEvalConfigForForm,
|
|
68386
|
-
parseEvalConfig: () => parseEvalConfig,
|
|
68387
68317
|
noopTracingContext: () => noopTracingContext,
|
|
68388
68318
|
mapOCRAttributes: () => mapOCRAttributes,
|
|
68389
68319
|
mapLLMAttributes: () => mapLLMAttributes,
|
|
@@ -68393,7 +68323,6 @@ __export(exports_src, {
|
|
|
68393
68323
|
judgeScoreJson: () => judgeScoreJson,
|
|
68394
68324
|
judgeLabelJson: () => judgeLabelJson,
|
|
68395
68325
|
isWorkflowResult: () => isWorkflowResult,
|
|
68396
|
-
isValidJudgeModel: () => isValidJudgeModel,
|
|
68397
68326
|
isTerminalExecutionStatus: () => isTerminalExecutionStatus,
|
|
68398
68327
|
isStepCategory: () => isStepCategory,
|
|
68399
68328
|
isOutputSchemaUnknown: () => isOutputSchemaUnknown,
|
|
@@ -68546,10 +68475,8 @@ __export(exports_src, {
|
|
|
68546
68475
|
LayoutElementTypeSchema: () => LayoutElementTypeSchema,
|
|
68547
68476
|
LayoutElementSchema: () => LayoutElementSchema,
|
|
68548
68477
|
LLM_JUDGE_PROMPT_MIN_LENGTH: () => LLM_JUDGE_PROMPT_MIN_LENGTH,
|
|
68549
|
-
JudgeModelSchema: () => JudgeModelSchema,
|
|
68550
68478
|
JudgeModeSchema: () => JudgeModeSchema,
|
|
68551
68479
|
JsonSchemaSchema: () => JsonSchemaSchema,
|
|
68552
|
-
JUDGE_MODEL_IDS: () => JUDGE_MODEL_IDS,
|
|
68553
68480
|
IfStepSchema: () => IfStepSchema,
|
|
68554
68481
|
INPUT_KINDS: () => INPUT_KINDS,
|
|
68555
68482
|
ID_PREFIXES: () => ID_PREFIXES,
|
|
@@ -68582,7 +68509,6 @@ __export(exports_src, {
|
|
|
68582
68509
|
EvalOverridesSchema: () => EvalOverridesSchema,
|
|
68583
68510
|
EvalExampleMetaSchema: () => EvalExampleMetaSchema,
|
|
68584
68511
|
EvalConfigYamlSchema: () => EvalConfigYamlSchema,
|
|
68585
|
-
EvalConfigSchema: () => EvalConfigSchema,
|
|
68586
68512
|
EmailTriggerMethodSchema: () => EmailTriggerMethodSchema,
|
|
68587
68513
|
Eigenpal: () => Eigenpal,
|
|
68588
68514
|
EXECUTION_TYPES: () => EXECUTION_TYPES,
|
|
@@ -68596,8 +68522,6 @@ __export(exports_src, {
|
|
|
68596
68522
|
EXECUTION_AGENT_QUEUED_STATUSES: () => EXECUTION_AGENT_QUEUED_STATUSES,
|
|
68597
68523
|
EXECUTION_AGENT_METRICS_STATUSES: () => EXECUTION_AGENT_METRICS_STATUSES,
|
|
68598
68524
|
EXECUTION_AGENT_CANCEL_REQUESTABLE_STATUSES: () => EXECUTION_AGENT_CANCEL_REQUESTABLE_STATUSES,
|
|
68599
|
-
EVAL_CONFIG_FORM_KEYS: () => EVAL_CONFIG_FORM_KEYS,
|
|
68600
|
-
EVAL_CONFIG_FIELD_DEFINITIONS: () => EVAL_CONFIG_FIELD_DEFINITIONS,
|
|
68601
68525
|
ERROR_HINTS: () => ERROR_HINTS,
|
|
68602
68526
|
DocumentParserOutputSchema: () => DocumentParserOutputSchema,
|
|
68603
68527
|
DocumentParserInputSchema: () => DocumentParserInputSchema,
|
|
@@ -68610,7 +68534,6 @@ __export(exports_src, {
|
|
|
68610
68534
|
DURABLE_EXECUTION_TYPES: () => DURABLE_EXECUTION_TYPES,
|
|
68611
68535
|
DETERMINISTIC_TEMPERATURE: () => DETERMINISTIC_TEMPERATURE,
|
|
68612
68536
|
DEFAULT_PAGE_SIZE: () => DEFAULT_PAGE_SIZE,
|
|
68613
|
-
DEFAULT_CONCURRENCY: () => DEFAULT_CONCURRENCY,
|
|
68614
68537
|
DATASET_NAME_PATTERN: () => DATASET_NAME_PATTERN,
|
|
68615
68538
|
CustomScriptConfigSchema: () => CustomScriptConfigSchema,
|
|
68616
68539
|
CreateWorkflowDefinitionSchema: () => CreateWorkflowDefinitionSchema,
|
|
@@ -181229,7 +181152,7 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
181229
181152
|
// package.json
|
|
181230
181153
|
var package_default = {
|
|
181231
181154
|
name: "@eigenpal/cli",
|
|
181232
|
-
version: "0.
|
|
181155
|
+
version: "0.5.2",
|
|
181233
181156
|
description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
|
|
181234
181157
|
keywords: [
|
|
181235
181158
|
"eigenpal",
|
|
@@ -181304,7 +181227,9 @@ var package_default = {
|
|
|
181304
181227
|
|
|
181305
181228
|
// src/commands/agent.ts
|
|
181306
181229
|
var import_yaml = __toESM(require_dist(), 1);
|
|
181307
|
-
import {
|
|
181230
|
+
import { spawnSync } from "node:child_process";
|
|
181231
|
+
import { createHash } from "node:crypto";
|
|
181232
|
+
import { existsSync as existsSync2, promises as fs, readFileSync as readFileSync2 } from "node:fs";
|
|
181308
181233
|
import path from "node:path";
|
|
181309
181234
|
import { createInterface } from "node:readline/promises";
|
|
181310
181235
|
|
|
@@ -181387,6 +181312,15 @@ class ApiClient {
|
|
|
181387
181312
|
});
|
|
181388
181313
|
return this.handleResponse(res, url);
|
|
181389
181314
|
}
|
|
181315
|
+
async put(path, body) {
|
|
181316
|
+
const url = `${this.baseUrl}${path}`;
|
|
181317
|
+
const res = await fetch(url, {
|
|
181318
|
+
method: "PUT",
|
|
181319
|
+
headers: this.headers({ "Content-Type": "application/json" }),
|
|
181320
|
+
body: body !== undefined ? JSON.stringify(body) : undefined
|
|
181321
|
+
});
|
|
181322
|
+
return this.handleResponse(res, url);
|
|
181323
|
+
}
|
|
181390
181324
|
async patch(path, body) {
|
|
181391
181325
|
const url = `${this.baseUrl}${path}`;
|
|
181392
181326
|
const res = await fetch(url, {
|
|
@@ -181948,6 +181882,7 @@ Examples:
|
|
|
181948
181882
|
Version flags are intentionally unsupported for agents in this release.
|
|
181949
181883
|
`).action(action(pushAgent));
|
|
181950
181884
|
withBaseUrl(agent.command("pull <agent-id-or-slug>")).description("Download an agent project as agent.yaml, agent/, and dataset/.").option("--out <dir>", "Output directory").action(action(pullAgent));
|
|
181885
|
+
registerAgentFileCommands(agent);
|
|
181951
181886
|
addJsonFlag(agent.command("validate [dir]")).description("Validate a local agent project layout.").action(action(validateAgentCommand));
|
|
181952
181887
|
registerDatasetCommands(agent);
|
|
181953
181888
|
registerExecutionCommands(agent);
|
|
@@ -181957,6 +181892,16 @@ Version flags are intentionally unsupported for agents in this release.
|
|
|
181957
181892
|
registerComingSoon(agent, "evaluators", "Agent evaluators are reserved for future workflow-style evaluators.");
|
|
181958
181893
|
registerComingSoon(agent, "versions", "Agent versions are coming soon.");
|
|
181959
181894
|
}
|
|
181895
|
+
function registerAgentFileCommands(agent) {
|
|
181896
|
+
const file2 = agent.command("file").description("List, download, and upload individual live agent files.").action(() => {
|
|
181897
|
+
process.stderr.write("`eigenpal agent file` requires a subcommand. Run `eigenpal agent file --help`.\n");
|
|
181898
|
+
process.exit(2);
|
|
181899
|
+
});
|
|
181900
|
+
addJsonFlag(withBaseUrl(file2.command("list <agent-id-or-slug>"))).description("List live files for an agent.").option("--path <prefix>", "Only list files beneath this relative path").action(action(listAgentFiles));
|
|
181901
|
+
addJsonFlag(withBaseUrl(file2.command("get <agent-id-or-slug> <remote-path>"))).description("Download one live agent file.").option("--out <file>", "Output file path").action(action(getAgentFile));
|
|
181902
|
+
addJsonFlag(withBaseUrl(file2.command("put <agent-id-or-slug> <remote-path> <local-path>"))).description("Upload one local file into the live agent namespace.").option("--dry-run", "Validate local file and remote path without uploading").option("--preview", "Compare remote and local file without uploading").action(action(putAgentFile));
|
|
181903
|
+
addJsonFlag(withBaseUrl(file2.command("diff <agent-id-or-slug> <remote-path> <local-path>"))).description("Compare one live agent file against a local file.").action(action(diffAgentFile));
|
|
181904
|
+
}
|
|
181960
181905
|
function registerDatasetCommands(agent) {
|
|
181961
181906
|
const dataset = agent.command("dataset").description("Manage an agent dataset.").action(() => {
|
|
181962
181907
|
process.stderr.write("`eigenpal agent dataset` requires a subcommand. Run `eigenpal agent dataset --help`.\n");
|
|
@@ -181973,8 +181918,24 @@ function registerExecutionCommands(agent) {
|
|
|
181973
181918
|
process.exit(2);
|
|
181974
181919
|
});
|
|
181975
181920
|
addJsonFlag(withBaseUrl(execution.command("run <agent-id-or-slug>"))).description("Start one agent execution.").option("--input-json <json>", "JSON input object").option("--input-file <path>", "Input file to upload as multipart form-data").option("--wait", "Poll until the execution reaches a terminal status").action(action(runExecution));
|
|
181976
|
-
addJsonFlag(withBaseUrl(execution.command("get <execution-id>"))).description("Get one agent execution.").option("--include <parts>", "Comma-separated extra parts,
|
|
181977
|
-
addJsonFlag(
|
|
181921
|
+
addJsonFlag(withBaseUrl(execution.command("get <execution-id>"))).description("Get one agent execution.").option("--include <parts>", "Comma-separated extra parts: feedback,expected,files,trace,issues", "feedback").action(action(getExecution));
|
|
181922
|
+
addJsonFlag(withBaseUrl(execution.command("rerun <execution-id>"))).description("Create a new execution from a previous execution's stored input snapshot.").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 exiting 2", intArg, 1800).action(action(rerunExecution));
|
|
181923
|
+
const list = addJsonFlag(withPagination(withBaseUrl(execution.command("list <agent-id-or-slug>")), 50)).description("List agent executions.").option("--status <status>", "Filter by status").option("--batch-id <id>", "Filter by experiment batch id").option("--example-name <name>", "Filter by exact dataset example name").option("--example-name-contains <q>", "Filter by substring in example name").option("--created-after <time>", "Filter by created-at lower bound").option("--created-before <time>", "Filter by created-at upper bound").option("--completed-after <time>", "Filter by completed-at lower bound").option("--completed-before <time>", "Filter by completed-at upper bound").option("--feedback-status <open|resolved|ignored>", "Filter by feedback status").option("--feedback-rating <pass|fail|partial|none>", "Filter by feedback rating").option("--feedback-body-contains <q>", "Filter by feedback body substring").option("--feedback-created-after <time>", "Filter by feedback created-at lower bound").option("--feedback-created-before <time>", "Filter by feedback created-at upper bound").option("--feedback-updated-after <time>", "Filter by feedback updated-at lower bound").option("--feedback-updated-before <time>", "Filter by feedback updated-at upper bound").option("--feedback-resolved-after <time>", "Filter by feedback resolved-at lower bound").option("--feedback-resolved-before <time>", "Filter by feedback resolved-at upper bound").option("--has-feedback", "Only executions with feedback").option("--no-feedback", "Only executions without feedback").option("--has-expected", "Only executions with expected JSON or files").option("--has-expected-json", "Only executions with expected.json").option("--has-expected-files", "Only executions with expected files").option("--promoted-to-example", "Only executions promoted to dataset examples").option("--promoted-example-name <name>", "Filter by promoted dataset example name").option("--since-last-resolved", "Only executions created after the latest resolved feedback").option("--include <parts>", "Comma-separated extra parts: feedback,expected,files").option("--compact", "Return/print compact triage rows without full output payloads").option("--sort <field>", "Sort by createdAt, completedAt, status, or exampleName").option("--order <asc|desc>", "Sort direction").option("--scan-limit <n>", "Feedback scan window for feedback filters", intArg).action(action(listExecutions));
|
|
181924
|
+
list.addHelpText("after", `
|
|
181925
|
+
Examples:
|
|
181926
|
+
$ eigenpal agent execution list incorporator --feedback-rating fail --since-last-resolved --include feedback,expected
|
|
181927
|
+
$ eigenpal agent execution list activities --has-expected-files --created-after 2026-05-01
|
|
181928
|
+
`);
|
|
181929
|
+
withBaseUrl(execution.command("pull <execution-id>")).description("Download execution feedback, expected artifacts, files, and metadata.").option("--out <dir>", "Output directory").option("--include <parts>", "Comma-separated parts: feedback,expected,files,output,input,metadata,issues,trace,all", "feedback,expected").option("--json", "Output a JSON summary of written artifacts").action(action(pullExecution));
|
|
181930
|
+
addJsonFlag(withBaseUrl(execution.command("compare <reference-execution-id> <execution-id>"))).description("Compare one execution against another execution. PDF/DOCX text comparison uses pdftotext/python3 and reports byte fallbacks.").option("--baseline", "Compare actual outputs from both executions instead of expected artifacts").option("--out <dir>", "Write comparison artifacts to this directory").option("--normalize-dates", "Normalize YYYYMMDD and YYYY-MM-DD tokens in filenames/text").option("--fail-on-diff", "Exit 1 when comparison status is fail").action(action(compareExecution));
|
|
181931
|
+
const artifacts = execution.command("artifacts").description("Inspect execution artifact inventory.").action(() => {
|
|
181932
|
+
process.stderr.write("`eigenpal agent execution artifacts` requires a subcommand. Run `eigenpal agent execution artifacts --help`.\n");
|
|
181933
|
+
process.exit(2);
|
|
181934
|
+
});
|
|
181935
|
+
addJsonFlag(withBaseUrl(artifacts.command("list <execution-id>"))).description("List available execution artifacts without downloading them.").action(action(listExecutionArtifacts));
|
|
181936
|
+
withBaseUrl(execution.command("trace <execution-id>")).description("Print raw trace.jsonl for an execution, or write it with --out.").option("--out <file>", "Output file path").action(action(traceExecution));
|
|
181937
|
+
registerExecutionFeedbackCommands(execution);
|
|
181938
|
+
registerExecutionExpectedCommands(execution);
|
|
181978
181939
|
addJsonFlag(withBaseUrl(execution.command("watch <execution-id>"))).description("Watch an execution until it reaches a terminal status.").option("--interval <seconds>", "Polling interval in seconds", intArg, 2).option("--max-wait <seconds>", "Maximum wait before exiting 2", intArg, 1800).action(action(watchExecutionCommand));
|
|
181979
181940
|
addJsonFlag(withBaseUrl(execution.command("cancel <execution-id>"))).description("Cancel an agent execution.").option("--yes", "Required in non-interactive environments").action(action(cancelExecution));
|
|
181980
181941
|
}
|
|
@@ -181990,6 +181951,27 @@ function registerExperimentCommands(agent) {
|
|
|
181990
181951
|
addJsonFlag(withBaseUrl(experiment.command("compare <batch-id-a> <batch-id-b>"))).description("Compare two experiment batches.").option("--sort <mode>", "Accepted for compatibility; sorting happens client-side later").option("--regression-threshold <n>", "Accepted for compatibility", intArg).action(action(compareExperiments));
|
|
181991
181952
|
addJsonFlag(withBaseUrl(experiment.command("cancel <agent-id-or-slug> <batch-id>"))).description("Cancel every active execution in an experiment.").option("--yes", "Required in non-interactive environments").action(action(cancelExperiment));
|
|
181992
181953
|
}
|
|
181954
|
+
function registerExecutionFeedbackCommands(execution) {
|
|
181955
|
+
const feedback = execution.command("feedback").description("Update or clear feedback attached to an agent execution.").action(() => {
|
|
181956
|
+
process.stderr.write("`eigenpal agent execution feedback` requires a subcommand. Run `eigenpal agent execution feedback --help`.\n");
|
|
181957
|
+
process.exit(2);
|
|
181958
|
+
});
|
|
181959
|
+
addJsonFlag(withBaseUrl(feedback.command("update <execution-id>"))).description("Edit feedback state, rating, message, or expected JSON for an execution.").option("--status <open|resolved|ignored>", "Set feedback status").option("--rating <pass|fail|partial|none>", "Set feedback rating").option("--message <text>", "Set feedback message body").option("--message-file <path>", "Read feedback message body from a file").option("--expected-json <json>", "Set structured expected JSON").option("--expected-json-file <path>", "Read structured expected JSON from a file").option("--clear-message", "Clear the feedback message body").option("--clear-rating", "Clear feedback rating").option("--clear-expected-json", "Delete structured expected JSON").action(action(updateExecutionFeedback));
|
|
181960
|
+
addJsonFlag(withBaseUrl(feedback.command("resolve <execution-id>"))).description("Mark execution feedback as resolved.").option("--message <text>", "Set feedback message body").option("--message-file <path>", "Read feedback message body from a file").action(action((executionId, opts) => updateExecutionFeedback(executionId, { ...opts, status: "resolved" })));
|
|
181961
|
+
addJsonFlag(withBaseUrl(feedback.command("clear <execution-id>"))).description("Delete feedback, expected.json, and expected files for an execution.").option("--yes", "Required in non-interactive environments").action(action(clearExecutionFeedback));
|
|
181962
|
+
}
|
|
181963
|
+
function registerExecutionExpectedCommands(execution) {
|
|
181964
|
+
const expected = execution.command("expected").description("Manage expected artifacts attached to an agent execution.").action(() => {
|
|
181965
|
+
process.stderr.write("`eigenpal agent execution expected` requires a subcommand. Run `eigenpal agent execution expected --help`.\n");
|
|
181966
|
+
process.exit(2);
|
|
181967
|
+
});
|
|
181968
|
+
addJsonFlag(withBaseUrl(expected.command("list <execution-id>"))).description("List expected JSON and files attached to an execution.").action(action(listExecutionExpected));
|
|
181969
|
+
withBaseUrl(expected.command("pull <execution-id>")).description("Download expected JSON and files attached to an execution.").option("--out <dir>", "Output directory").action(action(pullExecutionExpected));
|
|
181970
|
+
addJsonFlag(withBaseUrl(expected.command("upload <execution-id> <file>"))).description("Upload a local file as an expected artifact.").option("--name <name>", "Expected artifact name").action(action(uploadExecutionExpected));
|
|
181971
|
+
addJsonFlag(withBaseUrl(expected.command("copy-output <execution-id> <output-file>"))).description("Copy a generated output file into expected artifacts.").option("--name <name>", "Expected artifact name").action(action(copyOutputToExpected));
|
|
181972
|
+
addJsonFlag(withBaseUrl(expected.command("rename <execution-id> <old-name> <new-name>"))).description("Rename an expected artifact.").action(action(renameExecutionExpected));
|
|
181973
|
+
addJsonFlag(withBaseUrl(expected.command("delete <execution-id> <name>"))).description("Delete an expected artifact.").option("--yes", "Required in non-interactive environments").action(action(deleteExecutionExpected));
|
|
181974
|
+
}
|
|
181993
181975
|
function registerSessionCommands(agent) {
|
|
181994
181976
|
const session = agent.command("session").description("Manage agent builder sessions.").action(() => {
|
|
181995
181977
|
process.stderr.write("`eigenpal agent session` requires a subcommand. Run `eigenpal agent session --help`.\n");
|
|
@@ -182108,6 +182090,55 @@ async function pullAgent(agentId, opts) {
|
|
|
182108
182090
|
await pullDataset(agentId, { ...opts, out: path.join(out, DATASET_DIR) });
|
|
182109
182091
|
success2(`Pulled agent to ${ui.bold(out)}`);
|
|
182110
182092
|
}
|
|
182093
|
+
async function listAgentFiles(agentId, opts) {
|
|
182094
|
+
const client = buildClient(opts);
|
|
182095
|
+
const payload = await client.get(`/api/v1/agents/${encodeURIComponent(agentId)}/files`, {
|
|
182096
|
+
...opts.path ? { prefix: opts.path } : {}
|
|
182097
|
+
});
|
|
182098
|
+
if (opts.json)
|
|
182099
|
+
return printJson(payload);
|
|
182100
|
+
console.log(table((payload.files ?? []).map((name) => ({ name })), [{ key: "name", header: "PATH" }]));
|
|
182101
|
+
}
|
|
182102
|
+
async function getAgentFile(agentId, remotePath, opts) {
|
|
182103
|
+
const client = buildClient(opts);
|
|
182104
|
+
const payload = await client.get(`/api/v1/agents/${encodeURIComponent(agentId)}/files`, {
|
|
182105
|
+
path: remotePath
|
|
182106
|
+
});
|
|
182107
|
+
if (opts.json)
|
|
182108
|
+
return printJson(payload);
|
|
182109
|
+
const out = path.resolve(opts.out ?? payload.path);
|
|
182110
|
+
await writeBase64File(out, payload.contentBase64);
|
|
182111
|
+
success2(`Downloaded ${payload.path} to ${ui.bold(out)}`);
|
|
182112
|
+
}
|
|
182113
|
+
async function putAgentFile(agentId, remotePath, localPath, opts) {
|
|
182114
|
+
const absolute = path.resolve(localPath);
|
|
182115
|
+
const data = await fs.readFile(absolute);
|
|
182116
|
+
if (opts.dryRun) {
|
|
182117
|
+
const payload2 = { ok: true, dryRun: true, path: remotePath, bytes: data.length };
|
|
182118
|
+
if (opts.json)
|
|
182119
|
+
return printJson(payload2);
|
|
182120
|
+
success2(`Validated ${remotePath} from ${ui.bold(absolute)} (${data.length} bytes)`);
|
|
182121
|
+
return;
|
|
182122
|
+
}
|
|
182123
|
+
if (opts.preview) {
|
|
182124
|
+
const report = await buildAgentFileDiff(agentId, remotePath, absolute, opts);
|
|
182125
|
+
if (opts.json)
|
|
182126
|
+
return printJson(report);
|
|
182127
|
+
renderAgentFileDiff(report);
|
|
182128
|
+
return;
|
|
182129
|
+
}
|
|
182130
|
+
const client = buildClient(opts);
|
|
182131
|
+
const payload = await client.put(`/api/v1/agents/${encodeURIComponent(agentId)}/files?path=${encodeURIComponent(remotePath)}`, { contentBase64: data.toString("base64") });
|
|
182132
|
+
if (opts.json)
|
|
182133
|
+
return printJson(payload);
|
|
182134
|
+
success2(`Uploaded ${remotePath} from ${ui.bold(absolute)}`);
|
|
182135
|
+
}
|
|
182136
|
+
async function diffAgentFile(agentId, remotePath, localPath, opts) {
|
|
182137
|
+
const report = await buildAgentFileDiff(agentId, remotePath, path.resolve(localPath), opts);
|
|
182138
|
+
if (opts.json)
|
|
182139
|
+
return printJson(report);
|
|
182140
|
+
renderAgentFileDiff(report);
|
|
182141
|
+
}
|
|
182111
182142
|
async function validateAgentCommand(dir = ".", opts) {
|
|
182112
182143
|
const result = await validateAgentProject(path.resolve(dir));
|
|
182113
182144
|
if (opts.json)
|
|
@@ -182184,18 +182215,302 @@ async function getExecution(executionId, opts) {
|
|
|
182184
182215
|
});
|
|
182185
182216
|
renderExecutionPayload(payload, opts);
|
|
182186
182217
|
}
|
|
182187
|
-
async function
|
|
182218
|
+
async function rerunExecution(executionId, opts) {
|
|
182188
182219
|
const client = buildClient(opts);
|
|
182189
|
-
|
|
182220
|
+
let payload = await client.post(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/rerun`, {});
|
|
182221
|
+
const rerunId = String(payload.executionId ?? "");
|
|
182222
|
+
if (opts.wait && rerunId) {
|
|
182223
|
+
payload = await pollExecution(client, rerunId, opts.interval, opts.maxWait);
|
|
182224
|
+
return renderExecutionPayload(payload, opts);
|
|
182225
|
+
}
|
|
182190
182226
|
if (opts.json)
|
|
182191
182227
|
return printJson(payload);
|
|
182192
|
-
|
|
182228
|
+
success2(`Started rerun ${ui.bold(rerunId)} from ${executionId}`);
|
|
182229
|
+
}
|
|
182230
|
+
async function pullExecution(executionId, opts) {
|
|
182231
|
+
const client = buildClient(opts);
|
|
182232
|
+
const include = new Set(opts.include.split(",").map((part) => part.trim()).filter(Boolean));
|
|
182233
|
+
if (include.has("all")) {
|
|
182234
|
+
include.add("feedback");
|
|
182235
|
+
include.add("expected");
|
|
182236
|
+
include.add("files");
|
|
182237
|
+
include.add("input");
|
|
182238
|
+
include.add("output");
|
|
182239
|
+
include.add("metadata");
|
|
182240
|
+
include.add("issues");
|
|
182241
|
+
include.add("trace");
|
|
182242
|
+
}
|
|
182243
|
+
const payload = await client.get(`/api/v1/agents/executions/${encodeURIComponent(executionId)}`, { include: [...include].join(",") });
|
|
182244
|
+
const execution = payload.execution;
|
|
182245
|
+
if (!execution)
|
|
182246
|
+
throw new Error(`Execution ${executionId} not found`);
|
|
182247
|
+
const out = path.resolve(opts.out ?? path.join(".eigenpal", "artifacts", "executions", executionId));
|
|
182248
|
+
await fs.mkdir(out, { recursive: true });
|
|
182249
|
+
const written = [];
|
|
182250
|
+
const skipped = [];
|
|
182251
|
+
const writeJsonArtifact = async (name, value) => {
|
|
182252
|
+
await fs.writeFile(path.join(out, name), JSON.stringify(value, null, 2));
|
|
182253
|
+
written.push(name);
|
|
182254
|
+
};
|
|
182255
|
+
await writeJsonArtifact("execution.json", execution);
|
|
182256
|
+
const feedback = execution.feedback;
|
|
182257
|
+
if (include.has("feedback") && feedback) {
|
|
182258
|
+
await fs.writeFile(path.join(out, "feedback.md"), serializeCliFeedback(feedback));
|
|
182259
|
+
written.push("feedback.md");
|
|
182260
|
+
} else if (include.has("feedback")) {
|
|
182261
|
+
skipped.push("feedback");
|
|
182262
|
+
}
|
|
182263
|
+
if (include.has("expected")) {
|
|
182264
|
+
written.push(...await writeExpectedArtifacts(client, executionId, out, execution));
|
|
182265
|
+
}
|
|
182266
|
+
if (include.has("files") || include.has("output")) {
|
|
182267
|
+
written.push(...await writeListedFiles(client, executionId, out, "output", execution.resultFiles));
|
|
182268
|
+
}
|
|
182269
|
+
if (include.has("files") || include.has("input")) {
|
|
182270
|
+
written.push(...await writeListedFiles(client, executionId, out, "input", execution.inputFiles));
|
|
182271
|
+
if (execution.inputJson) {
|
|
182272
|
+
await writeJsonArtifact("input.json", execution.inputJson);
|
|
182273
|
+
} else {
|
|
182274
|
+
skipped.push("input.json");
|
|
182275
|
+
}
|
|
182276
|
+
}
|
|
182277
|
+
if (include.has("files") || include.has("metadata")) {
|
|
182278
|
+
if (execution.metadata) {
|
|
182279
|
+
await writeJsonArtifact("metadata.json", execution.metadata);
|
|
182280
|
+
} else {
|
|
182281
|
+
skipped.push("metadata.json");
|
|
182282
|
+
}
|
|
182283
|
+
}
|
|
182284
|
+
if (include.has("files") || include.has("issues")) {
|
|
182285
|
+
const file2 = await writeDiagnosticFile(client, executionId, out, "issues", "issues.md", execution.issueFiles);
|
|
182286
|
+
if (file2)
|
|
182287
|
+
written.push(file2);
|
|
182288
|
+
else
|
|
182289
|
+
skipped.push("issues.md");
|
|
182290
|
+
}
|
|
182291
|
+
if (include.has("files") || include.has("trace")) {
|
|
182292
|
+
const file2 = await writeDiagnosticFile(client, executionId, out, "trace", "trace.jsonl", execution.traceFiles);
|
|
182293
|
+
if (file2)
|
|
182294
|
+
written.push(file2);
|
|
182295
|
+
else
|
|
182296
|
+
skipped.push("trace.jsonl");
|
|
182297
|
+
}
|
|
182298
|
+
const summary = {
|
|
182299
|
+
executionId,
|
|
182300
|
+
out,
|
|
182301
|
+
written,
|
|
182302
|
+
skipped,
|
|
182303
|
+
counts: {
|
|
182304
|
+
written: written.length,
|
|
182305
|
+
skipped: skipped.length
|
|
182306
|
+
}
|
|
182307
|
+
};
|
|
182308
|
+
if (opts.json)
|
|
182309
|
+
return printJson(summary);
|
|
182310
|
+
success2(`Pulled execution ${executionId} to ${out}`);
|
|
182311
|
+
dim(`Wrote ${written.length} artifact${written.length === 1 ? "" : "s"}${skipped.length ? `; skipped missing ${skipped.join(", ")}` : ""}`);
|
|
182312
|
+
}
|
|
182313
|
+
async function listExecutionArtifacts(executionId, opts) {
|
|
182314
|
+
const client = buildClient(opts);
|
|
182315
|
+
const payload = await client.get(`/api/v1/agents/executions/${encodeURIComponent(executionId)}`, { include: "expected,files,input,output,issues,trace,metadata" });
|
|
182316
|
+
const execution = payload.execution;
|
|
182317
|
+
if (!execution)
|
|
182318
|
+
throw new Error(`Execution ${executionId} not found`);
|
|
182319
|
+
const artifacts = executionArtifactInventory(execution);
|
|
182320
|
+
if (opts.json)
|
|
182321
|
+
return printJson({ executionId, artifacts });
|
|
182322
|
+
console.log(table(artifacts, [
|
|
182323
|
+
{ key: "kind", header: "KIND" },
|
|
182324
|
+
{ key: "name", header: "NAME" },
|
|
182325
|
+
{ key: "present", header: "PRESENT" }
|
|
182326
|
+
]));
|
|
182327
|
+
}
|
|
182328
|
+
async function traceExecution(executionId, opts) {
|
|
182329
|
+
const client = buildClient(opts);
|
|
182330
|
+
const text = await downloadTraceText(client, executionId);
|
|
182331
|
+
if (!opts.out) {
|
|
182332
|
+
process.stdout.write(text);
|
|
182333
|
+
return;
|
|
182334
|
+
}
|
|
182335
|
+
const out = path.resolve(opts.out);
|
|
182336
|
+
await fs.mkdir(path.dirname(out), { recursive: true });
|
|
182337
|
+
await fs.writeFile(out, text);
|
|
182338
|
+
success2(`Downloaded trace for ${executionId} to ${ui.bold(out)}`);
|
|
182339
|
+
}
|
|
182340
|
+
async function compareExecution(referenceId, executionId, opts) {
|
|
182341
|
+
const client = buildClient(opts);
|
|
182342
|
+
const targetPayload = await client.get(`/api/v1/agents/executions/${encodeURIComponent(executionId)}`, { include: "files,output" });
|
|
182343
|
+
const target = targetPayload.execution;
|
|
182344
|
+
if (!target)
|
|
182345
|
+
throw new Error(`Execution ${executionId} not found`);
|
|
182346
|
+
const mode = opts.baseline ? "baseline" : "expected";
|
|
182347
|
+
const reference = (await client.get(`/api/v1/agents/executions/${encodeURIComponent(referenceId)}`, {
|
|
182348
|
+
include: mode === "baseline" ? "files,output" : "expected"
|
|
182349
|
+
})).execution;
|
|
182350
|
+
if (!reference)
|
|
182351
|
+
throw new Error(`Reference execution ${referenceId} not found`);
|
|
182352
|
+
const out = path.resolve(opts.out ?? path.join(".eigenpal", "artifacts", "comparisons", `${referenceId}..${executionId}`));
|
|
182353
|
+
await fs.mkdir(out, { recursive: true });
|
|
182354
|
+
const warnings = [];
|
|
182355
|
+
if (mode === "expected" && reference.expected == null && fileNames(reference.expectedFiles).length === 0) {
|
|
182356
|
+
warnings.push(`Reference execution ${referenceId} has no expected JSON or expected files; comparison has no baseline artifacts. Use --baseline to compare actual outputs.`);
|
|
182357
|
+
}
|
|
182358
|
+
const jsonDiffs = diffJson(mode === "baseline" ? reference.output : reference.expected, target.output);
|
|
182359
|
+
const expectedFiles = mode === "baseline" ? fileNames(reference.resultFiles).filter((name) => name !== "issues.md" && name !== "trace.jsonl") : fileNames(reference.expectedFiles);
|
|
182360
|
+
const outputFiles = fileNames(target.resultFiles).filter((name) => name !== "issues.md" && name !== "trace.jsonl");
|
|
182361
|
+
const inventory = compareFileInventory(expectedFiles, outputFiles, Boolean(opts.normalizeDates));
|
|
182362
|
+
const textDifferences = await compareMatchedFileText(client, { executionId: referenceId, kind: mode === "baseline" ? "output" : "expected" }, { executionId, kind: "output" }, out, inventory.matched, Boolean(opts.normalizeDates));
|
|
182363
|
+
const report = {
|
|
182364
|
+
status: jsonDiffs.length === 0 && inventory.missing.length === 0 && inventory.extra.length === 0 && textDifferences.every((diff) => diff.status === "match" || diff.status === "binary-match") ? "pass" : "fail",
|
|
182365
|
+
executionId,
|
|
182366
|
+
comparedWith: referenceId,
|
|
182367
|
+
mode,
|
|
182368
|
+
warnings,
|
|
182369
|
+
jsonDifferences: jsonDiffs,
|
|
182370
|
+
matchedFiles: inventory.matched,
|
|
182371
|
+
missingFiles: inventory.missing,
|
|
182372
|
+
extraFiles: inventory.extra,
|
|
182373
|
+
textDifferences
|
|
182374
|
+
};
|
|
182375
|
+
await fs.writeFile(path.join(out, "comparison.json"), JSON.stringify(report, null, 2));
|
|
182376
|
+
if (opts.json) {
|
|
182377
|
+
printJson(report);
|
|
182378
|
+
} else {
|
|
182379
|
+
renderComparisonReport(report);
|
|
182380
|
+
}
|
|
182381
|
+
dim(`Comparison artifacts written to ${ui.bold(out)}`);
|
|
182382
|
+
if (opts.failOnDiff && report.status === "fail")
|
|
182383
|
+
process.exit(1);
|
|
182384
|
+
}
|
|
182385
|
+
async function listExecutions(agentId, opts) {
|
|
182386
|
+
const client = buildClient(opts);
|
|
182387
|
+
const params = buildExecutionListParams(opts);
|
|
182388
|
+
const payload = await client.get(`/api/v1/agents/${encodeURIComponent(agentId)}/executions`, params);
|
|
182389
|
+
const rows = opts.compact ? payload.executions.map(compactExecutionRow) : payload.executions;
|
|
182390
|
+
if (opts.json)
|
|
182391
|
+
return printJson({ ...payload, executions: rows });
|
|
182392
|
+
if (payload.scanLimited) {
|
|
182393
|
+
warn("Feedback/expected filters scanned only the first matching window. Increase --scan-limit or narrow DB filters for a fuller result.");
|
|
182394
|
+
}
|
|
182395
|
+
if (payload.noResolvedAnchor) {
|
|
182396
|
+
warn("No resolved feedback anchor was found in the scan window; --since-last-resolved returned no rows.");
|
|
182397
|
+
}
|
|
182398
|
+
console.log(table(rows, [
|
|
182193
182399
|
{ key: "id", header: "ID" },
|
|
182194
182400
|
{ key: "status", header: "STATUS" },
|
|
182195
182401
|
{ key: "exampleId", header: "EXAMPLE" },
|
|
182402
|
+
{
|
|
182403
|
+
key: "feedback",
|
|
182404
|
+
header: "FEEDBACK",
|
|
182405
|
+
format: (value) => value && typeof value === "object" ? `${String(value.rating ?? "")}/${String(value.status ?? "")}` : ""
|
|
182406
|
+
},
|
|
182196
182407
|
{ key: "createdAt", header: "CREATED", format: formatTimestamp }
|
|
182197
182408
|
]));
|
|
182198
182409
|
}
|
|
182410
|
+
function buildExecutionListParams(opts) {
|
|
182411
|
+
return compactParams({
|
|
182412
|
+
...opts,
|
|
182413
|
+
feedback: undefined,
|
|
182414
|
+
noFeedback: opts.noFeedback ?? (opts.feedback === false ? true : undefined)
|
|
182415
|
+
});
|
|
182416
|
+
}
|
|
182417
|
+
async function updateExecutionFeedback(executionId, opts) {
|
|
182418
|
+
const client = buildClient(opts);
|
|
182419
|
+
const body = {};
|
|
182420
|
+
if (opts.status)
|
|
182421
|
+
body.status = opts.status;
|
|
182422
|
+
if (opts.rating)
|
|
182423
|
+
body.rating = opts.rating === "none" ? null : opts.rating;
|
|
182424
|
+
if (opts.clearRating)
|
|
182425
|
+
body.rating = null;
|
|
182426
|
+
if (opts.messageFile)
|
|
182427
|
+
body.body = await fs.readFile(opts.messageFile, "utf-8");
|
|
182428
|
+
if (opts.message !== undefined)
|
|
182429
|
+
body.body = opts.message;
|
|
182430
|
+
if (opts.clearMessage)
|
|
182431
|
+
body.body = "";
|
|
182432
|
+
if (opts.expectedJsonFile)
|
|
182433
|
+
body.expected = JSON.parse(await fs.readFile(opts.expectedJsonFile, "utf-8"));
|
|
182434
|
+
if (opts.expectedJson !== undefined)
|
|
182435
|
+
body.expected = JSON.parse(opts.expectedJson);
|
|
182436
|
+
if (opts.clearExpectedJson)
|
|
182437
|
+
body.expected = null;
|
|
182438
|
+
const payload = await client.patch(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/feedback`, body);
|
|
182439
|
+
renderGeneric(payload, opts, `Updated feedback for ${executionId}`);
|
|
182440
|
+
}
|
|
182441
|
+
function compactExecutionRow(execution) {
|
|
182442
|
+
const feedback = execution.feedback && typeof execution.feedback === "object" ? execution.feedback : null;
|
|
182443
|
+
return {
|
|
182444
|
+
id: execution.id,
|
|
182445
|
+
status: execution.status,
|
|
182446
|
+
exampleId: execution.exampleId,
|
|
182447
|
+
feedback: feedback ? {
|
|
182448
|
+
rating: feedback.rating ?? null,
|
|
182449
|
+
status: feedback.status ?? null,
|
|
182450
|
+
updatedAt: feedback.updatedAt ?? null
|
|
182451
|
+
} : null,
|
|
182452
|
+
hasExpectedJson: execution.expected != null,
|
|
182453
|
+
expectedFileCount: Array.isArray(execution.expectedFiles) ? execution.expectedFiles.length : undefined,
|
|
182454
|
+
createdAt: execution.createdAt,
|
|
182455
|
+
completedAt: execution.completedAt
|
|
182456
|
+
};
|
|
182457
|
+
}
|
|
182458
|
+
async function clearExecutionFeedback(executionId, opts) {
|
|
182459
|
+
if (!(opts.yes || await confirmTyped(executionId, "clear feedback artifacts"))) {
|
|
182460
|
+
throw new Error("Clear cancelled");
|
|
182461
|
+
}
|
|
182462
|
+
const client = buildClient(opts);
|
|
182463
|
+
const payload = await client.delete(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/feedback`);
|
|
182464
|
+
renderGeneric(payload, opts, `Cleared feedback for ${executionId}`);
|
|
182465
|
+
}
|
|
182466
|
+
async function listExecutionExpected(executionId, opts) {
|
|
182467
|
+
const client = buildClient(opts);
|
|
182468
|
+
const payload = await client.get(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected`);
|
|
182469
|
+
if (opts.json)
|
|
182470
|
+
return printJson(payload);
|
|
182471
|
+
console.log(table(payload.files ?? [], [{ key: "name", header: "NAME" }]));
|
|
182472
|
+
if (payload.expected != null)
|
|
182473
|
+
dim("expected.json present");
|
|
182474
|
+
}
|
|
182475
|
+
async function pullExecutionExpected(executionId, opts) {
|
|
182476
|
+
const client = buildClient(opts);
|
|
182477
|
+
const payload = await client.get(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected`);
|
|
182478
|
+
const out = path.resolve(opts.out ?? path.join(executionId, "expected"));
|
|
182479
|
+
await fs.mkdir(out, { recursive: true });
|
|
182480
|
+
if (payload.expected != null) {
|
|
182481
|
+
await fs.writeFile(path.join(out, "expected.json"), JSON.stringify(payload.expected, null, 2));
|
|
182482
|
+
}
|
|
182483
|
+
await downloadExpectedFiles(client, executionId, out, payload.files);
|
|
182484
|
+
success2(`Pulled expected artifacts for ${executionId} to ${out}`);
|
|
182485
|
+
}
|
|
182486
|
+
async function uploadExecutionExpected(executionId, file2, opts) {
|
|
182487
|
+
const client = buildClient(opts);
|
|
182488
|
+
const form = new FormData;
|
|
182489
|
+
const data = await fs.readFile(file2);
|
|
182490
|
+
form.append("file", new Blob([data]), path.basename(file2));
|
|
182491
|
+
if (opts.name)
|
|
182492
|
+
form.append("name", opts.name);
|
|
182493
|
+
const payload = await client.postFormData(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected`, form);
|
|
182494
|
+
renderGeneric(payload, opts, `Uploaded expected file for ${executionId}`);
|
|
182495
|
+
}
|
|
182496
|
+
async function copyOutputToExpected(executionId, outputFile, opts) {
|
|
182497
|
+
const client = buildClient(opts);
|
|
182498
|
+
const payload = await client.post(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected`, { outputFileName: outputFile, ...opts.name ? { expectedName: opts.name } : {} });
|
|
182499
|
+
renderGeneric(payload, opts, `Copied output file to expected for ${executionId}`);
|
|
182500
|
+
}
|
|
182501
|
+
async function renameExecutionExpected(executionId, oldName, newName, opts) {
|
|
182502
|
+
const client = buildClient(opts);
|
|
182503
|
+
const payload = await client.patch(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected/${encodeURIComponent(oldName)}`, { name: newName });
|
|
182504
|
+
renderGeneric(payload, opts, `Renamed expected file for ${executionId}`);
|
|
182505
|
+
}
|
|
182506
|
+
async function deleteExecutionExpected(executionId, name, opts) {
|
|
182507
|
+
if (!(opts.yes || await confirmTyped(name, "delete expected file"))) {
|
|
182508
|
+
throw new Error("Delete cancelled");
|
|
182509
|
+
}
|
|
182510
|
+
const client = buildClient(opts);
|
|
182511
|
+
await client.delete(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected/${encodeURIComponent(name)}`);
|
|
182512
|
+
renderGeneric({ ok: true }, opts, `Deleted expected file ${name}`);
|
|
182513
|
+
}
|
|
182199
182514
|
async function watchExecutionCommand(executionId, opts) {
|
|
182200
182515
|
const client = buildClient(opts);
|
|
182201
182516
|
const payload = await pollExecution(client, executionId, opts.interval, opts.maxWait);
|
|
@@ -182410,6 +182725,336 @@ async function buildAgentExecutionRunFormData(inputFile, inputJson) {
|
|
|
182410
182725
|
form.append("_json", inputJson);
|
|
182411
182726
|
return form;
|
|
182412
182727
|
}
|
|
182728
|
+
function serializeCliFeedback(feedback) {
|
|
182729
|
+
const keys = [
|
|
182730
|
+
"rating",
|
|
182731
|
+
"status",
|
|
182732
|
+
"createdAt",
|
|
182733
|
+
"createdBy",
|
|
182734
|
+
"createdByEmail",
|
|
182735
|
+
"updatedAt",
|
|
182736
|
+
"resolvedAt",
|
|
182737
|
+
"resolvedBy",
|
|
182738
|
+
"resolvedByEmail",
|
|
182739
|
+
"resolvedBySessionId",
|
|
182740
|
+
"promotedExampleName"
|
|
182741
|
+
];
|
|
182742
|
+
const frontmatter = keys.map((key) => `${key}: ${feedback[key] ?? ""}`).join(`
|
|
182743
|
+
`);
|
|
182744
|
+
return `---
|
|
182745
|
+
${frontmatter}
|
|
182746
|
+
---
|
|
182747
|
+
|
|
182748
|
+
${String(feedback.body ?? "").trim()}
|
|
182749
|
+
`;
|
|
182750
|
+
}
|
|
182751
|
+
async function writeExpectedArtifacts(client, executionId, out, execution) {
|
|
182752
|
+
const written = [];
|
|
182753
|
+
const expectedDir = path.join(out, "expected");
|
|
182754
|
+
await fs.mkdir(expectedDir, { recursive: true });
|
|
182755
|
+
if (execution.expected != null) {
|
|
182756
|
+
await fs.writeFile(path.join(out, "expected.json"), JSON.stringify(execution.expected, null, 2));
|
|
182757
|
+
written.push("expected.json");
|
|
182758
|
+
}
|
|
182759
|
+
written.push(...(await downloadExpectedFiles(client, executionId, expectedDir, execution.expectedFiles)).map((name) => `expected/${name}`));
|
|
182760
|
+
return written;
|
|
182761
|
+
}
|
|
182762
|
+
async function downloadExpectedFiles(client, executionId, out, files) {
|
|
182763
|
+
const rows = Array.isArray(files) ? files : [];
|
|
182764
|
+
const written = await Promise.all(rows.map(async (file2) => {
|
|
182765
|
+
const name = String(file2.name ?? "");
|
|
182766
|
+
if (!name || name.includes("/") || name.includes(".."))
|
|
182767
|
+
return null;
|
|
182768
|
+
const response = await client.getStream(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/expected/${encodeURIComponent(name)}`);
|
|
182769
|
+
await fs.mkdir(out, { recursive: true });
|
|
182770
|
+
await fs.writeFile(path.join(out, name), Buffer.from(await response.arrayBuffer()));
|
|
182771
|
+
return name;
|
|
182772
|
+
}));
|
|
182773
|
+
return written.filter((name) => Boolean(name));
|
|
182774
|
+
}
|
|
182775
|
+
async function writeListedFiles(client, executionId, out, kind, files) {
|
|
182776
|
+
const rows = Array.isArray(files) ? files : [];
|
|
182777
|
+
const targetDir = path.join(out, kind);
|
|
182778
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
182779
|
+
const written = await Promise.all(rows.map(async (file2) => {
|
|
182780
|
+
const name = String(file2.name ?? "");
|
|
182781
|
+
if (!name || name.includes("/") || name.includes(".."))
|
|
182782
|
+
return null;
|
|
182783
|
+
const response = await client.getStream(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/files/${kind}/${encodeURIComponent(name)}`);
|
|
182784
|
+
await fs.writeFile(path.join(targetDir, name), Buffer.from(await response.arrayBuffer()));
|
|
182785
|
+
return `${kind}/${name}`;
|
|
182786
|
+
}));
|
|
182787
|
+
return written.filter((name) => Boolean(name));
|
|
182788
|
+
}
|
|
182789
|
+
async function writeDiagnosticFile(client, executionId, out, kind, filename, files) {
|
|
182790
|
+
const rows = Array.isArray(files) ? files : [];
|
|
182791
|
+
const exists = rows.some((file2) => String(file2.name ?? "") === filename);
|
|
182792
|
+
if (!exists)
|
|
182793
|
+
return null;
|
|
182794
|
+
const response = await client.getStream(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/files/${kind}/${filename}`);
|
|
182795
|
+
await fs.writeFile(path.join(out, filename), Buffer.from(await response.arrayBuffer()));
|
|
182796
|
+
return filename;
|
|
182797
|
+
}
|
|
182798
|
+
async function downloadTraceText(client, executionId) {
|
|
182799
|
+
const response = await client.getStream(`/api/v1/agents/executions/${encodeURIComponent(executionId)}/files/trace/trace.jsonl`);
|
|
182800
|
+
return Buffer.from(await response.arrayBuffer()).toString("utf-8");
|
|
182801
|
+
}
|
|
182802
|
+
function diffJson(expected, actual, basePath = "$") {
|
|
182803
|
+
if (expected === undefined || expected === null)
|
|
182804
|
+
return [];
|
|
182805
|
+
if (Object.is(expected, actual))
|
|
182806
|
+
return [];
|
|
182807
|
+
if (expected && actual && typeof expected === "object" && typeof actual === "object" && !Array.isArray(expected) && !Array.isArray(actual)) {
|
|
182808
|
+
const keys = new Set([...Object.keys(expected), ...Object.keys(actual)]);
|
|
182809
|
+
return [...keys].flatMap((key) => {
|
|
182810
|
+
const next = `${basePath}.${key}`;
|
|
182811
|
+
if (!(key in actual))
|
|
182812
|
+
return [{ path: next, type: "missing" }];
|
|
182813
|
+
if (!(key in expected))
|
|
182814
|
+
return [{ path: next, type: "extra" }];
|
|
182815
|
+
return diffJson(expected[key], actual[key], next);
|
|
182816
|
+
});
|
|
182817
|
+
}
|
|
182818
|
+
if (Array.isArray(expected) && Array.isArray(actual)) {
|
|
182819
|
+
const diffs = [];
|
|
182820
|
+
const max = Math.max(expected.length, actual.length);
|
|
182821
|
+
for (let index = 0;index < max; index += 1) {
|
|
182822
|
+
const next = `${basePath}[${index}]`;
|
|
182823
|
+
if (index >= actual.length)
|
|
182824
|
+
diffs.push({ path: next, type: "missing" });
|
|
182825
|
+
else if (index >= expected.length)
|
|
182826
|
+
diffs.push({ path: next, type: "extra" });
|
|
182827
|
+
else
|
|
182828
|
+
diffs.push(...diffJson(expected[index], actual[index], next));
|
|
182829
|
+
}
|
|
182830
|
+
return diffs;
|
|
182831
|
+
}
|
|
182832
|
+
return [
|
|
182833
|
+
{
|
|
182834
|
+
path: basePath,
|
|
182835
|
+
type: "changed",
|
|
182836
|
+
expected: JSON.stringify(expected),
|
|
182837
|
+
actual: JSON.stringify(actual)
|
|
182838
|
+
}
|
|
182839
|
+
];
|
|
182840
|
+
}
|
|
182841
|
+
function fileNames(files) {
|
|
182842
|
+
return (Array.isArray(files) ? files : []).map((file2) => String(file2.name ?? "")).filter(Boolean).sort();
|
|
182843
|
+
}
|
|
182844
|
+
function executionArtifactInventory(execution) {
|
|
182845
|
+
const rows = [
|
|
182846
|
+
{ kind: "metadata", name: "execution.json", present: "yes" }
|
|
182847
|
+
];
|
|
182848
|
+
if (execution.inputJson != null)
|
|
182849
|
+
rows.push({ kind: "input", name: "input.json", present: "yes" });
|
|
182850
|
+
if (execution.metadata != null)
|
|
182851
|
+
rows.push({ kind: "metadata", name: "metadata.json", present: "yes" });
|
|
182852
|
+
if (execution.expected != null)
|
|
182853
|
+
rows.push({ kind: "expected", name: "expected.json", present: "yes" });
|
|
182854
|
+
for (const name of fileNames(execution.inputFiles))
|
|
182855
|
+
rows.push({ kind: "input", name, present: "yes" });
|
|
182856
|
+
for (const name of fileNames(execution.resultFiles).filter((name2) => name2 !== "issues.md" && name2 !== "trace.jsonl")) {
|
|
182857
|
+
rows.push({ kind: "output", name, present: "yes" });
|
|
182858
|
+
}
|
|
182859
|
+
for (const name of fileNames(execution.expectedFiles)) {
|
|
182860
|
+
rows.push({ kind: "expected", name, present: "yes" });
|
|
182861
|
+
}
|
|
182862
|
+
for (const name of fileNames(execution.issueFiles))
|
|
182863
|
+
rows.push({ kind: "issues", name, present: "yes" });
|
|
182864
|
+
for (const name of fileNames(execution.traceFiles))
|
|
182865
|
+
rows.push({ kind: "trace", name, present: "yes" });
|
|
182866
|
+
return rows.sort((a, b) => `${a.kind}/${a.name}`.localeCompare(`${b.kind}/${b.name}`));
|
|
182867
|
+
}
|
|
182868
|
+
async function buildAgentFileDiff(agentId, remotePath, localPath, opts) {
|
|
182869
|
+
const client = buildClient(opts);
|
|
182870
|
+
const local = await fs.readFile(localPath);
|
|
182871
|
+
let remote = null;
|
|
182872
|
+
let serverPath = remotePath;
|
|
182873
|
+
try {
|
|
182874
|
+
const payload = await client.get(`/api/v1/agents/${encodeURIComponent(agentId)}/files`, {
|
|
182875
|
+
path: remotePath
|
|
182876
|
+
});
|
|
182877
|
+
serverPath = String(payload.path ?? remotePath);
|
|
182878
|
+
remote = Buffer.from(String(payload.contentBase64 ?? ""), "base64");
|
|
182879
|
+
} catch (err) {
|
|
182880
|
+
if (!(err instanceof ApiError) || err.status !== 404)
|
|
182881
|
+
throw err;
|
|
182882
|
+
}
|
|
182883
|
+
const localHash = createHash("sha256").update(local).digest("hex");
|
|
182884
|
+
const remoteHash = remote ? createHash("sha256").update(remote).digest("hex") : null;
|
|
182885
|
+
const status = !remote ? "remote-missing" : localHash === remoteHash ? "match" : "different";
|
|
182886
|
+
return {
|
|
182887
|
+
agentId,
|
|
182888
|
+
path: serverPath,
|
|
182889
|
+
localPath,
|
|
182890
|
+
status,
|
|
182891
|
+
localBytes: local.length,
|
|
182892
|
+
remoteBytes: remote?.length ?? null,
|
|
182893
|
+
localSha256: localHash,
|
|
182894
|
+
remoteSha256: remoteHash,
|
|
182895
|
+
textPreview: remote && isLikelyText(local) && isLikelyText(remote) ? buildTextDiffPreview(remote.toString("utf-8"), local.toString("utf-8")) : null
|
|
182896
|
+
};
|
|
182897
|
+
}
|
|
182898
|
+
function renderAgentFileDiff(report) {
|
|
182899
|
+
const label = `File ${report.status}`;
|
|
182900
|
+
if (report.status === "match")
|
|
182901
|
+
success2(label);
|
|
182902
|
+
else
|
|
182903
|
+
error51(label);
|
|
182904
|
+
console.log(table([
|
|
182905
|
+
{ item: "Remote path", value: report.path },
|
|
182906
|
+
{ item: "Local bytes", value: String(report.localBytes) },
|
|
182907
|
+
{ item: "Remote bytes", value: String(report.remoteBytes ?? "missing") },
|
|
182908
|
+
{ item: "Local sha256", value: report.localSha256.slice(0, 12) },
|
|
182909
|
+
{ item: "Remote sha256", value: report.remoteSha256?.slice(0, 12) ?? "missing" }
|
|
182910
|
+
], [
|
|
182911
|
+
{ key: "item", header: "ITEM" },
|
|
182912
|
+
{ key: "value", header: "VALUE" }
|
|
182913
|
+
]));
|
|
182914
|
+
if (report.textPreview?.length) {
|
|
182915
|
+
console.log(report.textPreview.join(`
|
|
182916
|
+
`));
|
|
182917
|
+
}
|
|
182918
|
+
}
|
|
182919
|
+
function isLikelyText(buffer) {
|
|
182920
|
+
return !buffer.includes(0);
|
|
182921
|
+
}
|
|
182922
|
+
function buildTextDiffPreview(remoteText, localText) {
|
|
182923
|
+
if (remoteText === localText)
|
|
182924
|
+
return [];
|
|
182925
|
+
const remoteLines = remoteText.split(/\r?\n/);
|
|
182926
|
+
const localLines = localText.split(/\r?\n/);
|
|
182927
|
+
const max = Math.max(remoteLines.length, localLines.length);
|
|
182928
|
+
const preview = [];
|
|
182929
|
+
for (let index = 0;index < max && preview.length < 12; index += 1) {
|
|
182930
|
+
if (remoteLines[index] === localLines[index])
|
|
182931
|
+
continue;
|
|
182932
|
+
preview.push(`-${remoteLines[index] ?? ""}`);
|
|
182933
|
+
preview.push(`+${localLines[index] ?? ""}`);
|
|
182934
|
+
}
|
|
182935
|
+
return preview;
|
|
182936
|
+
}
|
|
182937
|
+
function normalizeGeneratedTokens(value) {
|
|
182938
|
+
return value.replace(/\d{4}-\d{2}-\d{2}/g, "<date>").replace(/\d{8}/g, "<date>");
|
|
182939
|
+
}
|
|
182940
|
+
function compareFileInventory(expected, output, normalizeDates) {
|
|
182941
|
+
const normalize = (value) => normalizeDates ? normalizeGeneratedTokens(value) : value;
|
|
182942
|
+
const outputByNormalized = new Map(output.map((name) => [normalize(name), name]));
|
|
182943
|
+
const expectedByNormalized = new Map(expected.map((name) => [normalize(name), name]));
|
|
182944
|
+
const matched = expected.map((expectedName) => {
|
|
182945
|
+
const outputName = outputByNormalized.get(normalize(expectedName));
|
|
182946
|
+
return outputName ? { expected: expectedName, output: outputName } : null;
|
|
182947
|
+
}).filter((match) => Boolean(match));
|
|
182948
|
+
return {
|
|
182949
|
+
matched,
|
|
182950
|
+
missing: expected.filter((name) => !outputByNormalized.has(normalize(name))),
|
|
182951
|
+
extra: output.filter((name) => !expectedByNormalized.has(normalize(name)))
|
|
182952
|
+
};
|
|
182953
|
+
}
|
|
182954
|
+
async function compareMatchedFileText(client, left, right, out, matched, normalizeDates) {
|
|
182955
|
+
const expectedDir = path.join(out, "expected");
|
|
182956
|
+
const outputDir = path.join(out, "output");
|
|
182957
|
+
await fs.mkdir(expectedDir, { recursive: true });
|
|
182958
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
182959
|
+
const diffs = [];
|
|
182960
|
+
for (const pair of matched) {
|
|
182961
|
+
const expectedPath = path.join(expectedDir, pair.expected);
|
|
182962
|
+
const outputPath = path.join(outputDir, pair.output);
|
|
182963
|
+
await downloadStreamToFile(client, executionFileUrl(left, pair.expected), expectedPath);
|
|
182964
|
+
await downloadStreamToFile(client, executionFileUrl(right, pair.output), outputPath);
|
|
182965
|
+
const expectedText = extractComparableText(expectedPath);
|
|
182966
|
+
const outputText = extractComparableText(outputPath);
|
|
182967
|
+
if (expectedText.text == null || outputText.text == null) {
|
|
182968
|
+
const [expectedBuffer, outputBuffer] = await Promise.all([
|
|
182969
|
+
fs.readFile(expectedPath),
|
|
182970
|
+
fs.readFile(outputPath)
|
|
182971
|
+
]);
|
|
182972
|
+
const expectedHash = createHash("sha256").update(expectedBuffer).digest("hex");
|
|
182973
|
+
const outputHash = createHash("sha256").update(outputBuffer).digest("hex");
|
|
182974
|
+
diffs.push({
|
|
182975
|
+
...pair,
|
|
182976
|
+
status: expectedBuffer.length === outputBuffer.length && expectedHash === outputHash ? "binary-match" : "binary-different",
|
|
182977
|
+
expectedBytes: expectedBuffer.length,
|
|
182978
|
+
outputBytes: outputBuffer.length,
|
|
182979
|
+
expectedSha256: expectedHash,
|
|
182980
|
+
outputSha256: outputHash,
|
|
182981
|
+
textExtraction: {
|
|
182982
|
+
expected: expectedText.reason ?? null,
|
|
182983
|
+
output: outputText.reason ?? null
|
|
182984
|
+
}
|
|
182985
|
+
});
|
|
182986
|
+
continue;
|
|
182987
|
+
}
|
|
182988
|
+
const normalize = (value) => normalizeDates ? normalizeGeneratedTokens(value).trim() : value.trim();
|
|
182989
|
+
diffs.push({
|
|
182990
|
+
...pair,
|
|
182991
|
+
status: normalize(expectedText.text) === normalize(outputText.text) ? "match" : "text-different"
|
|
182992
|
+
});
|
|
182993
|
+
}
|
|
182994
|
+
return diffs;
|
|
182995
|
+
}
|
|
182996
|
+
function executionFileUrl(side, name) {
|
|
182997
|
+
const executionId = encodeURIComponent(side.executionId);
|
|
182998
|
+
const filename = encodeURIComponent(name);
|
|
182999
|
+
return side.kind === "expected" ? `/api/v1/agents/executions/${executionId}/expected/${filename}` : `/api/v1/agents/executions/${executionId}/files/output/${filename}`;
|
|
183000
|
+
}
|
|
183001
|
+
async function downloadStreamToFile(client, url2, target) {
|
|
183002
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
183003
|
+
const response = await client.getStream(url2);
|
|
183004
|
+
await fs.writeFile(target, Buffer.from(await response.arrayBuffer()));
|
|
183005
|
+
}
|
|
183006
|
+
function extractComparableText(file2) {
|
|
183007
|
+
const ext = path.extname(file2).toLowerCase();
|
|
183008
|
+
if ([".txt", ".md", ".json", ".csv", ".xml"].includes(ext)) {
|
|
183009
|
+
return { text: readFileSync2(file2, "utf8") };
|
|
183010
|
+
}
|
|
183011
|
+
if (ext === ".pdf") {
|
|
183012
|
+
const result = spawnSync("pdftotext", [file2, "-"], { encoding: "utf8" });
|
|
183013
|
+
return result.status === 0 ? { text: result.stdout } : { text: null, reason: textExtractionFallbackReason("pdftotext", result) };
|
|
183014
|
+
}
|
|
183015
|
+
if (ext === ".docx") {
|
|
183016
|
+
const script = "import re,sys,zipfile; z=zipfile.ZipFile(sys.argv[1]); x=z.read('word/document.xml').decode('utf-8','ignore'); print(re.sub('<[^>]+>',' ',x))";
|
|
183017
|
+
const result = spawnSync("python3", ["-c", script, file2], { encoding: "utf8" });
|
|
183018
|
+
return result.status === 0 ? { text: result.stdout } : { text: null, reason: textExtractionFallbackReason("python3", result) };
|
|
183019
|
+
}
|
|
183020
|
+
return { text: null, reason: `No text extractor for ${ext || "extensionless"} files` };
|
|
183021
|
+
}
|
|
183022
|
+
function textExtractionFallbackReason(tool, result) {
|
|
183023
|
+
if (result.error)
|
|
183024
|
+
return `${tool} unavailable; compared bytes instead`;
|
|
183025
|
+
return `${tool} could not extract text; compared bytes instead`;
|
|
183026
|
+
}
|
|
183027
|
+
function renderComparisonReport(report) {
|
|
183028
|
+
const header = `Comparison ${report.status}`;
|
|
183029
|
+
if (report.status === "pass") {
|
|
183030
|
+
success2(header);
|
|
183031
|
+
} else {
|
|
183032
|
+
error51(header);
|
|
183033
|
+
}
|
|
183034
|
+
for (const warning of report.warnings ?? []) {
|
|
183035
|
+
dim(`warning: ${warning}`);
|
|
183036
|
+
}
|
|
183037
|
+
console.log(table([
|
|
183038
|
+
{ item: "JSON differences", count: report.jsonDifferences.length },
|
|
183039
|
+
{ item: "Matched files", count: report.matchedFiles.length },
|
|
183040
|
+
{ item: "Missing files", count: report.missingFiles.length },
|
|
183041
|
+
{ item: "Extra files", count: report.extraFiles.length },
|
|
183042
|
+
{
|
|
183043
|
+
item: "Text differences",
|
|
183044
|
+
count: report.textDifferences.filter((diff) => diff.status === "text-different").length
|
|
183045
|
+
}
|
|
183046
|
+
], [
|
|
183047
|
+
{ key: "item", header: "ITEM" },
|
|
183048
|
+
{ key: "count", header: "COUNT" }
|
|
183049
|
+
]));
|
|
183050
|
+
for (const diff of report.textDifferences) {
|
|
183051
|
+
const textExtraction = diff.textExtraction;
|
|
183052
|
+
const reasons = [textExtraction?.expected, textExtraction?.output].filter((value) => typeof value === "string" && value.length > 0).filter((value, index, values) => values.indexOf(value) === index);
|
|
183053
|
+
for (const reason of reasons) {
|
|
183054
|
+
dim(`warning: ${String(diff.expected)} vs ${String(diff.output)}: ${reason}`);
|
|
183055
|
+
}
|
|
183056
|
+
}
|
|
183057
|
+
}
|
|
182413
183058
|
async function readAgentYaml(root) {
|
|
182414
183059
|
const file2 = path.join(root, AGENT_YAML);
|
|
182415
183060
|
const raw = await fs.readFile(file2, "utf-8");
|
|
@@ -182490,7 +183135,7 @@ function renderGeneric(payload, opts, message) {
|
|
|
182490
183135
|
function compactParams(opts) {
|
|
182491
183136
|
const params = {};
|
|
182492
183137
|
for (const [key, value] of Object.entries(opts)) {
|
|
182493
|
-
if (value === undefined || value === null || key === "json" || key === "baseUrl" || key === "yes")
|
|
183138
|
+
if (value === undefined || value === null || key === "json" || key === "baseUrl" || key === "yes" || key === "compact")
|
|
182494
183139
|
continue;
|
|
182495
183140
|
params[key] = String(value);
|
|
182496
183141
|
}
|
|
@@ -183007,7 +183652,7 @@ import {
|
|
|
183007
183652
|
existsSync as existsSync3,
|
|
183008
183653
|
mkdirSync as mkdirSync2,
|
|
183009
183654
|
readdirSync,
|
|
183010
|
-
readFileSync as
|
|
183655
|
+
readFileSync as readFileSync3,
|
|
183011
183656
|
statSync,
|
|
183012
183657
|
writeFileSync as writeFileSync2
|
|
183013
183658
|
} from "node:fs";
|
|
@@ -183105,7 +183750,7 @@ function copyTemplate(src, dst, projectName) {
|
|
|
183105
183750
|
}
|
|
183106
183751
|
mkdirSync2(dirname2(targetPath), { recursive: true });
|
|
183107
183752
|
if (isTextFile(sourcePath)) {
|
|
183108
|
-
const text =
|
|
183753
|
+
const text = readFileSync3(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
|
|
183109
183754
|
writeFileSync2(targetPath, text);
|
|
183110
183755
|
} else {
|
|
183111
183756
|
copyFileSync(sourcePath, targetPath);
|
|
@@ -183137,12 +183782,12 @@ function isTextFile(path2) {
|
|
|
183137
183782
|
|
|
183138
183783
|
// src/commands/skill.ts
|
|
183139
183784
|
init_dist4();
|
|
183140
|
-
import { createHash } from "node:crypto";
|
|
183785
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
183141
183786
|
import {
|
|
183142
183787
|
existsSync as existsSync4,
|
|
183143
183788
|
lstatSync,
|
|
183144
183789
|
mkdirSync as mkdirSync3,
|
|
183145
|
-
readFileSync as
|
|
183790
|
+
readFileSync as readFileSync4,
|
|
183146
183791
|
readdirSync as readdirSync2,
|
|
183147
183792
|
rmSync,
|
|
183148
183793
|
rmdirSync,
|
|
@@ -183236,7 +183881,7 @@ function resolveSkillTarget(opts) {
|
|
|
183236
183881
|
return opts.target ?? defaultClaudeTarget();
|
|
183237
183882
|
}
|
|
183238
183883
|
function sha256(buffer) {
|
|
183239
|
-
return
|
|
183884
|
+
return createHash2("sha256").update(buffer).digest("hex");
|
|
183240
183885
|
}
|
|
183241
183886
|
var CLI_VERSION_PLACEHOLDER = "__CLI_VERSION__";
|
|
183242
183887
|
function templateSourceFile(relativePath, bytes, cliVersion) {
|
|
@@ -183260,7 +183905,7 @@ async function installSkill(opts) {
|
|
|
183260
183905
|
for (const relativePath of sourceFiles) {
|
|
183261
183906
|
const sourcePath = join3(source, relativePath);
|
|
183262
183907
|
const targetPath = join3(target, relativePath);
|
|
183263
|
-
const sourceBytes = templateSourceFile(relativePath,
|
|
183908
|
+
const sourceBytes = templateSourceFile(relativePath, readFileSync4(sourcePath), cliVersion);
|
|
183264
183909
|
const sourceHash = sha256(sourceBytes);
|
|
183265
183910
|
if (!existsSync4(targetPath)) {
|
|
183266
183911
|
mkdirSync3(dirname3(targetPath), { recursive: true });
|
|
@@ -183268,7 +183913,7 @@ async function installSkill(opts) {
|
|
|
183268
183913
|
written += 1;
|
|
183269
183914
|
continue;
|
|
183270
183915
|
}
|
|
183271
|
-
const targetBytes =
|
|
183916
|
+
const targetBytes = readFileSync4(targetPath);
|
|
183272
183917
|
const targetHash = sha256(targetBytes);
|
|
183273
183918
|
if (targetHash === sourceHash) {
|
|
183274
183919
|
skipped += 1;
|
|
@@ -183299,7 +183944,7 @@ async function installSkill(opts) {
|
|
|
183299
183944
|
const targetPath = join3(target, relativePath);
|
|
183300
183945
|
if (!existsSync4(targetPath))
|
|
183301
183946
|
continue;
|
|
183302
|
-
manifestEntries.push({ path: relativePath, sha256: sha256(
|
|
183947
|
+
manifestEntries.push({ path: relativePath, sha256: sha256(readFileSync4(targetPath)) });
|
|
183303
183948
|
}
|
|
183304
183949
|
const manifest = {
|
|
183305
183950
|
cliVersion,
|
|
@@ -183340,7 +183985,7 @@ async function uninstallSkill(opts) {
|
|
|
183340
183985
|
}
|
|
183341
183986
|
if (!existsSync4(path2))
|
|
183342
183987
|
continue;
|
|
183343
|
-
const currentHash = sha256(
|
|
183988
|
+
const currentHash = sha256(readFileSync4(path2));
|
|
183344
183989
|
if (currentHash !== entry.sha256 && !opts.yes) {
|
|
183345
183990
|
kept += 1;
|
|
183346
183991
|
continue;
|
|
@@ -183570,7 +184215,7 @@ function readManifest(target) {
|
|
|
183570
184215
|
if (!existsSync4(path2))
|
|
183571
184216
|
return null;
|
|
183572
184217
|
try {
|
|
183573
|
-
return JSON.parse(
|
|
184218
|
+
return JSON.parse(readFileSync4(path2, "utf-8"));
|
|
183574
184219
|
} catch {
|
|
183575
184220
|
return null;
|
|
183576
184221
|
}
|
|
@@ -183584,7 +184229,7 @@ function readCliVersion() {
|
|
|
183584
184229
|
];
|
|
183585
184230
|
for (const candidate of candidates) {
|
|
183586
184231
|
if (existsSync4(candidate)) {
|
|
183587
|
-
const pkg = JSON.parse(
|
|
184232
|
+
const pkg = JSON.parse(readFileSync4(candidate, "utf-8"));
|
|
183588
184233
|
if (pkg.version)
|
|
183589
184234
|
return pkg.version;
|
|
183590
184235
|
}
|
|
@@ -184386,8 +185031,8 @@ import path15 from "node:path";
|
|
|
184386
185031
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
184387
185032
|
|
|
184388
185033
|
// src/lib/format-eigenpal.ts
|
|
184389
|
-
import { spawnSync } from "child_process";
|
|
184390
|
-
import { existsSync as existsSync5, readFileSync as
|
|
185034
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
185035
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
184391
185036
|
import { join as join4, resolve as resolve3 } from "path";
|
|
184392
185037
|
var PRETTRC_NAMES = [
|
|
184393
185038
|
".prettierrc",
|
|
@@ -184408,7 +185053,7 @@ function hasPrettierConfig(cwd) {
|
|
|
184408
185053
|
const pkgPath = join4(cwd, "package.json");
|
|
184409
185054
|
if (!existsSync5(pkgPath))
|
|
184410
185055
|
return false;
|
|
184411
|
-
const raw =
|
|
185056
|
+
const raw = readFileSync5(pkgPath, "utf-8");
|
|
184412
185057
|
const pkg = JSON.parse(raw);
|
|
184413
185058
|
return pkg != null && typeof pkg === "object" && "prettier" in pkg;
|
|
184414
185059
|
} catch {
|
|
@@ -184423,7 +185068,7 @@ function formatEigenpalDirIfAvailable(dir) {
|
|
|
184423
185068
|
if (!hasPrettierConfig(cwd))
|
|
184424
185069
|
return;
|
|
184425
185070
|
const runner = typeof Bun !== "undefined" ? "bunx" : "npx";
|
|
184426
|
-
|
|
185071
|
+
spawnSync2(runner, ["prettier", "--write", absDir], {
|
|
184427
185072
|
cwd,
|
|
184428
185073
|
stdio: "ignore",
|
|
184429
185074
|
shell: false
|
|
@@ -184509,7 +185154,7 @@ import { existsSync as existsSync7, readdirSync as readdirSync4, rmSync as rmSyn
|
|
|
184509
185154
|
import { basename, join as join7 } from "path";
|
|
184510
185155
|
|
|
184511
185156
|
// src/lib/payload.ts
|
|
184512
|
-
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as
|
|
185157
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
|
|
184513
185158
|
import { join as join6 } from "path";
|
|
184514
185159
|
|
|
184515
185160
|
// src/lib/fs-helpers.ts
|
|
@@ -184566,7 +185211,7 @@ function getExampleNames(dir, exampleNamesFilter) {
|
|
|
184566
185211
|
function readInput(exampleDir) {
|
|
184567
185212
|
const argsPath = join6(exampleDir, "input", "arguments.json");
|
|
184568
185213
|
const inputDir = join6(exampleDir, "input");
|
|
184569
|
-
const scalars = JSON.parse(
|
|
185214
|
+
const scalars = JSON.parse(readFileSync6(argsPath, "utf-8"));
|
|
184570
185215
|
const files = [];
|
|
184571
185216
|
for (const entry of readdirSync3(inputDir)) {
|
|
184572
185217
|
const full = join6(inputDir, entry);
|
|
@@ -184577,7 +185222,7 @@ function readInput(exampleDir) {
|
|
|
184577
185222
|
files.push({
|
|
184578
185223
|
argument: entry,
|
|
184579
185224
|
filename,
|
|
184580
|
-
content:
|
|
185225
|
+
content: readFileSync6(join6(full, filename)),
|
|
184581
185226
|
mimeType: guessMimeType(filename)
|
|
184582
185227
|
});
|
|
184583
185228
|
}
|
|
@@ -184588,7 +185233,7 @@ function readOverrides(exampleDir) {
|
|
|
184588
185233
|
const metaPath = join6(exampleDir, "meta.json");
|
|
184589
185234
|
if (!existsSync6(metaPath))
|
|
184590
185235
|
return null;
|
|
184591
|
-
const raw = JSON.parse(
|
|
185236
|
+
const raw = JSON.parse(readFileSync6(metaPath, "utf-8"));
|
|
184592
185237
|
const ov = raw.overrides;
|
|
184593
185238
|
if (ov && typeof ov === "object" && "steps" in ov && typeof ov.steps === "object") {
|
|
184594
185239
|
return ov;
|
|
@@ -184845,18 +185490,18 @@ async function watchExecution(opts) {
|
|
|
184845
185490
|
import { join as join11 } from "path";
|
|
184846
185491
|
|
|
184847
185492
|
// src/lib/execution-artifacts.ts
|
|
184848
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as
|
|
185493
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
184849
185494
|
import { join as join10 } from "path";
|
|
184850
185495
|
|
|
184851
185496
|
// src/lib/format.ts
|
|
184852
|
-
import { readFileSync as
|
|
185497
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
184853
185498
|
import { extname as extname3, resolve as resolve5 } from "path";
|
|
184854
185499
|
var PRETTIER_EXTENSIONS = new Set([".json", ".yaml", ".yml"]);
|
|
184855
185500
|
async function formatFileIfAvailable(filepath) {
|
|
184856
185501
|
if (!PRETTIER_EXTENSIONS.has(extname3(filepath)))
|
|
184857
185502
|
return;
|
|
184858
185503
|
try {
|
|
184859
|
-
const content =
|
|
185504
|
+
const content = readFileSync7(filepath, "utf-8");
|
|
184860
185505
|
const prettier = await Promise.resolve().then(() => (init_prettier(), exports_prettier));
|
|
184861
185506
|
const formatted = await prettier.format(content, {
|
|
184862
185507
|
filepath: resolve5(filepath)
|
|
@@ -185025,7 +185670,7 @@ function createProgressLines(options8) {
|
|
|
185025
185670
|
// src/commands/exec.ts
|
|
185026
185671
|
var POLL_INTERVAL_MS = 2000;
|
|
185027
185672
|
var MAX_POLL_MS = 5 * 60 * 1000;
|
|
185028
|
-
var
|
|
185673
|
+
var DEFAULT_CONCURRENCY = 3;
|
|
185029
185674
|
async function pollExecution2(client, executionId) {
|
|
185030
185675
|
const start = Date.now();
|
|
185031
185676
|
while (Date.now() - start < MAX_POLL_MS) {
|
|
@@ -185041,8 +185686,8 @@ async function runExec(client, dir, workflowIdOrSlug, exampleNames, options8 = {
|
|
|
185041
185686
|
const names = getExampleNames(dir, exampleNames.length ? exampleNames : undefined);
|
|
185042
185687
|
if (names.length === 0)
|
|
185043
185688
|
throw new Error("No matching eval examples found.");
|
|
185044
|
-
const requested = options8.concurrencyOverride ??
|
|
185045
|
-
const requestedValid = Number.isFinite(requested) && requested > 0 ? requested :
|
|
185689
|
+
const requested = options8.concurrencyOverride ?? DEFAULT_CONCURRENCY;
|
|
185690
|
+
const requestedValid = Number.isFinite(requested) && requested > 0 ? requested : DEFAULT_CONCURRENCY;
|
|
185046
185691
|
const concurrency = Math.max(1, Math.min(requestedValid, names.length));
|
|
185047
185692
|
const evalBaseDir = resolveEvalBaseDir(dir);
|
|
185048
185693
|
if (!evalBaseDir)
|
|
@@ -185623,7 +186268,7 @@ function parseWorkflow(yaml) {
|
|
|
185623
186268
|
}
|
|
185624
186269
|
// src/commands/validate.ts
|
|
185625
186270
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
185626
|
-
import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as
|
|
186271
|
+
import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
|
|
185627
186272
|
import { join as join12, resolve as resolve6 } from "path";
|
|
185628
186273
|
var NAME_RE = /^[a-z0-9][a-z0-9-_]*$/;
|
|
185629
186274
|
function isDirSafe(path15, issues, field) {
|
|
@@ -185641,7 +186286,7 @@ function validateWorkflowYaml(path15) {
|
|
|
185641
186286
|
if (!existsSync9(path15)) {
|
|
185642
186287
|
return [{ field: path15, message: "File not found." }];
|
|
185643
186288
|
}
|
|
185644
|
-
const text =
|
|
186289
|
+
const text = readFileSync9(path15, "utf-8");
|
|
185645
186290
|
try {
|
|
185646
186291
|
parseWorkflow(text);
|
|
185647
186292
|
return [];
|
|
@@ -185663,7 +186308,7 @@ function validateEvaluatorsYaml(path15) {
|
|
|
185663
186308
|
if (!existsSync9(path15)) {
|
|
185664
186309
|
return [{ field: path15, message: "File not found." }];
|
|
185665
186310
|
}
|
|
185666
|
-
const text =
|
|
186311
|
+
const text = readFileSync9(path15, "utf-8");
|
|
185667
186312
|
let parsed;
|
|
185668
186313
|
try {
|
|
185669
186314
|
parsed = import_yaml5.parse(text);
|
|
@@ -185715,7 +186360,7 @@ function validateDatasetFolder(root2) {
|
|
|
185715
186360
|
}
|
|
185716
186361
|
let args;
|
|
185717
186362
|
try {
|
|
185718
|
-
const parsed = JSON.parse(
|
|
186363
|
+
const parsed = JSON.parse(readFileSync9(argsPath, "utf-8"));
|
|
185719
186364
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
185720
186365
|
issues.push({
|
|
185721
186366
|
field: `examples/${exampleName}/input/arguments.json`,
|
|
@@ -185773,7 +186418,7 @@ function validateDatasetFolder(root2) {
|
|
|
185773
186418
|
if (existsSync9(expectedPath)) {
|
|
185774
186419
|
let parsed;
|
|
185775
186420
|
try {
|
|
185776
|
-
parsed = JSON.parse(
|
|
186421
|
+
parsed = JSON.parse(readFileSync9(expectedPath, "utf-8"));
|
|
185777
186422
|
} catch {
|
|
185778
186423
|
issues.push({
|
|
185779
186424
|
field: `examples/${exampleName}/expected/output.json`,
|
|
@@ -186316,7 +186961,7 @@ async function readDirAsZip(dir) {
|
|
|
186316
186961
|
}
|
|
186317
186962
|
return zipSync(tree);
|
|
186318
186963
|
}
|
|
186319
|
-
async function
|
|
186964
|
+
async function downloadStreamToFile2(client, path16, outFile) {
|
|
186320
186965
|
const res = await client.getStream(path16);
|
|
186321
186966
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
186322
186967
|
if (outFile) {
|
|
@@ -186620,7 +187265,7 @@ function registerDatasetCommands2(parent) {
|
|
|
186620
187265
|
const pullCmd = dataset.command("pull <workflow-id>").description(descriptionFor("workflow_get_dataset")).option("--out <zip>", "Write the dataset ZIP to this path. When omitted, the binary streams to stdout.");
|
|
186621
187266
|
withBaseUrl(pullCmd).action(action(async (workflow2, opts) => {
|
|
186622
187267
|
const { client, workflowId } = await buildClientForWorkflow(workflow2, opts);
|
|
186623
|
-
await
|
|
187268
|
+
await downloadStreamToFile2(client, `/api/v1/workflows/${workflowId}/dataset/export`, opts.out);
|
|
186624
187269
|
}));
|
|
186625
187270
|
const pushCmd = dataset.command("push <workflow-id>").description(descriptionFor("workflow_set_dataset")).requiredOption("--file <path>", "Path to a dataset ZIP file or a dataset/ folder (folder is zipped in memory before upload)").option("--mode <append|replace>", "Import mode (default: append)", "append").option("--yes", "Skip the destructive confirmation prompt for --mode replace (use in CI)", false).addHelpText("after", `
|
|
186626
187271
|
Examples:
|
|
@@ -187069,7 +187714,7 @@ Behavior:
|
|
|
187069
187714
|
const params = new URLSearchParams({ format: opts.format });
|
|
187070
187715
|
if (batchId)
|
|
187071
187716
|
params.set("batchId", batchId);
|
|
187072
|
-
await
|
|
187717
|
+
await downloadStreamToFile2(client, `/api/v1/workflows/${workflowId}/eval-results/export?${params.toString()}`, opts.out);
|
|
187073
187718
|
}));
|
|
187074
187719
|
const compareCmd = experiment.command("compare <batchIdA> <batchIdB>").description("Diff eval scores between two experiment batches.").option("--sort <abs-delta-desc|delta-asc|delta-desc|name>", "Row sort order (default: biggest movers first)", "abs-delta-desc").option("--regression-threshold <n>", "Δ below this is flagged as a regression (default 0.05)", Number.parseFloat, 0.05).addHelpText("after", `
|
|
187075
187720
|
Examples:
|
|
@@ -187157,7 +187802,7 @@ Behavior:
|
|
|
187157
187802
|
return;
|
|
187158
187803
|
const params = new URLSearchParams({ format: opts.format, batchId });
|
|
187159
187804
|
try {
|
|
187160
|
-
await
|
|
187805
|
+
await downloadStreamToFile2(client, `/api/v1/workflows/${workflowId}/eval-results/export?${params.toString()}`, dest);
|
|
187161
187806
|
} catch (err2) {
|
|
187162
187807
|
error51(`Watch finished but pulling results failed: ${err2 instanceof Error ? err2.message : String(err2)}. Re-run \`experiment results <wf> <batch>\` to retry.`);
|
|
187163
187808
|
process.exit(1);
|
|
@@ -187358,6 +188003,39 @@ function registerStepTypeCommands(parent) {
|
|
|
187358
188003
|
});
|
|
187359
188004
|
}
|
|
187360
188005
|
|
|
188006
|
+
// src/lib/command-aliases.ts
|
|
188007
|
+
var CONVENTION_ALIASES = new Map([
|
|
188008
|
+
["artifacts", "artifact"],
|
|
188009
|
+
["execution", "exec"],
|
|
188010
|
+
["experiment", "exp"],
|
|
188011
|
+
["feedback", "fb"],
|
|
188012
|
+
["list", "ls"],
|
|
188013
|
+
["compare", "diff"]
|
|
188014
|
+
]);
|
|
188015
|
+
function applyCommandAliasConventions(root2) {
|
|
188016
|
+
for (const command of root2.commands) {
|
|
188017
|
+
applySiblingAliases(command.parent ?? root2);
|
|
188018
|
+
applyCommandAliasConventions(command);
|
|
188019
|
+
}
|
|
188020
|
+
}
|
|
188021
|
+
function applySiblingAliases(parent) {
|
|
188022
|
+
const reserved = new Set;
|
|
188023
|
+
for (const sibling of parent.commands) {
|
|
188024
|
+
reserved.add(sibling.name());
|
|
188025
|
+
for (const alias of sibling.aliases())
|
|
188026
|
+
reserved.add(alias);
|
|
188027
|
+
}
|
|
188028
|
+
for (const command of parent.commands) {
|
|
188029
|
+
const alias = CONVENTION_ALIASES.get(command.name());
|
|
188030
|
+
if (!alias || command.aliases().includes(alias))
|
|
188031
|
+
continue;
|
|
188032
|
+
if (reserved.has(alias))
|
|
188033
|
+
continue;
|
|
188034
|
+
command.aliases([...command.aliases(), alias]);
|
|
188035
|
+
reserved.add(alias);
|
|
188036
|
+
}
|
|
188037
|
+
}
|
|
188038
|
+
|
|
187361
188039
|
// src/lib/logo.ts
|
|
187362
188040
|
var LOGO_WIDTH = 22;
|
|
187363
188041
|
var LOGO_LINES = [
|
|
@@ -187803,6 +188481,7 @@ skillCmd.command("list").description("Show every tool that has an Eigenpal skill
|
|
|
187803
188481
|
process.exit(1);
|
|
187804
188482
|
}
|
|
187805
188483
|
});
|
|
188484
|
+
applyCommandAliasConventions(program2);
|
|
187806
188485
|
function isEntryPoint() {
|
|
187807
188486
|
const argv1 = process.argv[1];
|
|
187808
188487
|
if (!argv1)
|