@swmansion/argent 0.21.1-next.8 → 0.22.0

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.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/cli-cmds.mjs CHANGED
@@ -2309,6 +2309,8 @@ var FAILURE_CODES = {
2309
2309
  IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
2310
2310
  IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
2311
2311
  ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
2312
+ PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
2313
+ PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
2312
2314
  SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
2313
2315
  NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
2314
2316
  NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
@@ -7214,7 +7216,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
7214
7216
  var SESSION_ID2 = randomUUID5();
7215
7217
  function readCliVersion() {
7216
7218
  if (true) {
7217
- return "0.21.1-next.8";
7219
+ return "0.22.0";
7218
7220
  }
7219
7221
  return "0.0.0";
7220
7222
  }
@@ -8400,8 +8402,9 @@ function stepIndent(depth) {
8400
8402
  if (typeof depth !== "number" || !Number.isInteger(depth) || depth <= 0) return "";
8401
8403
  return " ".repeat(Math.min(depth, MAX_RENDER_DEPTH));
8402
8404
  }
8403
- function printHelp() {
8404
- console.log(`Usage: argent flow <subcommand> [options]
8405
+ function printHelp(toStderr = false) {
8406
+ const print = toStderr ? console.error : console.log;
8407
+ print(`Usage: argent flow <subcommand> [options]
8405
8408
 
8406
8409
  Run a YAML flow without an LLM in the loop. \`run\` takes any of these forms:
8407
8410
 
@@ -8451,6 +8454,7 @@ Options (run):
8451
8454
  overwritten
8452
8455
  -r, --recursive With a directory path, also run flows in subdirectories
8453
8456
  --json Print the raw JSON report
8457
+ --json-stream Print progress and the final report as NDJSON (single flow only)
8454
8458
  --help, -h Show this help
8455
8459
  -- End of options \u2014 only needed for a flow whose name
8456
8460
  starts with "-" (\`argent flow run -- -nightly\`)
@@ -8466,7 +8470,8 @@ function parseRunArgs(argv) {
8466
8470
  const out = {
8467
8471
  updateBaselines: false,
8468
8472
  recursive: false,
8469
- json: false
8473
+ json: false,
8474
+ jsonStream: false
8470
8475
  };
8471
8476
  const takePositional = (tok) => {
8472
8477
  if (out.flowRef !== void 0) {
@@ -8516,6 +8521,9 @@ function parseRunArgs(argv) {
8516
8521
  } else if (flag === "--json") {
8517
8522
  noValue("--json");
8518
8523
  out.json = true;
8524
+ } else if (flag === "--json-stream") {
8525
+ noValue("--json-stream");
8526
+ out.jsonStream = true;
8519
8527
  } else if (flag === "--recursive" || flag === "-r") {
8520
8528
  noValue("--recursive");
8521
8529
  out.recursive = true;
@@ -8524,6 +8532,9 @@ function parseRunArgs(argv) {
8524
8532
  else if (flag === "--output") out.output = takeValue("--output");
8525
8533
  else throw new FlagParseException(`unknown flag ${tok}`);
8526
8534
  }
8535
+ if (out.json && out.jsonStream) {
8536
+ throw new FlagParseException("--json and --json-stream cannot be combined");
8537
+ }
8527
8538
  return out;
8528
8539
  }
8529
8540
  function renderEchoLine(s) {
@@ -8822,13 +8833,10 @@ async function collectFlowFiles(dir, recursive) {
8822
8833
  }
8823
8834
  async function requireLocalToolServer() {
8824
8835
  const routing = await getResolvedToolsUrl();
8825
- if (routing.source === "none") return true;
8836
+ if (routing.source === "none") return void 0;
8826
8837
  const recovery = routing.source === "env" ? routing.shadowedLink ? `Unset ARGENT_TOOLS_URL and run \`argent unlink\`, then try again \u2014 a link to ${routing.shadowedLink.url} is also configured and takes over once the env var is unset.` : "Unset ARGENT_TOOLS_URL and try again." : "Run `argent unlink` and try again.";
8827
- console.error(
8828
- `argent flow run requires the auto-started local tool server; ${routing.source} routing is configured.
8829
- ${recovery}`
8830
- );
8831
- return false;
8838
+ return `argent flow run requires the auto-started local tool server; ${routing.source} routing is configured.
8839
+ ${recovery}`;
8832
8840
  }
8833
8841
  function buildRunPayload(flowPath, projectRoot, args) {
8834
8842
  const payload = {
@@ -8842,6 +8850,18 @@ function buildRunPayload(flowPath, projectRoot, args) {
8842
8850
  if (args.updateBaselines) payload.updateBaselines = true;
8843
8851
  return payload;
8844
8852
  }
8853
+ function writeJsonStreamRecord(record) {
8854
+ console.log(JSON.stringify(record));
8855
+ }
8856
+ function writeJsonStreamError(err) {
8857
+ const message = err instanceof Error ? err.message : String(err);
8858
+ writeJsonStreamRecord({
8859
+ event: "error",
8860
+ error: message,
8861
+ ...err instanceof ToolInvocationError && err.errorCode ? { error_code: err.errorCode } : {},
8862
+ ...err instanceof ToolInvocationError && err.errorKind ? { error_kind: err.errorKind } : {}
8863
+ });
8864
+ }
8845
8865
  async function exportAndResolveArtifacts(report, outputDir, flowPath, baseUrl) {
8846
8866
  if (outputDir) {
8847
8867
  const { url, token } = await baseUrl();
@@ -8862,7 +8882,11 @@ async function runFlowDirectory(dir, args, projectRoot, options) {
8862
8882
  if (!args.recursive) console.error("Pass -r/--recursive to include subdirectories.");
8863
8883
  return exitAfterFlush(2);
8864
8884
  }
8865
- if (!await requireLocalToolServer()) return exitAfterFlush(2);
8885
+ const refusal = await requireLocalToolServer();
8886
+ if (refusal) {
8887
+ console.error(refusal);
8888
+ return exitAfterFlush(2);
8889
+ }
8866
8890
  const { callTool, baseUrl } = createToolsClient({ paths: options.paths });
8867
8891
  const outputBase = args.output ? path14.resolve(args.output) : void 0;
8868
8892
  const results = [];
@@ -8944,27 +8968,36 @@ async function flow(argv, options) {
8944
8968
  console.error(`Unknown flow subcommand "${sub}". Run \`argent flow --help\`.`);
8945
8969
  return exitAfterFlush(2);
8946
8970
  }
8971
+ const jsonStream = rest.some(
8972
+ (tok) => tok === "--json-stream" || tok.startsWith("--json-stream=")
8973
+ );
8947
8974
  if (rest.includes("--help") || rest.includes("-h")) {
8948
- printHelp();
8975
+ printHelp(jsonStream);
8949
8976
  return;
8950
8977
  }
8978
+ const fail = (message, code, err = message) => {
8979
+ if (jsonStream) writeJsonStreamError(err);
8980
+ console.error(message);
8981
+ return exitAfterFlush(code);
8982
+ };
8951
8983
  let args;
8952
8984
  try {
8953
8985
  args = parseRunArgs(rest);
8954
8986
  } catch (err) {
8955
8987
  if (err instanceof FlagParseException) {
8988
+ if (jsonStream) writeJsonStreamError(err);
8956
8989
  console.error(`Error: ${err.message}
8957
8990
  `);
8958
- printHelp();
8991
+ printHelp(jsonStream);
8959
8992
  return exitAfterFlush(2);
8960
8993
  }
8961
8994
  throw err;
8962
8995
  }
8963
8996
  if (!args.flowRef) {
8964
- console.error(
8965
- "argent flow run <flow|flow.yaml|dir> requires a flow name, a YAML file path, or a directory path."
8966
- );
8967
- printHelp();
8997
+ const message = "argent flow run <flow|flow.yaml|dir> requires a flow name, a YAML file path, or a directory path.";
8998
+ if (jsonStream) writeJsonStreamError(message);
8999
+ console.error(message);
9000
+ printHelp(jsonStream);
8968
9001
  return exitAfterFlush(2);
8969
9002
  }
8970
9003
  const projectRoot = process.cwd();
@@ -8980,11 +9013,11 @@ async function flow(argv, options) {
8980
9013
  } catch {
8981
9014
  }
8982
9015
  }
8983
- console.error(
9016
+ return fail(
8984
9017
  `Flow path must not contain ".." segments \u2014 they are collapsed without following symlinks, so the path can name a different file than the one your shell opens: ${suppliedPath}
8985
- ` + recovery
9018
+ ` + recovery,
9019
+ 2
8986
9020
  );
8987
- return exitAfterFlush(2);
8988
9021
  }
8989
9022
  const resolvedPath = path14.resolve(projectRoot, suppliedPath);
8990
9023
  let isDirectory = false;
@@ -8992,61 +9025,65 @@ async function flow(argv, options) {
8992
9025
  isDirectory = (await fsp.stat(resolvedPath)).isDirectory();
8993
9026
  } catch {
8994
9027
  if (args.recursive && !fromName) {
8995
- console.error(`Flow directory not found: ${resolvedPath}`);
8996
- return exitAfterFlush(2);
9028
+ return fail(`Flow directory not found: ${resolvedPath}`, 2);
8997
9029
  }
8998
9030
  }
8999
9031
  if (isDirectory) {
9032
+ if (args.jsonStream) {
9033
+ return fail("--json-stream supports a single flow; directory runs are not supported.", 2);
9034
+ }
9000
9035
  return runFlowDirectory(resolvedPath, args, projectRoot, options);
9001
9036
  }
9002
9037
  if (args.recursive) {
9003
- console.error(
9004
- fromName ? `flow run --recursive requires a directory path; "${args.flowRef}" is a saved-flow name, which always addresses the single file ${suppliedPath}.` : `flow run --recursive requires a directory path: ${suppliedPath}`
9038
+ return fail(
9039
+ fromName ? `flow run --recursive requires a directory path; "${args.flowRef}" is a saved-flow name, which always addresses the single file ${suppliedPath}.` : `flow run --recursive requires a directory path: ${suppliedPath}`,
9040
+ 2
9005
9041
  );
9006
- return exitAfterFlush(2);
9007
9042
  }
9008
9043
  const separatorTrimmedPath = suppliedPath.replace(/[\\/]+$/, "");
9009
9044
  if (separatorTrimmedPath !== suppliedPath && separatorTrimmedPath !== "") {
9010
9045
  const hint = SAFE_FLOW_NAME.test(separatorTrimmedPath) ? `.${path14.sep}${separatorTrimmedPath}` : separatorTrimmedPath;
9011
- console.error(
9046
+ return fail(
9012
9047
  `Flow path must not end in a path separator \u2014 the separator claims a directory, which the kernel would refuse to open as a file, so the CLI would run a file this string does not name: ${suppliedPath}
9013
- Did you mean: argent flow run ${shellQuoteArg(hint)}`
9048
+ Did you mean: argent flow run ${shellQuoteArg(hint)}`,
9049
+ 2
9014
9050
  );
9015
- return exitAfterFlush(2);
9016
9051
  }
9017
9052
  if (path14.extname(suppliedPath) !== ".yaml") {
9018
9053
  const looksLikeName = !suppliedPath.includes("/") && !suppliedPath.includes("\\") && path14.extname(suppliedPath) === "";
9019
9054
  if (path14.basename(suppliedPath).toLowerCase() === ".yaml") {
9020
- console.error(
9021
- `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`
9055
+ return fail(
9056
+ `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
9057
+ 2
9022
9058
  );
9023
- } else if (looksLikeName) {
9024
- console.error(
9059
+ }
9060
+ if (looksLikeName) {
9061
+ return fail(
9025
9062
  `Flow name must contain only letters, numbers, "_", or "-": ${suppliedPath}
9026
- Names run \`${FLOWS_DIR}/<name>.yaml\`; pass a path ending in .yaml to run a flow file kept elsewhere.`
9063
+ Names run \`${FLOWS_DIR}/<name>.yaml\`; pass a path ending in .yaml to run a flow file kept elsewhere.`,
9064
+ 2
9027
9065
  );
9028
- } else if (path14.extname(suppliedPath).toLowerCase() === ".yaml") {
9029
- console.error(
9030
- `Flow extension must be lowercase .yaml, not ${path14.extname(suppliedPath)}: ${suppliedPath}`
9066
+ }
9067
+ if (path14.extname(suppliedPath).toLowerCase() === ".yaml") {
9068
+ return fail(
9069
+ `Flow extension must be lowercase .yaml, not ${path14.extname(suppliedPath)}: ${suppliedPath}`,
9070
+ 2
9031
9071
  );
9032
- } else {
9033
- console.error(`Flow path must end in .yaml: ${suppliedPath}`);
9034
9072
  }
9035
- return exitAfterFlush(2);
9073
+ return fail(`Flow path must end in .yaml: ${suppliedPath}`, 2);
9036
9074
  }
9037
9075
  const flowName = path14.basename(suppliedPath, ".yaml");
9038
9076
  if (!SAFE_FLOW_NAME.test(flowName)) {
9039
- console.error(
9040
- `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`
9077
+ return fail(
9078
+ `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
9079
+ 2
9041
9080
  );
9042
- return exitAfterFlush(2);
9043
9081
  }
9044
9082
  const flowPath = resolvedPath;
9045
9083
  try {
9046
9084
  const stat5 = await fsp.stat(flowPath);
9047
9085
  if (!stat5.isFile()) {
9048
- console.error(`Flow path is not a file: ${flowPath}`);
9049
- return exitAfterFlush(2);
9086
+ return fail(`Flow path is not a file: ${flowPath}`, 2);
9050
9087
  }
9051
9088
  await fsp.access(flowPath, fsConstants2.R_OK);
9052
9089
  } catch (err) {
@@ -9057,8 +9094,7 @@ Names run \`${FLOWS_DIR}/<name>.yaml\`; pass a path ending in .yaml to run a flo
9057
9094
  recovery = fromName ? `
9058
9095
  No flow named "${args.flowRef}" is saved there \u2014 run \`argent flow list\` to see the saved flows.` : await savedFlowHint(projectRoot, flowPath);
9059
9096
  }
9060
- console.error(`${detail}: ${flowPath}${recovery}`);
9061
- return exitAfterFlush(2);
9097
+ return fail(`${detail}: ${flowPath}${recovery}`, 2);
9062
9098
  }
9063
9099
  const suppliedBase = path14.basename(flowPath);
9064
9100
  const siblings = await fsp.readdir(path14.dirname(flowPath)).catch(() => null);
@@ -9066,19 +9102,24 @@ No flow named "${args.flowRef}" is saved there \u2014 run \`argent flow list\` t
9066
9102
  const actual = siblings.find((name) => name.toLowerCase() === suppliedBase.toLowerCase());
9067
9103
  const actualRunnable = actual !== void 0 && path14.extname(actual) === ".yaml" && SAFE_FLOW_NAME.test(path14.basename(actual, ".yaml"));
9068
9104
  const recovery = actualRunnable ? fromName ? `Did you mean: argent flow run ${path14.basename(actual, ".yaml")}` : `Did you mean: argent flow run ${shellQuoteArg(path14.join(path14.dirname(suppliedPath), actual))}` : actual !== void 0 ? `Rename ${actual} to ${suppliedBase} to run it \u2014 flow files must be lowercase .yaml.` : "Pass the flow file's name exactly as it appears on disk.";
9069
- console.error(
9105
+ return fail(
9070
9106
  `Flow path must name the file as it appears on disk \u2014 this filesystem matched ${JSON.stringify(suppliedBase)} case-insensitively${actual !== void 0 ? ` to ${JSON.stringify(actual)}` : ""}, so the flow name (which keys the report, __baselines__/, and --output) would be one no file carries: ${suppliedPath}
9071
- ${recovery}`
9107
+ ${recovery}`,
9108
+ 2
9072
9109
  );
9073
- return exitAfterFlush(2);
9074
9110
  }
9075
- if (!await requireLocalToolServer()) return exitAfterFlush(2);
9111
+ const refusal = await requireLocalToolServer();
9112
+ if (refusal) return fail(refusal, 2);
9076
9113
  const { callTool, baseUrl } = createToolsClient({ paths: options.paths });
9077
9114
  const payload = buildRunPayload(flowPath, projectRoot, args);
9078
9115
  let liveSteps = 0;
9079
9116
  let liveIndex = 0;
9080
9117
  const onStepReport = (event) => {
9081
9118
  const s = event;
9119
+ if (args.jsonStream) {
9120
+ writeJsonStreamRecord({ event: "progress", data: s });
9121
+ return;
9122
+ }
9082
9123
  if (liveSteps === 0) console.log(`Flow "${flowName}"`);
9083
9124
  liveSteps++;
9084
9125
  if (s.kind === "echo") {
@@ -9099,20 +9140,25 @@ ${recovery}`
9099
9140
  );
9100
9141
  report = resp.data;
9101
9142
  } catch (err) {
9102
- console.error(err instanceof Error ? err.message : String(err));
9103
- return exitAfterFlush(1);
9143
+ return fail(err instanceof Error ? err.message : String(err), 1, err);
9104
9144
  }
9105
- if (!report || !("steps" in report)) {
9106
- console.error(`"${flowName}" did not produce a run report.`);
9107
- return exitAfterFlush(2);
9145
+ if (!report || typeof report !== "object" || !("steps" in report)) {
9146
+ return fail(`"${flowName}" did not produce a run report.`, 2);
9108
9147
  }
9109
- await exportAndResolveArtifacts(
9110
- report,
9111
- args.output ? path14.resolve(args.output) : void 0,
9112
- flowPath,
9113
- baseUrl
9114
- );
9115
- if (args.json) {
9148
+ try {
9149
+ await exportAndResolveArtifacts(
9150
+ report,
9151
+ args.output ? path14.resolve(args.output) : void 0,
9152
+ flowPath,
9153
+ baseUrl
9154
+ );
9155
+ } catch (err) {
9156
+ if (!args.jsonStream) throw err;
9157
+ return fail(err instanceof Error ? err.message : String(err), 2, err);
9158
+ }
9159
+ if (args.jsonStream) {
9160
+ writeJsonStreamRecord({ event: "result", data: report });
9161
+ } else if (args.json) {
9116
9162
  console.log(JSON.stringify(report, null, 2));
9117
9163
  } else if (liveSteps > 0) {
9118
9164
  if (report.executionPrerequisite) console.log(` assumes: ${report.executionPrerequisite}`);
@@ -15468,6 +15468,8 @@ var FAILURE_CODES = {
15468
15468
  IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
15469
15469
  IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
15470
15470
  ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
15471
+ PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
15472
+ PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
15471
15473
  SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
15472
15474
  NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
15473
15475
  NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
@@ -16434,7 +16436,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
16434
16436
  var SESSION_ID = randomUUID4();
16435
16437
  function readCliVersion() {
16436
16438
  if (true) {
16437
- return "0.21.1-next.8";
16439
+ return "0.22.0";
16438
16440
  }
16439
16441
  return "0.0.0";
16440
16442
  }
@@ -16493,6 +16493,8 @@ var FAILURE_CODES = {
16493
16493
  IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
16494
16494
  IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
16495
16495
  ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
16496
+ PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
16497
+ PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
16496
16498
  SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
16497
16499
  NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
16498
16500
  NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
@@ -18491,6 +18493,7 @@ var AUTO_SCREENSHOT_TOOLS = /* @__PURE__ */ new Set([
18491
18493
  "gesture-rotate",
18492
18494
  "button",
18493
18495
  "keyboard",
18496
+ "paste",
18494
18497
  "rotate",
18495
18498
  "launch-app",
18496
18499
  "restart-app",
@@ -18513,6 +18516,7 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
18513
18516
  "button": 1500,
18514
18517
  "rotate": 1e3,
18515
18518
  "keyboard": 300,
18519
+ "paste": 300,
18516
18520
  "describe": 100
18517
18521
  };
18518
18522
  var DEFAULT_DELAY_MS = 1400;