@swmansion/argent 0.29.1-next.21 → 0.29.1-next.23

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-cmds.mjs CHANGED
@@ -124,17 +124,17 @@ var require_visit = __commonJS({
124
124
  visit2.BREAK = BREAK;
125
125
  visit2.SKIP = SKIP;
126
126
  visit2.REMOVE = REMOVE;
127
- function visit_(key, node2, visitor, path24) {
128
- const ctrl = callVisitor(key, node2, visitor, path24);
127
+ function visit_(key, node2, visitor, path25) {
128
+ const ctrl = callVisitor(key, node2, visitor, path25);
129
129
  if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
130
- replaceNode(key, path24, ctrl);
131
- return visit_(key, ctrl, visitor, path24);
130
+ replaceNode(key, path25, ctrl);
131
+ return visit_(key, ctrl, visitor, path25);
132
132
  }
133
133
  if (typeof ctrl !== "symbol") {
134
134
  if (identity2.isCollection(node2)) {
135
- path24 = Object.freeze(path24.concat(node2));
135
+ path25 = Object.freeze(path25.concat(node2));
136
136
  for (let i2 = 0; i2 < node2.items.length; ++i2) {
137
- const ci = visit_(i2, node2.items[i2], visitor, path24);
137
+ const ci = visit_(i2, node2.items[i2], visitor, path25);
138
138
  if (typeof ci === "number")
139
139
  i2 = ci - 1;
140
140
  else if (ci === BREAK)
@@ -145,13 +145,13 @@ var require_visit = __commonJS({
145
145
  }
146
146
  }
147
147
  } else if (identity2.isPair(node2)) {
148
- path24 = Object.freeze(path24.concat(node2));
149
- const ck = visit_("key", node2.key, visitor, path24);
148
+ path25 = Object.freeze(path25.concat(node2));
149
+ const ck = visit_("key", node2.key, visitor, path25);
150
150
  if (ck === BREAK)
151
151
  return BREAK;
152
152
  else if (ck === REMOVE)
153
153
  node2.key = null;
154
- const cv = visit_("value", node2.value, visitor, path24);
154
+ const cv = visit_("value", node2.value, visitor, path25);
155
155
  if (cv === BREAK)
156
156
  return BREAK;
157
157
  else if (cv === REMOVE)
@@ -172,17 +172,17 @@ var require_visit = __commonJS({
172
172
  visitAsync.BREAK = BREAK;
173
173
  visitAsync.SKIP = SKIP;
174
174
  visitAsync.REMOVE = REMOVE;
175
- async function visitAsync_(key, node2, visitor, path24) {
176
- const ctrl = await callVisitor(key, node2, visitor, path24);
175
+ async function visitAsync_(key, node2, visitor, path25) {
176
+ const ctrl = await callVisitor(key, node2, visitor, path25);
177
177
  if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
178
- replaceNode(key, path24, ctrl);
179
- return visitAsync_(key, ctrl, visitor, path24);
178
+ replaceNode(key, path25, ctrl);
179
+ return visitAsync_(key, ctrl, visitor, path25);
180
180
  }
181
181
  if (typeof ctrl !== "symbol") {
182
182
  if (identity2.isCollection(node2)) {
183
- path24 = Object.freeze(path24.concat(node2));
183
+ path25 = Object.freeze(path25.concat(node2));
184
184
  for (let i2 = 0; i2 < node2.items.length; ++i2) {
185
- const ci = await visitAsync_(i2, node2.items[i2], visitor, path24);
185
+ const ci = await visitAsync_(i2, node2.items[i2], visitor, path25);
186
186
  if (typeof ci === "number")
187
187
  i2 = ci - 1;
188
188
  else if (ci === BREAK)
@@ -193,13 +193,13 @@ var require_visit = __commonJS({
193
193
  }
194
194
  }
195
195
  } else if (identity2.isPair(node2)) {
196
- path24 = Object.freeze(path24.concat(node2));
197
- const ck = await visitAsync_("key", node2.key, visitor, path24);
196
+ path25 = Object.freeze(path25.concat(node2));
197
+ const ck = await visitAsync_("key", node2.key, visitor, path25);
198
198
  if (ck === BREAK)
199
199
  return BREAK;
200
200
  else if (ck === REMOVE)
201
201
  node2.key = null;
202
- const cv = await visitAsync_("value", node2.value, visitor, path24);
202
+ const cv = await visitAsync_("value", node2.value, visitor, path25);
203
203
  if (cv === BREAK)
204
204
  return BREAK;
205
205
  else if (cv === REMOVE)
@@ -226,23 +226,23 @@ var require_visit = __commonJS({
226
226
  }
227
227
  return visitor;
228
228
  }
229
- function callVisitor(key, node2, visitor, path24) {
229
+ function callVisitor(key, node2, visitor, path25) {
230
230
  if (typeof visitor === "function")
231
- return visitor(key, node2, path24);
231
+ return visitor(key, node2, path25);
232
232
  if (identity2.isMap(node2))
233
- return visitor.Map?.(key, node2, path24);
233
+ return visitor.Map?.(key, node2, path25);
234
234
  if (identity2.isSeq(node2))
235
- return visitor.Seq?.(key, node2, path24);
235
+ return visitor.Seq?.(key, node2, path25);
236
236
  if (identity2.isPair(node2))
237
- return visitor.Pair?.(key, node2, path24);
237
+ return visitor.Pair?.(key, node2, path25);
238
238
  if (identity2.isScalar(node2))
239
- return visitor.Scalar?.(key, node2, path24);
239
+ return visitor.Scalar?.(key, node2, path25);
240
240
  if (identity2.isAlias(node2))
241
- return visitor.Alias?.(key, node2, path24);
241
+ return visitor.Alias?.(key, node2, path25);
242
242
  return void 0;
243
243
  }
244
- function replaceNode(key, path24, node2) {
245
- const parent = path24[path24.length - 1];
244
+ function replaceNode(key, path25, node2) {
245
+ const parent = path25[path25.length - 1];
246
246
  if (identity2.isCollection(parent)) {
247
247
  parent.items[key] = node2;
248
248
  } else if (identity2.isPair(parent)) {
@@ -854,10 +854,10 @@ var require_Collection = __commonJS({
854
854
  var createNode = require_createNode();
855
855
  var identity2 = require_identity();
856
856
  var Node = require_Node();
857
- function collectionFromPath(schema, path24, value) {
857
+ function collectionFromPath(schema, path25, value) {
858
858
  let v = value;
859
- for (let i2 = path24.length - 1; i2 >= 0; --i2) {
860
- const k = path24[i2];
859
+ for (let i2 = path25.length - 1; i2 >= 0; --i2) {
860
+ const k = path25[i2];
861
861
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
862
862
  const a2 = [];
863
863
  a2[k] = v;
@@ -876,7 +876,7 @@ var require_Collection = __commonJS({
876
876
  sourceObjects: /* @__PURE__ */ new Map()
877
877
  });
878
878
  }
879
- var isEmptyPath = (path24) => path24 == null || typeof path24 === "object" && !!path24[Symbol.iterator]().next().done;
879
+ var isEmptyPath = (path25) => path25 == null || typeof path25 === "object" && !!path25[Symbol.iterator]().next().done;
880
880
  var Collection = class extends Node.NodeBase {
881
881
  constructor(type, schema) {
882
882
  super(type);
@@ -906,11 +906,11 @@ var require_Collection = __commonJS({
906
906
  * be a Pair instance or a `{ key, value }` object, which may not have a key
907
907
  * that already exists in the map.
908
908
  */
909
- addIn(path24, value) {
910
- if (isEmptyPath(path24))
909
+ addIn(path25, value) {
910
+ if (isEmptyPath(path25))
911
911
  this.add(value);
912
912
  else {
913
- const [key, ...rest] = path24;
913
+ const [key, ...rest] = path25;
914
914
  const node2 = this.get(key, true);
915
915
  if (identity2.isCollection(node2))
916
916
  node2.addIn(rest, value);
@@ -924,8 +924,8 @@ var require_Collection = __commonJS({
924
924
  * Removes a value from the collection.
925
925
  * @returns `true` if the item was found and removed.
926
926
  */
927
- deleteIn(path24) {
928
- const [key, ...rest] = path24;
927
+ deleteIn(path25) {
928
+ const [key, ...rest] = path25;
929
929
  if (rest.length === 0)
930
930
  return this.delete(key);
931
931
  const node2 = this.get(key, true);
@@ -939,8 +939,8 @@ var require_Collection = __commonJS({
939
939
  * scalar values from their surrounding node; to disable set `keepScalar` to
940
940
  * `true` (collections are always returned intact).
941
941
  */
942
- getIn(path24, keepScalar) {
943
- const [key, ...rest] = path24;
942
+ getIn(path25, keepScalar) {
943
+ const [key, ...rest] = path25;
944
944
  const node2 = this.get(key, true);
945
945
  if (rest.length === 0)
946
946
  return !keepScalar && identity2.isScalar(node2) ? node2.value : node2;
@@ -958,8 +958,8 @@ var require_Collection = __commonJS({
958
958
  /**
959
959
  * Checks if the collection includes a value with the key `key`.
960
960
  */
961
- hasIn(path24) {
962
- const [key, ...rest] = path24;
961
+ hasIn(path25) {
962
+ const [key, ...rest] = path25;
963
963
  if (rest.length === 0)
964
964
  return this.has(key);
965
965
  const node2 = this.get(key, true);
@@ -969,8 +969,8 @@ var require_Collection = __commonJS({
969
969
  * Sets a value in this collection. For `!!set`, `value` needs to be a
970
970
  * boolean to add/remove the item from the set.
971
971
  */
972
- setIn(path24, value) {
973
- const [key, ...rest] = path24;
972
+ setIn(path25, value) {
973
+ const [key, ...rest] = path25;
974
974
  if (rest.length === 0) {
975
975
  this.set(key, value);
976
976
  } else {
@@ -1650,8 +1650,8 @@ ${ctx.indent}`;
1650
1650
  const vs0 = valueStr[0];
1651
1651
  const nl0 = valueStr.indexOf("\n");
1652
1652
  const hasNewline = nl0 !== -1;
1653
- const flow2 = ctx.inFlow ?? value.flow ?? value.items.length === 0;
1654
- if (hasNewline || !flow2) {
1653
+ const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0;
1654
+ if (hasNewline || !flow) {
1655
1655
  let hasPropsLine = false;
1656
1656
  if (hasNewline && (vs0 === "&" || vs0 === "!")) {
1657
1657
  let sp0 = valueStr.indexOf(" ");
@@ -1877,8 +1877,8 @@ var require_stringifyCollection = __commonJS({
1877
1877
  var stringify = require_stringify();
1878
1878
  var stringifyComment = require_stringifyComment();
1879
1879
  function stringifyCollection(collection, ctx, options) {
1880
- const flow2 = ctx.inFlow ?? collection.flow;
1881
- const stringify2 = flow2 ? stringifyFlowCollection : stringifyBlockCollection;
1880
+ const flow = ctx.inFlow ?? collection.flow;
1881
+ const stringify2 = flow ? stringifyFlowCollection : stringifyBlockCollection;
1882
1882
  return stringify2(collection, ctx, options);
1883
1883
  }
1884
1884
  function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
@@ -3485,9 +3485,9 @@ var require_Document = __commonJS({
3485
3485
  this.contents.add(value);
3486
3486
  }
3487
3487
  /** Adds a value to the document. */
3488
- addIn(path24, value) {
3488
+ addIn(path25, value) {
3489
3489
  if (assertCollection(this.contents))
3490
- this.contents.addIn(path24, value);
3490
+ this.contents.addIn(path25, value);
3491
3491
  }
3492
3492
  /**
3493
3493
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3521,7 +3521,7 @@ var require_Document = __commonJS({
3521
3521
  options = replacer;
3522
3522
  replacer = void 0;
3523
3523
  }
3524
- const { aliasDuplicateObjects, anchorPrefix, flow: flow2, keepUndefined, onTagObj, tag } = options ?? {};
3524
+ const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options ?? {};
3525
3525
  const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(
3526
3526
  this,
3527
3527
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -3537,7 +3537,7 @@ var require_Document = __commonJS({
3537
3537
  sourceObjects
3538
3538
  };
3539
3539
  const node2 = createNode.createNode(value, tag, ctx);
3540
- if (flow2 && identity2.isCollection(node2))
3540
+ if (flow && identity2.isCollection(node2))
3541
3541
  node2.flow = true;
3542
3542
  setAnchors();
3543
3543
  return node2;
@@ -3562,14 +3562,14 @@ var require_Document = __commonJS({
3562
3562
  * Removes a value from the document.
3563
3563
  * @returns `true` if the item was found and removed.
3564
3564
  */
3565
- deleteIn(path24) {
3566
- if (Collection.isEmptyPath(path24)) {
3565
+ deleteIn(path25) {
3566
+ if (Collection.isEmptyPath(path25)) {
3567
3567
  if (this.contents == null)
3568
3568
  return false;
3569
3569
  this.contents = null;
3570
3570
  return true;
3571
3571
  }
3572
- return assertCollection(this.contents) ? this.contents.deleteIn(path24) : false;
3572
+ return assertCollection(this.contents) ? this.contents.deleteIn(path25) : false;
3573
3573
  }
3574
3574
  /**
3575
3575
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3584,10 +3584,10 @@ var require_Document = __commonJS({
3584
3584
  * scalar values from their surrounding node; to disable set `keepScalar` to
3585
3585
  * `true` (collections are always returned intact).
3586
3586
  */
3587
- getIn(path24, keepScalar) {
3588
- if (Collection.isEmptyPath(path24))
3587
+ getIn(path25, keepScalar) {
3588
+ if (Collection.isEmptyPath(path25))
3589
3589
  return !keepScalar && identity2.isScalar(this.contents) ? this.contents.value : this.contents;
3590
- return identity2.isCollection(this.contents) ? this.contents.getIn(path24, keepScalar) : void 0;
3590
+ return identity2.isCollection(this.contents) ? this.contents.getIn(path25, keepScalar) : void 0;
3591
3591
  }
3592
3592
  /**
3593
3593
  * Checks if the document includes a value with the key `key`.
@@ -3598,10 +3598,10 @@ var require_Document = __commonJS({
3598
3598
  /**
3599
3599
  * Checks if the document includes a value at `path`.
3600
3600
  */
3601
- hasIn(path24) {
3602
- if (Collection.isEmptyPath(path24))
3601
+ hasIn(path25) {
3602
+ if (Collection.isEmptyPath(path25))
3603
3603
  return this.contents !== void 0;
3604
- return identity2.isCollection(this.contents) ? this.contents.hasIn(path24) : false;
3604
+ return identity2.isCollection(this.contents) ? this.contents.hasIn(path25) : false;
3605
3605
  }
3606
3606
  /**
3607
3607
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3618,13 +3618,13 @@ var require_Document = __commonJS({
3618
3618
  * Sets a value in this document. For `!!set`, `value` needs to be a
3619
3619
  * boolean to add/remove the item from the set.
3620
3620
  */
3621
- setIn(path24, value) {
3622
- if (Collection.isEmptyPath(path24)) {
3621
+ setIn(path25, value) {
3622
+ if (Collection.isEmptyPath(path25)) {
3623
3623
  this.contents = value;
3624
3624
  } else if (this.contents == null) {
3625
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path24), value);
3625
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path25), value);
3626
3626
  } else if (assertCollection(this.contents)) {
3627
- this.contents.setIn(path24, value);
3627
+ this.contents.setIn(path25, value);
3628
3628
  }
3629
3629
  }
3630
3630
  /**
@@ -3785,7 +3785,7 @@ ${pointer}
3785
3785
  var require_resolve_props = __commonJS({
3786
3786
  "../../node_modules/yaml/dist/compose/resolve-props.js"(exports) {
3787
3787
  "use strict";
3788
- function resolveProps(tokens, { flow: flow2, indicator, next, offset, onError, parentIndent, startOnNewline }) {
3788
+ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
3789
3789
  let spaceBefore = false;
3790
3790
  let atNewline = startOnNewline;
3791
3791
  let hasSpace = startOnNewline;
@@ -3814,7 +3814,7 @@ var require_resolve_props = __commonJS({
3814
3814
  }
3815
3815
  switch (token.type) {
3816
3816
  case "space":
3817
- if (!flow2 && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
3817
+ if (!flow && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
3818
3818
  tab = token;
3819
3819
  }
3820
3820
  hasSpace = true;
@@ -3870,15 +3870,15 @@ var require_resolve_props = __commonJS({
3870
3870
  if (anchor2 || tag)
3871
3871
  onError(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`);
3872
3872
  if (found)
3873
- onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow2 ?? "collection"}`);
3873
+ onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow ?? "collection"}`);
3874
3874
  found = token;
3875
3875
  atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind";
3876
3876
  hasSpace = false;
3877
3877
  break;
3878
3878
  case "comma":
3879
- if (flow2) {
3879
+ if (flow) {
3880
3880
  if (comma)
3881
- onError(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow2}`);
3881
+ onError(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow}`);
3882
3882
  comma = token;
3883
3883
  atNewline = false;
3884
3884
  hasSpace = false;
@@ -5585,9 +5585,9 @@ var require_cst_visit = __commonJS({
5585
5585
  visit2.BREAK = BREAK;
5586
5586
  visit2.SKIP = SKIP;
5587
5587
  visit2.REMOVE = REMOVE;
5588
- visit2.itemAtPath = (cst, path24) => {
5588
+ visit2.itemAtPath = (cst, path25) => {
5589
5589
  let item = cst;
5590
- for (const [field, index] of path24) {
5590
+ for (const [field, index] of path25) {
5591
5591
  const tok = item?.[field];
5592
5592
  if (tok && "items" in tok) {
5593
5593
  item = tok.items[index];
@@ -5596,23 +5596,23 @@ var require_cst_visit = __commonJS({
5596
5596
  }
5597
5597
  return item;
5598
5598
  };
5599
- visit2.parentCollection = (cst, path24) => {
5600
- const parent = visit2.itemAtPath(cst, path24.slice(0, -1));
5601
- const field = path24[path24.length - 1][0];
5599
+ visit2.parentCollection = (cst, path25) => {
5600
+ const parent = visit2.itemAtPath(cst, path25.slice(0, -1));
5601
+ const field = path25[path25.length - 1][0];
5602
5602
  const coll = parent?.[field];
5603
5603
  if (coll && "items" in coll)
5604
5604
  return coll;
5605
5605
  throw new Error("Parent collection not found");
5606
5606
  };
5607
- function _visit(path24, item, visitor) {
5608
- let ctrl = visitor(item, path24);
5607
+ function _visit(path25, item, visitor) {
5608
+ let ctrl = visitor(item, path25);
5609
5609
  if (typeof ctrl === "symbol")
5610
5610
  return ctrl;
5611
5611
  for (const field of ["key", "value"]) {
5612
5612
  const token = item[field];
5613
5613
  if (token && "items" in token) {
5614
5614
  for (let i2 = 0; i2 < token.items.length; ++i2) {
5615
- const ci = _visit(Object.freeze(path24.concat([[field, i2]])), token.items[i2], visitor);
5615
+ const ci = _visit(Object.freeze(path25.concat([[field, i2]])), token.items[i2], visitor);
5616
5616
  if (typeof ci === "number")
5617
5617
  i2 = ci - 1;
5618
5618
  else if (ci === BREAK)
@@ -5623,10 +5623,10 @@ var require_cst_visit = __commonJS({
5623
5623
  }
5624
5624
  }
5625
5625
  if (typeof ctrl === "function" && field === "key")
5626
- ctrl = ctrl(item, path24);
5626
+ ctrl = ctrl(item, path25);
5627
5627
  }
5628
5628
  }
5629
- return typeof ctrl === "function" ? ctrl(item, path24) : ctrl;
5629
+ return typeof ctrl === "function" ? ctrl(item, path25) : ctrl;
5630
5630
  }
5631
5631
  exports.visit = visit2;
5632
5632
  }
@@ -6928,14 +6928,14 @@ var require_parser = __commonJS({
6928
6928
  case "scalar":
6929
6929
  case "single-quoted-scalar":
6930
6930
  case "double-quoted-scalar": {
6931
- const fs18 = this.flowScalar(this.type);
6931
+ const fs19 = this.flowScalar(this.type);
6932
6932
  if (atNextItem || it.value) {
6933
- map2.items.push({ start, key: fs18, sep: [] });
6933
+ map2.items.push({ start, key: fs19, sep: [] });
6934
6934
  this.onKeyLine = true;
6935
6935
  } else if (it.sep) {
6936
- this.stack.push(fs18);
6936
+ this.stack.push(fs19);
6937
6937
  } else {
6938
- Object.assign(it, { key: fs18, sep: [] });
6938
+ Object.assign(it, { key: fs19, sep: [] });
6939
6939
  this.onKeyLine = true;
6940
6940
  }
6941
6941
  return;
@@ -7063,13 +7063,13 @@ var require_parser = __commonJS({
7063
7063
  case "scalar":
7064
7064
  case "single-quoted-scalar":
7065
7065
  case "double-quoted-scalar": {
7066
- const fs18 = this.flowScalar(this.type);
7066
+ const fs19 = this.flowScalar(this.type);
7067
7067
  if (!it || it.value)
7068
- fc.items.push({ start: [], key: fs18, sep: [] });
7068
+ fc.items.push({ start: [], key: fs19, sep: [] });
7069
7069
  else if (it.sep)
7070
- this.stack.push(fs18);
7070
+ this.stack.push(fs19);
7071
7071
  else
7072
- Object.assign(it, { key: fs18, sep: [] });
7072
+ Object.assign(it, { key: fs19, sep: [] });
7073
7073
  return;
7074
7074
  }
7075
7075
  case "flow-map-end":
@@ -8916,8 +8916,8 @@ var require_src = __commonJS({
8916
8916
  });
8917
8917
 
8918
8918
  // ../argent-cli/src/run.ts
8919
- import * as fs11 from "node:fs";
8920
- import * as path16 from "node:path";
8919
+ import * as fs12 from "node:fs";
8920
+ import * as path17 from "node:path";
8921
8921
 
8922
8922
  // ../argent-tools-client/src/launcher.ts
8923
8923
  import * as net from "node:net";
@@ -8958,7 +8958,7 @@ function generateAuthToken() {
8958
8958
  return generateToken();
8959
8959
  }
8960
8960
  function findFreePort() {
8961
- return new Promise((resolve12, reject) => {
8961
+ return new Promise((resolve13, reject) => {
8962
8962
  const srv = net.createServer();
8963
8963
  srv.listen(0, "127.0.0.1", () => {
8964
8964
  const addr = srv.address();
@@ -8969,7 +8969,7 @@ function findFreePort() {
8969
8969
  const port = addr.port;
8970
8970
  srv.close((err) => {
8971
8971
  if (err) reject(err);
8972
- else resolve12(port);
8972
+ else resolve13(port);
8973
8973
  });
8974
8974
  });
8975
8975
  srv.on("error", reject);
@@ -9070,7 +9070,7 @@ function killSpawnedChild(child, pid) {
9070
9070
  }
9071
9071
  }
9072
9072
  function spawnToolsServer(paths, port, options = {}) {
9073
- return new Promise((resolve12, reject) => {
9073
+ return new Promise((resolve13, reject) => {
9074
9074
  let logFd;
9075
9075
  try {
9076
9076
  fs.mkdirSync(STATE_DIR, { recursive: true });
@@ -9116,7 +9116,7 @@ function spawnToolsServer(paths, port, options = {}) {
9116
9116
  rl.close();
9117
9117
  child.stdout?.resume();
9118
9118
  child.stdout?.unref?.();
9119
- settle2(() => resolve12({ port: actualPort, pid }));
9119
+ settle2(() => resolve13({ port: actualPort, pid }));
9120
9120
  }
9121
9121
  });
9122
9122
  child.on("error", (err) => {
@@ -9430,10 +9430,11 @@ async function ensureToolsServer(paths) {
9430
9430
  }
9431
9431
 
9432
9432
  // ../argent-tools-client/src/tools-client.ts
9433
- import * as path6 from "node:path";
9433
+ import * as path7 from "node:path";
9434
9434
 
9435
9435
  // ../registry/src/types.ts
9436
9436
  var LINKED_CALL_HEADER = "x-argent-linked";
9437
+ var E2E_DIR_CLIENT_HEADER = "x-argent-e2e-dir";
9437
9438
 
9438
9439
  // ../registry/src/artifacts.ts
9439
9440
  import { stat } from "node:fs/promises";
@@ -9471,19 +9472,98 @@ function toolStepFiles(specs, args) {
9471
9472
  }
9472
9473
  return files;
9473
9474
  }
9474
- function isClientFileArgument({ spec, path: path24 }) {
9475
- return spec.kind === "file" && spec.path === `\${${spec.target}}` && path24.startsWith("/") && hasToolFileExtension(path24);
9475
+ function isClientFileArgument({ spec, path: path25 }) {
9476
+ return spec.kind === "file" && spec.path === `\${${spec.target}}` && path25.startsWith("/") && hasToolFileExtension(path25);
9476
9477
  }
9477
9478
 
9478
9479
  // ../registry/src/flow-file-refs.ts
9480
+ import * as fs3 from "node:fs/promises";
9481
+ import * as path3 from "node:path";
9482
+
9483
+ // ../registry/src/e2e-dirs.ts
9479
9484
  import * as fs2 from "node:fs/promises";
9480
9485
  import * as path2 from "node:path";
9486
+ var E2E_DIR = path2.join(".argent", "e2e");
9487
+ var LEGACY_E2E_DIRS = Object.freeze([path2.join(".argent", "flows")]);
9488
+ var E2E_DIRS = Object.freeze([E2E_DIR, ...LEGACY_E2E_DIRS]);
9489
+ function e2eDirFor(projectRoot) {
9490
+ return path2.join(projectRoot, E2E_DIR);
9491
+ }
9492
+ function e2eDirsFor(projectRoot) {
9493
+ return E2E_DIRS.map((dir) => path2.join(projectRoot, dir));
9494
+ }
9495
+ function e2eFileCandidates(projectRoot, name) {
9496
+ return e2eDirsFor(projectRoot).map((dir) => path2.join(dir, `${name}.yaml`));
9497
+ }
9498
+ async function exists(file2) {
9499
+ return fs2.stat(file2).then(
9500
+ () => true,
9501
+ () => false
9502
+ );
9503
+ }
9504
+ async function pickE2eFile(candidates) {
9505
+ for (let i2 = 0; i2 < candidates.length; i2++) {
9506
+ if (!await exists(candidates[i2])) continue;
9507
+ let shadowed;
9508
+ for (const later of candidates.slice(i2 + 1)) {
9509
+ if (await exists(later)) {
9510
+ shadowed = later;
9511
+ break;
9512
+ }
9513
+ }
9514
+ return {
9515
+ path: candidates[i2],
9516
+ exists: true,
9517
+ legacy: i2 > 0,
9518
+ ...shadowed === void 0 ? {} : { shadowed }
9519
+ };
9520
+ }
9521
+ return { path: candidates[0], exists: false, legacy: false };
9522
+ }
9523
+ function resolveE2eFile(projectRoot, name) {
9524
+ return pickE2eFile(e2eFileCandidates(projectRoot, name));
9525
+ }
9526
+ function e2eShadowWarning(used, shadowed) {
9527
+ return `${shadowed} is not used: ${used} has the same name and is read first.`;
9528
+ }
9529
+ var E2E_DIR_NAMES = E2E_DIRS.map((dir) => path2.basename(dir));
9530
+ function e2eDirProject(dir) {
9531
+ const trimmed = dir.length > 1 ? dir.replace(/[\\/]+$/, "") : dir;
9532
+ const argent = path2.dirname(trimmed);
9533
+ if (!E2E_DIR_NAMES.includes(path2.basename(trimmed)) || path2.basename(argent) !== ".argent") {
9534
+ return null;
9535
+ }
9536
+ return path2.dirname(argent);
9537
+ }
9538
+ function e2eRunFallbackDirs(anchorDir, target) {
9539
+ if (target.includes("/") || target.includes("\\")) return [];
9540
+ const project = e2eDirProject(anchorDir);
9541
+ if (project === null) return [];
9542
+ const anchor2 = path2.resolve(anchorDir);
9543
+ return e2eDirsFor(project).filter((dir) => path2.resolve(dir) !== anchor2);
9544
+ }
9545
+
9546
+ // ../registry/src/tool-ids.ts
9547
+ var TOOL_ID_ALIASES = Object.freeze({
9548
+ "flow-start-recording": "e2e-start-recording",
9549
+ "flow-add-step": "e2e-add-step",
9550
+ "flow-add-echo": "e2e-add-echo",
9551
+ "flow-add-script": "e2e-add-script",
9552
+ "flow-finish-recording": "e2e-finish-recording",
9553
+ "flow-read-prerequisite": "e2e-read-prerequisite",
9554
+ "flow-execute": "e2e-execute"
9555
+ });
9556
+ function canonicalToolId(id) {
9557
+ return Object.hasOwn(TOOL_ID_ALIASES, id) ? TOOL_ID_ALIASES[id] : id;
9558
+ }
9559
+
9560
+ // ../registry/src/flow-file-refs.ts
9481
9561
  async function canonicalFlowPath(p) {
9482
9562
  try {
9483
- return await fs2.realpath(p);
9563
+ return await fs3.realpath(p);
9484
9564
  } catch {
9485
9565
  try {
9486
- return path2.join(await fs2.realpath(path2.dirname(p)), path2.basename(p));
9566
+ return path3.join(await fs3.realpath(path3.dirname(p)), path3.basename(p));
9487
9567
  } catch {
9488
9568
  return p;
9489
9569
  }
@@ -9492,7 +9572,7 @@ async function canonicalFlowPath(p) {
9492
9572
  function completeRunExtension(value) {
9493
9573
  if (value.endsWith(".yaml")) return value;
9494
9574
  const candidate = `${value}.yaml`;
9495
- return FLOW_FILE_NAME_PATTERN.test(path2.posix.basename(candidate)) ? candidate : value;
9575
+ return FLOW_FILE_NAME_PATTERN.test(path3.posix.basename(candidate)) ? candidate : value;
9496
9576
  }
9497
9577
  var MAX_RUN_DEPTH = 20;
9498
9578
  var MAX_BLOCK_NESTING = 64;
@@ -9511,16 +9591,16 @@ function collectFlowRequests(doc) {
9511
9591
  for (const step of steps) {
9512
9592
  if (!isRecord(step)) continue;
9513
9593
  const run2 = step.run;
9514
- if (typeof run2 === "string" && !run2.includes("\\") && !path2.posix.isAbsolute(run2) && !/^[A-Za-z]:/.test(run2)) {
9594
+ if (typeof run2 === "string" && !run2.includes("\\") && !path3.posix.isAbsolute(run2) && !/^[A-Za-z]:/.test(run2)) {
9515
9595
  const target = completeRunExtension(run2);
9516
- if (FLOW_FILE_NAME_PATTERN.test(path2.posix.basename(target))) runTargets.add(target);
9596
+ if (FLOW_FILE_NAME_PATTERN.test(path3.posix.basename(target))) runTargets.add(target);
9517
9597
  }
9518
9598
  const snapshot = isRecord(step.snapshot) ? step.snapshot.name : step.snapshot;
9519
9599
  if (typeof snapshot === "string" && FLOW_NAME_PATTERN.test(snapshot)) snapshots.add(snapshot);
9520
9600
  if (typeof step.tool === "string") {
9521
9601
  const args = isRecord(step.args) ? step.args : {};
9522
9602
  toolSteps.push({ tool: step.tool, args });
9523
- const target = step.tool === "flow-execute" ? nestedFlowTarget(args) : void 0;
9603
+ const target = canonicalToolId(step.tool) === "e2e-execute" ? nestedFlowTarget(args) : void 0;
9524
9604
  if (target !== void 0) nested.push({ target, args });
9525
9605
  }
9526
9606
  visit2(step.steps, depth + 1);
@@ -9530,14 +9610,14 @@ function collectFlowRequests(doc) {
9530
9610
  return { runTargets: [...runTargets], snapshots: [...snapshots], toolSteps, nested };
9531
9611
  }
9532
9612
  function baselineKeyFor(canonicalPath, flowName) {
9533
- const stem = path2.basename(canonicalPath, ".yaml");
9613
+ const stem = path3.basename(canonicalPath, ".yaml");
9534
9614
  return FLOW_NAME_PATTERN.test(stem) ? stem : flowName;
9535
9615
  }
9536
9616
  function flowMemberKey(anchorDir, target) {
9537
9617
  return `${anchorDir}\0${target}`;
9538
9618
  }
9539
9619
  async function classifyOnDiskSpelling(dir, base, addressable = FLOW_FILE_NAME_PATTERN) {
9540
- const entries = await fs2.readdir(dir).catch(() => null);
9620
+ const entries = await fs3.readdir(dir).catch(() => null);
9541
9621
  if (entries === null || entries.includes(base)) return { state: "listed" };
9542
9622
  const actual = entries.find((entry) => entry.toLowerCase() === base.toLowerCase());
9543
9623
  if (actual === void 0) return { state: "absent" };
@@ -9549,19 +9629,15 @@ function nestedFlowTarget(args) {
9549
9629
  if (flowPath === void 0) {
9550
9630
  if (typeof name !== "string" || !FLOW_NAME_PATTERN.test(name)) return void 0;
9551
9631
  if (!isResolvedAbsolute(projectRoot)) return void 0;
9552
- return {
9553
- kind: "name",
9554
- projectRoot,
9555
- name,
9556
- path: path2.join(projectRoot, ".argent", "flows", `${name}.yaml`)
9557
- };
9632
+ const paths = e2eFileCandidates(projectRoot, name);
9633
+ return { kind: "name", projectRoot, name, path: paths[0], paths };
9558
9634
  }
9559
9635
  if (name !== void 0 || !isResolvedAbsolute(flowPath)) return void 0;
9560
- if (!FLOW_FILE_NAME_PATTERN.test(path2.basename(flowPath))) return void 0;
9636
+ if (!FLOW_FILE_NAME_PATTERN.test(path3.basename(flowPath))) return void 0;
9561
9637
  return { kind: "flow_path", path: flowPath };
9562
9638
  }
9563
9639
  function isResolvedAbsolute(value) {
9564
- return typeof value === "string" && path2.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
9640
+ return typeof value === "string" && path3.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
9565
9641
  }
9566
9642
 
9567
9643
  // ../registry/src/failure-codes.ts
@@ -10743,10 +10819,10 @@ function mergeDefs(...defs) {
10743
10819
  function cloneDef(schema) {
10744
10820
  return mergeDefs(schema._zod.def);
10745
10821
  }
10746
- function getElementAtPath(obj, path24) {
10747
- if (!path24)
10822
+ function getElementAtPath(obj, path25) {
10823
+ if (!path25)
10748
10824
  return obj;
10749
- return path24.reduce((acc, key) => acc?.[key], obj);
10825
+ return path25.reduce((acc, key) => acc?.[key], obj);
10750
10826
  }
10751
10827
  function promiseAllObject(promisesObj) {
10752
10828
  const keys = Object.keys(promisesObj);
@@ -11086,11 +11162,11 @@ function explicitlyAborted(x, startIndex = 0) {
11086
11162
  }
11087
11163
  return false;
11088
11164
  }
11089
- function prefixIssues(path24, issues) {
11165
+ function prefixIssues(path25, issues) {
11090
11166
  return issues.map((iss) => {
11091
11167
  var _a3;
11092
11168
  (_a3 = iss).path ?? (_a3.path = []);
11093
- iss.path.unshift(path24);
11169
+ iss.path.unshift(path25);
11094
11170
  return iss;
11095
11171
  });
11096
11172
  }
@@ -11552,16 +11628,16 @@ function flattenError(error63, mapper = (issue2) => issue2.message) {
11552
11628
  }
11553
11629
  function formatError(error63, mapper = (issue2) => issue2.message) {
11554
11630
  const fieldErrors = { _errors: [] };
11555
- const processError = (error64, path24 = []) => {
11631
+ const processError = (error64, path25 = []) => {
11556
11632
  for (const issue2 of error64.issues) {
11557
11633
  if (issue2.code === "invalid_union" && issue2.errors.length) {
11558
- issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
11634
+ issue2.errors.map((issues) => processError({ issues }, [...path25, ...issue2.path]));
11559
11635
  } else if (issue2.code === "invalid_key") {
11560
- processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11636
+ processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
11561
11637
  } else if (issue2.code === "invalid_element") {
11562
- processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11638
+ processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
11563
11639
  } else {
11564
- const fullpath = [...path24, ...issue2.path];
11640
+ const fullpath = [...path25, ...issue2.path];
11565
11641
  if (fullpath.length === 0) {
11566
11642
  fieldErrors._errors.push(mapper(issue2));
11567
11643
  } else {
@@ -11600,17 +11676,17 @@ function formatError(error63, mapper = (issue2) => issue2.message) {
11600
11676
  }
11601
11677
  function treeifyError(error63, mapper = (issue2) => issue2.message) {
11602
11678
  const result = { errors: [] };
11603
- const processError = (error64, path24 = []) => {
11679
+ const processError = (error64, path25 = []) => {
11604
11680
  var _a3;
11605
11681
  for (const issue2 of error64.issues) {
11606
11682
  if (issue2.code === "invalid_union" && issue2.errors.length) {
11607
- issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
11683
+ issue2.errors.map((issues) => processError({ issues }, [...path25, ...issue2.path]));
11608
11684
  } else if (issue2.code === "invalid_key") {
11609
- processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11685
+ processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
11610
11686
  } else if (issue2.code === "invalid_element") {
11611
- processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
11687
+ processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
11612
11688
  } else {
11613
- const fullpath = [...path24, ...issue2.path];
11689
+ const fullpath = [...path25, ...issue2.path];
11614
11690
  if (fullpath.length === 0) {
11615
11691
  result.errors.push(mapper(issue2));
11616
11692
  continue;
@@ -11649,8 +11725,8 @@ function treeifyError(error63, mapper = (issue2) => issue2.message) {
11649
11725
  }
11650
11726
  function toDotPath(_path) {
11651
11727
  const segs = [];
11652
- const path24 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11653
- for (const seg of path24) {
11728
+ const path25 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
11729
+ for (const seg of path25) {
11654
11730
  if (typeof seg === "number")
11655
11731
  segs.push(`[${seg}]`);
11656
11732
  else if (typeof seg === "symbol")
@@ -14993,7 +15069,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
14993
15069
  var NONE = 0;
14994
15070
  var ASSUMED = 1;
14995
15071
  var PROVEN = 2;
14996
- function isRecursive(inst, stack, resolve12) {
15072
+ function isRecursive(inst, stack, resolve13) {
14997
15073
  const cached3 = recursive.get(inst);
14998
15074
  if (cached3 !== void 0)
14999
15075
  return cached3 ? PROVEN : NONE;
@@ -15003,7 +15079,7 @@ function isRecursive(inst, stack, resolve12) {
15003
15079
  let result = NONE;
15004
15080
  const check2 = (child) => {
15005
15081
  if (result !== PROVEN && child?._zod) {
15006
- const answer = isRecursive(child, stack, resolve12);
15082
+ const answer = isRecursive(child, stack, resolve13);
15007
15083
  if (answer > result)
15008
15084
  result = answer;
15009
15085
  }
@@ -15014,7 +15090,7 @@ function isRecursive(inst, stack, resolve12) {
15014
15090
  const desc = Object.getOwnPropertyDescriptor(sh, key);
15015
15091
  if (spread && !desc.enumerable)
15016
15092
  continue;
15017
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve12) : NONE;
15093
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve13) : NONE;
15018
15094
  if (child > answer)
15019
15095
  answer = child;
15020
15096
  }
@@ -15078,7 +15154,7 @@ function isRecursive(inst, stack, resolve12) {
15078
15154
  break;
15079
15155
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
15080
15156
  case "lazy": {
15081
- const inner = def._cachedInner ?? (resolve12 ? inst._zod.innerType : void 0);
15157
+ const inner = def._cachedInner ?? (resolve13 ? inst._zod.innerType : void 0);
15082
15158
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
15083
15159
  break;
15084
15160
  }
@@ -28788,13 +28864,13 @@ function resolveRef(ref, ctx) {
28788
28864
  if (!ref.startsWith("#")) {
28789
28865
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
28790
28866
  }
28791
- const path24 = ref.slice(1).split("/").filter(Boolean);
28792
- if (path24.length === 0) {
28867
+ const path25 = ref.slice(1).split("/").filter(Boolean);
28868
+ if (path25.length === 0) {
28793
28869
  return ctx.rootSchema;
28794
28870
  }
28795
28871
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
28796
- if (path24[0] === defsKey) {
28797
- const key = path24[1] === void 0 ? void 0 : decodeJSONPointerSegment(path24[1]);
28872
+ if (path25[0] === defsKey) {
28873
+ const key = path25[1] === void 0 ? void 0 : decodeJSONPointerSegment(path25[1]);
28798
28874
  if (!key || !ctx.defs[key]) {
28799
28875
  throw new Error(`Reference not found: ${ref}`);
28800
28876
  }
@@ -29647,9 +29723,9 @@ function date4(params) {
29647
29723
  import { randomUUID as randomUUID2 } from "node:crypto";
29648
29724
  import { AsyncLocalStorage } from "node:async_hooks";
29649
29725
  var resolvedDuringInvocation = new AsyncLocalStorage();
29650
- function valueAtPath(root, path24) {
29726
+ function valueAtPath(root, path25) {
29651
29727
  let current = root;
29652
- for (const key of path24) {
29728
+ for (const key of path25) {
29653
29729
  if (current === null || typeof current !== "object") return void 0;
29654
29730
  if (!Object.hasOwn(current, key)) return void 0;
29655
29731
  current = current[key];
@@ -29707,11 +29783,11 @@ function describeParamIssues(error63, params) {
29707
29783
  }
29708
29784
 
29709
29785
  // ../argent-tools-client/src/link-config.ts
29710
- import * as path3 from "node:path";
29786
+ import * as path4 from "node:path";
29711
29787
  import { homedir as homedir2 } from "node:os";
29712
29788
  import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile2, unlink as unlink2, chmod as chmod2 } from "node:fs/promises";
29713
- var LINK_DIR = path3.join(homedir2(), ".argent");
29714
- var LINK_FILE = path3.join(LINK_DIR, "link.json");
29789
+ var LINK_DIR = path4.join(homedir2(), ".argent");
29790
+ var LINK_FILE = path4.join(LINK_DIR, "link.json");
29715
29791
  async function readLinkConfig() {
29716
29792
  try {
29717
29793
  const raw = await readFile2(LINK_FILE, "utf8");
@@ -29809,8 +29885,8 @@ function parseLinkTarget(input2) {
29809
29885
  const host = u3.hostname.startsWith("[") ? u3.hostname.slice(1, -1) : u3.hostname;
29810
29886
  if (!host) throw new Error(`URL "${input2}" is missing a host.`);
29811
29887
  const port = u3.port ? Number(u3.port) : u3.protocol === "https:" ? 443 : 80;
29812
- const path24 = u3.pathname === "/" ? "" : u3.pathname.replace(/\/+$/, "");
29813
- const url2 = `${u3.protocol}//${u3.host}${path24}`;
29888
+ const path25 = u3.pathname === "/" ? "" : u3.pathname.replace(/\/+$/, "");
29889
+ const url2 = `${u3.protocol}//${u3.host}${path25}`;
29814
29890
  const token = u3.username ? decodeURIComponent(u3.username) : void 0;
29815
29891
  return { url: url2, host, port, ...token ? { token } : {} };
29816
29892
  }
@@ -29826,22 +29902,22 @@ import {
29826
29902
  realpath as realpath2,
29827
29903
  rename as rename2,
29828
29904
  rm as rm2,
29829
- stat as stat2,
29905
+ stat as stat3,
29830
29906
  writeFile as writeFile3
29831
29907
  } from "node:fs/promises";
29832
29908
  import { constants, tmpdir } from "node:os";
29833
- import * as path4 from "node:path";
29909
+ import * as path5 from "node:path";
29834
29910
 
29835
29911
  // ../archive/src/index.ts
29836
29912
  import { execFile } from "node:child_process";
29837
29913
  import { rm, readdir as readdir3 } from "node:fs/promises";
29838
- import { basename as basename3, dirname as dirname3, join as join4, posix as posix2, resolve as resolve2, sep as sep2 } from "node:path";
29914
+ import { basename as basename4, dirname as dirname4, join as join5, posix as posix2, resolve as resolve3, sep as sep2 } from "node:path";
29839
29915
  import { promisify } from "node:util";
29840
29916
  var execFileAsync = promisify(execFile);
29841
29917
  var ArchiveError = class extends Error {
29842
29918
  };
29843
29919
  function createTarGzArgs(sourcePath, target) {
29844
- return ["-czf", target, "-C", dirname3(sourcePath), basename3(sourcePath)];
29920
+ return ["-czf", target, "-C", dirname4(sourcePath), basename4(sourcePath)];
29845
29921
  }
29846
29922
  async function createTarGzFile(sourcePath, tarPath) {
29847
29923
  try {
@@ -29863,8 +29939,8 @@ function isSafeTarMember(memberPath, destDir) {
29863
29939
  if (relative3 === ".." || relative3.startsWith("../") || relative3.split("/").includes("..")) {
29864
29940
  return false;
29865
29941
  }
29866
- const root = resolve2(destDir);
29867
- const resolved = resolve2(destDir, relative3);
29942
+ const root = resolve3(destDir);
29943
+ const resolved = resolve3(destDir, relative3);
29868
29944
  return resolved === root || resolved.startsWith(root + sep2);
29869
29945
  }
29870
29946
  async function listTarMembers(tarPath) {
@@ -29918,7 +29994,7 @@ async function assertSafeArchive(tarPath, destDir) {
29918
29994
  async function resolveMember(destDir, expectedName) {
29919
29995
  const entries = await readdir3(destDir);
29920
29996
  if (entries.includes(expectedName)) {
29921
- return join4(destDir, expectedName);
29997
+ return join5(destDir, expectedName);
29922
29998
  }
29923
29999
  const real = entries.filter((e) => !e.startsWith("._"));
29924
30000
  if (real.length !== 1) {
@@ -29926,7 +30002,7 @@ async function resolveMember(destDir, expectedName) {
29926
30002
  `Could not identify the extracted member (expected "${expectedName}", found ${real.length} entries).`
29927
30003
  );
29928
30004
  }
29929
- return join4(destDir, real[0]);
30005
+ return join5(destDir, real[0]);
29930
30006
  }
29931
30007
  async function safeExtractTarGz(tarPath, destDir, expectedName) {
29932
30008
  await assertSafeArchive(tarPath, destDir);
@@ -29964,6 +30040,16 @@ function interpolatePath(template, args) {
29964
30040
  });
29965
30041
  return missing ? null : out;
29966
30042
  }
30043
+ async function specPath(spec, args) {
30044
+ if (spec.kind !== "file" || !spec.paths?.length) return interpolatePath(spec.path, args);
30045
+ const candidates = [];
30046
+ for (const template of spec.paths) {
30047
+ const filled = interpolatePath(template, args);
30048
+ if (filled === null) return null;
30049
+ candidates.push(filled);
30050
+ }
30051
+ return (await pickE2eFile(candidates)).path;
30052
+ }
29967
30053
  var pendingArchives = /* @__PURE__ */ new Set();
29968
30054
  var ARCHIVE_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
29969
30055
  function removePendingArchives() {
@@ -29999,9 +30085,9 @@ function untrackArchive(archive) {
29999
30085
  process.removeListener("exit", removePendingArchives);
30000
30086
  }
30001
30087
  function sha256File(filePath) {
30002
- return new Promise((resolve12, reject) => {
30088
+ return new Promise((resolve13, reject) => {
30003
30089
  const hash2 = createHash2("sha256");
30004
- createReadStream(filePath).on("data", (chunk) => hash2.update(chunk)).on("end", () => resolve12(hash2.digest("hex"))).on("error", reject);
30090
+ createReadStream(filePath).on("data", (chunk) => hash2.update(chunk)).on("end", () => resolve13(hash2.digest("hex"))).on("error", reject);
30005
30091
  });
30006
30092
  }
30007
30093
  function toolServerError(text2) {
@@ -30028,7 +30114,7 @@ function uploadFailure(url2, res, text2, bytes) {
30028
30114
  });
30029
30115
  }
30030
30116
  async function uploadTar(tarPath, endpoint, signal) {
30031
- const { size } = await stat2(tarPath);
30117
+ const { size } = await stat3(tarPath);
30032
30118
  const init2 = {
30033
30119
  method: "POST",
30034
30120
  headers: {
@@ -30052,7 +30138,7 @@ async function uploadTar(tarPath, endpoint, signal) {
30052
30138
  return json2.uploadId;
30053
30139
  }
30054
30140
  async function uploadFile(sourcePath, endpoint, signal) {
30055
- const tarPath = path4.join(tmpdir(), `argent-upload-${randomUUID3()}.tar.gz`);
30141
+ const tarPath = path5.join(tmpdir(), `argent-upload-${randomUUID3()}.tar.gz`);
30056
30142
  trackArchive(tarPath);
30057
30143
  try {
30058
30144
  await createTarGzFile(await realpath2(sourcePath), tarPath);
@@ -30067,7 +30153,7 @@ async function uploadFile(sourcePath, endpoint, signal) {
30067
30153
  async function readFileInputWire(filePath, opts) {
30068
30154
  let st;
30069
30155
  try {
30070
- st = await stat2(filePath);
30156
+ st = await stat3(filePath);
30071
30157
  } catch {
30072
30158
  return null;
30073
30159
  }
@@ -30095,7 +30181,7 @@ async function prepareFileInputs(specs, args, opts) {
30095
30181
  for (const spec of specs) {
30096
30182
  if (spec.skipWhenSet && record2[spec.skipWhenSet] !== void 0) continue;
30097
30183
  if (spec.target in record2 && typeof record2[spec.target] !== "string") continue;
30098
- const filePath = interpolatePath(spec.path, record2);
30184
+ const filePath = await specPath(spec, record2);
30099
30185
  if (filePath === null) continue;
30100
30186
  if (spec.target in record2 && record2[spec.target] !== filePath) continue;
30101
30187
  const wire = { [FILE_INPUT_MARKER2]: true, path: filePath };
@@ -30113,13 +30199,13 @@ async function prepareFileInputs(specs, args, opts) {
30113
30199
  wire.members = await opts.collectStepMembers(record2, opts);
30114
30200
  }
30115
30201
  if (spec.kind === "tar-upload") {
30116
- const st = await stat2(filePath).catch(() => null);
30202
+ const st = await stat3(filePath).catch(() => null);
30117
30203
  if (st) {
30118
30204
  wire.size = st.size;
30119
30205
  wire.mtimeMs = st.mtimeMs;
30120
30206
  }
30121
30207
  if (opts.uploadEndpoint && st) {
30122
- process.stderr.write(`Uploading ${path4.basename(filePath)} to the remote tool-server...
30208
+ process.stderr.write(`Uploading ${path5.basename(filePath)} to the remote tool-server...
30123
30209
  `);
30124
30210
  Object.assign(wire, await uploadFile(filePath, opts.uploadEndpoint, opts.signal));
30125
30211
  }
@@ -30130,18 +30216,18 @@ async function prepareFileInputs(specs, args, opts) {
30130
30216
  return out ?? args;
30131
30217
  }
30132
30218
  function isAllowedClientFilePath(p) {
30133
- if (!path4.isAbsolute(p)) return false;
30219
+ if (!path5.isAbsolute(p)) return false;
30134
30220
  const segments = p.split(/[\\/]+/);
30135
30221
  if (segments.includes("..")) return false;
30136
30222
  const file2 = segments[segments.length - 1] ?? "";
30137
30223
  if (!FLOW_FILE_NAME_PATTERN.test(file2)) return false;
30138
- return segments[segments.length - 3] === ".argent" && segments[segments.length - 2] === "flows";
30224
+ return e2eDirProject(segments.slice(0, -1).join("/")) !== null;
30139
30225
  }
30140
30226
  function isClientFileDirective2(value) {
30141
30227
  return !!value && typeof value === "object" && value[CLIENT_FILE_MARKER2] === true && typeof value.path === "string" && typeof value.content === "string";
30142
30228
  }
30143
30229
  async function replaceFile(target, bytes, mode) {
30144
- const temp = path4.join(path4.dirname(target), `.baseline-${randomUUID3()}.tmp`);
30230
+ const temp = path5.join(path5.dirname(target), `.baseline-${randomUUID3()}.tmp`);
30145
30231
  try {
30146
30232
  await writeFile3(temp, bytes, { flag: "wx" });
30147
30233
  if (mode !== void 0) await chmod3(temp, mode & 511);
@@ -30152,27 +30238,27 @@ async function replaceFile(target, bytes, mode) {
30152
30238
  }
30153
30239
  }
30154
30240
  async function writeBaselineFile(file2, bytes, allowedDirs) {
30155
- if (!path4.isAbsolute(file2) || path4.normalize(file2) !== file2 || file2.split(/[\\/]/).includes("..") || !file2.endsWith(".png") || !allowedDirs.includes(path4.dirname(file2))) {
30241
+ if (!path5.isAbsolute(file2) || path5.normalize(file2) !== file2 || file2.split(/[\\/]/).includes("..") || !file2.endsWith(".png") || !allowedDirs.includes(path5.dirname(file2))) {
30156
30242
  return allowedDirs.length === 0 ? "this call writes no baselines" : `${file2} is not a baseline of this call (${allowedDirs.map((d) => `${d}/<name>.png`).join(", ")})`;
30157
30243
  }
30158
30244
  if (bytes.length > MAX_CONTENT_BYTES) {
30159
30245
  return `${file2}: the baseline is larger than the 32 MiB cap on a file this client writes`;
30160
30246
  }
30161
- const dir = path4.dirname(file2);
30247
+ const dir = path5.dirname(file2);
30162
30248
  await mkdir3(dir, { recursive: true });
30163
30249
  const link2 = await lstat(file2).catch(() => null);
30164
30250
  const real = link2 === null ? null : await realpath2(file2).catch(() => null);
30165
30251
  if (link2 !== null && real === null) return `${file2} is a symbolic link to a missing file`;
30166
30252
  if (real !== null) {
30167
30253
  if (!real.endsWith(".png")) return `${file2} links to a file that is not a PNG file`;
30168
- if (path4.dirname(real) !== await realpath2(dir)) {
30254
+ if (path5.dirname(real) !== await realpath2(dir)) {
30169
30255
  return `${file2} links outside its baseline directory`;
30170
30256
  }
30171
30257
  }
30172
- const existing = real === null ? null : await stat2(real);
30258
+ const existing = real === null ? null : await stat3(real);
30173
30259
  if (existing !== null && !existing.isFile()) return `${file2} is not a regular file`;
30174
30260
  await replaceFile(
30175
- real ?? path4.join(await realpath2(dir), path4.basename(file2)),
30261
+ real ?? path5.join(await realpath2(dir), path5.basename(file2)),
30176
30262
  bytes,
30177
30263
  existing?.mode
30178
30264
  );
@@ -30198,7 +30284,7 @@ async function applyClientFileDirectives(result, opts = {}) {
30198
30284
  if (isClientFileDirective2(value)) {
30199
30285
  if (!isAllowedClientFilePath(value.path)) return null;
30200
30286
  try {
30201
- await mkdir3(path4.dirname(value.path), { recursive: true });
30287
+ await mkdir3(path5.dirname(value.path), { recursive: true });
30202
30288
  await writeFile3(value.path, value.content, "utf8");
30203
30289
  written.push(value.path);
30204
30290
  return value.path;
@@ -30226,12 +30312,14 @@ async function applyClientFileDirectives(result, opts = {}) {
30226
30312
 
30227
30313
  // ../argent-tools-client/src/flow-files.ts
30228
30314
  var import_yaml = __toESM(require_dist(), 1);
30229
- import { readdir as readdir4, readFile as readFile4, realpath as realpath3, stat as stat3 } from "node:fs/promises";
30230
- import * as path5 from "node:path";
30315
+ import { readdir as readdir4, readFile as readFile4, realpath as realpath3, stat as stat4 } from "node:fs/promises";
30316
+ import * as path6 from "node:path";
30231
30317
  var INLINE_MEMBERS_BYTES = 256 * 1024;
30232
- var FLOW_FILES_LOG_ENV = "ARGENT_FLOW_FILES_LOG";
30318
+ function filesLogEnabled() {
30319
+ return (process.env.ARGENT_E2E_FILES_LOG ?? process.env.ARGENT_FLOW_FILES_LOG) === "1";
30320
+ }
30233
30321
  function isWithin(inner, outer) {
30234
- return inner === outer || inner.startsWith(outer.endsWith(path5.sep) ? outer : outer + path5.sep);
30322
+ return inner === outer || inner.startsWith(outer.endsWith(path6.sep) ? outer : outer + path6.sep);
30235
30323
  }
30236
30324
  function printable(text2) {
30237
30325
  return [...text2].map(
@@ -30239,23 +30327,21 @@ function printable(text2) {
30239
30327
  ).join("");
30240
30328
  }
30241
30329
  function isResolvedAbsolute2(value) {
30242
- return typeof value === "string" && path5.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
30330
+ return typeof value === "string" && path6.isAbsolute(value) && !value.split(/[\\/]+/).includes("..");
30243
30331
  }
30244
30332
  function namesValidFlow(args) {
30245
30333
  const { project_root, flow_path, name } = args;
30246
30334
  if (!isResolvedAbsolute2(project_root)) return false;
30247
30335
  if (name === void 0) {
30248
- return isResolvedAbsolute2(flow_path) && FLOW_FILE_NAME_PATTERN.test(path5.basename(flow_path));
30336
+ return isResolvedAbsolute2(flow_path) && FLOW_FILE_NAME_PATTERN.test(path6.basename(flow_path));
30249
30337
  }
30250
30338
  return flow_path === void 0 && typeof name === "string" && FLOW_NAME_PATTERN.test(name);
30251
30339
  }
30252
30340
  function savedFlowProject(file2) {
30253
- if (!path5.isAbsolute(file2)) return null;
30254
- const parts = file2.split(path5.sep);
30255
- for (let i2 = parts.length - 3; i2 >= 0; i2--) {
30256
- if (parts[i2] === ".argent" && parts[i2 + 1] === "flows") {
30257
- return parts.slice(0, i2).join(path5.sep) || path5.sep;
30258
- }
30341
+ if (!path6.isAbsolute(file2)) return null;
30342
+ for (let dir = path6.dirname(file2); dir !== path6.dirname(dir); dir = path6.dirname(dir)) {
30343
+ const project = e2eDirProject(dir);
30344
+ if (project !== null) return project;
30259
30345
  }
30260
30346
  return null;
30261
30347
  }
@@ -30268,11 +30354,11 @@ async function landing(spelled) {
30268
30354
  const canonical = await canonicalFlowPath(spelled);
30269
30355
  let at = spelled;
30270
30356
  for (; ; ) {
30271
- const parent = path5.dirname(at);
30357
+ const parent = path6.dirname(at);
30272
30358
  if (parent === at) return { canonical, fence: spelled, ...failure2 };
30273
30359
  const real = await realpath3(parent).catch(() => null);
30274
30360
  if (real !== null) {
30275
- return { canonical, fence: path5.join(real, path5.basename(at)), ...failure2 };
30361
+ return { canonical, fence: path6.join(real, path6.basename(at)), ...failure2 };
30276
30362
  }
30277
30363
  at = parent;
30278
30364
  }
@@ -30280,10 +30366,10 @@ async function landing(spelled) {
30280
30366
  }
30281
30367
  async function closureRoots(rootPath, rootCanonical, projectRoot) {
30282
30368
  const candidates = [];
30283
- if (typeof projectRoot === "string" && path5.isAbsolute(projectRoot)) {
30284
- candidates.push(projectRoot, path5.join(projectRoot, ".argent", "flows"));
30369
+ if (typeof projectRoot === "string" && path6.isAbsolute(projectRoot)) {
30370
+ candidates.push(projectRoot, ...e2eDirsFor(projectRoot));
30285
30371
  }
30286
- candidates.push(path5.dirname(rootPath), path5.dirname(rootCanonical));
30372
+ candidates.push(path6.dirname(rootPath), path6.dirname(rootCanonical));
30287
30373
  for (const file2 of [rootPath, rootCanonical]) {
30288
30374
  const project = savedFlowProject(file2);
30289
30375
  if (project !== null) candidates.push(project);
@@ -30296,11 +30382,11 @@ async function closureRoots(rootPath, rootCanonical, projectRoot) {
30296
30382
  return real.filter((root) => !real.some((other) => other !== root && isWithin(root, other)));
30297
30383
  }
30298
30384
  async function readFlowMember(anchorDir, target, roots, budget, opts) {
30299
- const spelled = anchorDir + path5.sep + target;
30385
+ const spelled = anchorDir + path6.sep + target;
30300
30386
  const { canonical, fence, missing, error: error63 } = await landing(spelled);
30301
30387
  const spelling = await classifyOnDiskSpelling(
30302
- path5.dirname(spelled),
30303
- path5.posix.basename(target),
30388
+ path6.dirname(spelled),
30389
+ path6.posix.basename(target),
30304
30390
  FLOW_FILE_NAME_PATTERN
30305
30391
  );
30306
30392
  const member = {
@@ -30319,13 +30405,13 @@ async function readFlowMember(anchorDir, target, roots, budget, opts) {
30319
30405
  }
30320
30406
  if (error63 !== void 0) return refuse(error63);
30321
30407
  if (missing) return { member: { ...member, state: "missing" }, sent: "missing" };
30322
- const st = await stat3(canonical).catch((err) => err);
30408
+ const st = await stat4(canonical).catch((err) => err);
30323
30409
  if (st instanceof Error) {
30324
30410
  if (st.code !== "ENOENT") return refuse(st.message);
30325
30411
  return { member: { ...member, state: "missing" }, sent: "missing" };
30326
30412
  }
30327
30413
  if (st.isDirectory()) return refuse("EISDIR: illegal operation on a directory, read");
30328
- if (!/\.ya?ml$/i.test(path5.basename(canonical))) {
30414
+ if (!/\.ya?ml$/i.test(path6.basename(canonical))) {
30329
30415
  return refuse(`${target} links to a file that is not a YAML file`);
30330
30416
  }
30331
30417
  const sent = await sendBytes(member, canonical, budget, opts);
@@ -30344,7 +30430,7 @@ async function readToolMember(file2, roots, budget, opts) {
30344
30430
  if (!hasToolFileExtension(canonical)) {
30345
30431
  return refuse(`${file2} links to a file that is not one of ${TOOL_FILE_EXTENSIONS.join(", ")}`);
30346
30432
  }
30347
- const st = await stat3(canonical).catch((err) => err);
30433
+ const st = await stat4(canonical).catch((err) => err);
30348
30434
  if (st instanceof Error) {
30349
30435
  if (st.code === "ENOENT" || st.code === "ENOTDIR") {
30350
30436
  return { member: { ...member, state: "missing" }, sent: "missing" };
@@ -30368,7 +30454,7 @@ async function baselineEntry(file2, roots, forWrite) {
30368
30454
  };
30369
30455
  }
30370
30456
  if (error63 !== void 0) return { state: "refused", error: error63 };
30371
- const st = await stat3(canonical).catch((err) => err);
30457
+ const st = await stat4(canonical).catch((err) => err);
30372
30458
  if (st instanceof Error) {
30373
30459
  if (st.code !== "ENOENT") return { state: "refused", error: st.message };
30374
30460
  return forWrite ? { state: "refused", error: `${file2} is a symbolic link to a missing file` } : { state: "missing" };
@@ -30418,7 +30504,7 @@ function memberCollector(roots, opts) {
30418
30504
  const runs = /* @__PURE__ */ new Set();
30419
30505
  const baselineDirs = /* @__PURE__ */ new Map();
30420
30506
  const budget = { inline: 0 };
30421
- const logging = process.env[FLOW_FILES_LOG_ENV] === "1";
30507
+ const logging = filesLogEnabled();
30422
30508
  const log2 = opts.log ?? ((line) => void process.stderr.write(`${line}
30423
30509
  `));
30424
30510
  const emit = (member, sent) => {
@@ -30426,18 +30512,19 @@ function memberCollector(roots, opts) {
30426
30512
  const subject = member.role === "flow" ? member.canonical : member.key;
30427
30513
  if (logging) log2(printable(`[flow-files] ${member.role} ${subject}: ${sent}`));
30428
30514
  };
30429
- async function flow2(anchorDir, target) {
30515
+ async function flow(anchorDir, target, onlyPresent) {
30430
30516
  const key = flowMemberKey(anchorDir, target);
30431
30517
  const known = flows.get(key);
30432
- if (known !== void 0) return known;
30518
+ if (known !== void 0) return onlyPresent && known.text === void 0 ? void 0 : known;
30433
30519
  const { member, text: text2, sent } = await readFlowMember(anchorDir, target, roots, budget, opts);
30520
+ if (onlyPresent && text2 === void 0) return void 0;
30434
30521
  const entry = { member, ...text2 === void 0 ? {} : { text: text2 } };
30435
30522
  flows.set(key, entry);
30436
30523
  emit(member, sent);
30437
30524
  return entry;
30438
30525
  }
30439
30526
  async function toolFiles(step) {
30440
- if (step.tool === "flow-execute") return;
30527
+ if (canonicalToolId(step.tool) === "e2e-execute") return;
30441
30528
  for (const file2 of toolStepFiles(opts.toolFileInputs?.(step.tool), step.args)) {
30442
30529
  const { unwrapWhenSet } = file2.spec;
30443
30530
  if (unwrapWhenSet !== void 0 && step.args[unwrapWhenSet] !== void 0) continue;
@@ -30447,11 +30534,31 @@ function memberCollector(roots, opts) {
30447
30534
  emit(read.member, read.sent);
30448
30535
  }
30449
30536
  }
30537
+ async function savedTest(target) {
30538
+ for (const candidate of target.paths) {
30539
+ const found = await flow(path6.dirname(candidate), path6.basename(candidate), true);
30540
+ if (found !== void 0) return found;
30541
+ }
30542
+ let first;
30543
+ for (const candidate of target.paths) {
30544
+ first ??= await flow(path6.dirname(candidate), path6.basename(candidate));
30545
+ }
30546
+ return first;
30547
+ }
30450
30548
  async function nestedRun(target, hop, updates, platform) {
30451
- const { member, text: text2 } = await flow2(path5.dirname(target.path), `${target.name}.yaml`);
30549
+ const { member, text: text2 } = await savedTest(target);
30452
30550
  if (text2 === void 0 || hop >= MAX_RUN_DEPTH) return void 0;
30453
30551
  return { canonical: member.canonical, text: text2, flowName: target.name, hop, updates, platform };
30454
30552
  }
30553
+ async function runTarget(anchorDir, target) {
30554
+ const found = await flow(anchorDir, target);
30555
+ if (found.member.spelling?.state !== "absent") return found;
30556
+ for (const dir of e2eRunFallbackDirs(anchorDir, target)) {
30557
+ const other = await flow(dir, target, true);
30558
+ if (other !== void 0) return other;
30559
+ }
30560
+ return found;
30561
+ }
30455
30562
  async function walk(start) {
30456
30563
  const queue = [...start];
30457
30564
  for (let run2 = queue.shift(); run2 !== void 0; run2 = queue.shift()) {
@@ -30471,12 +30578,12 @@ function memberCollector(roots, opts) {
30471
30578
  const requests = collectFlowRequests(doc);
30472
30579
  for (const name of requests.snapshots) snapshots.add(name);
30473
30580
  for (const step of requests.toolSteps) await toolFiles(step);
30474
- const anchorDir = path5.dirname(file2.canonical);
30581
+ const anchorDir = path6.dirname(file2.canonical);
30475
30582
  for (const target of requests.runTargets) {
30476
30583
  const key = flowMemberKey(anchorDir, target);
30477
30584
  if (visited.has(key)) continue;
30478
30585
  visited.add(key);
30479
- const { member, text: text2 } = await flow2(anchorDir, target);
30586
+ const { member, text: text2 } = await runTarget(anchorDir, target);
30480
30587
  if (text2 !== void 0 && file2.hop + 1 < MAX_RUN_DEPTH) {
30481
30588
  files.push({ canonical: member.canonical, text: text2, hop: file2.hop + 1 });
30482
30589
  }
@@ -30493,8 +30600,8 @@ function memberCollector(roots, opts) {
30493
30600
  }
30494
30601
  }
30495
30602
  if (snapshots.size === 0) continue;
30496
- const dir = path5.join(
30497
- path5.dirname(run2.canonical),
30603
+ const dir = path6.join(
30604
+ path6.dirname(run2.canonical),
30498
30605
  "__baselines__",
30499
30606
  baselineKeyFor(run2.canonical, run2.flowName)
30500
30607
  );
@@ -30518,7 +30625,7 @@ function memberCollector(roots, opts) {
30518
30625
  if (!name.endsWith(".png")) continue;
30519
30626
  const compared = [...prefixes].some((prefix) => name.startsWith(prefix));
30520
30627
  if (!updates && !compared) continue;
30521
- const file2 = path5.join(dir, name);
30628
+ const file2 = path6.join(dir, name);
30522
30629
  if (tools2.has(file2)) continue;
30523
30630
  const member = { role: "baseline", key: file2, path: file2 };
30524
30631
  const entry = await baselineEntry(file2, roots, updates && !compared);
@@ -30535,14 +30642,14 @@ function memberCollector(roots, opts) {
30535
30642
  }
30536
30643
  }
30537
30644
  }
30538
- return { members: members2, flow: flow2, toolFiles, nestedRun, walk, sendBaselines };
30645
+ return { members: members2, flow, toolFiles, nestedRun, walk, sendBaselines };
30539
30646
  }
30540
30647
  async function collectFlowMembers(rootPath, rootBytes, args, opts) {
30541
30648
  if (!namesValidFlow(args)) return {};
30542
30649
  const canonical = await canonicalFlowPath(rootPath);
30543
30650
  const spelling = await classifyOnDiskSpelling(
30544
- path5.dirname(rootPath),
30545
- path5.basename(rootPath),
30651
+ path6.dirname(rootPath),
30652
+ path6.basename(rootPath),
30546
30653
  FLOW_FILE_NAME_PATTERN
30547
30654
  );
30548
30655
  const collector = memberCollector(
@@ -30553,7 +30660,7 @@ async function collectFlowMembers(rootPath, rootBytes, args, opts) {
30553
30660
  {
30554
30661
  canonical,
30555
30662
  text: rootBytes.toString("utf8"),
30556
- flowName: path5.basename(rootPath, ".yaml"),
30663
+ flowName: path6.basename(rootPath, ".yaml"),
30557
30664
  hop: 0,
30558
30665
  updates: args.updateBaselines === true,
30559
30666
  platform: callPlatform(args)
@@ -30576,33 +30683,37 @@ function recordedStep(args) {
30576
30683
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
30577
30684
  return { tool: command, args: parsed };
30578
30685
  }
30579
- async function collectStepMembers(args, opts) {
30686
+ async function collectStepMembers(args, opts, recordingDirFor = e2eDirFor) {
30580
30687
  const { name, project_root: projectRoot } = args;
30581
30688
  const step = recordedStep(args);
30582
- if (typeof name !== "string" || !FLOW_NAME_PATTERN.test(name) || typeof projectRoot !== "string" || !path5.isAbsolute(projectRoot) || step === void 0) {
30689
+ if (typeof name !== "string" || !FLOW_NAME_PATTERN.test(name) || typeof projectRoot !== "string" || !path6.isAbsolute(projectRoot) || step === void 0) {
30583
30690
  return [];
30584
30691
  }
30585
- const recording = path5.join(projectRoot, ".argent", "flows", `${name}.yaml`);
30692
+ const recording = path6.join(recordingDirFor(projectRoot), `${name}.yaml`);
30586
30693
  const collector = memberCollector(
30587
30694
  await closureRoots(recording, (await landing(recording)).canonical, projectRoot),
30588
30695
  opts
30589
30696
  );
30590
30697
  await collector.toolFiles(step);
30591
- if (step.tool === "flow-execute") {
30592
- const self2 = await collector.flow(path5.dirname(recording), path5.basename(recording));
30698
+ if (canonicalToolId(step.tool) === "e2e-execute") {
30699
+ const self2 = await collector.flow(path6.dirname(recording), path6.basename(recording));
30593
30700
  let runArgs = step.args;
30594
30701
  const named = nestedFlowTarget(runArgs);
30595
30702
  if (named?.kind === "flow_path") {
30596
- const stem = path5.basename(named.path, ".yaml");
30597
- if (path5.resolve(path5.dirname(named.path)) === path5.resolve(path5.dirname(recording))) {
30598
- await collector.flow(path5.dirname(recording), path5.basename(named.path));
30703
+ const stem = path6.basename(named.path, ".yaml");
30704
+ const base = path6.basename(named.path);
30705
+ const dir = path6.resolve(path6.dirname(named.path));
30706
+ const recordingDir = path6.dirname(recording);
30707
+ const dirs = [recordingDir, ...e2eRunFallbackDirs(recordingDir, base)];
30708
+ if (dirs.some((d) => path6.resolve(d) === dir)) {
30709
+ await collector.flow(path6.dirname(named.path), base);
30599
30710
  runArgs = { ...runArgs, name: stem };
30600
30711
  delete runArgs.flow_path;
30601
30712
  }
30602
30713
  }
30603
30714
  const target = nestedFlowTarget(runArgs);
30604
30715
  if (target?.kind === "name") {
30605
- await collector.flow(path5.dirname(self2.member.canonical), `${target.name}.yaml`);
30716
+ await collector.flow(path6.dirname(self2.member.canonical), `${target.name}.yaml`);
30606
30717
  const run2 = await collector.nestedRun(
30607
30718
  target,
30608
30719
  0,
@@ -30615,6 +30726,43 @@ async function collectStepMembers(args, opts) {
30615
30726
  await collector.sendBaselines();
30616
30727
  return collector.members;
30617
30728
  }
30729
+ async function nameToE2ePathForOlderServer(tool, fileInputs, args) {
30730
+ const id = canonicalToolId(tool);
30731
+ if (id !== "e2e-execute" && id !== "e2e-read-prerequisite") return args;
30732
+ const spec = fileInputs?.find((s) => s.target === "flow_file");
30733
+ if (spec === void 0 || spec.kind !== "file" || spec.paths?.length) return args;
30734
+ const target = nestedFlowTarget(args);
30735
+ if (target?.kind !== "name") return args;
30736
+ const picked = await pickE2eFile(target.paths);
30737
+ if (!picked.exists || picked.legacy) return args;
30738
+ const { name: _name, ...rest } = args;
30739
+ return { ...rest, flow_path: picked.path };
30740
+ }
30741
+ async function stepForOlderServer(args, listedId) {
30742
+ if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
30743
+ const record2 = args;
30744
+ if (typeof record2.command !== "string") return args;
30745
+ const command = listedId(record2.command) ?? record2.command;
30746
+ const step = recordedStep({ ...record2, command });
30747
+ const target = step && canonicalToolId(step.tool) === "e2e-execute" && nestedFlowTarget(step.args);
30748
+ if (target && target.kind === "name") {
30749
+ const picked = await pickE2eFile(target.paths);
30750
+ if (picked.exists && !picked.legacy) {
30751
+ throw new Error(
30752
+ `Cannot record a nested ${record2.command} of "${target.name}": the tool-server runs an older argent that records and runs nested e2e tests only from .argent/flows/, and "${target.name}" is ${picked.path}. Upgrade the tool-server to record it, or run it with e2e-execute outside the recording.`
30753
+ );
30754
+ }
30755
+ }
30756
+ return command === record2.command ? args : { ...record2, command };
30757
+ }
30758
+ async function e2eShadowWarningFor(tool, args) {
30759
+ const id = canonicalToolId(tool);
30760
+ if (id !== "e2e-execute" && id !== "e2e-read-prerequisite") return void 0;
30761
+ const target = nestedFlowTarget(args);
30762
+ if (target?.kind !== "name") return void 0;
30763
+ const picked = await pickE2eFile(target.paths);
30764
+ return picked.shadowed === void 0 ? void 0 : e2eShadowWarning(picked.path, picked.shadowed);
30765
+ }
30618
30766
 
30619
30767
  // ../argent-tools-client/src/tools-client.ts
30620
30768
  function authHeaders2(token) {
@@ -30692,6 +30840,10 @@ function errorBodyMessage(body) {
30692
30840
  if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
30693
30841
  return body.error ?? body.message;
30694
30842
  }
30843
+ function findTool(tools2, name) {
30844
+ const id = canonicalToolId(name);
30845
+ return tools2.find((t2) => t2.name === name) ?? tools2.find((t2) => canonicalToolId(t2.name) === id) ?? null;
30846
+ }
30695
30847
  function assertRequiredPresent(meta3, args) {
30696
30848
  const record2 = typeof args === "object" && args !== null ? args : {};
30697
30849
  const schema = meta3.inputSchema;
@@ -30767,26 +30919,33 @@ function createToolsClient(options = {}) {
30767
30919
  return json2.tools;
30768
30920
  }
30769
30921
  async function fetchTool(name, opts) {
30770
- const tools2 = await fetchTools(opts);
30771
- return tools2.find((t2) => t2.name === name) ?? null;
30922
+ return findTool(await fetchTools(opts), name);
30772
30923
  }
30773
30924
  async function callTool(name, args, opts) {
30774
30925
  opts?.signal?.throwIfAborted();
30775
30926
  const { url: url2, token, remote } = await route();
30776
30927
  let finalArgs = args;
30777
30928
  const tools2 = await fetchTools({ signal: opts?.signal });
30778
- const meta3 = tools2.find((t2) => t2.name === name) ?? null;
30929
+ const meta3 = findTool(tools2, name);
30930
+ const olderServer = meta3 !== null && !tools2.some((t2) => t2.name === canonicalToolId(meta3.name));
30931
+ if (meta3) {
30932
+ finalArgs = await nameToE2ePathForOlderServer(meta3.name, meta3.fileInputs, args);
30933
+ }
30934
+ if (olderServer && canonicalToolId(meta3.name) === "e2e-add-step") {
30935
+ finalArgs = await stepForOlderServer(finalArgs, (tool) => findTool(tools2, tool)?.name);
30936
+ }
30937
+ const shadowWarning = await e2eShadowWarningFor(name, args);
30779
30938
  const baselineDirs = [];
30780
30939
  if (meta3?.fileInputs?.length) {
30781
- if (remote) assertRequiredPresent(meta3, args);
30782
- finalArgs = await prepareFileInputs(meta3.fileInputs, args ?? {}, {
30940
+ if (remote) assertRequiredPresent(meta3, finalArgs);
30941
+ finalArgs = await prepareFileInputs(meta3.fileInputs, finalArgs ?? {}, {
30783
30942
  includeContent: remote,
30784
30943
  uploadEndpoint: remote ? { url: url2, token } : void 0,
30785
30944
  log: diagnose,
30786
30945
  baselineDirs,
30787
30946
  collectMembers: collectFlowMembers,
30788
- collectStepMembers,
30789
- toolFileInputs: (tool) => tools2.find((t2) => t2.name === tool)?.fileInputs,
30947
+ collectStepMembers: olderServer ? (record2, o) => collectStepMembers(record2, o, (root) => path7.join(root, LEGACY_E2E_DIRS[0])) : collectStepMembers,
30948
+ toolFileInputs: (tool) => findTool(tools2, tool)?.fileInputs,
30790
30949
  signal: opts?.signal
30791
30950
  });
30792
30951
  }
@@ -30795,19 +30954,23 @@ function createToolsClient(options = {}) {
30795
30954
  for (const { path: file2, error: error63 } of applied.failed) {
30796
30955
  diagnose(`The baseline ${file2} was not written on this client: ${error63}`);
30797
30956
  }
30798
- if (process.env.ARGENT_FLOW_FILES_LOG === "1") {
30957
+ if (filesLogEnabled()) {
30799
30958
  for (const file2 of applied.written) {
30800
- if (baselineDirs.includes(path6.dirname(file2))) {
30959
+ if (baselineDirs.includes(path7.dirname(file2))) {
30801
30960
  diagnose(`[flow-files] baseline ${file2}: written`);
30802
30961
  }
30803
30962
  }
30804
30963
  }
30805
- return applied.result;
30964
+ const result = applied.result;
30965
+ if (shadowWarning === void 0 || typeof result !== "object" || result === null || Array.isArray(result) || typeof result.warning === "string") {
30966
+ return result;
30967
+ }
30968
+ return { ...result, warning: shadowWarning };
30806
30969
  };
30807
30970
  const stream = opts?.onProgress !== void 0 || carriesMembers(finalArgs);
30808
30971
  const sentOnce = carriesUpload(finalArgs);
30809
30972
  const res = await doFetch(
30810
- `${url2}/tools/${encodeURIComponent(name)}`,
30973
+ `${url2}/tools/${encodeURIComponent(meta3?.name ?? name)}`,
30811
30974
  {
30812
30975
  method: "POST",
30813
30976
  headers: {
@@ -30815,6 +30978,9 @@ function createToolsClient(options = {}) {
30815
30978
  // Tells the tool-server the call came over a link, a link to
30816
30979
  // 127.0.0.1 included, which nothing else in the request shows.
30817
30980
  ...remote ? { [LINKED_CALL_HEADER]: "1" } : {},
30981
+ // Tells the tool-server this client writes recordings under
30982
+ // `.argent/e2e/`; an older client writes only `.argent/flows/`.
30983
+ [E2E_DIR_CLIENT_HEADER]: "1",
30818
30984
  // A proxy that compresses the stream holds each line until its buffer
30819
30985
  // fills. `identity` keeps the stream uncompressed end to end.
30820
30986
  ...stream ? { "Accept": "application/x-ndjson", "Accept-Encoding": "identity" } : {},
@@ -30872,15 +31038,15 @@ function createToolsClient(options = {}) {
30872
31038
  }
30873
31039
 
30874
31040
  // ../argent-tools-client/src/artifacts.ts
30875
- import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as realpath4, rm as rm3, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
31041
+ import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as realpath4, rm as rm3, stat as stat5, writeFile as writeFile4 } from "node:fs/promises";
30876
31042
  import { constants as fsConstants } from "node:fs";
30877
31043
  import { tmpdir as tmpdir2 } from "node:os";
30878
- import { basename as basename6, dirname as dirname8, extname as extname2, isAbsolute as isAbsolute6, join as join11, normalize as normalize2, resolve as resolve7, sep as sep4 } from "node:path";
31044
+ import { basename as basename7, dirname as dirname9, extname as extname2, isAbsolute as isAbsolute6, join as join13, normalize as normalize2, resolve as resolve8, sep as sep4 } from "node:path";
30879
31045
  import { createHash as createHash3 } from "node:crypto";
30880
31046
 
30881
31047
  // ../configuration-core/src/flags.ts
30882
- import * as fs3 from "node:fs";
30883
- import * as path7 from "node:path";
31048
+ import * as fs4 from "node:fs";
31049
+ import * as path8 from "node:path";
30884
31050
  import { homedir as homedir3 } from "node:os";
30885
31051
  var FLAG_REGISTRY = [
30886
31052
  {
@@ -30922,31 +31088,31 @@ function getFlagDefinition(name, registry2 = FLAG_REGISTRY) {
30922
31088
  }
30923
31089
  var PROJECT_MARKERS = [".argent", ".git", "package.json"];
30924
31090
  function findProjectRoot(startDir) {
30925
- let current = path7.resolve(startDir);
31091
+ let current = path8.resolve(startDir);
30926
31092
  while (true) {
30927
31093
  for (const marker of PROJECT_MARKERS) {
30928
- if (fs3.existsSync(path7.join(current, marker))) return current;
31094
+ if (fs4.existsSync(path8.join(current, marker))) return current;
30929
31095
  }
30930
- const parent = path7.dirname(current);
31096
+ const parent = path8.dirname(current);
30931
31097
  if (parent === current) return null;
30932
31098
  current = parent;
30933
31099
  }
30934
31100
  }
30935
31101
  function resolveProjectRoot(startDir) {
30936
- return findProjectRoot(startDir) ?? path7.resolve(startDir);
31102
+ return findProjectRoot(startDir) ?? path8.resolve(startDir);
30937
31103
  }
30938
31104
  function getFlagsPath(scope, options = {}) {
30939
31105
  const home = options.homeDir ?? homedir3();
30940
31106
  if (scope === "global") {
30941
- return path7.join(home, ".argent", "flags.json");
31107
+ return path8.join(home, ".argent", "flags.json");
30942
31108
  }
30943
31109
  const cwd = options.cwd ?? process.cwd();
30944
- return path7.join(resolveProjectRoot(cwd), ".argent", "flags.json");
31110
+ return path8.join(resolveProjectRoot(cwd), ".argent", "flags.json");
30945
31111
  }
30946
31112
  function readFlagsFile(filePath) {
30947
31113
  let raw;
30948
31114
  try {
30949
- raw = fs3.readFileSync(filePath, "utf8");
31115
+ raw = fs4.readFileSync(filePath, "utf8");
30950
31116
  } catch {
30951
31117
  return {};
30952
31118
  }
@@ -30967,20 +31133,20 @@ function readFlagsFile(filePath) {
30967
31133
  }
30968
31134
  function writeFlagsFile(filePath, flags2) {
30969
31135
  if (Object.keys(flags2).length === 0) {
30970
- if (fs3.existsSync(filePath)) fs3.rmSync(filePath, { force: true });
30971
- const parent = path7.dirname(filePath);
31136
+ if (fs4.existsSync(filePath)) fs4.rmSync(filePath, { force: true });
31137
+ const parent = path8.dirname(filePath);
30972
31138
  try {
30973
- if (fs3.existsSync(parent) && fs3.readdirSync(parent).length === 0) {
30974
- fs3.rmdirSync(parent);
31139
+ if (fs4.existsSync(parent) && fs4.readdirSync(parent).length === 0) {
31140
+ fs4.rmdirSync(parent);
30975
31141
  }
30976
31142
  } catch {
30977
31143
  }
30978
31144
  return;
30979
31145
  }
30980
- fs3.mkdirSync(path7.dirname(filePath), { recursive: true });
31146
+ fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
30981
31147
  const tmp = `${filePath}.${process.pid}.tmp`;
30982
- fs3.writeFileSync(tmp, JSON.stringify({ flags: flags2 }, null, 2) + "\n");
30983
- fs3.renameSync(tmp, filePath);
31148
+ fs4.writeFileSync(tmp, JSON.stringify({ flags: flags2 }, null, 2) + "\n");
31149
+ fs4.renameSync(tmp, filePath);
30984
31150
  }
30985
31151
  function readFlags(scope, options = {}) {
30986
31152
  return readFlagsFile(getFlagsPath(scope, options));
@@ -31009,7 +31175,7 @@ function isFlagEnabled(name, options = {}) {
31009
31175
 
31010
31176
  // ../configuration-core/src/paths.ts
31011
31177
  import * as os from "node:os";
31012
- import * as path8 from "node:path";
31178
+ import * as path9 from "node:path";
31013
31179
  function nonEmpty(value) {
31014
31180
  if (value == void 0) return null;
31015
31181
  const trimmed = value.trim();
@@ -31020,26 +31186,26 @@ function resolveHomeDir(options = {}) {
31020
31186
  return process.platform === "win32" ? nonEmpty(process.env.USERPROFILE) ?? os.homedir() : nonEmpty(process.env.HOME) ?? os.homedir();
31021
31187
  }
31022
31188
  function argentHomeDir() {
31023
- return path8.join(resolveHomeDir(), ".argent");
31189
+ return path9.join(resolveHomeDir(), ".argent");
31024
31190
  }
31025
31191
  function configDir(scope = "global", options = {}) {
31026
31192
  if (scope === "global") {
31027
- return path8.join(resolveHomeDir(options), ".argent");
31193
+ return path9.join(resolveHomeDir(options), ".argent");
31028
31194
  }
31029
31195
  const cwd = options.cwd ?? process.cwd();
31030
- return path8.join(resolveProjectRoot(cwd), ".argent");
31196
+ return path9.join(resolveProjectRoot(cwd), ".argent");
31031
31197
  }
31032
31198
  function configFilePath(scope = "global", options = {}) {
31033
- return path8.join(configDir(scope, options), "config.json");
31199
+ return path9.join(configDir(scope, options), "config.json");
31034
31200
  }
31035
31201
 
31036
31202
  // ../configuration-core/src/config.ts
31037
31203
  import * as crypto from "node:crypto";
31038
- import * as fs4 from "node:fs";
31039
- import * as path9 from "node:path";
31204
+ import * as fs5 from "node:fs";
31205
+ import * as path10 from "node:path";
31040
31206
  function readConfigObject(scope = "global", options = {}) {
31041
31207
  try {
31042
- const raw = fs4.readFileSync(configFilePath(scope, options), "utf8");
31208
+ const raw = fs5.readFileSync(configFilePath(scope, options), "utf8");
31043
31209
  const json2 = JSON.parse(raw);
31044
31210
  if (json2 && typeof json2 === "object" && !Array.isArray(json2)) {
31045
31211
  return json2;
@@ -31115,9 +31281,9 @@ function acquireConfigLock(finalPath) {
31115
31281
  const deadline = Date.now() + LOCK_MAX_WAIT_MS;
31116
31282
  for (; ; ) {
31117
31283
  try {
31118
- const fd = fs4.openSync(lockPath, "wx", 384);
31284
+ const fd = fs5.openSync(lockPath, "wx", 384);
31119
31285
  try {
31120
- fs4.writeSync(fd, `${process.pid}
31286
+ fs5.writeSync(fd, `${process.pid}
31121
31287
  `);
31122
31288
  } catch {
31123
31289
  }
@@ -31125,8 +31291,8 @@ function acquireConfigLock(finalPath) {
31125
31291
  } catch (err) {
31126
31292
  if (err.code !== "EEXIST") return null;
31127
31293
  try {
31128
- if (Date.now() - fs4.statSync(lockPath).mtimeMs > LOCK_STALE_MS2) {
31129
- fs4.unlinkSync(lockPath);
31294
+ if (Date.now() - fs5.statSync(lockPath).mtimeMs > LOCK_STALE_MS2) {
31295
+ fs5.unlinkSync(lockPath);
31130
31296
  continue;
31131
31297
  }
31132
31298
  } catch {
@@ -31138,35 +31304,35 @@ function acquireConfigLock(finalPath) {
31138
31304
  }
31139
31305
  function releaseConfigLock(lock) {
31140
31306
  try {
31141
- fs4.closeSync(lock.fd);
31307
+ fs5.closeSync(lock.fd);
31142
31308
  } catch {
31143
31309
  }
31144
31310
  try {
31145
- fs4.unlinkSync(lock.lockPath);
31311
+ fs5.unlinkSync(lock.lockPath);
31146
31312
  } catch {
31147
31313
  }
31148
31314
  }
31149
31315
  function updateConfig(mutate, scope = "global", options = {}) {
31150
31316
  const dir = configDir(scope, options);
31151
- fs4.mkdirSync(dir, { recursive: true });
31317
+ fs5.mkdirSync(dir, { recursive: true });
31152
31318
  const finalPath = configFilePath(scope, options);
31153
31319
  const lock = acquireConfigLock(finalPath);
31154
31320
  try {
31155
31321
  const next = readConfigObject(scope, options);
31156
31322
  mutate(next);
31157
- const tmpPath = path9.join(dir, `.config.tmp.${process.pid}.${crypto.randomUUID()}`);
31158
- const fd = fs4.openSync(tmpPath, "wx", 384);
31323
+ const tmpPath = path10.join(dir, `.config.tmp.${process.pid}.${crypto.randomUUID()}`);
31324
+ const fd = fs5.openSync(tmpPath, "wx", 384);
31159
31325
  try {
31160
- fs4.writeSync(fd, JSON.stringify(next, null, 2) + "\n");
31161
- fs4.fsyncSync(fd);
31326
+ fs5.writeSync(fd, JSON.stringify(next, null, 2) + "\n");
31327
+ fs5.fsyncSync(fd);
31162
31328
  } finally {
31163
- fs4.closeSync(fd);
31329
+ fs5.closeSync(fd);
31164
31330
  }
31165
31331
  try {
31166
- fs4.renameSync(tmpPath, finalPath);
31332
+ fs5.renameSync(tmpPath, finalPath);
31167
31333
  } catch (err) {
31168
31334
  try {
31169
- fs4.unlinkSync(tmpPath);
31335
+ fs5.unlinkSync(tmpPath);
31170
31336
  } catch {
31171
31337
  }
31172
31338
  throw err;
@@ -31178,8 +31344,8 @@ function updateConfig(mutate, scope = "global", options = {}) {
31178
31344
 
31179
31345
  // ../configuration-core/src/secrets.ts
31180
31346
  var import_dotenv = __toESM(require_dist2(), 1);
31181
- import * as fs5 from "node:fs";
31182
- import * as path10 from "node:path";
31347
+ import * as fs6 from "node:fs";
31348
+ import * as path11 from "node:path";
31183
31349
  var SECRET_ENV_PREFIX = "ARGENT_SECRET_";
31184
31350
  var SECRETS_FILE_NAME = "secrets.env";
31185
31351
  var SHARED_ENV_FILES = [".env.local", ".env"];
@@ -31208,10 +31374,10 @@ function fileSource(filePath, exposure) {
31208
31374
  names: [],
31209
31375
  values: /* @__PURE__ */ new Map()
31210
31376
  };
31211
- if (!fs5.statSync(filePath, { throwIfNoEntry: false })) return absent;
31377
+ if (!fs6.statSync(filePath, { throwIfNoEntry: false })) return absent;
31212
31378
  let content;
31213
31379
  try {
31214
- content = fs5.readFileSync(filePath, "utf8");
31380
+ content = fs6.readFileSync(filePath, "utf8");
31215
31381
  } catch {
31216
31382
  return absent;
31217
31383
  }
@@ -31241,20 +31407,20 @@ function secretSources(options = {}) {
31241
31407
  const filePaths = [];
31242
31408
  if (projectRoot) {
31243
31409
  filePaths.push({
31244
- path: path10.join(projectRoot, ".argent", SECRETS_FILE_NAME),
31410
+ path: path11.join(projectRoot, ".argent", SECRETS_FILE_NAME),
31245
31411
  exposure: "dedicated"
31246
31412
  });
31247
31413
  for (const name of SHARED_ENV_FILES) {
31248
- filePaths.push({ path: path10.join(projectRoot, name), exposure: "shared" });
31414
+ filePaths.push({ path: path11.join(projectRoot, name), exposure: "shared" });
31249
31415
  }
31250
31416
  }
31251
31417
  filePaths.push({
31252
- path: path10.join(resolveHomeDir(options), ".argent", SECRETS_FILE_NAME),
31418
+ path: path11.join(resolveHomeDir(options), ".argent", SECRETS_FILE_NAME),
31253
31419
  exposure: "dedicated"
31254
31420
  });
31255
31421
  const seen = /* @__PURE__ */ new Set();
31256
31422
  for (const entry of filePaths) {
31257
- const resolved = path10.resolve(entry.path);
31423
+ const resolved = path11.resolve(entry.path);
31258
31424
  if (seen.has(resolved)) continue;
31259
31425
  seen.add(resolved);
31260
31426
  sources.push(fileSource(resolved, entry.exposure));
@@ -31422,7 +31588,7 @@ var CONFIG_SCHEMA = [
31422
31588
  // nominal here — the project scope of a global-only key is never read.
31423
31589
  {
31424
31590
  key: "scripts.maxTimeoutMs",
31425
- description: `Upper bound, in milliseconds, on the time limit a flow \`script\` step may ask for (default 300000 \u2014 five minutes). Bounds how long one script can occupy the host. Values below ${MIN_SCRIPT_TIMEOUT_MS} ms are refused: the step starts a Node process before the script runs, so a smaller ceiling ends a script that did nothing wrong.`,
31591
+ description: `Upper bound, in milliseconds, on the time limit an e2e test \`script\` step may ask for (default 300000 \u2014 five minutes). Bounds how long one script can occupy the host. Values below ${MIN_SCRIPT_TIMEOUT_MS} ms are refused: the step starts a Node process before the script runs, so a smaller ceiling ends a script that did nothing wrong.`,
31426
31592
  scopes: ["global"],
31427
31593
  parse: (raw) => {
31428
31594
  const value = asPositiveInteger(raw);
@@ -31435,7 +31601,7 @@ var CONFIG_SCHEMA = [
31435
31601
  },
31436
31602
  {
31437
31603
  key: "scripts.heapLimitMb",
31438
- description: `Old-space heap limit, in MiB, given to each flow \`script\` process (default 512). Values below ${MIN_SCRIPT_HEAP_LIMIT_MB} MiB are refused: that is already below what importing a real npm dependency needs, and under about 5 MiB the process dies inside V8's own startup before any script runs.`,
31604
+ description: `Old-space heap limit, in MiB, given to each e2e test \`script\` process (default 512). Values below ${MIN_SCRIPT_HEAP_LIMIT_MB} MiB are refused: that is already below what importing a real npm dependency needs, and under about 5 MiB the process dies inside V8's own startup before any script runs.`,
31439
31605
  scopes: ["global"],
31440
31606
  parse: (raw) => {
31441
31607
  const value = asPositiveInteger(raw);
@@ -31452,7 +31618,7 @@ function getConfigDefinition(key, registry2 = CONFIG_SCHEMA) {
31452
31618
  }
31453
31619
 
31454
31620
  // ../configuration-core/src/config-access.ts
31455
- import * as path11 from "node:path";
31621
+ import * as path12 from "node:path";
31456
31622
  function readScopeValue(def, scope, options) {
31457
31623
  if (!def.scopes.includes(scope)) return void 0;
31458
31624
  const raw = getAtPath(readConfigObject(scope, options), def.key);
@@ -31599,20 +31765,20 @@ function sanitizeSegment(segment) {
31599
31765
  function projectSlug() {
31600
31766
  const cwd = process.cwd();
31601
31767
  const hash2 = createHash3("sha1").update(cwd).digest("hex").slice(0, 6);
31602
- const name = sanitizeSegment(basename6(cwd)) || "root";
31768
+ const name = sanitizeSegment(basename7(cwd)) || "root";
31603
31769
  return `${name}-${hash2}`;
31604
31770
  }
31605
31771
  function artifactsRoot() {
31606
- return process.env.ARGENT_ARTIFACTS_DIR ?? join11(tmpdir2(), "argent-artifacts");
31772
+ return process.env.ARGENT_ARTIFACTS_DIR ?? join13(tmpdir2(), "argent-artifacts");
31607
31773
  }
31608
31774
  function artifactDir(deviceId) {
31609
31775
  const parts = [artifactsRoot(), projectSlug(), sessionId()];
31610
31776
  if (deviceId) parts.push(sanitizeSegment(deviceId));
31611
- return join11(...parts);
31777
+ return join13(...parts);
31612
31778
  }
31613
31779
  function durableBaseDir() {
31614
31780
  const projectRoot = findProjectRoot(process.cwd());
31615
- return projectRoot ?? dirname8(argentHomeDir());
31781
+ return projectRoot ?? dirname9(argentHomeDir());
31616
31782
  }
31617
31783
  var ALLOWED_SAVE_DIRS = /* @__PURE__ */ new Set([normalize2(".argent/recordings")]);
31618
31784
  var RECORDINGS_SAVE_DIR = normalize2(".argent/recordings");
@@ -31626,9 +31792,9 @@ function configuredRecordingsDir() {
31626
31792
  if (typeof value !== "string") return null;
31627
31793
  const trimmed = value.trim();
31628
31794
  if (trimmed === "") return null;
31629
- const home = dirname8(argentHomeDir());
31630
- const expanded = trimmed === "~" ? home : trimmed.startsWith("~/") || trimmed.startsWith(`~${sep4}`) ? join11(home, trimmed.slice(2)) : trimmed;
31631
- return resolve7(durableBaseDir(), expanded);
31795
+ const home = dirname9(argentHomeDir());
31796
+ const expanded = trimmed === "~" ? home : trimmed.startsWith("~/") || trimmed.startsWith(`~${sep4}`) ? join13(home, trimmed.slice(2)) : trimmed;
31797
+ return resolve8(durableBaseDir(), expanded);
31632
31798
  }
31633
31799
  var MAX_DURABLE_BYTES = 2 * 1024 * 1024 * 1024;
31634
31800
  async function readCapped(res, cap) {
@@ -31661,10 +31827,10 @@ async function writeDurableUnique(dir, filename, write) {
31661
31827
  const stem = filename.slice(0, filename.length - ext.length);
31662
31828
  for (let i2 = 1; i2 <= 1e3; i2++) {
31663
31829
  const candidate = i2 === 1 ? filename : `${stem} (${i2})${ext}`;
31664
- const path24 = join11(dir, candidate);
31830
+ const path25 = join13(dir, candidate);
31665
31831
  try {
31666
- await write(path24);
31667
- return path24;
31832
+ await write(path25);
31833
+ return path25;
31668
31834
  } catch (err) {
31669
31835
  if (err?.code === "EEXIST") continue;
31670
31836
  throw err;
@@ -31684,21 +31850,21 @@ function durableSaveTarget(handle) {
31684
31850
  if (configured) {
31685
31851
  return {
31686
31852
  dir: configured,
31687
- path: join11(configured, sanitizeSegment(handle.filename)),
31853
+ path: join13(configured, sanitizeSegment(handle.filename)),
31688
31854
  base: configured,
31689
31855
  rel: ""
31690
31856
  };
31691
31857
  }
31692
31858
  }
31693
31859
  const base = durableBaseDir();
31694
- const dir = join11(base, rel);
31695
- return { dir, path: join11(dir, sanitizeSegment(handle.filename)), base, rel };
31860
+ const dir = join13(base, rel);
31861
+ return { dir, path: join13(dir, sanitizeSegment(handle.filename)), base, rel };
31696
31862
  }
31697
31863
  async function confineToRealBase(dir, base, rel) {
31698
31864
  try {
31699
31865
  const realDir = await realpath4(dir);
31700
31866
  const realBase = await realpath4(base);
31701
- return realDir === join11(realBase, rel);
31867
+ return realDir === join13(realBase, rel);
31702
31868
  } catch {
31703
31869
  return false;
31704
31870
  }
@@ -31706,7 +31872,7 @@ async function confineToRealBase(dir, base, rel) {
31706
31872
  async function resolveLocalFile(handle) {
31707
31873
  if (!handle.hostPath) return null;
31708
31874
  try {
31709
- const st = await stat4(handle.hostPath);
31875
+ const st = await stat5(handle.hostPath);
31710
31876
  if (handle.archive) {
31711
31877
  return st.isDirectory() ? handle.hostPath : null;
31712
31878
  }
@@ -31721,7 +31887,7 @@ async function resolveLocalFile(handle) {
31721
31887
  }
31722
31888
  }
31723
31889
  async function downloadAndExtractArchive(handle, data, dir) {
31724
- const tarball = join11(dir, `${sanitizeSegment(handle.filename)}.tar.gz`);
31890
+ const tarball = join13(dir, `${sanitizeSegment(handle.filename)}.tar.gz`);
31725
31891
  try {
31726
31892
  await writeFile4(tarball, data);
31727
31893
  return await safeExtractTarGz(tarball, dir, handle.filename);
@@ -31749,7 +31915,7 @@ async function materializeArtifacts(result, ctx) {
31749
31915
  const localPath = await resolveLocalFile(value);
31750
31916
  const saveTarget = durableSaveTarget(value);
31751
31917
  if (saveTarget) {
31752
- const filename = basename6(saveTarget.path);
31918
+ const filename = basename7(saveTarget.path);
31753
31919
  try {
31754
31920
  await mkdir4(saveTarget.dir, { recursive: true });
31755
31921
  if (!await confineToRealBase(saveTarget.dir, saveTarget.base, saveTarget.rel)) {
@@ -31813,7 +31979,7 @@ async function materializeArtifacts(result, ctx) {
31813
31979
  return await downloadAndExtractArchive(value, data, dir);
31814
31980
  }
31815
31981
  if (value.size > 0 && data.length !== value.size) return null;
31816
- const downloadedPath = join11(dir, sanitizeSegment(value.filename));
31982
+ const downloadedPath = join13(dir, sanitizeSegment(value.filename));
31817
31983
  await writeFile4(downloadedPath, data);
31818
31984
  if (value.mimeType.startsWith("image/")) {
31819
31985
  images.push({ localPath: downloadedPath, data, mimeType: value.mimeType });
@@ -32270,8 +32436,8 @@ var Deferred = class {
32270
32436
  _resolve;
32271
32437
  _reject;
32272
32438
  constructor() {
32273
- this._promise = new Promise((resolve12, reject) => {
32274
- this._resolve = resolve12;
32439
+ this._promise = new Promise((resolve13, reject) => {
32440
+ this._resolve = resolve13;
32275
32441
  this._reject = reject;
32276
32442
  });
32277
32443
  }
@@ -33164,8 +33330,8 @@ var ExportOperation = class {
33164
33330
  _metrics;
33165
33331
  _exportScheduledResolve;
33166
33332
  constructor(exporter, logRecords, exportTimeoutMillis, metrics) {
33167
- this._exportScheduledPromise = new Promise((resolve12) => {
33168
- this._exportScheduledResolve = resolve12;
33333
+ this._exportScheduledPromise = new Promise((resolve13) => {
33334
+ this._exportScheduledResolve = resolve13;
33169
33335
  });
33170
33336
  this._exportCompleted = this._executeExport(exporter, logRecords, exportTimeoutMillis);
33171
33337
  this._metrics = metrics;
@@ -33190,7 +33356,7 @@ var ExportOperation = class {
33190
33356
  }
33191
33357
  }
33192
33358
  async _exportWithTimeout(exporter, logRecords, exportTimeoutMillis) {
33193
- return new Promise((resolve12, reject) => {
33359
+ return new Promise((resolve13, reject) => {
33194
33360
  const timer = setTimeout(() => {
33195
33361
  reject(new Error("Timeout"));
33196
33362
  }, exportTimeoutMillis);
@@ -33198,7 +33364,7 @@ var ExportOperation = class {
33198
33364
  this._metrics.finishLogs(logRecords.length, result.error);
33199
33365
  clearTimeout(timer);
33200
33366
  if (result.code === ExportResultCode.SUCCESS) {
33201
- resolve12();
33367
+ resolve13();
33202
33368
  } else {
33203
33369
  reject(result.error ?? new Error("BatchLogRecordProcessor: log record export failed"));
33204
33370
  }
@@ -33979,7 +34145,7 @@ function parseRetryAfterToMills(retryAfter) {
33979
34145
  var DEFAULT_USER_AGENT = `OTel-OTLP-Exporter-JavaScript/${VERSION4}`;
33980
34146
  var MAX_RESPONSE_BODY_SIZE = 4 * 1024 * 1024;
33981
34147
  function sendWithHttp(request, url2, headers, compression, userAgent, agent, data, timeoutMillis) {
33982
- return new Promise((resolve12) => {
34148
+ return new Promise((resolve13) => {
33983
34149
  const parsedUrl = new URL(url2);
33984
34150
  if (userAgent) {
33985
34151
  headers["User-Agent"] = `${userAgent} ${DEFAULT_USER_AGENT}`;
@@ -33998,7 +34164,7 @@ function sendWithHttp(request, url2, headers, compression, userAgent, agent, dat
33998
34164
  responseSize += chunk.length;
33999
34165
  if (responseSize > MAX_RESPONSE_BODY_SIZE) {
34000
34166
  const sizeError = new Error(`OTLP export response body exceeded size limit of ${MAX_RESPONSE_BODY_SIZE} bytes`);
34001
- resolve12({ status: "failure", error: sizeError });
34167
+ resolve13({ status: "failure", error: sizeError });
34002
34168
  res.destroy();
34003
34169
  return;
34004
34170
  }
@@ -34006,18 +34172,18 @@ function sendWithHttp(request, url2, headers, compression, userAgent, agent, dat
34006
34172
  });
34007
34173
  res.on("end", () => {
34008
34174
  if (res.statusCode && res.statusCode <= 299) {
34009
- resolve12({
34175
+ resolve13({
34010
34176
  status: "success",
34011
34177
  data: Buffer.concat(responseData)
34012
34178
  });
34013
34179
  } else if (res.statusCode && isExportHTTPErrorRetryable(res.statusCode)) {
34014
- resolve12({
34180
+ resolve13({
34015
34181
  status: "retryable",
34016
34182
  retryInMillis: parseRetryAfterToMills(res.headers["retry-after"])
34017
34183
  });
34018
34184
  } else {
34019
34185
  const error63 = new OTLPExporterError(res.statusMessage, res.statusCode, Buffer.concat(responseData).toString());
34020
- resolve12({
34186
+ resolve13({
34021
34187
  status: "failure",
34022
34188
  error: error63
34023
34189
  });
@@ -34025,17 +34191,17 @@ function sendWithHttp(request, url2, headers, compression, userAgent, agent, dat
34025
34191
  });
34026
34192
  res.on("error", (error63) => {
34027
34193
  if (res.statusCode && res.statusCode <= 299) {
34028
- resolve12({
34194
+ resolve13({
34029
34195
  status: "success"
34030
34196
  });
34031
34197
  } else if (res.statusCode && isExportHTTPErrorRetryable(res.statusCode)) {
34032
- resolve12({
34198
+ resolve13({
34033
34199
  status: "retryable",
34034
34200
  error: error63,
34035
34201
  retryInMillis: parseRetryAfterToMills(res.headers["retry-after"])
34036
34202
  });
34037
34203
  } else {
34038
- resolve12({
34204
+ resolve13({
34039
34205
  status: "failure",
34040
34206
  error: error63
34041
34207
  });
@@ -34044,26 +34210,26 @@ function sendWithHttp(request, url2, headers, compression, userAgent, agent, dat
34044
34210
  });
34045
34211
  req.setTimeout(timeoutMillis, () => {
34046
34212
  req.destroy();
34047
- resolve12({
34213
+ resolve13({
34048
34214
  status: "retryable",
34049
34215
  error: new Error("Request timed out")
34050
34216
  });
34051
34217
  });
34052
34218
  req.on("error", (error63) => {
34053
34219
  if (isHttpTransportNetworkErrorRetryable(error63)) {
34054
- resolve12({
34220
+ resolve13({
34055
34221
  status: "retryable",
34056
34222
  error: error63
34057
34223
  });
34058
34224
  } else {
34059
- resolve12({
34225
+ resolve13({
34060
34226
  status: "failure",
34061
34227
  error: error63
34062
34228
  });
34063
34229
  }
34064
34230
  });
34065
34231
  compressAndSend(req, compression, data, (error63) => {
34066
- resolve12({
34232
+ resolve13({
34067
34233
  status: "failure",
34068
34234
  error: error63
34069
34235
  });
@@ -34153,9 +34319,9 @@ var RetryingTransport = class {
34153
34319
  this._transport = transport;
34154
34320
  }
34155
34321
  retry(data, timeoutMillis, inMillis) {
34156
- return new Promise((resolve12, reject) => {
34322
+ return new Promise((resolve13, reject) => {
34157
34323
  setTimeout(() => {
34158
- this._transport.send(data, timeoutMillis).then(resolve12, reject);
34324
+ this._transport.send(data, timeoutMillis).then(resolve13, reject);
34159
34325
  }, inMillis);
34160
34326
  });
34161
34327
  }
@@ -34268,8 +34434,8 @@ function getSharedConfigurationFromEnvironment(signalIdentifier) {
34268
34434
  init_esm();
34269
34435
 
34270
34436
  // ../../node_modules/@opentelemetry/otlp-exporter-base/build/esm/configuration/otlp-node-http-env-configuration.js
34271
- import * as fs6 from "fs";
34272
- import * as path12 from "path";
34437
+ import * as fs7 from "fs";
34438
+ import * as path13 from "path";
34273
34439
  init_esm();
34274
34440
  function getStaticHeadersFromEnv(signalIdentifier) {
34275
34441
  const signalSpecificRawHeaders = getStringFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_HEADERS`);
@@ -34290,7 +34456,7 @@ function appendRootPathToUrlIfNeeded(url2) {
34290
34456
  return void 0;
34291
34457
  }
34292
34458
  }
34293
- function appendResourcePathToUrl(url2, path24) {
34459
+ function appendResourcePathToUrl(url2, path25) {
34294
34460
  try {
34295
34461
  new URL(url2);
34296
34462
  } catch {
@@ -34300,11 +34466,11 @@ function appendResourcePathToUrl(url2, path24) {
34300
34466
  if (!url2.endsWith("/")) {
34301
34467
  url2 = url2 + "/";
34302
34468
  }
34303
- url2 += path24;
34469
+ url2 += path25;
34304
34470
  try {
34305
34471
  new URL(url2);
34306
34472
  } catch {
34307
- diag2.warn(`Configuration: Provided URL appended with '${path24}' is not a valid URL, using 'undefined' instead of '${url2}'`);
34473
+ diag2.warn(`Configuration: Provided URL appended with '${path25}' is not a valid URL, using 'undefined' instead of '${url2}'`);
34308
34474
  return void 0;
34309
34475
  }
34310
34476
  return url2;
@@ -34329,7 +34495,7 @@ function readFileFromEnv(signalSpecificEnvVar, nonSignalSpecificEnvVar, warningM
34329
34495
  const filePath = signalSpecificPath ?? nonSignalSpecificPath;
34330
34496
  if (filePath != null) {
34331
34497
  try {
34332
- return fs6.readFileSync(path12.resolve(process.cwd(), filePath));
34498
+ return fs7.readFileSync(path13.resolve(process.cwd(), filePath));
34333
34499
  } catch {
34334
34500
  diag2.warn(warningMessage);
34335
34501
  return void 0;
@@ -34415,15 +34581,15 @@ var OTLPLogExporter = class extends OTLPExporterBase {
34415
34581
  init_esm();
34416
34582
 
34417
34583
  // ../telemetry/src/debug.ts
34418
- import * as fs7 from "node:fs";
34584
+ import * as fs8 from "node:fs";
34419
34585
 
34420
34586
  // ../telemetry/src/paths.ts
34421
- import * as path13 from "node:path";
34587
+ import * as path14 from "node:path";
34422
34588
  function identityFilePath() {
34423
- return path13.join(argentHomeDir(), "telemetry-id");
34589
+ return path14.join(argentHomeDir(), "telemetry-id");
34424
34590
  }
34425
34591
  function debugLogPath() {
34426
- return path13.join(argentHomeDir(), "telemetry-debug.log");
34592
+ return path14.join(argentHomeDir(), "telemetry-debug.log");
34427
34593
  }
34428
34594
 
34429
34595
  // ../telemetry/src/debug.ts
@@ -34453,8 +34619,8 @@ function emitDebugPayload(payload) {
34453
34619
  } catch {
34454
34620
  }
34455
34621
  try {
34456
- fs7.mkdirSync(argentHomeDir(), { recursive: true });
34457
- fs7.appendFileSync(debugLogPath(), line + "\n");
34622
+ fs8.mkdirSync(argentHomeDir(), { recursive: true });
34623
+ fs8.appendFileSync(debugLogPath(), line + "\n");
34458
34624
  } catch {
34459
34625
  }
34460
34626
  }
@@ -34825,6 +34991,7 @@ var ALLOWED = {
34825
34991
  "tool:invoke": {
34826
34992
  device_provider: DEVICE_PROVIDER,
34827
34993
  tool: TOOL_NAME,
34994
+ alias_used: bool,
34828
34995
  tool_invocation_id: UUID,
34829
34996
  platform: PLATFORM,
34830
34997
  device_kind: DEVICE_KIND,
@@ -34833,6 +35000,7 @@ var ALLOWED = {
34833
35000
  "tool:complete": {
34834
35001
  device_provider: DEVICE_PROVIDER,
34835
35002
  tool: TOOL_NAME,
35003
+ alias_used: bool,
34836
35004
  tool_invocation_id: UUID,
34837
35005
  platform: PLATFORM,
34838
35006
  device_kind: DEVICE_KIND,
@@ -34842,6 +35010,7 @@ var ALLOWED = {
34842
35010
  "tool:fail": {
34843
35011
  device_provider: DEVICE_PROVIDER,
34844
35012
  tool: TOOL_NAME,
35013
+ alias_used: bool,
34845
35014
  tool_invocation_id: UUID,
34846
35015
  platform: PLATFORM,
34847
35016
  device_kind: DEVICE_KIND,
@@ -34860,6 +35029,7 @@ var ALLOWED = {
34860
35029
  },
34861
35030
  "cli:run_fail": {
34862
35031
  tool: TOOL_NAME,
35032
+ alias_used: bool,
34863
35033
  duration_ms: DURATION_MS,
34864
35034
  ...FAILURE_SIGNAL
34865
35035
  },
@@ -34956,9 +35126,9 @@ function isReplitAgent(env) {
34956
35126
  }
34957
35127
  var DEVIN_MARKER_PATH = "/opt/.devin";
34958
35128
  var JULES_MARKER_PATH = "/opt/environment_summary.sh";
34959
- function safeExists(fileExists, path24) {
35129
+ function safeExists(fileExists, path25) {
34960
35130
  try {
34961
- return fileExists(path24);
35131
+ return fileExists(path25);
34962
35132
  } catch {
34963
35133
  return false;
34964
35134
  }
@@ -35379,7 +35549,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
35379
35549
  var SESSION_ID2 = randomUUID5();
35380
35550
  function readCliVersion() {
35381
35551
  if (true) {
35382
- return "0.29.1-next.21";
35552
+ return "0.29.1-next.23";
35383
35553
  }
35384
35554
  return "0.0.0";
35385
35555
  }
@@ -35412,8 +35582,8 @@ function getBaseProps(runtime) {
35412
35582
 
35413
35583
  // ../telemetry/src/identity.ts
35414
35584
  import * as crypto2 from "node:crypto";
35415
- import * as fs8 from "node:fs";
35416
- import * as path14 from "node:path";
35585
+ import * as fs9 from "node:fs";
35586
+ import * as path15 from "node:path";
35417
35587
  var FINGERPRINT_PATTERN = /^[0-9a-f]{64}$/;
35418
35588
  var cached2 = null;
35419
35589
  var fingerprintResolved = null;
@@ -35509,66 +35679,66 @@ function resolveFingerprintOnce(resolveFingerprint) {
35509
35679
  function isCorruptIdFile(filePath) {
35510
35680
  let isRegularFile;
35511
35681
  try {
35512
- isRegularFile = fs8.lstatSync(filePath).isFile();
35682
+ isRegularFile = fs9.lstatSync(filePath).isFile();
35513
35683
  } catch {
35514
35684
  return false;
35515
35685
  }
35516
35686
  return isRegularFile && tryReadId(filePath) === null;
35517
35687
  }
35518
35688
  function writeIdFileAtomic(finalPath, id) {
35519
- fs8.mkdirSync(argentHomeDir(), { recursive: true });
35689
+ fs9.mkdirSync(argentHomeDir(), { recursive: true });
35520
35690
  let occupant;
35521
35691
  try {
35522
- occupant = fs8.lstatSync(finalPath);
35692
+ occupant = fs9.lstatSync(finalPath);
35523
35693
  } catch (err) {
35524
35694
  if (err.code !== "ENOENT") throw err;
35525
35695
  }
35526
35696
  if (occupant && !occupant.isFile()) {
35527
35697
  throw new Error("telemetry: refusing to replace a non-regular file at the identity path");
35528
35698
  }
35529
- const tmpPath = path14.join(
35699
+ const tmpPath = path15.join(
35530
35700
  argentHomeDir(),
35531
35701
  `.telemetry-id.tmp.${process.pid}.${crypto2.randomUUID()}`
35532
35702
  );
35533
- const fd = fs8.openSync(tmpPath, "wx", 384);
35703
+ const fd = fs9.openSync(tmpPath, "wx", 384);
35534
35704
  try {
35535
35705
  try {
35536
- fs8.writeSync(fd, id);
35537
- fs8.fsyncSync(fd);
35706
+ fs9.writeSync(fd, id);
35707
+ fs9.fsyncSync(fd);
35538
35708
  } finally {
35539
- fs8.closeSync(fd);
35709
+ fs9.closeSync(fd);
35540
35710
  }
35541
- fs8.renameSync(tmpPath, finalPath);
35711
+ fs9.renameSync(tmpPath, finalPath);
35542
35712
  } finally {
35543
35713
  try {
35544
- fs8.unlinkSync(tmpPath);
35714
+ fs9.unlinkSync(tmpPath);
35545
35715
  } catch {
35546
35716
  }
35547
35717
  }
35548
35718
  }
35549
35719
  function mintRandomId(finalPath) {
35550
- fs8.mkdirSync(argentHomeDir(), { recursive: true });
35720
+ fs9.mkdirSync(argentHomeDir(), { recursive: true });
35551
35721
  let value = crypto2.randomUUID();
35552
35722
  for (let attempt = 0; attempt < 3; attempt++) {
35553
- const tmpPath = path14.join(
35723
+ const tmpPath = path15.join(
35554
35724
  argentHomeDir(),
35555
35725
  `.telemetry-id.tmp.${process.pid}.${crypto2.randomUUID()}`
35556
35726
  );
35557
35727
  let fd;
35558
35728
  try {
35559
- fd = fs8.openSync(tmpPath, "wx", 384);
35729
+ fd = fs9.openSync(tmpPath, "wx", 384);
35560
35730
  } catch (err) {
35561
35731
  if (err.code === "EEXIST") continue;
35562
35732
  throw err;
35563
35733
  }
35564
35734
  try {
35565
35735
  try {
35566
- fs8.writeSync(fd, value);
35567
- fs8.fsyncSync(fd);
35736
+ fs9.writeSync(fd, value);
35737
+ fs9.fsyncSync(fd);
35568
35738
  } finally {
35569
- fs8.closeSync(fd);
35739
+ fs9.closeSync(fd);
35570
35740
  }
35571
- fs8.linkSync(tmpPath, finalPath);
35741
+ fs9.linkSync(tmpPath, finalPath);
35572
35742
  cached2 = { path: finalPath, id: value };
35573
35743
  return value;
35574
35744
  } catch (err) {
@@ -35587,7 +35757,7 @@ function mintRandomId(finalPath) {
35587
35757
  throw err;
35588
35758
  } finally {
35589
35759
  try {
35590
- fs8.unlinkSync(tmpPath);
35760
+ fs9.unlinkSync(tmpPath);
35591
35761
  } catch {
35592
35762
  }
35593
35763
  }
@@ -35595,12 +35765,12 @@ function mintRandomId(finalPath) {
35595
35765
  throw new Error("telemetry: failed to create identity after retries");
35596
35766
  }
35597
35767
  function claimCorruptOccupant(finalPath) {
35598
- const claimed = path14.join(
35768
+ const claimed = path15.join(
35599
35769
  argentHomeDir(),
35600
35770
  `.telemetry-id.corrupt.${process.pid}.${crypto2.randomUUID()}`
35601
35771
  );
35602
35772
  try {
35603
- fs8.renameSync(finalPath, claimed);
35773
+ fs9.renameSync(finalPath, claimed);
35604
35774
  } catch {
35605
35775
  return null;
35606
35776
  }
@@ -35609,7 +35779,7 @@ function claimCorruptOccupant(finalPath) {
35609
35779
  grabbed = tryReadId(claimed);
35610
35780
  } finally {
35611
35781
  try {
35612
- fs8.unlinkSync(claimed);
35782
+ fs9.unlinkSync(claimed);
35613
35783
  } catch {
35614
35784
  }
35615
35785
  }
@@ -35621,9 +35791,9 @@ function peekAnonId() {
35621
35791
  function tryReadId(filePath) {
35622
35792
  let raw;
35623
35793
  try {
35624
- const stats = fs8.lstatSync(filePath);
35794
+ const stats = fs9.lstatSync(filePath);
35625
35795
  if (!stats.isFile()) return null;
35626
- raw = fs8.readFileSync(filePath, "utf8");
35796
+ raw = fs9.readFileSync(filePath, "utf8");
35627
35797
  } catch (err) {
35628
35798
  if (err.code === "ENOENT") return null;
35629
35799
  return null;
@@ -35637,12 +35807,12 @@ function tryReadId(filePath) {
35637
35807
  import { execFileSync as execFileSync2, spawn as spawn2 } from "node:child_process";
35638
35808
 
35639
35809
  // ../native-devtools-ios/src/index.ts
35640
- import * as path15 from "node:path";
35641
- import * as fs9 from "node:fs";
35642
- var DYLIB_DIR = process.env.ARGENT_NATIVE_DEVTOOLS_DIR ?? path15.join(__dirname, "..", "dylibs");
35643
- var BIN_DIR = process.env.ARGENT_SIMULATOR_SERVER_DIR ?? path15.join(__dirname, "..", "bin");
35644
- var DYLIB_TCP_DIR = process.env.ARGENT_NATIVE_DEVTOOLS_TCP_DIR ?? path15.join(DYLIB_DIR, "tcp");
35645
- var DYLIB_TVOS_DIR = path15.join(DYLIB_DIR, "tvos");
35810
+ import * as path16 from "node:path";
35811
+ import * as fs10 from "node:fs";
35812
+ var DYLIB_DIR = process.env.ARGENT_NATIVE_DEVTOOLS_DIR ?? path16.join(__dirname, "..", "dylibs");
35813
+ var BIN_DIR = process.env.ARGENT_SIMULATOR_SERVER_DIR ?? path16.join(__dirname, "..", "bin");
35814
+ var DYLIB_TCP_DIR = process.env.ARGENT_NATIVE_DEVTOOLS_TCP_DIR ?? path16.join(DYLIB_DIR, "tcp");
35815
+ var DYLIB_TVOS_DIR = path16.join(DYLIB_DIR, "tvos");
35646
35816
  function hostPlatformKey() {
35647
35817
  if (process.platform === "linux" && process.arch === "arm64") {
35648
35818
  return "linux-arm64";
@@ -35653,14 +35823,14 @@ function simulatorServerBinaryName() {
35653
35823
  return process.platform === "win32" ? "simulator-server.exe" : "simulator-server";
35654
35824
  }
35655
35825
  function platformBinDir() {
35656
- return path15.join(BIN_DIR, hostPlatformKey());
35826
+ return path16.join(BIN_DIR, hostPlatformKey());
35657
35827
  }
35658
35828
  function simulatorServerBinaryPath() {
35659
35829
  const binaryName = simulatorServerBinaryName();
35660
- const p = path15.join(platformBinDir(), binaryName);
35661
- if (!fs9.existsSync(p)) {
35662
- const flat = path15.join(BIN_DIR, binaryName);
35663
- const migrationHint = fs9.existsSync(flat) ? ` Found a binary at the old flat path ${flat}; move it to ${p} or update ARGENT_SIMULATOR_SERVER_DIR to point at the parent of the platform subdirectory.` : "";
35830
+ const p = path16.join(platformBinDir(), binaryName);
35831
+ if (!fs10.existsSync(p)) {
35832
+ const flat = path16.join(BIN_DIR, binaryName);
35833
+ const migrationHint = fs10.existsSync(flat) ? ` Found a binary at the old flat path ${flat}; move it to ${p} or update ARGENT_SIMULATOR_SERVER_DIR to point at the parent of the platform subdirectory.` : "";
35664
35834
  throw new Error(
35665
35835
  `simulator-server binary not found for platform "${hostPlatformKey()}" at ${p}. Supported hosts today: darwin, linux (x86_64 and arm64), win32.${migrationHint}`
35666
35836
  );
@@ -35689,12 +35859,12 @@ function resolveHostFingerprint() {
35689
35859
  }
35690
35860
  }
35691
35861
  function resolveHostFingerprintAsync() {
35692
- return new Promise((resolve12) => {
35862
+ return new Promise((resolve13) => {
35693
35863
  let binary;
35694
35864
  try {
35695
35865
  binary = simulatorServerBinaryPath();
35696
35866
  } catch {
35697
- resolve12(null);
35867
+ resolve13(null);
35698
35868
  return;
35699
35869
  }
35700
35870
  let settled = false;
@@ -35707,7 +35877,7 @@ function resolveHostFingerprintAsync() {
35707
35877
  child?.kill("SIGKILL");
35708
35878
  } catch {
35709
35879
  }
35710
- resolve12(value);
35880
+ resolve13(value);
35711
35881
  };
35712
35882
  const watchdog = setTimeout(() => finish(null), FINGERPRINT_TIMEOUT_MS);
35713
35883
  watchdog.unref?.();
@@ -35740,14 +35910,14 @@ function resolveHostFingerprintAsync() {
35740
35910
  }
35741
35911
 
35742
35912
  // ../telemetry/src/consent.ts
35743
- import * as fs10 from "node:fs";
35913
+ import * as fs11 from "node:fs";
35744
35914
  var cache = /* @__PURE__ */ new Map();
35745
35915
  var sessionOverride = null;
35746
35916
  function readConfigOverrideAt(filePath) {
35747
35917
  const miss = { mtimeMs: null, fingerprint: null, enabledOverride: null };
35748
35918
  let stats;
35749
35919
  try {
35750
- stats = fs10.lstatSync(filePath);
35920
+ stats = fs11.lstatSync(filePath);
35751
35921
  } catch {
35752
35922
  cache.set(filePath, miss);
35753
35923
  return null;
@@ -35764,7 +35934,7 @@ function readConfigOverrideAt(filePath) {
35764
35934
  }
35765
35935
  let parsedEnabled = null;
35766
35936
  try {
35767
- const raw = fs10.readFileSync(filePath, "utf8");
35937
+ const raw = fs11.readFileSync(filePath, "utf8");
35768
35938
  const json2 = JSON.parse(raw);
35769
35939
  if (json2 && typeof json2 === "object") {
35770
35940
  const t2 = json2.telemetry;
@@ -35921,7 +36091,7 @@ var DRAIN_GRACE_MS = 250;
35921
36091
  async function raceDrain(client2, timeoutMs) {
35922
36092
  await Promise.race([
35923
36093
  client2.shutdown(timeoutMs),
35924
- new Promise((resolve12) => setTimeout(resolve12, timeoutMs + DRAIN_GRACE_MS).unref())
36094
+ new Promise((resolve13) => setTimeout(resolve13, timeoutMs + DRAIN_GRACE_MS).unref())
35925
36095
  ]);
35926
36096
  }
35927
36097
  async function shutdown(timeoutMs = SHORT_FLUSH_TIMEOUT_MS) {
@@ -36345,13 +36515,13 @@ function splitOptions(argv) {
36345
36515
  return { json: json2, outPath, argvForFlags: rest };
36346
36516
  }
36347
36517
  async function readStdin() {
36348
- return new Promise((resolve12, reject) => {
36518
+ return new Promise((resolve13, reject) => {
36349
36519
  let data = "";
36350
36520
  process.stdin.setEncoding("utf8");
36351
36521
  process.stdin.on("data", (chunk) => {
36352
36522
  data += chunk;
36353
36523
  });
36354
- process.stdin.on("end", () => resolve12(data));
36524
+ process.stdin.on("end", () => resolve13(data));
36355
36525
  process.stdin.on("error", reject);
36356
36526
  });
36357
36527
  }
@@ -36383,8 +36553,8 @@ async function fetchImageToFile(result, outPath) {
36383
36553
  const res = await fetch(url2);
36384
36554
  if (!res.ok) throw new Error(`Failed to download image: ${res.status} ${res.statusText}`);
36385
36555
  const buf = Buffer.from(await res.arrayBuffer());
36386
- fs11.mkdirSync(path16.dirname(path16.resolve(outPath)), { recursive: true });
36387
- fs11.writeFileSync(outPath, buf);
36556
+ fs12.mkdirSync(path17.dirname(path17.resolve(outPath)), { recursive: true });
36557
+ fs12.writeFileSync(outPath, buf);
36388
36558
  }
36389
36559
  function renderResult(result, outputHint, images, json2) {
36390
36560
  if (json2) return JSON.stringify(result, null, 2);
@@ -36402,8 +36572,10 @@ function safeToolName(toolName) {
36402
36572
  return toolName && SAFE_TOOL_RE.test(toolName) ? toolName : "unknown";
36403
36573
  }
36404
36574
  async function trackRunFailure(toolName, startedAt, signal) {
36575
+ const tool = toolName ? canonicalToolId(toolName) : toolName;
36405
36576
  track("cli:run_fail", {
36406
- tool: safeToolName(toolName),
36577
+ tool: safeToolName(tool),
36578
+ ...tool !== toolName ? { alias_used: true } : {},
36407
36579
  duration_ms: performance.now() - startedAt,
36408
36580
  ...signal
36409
36581
  });
@@ -36578,8 +36750,8 @@ Examples:
36578
36750
  if (outPath && meta3.outputHint === "image") {
36579
36751
  try {
36580
36752
  if (images.length > 0) {
36581
- fs11.mkdirSync(path16.dirname(path16.resolve(outPath)), { recursive: true });
36582
- fs11.writeFileSync(outPath, images[0].data);
36753
+ fs12.mkdirSync(path17.dirname(path17.resolve(outPath)), { recursive: true });
36754
+ fs12.writeFileSync(outPath, images[0].data);
36583
36755
  } else if (result && typeof result === "object") {
36584
36756
  await fetchImageToFile(result, outPath);
36585
36757
  }
@@ -36601,11 +36773,11 @@ Examples:
36601
36773
  }
36602
36774
  }
36603
36775
 
36604
- // ../argent-cli/src/flow.ts
36776
+ // ../argent-cli/src/e2e.ts
36605
36777
  import * as fsp from "node:fs/promises";
36606
36778
  import { constants as fsConstants2 } from "node:fs";
36607
36779
  import { createHash as createHash5 } from "node:crypto";
36608
- import * as path17 from "node:path";
36780
+ import * as path18 from "node:path";
36609
36781
 
36610
36782
  // ../argent-cli/src/command-args.ts
36611
36783
  var UsageError = class extends Error {
@@ -36677,7 +36849,7 @@ function parseCommandArgs(argv, specs) {
36677
36849
  return { positionals, options };
36678
36850
  }
36679
36851
 
36680
- // ../argent-cli/src/flow.ts
36852
+ // ../argent-cli/src/e2e.ts
36681
36853
  var STATUS_GLYPH = {
36682
36854
  pass: "\u2713",
36683
36855
  fail: "\u2717",
@@ -36698,93 +36870,96 @@ function durationSuffix(ms) {
36698
36870
  }
36699
36871
  function printHelp(toStderr = false) {
36700
36872
  const print = toStderr ? console.error : console.log;
36701
- print(`Usage: argent flow <subcommand> [options]
36873
+ print(`Usage: argent e2e <subcommand> [options]
36702
36874
 
36703
- Run a YAML flow without an LLM in the loop. \`run\` takes any of these forms:
36875
+ Run a YAML e2e test without an LLM in the loop. \`run\` takes any of these forms:
36704
36876
 
36705
- a name A flow saved under .argent/flows \u2014 "checkout" runs
36706
- .argent/flows/checkout.yaml, resolved from the current directory
36877
+ a name An e2e test saved under .argent/e2e or .argent/flows, resolved
36878
+ from the current directory. "checkout" runs
36879
+ .argent/e2e/checkout.yaml, or .argent/flows/checkout.yaml when only
36880
+ that one exists
36707
36881
  a path Any .yaml file on the local filesystem, resolved from the current
36708
36882
  directory. It must not contain ".." segments (pass the resolved
36709
- path instead); a path is what reaches flows kept elsewhere, and
36710
- what \`argent flow list\` prints for nested ones
36711
- a dir Every flow in that directory, run sequentially
36883
+ path instead); a path is what reaches e2e tests kept elsewhere, and
36884
+ what \`argent e2e list\` prints for nested ones
36885
+ a dir Every e2e test in that directory, run sequentially
36712
36886
 
36713
36887
  For a name and for a file path alike, the
36714
36888
  filename (minus .yaml) names the run's report and artifacts, so it must
36715
36889
  contain only letters, numbers, "_", or "-" \u2014 the same charset a name must
36716
- match. A flow is e2e when its first non-\`echo\`/\`script\` step is \`launch\`.
36717
- Other flows are fragments and use the device's current state. Exception: a fragment whose first step \`run:\`s a chromium e2e
36718
- flow boots that flow's app before step 1 \u2014 when that launch is unambiguously
36890
+ match. A test is standalone when its first non-\`echo\`/\`script\` step is \`launch\`.
36891
+ Other tests are fragments and use the device's current state. Exception: a fragment whose first step \`run:\`s a chromium standalone
36892
+ test boots that test's app before step 1 \u2014 when that launch is unambiguously
36719
36893
  chromium (a lone \`{ chromium: ... }\` target, or --platform chromium); a
36720
36894
  multi-platform launch auto-detects a device instead. Pass --device to attach to
36721
36895
  a running instance.
36722
36896
 
36723
36897
  A directory run prints only the steps that need attention (each failure, each
36724
- warning, and each script step's output), then its outcome. After the last flow
36725
- it lists every failed flow with its reason and a command that re-runs that flow
36726
- alone, then a final flow summary; --recursive walks subdirectories too
36727
- (dot-directories and node_modules are skipped). A flow that fails its steps
36898
+ warning, and each script step's output), then its outcome. After the last test
36899
+ it lists every failed test with its reason and a command that re-runs that test
36900
+ alone, then a final summary; --recursive walks subdirectories too
36901
+ (dot-directories and node_modules are skipped). A test that fails its steps
36728
36902
  keeps the batch running, as does one the server rejects up front \u2014 an invalid
36729
36903
  file, or a device it cannot resolve. A transport failure, a rejection the server
36730
36904
  does not mark as validation, or a reply that is not a report stops the batch and
36731
- counts the remaining flows skipped.
36905
+ counts the remaining tests skipped.
36732
36906
 
36733
36907
  The CLI sends a run to its tool-server: the local one that starts
36734
36908
  automatically, or the one that \`argent link\` or ARGENT_TOOLS_URL names. Over
36735
36909
  a link, the CLI uploads these files and writes the new baselines that the run
36736
36910
  returns:
36737
- - the flow file and the run: fragments that it reaches
36738
- - each flow that a tool: flow-execute step names with name (a nested flow)
36911
+ - the e2e test file and the run: fragments that it reaches
36912
+ - each e2e test that a tool: e2e-execute step names with name (a nested test)
36739
36913
  - the snapshot baselines of each run
36740
36914
  - each .png or .yaml file that a tool: step takes as a file argument by an
36741
36915
  absolute path
36742
- The tool-server rejects the flow before the first step when the flow, a
36743
- fragment or a nested flow has one of these steps:
36916
+ The tool-server rejects the test before the first step when the test, a
36917
+ fragment or a nested test has one of these steps:
36744
36918
  - a script: step
36745
- - a tool: flow-execute step that does not name its flow with name and an
36919
+ - a tool: e2e-execute step that does not name its test with name and an
36746
36920
  absolute project_root that has no .. segment
36747
- - a tool: step that records a flow
36921
+ - a tool: step that records an e2e test
36748
36922
  - a tool: step that takes a directory, an app or an output directory
36749
36923
  - a tool: step whose tool builds a file path from several arguments
36750
36924
  - a tool: step that names a relative path or a file other than .png or .yaml
36751
36925
  Without a link, all step kinds run.
36752
36926
 
36753
36927
  Subcommands:
36754
- run <flow|flow.yaml|dir> Run a saved flow by name, a YAML file by path, or
36755
- every flow in a directory, and report pass/fail
36928
+ run <test|test.yaml|dir> Run a saved e2e test by name, a YAML file by path,
36929
+ or every test in a directory, and report pass/fail
36756
36930
  (exit reflects result)
36757
- list List runnable YAML paths in .argent/flows
36931
+ list List runnable YAML paths in .argent/e2e and
36932
+ .argent/flows (legacy); notes go to stderr
36758
36933
 
36759
36934
  Options (run):
36760
36935
  --device <id> Device id to run against (auto-detected when omitted)
36761
36936
  --platform <p> ios | android | chromium | vega | ios-remote \u2014 narrow
36762
36937
  auto-detection (ios never picks a remote simulator)
36763
36938
  --update-baselines Write/refresh screenshot baselines instead of diffing,
36764
- also those of flows that tool: flow-execute steps run,
36939
+ also those of tests that tool: e2e-execute steps run,
36765
36940
  unless such a step sets updateBaselines
36766
36941
  --output <dir> Also write failed snapshot images (baseline/current/diff)
36767
36942
  and failed-step screenshots (step-<n>-screen.png)
36768
- under <dir>/<flow>/ \u2014 a stable path for CI artifact
36769
- upload; a directory run keys nested flows as
36770
- <dir>/<subdir>/<flow>/. A different flow file with the
36771
- same filename sharing <dir> exports to <flow>-<pathhash>/
36772
- instead (with a warning), so no flow's evidence is
36943
+ under <dir>/<test>/ \u2014 a stable path for CI artifact
36944
+ upload; a directory run keys nested tests as
36945
+ <dir>/<subdir>/<test>/. A different test file with the
36946
+ same filename sharing <dir> exports to <test>-<pathhash>/
36947
+ instead (with a warning), so no test's evidence is
36773
36948
  overwritten
36774
- -r, --recursive With a directory path, also run flows in subdirectories
36775
- --json Print the flow's JSON report, or a directory run's JSON
36949
+ -r, --recursive With a directory path, also run tests in subdirectories
36950
+ --json Print the test's JSON report, or a directory run's JSON
36776
36951
  aggregate
36777
36952
  --json-stream Print each step and the final report as NDJSON (single
36778
- flow only, never with --json)
36953
+ test only, never with --json)
36779
36954
  --help, -h Show this help
36780
- -- End of options \u2014 only needed for a flow whose name
36781
- starts with "-" (\`argent flow run -- -nightly\`)
36955
+ -- End of options \u2014 only needed for a test whose name
36956
+ starts with "-" (\`argent e2e run -- -nightly\`)
36782
36957
 
36783
36958
  Examples:
36784
- argent flow run checkout --platform ios
36785
- argent flow run .argent/flows/checkout.yaml --output flow-artifacts --json
36786
- argent flow run ~/shared-flows/checkout.yaml --device <UDID> --update-baselines
36787
- argent flow run .argent/flows --recursive
36959
+ argent e2e run checkout --platform ios
36960
+ argent e2e run .argent/e2e/checkout.yaml --output e2e-artifacts --json
36961
+ argent e2e run ~/shared-e2e/checkout.yaml --device <UDID> --update-baselines
36962
+ argent e2e run .argent/e2e --recursive
36788
36963
  `);
36789
36964
  }
36790
36965
  var RUN_OPTIONS = {
@@ -36807,7 +36982,7 @@ function parseRunArgs(argv) {
36807
36982
  const { positionals, options } = parsed;
36808
36983
  if (positionals.length > 1) {
36809
36984
  throw new FlagParseException(
36810
- `unexpected argument ${JSON.stringify(positionals[1])}; flow run accepts one flow name, YAML file path, or directory path`
36985
+ `unexpected argument ${JSON.stringify(positionals[1])}; e2e run accepts one e2e test name, YAML file path, or directory path`
36811
36986
  );
36812
36987
  }
36813
36988
  const out = {
@@ -36907,7 +37082,7 @@ function renderFailedSteps(report) {
36907
37082
  return lines;
36908
37083
  }
36909
37084
  function renderBatchSummary(counts, durationMs) {
36910
- return `${counts.failed === 0 ? "PASS" : "FAIL"} \u2014 ${counts.total} flow${counts.total === 1 ? "" : "s"}: ${counts.passed} passed, ${counts.failed} failed, ${counts.skipped} skipped${durationSuffix(durationMs)}`;
37085
+ return `${counts.failed === 0 ? "PASS" : "FAIL"} \u2014 ${counts.total} e2e test${counts.total === 1 ? "" : "s"}: ${counts.passed} passed, ${counts.failed} failed, ${counts.skipped} skipped${durationSuffix(durationMs)}`;
36911
37086
  }
36912
37087
  function summarizeFailure(report) {
36913
37088
  let n3 = 0;
@@ -36934,34 +37109,33 @@ function renderFailedFlows(failed) {
36934
37109
  if (failed.length === 0) return [];
36935
37110
  return [
36936
37111
  "",
36937
- `Failed flows (${failed.length})`,
37112
+ `Failed e2e tests (${failed.length})`,
36938
37113
  ...failed.flatMap((f) => ["", ...renderFailedFlow(f)])
36939
37114
  ];
36940
37115
  }
36941
37116
  var SAFE_ARTIFACT_NAME = FLOW_NAME_PATTERN;
36942
37117
  var SAFE_FLOW_NAME = FLOW_NAME_PATTERN;
36943
- var FLOWS_DIR = path17.join(".argent", "flows");
36944
37118
  var SHELL_SAFE_ARG = /^(?!=)[A-Za-z0-9_@%+=:,./-]+$/;
36945
37119
  function shellQuoteArg(arg) {
36946
37120
  if (SHELL_SAFE_ARG.test(arg)) return arg;
36947
37121
  return `'${arg.replaceAll("'", "'\\''")}'`;
36948
37122
  }
36949
37123
  function rerunCommand(flowPath, rel, projectRoot, args) {
36950
- const pathArg = (p) => shellQuoteArg(p.startsWith("-") ? `.${path17.sep}${p}` : p);
36951
- const fromCwd = path17.relative(projectRoot, flowPath);
36952
- const shown = path17.isAbsolute(fromCwd) || fromCwd.split(/[\\/]+/).includes("..") ? flowPath : fromCwd;
36953
- const parts = ["argent flow run", pathArg(shown)];
37124
+ const pathArg = (p) => shellQuoteArg(p.startsWith("-") ? `.${path18.sep}${p}` : p);
37125
+ const fromCwd = path18.relative(projectRoot, flowPath);
37126
+ const shown = path18.isAbsolute(fromCwd) || fromCwd.split(/[\\/]+/).includes("..") ? flowPath : fromCwd;
37127
+ const parts = ["argent e2e run", pathArg(shown)];
36954
37128
  if (args.device) parts.push("--device", shellQuoteArg(args.device));
36955
37129
  if (args.platform) parts.push("--platform", shellQuoteArg(args.platform));
36956
37130
  if (args.updateBaselines) parts.push("--update-baselines");
36957
- if (args.output) parts.push("--output", pathArg(path17.join(args.output, path17.dirname(rel))));
37131
+ if (args.output) parts.push("--output", pathArg(path18.join(args.output, path18.dirname(rel))));
36958
37132
  return parts.join(" ");
36959
37133
  }
36960
37134
  var EXPORT_SOURCE_MARKER = ".argent-flow-source";
36961
37135
  var MARKER_READ_RETRIES = 4;
36962
37136
  var MARKER_READ_DELAY_MS = 5;
36963
37137
  async function readExportMarker(dir) {
36964
- const marker = path17.join(dir, EXPORT_SOURCE_MARKER);
37138
+ const marker = path18.join(dir, EXPORT_SOURCE_MARKER);
36965
37139
  for (let attempt = 0; ; attempt++) {
36966
37140
  let owner;
36967
37141
  try {
@@ -36971,7 +37145,7 @@ async function readExportMarker(dir) {
36971
37145
  }
36972
37146
  if (owner) return owner;
36973
37147
  if (attempt === MARKER_READ_RETRIES) return null;
36974
- await new Promise((resolve12) => setTimeout(resolve12, MARKER_READ_DELAY_MS));
37148
+ await new Promise((resolve13) => setTimeout(resolve13, MARKER_READ_DELAY_MS));
36975
37149
  }
36976
37150
  }
36977
37151
  async function classifyExportDir(dir, flowPath) {
@@ -36996,7 +37170,7 @@ function occupiedBy(owner) {
36996
37170
  async function takeExportDir(dir, flowPath) {
36997
37171
  try {
36998
37172
  await fsp.mkdir(dir, { recursive: true });
36999
- await fsp.writeFile(path17.join(dir, EXPORT_SOURCE_MARKER), `${flowPath}
37173
+ await fsp.writeFile(path18.join(dir, EXPORT_SOURCE_MARKER), `${flowPath}
37000
37174
  `, { flag: "wx" });
37001
37175
  return null;
37002
37176
  } catch (err) {
@@ -37015,7 +37189,7 @@ async function claimExportDirName(outputDir, flowPath, stem) {
37015
37189
  }
37016
37190
  const avoided = [];
37017
37191
  for (const name of candidates) {
37018
- const dir = path17.join(outputDir, name);
37192
+ const dir = path18.join(outputDir, name);
37019
37193
  const claim2 = await classifyExportDir(dir, flowPath);
37020
37194
  const reason = claim2.state === "foreign" ? occupiedBy(claim2.owner) : await takeExportDir(dir, flowPath);
37021
37195
  if (reason !== null) {
@@ -37024,7 +37198,7 @@ async function claimExportDirName(outputDir, flowPath, stem) {
37024
37198
  }
37025
37199
  for (const entry of avoided) {
37026
37200
  console.error(
37027
- `warning: ${entry.dir} ${entry.reason}; writing this flow's artifacts to ${dir} so neither set is overwritten`
37201
+ `warning: ${entry.dir} ${entry.reason}; writing this e2e test's artifacts to ${dir} so neither set is overwritten`
37028
37202
  );
37029
37203
  }
37030
37204
  return name;
@@ -37035,10 +37209,10 @@ async function claimExportDirName(outputDir, flowPath, stem) {
37035
37209
  return null;
37036
37210
  }
37037
37211
  async function exportFailureArtifacts(report, outputDir, flowPath, ctx) {
37038
- const stem = path17.basename(flowPath, ".yaml");
37212
+ const stem = path18.basename(flowPath, ".yaml");
37039
37213
  if (!SAFE_ARTIFACT_NAME.test(stem)) {
37040
37214
  console.error(
37041
- `warning: skipping artifact export for unsafe flow filename ${JSON.stringify(stem)}`
37215
+ `warning: skipping artifact export for unsafe e2e test filename ${JSON.stringify(stem)}`
37042
37216
  );
37043
37217
  return;
37044
37218
  }
@@ -37068,11 +37242,11 @@ async function exportFailureArtifacts(report, outputDir, flowPath, ctx) {
37068
37242
  if (dir === null) {
37069
37243
  const dirName = await claimExportDirName(outputDir, flowPath, stem);
37070
37244
  if (dirName === null) return;
37071
- dir = path17.join(outputDir, dirName);
37245
+ dir = path18.join(outputDir, dirName);
37072
37246
  }
37073
- const dest = path17.join(dir, fileName(role));
37074
- const rel = path17.relative(outputDir, dest);
37075
- if (rel.startsWith("..") || path17.isAbsolute(rel)) continue;
37247
+ const dest = path18.join(dir, fileName(role));
37248
+ const rel = path18.relative(outputDir, dest);
37249
+ if (rel.startsWith("..") || path18.isAbsolute(rel)) continue;
37076
37250
  try {
37077
37251
  await fsp.copyFile(value, dest);
37078
37252
  s.artifacts[role] = dest;
@@ -37087,7 +37261,7 @@ async function exportFailureArtifacts(report, outputDir, flowPath, ctx) {
37087
37261
  function keyFromBaselinePath(artifacts) {
37088
37262
  const baseline = artifacts.baseline;
37089
37263
  if (typeof baseline !== "string") return null;
37090
- return path17.basename(baseline).replace(/\.png$/, "");
37264
+ return path18.basename(baseline).replace(/\.png$/, "");
37091
37265
  }
37092
37266
  function resolveArtifactDisplayPaths(report) {
37093
37267
  for (const s of report.steps) {
@@ -37099,12 +37273,12 @@ function resolveArtifactDisplayPaths(report) {
37099
37273
  }
37100
37274
  function exitAfterFlush(code, streams = [process.stdout, process.stderr]) {
37101
37275
  return Promise.all(
37102
- streams.map((s) => new Promise((resolve12) => s.write("", () => resolve12())))
37276
+ streams.map((s) => new Promise((resolve13) => s.write("", () => resolve13())))
37103
37277
  ).then(() => process.exit(code));
37104
37278
  }
37105
37279
  function renderReport(report) {
37106
37280
  const lines = [];
37107
- lines.push(`Flow "${report.flow}"${report.device ? ` on ${report.device}` : ""}`);
37281
+ lines.push(`E2E test "${report.flow}"${report.device ? ` on ${report.device}` : ""}`);
37108
37282
  if (report.executionPrerequisite) {
37109
37283
  lines.push(` assumes: ${report.executionPrerequisite}`);
37110
37284
  }
@@ -37132,8 +37306,8 @@ ${renderSummary(report)}`);
37132
37306
  }
37133
37307
  async function isRunnableFlowFile(filePath) {
37134
37308
  try {
37135
- const stat6 = await fsp.stat(filePath);
37136
- if (!stat6.isFile()) return false;
37309
+ const stat7 = await fsp.stat(filePath);
37310
+ if (!stat7.isFile()) return false;
37137
37311
  await fsp.access(filePath, fsConstants2.R_OK);
37138
37312
  return true;
37139
37313
  } catch {
@@ -37144,59 +37318,70 @@ async function collectRunnableFlowPaths(dir, relDir = "") {
37144
37318
  const found = [];
37145
37319
  const entries = await fsp.readdir(dir, { withFileTypes: true });
37146
37320
  for (const entry of entries) {
37147
- const rel = relDir ? path17.join(relDir, entry.name) : entry.name;
37321
+ const rel = relDir ? path18.join(relDir, entry.name) : entry.name;
37148
37322
  if (entry.isDirectory()) {
37149
37323
  if (entry.name === "__baselines__") continue;
37150
37324
  found.push(
37151
- ...await collectRunnableFlowPaths(path17.join(dir, entry.name), rel).catch(() => [])
37325
+ ...await collectRunnableFlowPaths(path18.join(dir, entry.name), rel).catch(() => [])
37152
37326
  );
37153
37327
  continue;
37154
37328
  }
37155
37329
  if (!entry.name.endsWith(".yaml")) continue;
37156
- if (!SAFE_FLOW_NAME.test(path17.basename(entry.name, ".yaml"))) continue;
37157
- if (await isRunnableFlowFile(path17.join(dir, entry.name))) found.push(rel);
37330
+ if (!SAFE_FLOW_NAME.test(path18.basename(entry.name, ".yaml"))) continue;
37331
+ if (await isRunnableFlowFile(path18.join(dir, entry.name))) found.push(rel);
37158
37332
  }
37159
37333
  return found;
37160
37334
  }
37161
- function resolveFlowRef(ref) {
37335
+ async function resolveFlowRef(ref, projectRoot) {
37162
37336
  if (!SAFE_FLOW_NAME.test(ref)) return { suppliedPath: ref, fromName: false };
37163
- return { suppliedPath: path17.join(FLOWS_DIR, `${ref}.yaml`), fromName: true };
37337
+ const picked = await resolveE2eFile(projectRoot, ref);
37338
+ return {
37339
+ suppliedPath: path18.relative(projectRoot, picked.path),
37340
+ fromName: true,
37341
+ ...picked.shadowed === void 0 ? {} : { shadowed: path18.relative(projectRoot, picked.shadowed) }
37342
+ };
37164
37343
  }
37165
37344
  async function savedFlowHint(projectRoot, missingPath) {
37166
- const dir = path17.resolve(projectRoot, FLOWS_DIR);
37167
- const within = path17.relative(dir, missingPath);
37168
- if (!within.startsWith("..") && !path17.isAbsolute(within)) return "";
37169
- const wanted = `${path17.basename(missingPath, ".yaml")}.yaml`;
37170
- const entries = await fsp.readdir(dir).catch(() => null);
37171
- if (entries === null) return "";
37172
- const actual = entries.includes(wanted) ? wanted : entries.find((name2) => name2.toLowerCase() === wanted.toLowerCase());
37173
- if (actual === void 0) return "";
37174
- const name = path17.basename(actual, ".yaml");
37175
- if (!SAFE_FLOW_NAME.test(name)) return "";
37176
- if (!await isRunnableFlowFile(path17.join(dir, actual))) return "";
37177
- return `
37178
- A flow named "${name}" is saved under ${FLOWS_DIR} \u2014 did you mean: argent flow run ${name}`;
37345
+ const dirs = E2E_DIRS.map((rel) => ({ rel, abs: path18.resolve(projectRoot, rel) }));
37346
+ for (const { abs } of dirs) {
37347
+ const within = path18.relative(abs, missingPath);
37348
+ if (!within.startsWith("..") && !path18.isAbsolute(within)) return "";
37349
+ }
37350
+ const wanted = `${path18.basename(missingPath, ".yaml")}.yaml`;
37351
+ for (const { rel, abs } of dirs) {
37352
+ const entries = await fsp.readdir(abs).catch(() => null);
37353
+ if (entries === null) continue;
37354
+ const actual = entries.includes(wanted) ? wanted : entries.find((name2) => name2.toLowerCase() === wanted.toLowerCase());
37355
+ if (actual === void 0) continue;
37356
+ const name = path18.basename(actual, ".yaml");
37357
+ if (!SAFE_FLOW_NAME.test(name)) return "";
37358
+ if (!await isRunnableFlowFile(path18.join(abs, actual))) return "";
37359
+ return `
37360
+ An e2e test named "${name}" is saved under ${rel} \u2014 did you mean: argent e2e run ${name}`;
37361
+ }
37362
+ return "";
37179
37363
  }
37180
37364
  async function collectFlowFiles(dir, recursive2) {
37181
37365
  const found = [];
37182
37366
  const walk = async (current, rel) => {
37183
37367
  for (const entry of await fsp.readdir(current, { withFileTypes: true })) {
37184
- const entryRel = rel ? path17.join(rel, entry.name) : entry.name;
37368
+ const entryRel = rel ? path18.join(rel, entry.name) : entry.name;
37185
37369
  if (entry.isDirectory()) {
37186
37370
  if (recursive2 && !entry.name.startsWith(".") && entry.name !== "node_modules") {
37187
- await walk(path17.join(current, entry.name), entryRel).catch(() => {
37371
+ await walk(path18.join(current, entry.name), entryRel).catch(() => {
37188
37372
  });
37189
37373
  }
37190
37374
  continue;
37191
37375
  }
37192
37376
  if (!entry.name.endsWith(".yaml")) continue;
37193
- if (!SAFE_FLOW_NAME.test(path17.basename(entry.name, ".yaml"))) continue;
37194
- if (await isRunnableFlowFile(path17.join(current, entry.name))) found.push(entryRel);
37377
+ if (!SAFE_FLOW_NAME.test(path18.basename(entry.name, ".yaml"))) continue;
37378
+ if (await isRunnableFlowFile(path18.join(current, entry.name))) found.push(entryRel);
37195
37379
  }
37196
37380
  };
37197
37381
  await walk(dir, "");
37198
37382
  return found.sort();
37199
37383
  }
37384
+ var RUN_TOOL_ID = "e2e-execute";
37200
37385
  function buildRunPayload(flowPath, projectRoot, args) {
37201
37386
  const payload = {
37202
37387
  flow_path: flowPath,
@@ -37278,7 +37463,7 @@ function rejectionVerdict(code) {
37278
37463
  case FAILURE_CODES.FLOW_FILE_INVALID:
37279
37464
  case FAILURE_CODES.FLOW_ENTRY_UNRECOGNIZED:
37280
37465
  case FAILURE_CODES.FLOW_E2E_HAS_PREREQUISITE:
37281
- return "not run (invalid flow)";
37466
+ return "not run (invalid e2e test)";
37282
37467
  case FAILURE_CODES.FLOW_DEVICE_RESOLUTION:
37283
37468
  return "not run (no device resolved)";
37284
37469
  case FAILURE_CODES.FILE_INPUT_UPLOAD_FAILED:
@@ -37287,6 +37472,20 @@ function rejectionVerdict(code) {
37287
37472
  return "not run (rejected)";
37288
37473
  }
37289
37474
  }
37475
+ function nestedStepWarnings(steps, into = /* @__PURE__ */ new Set()) {
37476
+ for (const s of steps) {
37477
+ if (!s || typeof s.result !== "object" || s.result === null) continue;
37478
+ const { warning, steps: inner } = s.result;
37479
+ if (typeof warning === "string" && warning !== s.warning) into.add(warning);
37480
+ if (Array.isArray(inner)) nestedStepWarnings(inner, into);
37481
+ }
37482
+ return [...into];
37483
+ }
37484
+ function printWarnings(warnings, json2) {
37485
+ for (const warning of warnings) {
37486
+ console.error(json2 ? JSON.stringify({ event: "warning", warning }) : `warning: ${warning}`);
37487
+ }
37488
+ }
37290
37489
  function isFlowReport(data) {
37291
37490
  const steps = data?.steps;
37292
37491
  return Array.isArray(steps) && steps.every((step) => !!step && typeof step === "object");
@@ -37311,15 +37510,15 @@ async function runFlowDirectory(dir, args, projectRoot, options) {
37311
37510
  try {
37312
37511
  flows = await collectFlowFiles(dir, args.recursive);
37313
37512
  } catch {
37314
- return reject(`Could not read flow directory: ${dir}`);
37513
+ return reject(`Could not read e2e test directory: ${dir}`);
37315
37514
  }
37316
37515
  if (flows.length === 0) {
37317
37516
  return reject(
37318
- `No flows found in ${dir}` + (args.recursive ? "" : "\nPass -r/--recursive to include subdirectories.")
37517
+ `No e2e tests found in ${dir}` + (args.recursive ? "" : "\nPass -r/--recursive to include subdirectories.")
37319
37518
  );
37320
37519
  }
37321
37520
  const { callTool, baseUrl } = runToolsClient(args, options);
37322
- const outputBase = args.output ? path17.resolve(args.output) : void 0;
37521
+ const outputBase = args.output ? path18.resolve(args.output) : void 0;
37323
37522
  const results = [];
37324
37523
  const failures = [];
37325
37524
  const batchStartedAt = Date.now();
@@ -37332,11 +37531,11 @@ async function runFlowDirectory(dir, args, projectRoot, options) {
37332
37531
  if (!args.json) console.log(` ${STATUS_GLYPH.skip} not run (batch stopped)`);
37333
37532
  continue;
37334
37533
  }
37335
- const flowPath = path17.join(dir, rel);
37534
+ const flowPath = path18.join(dir, rel);
37336
37535
  const rerun = rerunCommand(flowPath, rel, projectRoot, args);
37337
37536
  let report;
37338
37537
  try {
37339
- const resp = await callTool("flow-execute", buildRunPayload(flowPath, projectRoot, args));
37538
+ const resp = await callTool(RUN_TOOL_ID, buildRunPayload(flowPath, projectRoot, args));
37340
37539
  if (isFlowReport(resp.data)) report = resp.data;
37341
37540
  } catch (thrown) {
37342
37541
  const unreachableErr = await toolServerUnreachable(thrown);
@@ -37363,9 +37562,10 @@ async function runFlowDirectory(dir, args, projectRoot, options) {
37363
37562
  stopped = true;
37364
37563
  continue;
37365
37564
  }
37565
+ printWarnings(nestedStepWarnings(report.steps), args.json);
37366
37566
  await exportAndResolveArtifacts(
37367
37567
  report,
37368
- outputBase ? path17.join(outputBase, path17.dirname(rel)) : void 0,
37568
+ outputBase ? path18.join(outputBase, path18.dirname(rel)) : void 0,
37369
37569
  flowPath,
37370
37570
  baseUrl
37371
37571
  );
@@ -37403,25 +37603,54 @@ ${renderBatchSummary(counts, durationMs)}`);
37403
37603
  }
37404
37604
  return exitAfterFlush(unreachable ? 2 : counts.failed === 0 ? 0 : 1);
37405
37605
  }
37406
- async function flow(argv, options) {
37606
+ async function e2e(argv, options) {
37407
37607
  const [sub, ...rest] = argv;
37408
37608
  if (!sub || sub === "--help" || sub === "-h") {
37409
37609
  printHelp();
37410
37610
  return;
37411
37611
  }
37412
37612
  if (sub === "list") {
37413
- const dir = path17.join(process.cwd(), FLOWS_DIR);
37414
- try {
37415
- const paths = (await collectRunnableFlowPaths(dir)).sort().map((rel) => path17.join(FLOWS_DIR, rel));
37416
- if (paths.length === 0) console.log("No flows found in .argent/flows");
37417
- else console.log(paths.join("\n"));
37418
- } catch {
37419
- console.log("No .argent/flows directory in the current working directory.");
37613
+ const lines = [];
37614
+ const notes = [];
37615
+ let legacyCount = 0;
37616
+ const byName = /* @__PURE__ */ new Map();
37617
+ let anyDir = false;
37618
+ for (const dir of E2E_DIRS) {
37619
+ let rels;
37620
+ try {
37621
+ rels = (await collectRunnableFlowPaths(path18.join(process.cwd(), dir))).sort();
37622
+ } catch {
37623
+ continue;
37624
+ }
37625
+ anyDir = true;
37626
+ for (const rel of rels) {
37627
+ const shown = path18.join(dir, rel);
37628
+ const name = path18.dirname(rel) === "." ? path18.basename(rel, ".yaml") : void 0;
37629
+ const usedByName = name === void 0 ? void 0 : byName.get(name);
37630
+ if (name !== void 0 && usedByName === void 0) byName.set(name, shown);
37631
+ lines.push(shown);
37632
+ if (dir === E2E_DIR) continue;
37633
+ legacyCount++;
37634
+ if (usedByName)
37635
+ notes.push(`warning: ${shown} is shadowed by ${usedByName} when run by name`);
37636
+ }
37637
+ }
37638
+ if (legacyCount > 0) {
37639
+ notes.push(
37640
+ `note: ${legacyCount} test${legacyCount === 1 ? "" : "s"} listed from .argent/flows (legacy); move ${legacyCount === 1 ? "it" : "them"} to .argent/e2e`
37641
+ );
37642
+ }
37643
+ if (!anyDir) {
37644
+ console.log(`No ${E2E_DIRS.join(" or ")} directory in the current working directory.`);
37645
+ } else if (lines.length === 0) console.log(`No e2e tests found in ${E2E_DIRS.join(" or ")}`);
37646
+ else {
37647
+ console.log(lines.join("\n"));
37648
+ for (const note of notes) console.error(note);
37420
37649
  }
37421
37650
  return;
37422
37651
  }
37423
37652
  if (sub !== "run") {
37424
- console.error(`Unknown flow subcommand "${sub}". Run \`argent flow --help\`.`);
37653
+ console.error(`Unknown e2e subcommand "${sub}". Run \`argent e2e --help\`.`);
37425
37654
  return exitAfterFlush(2);
37426
37655
  }
37427
37656
  const flagGiven = (flag) => rest.some((tok) => tok === flag || tok.startsWith(`${flag}=`));
@@ -37452,7 +37681,7 @@ async function flow(argv, options) {
37452
37681
  throw err;
37453
37682
  }
37454
37683
  if (!args.flowRef) {
37455
- const message = "argent flow run <flow|flow.yaml|dir> requires a flow name, a YAML file path, or a directory path.";
37684
+ const message = "argent e2e run <test|test.yaml|dir> requires an e2e test name, a YAML file path, or a directory path.";
37456
37685
  return usageError(message, message);
37457
37686
  }
37458
37687
  const fail = (message, code, err = message) => {
@@ -37461,109 +37690,112 @@ async function flow(argv, options) {
37461
37690
  return exitAfterFlush(code);
37462
37691
  };
37463
37692
  const projectRoot = process.cwd();
37464
- const { suppliedPath, fromName } = resolveFlowRef(args.flowRef);
37693
+ const { suppliedPath, fromName, shadowed } = await resolveFlowRef(args.flowRef, projectRoot);
37694
+ if (shadowed !== void 0) {
37695
+ printWarnings([e2eShadowWarning(suppliedPath, shadowed)], args.json);
37696
+ }
37465
37697
  if (suppliedPath.split(/[\\/]+/).includes("..")) {
37466
- let recovery = "Pass the fully resolved path to the flow's YAML.";
37467
- const suppliedBase2 = path17.basename(suppliedPath);
37698
+ let recovery = "Pass the fully resolved path to the e2e test's YAML.";
37699
+ const suppliedBase2 = path18.basename(suppliedPath);
37468
37700
  if (suppliedBase2 !== ".." && suppliedBase2 !== ".") {
37469
37701
  try {
37470
- const resolved = path17.join(await fsp.realpath(path17.dirname(suppliedPath)), suppliedBase2);
37702
+ const resolved = path18.join(await fsp.realpath(path18.dirname(suppliedPath)), suppliedBase2);
37471
37703
  await fsp.stat(resolved);
37472
- recovery = `Did you mean: argent flow run ${shellQuoteArg(resolved)}`;
37704
+ recovery = `Did you mean: argent e2e run ${shellQuoteArg(resolved)}`;
37473
37705
  } catch {
37474
37706
  }
37475
37707
  }
37476
37708
  return fail(
37477
- `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}
37709
+ `E2E test 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}
37478
37710
  ` + recovery,
37479
37711
  2
37480
37712
  );
37481
37713
  }
37482
- const resolvedPath = path17.resolve(projectRoot, suppliedPath);
37714
+ const resolvedPath = path18.resolve(projectRoot, suppliedPath);
37483
37715
  let isDirectory = false;
37484
37716
  try {
37485
37717
  isDirectory = (await fsp.stat(resolvedPath)).isDirectory();
37486
37718
  } catch {
37487
37719
  if (args.recursive && !fromName) {
37488
- return fail(`Flow directory not found: ${resolvedPath}`, 2);
37720
+ return fail(`E2E test directory not found: ${resolvedPath}`, 2);
37489
37721
  }
37490
37722
  }
37491
37723
  if (isDirectory) {
37492
37724
  if (args.jsonStream) {
37493
- return fail("--json-stream supports a single flow; directory runs are not supported.", 2);
37725
+ return fail("--json-stream supports a single e2e test; directory runs are not supported.", 2);
37494
37726
  }
37495
37727
  return runFlowDirectory(resolvedPath, args, projectRoot, options);
37496
37728
  }
37497
37729
  if (args.recursive) {
37498
37730
  return fail(
37499
- 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}`,
37731
+ fromName ? `e2e run --recursive requires a directory path; "${args.flowRef}" is a saved test's name, which always addresses the single file ${suppliedPath}.` : `e2e run --recursive requires a directory path: ${suppliedPath}`,
37500
37732
  2
37501
37733
  );
37502
37734
  }
37503
37735
  const separatorTrimmedPath = suppliedPath.replace(/[\\/]+$/, "");
37504
37736
  if (separatorTrimmedPath !== suppliedPath && separatorTrimmedPath !== "") {
37505
- const hint = SAFE_FLOW_NAME.test(separatorTrimmedPath) ? `.${path17.sep}${separatorTrimmedPath}` : separatorTrimmedPath;
37737
+ const hint = SAFE_FLOW_NAME.test(separatorTrimmedPath) ? `.${path18.sep}${separatorTrimmedPath}` : separatorTrimmedPath;
37506
37738
  return fail(
37507
- `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}
37508
- Did you mean: argent flow run ${shellQuoteArg(hint)}`,
37739
+ `E2E test 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}
37740
+ Did you mean: argent e2e run ${shellQuoteArg(hint)}`,
37509
37741
  2
37510
37742
  );
37511
37743
  }
37512
- if (path17.extname(suppliedPath) !== ".yaml") {
37513
- const looksLikeName = !suppliedPath.includes("/") && !suppliedPath.includes("\\") && path17.extname(suppliedPath) === "";
37514
- if (path17.basename(suppliedPath).toLowerCase() === ".yaml") {
37744
+ if (path18.extname(suppliedPath) !== ".yaml") {
37745
+ const looksLikeName = !suppliedPath.includes("/") && !suppliedPath.includes("\\") && path18.extname(suppliedPath) === "";
37746
+ if (path18.basename(suppliedPath).toLowerCase() === ".yaml") {
37515
37747
  return fail(
37516
- `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
37748
+ `E2E test filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
37517
37749
  2
37518
37750
  );
37519
37751
  }
37520
37752
  if (looksLikeName) {
37521
37753
  return fail(
37522
- `Flow name must contain only letters, numbers, "_", or "-": ${suppliedPath}
37523
- Names run \`${FLOWS_DIR}/<name>.yaml\`; pass a path ending in .yaml to run a flow file kept elsewhere.`,
37754
+ `E2E test name must contain only letters, numbers, "_", or "-": ${suppliedPath}
37755
+ Names run \`${E2E_DIRS.map((dir) => `${dir}/<name>.yaml`).join("` or `")}\`; pass a path ending in .yaml to run an e2e test file kept elsewhere.`,
37524
37756
  2
37525
37757
  );
37526
37758
  }
37527
- if (path17.extname(suppliedPath).toLowerCase() === ".yaml") {
37759
+ if (path18.extname(suppliedPath).toLowerCase() === ".yaml") {
37528
37760
  return fail(
37529
- `Flow extension must be lowercase .yaml, not ${path17.extname(suppliedPath)}: ${suppliedPath}`,
37761
+ `E2E test extension must be lowercase .yaml, not ${path18.extname(suppliedPath)}: ${suppliedPath}`,
37530
37762
  2
37531
37763
  );
37532
37764
  }
37533
- return fail(`Flow path must end in .yaml: ${suppliedPath}`, 2);
37765
+ return fail(`E2E test path must end in .yaml: ${suppliedPath}`, 2);
37534
37766
  }
37535
- const flowName = path17.basename(suppliedPath, ".yaml");
37767
+ const flowName = path18.basename(suppliedPath, ".yaml");
37536
37768
  if (!SAFE_FLOW_NAME.test(flowName)) {
37537
37769
  return fail(
37538
- `Flow filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
37770
+ `E2E test filename must have a non-empty name containing only letters, numbers, "_", or "-": ${suppliedPath}`,
37539
37771
  2
37540
37772
  );
37541
37773
  }
37542
37774
  const flowPath = resolvedPath;
37543
37775
  try {
37544
- const stat6 = await fsp.stat(flowPath);
37545
- if (!stat6.isFile()) {
37546
- return fail(`Flow path is not a file: ${flowPath}`, 2);
37776
+ const stat7 = await fsp.stat(flowPath);
37777
+ if (!stat7.isFile()) {
37778
+ return fail(`E2E test path is not a file: ${flowPath}`, 2);
37547
37779
  }
37548
37780
  await fsp.access(flowPath, fsConstants2.R_OK);
37549
37781
  } catch (err) {
37550
37782
  const code = err.code;
37551
- const detail = code === "ENOENT" ? "Flow file not found" : "Could not read flow file";
37783
+ const detail = code === "ENOENT" ? "E2E test file not found" : "Could not read e2e test file";
37552
37784
  let recovery = "";
37553
37785
  if (code === "ENOENT") {
37554
37786
  recovery = fromName ? `
37555
- No flow named "${args.flowRef}" is saved there \u2014 run \`argent flow list\` to see the saved flows.` : await savedFlowHint(projectRoot, flowPath);
37787
+ No e2e test named "${args.flowRef}" is saved in ${E2E_DIRS.join(" or ")} \u2014 run \`argent e2e list\` to see the saved tests.` : await savedFlowHint(projectRoot, flowPath);
37556
37788
  }
37557
37789
  return fail(`${detail}: ${flowPath}${recovery}`, 2);
37558
37790
  }
37559
- const suppliedBase = path17.basename(flowPath);
37560
- const siblings = await fsp.readdir(path17.dirname(flowPath)).catch(() => null);
37791
+ const suppliedBase = path18.basename(flowPath);
37792
+ const siblings = await fsp.readdir(path18.dirname(flowPath)).catch(() => null);
37561
37793
  if (siblings !== null && !siblings.includes(suppliedBase)) {
37562
37794
  const actual = siblings.find((name) => name.toLowerCase() === suppliedBase.toLowerCase());
37563
- const actualRunnable = actual !== void 0 && path17.extname(actual) === ".yaml" && SAFE_FLOW_NAME.test(path17.basename(actual, ".yaml"));
37564
- const recovery = actualRunnable ? fromName ? `Did you mean: argent flow run ${path17.basename(actual, ".yaml")}` : `Did you mean: argent flow run ${shellQuoteArg(path17.join(path17.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.";
37795
+ const actualRunnable = actual !== void 0 && path18.extname(actual) === ".yaml" && SAFE_FLOW_NAME.test(path18.basename(actual, ".yaml"));
37796
+ const recovery = actualRunnable ? fromName ? `Did you mean: argent e2e run ${path18.basename(actual, ".yaml")}` : `Did you mean: argent e2e run ${shellQuoteArg(path18.join(path18.dirname(suppliedPath), actual))}` : actual !== void 0 ? `Rename ${actual} to ${suppliedBase} to run it \u2014 e2e test files must be lowercase .yaml.` : "Pass the e2e test file's name exactly as it appears on disk.";
37565
37797
  return fail(
37566
- `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}
37798
+ `E2E test 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 test name (which keys the report, __baselines__/, and --output) would be one no file carries: ${suppliedPath}
37567
37799
  ${recovery}`,
37568
37800
  2
37569
37801
  );
@@ -37578,7 +37810,7 @@ ${recovery}`,
37578
37810
  writeJsonStreamRecord({ event: "progress", data: s });
37579
37811
  return;
37580
37812
  }
37581
- if (liveSteps === 0) console.log(`Flow "${flowName}"`);
37813
+ if (liveSteps === 0) console.log(`E2E test "${flowName}"`);
37582
37814
  liveSteps++;
37583
37815
  if (s.kind === "echo") {
37584
37816
  const line = renderEchoLine(s);
@@ -37593,7 +37825,7 @@ ${recovery}`,
37593
37825
  let report;
37594
37826
  try {
37595
37827
  const resp = await callTool(
37596
- "flow-execute",
37828
+ RUN_TOOL_ID,
37597
37829
  payload,
37598
37830
  args.json ? void 0 : { onProgress: onStepReport }
37599
37831
  );
@@ -37601,7 +37833,7 @@ ${recovery}`,
37601
37833
  } catch (err) {
37602
37834
  const unreachableErr = await toolServerUnreachable(err);
37603
37835
  if (!args.json && !args.jsonStream) {
37604
- if (liveSteps === 0) console.log(`Flow "${flowName}"`);
37836
+ if (liveSteps === 0) console.log(`E2E test "${flowName}"`);
37605
37837
  console.log(
37606
37838
  ` ${STATUS_GLYPH.error} ` + (unreachableErr ? UNREACHABLE_VERDICT : err instanceof ToolInvocationError && err.errorKind === "validation" ? rejectionVerdict(err.errorCode) : "did not finish (run error)")
37607
37839
  );
@@ -37611,15 +37843,16 @@ ${recovery}`,
37611
37843
  }
37612
37844
  if (!isFlowReport(report)) {
37613
37845
  if (!args.json && !args.jsonStream) {
37614
- if (liveSteps === 0) console.log(`Flow "${flowName}"`);
37846
+ if (liveSteps === 0) console.log(`E2E test "${flowName}"`);
37615
37847
  console.log(` ${STATUS_GLYPH.error} did not finish (no run report)`);
37616
37848
  }
37617
37849
  return fail(`"${flowName}" did not produce a run report.`, 2);
37618
37850
  }
37851
+ printWarnings(nestedStepWarnings(report.steps), args.json);
37619
37852
  try {
37620
37853
  await exportAndResolveArtifacts(
37621
37854
  report,
37622
- args.output ? path17.resolve(args.output) : void 0,
37855
+ args.output ? path18.resolve(args.output) : void 0,
37623
37856
  flowPath,
37624
37857
  baseUrl
37625
37858
  );
@@ -37658,7 +37891,7 @@ function summarize(description, max = 80) {
37658
37891
  async function tools(argv, options) {
37659
37892
  const { fetchTool, fetchTools } = createToolsClient({ paths: options.paths });
37660
37893
  async function listTools(json3) {
37661
- const list = await fetchTools();
37894
+ const list = (await fetchTools()).filter((tool) => tool.aliasOf === void 0);
37662
37895
  if (json3) {
37663
37896
  console.log(JSON.stringify(list, null, 2));
37664
37897
  return;
@@ -37733,12 +37966,12 @@ Listing tools contacts the argent tool-server, starting one if none is running.
37733
37966
  }
37734
37967
 
37735
37968
  // ../argent-cli/src/server.ts
37736
- import * as fs12 from "node:fs";
37737
- import * as path18 from "node:path";
37969
+ import * as fs13 from "node:fs";
37970
+ import * as path19 from "node:path";
37738
37971
  import { homedir as homedir5, networkInterfaces } from "node:os";
37739
37972
  import { spawn as spawn3 } from "node:child_process";
37740
- var STATE_DIR2 = path18.join(homedir5(), ".argent");
37741
- var LOG_FILE2 = path18.join(STATE_DIR2, "tool-server.log");
37973
+ var STATE_DIR2 = path19.join(homedir5(), ".argent");
37974
+ var LOG_FILE2 = path19.join(STATE_DIR2, "tool-server.log");
37742
37975
  async function describeForeignServers(ownBundlePath) {
37743
37976
  const others = (await readAllToolsServerStates()).filter(
37744
37977
  ({ state: state2 }) => state2.bundlePath !== ownBundlePath && isToolsServerProcessAlive(state2.pid)
@@ -37802,12 +38035,12 @@ Stop one with: kill <pid>`);
37802
38035
  }
37803
38036
  }
37804
38037
  function logsCmd(follow) {
37805
- if (!fs12.existsSync(LOG_FILE2)) {
38038
+ if (!fs13.existsSync(LOG_FILE2)) {
37806
38039
  console.log(`No log file at ${LOG_FILE2}`);
37807
38040
  return;
37808
38041
  }
37809
38042
  if (!follow) {
37810
- process.stdout.write(fs12.readFileSync(LOG_FILE2, "utf8"));
38043
+ process.stdout.write(fs13.readFileSync(LOG_FILE2, "utf8"));
37811
38044
  return;
37812
38045
  }
37813
38046
  const child = spawn3("tail", ["-f", LOG_FILE2], { stdio: "inherit" });
@@ -38131,9 +38364,9 @@ async function server(argv, options) {
38131
38364
  }
38132
38365
 
38133
38366
  // ../argent-cli/src/lens.ts
38134
- import * as fs13 from "node:fs";
38367
+ import * as fs14 from "node:fs";
38135
38368
  import * as os2 from "node:os";
38136
- import * as path19 from "node:path";
38369
+ import * as path20 from "node:path";
38137
38370
 
38138
38371
  // ../argent-cli/src/lens-terminal.ts
38139
38372
  import { execFileSync as execFileSync3 } from "node:child_process";
@@ -38351,15 +38584,15 @@ function isSessionAlive(session) {
38351
38584
  // ../argent-cli/src/lens-pty.ts
38352
38585
  import { chmodSync as chmodSync2, readdirSync as readdirSync2 } from "node:fs";
38353
38586
  import { createRequire } from "node:module";
38354
- import { dirname as dirname11, join as join17 } from "node:path";
38587
+ import { dirname as dirname12, join as join19 } from "node:path";
38355
38588
  var nodeRequire = createRequire(import.meta.url);
38356
38589
  function ensureSpawnHelperExecutable(req = nodeRequire) {
38357
38590
  if (process.platform !== "darwin") return;
38358
38591
  try {
38359
- const prebuilds = join17(dirname11(req.resolve("node-pty/package.json")), "prebuilds");
38592
+ const prebuilds = join19(dirname12(req.resolve("node-pty/package.json")), "prebuilds");
38360
38593
  for (const entry of readdirSync2(prebuilds)) {
38361
38594
  try {
38362
- chmodSync2(join17(prebuilds, entry, "spawn-helper"), 493);
38595
+ chmodSync2(join19(prebuilds, entry, "spawn-helper"), 493);
38363
38596
  } catch {
38364
38597
  }
38365
38598
  }
@@ -38391,7 +38624,7 @@ function ptyInjectBeats(text2) {
38391
38624
  ];
38392
38625
  }
38393
38626
  function sleep(ms) {
38394
- return new Promise((resolve12) => setTimeout(resolve12, ms));
38627
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
38395
38628
  }
38396
38629
  var DEFAULT_COLS = 80;
38397
38630
  var DEFAULT_ROWS = 24;
@@ -38612,7 +38845,7 @@ var SPAWN_GRACE_MS = 8e3;
38612
38845
  var DEATH_CONFIRMATIONS = 3;
38613
38846
  var SSE_RECONNECT_MS = 1e3;
38614
38847
  function sleep2(ms) {
38615
- return new Promise((resolve12) => setTimeout(resolve12, ms));
38848
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
38616
38849
  }
38617
38850
  var TRUST_PROMPT_RE = /trust this folder|do you trust|yes,? i trust|trust the files in this/i;
38618
38851
  async function dismissTrustPrompt(session) {
@@ -38884,12 +39117,12 @@ async function lens(argv, options) {
38884
39117
  await endSession(baseUrl);
38885
39118
  process.exit(1);
38886
39119
  }
38887
- const seedFile = path19.join(os2.tmpdir(), `argent-lens-seed-${process.pid}-${Date.now()}.txt`);
38888
- fs13.writeFileSync(seedFile, buildSeedPrompt(), "utf8");
39120
+ const seedFile = path20.join(os2.tmpdir(), `argent-lens-seed-${process.pid}-${Date.now()}.txt`);
39121
+ fs14.writeFileSync(seedFile, buildSeedPrompt(), "utf8");
38889
39122
  const launchCmd = agent.launch(shellQuote(process.cwd()), shellQuote(seedFile));
38890
39123
  const removeSeedFile = () => {
38891
39124
  try {
38892
- fs13.rmSync(seedFile, { force: true });
39125
+ fs14.rmSync(seedFile, { force: true });
38893
39126
  } catch {
38894
39127
  }
38895
39128
  };
@@ -39248,7 +39481,7 @@ Options:
39248
39481
 
39249
39482
  // ../argent-cli/src/config.ts
39250
39483
  var import_picocolors2 = __toESM(require_picocolors(), 1);
39251
- import * as path20 from "node:path";
39484
+ import * as path21 from "node:path";
39252
39485
  function config2(argv) {
39253
39486
  if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
39254
39487
  printUsage();
@@ -39419,16 +39652,16 @@ function wantsHelp(argv) {
39419
39652
  }
39420
39653
  function scopeLabel(scope) {
39421
39654
  if (scope === "global") return "global";
39422
- return `project: ${path20.dirname(configDir("project"))}`;
39655
+ return `project: ${path21.dirname(configDir("project"))}`;
39423
39656
  }
39424
39657
  function degenerateProjectScopeWarning(scope) {
39425
39658
  if (scope !== "project") return null;
39426
39659
  const projDir = configDir("project");
39427
- if (path20.resolve(projDir) === path20.resolve(configDir("global"))) {
39428
- return `WARNING: no project found between ${process.cwd()} and your home directory \u2014 "project" scope resolved to the home directory, so this writes the GLOBAL config file (${path20.join(projDir, "config.json")}).`;
39660
+ if (path21.resolve(projDir) === path21.resolve(configDir("global"))) {
39661
+ return `WARNING: no project found between ${process.cwd()} and your home directory \u2014 "project" scope resolved to the home directory, so this writes the GLOBAL config file (${path21.join(projDir, "config.json")}).`;
39429
39662
  }
39430
39663
  if (findProjectRoot(process.cwd()) === null) {
39431
- return `WARNING: no project markers (.argent, .git, package.json) found above ${process.cwd()} \u2014 treating it as the project root and creating ${path20.join(projDir, "config.json")}.`;
39664
+ return `WARNING: no project markers (.argent, .git, package.json) found above ${process.cwd()} \u2014 treating it as the project root and creating ${path21.join(projDir, "config.json")}.`;
39432
39665
  }
39433
39666
  return null;
39434
39667
  }
@@ -40345,7 +40578,7 @@ import { styleText as styleText2, stripVTControlCharacters } from "node:util";
40345
40578
  import process$1 from "node:process";
40346
40579
  var import_sisteransi2 = __toESM(require_src(), 1);
40347
40580
  import { existsSync as existsSync7, lstatSync as lstatSync3, readdirSync as readdirSync3 } from "node:fs";
40348
- import { dirname as dirname13, join as join20 } from "node:path";
40581
+ import { dirname as dirname14, join as join22 } from "node:path";
40349
40582
  function isUnicodeSupported() {
40350
40583
  if (process$1.platform !== "win32") {
40351
40584
  return process$1.env.TERM !== "linux";
@@ -41347,8 +41580,8 @@ async function cmdDisable(scope) {
41347
41580
 
41348
41581
  // ../argent-cli/src/providers.ts
41349
41582
  var import_picocolors7 = __toESM(require_picocolors(), 1);
41350
- import * as fs17 from "node:fs";
41351
- import * as path23 from "node:path";
41583
+ import * as fs18 from "node:fs";
41584
+ import * as path24 from "node:path";
41352
41585
 
41353
41586
  // ../device-providers/src/contract.ts
41354
41587
  var PROVIDER_SCHEMA_VERSION = 1;
@@ -41493,9 +41726,9 @@ var providerEnvelopeSchema = providerRecordSchema.extend({
41493
41726
  });
41494
41727
 
41495
41728
  // ../device-providers/src/read.ts
41496
- import * as fs14 from "node:fs";
41729
+ import * as fs15 from "node:fs";
41497
41730
  import * as os3 from "node:os";
41498
- import * as path21 from "node:path";
41731
+ import * as path22 from "node:path";
41499
41732
  var DISABLE_ENV = "ARGENT_DISABLE_DEVICE_PROVIDERS";
41500
41733
  var OVERRIDE_ENV = "ARGENT_DEVICE_PROVIDERS";
41501
41734
  function resolveHomeDir2() {
@@ -41504,7 +41737,7 @@ function resolveHomeDir2() {
41504
41737
  return trimmed ? raw : os3.homedir();
41505
41738
  }
41506
41739
  function providersDirectory() {
41507
- return path21.join(resolveHomeDir2(), ".argent", "providers");
41740
+ return path22.join(resolveHomeDir2(), ".argent", "providers");
41508
41741
  }
41509
41742
  function discoveryDisabled() {
41510
41743
  const raw = process.env[DISABLE_ENV];
@@ -41520,7 +41753,7 @@ function warnOnce(key, message) {
41520
41753
  function readProviderFile(file2) {
41521
41754
  let raw;
41522
41755
  try {
41523
- raw = fs14.readFileSync(file2, "utf8");
41756
+ raw = fs15.readFileSync(file2, "utf8");
41524
41757
  } catch {
41525
41758
  return void 0;
41526
41759
  }
@@ -41570,15 +41803,15 @@ function discoverProviders() {
41570
41803
  function descriptorFiles() {
41571
41804
  const directory = providersDirectory();
41572
41805
  try {
41573
- return fs14.readdirSync(directory).filter((name) => name.endsWith(".json")).sort().map((name) => path21.join(directory, name));
41806
+ return fs15.readdirSync(directory).filter((name) => name.endsWith(".json")).sort().map((name) => path22.join(directory, name));
41574
41807
  } catch {
41575
41808
  return [];
41576
41809
  }
41577
41810
  }
41578
41811
 
41579
41812
  // ../device-providers/src/write.ts
41580
- import * as fs15 from "node:fs";
41581
- import * as path22 from "node:path";
41813
+ import * as fs16 from "node:fs";
41814
+ import * as path23 from "node:path";
41582
41815
  var ProviderValidationError = class extends Error {
41583
41816
  /** One line per problem, `path: message`, in the order zod reported them. */
41584
41817
  issues;
@@ -41630,20 +41863,20 @@ function publishProvider(record2, options = {}) {
41630
41863
  );
41631
41864
  }
41632
41865
  const directory = providersDirectory();
41633
- const file2 = path22.join(directory, `${validated.id}.json`);
41866
+ const file2 = path23.join(directory, `${validated.id}.json`);
41634
41867
  const body = JSON.stringify(canonicalize(candidate), null, 2) + "\n";
41635
41868
  try {
41636
- if (fs15.readFileSync(file2, "utf8") === body) return { changed: false, path: file2 };
41869
+ if (fs16.readFileSync(file2, "utf8") === body) return { changed: false, path: file2 };
41637
41870
  } catch {
41638
41871
  }
41639
- fs15.mkdirSync(directory, { recursive: true });
41872
+ fs16.mkdirSync(directory, { recursive: true });
41640
41873
  const temporary = `${file2}.${process.pid}.tmp`;
41641
41874
  try {
41642
- fs15.writeFileSync(temporary, body);
41643
- fs15.renameSync(temporary, file2);
41875
+ fs16.writeFileSync(temporary, body);
41876
+ fs16.renameSync(temporary, file2);
41644
41877
  } catch (error63) {
41645
41878
  try {
41646
- fs15.rmSync(temporary, { force: true });
41879
+ fs16.rmSync(temporary, { force: true });
41647
41880
  } catch {
41648
41881
  }
41649
41882
  throw error63;
@@ -41654,9 +41887,9 @@ function withdrawProvider(id) {
41654
41887
  if (!PROVIDER_ID_SHAPE.test(id)) {
41655
41888
  throw new Error(`'${id}' is not a valid provider id (${String(PROVIDER_ID_SHAPE)}).`);
41656
41889
  }
41657
- const file2 = path22.join(providersDirectory(), `${id}.json`);
41890
+ const file2 = path23.join(providersDirectory(), `${id}.json`);
41658
41891
  try {
41659
- fs15.unlinkSync(file2);
41892
+ fs16.unlinkSync(file2);
41660
41893
  return true;
41661
41894
  } catch (e) {
41662
41895
  if (e.code === "ENOENT") return false;
@@ -41686,7 +41919,7 @@ function pruneOrphanedProviders(options = {}) {
41686
41919
  continue;
41687
41920
  }
41688
41921
  try {
41689
- fs15.unlinkSync(file2);
41922
+ fs16.unlinkSync(file2);
41690
41923
  removed.push(entry);
41691
41924
  } catch {
41692
41925
  }
@@ -41696,7 +41929,7 @@ function pruneOrphanedProviders(options = {}) {
41696
41929
 
41697
41930
  // ../argent-cli/src/providers-check.ts
41698
41931
  var import_picocolors6 = __toESM(require_picocolors(), 1);
41699
- import * as fs16 from "node:fs";
41932
+ import * as fs17 from "node:fs";
41700
41933
  var KNOWN_CAPABILITIES = new Set(EXTERNAL_CAPABILITIES);
41701
41934
  var PROBE_TIMEOUT_MS = 5e3;
41702
41935
  function error62(message) {
@@ -41762,7 +41995,7 @@ async function checkDevices(devices, findings) {
41762
41995
  );
41763
41996
  } else {
41764
41997
  try {
41765
- fs16.accessSync(device.deviceSet, fs16.constants.R_OK);
41998
+ fs17.accessSync(device.deviceSet, fs17.constants.R_OK);
41766
41999
  } catch {
41767
42000
  findings.push(
41768
42001
  error62(`${label}: deviceSet '${device.deviceSet}' is not readable by this user`)
@@ -41819,7 +42052,7 @@ async function checkDevices(devices, findings) {
41819
42052
  );
41820
42053
  } else {
41821
42054
  try {
41822
- fs16.accessSync(device.nativeDevtools.socketPath, fs16.constants.R_OK | fs16.constants.W_OK);
42055
+ fs17.accessSync(device.nativeDevtools.socketPath, fs17.constants.R_OK | fs17.constants.W_OK);
41823
42056
  } catch {
41824
42057
  findings.push(
41825
42058
  error62(
@@ -41890,7 +42123,7 @@ async function checkDescriptorFile(file2, expectedVersion) {
41890
42123
  const report = { deviceCount: 0, findings, source: file2 };
41891
42124
  let raw;
41892
42125
  try {
41893
- raw = fs16.readFileSync(file2, "utf8");
42126
+ raw = fs17.readFileSync(file2, "utf8");
41894
42127
  } catch (e) {
41895
42128
  findings.push(error62(`unreadable: ${e instanceof Error ? e.message : String(e)}`));
41896
42129
  return report;
@@ -42026,7 +42259,7 @@ async function readDocument(args) {
42026
42259
  }
42027
42260
  if (args.file) {
42028
42261
  try {
42029
- return { raw: fs17.readFileSync(args.file, "utf8"), source: args.file };
42262
+ return { raw: fs18.readFileSync(args.file, "utf8"), source: args.file };
42030
42263
  } catch (e) {
42031
42264
  throw new UsageError2(
42032
42265
  `cannot read ${args.file}: ${e instanceof Error ? e.message : String(e)}`
@@ -42159,7 +42392,7 @@ function runWithdraw(args) {
42159
42392
  throw new UsageError2(`'${id}' is not a valid provider id (${String(PROVIDER_ID_SHAPE)})`);
42160
42393
  }
42161
42394
  const removed = withdrawProvider(id);
42162
- const file2 = path23.join(providersDirectory(), `${id}.json`);
42395
+ const file2 = path24.join(providersDirectory(), `${id}.json`);
42163
42396
  if (args.json) {
42164
42397
  console.log(JSON.stringify({ ok: true, path: file2, removed }, null, 2));
42165
42398
  return;
@@ -42367,9 +42600,10 @@ export {
42367
42600
  FLAG_REGISTRY,
42368
42601
  config2 as config,
42369
42602
  disable,
42603
+ e2e,
42370
42604
  enable,
42371
42605
  flags,
42372
- flow,
42606
+ e2e as flow,
42373
42607
  getFlagDefinition,
42374
42608
  isFlagEnabled,
42375
42609
  lens,