@swmansion/argent 0.31.2-next.1 → 0.31.2-next.3

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.
@@ -25593,6 +25593,36 @@ var TOOL_ID_ALIASES = Object.freeze({
25593
25593
  function canonicalToolId(id) {
25594
25594
  return Object.hasOwn(TOOL_ID_ALIASES, id) ? TOOL_ID_ALIASES[id] : id;
25595
25595
  }
25596
+ var TOOL_PARAM_ALIASES = Object.freeze({
25597
+ "e2e-execute": Object.freeze({ flow_path: "e2e_test_path", flow_file: "e2e_test_file" }),
25598
+ "e2e-read-prerequisite": Object.freeze({
25599
+ flow_path: "e2e_test_path",
25600
+ flow_file: "e2e_test_file"
25601
+ })
25602
+ });
25603
+ var ToolParamAliasError = class extends Error {
25604
+ constructor(former, current) {
25605
+ super(`Pass ${current} or its former name ${former}, not both.`);
25606
+ this.name = "ToolParamAliasError";
25607
+ }
25608
+ };
25609
+ function toolParamAliases(tool) {
25610
+ const id = canonicalToolId(tool);
25611
+ return Object.hasOwn(TOOL_PARAM_ALIASES, id) ? TOOL_PARAM_ALIASES[id] : {};
25612
+ }
25613
+ function canonicalToolArgs(tool, args) {
25614
+ if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
25615
+ const record2 = args;
25616
+ let out;
25617
+ for (const [former, current] of Object.entries(toolParamAliases(tool))) {
25618
+ if (record2[former] === void 0) continue;
25619
+ if (record2[current] !== void 0) throw new ToolParamAliasError(former, current);
25620
+ out ??= { ...record2 };
25621
+ out[current] = out[former];
25622
+ delete out[former];
25623
+ }
25624
+ return out ?? args;
25625
+ }
25596
25626
 
25597
25627
  // ../registry/src/flow-file-refs.ts
25598
25628
  async function canonicalFlowPath(p) {
@@ -25662,7 +25692,13 @@ async function classifyOnDiskSpelling(dir, base, addressable = FLOW_FILE_NAME_PA
25662
25692
  }
25663
25693
  function nestedFlowTarget(args) {
25664
25694
  if (typeof args !== "object" || args === null || Array.isArray(args)) return void 0;
25665
- const { name, project_root: projectRoot, flow_path: flowPath } = args;
25695
+ let canonical;
25696
+ try {
25697
+ canonical = canonicalToolArgs("e2e-execute", args);
25698
+ } catch {
25699
+ return void 0;
25700
+ }
25701
+ const { name, project_root: projectRoot, e2e_test_path: flowPath } = canonical;
25666
25702
  if (flowPath === void 0) {
25667
25703
  if (typeof name !== "string" || !FLOW_NAME_PATTERN.test(name)) return void 0;
25668
25704
  if (!isResolvedAbsolute(projectRoot)) return void 0;
@@ -25671,7 +25707,7 @@ function nestedFlowTarget(args) {
25671
25707
  }
25672
25708
  if (name !== void 0 || !isResolvedAbsolute(flowPath)) return void 0;
25673
25709
  if (!FLOW_FILE_NAME_PATTERN.test(path8.basename(flowPath))) return void 0;
25674
- return { kind: "flow_path", path: flowPath };
25710
+ return { kind: "e2e_test_path", path: flowPath };
25675
25711
  }
25676
25712
  function isResolvedAbsolute(value) {
25677
25713
  return typeof value === "string" && path8.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
@@ -26611,12 +26647,18 @@ function isResolvedAbsolute2(value) {
26611
26647
  return typeof value === "string" && path11.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
26612
26648
  }
26613
26649
  function namesValidFlow(args) {
26614
- const { project_root, flow_path, name } = args;
26650
+ let canonical;
26651
+ try {
26652
+ canonical = canonicalToolArgs("e2e-execute", args);
26653
+ } catch {
26654
+ return false;
26655
+ }
26656
+ const { project_root, e2e_test_path: testPath, name } = canonical;
26615
26657
  if (!isResolvedAbsolute2(project_root)) return false;
26616
26658
  if (name === void 0) {
26617
- return isResolvedAbsolute2(flow_path) && FLOW_FILE_NAME_PATTERN.test(path11.basename(flow_path));
26659
+ return isResolvedAbsolute2(testPath) && FLOW_FILE_NAME_PATTERN.test(path11.basename(testPath));
26618
26660
  }
26619
- return flow_path === void 0 && typeof name === "string" && FLOW_NAME_PATTERN.test(name);
26661
+ return testPath === void 0 && typeof name === "string" && FLOW_NAME_PATTERN.test(name);
26620
26662
  }
26621
26663
  function savedFlowProject(file) {
26622
26664
  if (!path11.isAbsolute(file)) return null;
@@ -26790,8 +26832,8 @@ function memberCollector(roots, opts) {
26790
26832
  `));
26791
26833
  const emit = (member, sent) => {
26792
26834
  members2.push(member);
26793
- const subject = member.role === "flow" ? member.canonical : member.key;
26794
- if (logging) log(printable(`[flow-files] ${member.role} ${subject}: ${sent}`));
26835
+ const [label, subject] = member.role === "flow" ? ["e2e test", member.canonical] : [member.role, member.key];
26836
+ if (logging) log(printable(`[e2e-files] ${label} ${subject}: ${sent}`));
26795
26837
  };
26796
26838
  async function flow(anchorDir, target, onlyPresent) {
26797
26839
  const key = flowMemberKey(anchorDir, target);
@@ -26957,7 +26999,7 @@ function recordedStep(args) {
26957
26999
  if (typeof text !== "string") return void 0;
26958
27000
  let parsed;
26959
27001
  try {
26960
- parsed = JSON.parse(text);
27002
+ parsed = canonicalToolArgs(command, JSON.parse(text));
26961
27003
  } catch {
26962
27004
  return void 0;
26963
27005
  }
@@ -26980,7 +27022,7 @@ async function collectStepMembers(args, opts, recordingDirFor = e2eDirFor) {
26980
27022
  const self = await collector.flow(path11.dirname(recording), path11.basename(recording));
26981
27023
  let runArgs = step.args;
26982
27024
  const named = nestedFlowTarget(runArgs);
26983
- if (named?.kind === "flow_path") {
27025
+ if (named?.kind === "e2e_test_path") {
26984
27026
  const stem = path11.basename(named.path, ".yaml");
26985
27027
  const base = path11.basename(named.path);
26986
27028
  const dir = path11.resolve(path11.dirname(named.path));
@@ -26989,7 +27031,7 @@ async function collectStepMembers(args, opts, recordingDirFor = e2eDirFor) {
26989
27031
  if (dirs.some((d) => path11.resolve(d) === dir)) {
26990
27032
  await collector.flow(path11.dirname(named.path), base);
26991
27033
  runArgs = { ...runArgs, name: stem };
26992
- delete runArgs.flow_path;
27034
+ delete runArgs.e2e_test_path;
26993
27035
  }
26994
27036
  }
26995
27037
  const target = nestedFlowTarget(runArgs);
@@ -27017,7 +27059,21 @@ async function nameToE2ePathForOlderServer(tool, fileInputs, args) {
27017
27059
  const picked = await pickE2eFile(target.paths);
27018
27060
  if (!picked.exists || picked.legacy) return args;
27019
27061
  const { name: _name, ...rest } = args;
27020
- return { ...rest, flow_path: picked.path };
27062
+ return { ...rest, e2e_test_path: picked.path };
27063
+ }
27064
+ function formerParamsForOlderServer(meta2, args) {
27065
+ const listed = meta2.inputSchema.properties;
27066
+ if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
27067
+ if (typeof listed !== "object" || listed === null) return args;
27068
+ const record2 = args;
27069
+ let out;
27070
+ for (const [former, current] of Object.entries(toolParamAliases(meta2.name))) {
27071
+ if (record2[current] === void 0 || current in listed || !(former in listed)) continue;
27072
+ out ??= { ...record2 };
27073
+ out[former] = out[current];
27074
+ delete out[current];
27075
+ }
27076
+ return out ?? args;
27021
27077
  }
27022
27078
  async function stepForOlderServer(args, listedId) {
27023
27079
  if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
@@ -27275,12 +27331,13 @@ function createToolsClient(options = {}) {
27275
27331
  async function callTool(name, args, opts) {
27276
27332
  opts?.signal?.throwIfAborted();
27277
27333
  const { url, token, remote } = await route();
27278
- let finalArgs = args;
27334
+ let finalArgs = canonicalToolArgs(name, args);
27279
27335
  const tools = await fetchTools({ signal: opts?.signal });
27280
27336
  const meta2 = findTool(tools, name);
27281
27337
  const olderServer = meta2 !== null && !tools.some((t) => t.name === canonicalToolId(meta2.name));
27282
27338
  if (meta2) {
27283
- finalArgs = await nameToE2ePathForOlderServer(meta2.name, meta2.fileInputs, args);
27339
+ finalArgs = await nameToE2ePathForOlderServer(meta2.name, meta2.fileInputs, finalArgs);
27340
+ finalArgs = formerParamsForOlderServer(meta2, finalArgs);
27284
27341
  }
27285
27342
  if (olderServer && canonicalToolId(meta2.name) === "e2e-add-step") {
27286
27343
  finalArgs = await stepForOlderServer(finalArgs, (tool) => findTool(tools, tool)?.name);
@@ -27308,7 +27365,7 @@ function createToolsClient(options = {}) {
27308
27365
  if (filesLogEnabled()) {
27309
27366
  for (const file of applied.written) {
27310
27367
  if (baselineDirs.includes(path12.dirname(file))) {
27311
- diagnose(`[flow-files] baseline ${file}: written`);
27368
+ diagnose(`[e2e-files] baseline ${file}: written`);
27312
27369
  }
27313
27370
  }
27314
27371
  }
@@ -28678,12 +28735,13 @@ function stepLabel(step) {
28678
28735
  }
28679
28736
  async function flowRunToMcpContent(result, ctx) {
28680
28737
  const blocks = [];
28738
+ const name = result.e2eTest ?? result.flow;
28681
28739
  if (result.executionPrerequisite) {
28682
28740
  blocks.push({ type: "text", text: `Prerequisite: ${result.executionPrerequisite}` });
28683
28741
  }
28684
28742
  blocks.push({
28685
28743
  type: "text",
28686
- text: `Running e2e test "${result.flow}"${result.device ? ` on ${result.device}` : ""} (${result.steps.length} steps)`
28744
+ text: `Running e2e test "${name}"${result.device ? ` on ${result.device}` : ""} (${result.steps.length} steps)`
28687
28745
  });
28688
28746
  if (typeof result.warning === "string")
28689
28747
  blocks.push({ type: "text", text: `\u26A0 ${result.warning}` });
@@ -28728,7 +28786,7 @@ async function flowRunToMcpContent(result, ctx) {
28728
28786
  text: `${result.ok ? "PASS" : "FAIL"} \u2014 ${result.passed ?? 0} passed, ${result.failed ?? 0} failed, ${result.errored ?? 0} errored, ${result.skipped ?? 0} skipped${note}${durationSuffix(result.durationMs)}`
28729
28787
  });
28730
28788
  } else {
28731
- blocks.push({ type: "text", text: `E2E test "${result.flow}" complete.` });
28789
+ blocks.push({ type: "text", text: `E2E test "${name}" complete.` });
28732
28790
  }
28733
28791
  return blocks;
28734
28792
  }
@@ -29339,7 +29397,7 @@ ${desc}` }];
29339
29397
  deviceId: getDeviceIdFromArgs(params.arguments)
29340
29398
  };
29341
29399
  let content;
29342
- if (canonicalToolId(params.name) === "e2e-execute" && result && typeof result === "object" && "flow" in result && "steps" in result) {
29400
+ if (canonicalToolId(params.name) === "e2e-execute" && result && typeof result === "object" && ("e2eTest" in result || "flow" in result) && "steps" in result) {
29343
29401
  content = await flowRunToMcpContent(result, ctx);
29344
29402
  } else if (params.name === "screenshot-diff" && isScreenshotDiffResult(result)) {
29345
29403
  content = await screenshotDiffToMcpContent(result, ctx);
@@ -223,14 +223,14 @@ export interface ArgentToolArgs {
223
223
  delayMs?: number;
224
224
  };
225
225
  "e2e-execute": {
226
- /** Name of a saved e2e test to run from `.argent/e2e`, or `.argent/flows` when it is not there (e.g. "settings-explore"). Omit when flow_path is set. */
226
+ /** Name of a saved e2e test to run from `.argent/e2e`, or `.argent/flows` when it is not there (e.g. "settings-explore"). Omit when e2e_test_path is set. */
227
227
  name?: string;
228
- /** Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved e2e test is read from `.argent/e2e/<name>.yaml`, else `.argent/flows/<name>.yaml`, under this root; with flow_path, the e2e test, its run: siblings, its script: paths and baselines all resolve beside the YAML instead, so pass the agent's cwd. A script still RUNS in this root whichever source was used. */
228
+ /** Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved e2e test is read from `.argent/e2e/<name>.yaml`, else `.argent/flows/<name>.yaml`, under this root; with e2e_test_path, the e2e test, its run: siblings, its script: paths and baselines all resolve beside the YAML instead, so pass the agent's cwd. A script still RUNS in this root whichever source was used. */
229
229
  project_root: string;
230
230
  /** Path to the e2e test .yaml as readable by the tool-server. Internal: the argent client derives it from project_root and name automatically; leave unset. */
231
- flow_file?: string;
231
+ e2e_test_file?: string;
232
232
  /** Omit when name is set. Absolute path to an e2e test .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file, its run: fragments and the snapshot baselines of each run, and the tool-server runs those copies. Keep run: fragments under project_root or beside the e2e test file. With updateBaselines, the client writes the new baselines when the run ends. The client also uploads each absolute .png or .yaml path that a tool: step takes as a file argument, when the file is under project_root or beside the e2e test file. A tool: e2e-execute step that names an e2e test with name and an absolute project_root without a .. segment runs: the client also uploads that e2e test and its own files. Over a link, the uploaded e2e tests must not have: script: steps; tool: steps that run an e2e test another way or record an e2e test; tool: steps that take a directory, an app or an output directory; tool: steps whose tool builds a file path from several arguments; tool: steps that name a relative path or a file other than .png or .yaml. Without a link, the tool-server reads the files in place and all step kinds run. */
233
- flow_path?: string;
233
+ e2e_test_path?: string;
234
234
  /** Device id to run against (iOS UDID, Android/Vega serial, Chromium id), as list-devices reports it. Auto-detected when omitted, but only when exactly one booted device matches (optionally narrowed by `platform`); with several booted the run fails and lists them, so pass this explicitly whenever more than one device is up. */
235
235
  device?: string;
236
236
  /** Restrict auto-detection to this platform when several devices are booted. `ios` selects local simulators only; pass `ios-remote` to select a remote one. `chromium` does more than filter: with no `device` it SELECTS the self-boot branch for a standalone e2e test - the runner boots an Electron instance from the `launch` step's chromium value and tears it down after the run (a single-key `launch: { chromium: … }` map selects it on its own, without this parameter). When it selects that branch it never falls back to device auto-detection (a fragment, or a standalone e2e test's launch map with no `chromium` key, still does), and the launch value must be a real Electron app path on the tool-server host: a bare-string `launch:` - what the recorder writes - holds an installed-app bundle id, so passing `chromium` for one fails the whole run with `Electron boot: path does not exist`. Edit the launch to `{ chromium: <app path> }` first. */
@@ -239,6 +239,10 @@ export interface ArgentToolArgs {
239
239
  updateBaselines?: boolean;
240
240
  /** Set to true to confirm the execution prerequisite has been met. Required (LLM path) when a fragment defines an executionPrerequisite. */
241
241
  prerequisiteAcknowledged?: boolean;
242
+ /** @deprecated Renamed to `e2e_test_path`. */
243
+ flow_path?: string;
244
+ /** @deprecated Renamed to `e2e_test_file`. */
245
+ flow_file?: string;
242
246
  };
243
247
  "e2e-finish-recording": {
244
248
  /** Name of the e2e test being recorded: the one passed to e2e-start-recording. */
@@ -247,14 +251,18 @@ export interface ArgentToolArgs {
247
251
  project_root: string;
248
252
  };
249
253
  "e2e-read-prerequisite": {
250
- /** Name of a saved e2e test to inspect from `.argent/e2e`, or `.argent/flows` when it is not there (e.g. "settings-explore"). Omit when flow_path is set. */
254
+ /** Name of a saved e2e test to inspect from `.argent/e2e`, or `.argent/flows` when it is not there (e.g. "settings-explore"). Omit when e2e_test_path is set. */
251
255
  name?: string;
252
- /** Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved e2e test is read from `.argent/e2e/<name>.yaml`, else `.argent/flows/<name>.yaml`, under this root; with flow_path, the prerequisite is read from that YAML instead, so pass the agent's cwd. */
256
+ /** Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved e2e test is read from `.argent/e2e/<name>.yaml`, else `.argent/flows/<name>.yaml`, under this root; with e2e_test_path, the prerequisite is read from that YAML instead, so pass the agent's cwd. */
253
257
  project_root: string;
254
258
  /** Path to the e2e test .yaml as readable by the tool-server. Internal: the argent client derives it from project_root and name automatically; leave unset. */
255
- flow_file?: string;
259
+ e2e_test_file?: string;
256
260
  /** Omit when name is set. Absolute path to an e2e test .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file and the tool-server reads the uploaded copy; without a link, the tool-server reads the file in place. Pass the path through the argent client; a raw path that the file-input boundary did not verify is rejected. Pass the same e2e test source here as to e2e-execute, so the prerequisite you read belongs to the e2e test that will run. */
261
+ e2e_test_path?: string;
262
+ /** @deprecated Renamed to `e2e_test_path`. */
257
263
  flow_path?: string;
264
+ /** @deprecated Renamed to `e2e_test_file`. */
265
+ flow_file?: string;
258
266
  };
259
267
  "e2e-start-recording": {
260
268
  /** Name for this e2e test (e.g. "settings-explore"): letters, digits, underscore and hyphen only. */