@eigenpal/cli 0.16.8 → 0.16.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -7671,9 +7671,51 @@ var require_picocolors = __commonJS(function(exports, module) {
7671
7671
  module.exports.createColors = createColors;
7672
7672
  });
7673
7673
 
7674
+ // ../../node_modules/nanoid/index.js
7675
+ import { webcrypto as crypto } from "node:crypto";
7676
+ function fillPool(bytes) {
7677
+ if (!pool || pool.length < bytes) {
7678
+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
7679
+ crypto.getRandomValues(pool);
7680
+ poolOffset = 0;
7681
+ } else if (poolOffset + bytes > pool.length) {
7682
+ crypto.getRandomValues(pool);
7683
+ poolOffset = 0;
7684
+ }
7685
+ poolOffset += bytes;
7686
+ }
7687
+ function random(bytes) {
7688
+ fillPool(bytes |= 0);
7689
+ return pool.subarray(poolOffset - bytes, poolOffset);
7690
+ }
7691
+ function customRandom(alphabet, defaultSize, getRandom) {
7692
+ let mask = (2 << 31 - Math.clz32(alphabet.length - 1 | 1)) - 1;
7693
+ let step = Math.ceil(1.6 * mask * defaultSize / alphabet.length);
7694
+ return (size = defaultSize) => {
7695
+ if (!size)
7696
+ return "";
7697
+ let id = "";
7698
+ while (true) {
7699
+ let bytes = getRandom(step);
7700
+ let i = step;
7701
+ while (i--) {
7702
+ id += alphabet[bytes[i] & mask] || "";
7703
+ if (id.length >= size)
7704
+ return id;
7705
+ }
7706
+ }
7707
+ };
7708
+ }
7709
+ function customAlphabet(alphabet, size = 21) {
7710
+ return customRandom(alphabet, size, random);
7711
+ }
7712
+ var POOL_SIZE_MULTIPLIER = 128, pool, poolOffset;
7713
+ var init_nanoid = () => {};
7714
+
7674
7715
  // ../types/src/core/common.ts
7675
- var ID_PREFIXES, NANOID_SUFFIX_PATTERN = "[A-Za-z0-9_-]{21}", TemplateIdSchema, TemplateRevisionIdSchema, TimestampSchema, JsonSchemaSchema, BaseEntitySchema;
7716
+ var ID_PREFIXES, generateRandomId, NANOID_SUFFIX_PATTERN = "[A-Za-z0-9_-]{21}", TemplateIdSchema, TemplateRevisionIdSchema, TimestampSchema, JsonSchemaSchema, BaseEntitySchema;
7676
7717
  var init_common = __esm(() => {
7718
+ init_nanoid();
7677
7719
  init_zod();
7678
7720
  ID_PREFIXES = {
7679
7721
  WORKFLOW: "wf",
@@ -7731,6 +7773,7 @@ var init_common = __esm(() => {
7731
7773
  OCR_JOB: "opj",
7732
7774
  SANDBOX_WS_TOKEN: "sws"
7733
7775
  };
7776
+ generateRandomId = customAlphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 21);
7734
7777
  TemplateIdSchema = string2().regex(new RegExp(`^${ID_PREFIXES.TEMPLATE}_${NANOID_SUFFIX_PATTERN}$`), "Expected tmpl_… id; file_… ids are not public template identities");
7735
7778
  TemplateRevisionIdSchema = string2().regex(new RegExp(`^${ID_PREFIXES.TEMPLATE_REVISION}_${NANOID_SUFFIX_PATTERN}$`), "Expected tmpr_… id");
7736
7779
  TimestampSchema = union([date3(), string2().datetime()]).transform((val2) => {
@@ -206235,7 +206278,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
206235
206278
  // package.json
206236
206279
  var package_default = {
206237
206280
  name: "@eigenpal/cli",
206238
- version: "0.16.8",
206281
+ version: "0.16.9",
206239
206282
  description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
206240
206283
  keywords: [
206241
206284
  "eigenpal",
@@ -207042,6 +207085,47 @@ function resolveBaseUrlFromActionArgs(args) {
207042
207085
  }
207043
207086
  }
207044
207087
 
207088
+ // src/lib/non-interactive.ts
207089
+ import { createInterface } from "node:readline/promises";
207090
+ function isInteractiveStderr() {
207091
+ return Boolean(process.stdin.isTTY && process.stderr.isTTY);
207092
+ }
207093
+ function isInteractiveStdout() {
207094
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
207095
+ }
207096
+ function nonInteractiveYesRequired(action) {
207097
+ return `${action} requires --yes when run non-interactively (CI, pipes, or agent terminals without a TTY).`;
207098
+ }
207099
+ function requireYesInNonInteractive(yes, action) {
207100
+ if (yes || isInteractiveStderr())
207101
+ return;
207102
+ throw new Error(nonInteractiveYesRequired(action));
207103
+ }
207104
+ async function confirmTyped(id, actionName) {
207105
+ if (!isInteractiveStderr())
207106
+ return false;
207107
+ process.stderr.write(`
207108
+ ${ui.warn("!")} About to ${actionName} for ${ui.bold(id)}.
207109
+ Type ${ui.bold(id)} to confirm: `);
207110
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
207111
+ try {
207112
+ return (await rl.question("")).trim() === id;
207113
+ } finally {
207114
+ rl.close();
207115
+ }
207116
+ }
207117
+ async function requireTypedConfirmation(opts) {
207118
+ if (opts.yes)
207119
+ return;
207120
+ if (!isInteractiveStderr()) {
207121
+ throw new Error(nonInteractiveYesRequired(`Typed confirmation to ${opts.actionName}`));
207122
+ }
207123
+ const ok = await confirmTyped(opts.id, opts.actionName);
207124
+ if (!ok) {
207125
+ throw new Error(opts.cancelledMessage ?? `${opts.actionName} aborted`);
207126
+ }
207127
+ }
207128
+
207045
207129
  // src/commands/git/index.ts
207046
207130
  init_src();
207047
207131
  init_zod();
@@ -209049,6 +209133,27 @@ function registerGitCommands(program) {
209049
209133
  credentialHelper.hidden = true;
209050
209134
  }
209051
209135
 
209136
+ // src/commands/workflow/lifecycle-shared.ts
209137
+ function buildClient(opts) {
209138
+ const config = resolveConfig(opts);
209139
+ requireApiKey(config);
209140
+ return new ApiClient(config);
209141
+ }
209142
+ function printJson(value) {
209143
+ console.log(JSON.stringify(value, null, 2));
209144
+ }
209145
+ async function fetchAutomation(client, automationId) {
209146
+ return await client.get(`/v1/automations/${encodeURIComponent(automationId)}`);
209147
+ }
209148
+ function parseAutomationDeleteResult(result) {
209149
+ if (result == null)
209150
+ return { deleted: true };
209151
+ if (typeof result === "object" && result !== null && "deleted" in result) {
209152
+ return result;
209153
+ }
209154
+ return { deleted: true };
209155
+ }
209156
+
209052
209157
  // ../../node_modules/fflate/esm/index.mjs
209053
209158
  import { createRequire as createRequire2 } from "module";
209054
209159
  var require2 = createRequire2("/");
@@ -209696,47 +209801,6 @@ function zipSync(data, opts) {
209696
209801
  import { existsSync as existsSync8, promises as fs3 } from "node:fs";
209697
209802
  import path8 from "node:path";
209698
209803
 
209699
- // src/lib/non-interactive.ts
209700
- import { createInterface as createInterface2 } from "node:readline/promises";
209701
- function isInteractiveStderr() {
209702
- return Boolean(process.stdin.isTTY && process.stderr.isTTY);
209703
- }
209704
- function isInteractiveStdout() {
209705
- return Boolean(process.stdin.isTTY && process.stdout.isTTY);
209706
- }
209707
- function nonInteractiveYesRequired(action) {
209708
- return `${action} requires --yes when run non-interactively (CI, pipes, or agent terminals without a TTY).`;
209709
- }
209710
- function requireYesInNonInteractive(yes, action) {
209711
- if (yes || isInteractiveStderr())
209712
- return;
209713
- throw new Error(nonInteractiveYesRequired(action));
209714
- }
209715
- async function confirmTyped(id, actionName) {
209716
- if (!isInteractiveStderr())
209717
- return false;
209718
- process.stderr.write(`
209719
- ${ui.warn("!")} About to ${actionName} for ${ui.bold(id)}.
209720
- Type ${ui.bold(id)} to confirm: `);
209721
- const rl = createInterface2({ input: process.stdin, output: process.stderr });
209722
- try {
209723
- return (await rl.question("")).trim() === id;
209724
- } finally {
209725
- rl.close();
209726
- }
209727
- }
209728
- async function requireTypedConfirmation(opts) {
209729
- if (opts.yes)
209730
- return;
209731
- if (!isInteractiveStderr()) {
209732
- throw new Error(nonInteractiveYesRequired(`Typed confirmation to ${opts.actionName}`));
209733
- }
209734
- const ok = await confirmTyped(opts.id, opts.actionName);
209735
- if (!ok) {
209736
- throw new Error(opts.cancelledMessage ?? `${opts.actionName} aborted`);
209737
- }
209738
- }
209739
-
209740
209804
  // src/commands/agents/shared.ts
209741
209805
  init_src();
209742
209806
  import { existsSync as existsSync6, promises as fs } from "node:fs";
@@ -209760,7 +209824,7 @@ function agentAutomationId(value) {
209760
209824
  return value;
209761
209825
  return `agents.${value}`;
209762
209826
  }
209763
- function buildClient(opts) {
209827
+ function buildClient2(opts) {
209764
209828
  const config = resolveConfig(opts);
209765
209829
  requireApiKey(config);
209766
209830
  return new ApiClient(config);
@@ -209780,7 +209844,7 @@ async function pollRun(client, executionId, interval, maxWait, json = false) {
209780
209844
  }
209781
209845
  if (Date.now() - started > maxWait * 1000) {
209782
209846
  if (json)
209783
- printJson(payload);
209847
+ printJson2(payload);
209784
209848
  process.stderr.write(`Timed out waiting for run ${executionId}
209785
209849
  `);
209786
209850
  process.exit(2);
@@ -209808,7 +209872,7 @@ async function pollExperiment(client, automationId, batchId, interval, maxWait,
209808
209872
  return payload;
209809
209873
  if (Date.now() - started > maxWait * 1000) {
209810
209874
  if (json)
209811
- printJson(lastPayload ?? { batchId, status: "pending" });
209875
+ printJson2(lastPayload ?? { batchId, status: "pending" });
209812
209876
  process.stderr.write(`Timed out waiting for experiment ${batchId}
209813
209877
  `);
209814
209878
  process.exit(2);
@@ -209818,10 +209882,10 @@ async function pollExperiment(client, automationId, batchId, interval, maxWait,
209818
209882
  }
209819
209883
  function renderRunPayload(payload, opts) {
209820
209884
  if (opts.json)
209821
- return printJson(payload);
209885
+ return printJson2(payload);
209822
209886
  const run = payload;
209823
209887
  if (!run || run.id === undefined)
209824
- return printJson(payload);
209888
+ return printJson2(payload);
209825
209889
  const status = run.execution?.status ?? (run.finished === true ? "completed" : "running");
209826
209890
  success(`Run ${run.id} is ${status}`);
209827
209891
  }
@@ -209834,7 +209898,7 @@ function setExitCodeForFailedTerminalRun(payload) {
209834
209898
  }
209835
209899
  function renderGeneric(payload, opts, message) {
209836
209900
  if (opts.json)
209837
- return printJson(payload);
209901
+ return printJson2(payload);
209838
209902
  success(message);
209839
209903
  }
209840
209904
  function compactParams(opts) {
@@ -209846,7 +209910,7 @@ function compactParams(opts) {
209846
209910
  }
209847
209911
  return params;
209848
209912
  }
209849
- function printJson(value) {
209913
+ function printJson2(value) {
209850
209914
  console.log(JSON.stringify(value, null, 2));
209851
209915
  }
209852
209916
  function parseDatasetMode(value) {
@@ -210230,11 +210294,11 @@ Layout (mirrors the server import rules)
210230
210294
  `).action(action(validateDatasetCommand));
210231
210295
  }
210232
210296
  async function listDataset(agentId, opts) {
210233
- const client = buildClient(opts);
210297
+ const client = buildClient2(opts);
210234
210298
  const payload = await client.get(`/v1/automations/${encodeURIComponent(agentAutomationId(agentId))}/examples`, compactParams(opts));
210235
210299
  const examples = payload.data ?? [];
210236
210300
  if (opts.json)
210237
- return printJson(payload);
210301
+ return printJson2(payload);
210238
210302
  console.log(table(examples.map((row) => ({ id: row.id, name: row.name })), [
210239
210303
  { key: "id", header: "ID" },
210240
210304
  { key: "name", header: "NAME" }
@@ -210256,14 +210320,14 @@ async function pushDataset(agentId, opts) {
210256
210320
  const form = new FormData;
210257
210321
  form.set("file", new Blob([archive], { type: "application/zip" }), stat.isDirectory() ? "dataset.zip" : path8.basename(resolved));
210258
210322
  form.set("mode", opts.mode);
210259
- const client = buildClient(opts);
210323
+ const client = buildClient2(opts);
210260
210324
  const payload = await client.postFormData(`/v1/automations/${encodeURIComponent(agentAutomationId(agentId))}/dataset/import`, form);
210261
210325
  if (opts.json)
210262
- return printJson(payload);
210326
+ return printJson2(payload);
210263
210327
  success(`${opts.mode === "replace" ? "Replaced" : "Uploaded"} dataset archive`);
210264
210328
  }
210265
210329
  async function pullDataset(agentId, opts) {
210266
- const client = buildClient(opts);
210330
+ const client = buildClient2(opts);
210267
210331
  const res = await client.getStream(`/v1/automations/${encodeURIComponent(agentAutomationId(agentId))}/dataset/export`);
210268
210332
  const archive = Buffer.from(await res.arrayBuffer());
210269
210333
  const out = path8.resolve(opts.out ?? DATASET_DIR);
@@ -210276,7 +210340,7 @@ async function validateDatasetCommand(dir = DATASET_DIR, opts) {
210276
210340
  agentDir: path8.resolve(opts.agentDir ?? ".")
210277
210341
  });
210278
210342
  if (opts.json)
210279
- return printJson(result);
210343
+ return printJson2(result);
210280
210344
  if (result.valid)
210281
210345
  return success("Dataset is valid");
210282
210346
  for (const issue of result.errors)
@@ -210348,7 +210412,7 @@ async function pullAgentEnv(target, opts) {
210348
210412
  if (format !== "shell" && format !== "dotenv") {
210349
210413
  throw new Error("--format must be shell or dotenv");
210350
210414
  }
210351
- const client = buildClient(opts);
210415
+ const client = buildClient2(opts);
210352
210416
  const requests = target ? await collectEncryptedSecretsForTarget(client, target) : await collectEncryptedSecrets(path9.resolve(opts.dir ?? "."));
210353
210417
  if (requests.length === 0)
210354
210418
  return;
@@ -211173,7 +211237,7 @@ function registerExperimentCommands(agent) {
211173
211237
  addJsonFlag(withBaseUrl(experiment.command("cancel <agent-id-or-slug> <batch-id>"))).description("Cancel every active execution in an experiment.").option("--yes", "Skip confirmation (required in CI / agent terminals without a TTY)").action(action(cancelExperiment));
211174
211238
  }
211175
211239
  async function runExperiment(agentId, opts) {
211176
- const client = buildClient(opts);
211240
+ const client = buildClient2(opts);
211177
211241
  const automationId = agentAutomationId(agentId);
211178
211242
  let payload = await client.post(`/v1/automations/${encodeURIComponent(automationId)}/experiments`, {
211179
211243
  ...opts.exampleId ? { examples: [opts.exampleId] } : {}
@@ -211197,7 +211261,7 @@ async function runExperiment(agentId, opts) {
211197
211261
  }
211198
211262
  }
211199
211263
  async function experimentStatus(agentId, batchId, opts) {
211200
- const client = buildClient(opts);
211264
+ const client = buildClient2(opts);
211201
211265
  const automationId = agentAutomationId(agentId);
211202
211266
  const payload = opts.watch ? await pollExperiment(client, automationId, batchId, opts.interval, opts.maxWait, opts.json) : await client.get(`/v1/automations/${encodeURIComponent(automationId)}/experiments/${encodeURIComponent(batchId)}`);
211203
211267
  renderGeneric(payload, opts, `Experiment ${batchId}`);
@@ -211209,7 +211273,7 @@ async function experimentStatus(agentId, batchId, opts) {
211209
211273
  }
211210
211274
  }
211211
211275
  async function experimentResults(agentId, batchId, opts) {
211212
- const client = buildClient(opts);
211276
+ const client = buildClient2(opts);
211213
211277
  const automationId = agentAutomationId(agentId);
211214
211278
  if (opts.json && opts.format !== "json") {
211215
211279
  throw new Error("--json cannot be combined with --format csv");
@@ -211257,7 +211321,7 @@ async function experimentResults(agentId, batchId, opts) {
211257
211321
  }
211258
211322
  }
211259
211323
  async function listExperiments(agentId, opts) {
211260
- const client = buildClient(opts);
211324
+ const client = buildClient2(opts);
211261
211325
  const automationId = agentAutomationId(agentId);
211262
211326
  const payload = await client.get(`/v1/automations/${encodeURIComponent(automationId)}/experiments`, compactParams(opts));
211263
211327
  const experiments = payload.data ?? [];
@@ -211265,7 +211329,7 @@ async function listExperiments(agentId, opts) {
211265
211329
  payload.data = experiments.filter((row) => row.id === opts.batchId || row.batchId === opts.batchId);
211266
211330
  }
211267
211331
  if (opts.json)
211268
- return printJson(payload);
211332
+ return printJson2(payload);
211269
211333
  console.log(table(payload.data ?? experiments, [
211270
211334
  { key: "id", header: "EXPERIMENT" },
211271
211335
  { key: "runCount", header: "RUNS" }
@@ -211277,7 +211341,7 @@ async function compareExperiments(batchIdA, batchIdB, opts) {
211277
211341
  if (!Number.isFinite(threshold) || threshold < 0) {
211278
211342
  throw new Error("--regression-threshold must be a non-negative number");
211279
211343
  }
211280
- const client = buildClient(opts);
211344
+ const client = buildClient2(opts);
211281
211345
  if (opts.outputs) {
211282
211346
  const [outputsA, outputsB] = await Promise.all([
211283
211347
  fetchExperimentOutputs(client, batchIdA),
@@ -211293,7 +211357,7 @@ async function compareExperiments(batchIdA, batchIdB, opts) {
211293
211357
  rowsB: outputsB.rows
211294
211358
  });
211295
211359
  if (opts.json)
211296
- return printJson(diff);
211360
+ return printJson2(diff);
211297
211361
  renderExperimentOutputDiffHuman(diff);
211298
211362
  return;
211299
211363
  }
@@ -211310,12 +211374,12 @@ async function compareExperiments(batchIdA, batchIdB, opts) {
211310
211374
  regressionThreshold: threshold
211311
211375
  });
211312
211376
  if (opts.json)
211313
- return printJson(diff);
211377
+ return printJson2(diff);
211314
211378
  renderBatchDiffHuman(diff);
211315
211379
  }
211316
211380
  async function cancelExperiment(agentId, batchId, opts) {
211317
211381
  requireYesInNonInteractive(opts.yes, "Cancel experiment batch");
211318
- const client = buildClient(opts);
211382
+ const client = buildClient2(opts);
211319
211383
  const payload = await client.post(`/v1/automations/${encodeURIComponent(agentAutomationId(agentId))}/experiments/${encodeURIComponent(batchId)}/cancel`);
211320
211384
  renderGeneric(payload, opts, `Cancelled experiment ${batchId}`);
211321
211385
  }
@@ -211334,24 +211398,24 @@ function registerAgentFileCommands(agent) {
211334
211398
  addJsonFlag(withBaseUrl(file.command("diff <agent-id-or-slug> <remote-path> <local-path>"))).description("Compare one live agent file against a local file.").action(action(diffAgentFile));
211335
211399
  }
211336
211400
  async function listAgentFiles(agentId, opts) {
211337
- const client = buildClient(opts);
211401
+ const client = buildClient2(opts);
211338
211402
  const packagePath = await resolveAgentPackagePath2(client, agentId);
211339
211403
  const payload = await client.get("/v1/source/tree", {
211340
211404
  packagePath,
211341
211405
  ...opts.path ? { prefix: normalizeAgentFilePath(opts.path, { allowEmpty: true }) } : {}
211342
211406
  });
211343
211407
  if (opts.json)
211344
- return printJson(payload);
211408
+ return printJson2(payload);
211345
211409
  console.log(table((payload.files ?? []).map((name) => ({ name })), [{ key: "name", header: "PATH" }]));
211346
211410
  }
211347
211411
  async function getAgentFile(agentId, remotePath, opts) {
211348
211412
  if (opts.json && opts.out) {
211349
211413
  throw new Error("--json and --out are mutually exclusive");
211350
211414
  }
211351
- const client = buildClient(opts);
211415
+ const client = buildClient2(opts);
211352
211416
  const payload = await readAgentFile(client, agentId, remotePath);
211353
211417
  if (opts.json)
211354
- return printJson(payload);
211418
+ return printJson2(payload);
211355
211419
  const out = path10.resolve(opts.out ?? payload.path);
211356
211420
  await writeBase64File(out, payload.contentBase64);
211357
211421
  success(`Downloaded ${payload.path} to ${ui.bold(out)}`);
@@ -211359,11 +211423,11 @@ async function getAgentFile(agentId, remotePath, opts) {
211359
211423
  async function diffAgentFile(agentId, remotePath, localPath, opts) {
211360
211424
  const report = await buildAgentFileDiff(agentId, remotePath, path10.resolve(localPath), opts);
211361
211425
  if (opts.json)
211362
- return printJson(report);
211426
+ return printJson2(report);
211363
211427
  renderAgentFileDiff(report);
211364
211428
  }
211365
211429
  async function buildAgentFileDiff(agentId, remotePath, localPath, opts) {
211366
- const client = buildClient(opts);
211430
+ const client = buildClient2(opts);
211367
211431
  const local = await fs6.readFile(localPath);
211368
211432
  let remote = null;
211369
211433
  let serverPath = normalizeAgentFilePath(remotePath);
@@ -211471,10 +211535,10 @@ function registerSessionCommands(agent) {
211471
211535
  addJsonFlag(withBaseUrl(session.command("stop <session-id>"))).description("Stop a builder session.").option("--yes", "Skip confirmation (required in CI / agent terminals without a TTY)").action(action(stopSession));
211472
211536
  }
211473
211537
  async function listSessions(agentId, opts) {
211474
- const client = buildClient(opts);
211538
+ const client = buildClient2(opts);
211475
211539
  const payload = await client.get(`/v1/agents/${encodeURIComponent(agentId)}/sessions`, compactParams(opts));
211476
211540
  if (opts.json)
211477
- return printJson(payload);
211541
+ return printJson2(payload);
211478
211542
  console.log(table(payload.sessions, [
211479
211543
  { key: "id", header: "ID" },
211480
211544
  { key: "status", header: "STATUS" },
@@ -211482,24 +211546,24 @@ async function listSessions(agentId, opts) {
211482
211546
  ]));
211483
211547
  }
211484
211548
  async function getSession(sessionId, opts) {
211485
- const client = buildClient(opts);
211549
+ const client = buildClient2(opts);
211486
211550
  renderGeneric(await client.get(`/v1/agents/sessions/${encodeURIComponent(sessionId)}`), opts, `Session ${sessionId}`);
211487
211551
  }
211488
211552
  async function startSession(agentId, opts) {
211489
- const client = buildClient(opts);
211553
+ const client = buildClient2(opts);
211490
211554
  renderGeneric(await client.post(`/v1/agents/${encodeURIComponent(agentId)}/sessions`, {
211491
211555
  ...opts.title ? { title: opts.title } : {}
211492
211556
  }), opts, "Started session");
211493
211557
  }
211494
211558
  async function messageSession(sessionId, opts) {
211495
- const client = buildClient(opts);
211559
+ const client = buildClient2(opts);
211496
211560
  renderGeneric(await client.post(`/v1/agents/sessions/${encodeURIComponent(sessionId)}`, {
211497
211561
  text: opts.text
211498
211562
  }), opts, "Sent message");
211499
211563
  }
211500
211564
  async function stopSession(sessionId, opts) {
211501
211565
  requireYesInNonInteractive(opts.yes, "Stop builder session");
211502
- const client = buildClient(opts);
211566
+ const client = buildClient2(opts);
211503
211567
  renderGeneric(await client.delete(`/v1/agents/sessions/${encodeURIComponent(sessionId)}`), opts, "Stopped session");
211504
211568
  }
211505
211569
 
@@ -239676,7 +239740,7 @@ async function runExample(agentId, opts) {
239676
239740
  if (opts.failOnMismatch && !opts.wait) {
239677
239741
  throw new Error("--fail-on-mismatch requires --wait because the evaluator verdict is asynchronous");
239678
239742
  }
239679
- const client = buildClient(opts);
239743
+ const client = buildClient2(opts);
239680
239744
  const started = await client.post(`/v1/automations/${encodeURIComponent(agentAutomationId(agentId))}/experiments`, {
239681
239745
  examples: [opts.example],
239682
239746
  ...opts.sourceRef ? { sourceRef: opts.sourceRef } : {}
@@ -239722,7 +239786,7 @@ async function runExample(agentId, opts) {
239722
239786
  status: "pending"
239723
239787
  };
239724
239788
  if (opts.json)
239725
- return printJson(payload);
239789
+ return printJson2(payload);
239726
239790
  success(`Run ${runId ?? ""} queued for example ${opts.example}`);
239727
239791
  }
239728
239792
  async function waitForExampleEvalRollup(client, agentId, runId) {
@@ -239806,7 +239870,7 @@ function projectionIncludeSource(opts) {
239806
239870
  return parts.length > 0 ? parts.join(",") : undefined;
239807
239871
  }
239808
239872
  async function getRun(executionId, opts) {
239809
- const client = buildClient(opts);
239873
+ const client = buildClient2(opts);
239810
239874
  const run = toLegacyRunView(await client.get(`/v1/runs/${encodeURIComponent(executionId)}`, {
239811
239875
  expand: serverExpandParam({ expand: opts.expand, include: opts.include })
239812
239876
  }));
@@ -239818,10 +239882,10 @@ async function getRun(executionId, opts) {
239818
239882
  const projectionIncludes = workflowStepProjectionIncludes(projectionIncludeSource(opts));
239819
239883
  const projectedRun = opts.step ? { ...run, stepExecutions: projectWorkflowSteps(steps, projectionIncludes) } : run;
239820
239884
  if (opts.select) {
239821
- return printJson(selectJsonValue(projectedRun, opts.select));
239885
+ return printJson2(selectJsonValue(projectedRun, opts.select));
239822
239886
  }
239823
239887
  if (opts.json) {
239824
- return printJson(projectedRun);
239888
+ return printJson2(projectedRun);
239825
239889
  }
239826
239890
  console.log(renderFrame(toExecutionSnapshot(projectedRun, executionId)));
239827
239891
  process.stderr.write(`${ui.dim(`use --json for the full payload, then pipe to jq for field projection`)}
@@ -239829,7 +239893,7 @@ async function getRun(executionId, opts) {
239829
239893
  return;
239830
239894
  }
239831
239895
  if (opts.select)
239832
- return printJson(selectJsonValue(run, opts.select));
239896
+ return printJson2(selectJsonValue(run, opts.select));
239833
239897
  renderRunPayload(run, opts);
239834
239898
  }
239835
239899
  function isWorkflowRun(run) {
@@ -240010,7 +240074,7 @@ function previewOutput(value) {
240010
240074
  return flat.length > PREVIEW_MAX ? `${flat.slice(0, PREVIEW_MAX - 3)}...` : flat;
240011
240075
  }
240012
240076
  async function rerunRun(executionId, opts) {
240013
- const client = buildClient(opts);
240077
+ const client = buildClient2(opts);
240014
240078
  const params = new URLSearchParams;
240015
240079
  const version = (opts.sourceRef ?? opts.version)?.trim();
240016
240080
  if (version && version !== "latest") {
@@ -240030,21 +240094,21 @@ async function rerunRun(executionId, opts) {
240030
240094
  return;
240031
240095
  }
240032
240096
  if (opts.json)
240033
- return printJson(payload);
240097
+ return printJson2(payload);
240034
240098
  success(`Started rerun ${ui.bold(rerunId)} from ${executionId}`);
240035
240099
  }
240036
240100
  async function promoteRun(executionId, opts) {
240037
- const client = buildClient(opts);
240101
+ const client = buildClient2(opts);
240038
240102
  const body = {};
240039
240103
  if (opts.name)
240040
240104
  body.name = opts.name;
240041
240105
  const payload = await client.post(`/v1/runs/${encodeURIComponent(executionId)}/promote`, body);
240042
240106
  if (opts.json)
240043
- return printJson(payload);
240107
+ return printJson2(payload);
240044
240108
  success(`Promoted ${executionId} to example ${ui.bold(payload.name ?? payload.exampleId ?? "")}` + `${payload.automationId ? ` on ${payload.automationType ?? ""} ${payload.automationId}`.trimEnd() : ""}`);
240045
240109
  }
240046
240110
  async function fetchRunArtifacts(executionId, opts) {
240047
- const client = buildClient(opts);
240111
+ const client = buildClient2(opts);
240048
240112
  const baseRun = toLegacyRunView(await client.get(`/v1/runs/${encodeURIComponent(executionId)}`, {
240049
240113
  expand: "input,execution"
240050
240114
  }));
@@ -240077,7 +240141,7 @@ async function fetchRunArtifacts(executionId, opts) {
240077
240141
  }
240078
240142
  };
240079
240143
  if (opts.json)
240080
- return printJson(summary);
240144
+ return printJson2(summary);
240081
240145
  success(`Fetched run artifacts for ${executionId} to ${out}`);
240082
240146
  dim(`Wrote ${written.length} artifact${written.length === 1 ? "" : "s"}${skipped.length ? `; skipped missing ${skipped.join(", ")}` : ""}`);
240083
240147
  }
@@ -240112,7 +240176,7 @@ async function inspectRunArtifact(runId, artifactPathArg, opts) {
240112
240176
  if (source.kind === "local") {
240113
240177
  buffer = await fs15.readFile(source.path);
240114
240178
  } else {
240115
- const client = buildClient(opts);
240179
+ const client = buildClient2(opts);
240116
240180
  const response = await client.getStream(`/v1/runs/${encodeURIComponent(source.runId)}/artifacts/${encodeRunArtifactPath(source.artifactPath)}`);
240117
240181
  buffer = Buffer.from(await response.arrayBuffer());
240118
240182
  }
@@ -240121,13 +240185,13 @@ async function inspectRunArtifact(runId, artifactPathArg, opts) {
240121
240185
  ...source.kind === "local" ? { file: source.path } : { runId: source.runId, artifactPath: source.artifactPath },
240122
240186
  ...inspect
240123
240187
  };
240124
- printJson(payload);
240188
+ printJson2(payload);
240125
240189
  }
240126
240190
  async function listRunArtifacts(executionId, opts) {
240127
- const client = buildClient(opts);
240191
+ const client = buildClient2(opts);
240128
240192
  const artifacts = await listCanonicalRunArtifacts(client, executionId);
240129
240193
  if (opts.json)
240130
- return printJson({ runId: executionId, artifacts });
240194
+ return printJson2({ runId: executionId, artifacts });
240131
240195
  console.log(table(artifacts, [
240132
240196
  { key: "kind", header: "KIND" },
240133
240197
  { key: "name", header: "NAME" },
@@ -240238,7 +240302,7 @@ async function writeRunArtifact(client, executionId, out, artifactPath, run) {
240238
240302
  return artifactPath;
240239
240303
  }
240240
240304
  async function traceRun(executionId, opts) {
240241
- const client = buildClient(opts);
240305
+ const client = buildClient2(opts);
240242
240306
  const text = await downloadTraceText(client, executionId);
240243
240307
  if (text.length === 0) {
240244
240308
  warn(`No trace events recorded for run ${executionId}.`);
@@ -240253,7 +240317,7 @@ async function traceRun(executionId, opts) {
240253
240317
  success(`Downloaded trace for ${executionId} to ${ui.bold(out)}`);
240254
240318
  }
240255
240319
  async function compareRun(referenceId, executionId, opts) {
240256
- const client = buildClient(opts);
240320
+ const client = buildClient2(opts);
240257
240321
  const target = toLegacyRunView(await client.get(`/v1/runs/${encodeURIComponent(executionId)}`, {
240258
240322
  expand: "execution"
240259
240323
  }));
@@ -240264,7 +240328,7 @@ async function compareRun(referenceId, executionId, opts) {
240264
240328
  if (isWorkflowRun(reference) && isWorkflowRun(target)) {
240265
240329
  const report = compareWorkflowRuns(referenceId, reference, executionId, target, opts.step);
240266
240330
  if (opts.json) {
240267
- printJson(report);
240331
+ printJson2(report);
240268
240332
  } else {
240269
240333
  renderWorkflowComparisonReport(report);
240270
240334
  }
@@ -240303,7 +240367,7 @@ async function compareRun(referenceId, executionId, opts) {
240303
240367
  };
240304
240368
  await fs15.writeFile(path15.join(out, "comparison.json"), JSON.stringify(report, null, 2));
240305
240369
  if (opts.json) {
240306
- printJson(report);
240370
+ printJson2(report);
240307
240371
  } else {
240308
240372
  renderComparisonReport(report);
240309
240373
  }
@@ -240420,7 +240484,7 @@ function compareOutputs(reference, target) {
240420
240484
  return `differs (A=${referenceJson.length}b, B=${targetJson.length}b)`;
240421
240485
  }
240422
240486
  async function listRuns(source, opts) {
240423
- const client = buildClient(opts);
240487
+ const client = buildClient2(opts);
240424
240488
  const parsedAgentTarget = source && (opts.type === "agent" || source.startsWith("agents.") || source.includes("@")) ? parseAgentTarget(source) : null;
240425
240489
  const resolvedWorkflowSource = source && opts.type === "workflow" ? await resolveWorkflowId(client, source) : undefined;
240426
240490
  const params = {
@@ -240431,7 +240495,7 @@ async function listRuns(source, opts) {
240431
240495
  const payload = await client.get("/v1/runs", params);
240432
240496
  const viewRuns = payload.runs.map(toLegacyRunView);
240433
240497
  if (opts.json)
240434
- return printJson({ ...payload, runs: viewRuns });
240498
+ return printJson2({ ...payload, runs: viewRuns });
240435
240499
  const rows = opts.compact ? viewRuns.map(compactRunRow) : viewRuns;
240436
240500
  if (payload.scanLimited)
240437
240501
  warn("Filtered run list scanned only the first matching window.");
@@ -240476,7 +240540,7 @@ function buildRunListParams(opts) {
240476
240540
  });
240477
240541
  }
240478
240542
  async function updateRunReview(executionId, opts) {
240479
- const client = buildClient(opts);
240543
+ const client = buildClient2(opts);
240480
240544
  const body = {};
240481
240545
  if (opts.status)
240482
240546
  body.status = opts.status;
@@ -240498,7 +240562,7 @@ async function updateRunReview(executionId, opts) {
240498
240562
  renderGeneric(payload, opts, `Updated review for ${executionId}`);
240499
240563
  }
240500
240564
  async function closeRunReview(executionId, opts) {
240501
- const client = buildClient(opts);
240565
+ const client = buildClient2(opts);
240502
240566
  const body = { status: opts.status ?? "closed" };
240503
240567
  if (opts.noteFile)
240504
240568
  body.note = await fs15.readFile(opts.noteFile, "utf-8");
@@ -240531,7 +240595,7 @@ async function clearRunReview(executionId, opts) {
240531
240595
  actionName: "clear review artifacts",
240532
240596
  cancelledMessage: "Clear cancelled"
240533
240597
  });
240534
- const client = buildClient(opts);
240598
+ const client = buildClient2(opts);
240535
240599
  const payload = await client.delete(`/v1/runs/${encodeURIComponent(executionId)}/reviews`);
240536
240600
  renderGeneric(payload, opts, `Cleared review for ${executionId}`);
240537
240601
  }
@@ -240545,16 +240609,16 @@ async function readRunExpected(client, executionId) {
240545
240609
  };
240546
240610
  }
240547
240611
  async function listRunExpected(executionId, opts) {
240548
- const client = buildClient(opts);
240612
+ const client = buildClient2(opts);
240549
240613
  const payload = await readRunExpected(client, executionId);
240550
240614
  if (opts.json)
240551
- return printJson(payload);
240615
+ return printJson2(payload);
240552
240616
  console.log(table(payload.files, [{ key: "name", header: "NAME" }]));
240553
240617
  if (payload.expected != null)
240554
240618
  dim("expected.json present");
240555
240619
  }
240556
240620
  async function pullRunExpected(executionId, opts) {
240557
- const client = buildClient(opts);
240621
+ const client = buildClient2(opts);
240558
240622
  const payload = await readRunExpected(client, executionId);
240559
240623
  const out = path15.resolve(opts.out ?? path15.join(executionId, "expected"));
240560
240624
  await fs15.mkdir(out, { recursive: true });
@@ -240578,7 +240642,7 @@ async function downloadExpectedFiles(client, executionId, out, files) {
240578
240642
  return written.filter((name) => Boolean(name));
240579
240643
  }
240580
240644
  async function uploadRunExpected(executionId, file, opts) {
240581
- const client = buildClient(opts);
240645
+ const client = buildClient2(opts);
240582
240646
  const form = new FormData;
240583
240647
  const data = await fs15.readFile(file);
240584
240648
  form.append("file", new Blob([data]), path15.basename(file));
@@ -240588,7 +240652,7 @@ async function uploadRunExpected(executionId, file, opts) {
240588
240652
  renderGeneric(payload, opts, `Uploaded expected file for ${executionId}`);
240589
240653
  }
240590
240654
  async function copyOutputToExpected(executionId, outputFile, opts) {
240591
- const client = buildClient(opts);
240655
+ const client = buildClient2(opts);
240592
240656
  const payload = await client.post(`/v1/runs/${encodeURIComponent(executionId)}/reviews/expected`, {
240593
240657
  outputFileName: outputFile,
240594
240658
  ...opts.name ? { expectedName: opts.name } : {}
@@ -240596,7 +240660,7 @@ async function copyOutputToExpected(executionId, outputFile, opts) {
240596
240660
  renderGeneric(payload, opts, `Copied output file to expected for ${executionId}`);
240597
240661
  }
240598
240662
  async function renameRunExpected(executionId, oldName, newName, opts) {
240599
- const client = buildClient(opts);
240663
+ const client = buildClient2(opts);
240600
240664
  const payload = await client.patch(`/v1/runs/${encodeURIComponent(executionId)}/reviews/expected/${encodeURIComponent(oldName)}`, { name: newName });
240601
240665
  renderGeneric(payload, opts, `Renamed expected file for ${executionId}`);
240602
240666
  }
@@ -240607,12 +240671,12 @@ async function deleteRunExpected(executionId, name, opts) {
240607
240671
  actionName: "delete expected file",
240608
240672
  cancelledMessage: "Delete cancelled"
240609
240673
  });
240610
- const client = buildClient(opts);
240674
+ const client = buildClient2(opts);
240611
240675
  await client.delete(`/v1/runs/${encodeURIComponent(executionId)}/reviews/expected/${encodeURIComponent(name)}`);
240612
240676
  renderGeneric({ ok: true }, opts, `Deleted expected file ${name}`);
240613
240677
  }
240614
240678
  async function watchRunCommand(executionId, opts) {
240615
- const client = buildClient(opts);
240679
+ const client = buildClient2(opts);
240616
240680
  if (opts.json) {
240617
240681
  const payload = await pollRun(client, executionId, opts.interval, opts.maxWait, opts.json);
240618
240682
  renderRunPayload(payload, opts);
@@ -240642,10 +240706,10 @@ Detached after ${opts.maxWait}s without reaching terminal status. Re-run \`eigen
240642
240706
  }
240643
240707
  async function cancelRun(executionId, opts) {
240644
240708
  requireYesInNonInteractive(opts.yes, "Cancel run");
240645
- const client = buildClient(opts);
240709
+ const client = buildClient2(opts);
240646
240710
  const payload = await client.post(`/v1/runs/${encodeURIComponent(executionId)}/cancel`, {});
240647
240711
  if (opts.json) {
240648
- printJson(payload);
240712
+ printJson2(payload);
240649
240713
  return;
240650
240714
  }
240651
240715
  success(`Cancellation requested for run ${executionId}.`);
@@ -240906,6 +240970,14 @@ function registerAgentCommands(program) {
240906
240970
  process.exit(2);
240907
240971
  });
240908
240972
  addJsonFlag(withPagination(withBaseUrl(agent.command("list")), 50)).description("List agents.").option("--search <q>", "Search by slug, name, or description").action(action(listAgents));
240973
+ addJsonFlag(withBaseUrl(agent.command("delete <agent-id-or-slug>"))).description("Delete an agent and its versions from the server.").option("--yes", "Skip typed-id confirmation (required in CI / agent terminals without a TTY)").addHelpText("after", `
240974
+ Permanently deletes the agent implementation, versions, and builder sessions.
240975
+ Unified prior runs remain in run history. This matches Studio agent deletion and
240976
+ cannot be undone.
240977
+
240978
+ Pass \`--yes\` in scripts, CI, and agent terminals (non-TTY). In a TTY, type the
240979
+ agent id (for example \`agents.invoice\`) to confirm.
240980
+ `).action(action(deleteAgent));
240909
240981
  registerAgentFileCommands(agent);
240910
240982
  addJsonFlag(agent.command("validate [dir]")).description("Validate a local agent package (layout, manifest, schemas, and Git source rules).").action(action(validateAgentCommand));
240911
240983
  registerAgentSourceCommands(agent);
@@ -240915,14 +240987,40 @@ function registerAgentCommands(program) {
240915
240987
  registerEnvCommands(agent);
240916
240988
  registerSecretsExportCommands(agent);
240917
240989
  }
240990
+ async function deleteAgent(agentRef, opts) {
240991
+ requireYesInNonInteractive(opts.yes, "delete agent");
240992
+ const automationId = agentAutomationId(agentRef);
240993
+ const client = buildClient2(opts);
240994
+ const automation = await fetchAutomation(client, automationId);
240995
+ if (automation.type != null && automation.type !== "agent") {
240996
+ throw new Error(`${automationId} is a workflow, not an agent. Use \`eigenpal workflow delete\` instead.`);
240997
+ }
240998
+ const confirmId = automationId;
240999
+ const label = automation.name ?? automation.slug ?? confirmId;
241000
+ warn(`This permanently deletes the agent "${label}", its versions, and builder sessions. Unified prior runs remain in run history. This cannot be undone.`);
241001
+ if (!opts.yes && isInteractiveStderr()) {
241002
+ await requireTypedConfirmation({
241003
+ id: confirmId,
241004
+ actionName: "delete agent",
241005
+ cancelledMessage: "Agent delete aborted"
241006
+ });
241007
+ }
241008
+ const result = await client.delete(`/v1/automations/${encodeURIComponent(automationId)}`);
241009
+ const parsed = parseAutomationDeleteResult(result);
241010
+ if (opts.json) {
241011
+ printJson2({ ...parsed, id: automationId, slug: automation.slug ?? null });
241012
+ return;
241013
+ }
241014
+ success(`Deleted agent ${ui.bold(label)} ${ui.dim(`(${automationId})`)}`);
241015
+ }
240918
241016
  async function listAgents(opts) {
240919
- const client = buildClient(opts);
241017
+ const client = buildClient2(opts);
240920
241018
  const payload = await client.get("/v1/automations", {
240921
241019
  ...compactParams(opts),
240922
241020
  type: "agent"
240923
241021
  });
240924
241022
  if (opts.json)
240925
- return printJson(payload);
241023
+ return printJson2(payload);
240926
241024
  console.log(table(payload.data, [
240927
241025
  { key: "slug", header: "SLUG" },
240928
241026
  { key: "name", header: "NAME" },
@@ -240944,7 +241042,7 @@ async function validateAgentCommand(dir = ".", opts) {
240944
241042
  }
240945
241043
  }
240946
241044
  if (opts.json) {
240947
- printJson(result);
241045
+ printJson2(result);
240948
241046
  if (!result.valid)
240949
241047
  process.exit(1);
240950
241048
  return;
@@ -241473,7 +241571,7 @@ function registerDocsCommands(program) {
241473
241571
  addJsonFlag(command.command("list [prefix]")).description("List bundled documentation topics, optionally under a path prefix.").option("--source <source>", "Filter by public, agent-reference, or api").action(action(async (prefix, opts) => {
241474
241572
  const results = listDocs(prefix, opts.source);
241475
241573
  if (opts.json) {
241476
- printJson(results.map(({ content: _content, ...doc }) => doc));
241574
+ printJson2(results.map(({ content: _content, ...doc }) => doc));
241477
241575
  return;
241478
241576
  }
241479
241577
  console.log(table(results, [
@@ -241485,7 +241583,7 @@ function registerDocsCommands(program) {
241485
241583
  addJsonFlag(command.command("search <query>")).description("Search every public page and detailed agent reference.").option("--limit <n>", "Maximum matches", intArg, 20).action(action(async (query, opts) => {
241486
241584
  const results = searchDocs(query, opts.limit);
241487
241585
  if (opts.json) {
241488
- printJson(results.map(({ content: _content, ...doc }) => doc));
241586
+ printJson2(results.map(({ content: _content, ...doc }) => doc));
241489
241587
  return;
241490
241588
  }
241491
241589
  console.log(table(results.map((doc) => ({ ...doc, match: doc.snippet || doc.description })), [
@@ -241497,7 +241595,7 @@ function registerDocsCommands(program) {
241497
241595
  addJsonFlag(command.command("read <topic>")).description("Print one bundled documentation topic to stdout.").action(action(async (topic, opts) => {
241498
241596
  const doc = resolveDoc(topic);
241499
241597
  if (opts.json) {
241500
- printJson(doc);
241598
+ printJson2(doc);
241501
241599
  return;
241502
241600
  }
241503
241601
  process.stdout.write(doc.content.endsWith(`
@@ -241865,12 +241963,12 @@ var LIST_COLUMNS = [
241865
241963
  format: (value) => formatTimestamp(value)
241866
241964
  }
241867
241965
  ];
241868
- function buildClient2(opts) {
241966
+ function buildClient3(opts) {
241869
241967
  const config = resolveConfig(opts);
241870
241968
  requireApiKey(config);
241871
241969
  return new ApiClient(config);
241872
241970
  }
241873
- function printJson2(value) {
241971
+ function printJson3(value) {
241874
241972
  console.log(JSON.stringify(value, null, 2));
241875
241973
  }
241876
241974
  function sharedCreateOptions(cmd) {
@@ -241902,7 +242000,7 @@ function registerEmailServersCommands(program) {
241902
242000
  const emailServers = program.command("email-servers").alias("email-server").description("Manage outbound email servers (ems_…): list, inspect, create, update, delete, and send a real test message.").addHelpText("after", EMAIL_SERVERS_EXAMPLES);
241903
242001
  const listCmd = emailServers.command("list").description("List outbound email servers for the current workspace.");
241904
242002
  addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
241905
- const client = buildClient2(opts);
242003
+ const client = buildClient3(opts);
241906
242004
  const raw = await client.get(apiPath("/email-servers"), {
241907
242005
  limit: String(opts.limit),
241908
242006
  offset: String(opts.offset)
@@ -241914,11 +242012,11 @@ function registerEmailServersCommands(program) {
241914
242012
  }));
241915
242013
  const getCmd = emailServers.command("get <id>").description("Inspect one email server. Human output is redacted even if the API regresses.");
241916
242014
  addJsonFlag(withBaseUrl(getCmd)).action(action(async (id, opts) => {
241917
- const client = buildClient2(opts);
242015
+ const client = buildClient3(opts);
241918
242016
  const raw = await client.get(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241919
242017
  const redacted = redactEmailServerPayload(raw);
241920
242018
  if (opts.json) {
241921
- printJson2(redacted);
242019
+ printJson3(redacted);
241922
242020
  return;
241923
242021
  }
241924
242022
  console.log(formatEmailServerHuman(redacted));
@@ -241926,11 +242024,11 @@ function registerEmailServersCommands(program) {
241926
242024
  const createCmd = emailServers.command("create").description("Create an outbound email server. Resend requires an API key; SMTP accepts optional username/password except with --security none, plus optional CA PEM, and defaults to starttls on port 587.");
241927
242025
  addJsonFlag(withBaseUrl(sharedCreateOptions(createCmd))).action(action(async (opts) => {
241928
242026
  const body = await buildCreateRequest(opts);
241929
- const client = buildClient2(opts);
242027
+ const client = buildClient3(opts);
241930
242028
  const created = await client.post(apiPath("/email-servers"), body);
241931
242029
  const redacted = redactEmailServerPayload(created);
241932
242030
  if (opts.json) {
241933
- printJson2(redacted);
242031
+ printJson3(redacted);
241934
242032
  return;
241935
242033
  }
241936
242034
  success(`Created ${ui.bold(redacted.id)} (${redacted.transport})`);
@@ -241938,13 +242036,13 @@ function registerEmailServersCommands(program) {
241938
242036
  }));
241939
242037
  const updateCmd = emailServers.command("update <id>").description("Update metadata or replace transport configuration. Omitted secrets are retained. Passing --transport smtp requires --host, --port, --security, --from-email, and --from-name (no security/port defaults). Metadata-only updates omit --transport.");
241940
242038
  addJsonFlag(withBaseUrl(sharedUpdateOptions(updateCmd))).action(action(async (id, opts) => {
241941
- const client = buildClient2(opts);
242039
+ const client = buildClient3(opts);
241942
242040
  const existing = await client.get(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241943
242041
  const body = await buildUpdateRequest({ existing, opts });
241944
242042
  const updated = await client.patch(apiPath(`/email-servers/${encodeURIComponent(id)}`), body);
241945
242043
  const redacted = redactEmailServerPayload(updated);
241946
242044
  if (opts.json) {
241947
- printJson2(redacted);
242045
+ printJson3(redacted);
241948
242046
  return;
241949
242047
  }
241950
242048
  success(`Updated ${ui.bold(redacted.id)}`);
@@ -241955,22 +242053,22 @@ function registerEmailServersCommands(program) {
241955
242053
  if (!opts.yes && !process.stdout.isTTY) {
241956
242054
  throw new Error("email-servers delete is destructive and requires --yes when run non-interactively");
241957
242055
  }
241958
- const client = buildClient2(opts);
242056
+ const client = buildClient3(opts);
241959
242057
  const result = await client.delete(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241960
242058
  if (opts.json) {
241961
- printJson2(result);
242059
+ printJson3(result);
241962
242060
  return;
241963
242061
  }
241964
242062
  success(`Deleted ${ui.bold(id)}`);
241965
242063
  }));
241966
242064
  const testCmd = emailServers.command("test <id>").description("Send a real connectivity test email through the stored server to --to. Disabled servers fail with a conflict.").requiredOption("--to <email>", "Recipient for the live test message");
241967
242065
  addJsonFlag(withBaseUrl(testCmd)).action(action(async (id, opts) => {
241968
- const client = buildClient2(opts);
242066
+ const client = buildClient3(opts);
241969
242067
  const result = await client.post(apiPath(`/email-servers/${encodeURIComponent(id)}/test`), {
241970
242068
  to: opts.to
241971
242069
  });
241972
242070
  if (opts.json) {
241973
- printJson2(result);
242071
+ printJson3(result);
241974
242072
  if (!result.ok)
241975
242073
  process.exit(1);
241976
242074
  return;
@@ -242173,56 +242271,8 @@ Examples:
242173
242271
  }));
242174
242272
  }
242175
242273
 
242176
- // src/commands/run.ts
242177
- init_src();
242178
-
242179
- // src/commands/run-form-data.ts
242274
+ // src/commands/reviews.ts
242180
242275
  import { promises as fs16 } from "node:fs";
242181
- import path18 from "node:path";
242182
-
242183
- // src/lib/upload-limits.ts
242184
- var DEFAULT_MULTIPART_MAX_BYTES = Math.floor(4.5 * 1024 * 1024);
242185
- var MULTIPART_ENVELOPE_HEADROOM_BYTES = 256 * 1024;
242186
- function multipartFileByteBudget(multipartMaxBytes = multipartMaxBytesFromEnv()) {
242187
- if (multipartMaxBytes === null)
242188
- return null;
242189
- return Math.max(0, multipartMaxBytes - MULTIPART_ENVELOPE_HEADROOM_BYTES);
242190
- }
242191
- function indicesRequiringPreUpload(files, multipartMaxBytes = multipartMaxBytesFromEnv()) {
242192
- const budget = multipartFileByteBudget(multipartMaxBytes);
242193
- const toPreUpload = new Set;
242194
- if (budget === null)
242195
- return toPreUpload;
242196
- files.forEach((file, index) => {
242197
- if (file.size > budget) {
242198
- toPreUpload.add(index);
242199
- }
242200
- });
242201
- let multipartTotal = 0;
242202
- files.forEach((file, index) => {
242203
- if (!toPreUpload.has(index))
242204
- multipartTotal += file.size;
242205
- });
242206
- const candidates = files.map((file, index) => ({ file, index })).filter(({ index }) => !toPreUpload.has(index)).slice().sort((a, b) => b.file.size - a.file.size || a.index - b.index);
242207
- for (const { file, index } of candidates) {
242208
- if (multipartTotal <= budget)
242209
- break;
242210
- toPreUpload.add(index);
242211
- multipartTotal -= file.size;
242212
- }
242213
- return toPreUpload;
242214
- }
242215
- function multipartMaxBytesFromEnv(raw = env.EIGENPAL_MULTIPART_MAX_BYTES) {
242216
- if (raw == null || raw.trim() === "")
242217
- return DEFAULT_MULTIPART_MAX_BYTES;
242218
- const normalized = raw.trim().toLowerCase();
242219
- if (normalized === "none" || normalized === "null" || normalized === "unlimited")
242220
- return null;
242221
- const parsed = Number(normalized);
242222
- if (Number.isSafeInteger(parsed) && parsed >= 0)
242223
- return parsed;
242224
- throw new Error("EIGENPAL_MULTIPART_MAX_BYTES must be a non-negative integer or one of: none, null, unlimited.");
242225
- }
242226
242276
 
242227
242277
  // src/lib/upload-reusable-file.ts
242228
242278
  import { randomUUID } from "node:crypto";
@@ -242604,6 +242654,306 @@ async function readWholeFile(filePath) {
242604
242654
  return readFile(filePath);
242605
242655
  }
242606
242656
 
242657
+ // src/lib/reviews-cli.ts
242658
+ var REVIEW_LIST_COLUMNS = [
242659
+ { key: "id", header: "ID" },
242660
+ { key: "status", header: "STATUS" },
242661
+ {
242662
+ key: "confirmedCount",
242663
+ header: "CONFIRMED",
242664
+ format: (_value, row) => `${row.confirmedCount}/${row.requiredCount}`
242665
+ },
242666
+ { key: "automationName", header: "AUTOMATION" },
242667
+ { key: "sourceLabel", header: "SOURCE" },
242668
+ { key: "executionId", header: "RUN" },
242669
+ { key: "version", header: "VER" },
242670
+ { key: "createdAt", header: "CREATED", format: formatTimestamp }
242671
+ ];
242672
+ var REVIEW_DECISION_COLUMNS = [
242673
+ { key: "path", header: "PATH" },
242674
+ {
242675
+ key: "required",
242676
+ header: "REQ",
242677
+ format: (value) => value ? "yes" : "no"
242678
+ },
242679
+ {
242680
+ key: "currentValue",
242681
+ header: "VALUE",
242682
+ format: (value) => formatScalarForDisplay(value)
242683
+ },
242684
+ { key: "confirmed", header: "CONFIRMED" },
242685
+ { key: "reason", header: "REASON" }
242686
+ ];
242687
+ function buildReviewListParams(opts) {
242688
+ const params = {};
242689
+ if (opts.automationId)
242690
+ params.automationId = opts.automationId;
242691
+ if (opts.waitingBefore)
242692
+ params.waitingBefore = opts.waitingBefore;
242693
+ if (opts.cursor)
242694
+ params.cursor = opts.cursor;
242695
+ if (opts.limit != null)
242696
+ params.limit = String(opts.limit);
242697
+ return params;
242698
+ }
242699
+ function parseReviewScalarValue(raw) {
242700
+ const trimmed = raw.trim();
242701
+ if (trimmed === "null")
242702
+ return null;
242703
+ if (trimmed === "true")
242704
+ return true;
242705
+ if (trimmed === "false")
242706
+ return false;
242707
+ if (/^-?\d+(?:\.\d+)?$/.test(trimmed)) {
242708
+ const asNumber = Number(trimmed);
242709
+ if (Number.isFinite(asNumber))
242710
+ return asNumber;
242711
+ }
242712
+ return raw;
242713
+ }
242714
+ function parseReviewJsonScalar(value) {
242715
+ if (value === null)
242716
+ return null;
242717
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
242718
+ return value;
242719
+ }
242720
+ throw new Error("Review field values must be scalar JSON: string, number, boolean, or null.");
242721
+ }
242722
+ function resolveReviewIdempotencyKey(explicit) {
242723
+ const key = explicit?.trim();
242724
+ if (key)
242725
+ return key;
242726
+ return newIdempotencyKey();
242727
+ }
242728
+ function formatScalarForDisplay(value) {
242729
+ if (value === null)
242730
+ return "null";
242731
+ if (typeof value === "string")
242732
+ return value;
242733
+ return JSON.stringify(value);
242734
+ }
242735
+ function decisionRows(task) {
242736
+ return (task.decisions ?? []).map((decision) => ({
242737
+ path: decision.path,
242738
+ required: decision.required,
242739
+ currentValue: decision.currentValue,
242740
+ confirmed: decision.confirmedAt ? "yes" : "no",
242741
+ reason: decision.reason
242742
+ }));
242743
+ }
242744
+ function formatReviewTaskSummary(task) {
242745
+ return [
242746
+ `ID ${task.id}`,
242747
+ `Status ${task.status}`,
242748
+ `Automation ${task.automationName} (${task.automationId})`,
242749
+ `Run ${task.executionId}`,
242750
+ `Source ${task.sourceKind} · ${task.sourceLabel}`,
242751
+ `Progress ${task.confirmedCount}/${task.requiredCount} confirmed · version ${task.version}`,
242752
+ `Created ${formatTimestamp(task.createdAt)}`,
242753
+ `Updated ${formatTimestamp(task.updatedAt)}`
242754
+ ].join(`
242755
+ `);
242756
+ }
242757
+ function formatReviewTaskDetail(task) {
242758
+ const lines = [formatReviewTaskSummary(task)];
242759
+ if (task.instructions) {
242760
+ lines.push("", "Instructions", task.instructions);
242761
+ }
242762
+ if (task.files?.length) {
242763
+ lines.push("", "Files");
242764
+ for (const file of task.files) {
242765
+ lines.push(` ${file.fileId} ${file.filename}${file.fieldName ? ` (${file.fieldName})` : ""}`);
242766
+ }
242767
+ }
242768
+ return lines.join(`
242769
+ `);
242770
+ }
242771
+
242772
+ // src/commands/reviews.ts
242773
+ function buildClient4(opts) {
242774
+ const config = resolveConfig(opts);
242775
+ requireApiKey(config);
242776
+ return new ApiClient(config);
242777
+ }
242778
+ function printJson4(value) {
242779
+ console.log(JSON.stringify(value, null, 2));
242780
+ }
242781
+ function taskPath(taskId, suffix = "") {
242782
+ return apiPath(`/human-reviews/${encodeURIComponent(taskId)}${suffix}`);
242783
+ }
242784
+ function renderTaskResult(task, json) {
242785
+ if (json) {
242786
+ printJson4({ task });
242787
+ return;
242788
+ }
242789
+ console.log(formatReviewTaskDetail(task));
242790
+ const rows = decisionRows(task);
242791
+ if (rows.length > 0) {
242792
+ console.log("");
242793
+ console.log(table(rows, REVIEW_DECISION_COLUMNS));
242794
+ }
242795
+ }
242796
+ var REVIEWS_EXAMPLES = `
242797
+ Examples:
242798
+ $ eigenpal reviews list
242799
+ $ eigenpal reviews list --automation-id auto_... --limit 20 --json
242800
+ $ eigenpal reviews get hrt_...
242801
+ $ eigenpal reviews confirm hrt_... --path /vendor --value "Acme" --expected-version 3
242802
+ $ eigenpal reviews confirm hrt_... --path /total --value 42 --expected-version 3 --withdraw
242803
+ $ eigenpal reviews approve hrt_... --expected-version 3
242804
+ $ eigenpal reviews reject hrt_... --reason "Missing PO number" --expected-version 3
242805
+ $ eigenpal reviews download hrt_... file_... --out invoice.pdf
242806
+
242807
+ Notes:
242808
+ Tasks are created by workflow human-review steps and finish through approve or reject.
242809
+ Use \`eigenpal runs cancel <run-id>\` to abort a paused run without approving review.
242810
+ Post-run eval corrections live under \`eigenpal runs reviews\`, not here.
242811
+ `;
242812
+ function registerReviewsCommands(program) {
242813
+ const reviews = program.command("reviews").description("Work the live human-review queue for paused runs: list pending tasks, confirm fields, approve, reject, and download attachments.").addHelpText("after", REVIEWS_EXAMPLES).action(() => {
242814
+ process.stderr.write("`eigenpal reviews` requires a subcommand. Run `eigenpal reviews --help`.\n");
242815
+ process.exit(2);
242816
+ });
242817
+ addJsonFlag(withBaseUrl(reviews.command("list").alias("ls").description("List pending human-review tasks (oldest first, cursor-paginated).").option("--automation-id <id>", "Filter to one automation id").option("--waiting-before <iso>", "Only tasks created before this ISO timestamp (queue age filter)").option("--cursor <token>", "Pagination cursor from a previous list response").option("--limit <n>", "Page size (1–100)", intArg, 50))).action(action(listReviews));
242818
+ addJsonFlag(withBaseUrl(reviews.command("get <task-id>").description("Get one human-review task with its field decisions and attached files."))).action(action(getReview));
242819
+ addJsonFlag(withBaseUrl(reviews.command("confirm <task-id>").description("Confirm or edit one scalar review field. Use --withdraw to persist a draft edit without confirming.").requiredOption("--path <json-pointer>", "Field JSON pointer (for example /vendor or /items/0/name)").option("--value <scalar>", "Scalar value: string, number, true, false, or null").option("--value-json <json>", "Scalar JSON literal (alternative to --value)").requiredOption("--expected-version <n>", "Optimistic concurrency version from get/list", intArg).option("--idempotency-key <key>", "Durable idempotency key (auto-generated when omitted)").option("--withdraw", "Persist the edit without confirming (confirmed=false)"))).action(action(confirmReviewField));
242820
+ addJsonFlag(withBaseUrl(reviews.command("approve <task-id>").description("Approve a review task after all required fields are confirmed.").requiredOption("--expected-version <n>", "Optimistic concurrency version from get/list", intArg))).action(action(approveReview));
242821
+ addJsonFlag(withBaseUrl(reviews.command("reject <task-id>").description("Reject a review task and fail the paused run with a reason.").requiredOption("--reason <text>", "Human-readable rejection reason").requiredOption("--expected-version <n>", "Optimistic concurrency version from get/list", intArg).option("--idempotency-key <key>", "Durable idempotency key (auto-generated when omitted)"))).action(action(rejectReview));
242822
+ withBaseUrl(reviews.command("download <task-id> <file-id>").description("Download one file attached to a review task.").requiredOption("--out <path>", "Write bytes to this file path")).action(action(downloadReviewFile));
242823
+ }
242824
+ async function listReviews(opts) {
242825
+ const client = buildClient4(opts);
242826
+ const payload = await client.get(apiPath("/human-reviews"), buildReviewListParams(opts));
242827
+ if (opts.json) {
242828
+ printJson4(payload);
242829
+ writeListHint(payload);
242830
+ return;
242831
+ }
242832
+ console.log(table(payload.tasks ?? [], REVIEW_LIST_COLUMNS));
242833
+ writeListHint(payload);
242834
+ }
242835
+ function writeListHint(payload) {
242836
+ const count = payload.tasks?.length ?? 0;
242837
+ if (count === 0)
242838
+ return;
242839
+ const cursorHint = payload.nextCursor ? ` · next page: --cursor ${payload.nextCursor}` : "";
242840
+ process.stderr.write(dim(`${count} pending task${count === 1 ? "" : "s"}${cursorHint} · use --json for machine-readable output`) + `
242841
+ `);
242842
+ }
242843
+ async function getReview(taskId, opts) {
242844
+ const client = buildClient4(opts);
242845
+ const payload = await client.get(taskPath(taskId));
242846
+ renderTaskResult(payload.task, opts.json);
242847
+ }
242848
+ async function confirmReviewField(taskId, opts) {
242849
+ if (opts.value !== undefined && opts.valueJson !== undefined) {
242850
+ throw new Error("Pass only one of --value or --value-json.");
242851
+ }
242852
+ const rawValue = opts.valueJson ?? opts.value;
242853
+ if (rawValue === undefined) {
242854
+ throw new Error("Missing field value. Pass --value <scalar> or --value-json <json>.");
242855
+ }
242856
+ const value = opts.valueJson !== undefined ? parseReviewJsonScalar(JSON.parse(opts.valueJson)) : parseReviewScalarValue(rawValue);
242857
+ const client = buildClient4(opts);
242858
+ const payload = await client.put(taskPath(taskId, "/fields"), {
242859
+ path: opts.path,
242860
+ value,
242861
+ expectedVersion: opts.expectedVersion,
242862
+ idempotencyKey: resolveReviewIdempotencyKey(opts.idempotencyKey),
242863
+ confirmed: opts.withdraw ? false : true
242864
+ });
242865
+ if (opts.json) {
242866
+ printJson4(payload);
242867
+ return;
242868
+ }
242869
+ success(`Updated ${ui.bold(payload.task.id)} (${payload.task.confirmedCount}/${payload.task.requiredCount} confirmed)`);
242870
+ console.log(formatReviewTaskSummary(payload.task));
242871
+ }
242872
+ async function approveReview(taskId, opts) {
242873
+ const client = buildClient4(opts);
242874
+ const payload = await client.post(taskPath(taskId, "/approve"), {
242875
+ expectedVersion: opts.expectedVersion
242876
+ });
242877
+ if (opts.json) {
242878
+ printJson4(payload);
242879
+ return;
242880
+ }
242881
+ success(`Approved ${ui.bold(payload.task.id)} · run ${payload.task.executionId} resumed`);
242882
+ console.log(formatReviewTaskSummary(payload.task));
242883
+ }
242884
+ async function rejectReview(taskId, opts) {
242885
+ const client = buildClient4(opts);
242886
+ const payload = await client.post(taskPath(taskId, "/reject"), {
242887
+ reason: opts.reason,
242888
+ expectedVersion: opts.expectedVersion,
242889
+ idempotencyKey: resolveReviewIdempotencyKey(opts.idempotencyKey)
242890
+ });
242891
+ if (opts.json) {
242892
+ printJson4(payload);
242893
+ return;
242894
+ }
242895
+ success(`Rejected ${ui.bold(payload.task.id)} · run ${payload.task.executionId} failed`);
242896
+ console.log(formatReviewTaskSummary(payload.task));
242897
+ }
242898
+ async function downloadReviewFile(taskId, fileId, opts) {
242899
+ const client = buildClient4(opts);
242900
+ const res = await client.getStream(taskPath(taskId, `/files/${encodeURIComponent(fileId)}/content`));
242901
+ const buf = Buffer.from(await res.arrayBuffer());
242902
+ await fs16.writeFile(opts.out, buf);
242903
+ success(`Wrote ${ui.bold(opts.out)} ${ui.dim(`(${buf.byteLength} bytes)`)}`);
242904
+ }
242905
+
242906
+ // src/commands/run.ts
242907
+ init_src();
242908
+
242909
+ // src/commands/run-form-data.ts
242910
+ import { promises as fs17 } from "node:fs";
242911
+ import path18 from "node:path";
242912
+
242913
+ // src/lib/upload-limits.ts
242914
+ var DEFAULT_MULTIPART_MAX_BYTES = Math.floor(4.5 * 1024 * 1024);
242915
+ var MULTIPART_ENVELOPE_HEADROOM_BYTES = 256 * 1024;
242916
+ function multipartFileByteBudget(multipartMaxBytes = multipartMaxBytesFromEnv()) {
242917
+ if (multipartMaxBytes === null)
242918
+ return null;
242919
+ return Math.max(0, multipartMaxBytes - MULTIPART_ENVELOPE_HEADROOM_BYTES);
242920
+ }
242921
+ function indicesRequiringPreUpload(files, multipartMaxBytes = multipartMaxBytesFromEnv()) {
242922
+ const budget = multipartFileByteBudget(multipartMaxBytes);
242923
+ const toPreUpload = new Set;
242924
+ if (budget === null)
242925
+ return toPreUpload;
242926
+ files.forEach((file, index) => {
242927
+ if (file.size > budget) {
242928
+ toPreUpload.add(index);
242929
+ }
242930
+ });
242931
+ let multipartTotal = 0;
242932
+ files.forEach((file, index) => {
242933
+ if (!toPreUpload.has(index))
242934
+ multipartTotal += file.size;
242935
+ });
242936
+ const candidates = files.map((file, index) => ({ file, index })).filter(({ index }) => !toPreUpload.has(index)).slice().sort((a, b) => b.file.size - a.file.size || a.index - b.index);
242937
+ for (const { file, index } of candidates) {
242938
+ if (multipartTotal <= budget)
242939
+ break;
242940
+ toPreUpload.add(index);
242941
+ multipartTotal -= file.size;
242942
+ }
242943
+ return toPreUpload;
242944
+ }
242945
+ function multipartMaxBytesFromEnv(raw = env.EIGENPAL_MULTIPART_MAX_BYTES) {
242946
+ if (raw == null || raw.trim() === "")
242947
+ return DEFAULT_MULTIPART_MAX_BYTES;
242948
+ const normalized = raw.trim().toLowerCase();
242949
+ if (normalized === "none" || normalized === "null" || normalized === "unlimited")
242950
+ return null;
242951
+ const parsed = Number(normalized);
242952
+ if (Number.isSafeInteger(parsed) && parsed >= 0)
242953
+ return parsed;
242954
+ throw new Error("EIGENPAL_MULTIPART_MAX_BYTES must be a non-negative integer or one of: none, null, unlimited.");
242955
+ }
242956
+
242607
242957
  // src/commands/run-form-data.ts
242608
242958
  var RESERVED_FIELD_NAMES = new Set([
242609
242959
  "_json",
@@ -242620,7 +242970,7 @@ async function buildPreparedRunRequest(client, input) {
242620
242970
  };
242621
242971
  const localFiles = [];
242622
242972
  for (const spec of parseInputFileSpecs(input.inputFile ?? [])) {
242623
- const info = await fs16.stat(spec.filePath);
242973
+ const info = await fs17.stat(spec.filePath);
242624
242974
  if (!info.isFile()) {
242625
242975
  throw new Error(`--input-file path is not a file: ${spec.filePath}`);
242626
242976
  }
@@ -242679,7 +243029,7 @@ async function buildPreparedRunRequest(client, input) {
242679
243029
  if (input.metadata)
242680
243030
  form.append("metadata", JSON.stringify(input.metadata));
242681
243031
  for (const file of remaining) {
242682
- const content = file.content ?? (file.filePath ? await fs16.readFile(file.filePath) : Buffer.alloc(0));
243032
+ const content = file.content ?? (file.filePath ? await fs17.readFile(file.filePath) : Buffer.alloc(0));
242683
243033
  appendFilePart(form, file.fieldName, content, file.filename, file.mimeType);
242684
243034
  }
242685
243035
  return { form, hasMultipartFiles: remaining.length > 0 };
@@ -242850,7 +243200,7 @@ async function runTarget(target, opts) {
242850
243200
  failOnMismatch: opts.failOnMismatch
242851
243201
  });
242852
243202
  }
242853
- const client = buildClient(opts);
243203
+ const client = buildClient2(opts);
242854
243204
  let payload;
242855
243205
  const runPath = runTargetApiPath(target);
242856
243206
  const pathTarget = runStartMultipartTarget(target);
@@ -244155,12 +244505,12 @@ function looksLikeFreeform(prop) {
244155
244505
  return prop.pattern !== undefined || prop.format !== undefined;
244156
244506
  }
244157
244507
  // src/commands/workflow/index.ts
244158
- import { existsSync as existsSync23, promises as fs20 } from "node:fs";
244508
+ import { existsSync as existsSync23, promises as fs21 } from "node:fs";
244159
244509
  import path19 from "node:path";
244160
244510
 
244161
244511
  // src/lib/local-templates.ts
244162
244512
  init_src();
244163
- import { existsSync as existsSync18, promises as fs17, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
244513
+ import { existsSync as existsSync18, promises as fs18, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
244164
244514
  import { basename, dirname as dirname6, isAbsolute, relative as relative4, resolve as resolve8, sep } from "node:path";
244165
244515
 
244166
244516
  // src/lib/office-template.ts
@@ -244464,7 +244814,7 @@ async function loadLocalTemplatesForPush(workflowFile, parsedSteps, opts = {}) {
244464
244814
  continue;
244465
244815
  }
244466
244816
  const absolutePath = resolveWorkflowTemplatePath(workflowFile, ref.templatePath, opts);
244467
- const bytes = await fs17.readFile(absolutePath);
244817
+ const bytes = await fs18.readFile(absolutePath);
244468
244818
  inspectOfficeTemplateBytes(bytes, basename(absolutePath));
244469
244819
  const row = {
244470
244820
  path: ref.templatePath,
@@ -244729,7 +245079,7 @@ async function clearEvalOutputs(dir, exampleNames = [], options = {}) {
244729
245079
 
244730
245080
  // src/commands/workflow/evaluator-type.ts
244731
245081
  init_src();
244732
- import { promises as fs18 } from "node:fs";
245082
+ import { promises as fs19 } from "node:fs";
244733
245083
  var EVALUATOR_REGISTRY = {
244734
245084
  "exact-diff": {
244735
245085
  type: "exact-diff",
@@ -244793,7 +245143,7 @@ function registerEvaluatorTypeCommands(parent) {
244793
245143
  };
244794
245144
  const text = JSON.stringify(result, null, 2);
244795
245145
  if (opts.out) {
244796
- await fs18.writeFile(opts.out, text);
245146
+ await fs19.writeFile(opts.out, text);
244797
245147
  process.stderr.write(`${ui.ok("✓")} Wrote ${ui.bold(opts.out)}
244798
245148
  `);
244799
245149
  } else {
@@ -244802,6 +245152,267 @@ function registerEvaluatorTypeCommands(parent) {
244802
245152
  });
244803
245153
  }
244804
245154
 
245155
+ // src/lib/workflow-folders.ts
245156
+ function assertWorkflowFolder(folder, ref) {
245157
+ if (folder.type !== "workflow") {
245158
+ throw new Error(`Folder is not a workflow folder: ${ref}`);
245159
+ }
245160
+ return folder;
245161
+ }
245162
+ function findSiblingFolder(folders, parentId, segment) {
245163
+ const decoded = safeDecode2(segment);
245164
+ return folders.find((f) => f.parentId === parentId && (f.name === segment || f.name === decoded || encodeURIComponent(f.name) === segment));
245165
+ }
245166
+ var FOLDER_ID_PREFIX = "fldr_";
245167
+ function looksLikeFolderId(value) {
245168
+ return value.startsWith(FOLDER_ID_PREFIX);
245169
+ }
245170
+ function normalizeFolderPathInput(path) {
245171
+ const trimmed = path.trim();
245172
+ if (trimmed === "/" || trimmed === "")
245173
+ return "/";
245174
+ return trimmed.replace(/^\/+|\/+$/g, "");
245175
+ }
245176
+ function folderPathSegments(path) {
245177
+ const normalized = normalizeFolderPathInput(path);
245178
+ if (normalized === "/")
245179
+ return [];
245180
+ return normalized.split("/").filter(Boolean);
245181
+ }
245182
+ function safeDecode2(segment) {
245183
+ try {
245184
+ return decodeURIComponent(segment);
245185
+ } catch {
245186
+ return segment;
245187
+ }
245188
+ }
245189
+ function resolveFolderPathToId(folders, path) {
245190
+ const segments = folderPathSegments(path);
245191
+ if (segments.length === 0)
245192
+ return null;
245193
+ let parentId = null;
245194
+ for (const segment of segments) {
245195
+ const decoded = safeDecode2(segment);
245196
+ const folder = folders.find((f) => f.parentId === parentId && (f.name === segment || f.name === decoded || encodeURIComponent(f.name) === segment));
245197
+ if (!folder)
245198
+ return null;
245199
+ parentId = folder.id;
245200
+ }
245201
+ return parentId;
245202
+ }
245203
+ function folderIdToPath(folders, folderId) {
245204
+ if (!folderId)
245205
+ return "/";
245206
+ const byId = new Map(folders.map((f) => [f.id, f]));
245207
+ const segments = [];
245208
+ let current = folderId;
245209
+ while (current) {
245210
+ const folder = byId.get(current);
245211
+ if (!folder)
245212
+ break;
245213
+ segments.unshift(folder.name);
245214
+ current = folder.parentId;
245215
+ }
245216
+ return segments.length > 0 ? segments.join("/") : "/";
245217
+ }
245218
+ function buildFolderTree(folders) {
245219
+ const nodes = new Map;
245220
+ for (const folder of folders) {
245221
+ nodes.set(folder.id, { folder, children: [] });
245222
+ }
245223
+ const roots = [];
245224
+ for (const folder of folders) {
245225
+ const node = nodes.get(folder.id);
245226
+ if (folder.parentId && nodes.has(folder.parentId)) {
245227
+ nodes.get(folder.parentId).children.push(node);
245228
+ } else {
245229
+ roots.push(node);
245230
+ }
245231
+ }
245232
+ const sortNodes = (list) => {
245233
+ list.sort((a, b) => a.folder.name.localeCompare(b.folder.name));
245234
+ for (const node of list)
245235
+ sortNodes(node.children);
245236
+ };
245237
+ sortNodes(roots);
245238
+ return roots;
245239
+ }
245240
+ function renderFolderTreeLines(nodes, indent = "") {
245241
+ const lines = [];
245242
+ for (let i = 0;i < nodes.length; i++) {
245243
+ const node = nodes[i];
245244
+ const branch = i === nodes.length - 1 ? "└── " : "├── ";
245245
+ const childIndent = indent + (i === nodes.length - 1 ? " " : "│ ");
245246
+ const counts = [];
245247
+ if (node.folder.workflowCount != null && node.folder.workflowCount > 0) {
245248
+ counts.push(`${node.folder.workflowCount} workflow${node.folder.workflowCount === 1 ? "" : "s"}`);
245249
+ }
245250
+ if (node.folder.childCount != null && node.folder.childCount > 0) {
245251
+ counts.push(`${node.folder.childCount} subfolder${node.folder.childCount === 1 ? "" : "s"}`);
245252
+ }
245253
+ const suffix = counts.length > 0 ? ` ${counts.join(", ")}` : "";
245254
+ lines.push(`${indent}${branch}${node.folder.name} (${node.folder.id})${suffix}`);
245255
+ lines.push(...renderFolderTreeLines(node.children, childIndent));
245256
+ }
245257
+ return lines;
245258
+ }
245259
+ async function fetchWorkflowFolders(client, opts = {}) {
245260
+ const params = { type: "workflow" };
245261
+ if (opts.tree)
245262
+ params.tree = "true";
245263
+ const raw = await client.get("/v1/folders", params);
245264
+ if (Array.isArray(raw))
245265
+ return raw;
245266
+ if (raw && typeof raw === "object" && Array.isArray(raw.data)) {
245267
+ return raw.data;
245268
+ }
245269
+ return [];
245270
+ }
245271
+ async function resolveWorkflowFolderRef(client, pathOrId) {
245272
+ const trimmed = pathOrId.trim();
245273
+ if (looksLikeFolderId(trimmed)) {
245274
+ const folder = assertWorkflowFolder(await client.get(`/v1/folders/${encodeURIComponent(trimmed)}`), trimmed);
245275
+ return folder;
245276
+ }
245277
+ const folders = await fetchWorkflowFolders(client, { tree: true });
245278
+ const folderId = resolveFolderPathToId(folders, trimmed);
245279
+ if (!folderId) {
245280
+ throw new Error(`Folder not found: ${trimmed}`);
245281
+ }
245282
+ const match = folders.find((f) => f.id === folderId);
245283
+ if (!match)
245284
+ throw new Error(`Folder not found: ${trimmed}`);
245285
+ return match;
245286
+ }
245287
+ async function ensureFolderPath(client, path) {
245288
+ const segments = folderPathSegments(path);
245289
+ if (segments.length === 0)
245290
+ return null;
245291
+ let folders = await fetchWorkflowFolders(client, { tree: true });
245292
+ let parentId = null;
245293
+ for (const segment of segments) {
245294
+ const decoded = safeDecode2(segment);
245295
+ let folder = findSiblingFolder(folders, parentId, segment);
245296
+ if (!folder) {
245297
+ try {
245298
+ folder = await client.post("/v1/folders", {
245299
+ name: decoded,
245300
+ parentId,
245301
+ type: "workflow"
245302
+ });
245303
+ folders = [...folders, folder];
245304
+ } catch (err) {
245305
+ if (!(err instanceof ApiError) || err.status !== 409)
245306
+ throw err;
245307
+ folders = await fetchWorkflowFolders(client, { tree: true });
245308
+ folder = findSiblingFolder(folders, parentId, segment);
245309
+ if (!folder)
245310
+ throw err;
245311
+ }
245312
+ }
245313
+ parentId = folder.id;
245314
+ }
245315
+ return parentId;
245316
+ }
245317
+
245318
+ // src/commands/workflow/folders.ts
245319
+ function registerWorkflowFolderCommands(parent) {
245320
+ const folders = parent.command("folders").description("Manage workflow folders (organize workflows in Studio).").action(() => {
245321
+ process.stderr.write("`eigenpal workflow folders` requires a subcommand. Run `eigenpal workflow folders --help`.\n");
245322
+ process.exit(2);
245323
+ });
245324
+ addJsonFlag(withBaseUrl(folders.command("list"))).description("List workflow folders.").option("--tree", "Render folders as an indented tree").action(action(listWorkflowFolders));
245325
+ addJsonFlag(withBaseUrl(folders.command("create <path>"))).description("Create a folder path, creating any missing parent segments.").action(action(createWorkflowFolder));
245326
+ addJsonFlag(withBaseUrl(folders.command("rename <path-or-id>"))).description("Rename a workflow folder.").requiredOption("--name <name>", "New folder name").action(action(renameWorkflowFolder));
245327
+ addJsonFlag(withBaseUrl(folders.command("delete <path-or-id>"))).description("Delete a workflow folder.").option("--yes", "Skip typed-id confirmation (required in CI / agent terminals without a TTY)").addHelpText("after", `
245328
+ Deleting a folder removes its subfolders. Workflows inside are moved to the
245329
+ root ("All workflows"), not deleted. This matches Studio folder deletion.
245330
+ `).action(action(deleteWorkflowFolder));
245331
+ }
245332
+ async function listWorkflowFolders(opts) {
245333
+ const client = buildClient(opts);
245334
+ const rows = await fetchWorkflowFolders(client, { tree: true });
245335
+ if (opts.json) {
245336
+ printJson({ data: rows, total: rows.length });
245337
+ return;
245338
+ }
245339
+ if (opts.tree) {
245340
+ const tree = buildFolderTree(rows);
245341
+ const lines = renderFolderTreeLines(tree);
245342
+ if (lines.length === 0) {
245343
+ dim("No workflow folders yet.");
245344
+ return;
245345
+ }
245346
+ console.log(lines.join(`
245347
+ `));
245348
+ dim(`${rows.length} folder${rows.length === 1 ? "" : "s"} · use --json for the raw payload`);
245349
+ return;
245350
+ }
245351
+ console.log(table(rows, [
245352
+ { key: "id", header: "ID" },
245353
+ {
245354
+ key: "name",
245355
+ header: "NAME",
245356
+ format: (_v, row) => folderIdToPath(rows, row.id)
245357
+ },
245358
+ { key: "workflowCount", header: "WORKFLOWS", format: (v) => String(v ?? 0) },
245359
+ { key: "childCount", header: "SUBFOLDERS", format: (v) => String(v ?? 0) }
245360
+ ]));
245361
+ dim(`${rows.length} folder${rows.length === 1 ? "" : "s"} · use --tree for hierarchy`);
245362
+ }
245363
+ async function createWorkflowFolder(path, opts) {
245364
+ const client = buildClient(opts);
245365
+ const normalized = normalizeFolderPathInput(path);
245366
+ if (normalized === "/") {
245367
+ throw new Error("Cannot create the root folder. Omit the path or choose a name.");
245368
+ }
245369
+ const segments = folderPathSegments(path);
245370
+ if (segments.length === 0) {
245371
+ throw new Error("Folder path is required (for example billing/invoices).");
245372
+ }
245373
+ const folderId = await ensureFolderPath(client, path);
245374
+ const folders = await fetchWorkflowFolders(client, { tree: true });
245375
+ const folder = folders.find((f) => f.id === folderId);
245376
+ if (opts.json) {
245377
+ printJson(folder ?? { id: folderId, path: normalized });
245378
+ return;
245379
+ }
245380
+ success(`Created folder ${ui.bold(normalized)} ${ui.dim(`(${folderId})`)}`);
245381
+ }
245382
+ async function renameWorkflowFolder(pathOrId, opts) {
245383
+ const client = buildClient(opts);
245384
+ const folder = await resolveWorkflowFolderRef(client, pathOrId);
245385
+ const result = await client.patch(`/v1/folders/${encodeURIComponent(folder.id)}`, {
245386
+ name: opts.name.trim()
245387
+ });
245388
+ if (opts.json) {
245389
+ printJson(result);
245390
+ return;
245391
+ }
245392
+ success(`Renamed folder ${ui.bold(folder.name)} → ${ui.bold(result.name ?? opts.name)}`);
245393
+ }
245394
+ async function deleteWorkflowFolder(pathOrId, opts) {
245395
+ requireYesInNonInteractive(opts.yes, "delete workflow folder");
245396
+ const client = buildClient(opts);
245397
+ const folder = await resolveWorkflowFolderRef(client, pathOrId);
245398
+ const folders = await fetchWorkflowFolders(client, { tree: true });
245399
+ const pathLabel = folderIdToPath(folders, folder.id);
245400
+ warn("Deleting this folder removes its subfolders. Workflows inside move to the root; they are not deleted.");
245401
+ if (!opts.yes && isInteractiveStderr()) {
245402
+ await requireTypedConfirmation({
245403
+ id: folder.id,
245404
+ actionName: `delete folder "${pathLabel}"`,
245405
+ cancelledMessage: "Folder delete aborted"
245406
+ });
245407
+ }
245408
+ await client.delete(`/v1/folders/${encodeURIComponent(folder.id)}`);
245409
+ if (opts.json) {
245410
+ printJson({ deleted: true, id: folder.id, path: pathLabel });
245411
+ return;
245412
+ }
245413
+ success(`Deleted folder ${ui.bold(pathLabel)}`);
245414
+ }
245415
+
244805
245416
  // src/commands/workflow/step-exec.ts
244806
245417
  init_src();
244807
245418
  var UNSUPPORTED_TYPE_EXIT = 2;
@@ -244830,20 +245441,20 @@ function registerStepExecCommands(workflow) {
244830
245441
 
244831
245442
  // src/commands/workflow/templates.ts
244832
245443
  init_src();
244833
- import { existsSync as existsSync20, promises as fs19 } from "node:fs";
245444
+ import { existsSync as existsSync20, promises as fs20 } from "node:fs";
244834
245445
  import { basename as basename3, resolve as resolve9 } from "node:path";
244835
- function buildClient3(opts) {
245446
+ function buildClient5(opts) {
244836
245447
  const config = resolveConfig(opts);
244837
245448
  requireApiKey(config);
244838
245449
  return new ApiClient(config);
244839
245450
  }
244840
- function printJson3(value) {
245451
+ function printJson5(value) {
244841
245452
  console.log(JSON.stringify(value, null, 2));
244842
245453
  }
244843
245454
  async function readJsonFixtureFile(fixturePath) {
244844
245455
  let raw;
244845
245456
  try {
244846
- raw = await fs19.readFile(resolve9(fixturePath), "utf8");
245457
+ raw = await fs20.readFile(resolve9(fixturePath), "utf8");
244847
245458
  } catch (err) {
244848
245459
  const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
244849
245460
  if (code === "ENOENT") {
@@ -244895,8 +245506,8 @@ function registerTemplateCommands(parent) {
244895
245506
  const uploadCmd = templates.command("upload <file>").description("Upload a DOCX or XLSX file as a new tmpl_… resource with an immutable tmpr_… revision.").option("--name <name>", "Display name (defaults to the filename without extension)").option("--description <text>", "Optional description");
244896
245507
  addJsonFlag(withBaseUrl(uploadCmd)).action(action(async (file, opts) => {
244897
245508
  const filePath = resolve9(file);
244898
- const bytes = await fs19.readFile(filePath);
244899
- const client = buildClient3(opts);
245509
+ const bytes = await fs20.readFile(filePath);
245510
+ const client = buildClient5(opts);
244900
245511
  const template = await uploadWorkspaceTemplate(client, {
244901
245512
  bytes,
244902
245513
  filename: basename3(filePath),
@@ -244904,7 +245515,7 @@ function registerTemplateCommands(parent) {
244904
245515
  description: opts.description
244905
245516
  });
244906
245517
  if (opts.json) {
244907
- printJson3(template);
245518
+ printJson5(template);
244908
245519
  return;
244909
245520
  }
244910
245521
  success(`Uploaded ${ui.bold(template.id)} revision ${ui.bold(template.currentRevision?.id ?? "-")} (${template.format})`);
@@ -244912,10 +245523,10 @@ function registerTemplateCommands(parent) {
244912
245523
  }));
244913
245524
  const listCmd = templates.command("list").description("List workspace templates.");
244914
245525
  addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
244915
- const client = buildClient3(opts);
245526
+ const client = buildClient5(opts);
244916
245527
  const result = await listPublicTemplates(client, { limit: opts.limit, offset: opts.offset });
244917
245528
  if (opts.json) {
244918
- printJson3(result);
245529
+ printJson5(result);
244919
245530
  return;
244920
245531
  }
244921
245532
  console.log(table(result.items.map((row) => ({
@@ -244940,10 +245551,10 @@ function registerTemplateCommands(parent) {
244940
245551
  }));
244941
245552
  const getCmd = templates.command("get <template-id>").alias("inspect").description("Inspect a tmpl_… resource: current tmpr_…, format, checksum, tokens, grammar.");
244942
245553
  addJsonFlag(withBaseUrl(getCmd)).action(action(async (templateId, opts) => {
244943
- const client = buildClient3(opts);
245554
+ const client = buildClient5(opts);
244944
245555
  const template = await getPublicTemplate(client, templateId);
244945
245556
  if (opts.json) {
244946
- printJson3(template);
245557
+ printJson5(template);
244947
245558
  return;
244948
245559
  }
244949
245560
  printTemplateHuman(template);
@@ -244952,21 +245563,21 @@ function registerTemplateCommands(parent) {
244952
245563
  withBaseUrl(downloadCmd).action(action(async (templateId, opts) => {
244953
245564
  if (!opts.out)
244954
245565
  throw new Error("Missing --out <path>.");
244955
- const client = buildClient3(opts);
245566
+ const client = buildClient5(opts);
244956
245567
  const downloaded = await downloadTemplateBytes(client, templateId, opts.revisionId);
244957
- await fs19.writeFile(opts.out, downloaded.bytes);
245568
+ await fs20.writeFile(opts.out, downloaded.bytes);
244958
245569
  success(`Wrote ${ui.bold(opts.out)} ${ui.dim(`(${downloaded.bytes.byteLength} bytes)`)}`);
244959
245570
  }));
244960
245571
  const replaceCmd = templates.command("replace <template-id> <file>").description("Append an immutable revision and advance the tmpl_… pointer.");
244961
245572
  addJsonFlag(withBaseUrl(replaceCmd)).action(action(async (templateId, file, opts) => {
244962
245573
  const filePath = resolve9(file);
244963
- const bytes = await fs19.readFile(filePath);
244964
- const client = buildClient3(opts);
245574
+ const bytes = await fs20.readFile(filePath);
245575
+ const client = buildClient5(opts);
244965
245576
  const current = await getPublicTemplate(client, templateId);
244966
245577
  const nextInspection = inspectOfficeTemplateBytes(bytes, basename3(filePath));
244967
245578
  if (current.currentRevision?.sha256 === nextInspection.sha256 || current.sha256 === nextInspection.sha256) {
244968
245579
  if (opts.json) {
244969
- printJson3({ ...current, reused: true });
245580
+ printJson5({ ...current, reused: true });
244970
245581
  return;
244971
245582
  }
244972
245583
  success(`Checksum matches current revision ${ui.bold(current.currentRevision?.id ?? "-")} — skipped upload`);
@@ -244978,7 +245589,7 @@ function registerTemplateCommands(parent) {
244978
245589
  filename: basename3(filePath)
244979
245590
  });
244980
245591
  if (opts.json) {
244981
- printJson3(template);
245592
+ printJson5(template);
244982
245593
  return;
244983
245594
  }
244984
245595
  success(`Replaced ${ui.bold(template.id)} → revision ${ui.bold(template.currentRevision?.id ?? "-")}`);
@@ -244989,10 +245600,10 @@ function registerTemplateCommands(parent) {
244989
245600
  if (!opts.yes && !process.stdout.isTTY) {
244990
245601
  throw new Error("templates delete is destructive and requires --yes when run non-interactively");
244991
245602
  }
244992
- const client = buildClient3(opts);
245603
+ const client = buildClient5(opts);
244993
245604
  const result = await deleteWorkspaceTemplate(client, templateId);
244994
245605
  if (opts.json) {
244995
- printJson3(result);
245606
+ printJson5(result);
244996
245607
  return;
244997
245608
  }
244998
245609
  success(`Deleted ${ui.bold(templateId)}`);
@@ -245005,7 +245616,7 @@ function registerTemplateCommands(parent) {
245005
245616
  let filename;
245006
245617
  const isTmpl = TemplateIdSchema.safeParse(templateArg).success;
245007
245618
  if (isTmpl) {
245008
- const client = buildClient3(opts);
245619
+ const client = buildClient5(opts);
245009
245620
  const downloaded = await downloadTemplateBytes(client, templateArg, opts.revisionId);
245010
245621
  bytes = downloaded.bytes;
245011
245622
  filename = downloaded.filename;
@@ -245014,12 +245625,12 @@ function registerTemplateCommands(parent) {
245014
245625
  if (!existsSync20(filePath)) {
245015
245626
  throw new Error(`Template file not found: ${filePath}. Pass a local .docx/.xlsx path or a tmpl_… id.`);
245016
245627
  }
245017
- bytes = await fs19.readFile(filePath);
245628
+ bytes = await fs20.readFile(filePath);
245018
245629
  filename = basename3(filePath);
245019
245630
  }
245020
245631
  const rendered = renderLocalOfficeTemplate(bytes, filename, data);
245021
245632
  const { unresolved, unusedDataKeys } = compareTemplateDataKeys(rendered.inspection.tokens, Object.keys(data));
245022
- await fs19.writeFile(opts.out, rendered.output);
245633
+ await fs20.writeFile(opts.out, rendered.output);
245023
245634
  const payload = {
245024
245635
  format: rendered.inspection.format,
245025
245636
  sha256: rendered.inspection.sha256,
@@ -245033,7 +245644,7 @@ function registerTemplateCommands(parent) {
245033
245644
  bytes: rendered.output.byteLength
245034
245645
  };
245035
245646
  if (opts.json) {
245036
- printJson3(payload);
245647
+ printJson5(payload);
245037
245648
  return;
245038
245649
  }
245039
245650
  success(`Wrote ${ui.bold(opts.out)} (${rendered.inspection.format}, ${rendered.output.byteLength} bytes)`);
@@ -245784,20 +246395,20 @@ function relPath(root, target) {
245784
246395
  }
245785
246396
 
245786
246397
  // src/commands/workflow/index.ts
245787
- function buildClient4(opts) {
246398
+ function buildClient6(opts) {
245788
246399
  const config = resolveConfig(opts);
245789
246400
  requireApiKey(config);
245790
246401
  return new ApiClient(config);
245791
246402
  }
245792
246403
  async function buildClientForWorkflow(workflowIdOrSlug, opts) {
245793
- const client = buildClient4(opts);
246404
+ const client = buildClient6(opts);
245794
246405
  const workflowId = await resolveWorkflowId(client, workflowIdOrSlug);
245795
246406
  return { client, workflowId };
245796
246407
  }
245797
246408
  function descriptionFor(tool) {
245798
246409
  return WORKFLOW_TOOL_METADATA[tool].description;
245799
246410
  }
245800
- function printJson4(value) {
246411
+ function printJson6(value) {
245801
246412
  console.log(JSON.stringify(value, null, 2));
245802
246413
  }
245803
246414
  function extractWorkflowVersion(yaml) {
@@ -245806,7 +246417,7 @@ function extractWorkflowVersion(yaml) {
245806
246417
  }
245807
246418
  async function writeOrPrint(out, content) {
245808
246419
  if (out) {
245809
- await fs20.writeFile(out, content);
246420
+ await fs21.writeFile(out, content);
245810
246421
  process.stderr.write(`${ui.ok("✓")} Wrote ${ui.bold(out)}
245811
246422
  `);
245812
246423
  return;
@@ -245816,7 +246427,7 @@ async function writeOrPrint(out, content) {
245816
246427
  async function readDirAsZip2(dir) {
245817
246428
  const tree = {};
245818
246429
  async function walk(current, relPrefix) {
245819
- const entries = await fs20.readdir(current, { withFileTypes: true });
246430
+ const entries = await fs21.readdir(current, { withFileTypes: true });
245820
246431
  for (const e of entries) {
245821
246432
  if (e.name.startsWith(".") || e.name === "node_modules")
245822
246433
  continue;
@@ -245825,7 +246436,7 @@ async function readDirAsZip2(dir) {
245825
246436
  if (e.isDirectory())
245826
246437
  await walk(full, rel);
245827
246438
  else if (e.isFile())
245828
- tree[rel] = new Uint8Array(await fs20.readFile(full));
246439
+ tree[rel] = new Uint8Array(await fs21.readFile(full));
245829
246440
  }
245830
246441
  }
245831
246442
  await walk(dir, "");
@@ -245845,7 +246456,7 @@ async function downloadStreamToFile2(client, path, outFile) {
245845
246456
  const res = await client.getStream(path);
245846
246457
  const buf = Buffer.from(await res.arrayBuffer());
245847
246458
  if (outFile) {
245848
- await fs20.writeFile(outFile, buf);
246459
+ await fs21.writeFile(outFile, buf);
245849
246460
  process.stderr.write(`${ui.ok("✓")} Wrote ${ui.bold(outFile)} ${ui.dim(`(${buf.byteLength} bytes)`)}
245850
246461
  `);
245851
246462
  return;
@@ -245884,6 +246495,7 @@ YAML's \`name:\` field). Both:
245884
246495
  $ eigenpal workflow pull my-extraction
245885
246496
  `);
245886
246497
  registerWorkflowCoreCommands(workflow);
246498
+ registerWorkflowFolderCommands(workflow);
245887
246499
  registerEvaluatorsCommands(workflow);
245888
246500
  registerDatasetCommands2(workflow);
245889
246501
  registerTemplateCommands(workflow);
@@ -245898,7 +246510,7 @@ YAML's \`name:\` field). Both:
245898
246510
  function registerWorkflowCoreCommands(parent) {
245899
246511
  const listCmd = parent.command("list").description(descriptionFor("workflow_list")).option("--search <q>", "Filter by name");
245900
246512
  addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
245901
- const client = buildClient4(opts);
246513
+ const client = buildClient6(opts);
245902
246514
  const params = {
245903
246515
  limit: String(opts.limit),
245904
246516
  offset: String(opts.offset)
@@ -246000,8 +246612,8 @@ new uploads are deleted. The file on disk is not rewritten.
246000
246612
  throw new Error("Missing --file <yaml>.");
246001
246613
  }
246002
246614
  }
246003
- const yamlOnDisk = await fs20.readFile(filePath, "utf8");
246004
- const client = buildClient4(opts);
246615
+ const yamlOnDisk = await fs21.readFile(filePath, "utf8");
246616
+ const client = buildClient6(opts);
246005
246617
  const definition = parseWorkflowOrThrow(yamlOnDisk);
246006
246618
  const loadedTemplates = await loadLocalTemplatesForPush(filePath, definition.steps, {
246007
246619
  allowExternal: Boolean(opts.allowExternalTemplates)
@@ -246059,7 +246671,7 @@ new uploads are deleted. The file on disk is not rewritten.
246059
246671
  });
246060
246672
  await finalizeCreatedWorkspaceTemplates(client, created);
246061
246673
  if (opts.json) {
246062
- printJson4(withLocalTemplates(result, resolvedTemplates));
246674
+ printJson6(withLocalTemplates(result, resolvedTemplates));
246063
246675
  return;
246064
246676
  }
246065
246677
  success(`Pushed ${ui.bold(workflowId)} (v${result.version ?? nextVersion})`);
@@ -246073,7 +246685,7 @@ new uploads are deleted. The file on disk is not rewritten.
246073
246685
  });
246074
246686
  await finalizeCreatedWorkspaceTemplates(client, created);
246075
246687
  if (opts.json) {
246076
- printJson4(withLocalTemplates(result, resolvedTemplates));
246688
+ printJson6(withLocalTemplates(result, resolvedTemplates));
246077
246689
  return;
246078
246690
  }
246079
246691
  const id = result.workflow?.id ?? result.id ?? "?";
@@ -246085,19 +246697,56 @@ new uploads are deleted. The file on disk is not rewritten.
246085
246697
  await rethrowAfterTemplateCleanup(client, created, err);
246086
246698
  }
246087
246699
  }));
246088
- const moveCmd = parent.command("move <workflow-id>").description("Move a workflow to a folder path, creating folders as needed").requiredOption("--folder <path>", "Target folder path (`/` for root)");
246700
+ const moveCmd = parent.command("move <workflow-id>").description("Move a workflow to a folder path, creating folders as needed").requiredOption("--folder <path>", "Target folder path (`/` for root)").addHelpText("after", `
246701
+ Uses the public \`/v1/automations/{id}\` move API. \`/\` moves the workflow to
246702
+ the root. Agents cannot be moved with this command.
246703
+ `);
246089
246704
  addJsonFlag(withBaseUrl(moveCmd)).action(action(async (workflow, opts) => {
246090
246705
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246091
- const result = await client.patch(`/api/workflows/${workflowId}`, {
246706
+ const automation = await fetchAutomation(client, workflowId);
246707
+ if (automation.type != null && automation.type !== "workflow") {
246708
+ throw new Error(`${workflowId} is an agent, not a workflow. Agents do not support folder placement.`);
246709
+ }
246710
+ const result = await client.patch(`/v1/automations/${encodeURIComponent(workflowId)}`, {
246092
246711
  folderPath: opts.folder
246093
246712
  });
246094
246713
  if (opts.json) {
246095
- printJson4(result);
246714
+ printJson6(result);
246096
246715
  return;
246097
246716
  }
246098
246717
  const target = opts.folder.trim() === "/" ? "root" : opts.folder;
246099
246718
  success(`Moved ${ui.bold(workflowId)} to ${ui.bold(target)}`);
246100
246719
  }));
246720
+ const deleteCmd = parent.command("delete <workflow-id>").description("Delete a workflow definition while preserving past runs.").option("--yes", "Skip typed-id confirmation (required in CI / agent terminals without a TTY)").addHelpText("after", `
246721
+ Permanently deletes the workflow definition and version history. Existing run
246722
+ history is preserved and marked as belonging to a deleted workflow.
246723
+
246724
+ Pass \`--yes\` in scripts, CI, and agent terminals (non-TTY). In a TTY, type the
246725
+ resolved workflow id to confirm.
246726
+ `);
246727
+ addJsonFlag(withBaseUrl(deleteCmd)).action(action(async (workflow, opts) => {
246728
+ requireYesInNonInteractive(opts.yes, "delete workflow");
246729
+ const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246730
+ const automation = await fetchAutomation(client, workflowId);
246731
+ if (automation.type != null && automation.type !== "workflow") {
246732
+ throw new Error(`${workflowId} is an agent, not a workflow. Use \`eigenpal agents delete\` instead.`);
246733
+ }
246734
+ warn("This permanently deletes the workflow definition and version history. Existing run history is preserved.");
246735
+ if (!opts.yes && isInteractiveStderr()) {
246736
+ await requireTypedConfirmation({
246737
+ id: workflowId,
246738
+ actionName: "delete workflow",
246739
+ cancelledMessage: "Workflow delete aborted"
246740
+ });
246741
+ }
246742
+ const result = await client.delete(`/v1/automations/${encodeURIComponent(workflowId)}`);
246743
+ const parsed = parseAutomationDeleteResult(result);
246744
+ if (opts.json) {
246745
+ printJson6({ ...parsed, id: workflowId });
246746
+ return;
246747
+ }
246748
+ success(`Deleted workflow ${ui.bold(workflowId)}`);
246749
+ }));
246101
246750
  }
246102
246751
  function withLocalTemplates(result, resolved) {
246103
246752
  if (resolved.length === 0)
@@ -246259,13 +246908,13 @@ function registerEvaluatorsCommands(parent) {
246259
246908
  }));
246260
246909
  const pushCmd = evaluators.command("push <workflow-id>").description(descriptionFor("workflow_set_evaluators")).requiredOption("--file <yaml>", "Path to evaluators YAML file");
246261
246910
  addJsonFlag(withBaseUrl(pushCmd)).action(action(async (workflow, opts) => {
246262
- const yaml = await fs20.readFile(opts.file, "utf8");
246911
+ const yaml = await fs21.readFile(opts.file, "utf8");
246263
246912
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246264
246913
  const result = await client.put(`/v1/automations/${workflowId}/evaluators`, {
246265
246914
  yaml
246266
246915
  });
246267
246916
  if (opts.json) {
246268
- printJson4(result);
246917
+ printJson6(result);
246269
246918
  return;
246270
246919
  }
246271
246920
  let count = null;
@@ -246343,8 +246992,8 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
246343
246992
  cancelledMessage: "Dataset replace aborted"
246344
246993
  });
246345
246994
  }
246346
- const stat = await fs20.stat(opts.file);
246347
- const data = stat.isDirectory() ? await readDirAsZip2(opts.file) : new Uint8Array(await fs20.readFile(opts.file));
246995
+ const stat = await fs21.stat(opts.file);
246996
+ const data = stat.isDirectory() ? await readDirAsZip2(opts.file) : new Uint8Array(await fs21.readFile(opts.file));
246348
246997
  const filename = stat.isDirectory() ? `${path19.basename(opts.file)}.zip` : opts.file;
246349
246998
  const formData = new FormData;
246350
246999
  formData.append("file", new Blob([data]), filename);
@@ -246373,7 +247022,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
246373
247022
  }));
246374
247023
  if (issues.length === 0) {
246375
247024
  error2("Import aborted with no structured issues — server-side bug.");
246376
- printJson4(terminal);
247025
+ printJson6(terminal);
246377
247026
  } else {
246378
247027
  printIssues("dataset", opts.file, issues);
246379
247028
  if (errPayload.limitMb != null && errPayload.actualMb != null) {
@@ -246394,7 +247043,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
246394
247043
  if (terminal.phase === "done") {
246395
247044
  const done = terminal;
246396
247045
  if (opts.json) {
246397
- printJson4(done);
247046
+ printJson6(done);
246398
247047
  return;
246399
247048
  }
246400
247049
  const created = done.created ?? 0;
@@ -246412,7 +247061,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
246412
247061
  }
246413
247062
  } else {
246414
247063
  error2(`Import response had unexpected terminal phase: ${terminal.phase}`);
246415
- printJson4(terminal);
247064
+ printJson6(terminal);
246416
247065
  process.exit(1);
246417
247066
  }
246418
247067
  }));
@@ -246437,7 +247086,7 @@ async function readJsonInput(literal, filePath, flagName) {
246437
247086
  process.stdin.on("data", (chunk) => buf += chunk);
246438
247087
  process.stdin.once("end", () => resolve(buf));
246439
247088
  process.stdin.once("error", reject);
246440
- }) : await fs20.readFile(filePath, "utf8");
247089
+ }) : await fs21.readFile(filePath, "utf8");
246441
247090
  try {
246442
247091
  return JSON.parse(raw);
246443
247092
  } catch (err) {
@@ -246472,7 +247121,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
246472
247121
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246473
247122
  const result = await client.post(`/v1/automations/${workflowId}/examples`, body);
246474
247123
  if (opts.json) {
246475
- printJson4(result);
247124
+ printJson6(result);
246476
247125
  return;
246477
247126
  }
246478
247127
  success(`Created example ${ui.bold(opts.name)} (${result.id}) in ${ui.bold(workflowId)}`);
@@ -246498,7 +247147,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
246498
247147
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246499
247148
  const result = await client.patch(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`, body);
246500
247149
  if (opts.json) {
246501
- printJson4(result);
247150
+ printJson6(result);
246502
247151
  return;
246503
247152
  }
246504
247153
  const fields = Object.keys(body).join(", ");
@@ -246512,7 +247161,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
246512
247161
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246513
247162
  const deleted = await client.delete(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`);
246514
247163
  if (opts.json) {
246515
- printJson4(deleted);
247164
+ printJson6(deleted);
246516
247165
  return;
246517
247166
  }
246518
247167
  success(`Deleted example ${ui.bold(deleted.name ?? exampleId)} ${ui.dim(`(${exampleId})`)} from ${ui.bold(workflowId)}`);
@@ -246522,7 +247171,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
246522
247171
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246523
247172
  const row = await client.get(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`);
246524
247173
  if (opts.json) {
246525
- printJson4(row);
247174
+ printJson6(row);
246526
247175
  return;
246527
247176
  }
246528
247177
  renderExampleHuman(row);
@@ -246649,7 +247298,7 @@ returns immediately with \`{ batchId, total }\`; poll
246649
247298
  const total = start.runCount ?? start.total ?? 0;
246650
247299
  if (!opts.wait) {
246651
247300
  if (opts.json) {
246652
- printJson4({ ...start, batchId: experimentId, total });
247301
+ printJson6({ ...start, batchId: experimentId, total });
246653
247302
  return;
246654
247303
  }
246655
247304
  success(`Started experiment ${ui.bold(experimentId)} ${ui.dim(`(${total} run${total === 1 ? "" : "s"} queued)`)}`);
@@ -246663,7 +247312,7 @@ returns immediately with \`{ batchId, total }\`; poll
246663
247312
  const status = await client.get(`/v1/automations/${workflowId}/experiments/${experimentId}`);
246664
247313
  if (status.status === "completed") {
246665
247314
  if (opts.json) {
246666
- printJson4({
247315
+ printJson6({
246667
247316
  ...status,
246668
247317
  batchId: experimentId,
246669
247318
  total: status.runCount ?? status.total
@@ -246683,7 +247332,7 @@ returns immediately with \`{ batchId, total }\`; poll
246683
247332
  }
246684
247333
  if (Date.now() >= deadline) {
246685
247334
  if (opts.json) {
246686
- printJson4({
247335
+ printJson6({
246687
247336
  ...status,
246688
247337
  batchId: experimentId,
246689
247338
  total: status.runCount ?? status.total
@@ -246723,12 +247372,12 @@ returns immediately with \`{ batchId, total }\`; poll
246723
247372
  const summary = summarizeExperimentExecutions(execs);
246724
247373
  if (execs.length === 0) {
246725
247374
  if (opts.json)
246726
- printJson4({ ...result, summary: rollupForJson(summary) });
247375
+ printJson6({ ...result, summary: rollupForJson(summary) });
246727
247376
  error2(`Experiment ${batchId} still has no executions after retrying — check the batch id.`);
246728
247377
  process.exit(1);
246729
247378
  }
246730
247379
  if (opts.json) {
246731
- printJson4({ ...result, summary: rollupForJson(summary) });
247380
+ printJson6({ ...result, summary: rollupForJson(summary) });
246732
247381
  return;
246733
247382
  }
246734
247383
  if (opts.short) {
@@ -246760,7 +247409,7 @@ returns immediately with \`{ batchId, total }\`; poll
246760
247409
  maxWait: opts.maxWait,
246761
247410
  onTerminal: (result, summary) => {
246762
247411
  if (wantPayload) {
246763
- printJson4({ ...result, summary: rollupForJson(summary) });
247412
+ printJson6({ ...result, summary: rollupForJson(summary) });
246764
247413
  } else {
246765
247414
  process.stderr.write(`${ui.dim(`use --include payload (or --json) for the full per-execution snapshot`)}
246766
247415
  `);
@@ -246768,7 +247417,7 @@ returns immediately with \`{ batchId, total }\`; poll
246768
247417
  },
246769
247418
  onDeadline: (result, summary) => {
246770
247419
  if (wantPayload)
246771
- printJson4({ ...result, summary: rollupForJson(summary) });
247420
+ printJson6({ ...result, summary: rollupForJson(summary) });
246772
247421
  }
246773
247422
  });
246774
247423
  }));
@@ -246792,7 +247441,7 @@ Behavior:
246792
247441
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
246793
247442
  const result = await client.post(`/v1/automations/${workflowId}/experiments/${batchId}/cancel`);
246794
247443
  if (opts.json) {
246795
- printJson4(result);
247444
+ printJson6(result);
246796
247445
  return;
246797
247446
  }
246798
247447
  const c = result.counts;
@@ -246866,7 +247515,7 @@ batches must belong to the same workflow within the caller's tenant.
246866
247515
  if (!Number.isFinite(threshold) || threshold < 0) {
246867
247516
  throw new Error("--regression-threshold must be a non-negative number");
246868
247517
  }
246869
- const client = buildClient4(opts);
247518
+ const client = buildClient6(opts);
246870
247519
  if (opts.outputs) {
246871
247520
  const [outputsA, outputsB] = await Promise.all([
246872
247521
  fetchExperimentOutputs(client, batchIdA),
@@ -246882,7 +247531,7 @@ batches must belong to the same workflow within the caller's tenant.
246882
247531
  rowsB: outputsB.rows
246883
247532
  });
246884
247533
  if (opts.json)
246885
- printJson4(outputDiff);
247534
+ printJson6(outputDiff);
246886
247535
  else
246887
247536
  renderExperimentOutputDiffHuman(outputDiff);
246888
247537
  return;
@@ -246900,7 +247549,7 @@ batches must belong to the same workflow within the caller's tenant.
246900
247549
  regressionThreshold: threshold
246901
247550
  });
246902
247551
  if (opts.json) {
246903
- printJson4(diff);
247552
+ printJson6(diff);
246904
247553
  return;
246905
247554
  }
246906
247555
  renderBatchDiffHuman(diff);
@@ -247158,7 +247807,7 @@ sent to the server is replaced with \`templateId\` + \`templateRevisionId\`.
247158
247807
  let yamlOnDisk;
247159
247808
  let loadedTemplates = [];
247160
247809
  if (opts.file) {
247161
- yamlOnDisk = await fs20.readFile(opts.file, "utf8");
247810
+ yamlOnDisk = await fs21.readFile(opts.file, "utf8");
247162
247811
  const definition = parseWorkflowOrThrow(yamlOnDisk);
247163
247812
  loadedTemplates = await loadLocalTemplatesForPush(opts.file, definition.steps, {
247164
247813
  allowExternal: Boolean(opts.allowExternalTemplates)
@@ -247185,7 +247834,7 @@ sent to the server is replaced with \`templateId\` + \`templateRevisionId\`.
247185
247834
  const result = await client.post(automationVersionsPath(workflowId), body).catch((err) => rethrowAfterTemplateCleanup(client, created, err));
247186
247835
  await finalizeCreatedWorkspaceTemplates(client, created);
247187
247836
  if (opts.json) {
247188
- printJson4(withLocalTemplates(result, resolvedTemplates));
247837
+ printJson6(withLocalTemplates(result, resolvedTemplates));
247189
247838
  return;
247190
247839
  }
247191
247840
  const id = typeof result.id === "string" ? result.id : "?";
@@ -247208,7 +247857,7 @@ restore HEAD) return 404 — create a tagged copy first.
247208
247857
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
247209
247858
  const result = await client.post(automationVersionsPath(workflowId, `/${encodeURIComponent(versionId)}/promote`));
247210
247859
  if (opts.json) {
247211
- printJson4(result);
247860
+ printJson6(result);
247212
247861
  return;
247213
247862
  }
247214
247863
  const label = formatWorkflowVersionLabel(result.version);
@@ -247231,7 +247880,7 @@ promoted until you create a tagged copy.
247231
247880
  const body = opts.message ? { message: opts.message } : {};
247232
247881
  const result = await client.post(automationVersionsPath(workflowId, `/${encodeURIComponent(versionId)}/restore`), body);
247233
247882
  if (opts.json) {
247234
- printJson4(result);
247883
+ printJson6(result);
247235
247884
  return;
247236
247885
  }
247237
247886
  const id = typeof result.id === "string" ? result.id : "?";
@@ -247494,8 +248143,8 @@ var HELP_GROUPS = [
247494
248143
  },
247495
248144
  {
247496
248145
  title: "Run",
247497
- description: "Start runs, then watch them, read their output, and download artifacts.",
247498
- commands: ["run", "rerun", "runs"]
248146
+ description: "Start runs, watch them, download artifacts, and work live human-review queues for paused runs.",
248147
+ commands: ["run", "rerun", "runs", "reviews"]
247499
248148
  },
247500
248149
  {
247501
248150
  title: "Tooling",
@@ -247711,6 +248360,7 @@ registerModelsCommands(program2);
247711
248360
  registerEmailServersCommands(program2);
247712
248361
  registerRunCommands(program2);
247713
248362
  registerRunsCommands(program2);
248363
+ registerReviewsCommands(program2);
247714
248364
  registerGitCommands(program2);
247715
248365
  registerDocsCommands(program2);
247716
248366
  program2.command("completion <shell>").description("Print a shell completion script to stdout (supported shells: bash, zsh, fish). Pipe into the appropriate completion file for your shell — see the script header for install instructions.").action(async (shell) => {