@swmansion/argent 0.19.1-next.2 → 0.19.1-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,7 +45,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
45
45
  // ../../node_modules/dotenv/lib/main.js
46
46
  var require_main = __commonJS({
47
47
  "../../node_modules/dotenv/lib/main.js"(exports2, module2) {
48
- var fs54 = require("fs");
48
+ var fs55 = require("fs");
49
49
  var path40 = require("path");
50
50
  var os15 = require("os");
51
51
  var crypto8 = require("crypto");
@@ -177,7 +177,7 @@ var require_main = __commonJS({
177
177
  if (options && options.path && options.path.length > 0) {
178
178
  if (Array.isArray(options.path)) {
179
179
  for (const filepath of options.path) {
180
- if (fs54.existsSync(filepath)) {
180
+ if (fs55.existsSync(filepath)) {
181
181
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
182
182
  }
183
183
  }
@@ -187,7 +187,7 @@ var require_main = __commonJS({
187
187
  } else {
188
188
  possibleVaultPath = path40.resolve(process.cwd(), ".env.vault");
189
189
  }
190
- if (fs54.existsSync(possibleVaultPath)) {
190
+ if (fs55.existsSync(possibleVaultPath)) {
191
191
  return possibleVaultPath;
192
192
  }
193
193
  return null;
@@ -240,7 +240,7 @@ var require_main = __commonJS({
240
240
  const parsedAll = {};
241
241
  for (const path41 of optionPaths) {
242
242
  try {
243
- const parsed = DotenvModule.parse(fs54.readFileSync(path41, { encoding }));
243
+ const parsed = DotenvModule.parse(fs55.readFileSync(path41, { encoding }));
244
244
  DotenvModule.populate(parsedAll, parsed, options);
245
245
  } catch (e) {
246
246
  if (debug) {
@@ -35264,7 +35264,7 @@ var require_view = __commonJS({
35264
35264
  "use strict";
35265
35265
  var debug = require_src()("express:view");
35266
35266
  var path40 = require("node:path");
35267
- var fs54 = require("node:fs");
35267
+ var fs55 = require("node:fs");
35268
35268
  var dirname15 = path40.dirname;
35269
35269
  var basename13 = path40.basename;
35270
35270
  var extname6 = path40.extname;
@@ -35344,7 +35344,7 @@ var require_view = __commonJS({
35344
35344
  function tryStat(path41) {
35345
35345
  debug('stat "%s"', path41);
35346
35346
  try {
35347
- return fs54.statSync(path41);
35347
+ return fs55.statSync(path41);
35348
35348
  } catch (e) {
35349
35349
  return void 0;
35350
35350
  }
@@ -67649,7 +67649,7 @@ var require_send = __commonJS({
67649
67649
  var escapeHtml = require_escape_html();
67650
67650
  var etag = require_etag();
67651
67651
  var fresh = require_fresh();
67652
- var fs54 = require("fs");
67652
+ var fs55 = require("fs");
67653
67653
  var mime = require_mime_types4();
67654
67654
  var ms = require_ms();
67655
67655
  var onFinished = require_on_finished();
@@ -67931,7 +67931,7 @@ var require_send = __commonJS({
67931
67931
  var i = 0;
67932
67932
  var self = this;
67933
67933
  debug('stat "%s"', path41);
67934
- fs54.stat(path41, function onstat(err, stat5) {
67934
+ fs55.stat(path41, function onstat(err, stat5) {
67935
67935
  var pathEndsWithSep = path41[path41.length - 1] === sep7;
67936
67936
  if (err && err.code === "ENOENT" && !extname6(path41) && !pathEndsWithSep) {
67937
67937
  return next(err);
@@ -67948,7 +67948,7 @@ var require_send = __commonJS({
67948
67948
  }
67949
67949
  var p = path41 + "." + self._extensions[i++];
67950
67950
  debug('stat "%s"', p);
67951
- fs54.stat(p, function(err2, stat5) {
67951
+ fs55.stat(p, function(err2, stat5) {
67952
67952
  if (err2) return next(err2);
67953
67953
  if (stat5.isDirectory()) return next();
67954
67954
  self.emit("file", p, stat5);
@@ -67966,7 +67966,7 @@ var require_send = __commonJS({
67966
67966
  }
67967
67967
  var p = join47(path41, self._index[i]);
67968
67968
  debug('stat "%s"', p);
67969
- fs54.stat(p, function(err2, stat5) {
67969
+ fs55.stat(p, function(err2, stat5) {
67970
67970
  if (err2) return next(err2);
67971
67971
  if (stat5.isDirectory()) return next();
67972
67972
  self.emit("file", p, stat5);
@@ -67978,7 +67978,7 @@ var require_send = __commonJS({
67978
67978
  SendStream.prototype.stream = function stream(path41, options) {
67979
67979
  var self = this;
67980
67980
  var res = this.res;
67981
- var stream2 = fs54.createReadStream(path41, options);
67981
+ var stream2 = fs55.createReadStream(path41, options);
67982
67982
  this.emit("stream", stream2);
67983
67983
  stream2.pipe(res);
67984
67984
  function cleanup() {
@@ -75469,10 +75469,10 @@ function avdRootCandidates() {
75469
75469
  return candidates.filter((p) => Boolean(p && (0, import_node_path6.isAbsolute)(p)));
75470
75470
  }
75471
75471
  async function resolveAvdPath(avdName) {
75472
- const { readFile: readFile12 } = await import("node:fs/promises");
75472
+ const { readFile: readFile13 } = await import("node:fs/promises");
75473
75473
  for (const root of avdRootCandidates()) {
75474
75474
  try {
75475
- const content = await readFile12(`${root}/${avdName}.ini`, "utf-8");
75475
+ const content = await readFile13(`${root}/${avdName}.ini`, "utf-8");
75476
75476
  const raw = (0, import_ini.parse)(content).path;
75477
75477
  if (typeof raw !== "string") continue;
75478
75478
  const trimmed = raw.trim();
@@ -75602,7 +75602,7 @@ var require_safe_json_stringify = __commonJS({
75602
75602
  // ../../node_modules/ncp/lib/ncp.js
75603
75603
  var require_ncp = __commonJS({
75604
75604
  "../../node_modules/ncp/lib/ncp.js"(exports2, module2) {
75605
- var fs54 = require("fs");
75605
+ var fs55 = require("fs");
75606
75606
  var path40 = require("path");
75607
75607
  module2.exports = ncp;
75608
75608
  ncp.ncp = ncp;
@@ -75631,7 +75631,7 @@ var require_ncp = __commonJS({
75631
75631
  return getStats(source2);
75632
75632
  }
75633
75633
  function getStats(source2) {
75634
- var stat5 = dereference ? fs54.stat : fs54.lstat;
75634
+ var stat5 = dereference ? fs55.stat : fs55.lstat;
75635
75635
  if (running >= limit) {
75636
75636
  return setImmediate(function() {
75637
75637
  getStats(source2);
@@ -75671,7 +75671,7 @@ var require_ncp = __commonJS({
75671
75671
  });
75672
75672
  }
75673
75673
  if (modified) {
75674
- var stat5 = dereference ? fs54.stat : fs54.lstat;
75674
+ var stat5 = dereference ? fs55.stat : fs55.lstat;
75675
75675
  stat5(target, function(err, stats) {
75676
75676
  if (file2.mtime.getTime() > stats.mtime.getTime())
75677
75677
  copyFile2(file2, target);
@@ -75683,7 +75683,7 @@ var require_ncp = __commonJS({
75683
75683
  });
75684
75684
  }
75685
75685
  function copyFile2(file2, target) {
75686
- var readStream = fs54.createReadStream(file2.name), writeStream = fs54.createWriteStream(target, { mode: file2.mode });
75686
+ var readStream = fs55.createReadStream(file2.name), writeStream = fs55.createWriteStream(target, { mode: file2.mode });
75687
75687
  readStream.on("error", onError);
75688
75688
  writeStream.on("error", onError);
75689
75689
  if (transform2) {
@@ -75695,13 +75695,13 @@ var require_ncp = __commonJS({
75695
75695
  }
75696
75696
  writeStream.once("finish", function() {
75697
75697
  if (modified) {
75698
- fs54.utimesSync(target, file2.atime, file2.mtime);
75698
+ fs55.utimesSync(target, file2.atime, file2.mtime);
75699
75699
  cb();
75700
75700
  } else cb();
75701
75701
  });
75702
75702
  }
75703
75703
  function rmFile(file2, done) {
75704
- fs54.unlink(file2, function(err) {
75704
+ fs55.unlink(file2, function(err) {
75705
75705
  if (err) {
75706
75706
  return onError(err);
75707
75707
  }
@@ -75718,7 +75718,7 @@ var require_ncp = __commonJS({
75718
75718
  });
75719
75719
  }
75720
75720
  function mkDir(dir, target) {
75721
- fs54.mkdir(target, dir.mode, function(err) {
75721
+ fs55.mkdir(target, dir.mode, function(err) {
75722
75722
  if (err) {
75723
75723
  return onError(err);
75724
75724
  }
@@ -75726,7 +75726,7 @@ var require_ncp = __commonJS({
75726
75726
  });
75727
75727
  }
75728
75728
  function copyDir(dir) {
75729
- fs54.readdir(dir, function(err, items) {
75729
+ fs55.readdir(dir, function(err, items) {
75730
75730
  if (err) {
75731
75731
  return onError(err);
75732
75732
  }
@@ -75738,7 +75738,7 @@ var require_ncp = __commonJS({
75738
75738
  }
75739
75739
  function onLink(link) {
75740
75740
  var target = link.replace(currentPath, targetPath);
75741
- fs54.readlink(link, function(err, resolvedPath) {
75741
+ fs55.readlink(link, function(err, resolvedPath) {
75742
75742
  if (err) {
75743
75743
  return onError(err);
75744
75744
  }
@@ -75753,7 +75753,7 @@ var require_ncp = __commonJS({
75753
75753
  if (writable) {
75754
75754
  return makeLink(resolvedPath, target);
75755
75755
  }
75756
- fs54.readlink(target, function(err, targetDest) {
75756
+ fs55.readlink(target, function(err, targetDest) {
75757
75757
  if (err) {
75758
75758
  return onError(err);
75759
75759
  }
@@ -75770,7 +75770,7 @@ var require_ncp = __commonJS({
75770
75770
  });
75771
75771
  }
75772
75772
  function makeLink(linkPath, target) {
75773
- fs54.symlink(linkPath, target, function(err) {
75773
+ fs55.symlink(linkPath, target, function(err) {
75774
75774
  if (err) {
75775
75775
  return onError(err);
75776
75776
  }
@@ -75778,7 +75778,7 @@ var require_ncp = __commonJS({
75778
75778
  });
75779
75779
  }
75780
75780
  function isWritable2(path41, done) {
75781
- fs54.lstat(path41, function(err) {
75781
+ fs55.lstat(path41, function(err) {
75782
75782
  if (err) {
75783
75783
  if (err.code === "ENOENT") return done(true);
75784
75784
  return done(false);
@@ -75790,7 +75790,7 @@ var require_ncp = __commonJS({
75790
75790
  if (options.stopOnError) {
75791
75791
  return cback(err);
75792
75792
  } else if (!errs && options.errs) {
75793
- errs = fs54.createWriteStream(options.errs);
75793
+ errs = fs55.createWriteStream(options.errs);
75794
75794
  } else if (!errs) {
75795
75795
  errs = [];
75796
75796
  }
@@ -76919,7 +76919,7 @@ var require_sync = __commonJS({
76919
76919
  "../../node_modules/glob/sync.js"(exports2, module2) {
76920
76920
  module2.exports = globSync;
76921
76921
  globSync.GlobSync = GlobSync;
76922
- var fs54 = require("fs");
76922
+ var fs55 = require("fs");
76923
76923
  var minimatch = require_minimatch();
76924
76924
  var Minimatch = minimatch.Minimatch;
76925
76925
  var Glob = require_glob().Glob;
@@ -76964,7 +76964,7 @@ var require_sync = __commonJS({
76964
76964
  for (var p in matchset) {
76965
76965
  try {
76966
76966
  p = self._makeAbs(p);
76967
- var real = fs54.realpathSync(p, self.realpathCache);
76967
+ var real = fs55.realpathSync(p, self.realpathCache);
76968
76968
  set2[real] = true;
76969
76969
  } catch (er) {
76970
76970
  if (er.syscall === "stat")
@@ -77091,7 +77091,7 @@ var require_sync = __commonJS({
77091
77091
  var lstat;
77092
77092
  var stat5;
77093
77093
  try {
77094
- lstat = fs54.lstatSync(abs);
77094
+ lstat = fs55.lstatSync(abs);
77095
77095
  } catch (er) {
77096
77096
  return null;
77097
77097
  }
@@ -77115,7 +77115,7 @@ var require_sync = __commonJS({
77115
77115
  return c;
77116
77116
  }
77117
77117
  try {
77118
- return this._readdirEntries(abs, fs54.readdirSync(abs));
77118
+ return this._readdirEntries(abs, fs55.readdirSync(abs));
77119
77119
  } catch (er) {
77120
77120
  this._readdirError(abs, er);
77121
77121
  return null;
@@ -77219,13 +77219,13 @@ var require_sync = __commonJS({
77219
77219
  if (!stat5) {
77220
77220
  var lstat;
77221
77221
  try {
77222
- lstat = fs54.lstatSync(abs);
77222
+ lstat = fs55.lstatSync(abs);
77223
77223
  } catch (er) {
77224
77224
  return false;
77225
77225
  }
77226
77226
  if (lstat.isSymbolicLink()) {
77227
77227
  try {
77228
- stat5 = fs54.statSync(abs);
77228
+ stat5 = fs55.statSync(abs);
77229
77229
  } catch (er) {
77230
77230
  stat5 = lstat;
77231
77231
  }
@@ -77299,7 +77299,7 @@ var require_inflight = __commonJS({
77299
77299
  var require_glob = __commonJS({
77300
77300
  "../../node_modules/glob/glob.js"(exports2, module2) {
77301
77301
  module2.exports = glob;
77302
- var fs54 = require("fs");
77302
+ var fs55 = require("fs");
77303
77303
  var minimatch = require_minimatch();
77304
77304
  var Minimatch = minimatch.Minimatch;
77305
77305
  var inherits = require_inherits();
@@ -77436,7 +77436,7 @@ var require_glob = __commonJS({
77436
77436
  var set2 = this.matches[index] = /* @__PURE__ */ Object.create(null);
77437
77437
  found.forEach(function(p, i) {
77438
77438
  p = self._makeAbs(p);
77439
- fs54.realpath(p, self.realpathCache, function(er, real) {
77439
+ fs55.realpath(p, self.realpathCache, function(er, real) {
77440
77440
  if (!er)
77441
77441
  set2[real] = true;
77442
77442
  else if (er.syscall === "stat")
@@ -77631,7 +77631,7 @@ var require_glob = __commonJS({
77631
77631
  var self = this;
77632
77632
  var lstatcb = inflight(lstatkey, lstatcb_);
77633
77633
  if (lstatcb)
77634
- fs54.lstat(abs, lstatcb);
77634
+ fs55.lstat(abs, lstatcb);
77635
77635
  function lstatcb_(er, lstat) {
77636
77636
  if (er)
77637
77637
  return cb();
@@ -77660,7 +77660,7 @@ var require_glob = __commonJS({
77660
77660
  return cb(null, c);
77661
77661
  }
77662
77662
  var self = this;
77663
- fs54.readdir(abs, readdirCb(this, abs, cb));
77663
+ fs55.readdir(abs, readdirCb(this, abs, cb));
77664
77664
  };
77665
77665
  function readdirCb(self, abs, cb) {
77666
77666
  return function(er, entries) {
@@ -77798,10 +77798,10 @@ var require_glob = __commonJS({
77798
77798
  var self = this;
77799
77799
  var statcb = inflight("stat\0" + abs, lstatcb_);
77800
77800
  if (statcb)
77801
- fs54.lstat(abs, statcb);
77801
+ fs55.lstat(abs, statcb);
77802
77802
  function lstatcb_(er, lstat) {
77803
77803
  if (lstat && lstat.isSymbolicLink()) {
77804
- return fs54.stat(abs, function(er2, stat6) {
77804
+ return fs55.stat(abs, function(er2, stat6) {
77805
77805
  if (er2)
77806
77806
  self._stat2(f, abs, null, lstat, cb);
77807
77807
  else
@@ -77837,7 +77837,7 @@ var require_rimraf = __commonJS({
77837
77837
  rimraf.sync = rimrafSync;
77838
77838
  var assert2 = require("assert");
77839
77839
  var path40 = require("path");
77840
- var fs54 = require("fs");
77840
+ var fs55 = require("fs");
77841
77841
  var glob = require_glob();
77842
77842
  var globOpts = {
77843
77843
  nosort: true,
@@ -77857,9 +77857,9 @@ var require_rimraf = __commonJS({
77857
77857
  "readdir"
77858
77858
  ];
77859
77859
  methods.forEach(function(m) {
77860
- options[m] = options[m] || fs54[m];
77860
+ options[m] = options[m] || fs55[m];
77861
77861
  m = m + "Sync";
77862
- options[m] = options[m] || fs54[m];
77862
+ options[m] = options[m] || fs55[m];
77863
77863
  });
77864
77864
  options.maxBusyTries = options.maxBusyTries || 3;
77865
77865
  options.emfileWait = options.emfileWait || 1e3;
@@ -77881,7 +77881,7 @@ var require_rimraf = __commonJS({
77881
77881
  var n = 0;
77882
77882
  if (options.disableGlob || !glob.hasMagic(p))
77883
77883
  return afterGlob(null, [p]);
77884
- fs54.lstat(p, function(er, stat5) {
77884
+ fs55.lstat(p, function(er, stat5) {
77885
77885
  if (!er)
77886
77886
  return afterGlob(null, [p]);
77887
77887
  glob(p, globOpts, afterGlob);
@@ -78038,7 +78038,7 @@ var require_rimraf = __commonJS({
78038
78038
  results = [p];
78039
78039
  } else {
78040
78040
  try {
78041
- fs54.lstatSync(p);
78041
+ fs55.lstatSync(p);
78042
78042
  results = [p];
78043
78043
  } catch (er) {
78044
78044
  results = glob.sync(p, globOpts);
@@ -78101,7 +78101,7 @@ var require_rimraf = __commonJS({
78101
78101
  var require_mkdirp = __commonJS({
78102
78102
  "../../node_modules/mkdirp/index.js"(exports2, module2) {
78103
78103
  var path40 = require("path");
78104
- var fs54 = require("fs");
78104
+ var fs55 = require("fs");
78105
78105
  var _0777 = parseInt("0777", 8);
78106
78106
  module2.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
78107
78107
  function mkdirP(p, opts, f, made) {
@@ -78112,7 +78112,7 @@ var require_mkdirp = __commonJS({
78112
78112
  opts = { mode: opts };
78113
78113
  }
78114
78114
  var mode = opts.mode;
78115
- var xfs = opts.fs || fs54;
78115
+ var xfs = opts.fs || fs55;
78116
78116
  if (mode === void 0) {
78117
78117
  mode = _0777;
78118
78118
  }
@@ -78151,7 +78151,7 @@ var require_mkdirp = __commonJS({
78151
78151
  opts = { mode: opts };
78152
78152
  }
78153
78153
  var mode = opts.mode;
78154
- var xfs = opts.fs || fs54;
78154
+ var xfs = opts.fs || fs55;
78155
78155
  if (mode === void 0) {
78156
78156
  mode = _0777;
78157
78157
  }
@@ -78188,7 +78188,7 @@ var require_mkdirp = __commonJS({
78188
78188
  // ../../node_modules/mv/index.js
78189
78189
  var require_mv = __commonJS({
78190
78190
  "../../node_modules/mv/index.js"(exports2, module2) {
78191
- var fs54 = require("fs");
78191
+ var fs55 = require("fs");
78192
78192
  var ncp = require_ncp().ncp;
78193
78193
  var path40 = require("path");
78194
78194
  var rimraf = require_rimraf();
@@ -78215,13 +78215,13 @@ var require_mv = __commonJS({
78215
78215
  }
78216
78216
  function doRename() {
78217
78217
  if (clobber) {
78218
- fs54.rename(source, dest, function(err) {
78218
+ fs55.rename(source, dest, function(err) {
78219
78219
  if (!err) return cb();
78220
78220
  if (err.code !== "EXDEV") return cb(err);
78221
78221
  moveFileAcrossDevice(source, dest, clobber, limit, cb);
78222
78222
  });
78223
78223
  } else {
78224
- fs54.link(source, dest, function(err) {
78224
+ fs55.link(source, dest, function(err) {
78225
78225
  if (err) {
78226
78226
  if (err.code === "EXDEV") {
78227
78227
  moveFileAcrossDevice(source, dest, clobber, limit, cb);
@@ -78234,15 +78234,15 @@ var require_mv = __commonJS({
78234
78234
  cb(err);
78235
78235
  return;
78236
78236
  }
78237
- fs54.unlink(source, cb);
78237
+ fs55.unlink(source, cb);
78238
78238
  });
78239
78239
  }
78240
78240
  }
78241
78241
  }
78242
78242
  function moveFileAcrossDevice(source, dest, clobber, limit, cb) {
78243
78243
  var outFlags = clobber ? "w" : "wx";
78244
- var ins = fs54.createReadStream(source);
78245
- var outs = fs54.createWriteStream(dest, { flags: outFlags });
78244
+ var ins = fs55.createReadStream(source);
78245
+ var outs = fs55.createWriteStream(dest, { flags: outFlags });
78246
78246
  ins.on("error", function(err) {
78247
78247
  ins.destroy();
78248
78248
  outs.destroy();
@@ -78262,7 +78262,7 @@ var require_mv = __commonJS({
78262
78262
  outs.once("close", onClose);
78263
78263
  ins.pipe(outs);
78264
78264
  function onClose() {
78265
- fs54.unlink(source, cb);
78265
+ fs55.unlink(source, cb);
78266
78266
  }
78267
78267
  }
78268
78268
  function moveDirAcrossDevice(source, dest, clobber, limit, cb) {
@@ -78317,7 +78317,7 @@ var require_bunyan = __commonJS({
78317
78317
  throw new Error("unknown runtime environment");
78318
78318
  }
78319
78319
  var os15;
78320
- var fs54;
78320
+ var fs55;
78321
78321
  var dtrace;
78322
78322
  if (runtimeEnv === "browser") {
78323
78323
  os15 = {
@@ -78325,11 +78325,11 @@ var require_bunyan = __commonJS({
78325
78325
  return window.location.host;
78326
78326
  }
78327
78327
  };
78328
- fs54 = {};
78328
+ fs55 = {};
78329
78329
  dtrace = null;
78330
78330
  } else {
78331
78331
  os15 = require("os");
78332
- fs54 = require("fs");
78332
+ fs55 = require("fs");
78333
78333
  try {
78334
78334
  dtrace = require("dtrace-provider");
78335
78335
  } catch (e) {
@@ -78709,7 +78709,7 @@ var require_bunyan = __commonJS({
78709
78709
  s.reemitErrorEvents = true;
78710
78710
  }
78711
78711
  if (!s.stream) {
78712
- s.stream = fs54.createWriteStream(
78712
+ s.stream = fs55.createWriteStream(
78713
78713
  s.path,
78714
78714
  { flags: "a", encoding: "utf8" }
78715
78715
  );
@@ -78779,7 +78779,7 @@ var require_bunyan = __commonJS({
78779
78779
  s.stream.destroySoon();
78780
78780
  delete s.stream;
78781
78781
  }
78782
- s.stream = fs54.createWriteStream(
78782
+ s.stream = fs55.createWriteStream(
78783
78783
  s.path,
78784
78784
  { flags: "a", encoding: "utf8" }
78785
78785
  );
@@ -79121,7 +79121,7 @@ var require_bunyan = __commonJS({
79121
79121
  }
79122
79122
  var lastModified = null;
79123
79123
  try {
79124
- var fileInfo = fs54.statSync(this.path);
79124
+ var fileInfo = fs55.statSync(this.path);
79125
79125
  lastModified = fileInfo.mtime.getTime();
79126
79126
  } catch (err) {
79127
79127
  }
@@ -79132,7 +79132,7 @@ var require_bunyan = __commonJS({
79132
79132
  rotateAfterOpen = true;
79133
79133
  }
79134
79134
  }
79135
- this.stream = fs54.createWriteStream(
79135
+ this.stream = fs55.createWriteStream(
79136
79136
  this.path,
79137
79137
  { flags: "a", encoding: "utf8" }
79138
79138
  );
@@ -79299,7 +79299,7 @@ var require_bunyan = __commonJS({
79299
79299
  }
79300
79300
  n -= 1;
79301
79301
  self._debug(" rm %s", toDel);
79302
- fs54.unlink(toDel, function(delErr) {
79302
+ fs55.unlink(toDel, function(delErr) {
79303
79303
  moves();
79304
79304
  });
79305
79305
  }
@@ -79313,7 +79313,7 @@ var require_bunyan = __commonJS({
79313
79313
  before += "." + String(n - 1);
79314
79314
  }
79315
79315
  n -= 1;
79316
- fs54.exists(before, function(exists2) {
79316
+ fs55.exists(before, function(exists2) {
79317
79317
  if (!exists2) {
79318
79318
  moves();
79319
79319
  } else {
@@ -79331,7 +79331,7 @@ var require_bunyan = __commonJS({
79331
79331
  }
79332
79332
  function finish() {
79333
79333
  self._debug(" open %s", self.path);
79334
- self.stream = fs54.createWriteStream(
79334
+ self.stream = fs55.createWriteStream(
79335
79335
  self.path,
79336
79336
  { flags: "a", encoding: "utf8" }
79337
79337
  );
@@ -83276,7 +83276,7 @@ var require_png = __commonJS({
83276
83276
  var Parser = require_parser_async();
83277
83277
  var Packer = require_packer_async();
83278
83278
  var PNGSync = require_png_sync();
83279
- var PNG4 = exports2.PNG = function(options) {
83279
+ var PNG5 = exports2.PNG = function(options) {
83280
83280
  Stream2.call(this);
83281
83281
  options = options || {};
83282
83282
  this.width = options.width | 0;
@@ -83305,9 +83305,9 @@ var require_png = __commonJS({
83305
83305
  this._parser.on("close", this._handleClose.bind(this));
83306
83306
  this._packer.on("error", this.emit.bind(this, "error"));
83307
83307
  };
83308
- util.inherits(PNG4, Stream2);
83309
- PNG4.sync = PNGSync;
83310
- PNG4.prototype.pack = function() {
83308
+ util.inherits(PNG5, Stream2);
83309
+ PNG5.sync = PNGSync;
83310
+ PNG5.prototype.pack = function() {
83311
83311
  if (!this.data || !this.data.length) {
83312
83312
  this.emit("error", "No data provided");
83313
83313
  return this;
@@ -83319,7 +83319,7 @@ var require_png = __commonJS({
83319
83319
  );
83320
83320
  return this;
83321
83321
  };
83322
- PNG4.prototype.parse = function(data, callback) {
83322
+ PNG5.prototype.parse = function(data, callback) {
83323
83323
  if (callback) {
83324
83324
  let onParsed, onError;
83325
83325
  onParsed = function(parsedData) {
@@ -83337,27 +83337,27 @@ var require_png = __commonJS({
83337
83337
  this.end(data);
83338
83338
  return this;
83339
83339
  };
83340
- PNG4.prototype.write = function(data) {
83340
+ PNG5.prototype.write = function(data) {
83341
83341
  this._parser.write(data);
83342
83342
  return true;
83343
83343
  };
83344
- PNG4.prototype.end = function(data) {
83344
+ PNG5.prototype.end = function(data) {
83345
83345
  this._parser.end(data);
83346
83346
  };
83347
- PNG4.prototype._metadata = function(metadata) {
83347
+ PNG5.prototype._metadata = function(metadata) {
83348
83348
  this.width = metadata.width;
83349
83349
  this.height = metadata.height;
83350
83350
  this.emit("metadata", metadata);
83351
83351
  };
83352
- PNG4.prototype._gamma = function(gamma) {
83352
+ PNG5.prototype._gamma = function(gamma) {
83353
83353
  this.gamma = gamma;
83354
83354
  };
83355
- PNG4.prototype._handleClose = function() {
83355
+ PNG5.prototype._handleClose = function() {
83356
83356
  if (!this._parser.writable && !this._packer.readable) {
83357
83357
  this.emit("close");
83358
83358
  }
83359
83359
  };
83360
- PNG4.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) {
83360
+ PNG5.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) {
83361
83361
  srcX |= 0;
83362
83362
  srcY |= 0;
83363
83363
  width |= 0;
@@ -83379,11 +83379,11 @@ var require_png = __commonJS({
83379
83379
  );
83380
83380
  }
83381
83381
  };
83382
- PNG4.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) {
83383
- PNG4.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
83382
+ PNG5.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) {
83383
+ PNG5.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
83384
83384
  return this;
83385
83385
  };
83386
- PNG4.adjustGamma = function(src) {
83386
+ PNG5.adjustGamma = function(src) {
83387
83387
  if (src.gamma) {
83388
83388
  for (let y = 0; y < src.height; y++) {
83389
83389
  for (let x = 0; x < src.width; x++) {
@@ -83398,8 +83398,8 @@ var require_png = __commonJS({
83398
83398
  src.gamma = 0;
83399
83399
  }
83400
83400
  };
83401
- PNG4.prototype.adjustGamma = function() {
83402
- PNG4.adjustGamma(this);
83401
+ PNG5.prototype.adjustGamma = function() {
83402
+ PNG5.adjustGamma(this);
83403
83403
  };
83404
83404
  }
83405
83405
  });
@@ -90282,14 +90282,14 @@ var require_parser2 = __commonJS({
90282
90282
  case "scalar":
90283
90283
  case "single-quoted-scalar":
90284
90284
  case "double-quoted-scalar": {
90285
- const fs54 = this.flowScalar(this.type);
90285
+ const fs55 = this.flowScalar(this.type);
90286
90286
  if (atNextItem || it.value) {
90287
- map2.items.push({ start: start2, key: fs54, sep: [] });
90287
+ map2.items.push({ start: start2, key: fs55, sep: [] });
90288
90288
  this.onKeyLine = true;
90289
90289
  } else if (it.sep) {
90290
- this.stack.push(fs54);
90290
+ this.stack.push(fs55);
90291
90291
  } else {
90292
- Object.assign(it, { key: fs54, sep: [] });
90292
+ Object.assign(it, { key: fs55, sep: [] });
90293
90293
  this.onKeyLine = true;
90294
90294
  }
90295
90295
  return;
@@ -90417,13 +90417,13 @@ var require_parser2 = __commonJS({
90417
90417
  case "scalar":
90418
90418
  case "single-quoted-scalar":
90419
90419
  case "double-quoted-scalar": {
90420
- const fs54 = this.flowScalar(this.type);
90420
+ const fs55 = this.flowScalar(this.type);
90421
90421
  if (!it || it.value)
90422
- fc.items.push({ start: [], key: fs54, sep: [] });
90422
+ fc.items.push({ start: [], key: fs55, sep: [] });
90423
90423
  else if (it.sep)
90424
- this.stack.push(fs54);
90424
+ this.stack.push(fs55);
90425
90425
  else
90426
- Object.assign(it, { key: fs54, sep: [] });
90426
+ Object.assign(it, { key: fs55, sep: [] });
90427
90427
  return;
90428
90428
  }
90429
90429
  case "flow-map-end":
@@ -135709,14 +135709,14 @@ function parseHangsXml(xml) {
135709
135709
  function parseLeaksXml(xml) {
135710
135710
  const leaks = [];
135711
135711
  const rowRe = /<row\s+([^>]*?)\/>/g;
135712
- let rm7;
135713
- while ((rm7 = rowRe.exec(xml)) !== null) {
135714
- const objectType = attr(rm7[0], "leaked-object") ?? "Unknown";
135715
- const sizeStr = attr(rm7[0], "size");
135712
+ let rm8;
135713
+ while ((rm8 = rowRe.exec(xml)) !== null) {
135714
+ const objectType = attr(rm8[0], "leaked-object") ?? "Unknown";
135715
+ const sizeStr = attr(rm8[0], "size");
135716
135716
  const sizeBytes = sizeStr ? parseInt(sizeStr, 10) : 0;
135717
- const responsibleFrame = attr(rm7[0], "responsible-frame") ?? "Unknown";
135718
- const responsibleLibrary = attr(rm7[0], "responsible-library") ?? "";
135719
- const countStr = attr(rm7[0], "count");
135717
+ const responsibleFrame = attr(rm8[0], "responsible-frame") ?? "Unknown";
135718
+ const responsibleLibrary = attr(rm8[0], "responsible-library") ?? "";
135719
+ const countStr = attr(rm8[0], "count");
135720
135720
  const count2 = countStr ? parseInt(countStr, 10) : 1;
135721
135721
  leaks.push({
135722
135722
  objectType,
@@ -142440,10 +142440,18 @@ function waitToYaml(condition, selector, expectedText, textMatch, timeoutMs) {
142440
142440
  if (timeoutMs !== void 0) body.timeout = timeoutMs;
142441
142441
  return body;
142442
142442
  }
142443
+ function idleToYaml(step) {
142444
+ const body = { idle: true };
142445
+ if (step.stableFor !== void 0) body.stableFor = step.stableFor;
142446
+ if (step.timeout !== void 0) body.timeout = step.timeout;
142447
+ return { await: body };
142448
+ }
142443
142449
  function toYamlStep(step) {
142444
142450
  switch (step.kind) {
142445
142451
  case "echo":
142446
142452
  return { echo: step.message };
142453
+ case "idle":
142454
+ return idleToYaml(step);
142447
142455
  case "launch":
142448
142456
  return { launch: step.app };
142449
142457
  case "run":
@@ -142735,16 +142743,14 @@ var TEXT_MATCH_MODES = Object.keys({
142735
142743
  });
142736
142744
  var SCROLL_DIRECTIONS = ["up", "down", "left", "right"];
142737
142745
  function parseWaitFields(raw, kind) {
142746
+ const legalKeys = kind === "await" ? [...WAIT_CONDITIONS, IDLE_CONDITION] : WAIT_CONDITIONS;
142738
142747
  if (raw === null || typeof raw !== "object") {
142739
- badEntry({ [kind]: raw }, `${kind} needs a condition (${WAIT_CONDITIONS.join(", ")})`);
142748
+ badEntry({ [kind]: raw }, `${kind} needs a condition (${legalKeys.join(", ")})`);
142740
142749
  }
142741
142750
  const b = raw;
142742
142751
  const present = WAIT_CONDITIONS.filter((c) => c in b);
142743
142752
  if (present.length !== 1) {
142744
- badEntry(
142745
- { [kind]: b },
142746
- `${kind} needs exactly one condition key (${WAIT_CONDITIONS.join(", ")})`
142747
- );
142753
+ badEntry({ [kind]: b }, `${kind} needs exactly one condition key (${legalKeys.join(", ")})`);
142748
142754
  }
142749
142755
  const condition = present[0];
142750
142756
  let timeout;
@@ -142755,13 +142761,7 @@ function parseWaitFields(raw, kind) {
142755
142761
  "assert has no timeout \u2014 it is an immediate check; use `await` for a timed wait"
142756
142762
  );
142757
142763
  }
142758
- if (typeof b.timeout !== "number" || !Number.isFinite(b.timeout) || b.timeout <= 0) {
142759
- badEntry(
142760
- { [kind]: b },
142761
- "await.timeout needs a positive number of milliseconds (e.g. `timeout: 10000`)"
142762
- );
142763
- }
142764
- timeout = b.timeout;
142764
+ timeout = parseAwaitTimeout({ [kind]: b }, b.timeout);
142765
142765
  }
142766
142766
  rejectUnknownKeys(
142767
142767
  { [kind]: b },
@@ -142806,6 +142806,76 @@ function parseWaitFields(raw, kind) {
142806
142806
  }
142807
142807
  return { condition, selector: parseSelector(b[condition], `${kind}.${condition}`), timeout };
142808
142808
  }
142809
+ var IDLE_CONDITION = "idle";
142810
+ var IDLE_DEFAULT_TIMEOUT_MS = 7500;
142811
+ var IDLE_DEFAULT_STABLE_FOR_MS = 250;
142812
+ var IDLE_POLL_MS = 200;
142813
+ var IDLE_MIN_STILL_INTERVALS = 2;
142814
+ var IDLE_SETTLE_SPAN_MS = IDLE_MIN_STILL_INTERVALS * IDLE_POLL_MS;
142815
+ function idleMinimumTimeoutMs(stableFor) {
142816
+ return Math.max(IDLE_SETTLE_SPAN_MS, stableFor) + IDLE_POLL_MS;
142817
+ }
142818
+ var IDLE_MAX_STABLE_FOR_MS = 6e5;
142819
+ function parseAwaitTimeout(entry, value) {
142820
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
142821
+ badEntry(
142822
+ entry,
142823
+ "await.timeout needs a positive number of milliseconds (e.g. `timeout: 10000`)"
142824
+ );
142825
+ }
142826
+ return value;
142827
+ }
142828
+ function parseBoundedMs(entry, value, where, max) {
142829
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > max) {
142830
+ badEntry(entry, `${where} needs an integer between 0 and ${max} (milliseconds)`);
142831
+ }
142832
+ return value;
142833
+ }
142834
+ function parseIdleFields(raw, kind) {
142835
+ const entry = { [kind]: raw };
142836
+ if (kind !== "await") {
142837
+ const mixed = WAIT_CONDITIONS.filter((c) => c in raw);
142838
+ badEntry(
142839
+ entry,
142840
+ "idle has no assert form \u2014 it waits for the screen to stop changing, which is an `await`" + (mixed.length > 0 ? `. Give it its own step as \`await: { idle: true }\` and leave \`${mixed.join(
142841
+ "`, `"
142842
+ )}\` in the assert \u2014 a step checks exactly one condition` : "")
142843
+ );
142844
+ }
142845
+ rejectUnknownKeys(entry, raw, ["idle", "stableFor", "timeout"], kind);
142846
+ if (raw.idle !== true) {
142847
+ badEntry(entry, "idle takes only `true` (`await: { idle: true }`)");
142848
+ }
142849
+ const step = { kind: "idle" };
142850
+ if ("timeout" in raw) step.timeout = parseAwaitTimeout(entry, raw.timeout);
142851
+ if (raw.stableFor !== void 0) {
142852
+ step.stableFor = parseBoundedMs(entry, raw.stableFor, "idle.stableFor", IDLE_MAX_STABLE_FOR_MS);
142853
+ }
142854
+ const timeoutMs = step.timeout ?? IDLE_DEFAULT_TIMEOUT_MS;
142855
+ const stableFor = step.stableFor ?? IDLE_DEFAULT_STABLE_FOR_MS;
142856
+ const needed = idleMinimumTimeoutMs(stableFor);
142857
+ if (timeoutMs < needed) {
142858
+ badEntry(
142859
+ entry,
142860
+ `idle needs a timeout of at least ${needed}ms to hold still for ${step.stableFor === void 0 ? `the default ` : ``}${stableFor}ms: a settle is ${IDLE_MIN_STILL_INTERVALS + 1} reads spanning ${IDLE_MIN_STILL_INTERVALS} ${IDLE_POLL_MS}ms polls, and the hold is counted across those polls rather than after them \u2014 so the wait has to contain whichever of the two is longer, plus the ${IDLE_POLL_MS}ms of budget the closing round has to have left to be allowed to start. Raise \`timeout\`${step.stableFor === void 0 ? "" : " or lower `stableFor`"}`
142861
+ );
142862
+ }
142863
+ return step;
142864
+ }
142865
+ function isIdleCondition(raw, kind) {
142866
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return false;
142867
+ const body = raw;
142868
+ if (!(IDLE_CONDITION in body)) return false;
142869
+ if (kind === "assert") return true;
142870
+ const selectorConditions = WAIT_CONDITIONS.filter((c) => c in body);
142871
+ if (selectorConditions.length > 0) {
142872
+ badEntry(
142873
+ { [kind]: body },
142874
+ `${kind} mixes \`${IDLE_CONDITION}\` with \`${selectorConditions.join("`, `")}\` \u2014 a step checks exactly one condition`
142875
+ );
142876
+ }
142877
+ return true;
142878
+ }
142809
142879
  var LAUNCH_PLATFORMS = ["ios", "android", "chromium", "vega"];
142810
142880
  var LAUNCH_MAP_KEYS = ["native", ...LAUNCH_PLATFORMS];
142811
142881
  function parseChromiumLaunch(raw) {
@@ -143019,6 +143089,12 @@ function parseWhenCondition(raw) {
143019
143089
  badEntry({ when: raw }, `when needs exactly one condition key (${conditionKeys})`);
143020
143090
  }
143021
143091
  const b = raw;
143092
+ if (IDLE_CONDITION in b) {
143093
+ badEntry(
143094
+ { when: raw },
143095
+ "when has no idle form \u2014 stillness is a wait, and a guard asks what is on the screen now. Put `await: { idle: true }` before the block instead"
143096
+ );
143097
+ }
143022
143098
  const present = [...WAIT_CONDITIONS, "platform"].filter((c) => c in b);
143023
143099
  if (present.length !== 1) {
143024
143100
  badEntry({ when: raw }, `when needs exactly one condition key (${conditionKeys})`);
@@ -143128,6 +143204,9 @@ function fromYamlStep(raw, whenDepth = 0) {
143128
143204
  }
143129
143205
  const kinds = STEP_DIRECTIVE_KEYS.filter((k) => k in entry);
143130
143206
  if (kinds.length === 0) {
143207
+ if (IDLE_CONDITION in entry) {
143208
+ badEntry(raw, `idle is a condition, not a step kind \u2014 write it as \`await: { idle: true }\``);
143209
+ }
143131
143210
  const hint = Object.keys(entry).map((k) => closestKey(k, STEP_DIRECTIVE_KEYS)).find((h) => h !== null);
143132
143211
  badEntry(raw, `unrecognized step kind${hint ? ` (did you mean \`${hint}\`?)` : ""}`);
143133
143212
  }
@@ -143175,10 +143254,18 @@ function fromYamlStep(raw, whenDepth = 0) {
143175
143254
  return step;
143176
143255
  }
143177
143256
  if ("await" in raw) {
143178
- return { kind: "await", ...parseWaitFields(raw.await, "await") };
143257
+ const body = raw.await;
143258
+ if (isIdleCondition(body, "await")) {
143259
+ return parseIdleFields(body, "await");
143260
+ }
143261
+ return { kind: "await", ...parseWaitFields(body, "await") };
143179
143262
  }
143180
143263
  if ("assert" in raw) {
143181
- return { kind: "assert", ...parseWaitFields(raw.assert, "assert") };
143264
+ const body = raw.assert;
143265
+ if (isIdleCondition(body, "assert")) {
143266
+ return parseIdleFields(body, "assert");
143267
+ }
143268
+ return { kind: "assert", ...parseWaitFields(body, "assert") };
143182
143269
  }
143183
143270
  if ("wait" in raw) {
143184
143271
  const ms = Number(raw.wait);
@@ -143709,6 +143796,7 @@ function stepRequiresDevice(registry2, step) {
143709
143796
  case "type":
143710
143797
  case "await":
143711
143798
  case "assert":
143799
+ case "idle":
143712
143800
  case "scroll-to":
143713
143801
  case "pinch":
143714
143802
  case "rotate":
@@ -144563,6 +144651,8 @@ function summarizeSteps(flow) {
144563
144651
  return `${n}. rotate: by ${step.by}\xB0${step.selector ? ` on ${selectorLabel(step.selector)}` : ""}`;
144564
144652
  case "snapshot":
144565
144653
  return `${n}. snapshot: ${step.name}`;
144654
+ case "idle":
144655
+ return `${n}. await: screen idle`;
144566
144656
  case "tool":
144567
144657
  default:
144568
144658
  return `${n}. tool: ${step.name} ${renderToolArgs(step.args)}`;
@@ -144572,7 +144662,7 @@ function summarizeSteps(flow) {
144572
144662
 
144573
144663
  // ../tool-server/src/tools/flows/flow-run.ts
144574
144664
  init_zod();
144575
- var fs48 = __toESM(require("node:fs/promises"));
144665
+ var fs49 = __toESM(require("node:fs/promises"));
144576
144666
  var path35 = __toESM(require("node:path"));
144577
144667
  init_src();
144578
144668
 
@@ -144644,6 +144734,122 @@ function nestedOrchestratorOutcome(tool, result) {
144644
144734
  return void 0;
144645
144735
  }
144646
144736
 
144737
+ // ../tool-server/src/tools/flows/flow-pixels.ts
144738
+ var fs46 = __toESM(require("node:fs/promises"));
144739
+ var import_pngjs2 = __toESM(require_png());
144740
+ init_adb();
144741
+ var CAPTURE_SCALE = 0.25;
144742
+ var PIXEL_THRESHOLD = 0.03;
144743
+ var MAX_RGB_DISTANCE_SQUARED = 255 * 255 * 3;
144744
+ var PIXEL_THRESHOLD_SQUARED = PIXEL_THRESHOLD * PIXEL_THRESHOLD * MAX_RGB_DISTANCE_SQUARED;
144745
+ var MOTION_FRACTION = 2e-3;
144746
+ var MOTION_MIN_PIXELS = 100;
144747
+ var MOTION_MIN_PIXELS_FRAME_SHARE = 0.1;
144748
+ var LOCALIZED_MOTION_MIN_PIXELS = 10;
144749
+ var STATUS_BAR_MASK_FRACTION = 0.06;
144750
+ async function statusBarMaskFraction(device) {
144751
+ if (device.platform === "android") {
144752
+ return await isAndroidTv(device.id) ? 0 : STATUS_BAR_MASK_FRACTION;
144753
+ }
144754
+ if (device.platform === "ios-remote") return STATUS_BAR_MASK_FRACTION;
144755
+ if (device.platform !== "ios") return 0;
144756
+ return await isTvOsSimulator(device.id) ? 0 : STATUS_BAR_MASK_FRACTION;
144757
+ }
144758
+ var FIRST_CAPTURE_COMPLETION_MARGIN_MS = 500;
144759
+ var FIRST_PIXEL_CAPTURE_TIMEOUT_MS = FIRST_FRAME_WAIT_MS + FIRST_CAPTURE_COMPLETION_MARGIN_MS;
144760
+ var PIXEL_CAPTURE_TIMEOUT_MS = 2e3;
144761
+ function pixelCaptureTimeoutMs(device, firstCapture) {
144762
+ const warmFromTheStart = device.platform === "chromium" || device.platform === "vega";
144763
+ return firstCapture && !warmFromTheStart ? FIRST_PIXEL_CAPTURE_TIMEOUT_MS : PIXEL_CAPTURE_TIMEOUT_MS;
144764
+ }
144765
+ async function captureChromiumPng(env) {
144766
+ const ref = chromiumCdpRef(env.device);
144767
+ const api = await env.registry.resolveService(ref.urn, ref.options);
144768
+ const { width, height } = api.getViewport();
144769
+ const { x, y } = await chromiumScrollOffset(api);
144770
+ const shot = await api.cdp.send("Page.captureScreenshot", {
144771
+ format: "png",
144772
+ captureBeyondViewport: false,
144773
+ clip: { x, y, width, height, scale: CAPTURE_SCALE }
144774
+ });
144775
+ if (!shot.data) throw new Error("Page.captureScreenshot returned no data");
144776
+ return Buffer.from(shot.data, "base64");
144777
+ }
144778
+ async function chromiumScrollOffset(api) {
144779
+ try {
144780
+ const metrics = await api.cdp.send("Page.getLayoutMetrics");
144781
+ const vp = metrics.cssVisualViewport ?? metrics.cssLayoutViewport ?? metrics.layoutViewport;
144782
+ const x = vp?.pageX;
144783
+ const y = vp?.pageY;
144784
+ return {
144785
+ x: typeof x === "number" && Number.isFinite(x) ? x : 0,
144786
+ y: typeof y === "number" && Number.isFinite(y) ? y : 0
144787
+ };
144788
+ } catch {
144789
+ return { x: 0, y: 0 };
144790
+ }
144791
+ }
144792
+ async function captureFile(env, budgetMs) {
144793
+ if (env.device.platform === "vega") {
144794
+ return captureVegaScreenshotPng({ scale: CAPTURE_SCALE });
144795
+ }
144796
+ if (env.device.platform === "ios" && await isTvOsSimulator(env.device.id)) {
144797
+ return tvScreenshot(env.device.id, CAPTURE_SCALE, captureAbortSignal(env, budgetMs));
144798
+ }
144799
+ const ref = simulatorServerRef(env.device);
144800
+ const api = await env.registry.resolveService(ref.urn, ref.options);
144801
+ const { path: path40 } = await httpScreenshot(api, void 0, void 0, CAPTURE_SCALE);
144802
+ return path40;
144803
+ }
144804
+ async function capturePng(env, budgetMs) {
144805
+ if (env.device.platform === "chromium") return captureChromiumPng(env);
144806
+ const file2 = await captureFile(env, budgetMs);
144807
+ try {
144808
+ return await fs46.readFile(file2);
144809
+ } finally {
144810
+ await fs46.rm(file2, { force: true }).catch(() => {
144811
+ });
144812
+ }
144813
+ }
144814
+ async function capturePixels(env, budgetMs) {
144815
+ try {
144816
+ const png = import_pngjs2.PNG.sync.read(await capturePng(env, budgetMs));
144817
+ return { width: png.width, height: png.height, data: png.data };
144818
+ } catch {
144819
+ return void 0;
144820
+ }
144821
+ }
144822
+ async function capturePixelsWithin(env, deadline, firstCapture) {
144823
+ const budget = Math.min(deadline - Date.now(), pixelCaptureTimeoutMs(env.device, firstCapture));
144824
+ if (budget <= 0) return void 0;
144825
+ const result = await settleWithin(capturePixels(env, budget), budget, env.signal);
144826
+ return result.type === "value" ? result.value : void 0;
144827
+ }
144828
+ function captureAbortSignal(env, budgetMs) {
144829
+ const bound = AbortSignal.timeout(budgetMs);
144830
+ return env.signal ? AbortSignal.any([env.signal, bound]) : bound;
144831
+ }
144832
+ function comparePixels(a, b, maskTopFraction = 0) {
144833
+ if (a.width !== b.width || a.height !== b.height) return "moving";
144834
+ const maskedRows = Math.min(a.height, Math.floor(a.height * maskTopFraction));
144835
+ const total = a.width * (a.height - maskedRows);
144836
+ if (total <= 0) return "still";
144837
+ const limit = Math.min(a.data.length, b.data.length);
144838
+ let changed = 0;
144839
+ for (let o = maskedRows * a.width * 4; o + 2 < limit; o += 4) {
144840
+ const dr = a.data[o] - b.data[o];
144841
+ const dg = a.data[o + 1] - b.data[o + 1];
144842
+ const db = a.data[o + 2] - b.data[o + 2];
144843
+ if (dr * dr + dg * dg + db * db > PIXEL_THRESHOLD_SQUARED) changed++;
144844
+ }
144845
+ const motionThreshold = Math.max(
144846
+ total * MOTION_FRACTION,
144847
+ Math.min(MOTION_MIN_PIXELS, total * MOTION_MIN_PIXELS_FRAME_SHARE)
144848
+ );
144849
+ if (changed > motionThreshold) return "moving";
144850
+ return changed >= LOCALIZED_MOTION_MIN_PIXELS ? "localized" : "still";
144851
+ }
144852
+
144647
144853
  // ../tool-server/src/tools/flows/flow-actions.ts
144648
144854
  var ABORTED_OUTCOME = {
144649
144855
  ok: false,
@@ -144889,6 +145095,8 @@ async function runDirective(env, step) {
144889
145095
  return waitForCondition(env, step, step.timeout ?? DEFAULT_ACTION_TIMEOUT_MS);
144890
145096
  case "assert":
144891
145097
  return waitForCondition(env, step, DEFAULT_ASSERT_TIMEOUT_MS);
145098
+ case "idle":
145099
+ return waitForIdle(env, step);
144892
145100
  case "scroll-to": {
144893
145101
  const r = await scrollToVisible(env, step.target, step.direction, step.within);
144894
145102
  if (r.aborted) return ABORTED_OUTCOME;
@@ -145131,6 +145339,215 @@ async function waitForCondition(env, step, timeoutMs) {
145131
145339
  reason: assertReason(step.condition, step.selector, step.expectedText, step.textMatch, lastMatches) + blipNote
145132
145340
  };
145133
145341
  }
145342
+ var MIN_STILL_INTERVALS = IDLE_MIN_STILL_INTERVALS;
145343
+ var MIN_ROUND_BUDGET_MS = IDLE_POLL_MS;
145344
+ var LOCALIZED_MOTION_WARNING = `the screen settled, but a small part of it was still changing while it did \u2014 a spinner, a caret, a progress dot. If it is a loading spinner then the screen had not finished loading, and stillness cannot tell those apart: look at what is moving, and gate the next action on the element the loading produces rather than on this settle.`;
145345
+ var HUNG_TREE_READ_MS = 2e3;
145346
+ var IDLE_TOLERATED_DARK_READS = 1;
145347
+ function isBlindTreeRead(data) {
145348
+ return data.tree.children.length === 0 && Boolean(data.hint || data.should_restart);
145349
+ }
145350
+ async function waitForIdle(env, step) {
145351
+ const timeoutMs = step.timeout ?? IDLE_DEFAULT_TIMEOUT_MS;
145352
+ const stableFor = step.stableFor ?? IDLE_DEFAULT_STABLE_FOR_MS;
145353
+ const maskTopFraction = await statusBarMaskFraction(env.device);
145354
+ const deadline = Date.now() + timeoutMs;
145355
+ let treeSignature2;
145356
+ let treeSince = 0;
145357
+ let treeStillIntervals = 0;
145358
+ let treeSettledAtLastRead = false;
145359
+ let previousFrame;
145360
+ let bothSince = 0;
145361
+ let stillIntervals = 0;
145362
+ let heldForMs = 0;
145363
+ let localizedMotionDuringHold = false;
145364
+ let readsSucceeded = 0;
145365
+ let contentReads = 0;
145366
+ let lastRead;
145367
+ let treeErrorMessage;
145368
+ let treeReadBlind = false;
145369
+ let blindHint;
145370
+ let darkReads = 0;
145371
+ let treeReadHung = false;
145372
+ let slowestAnsweredReadMs = 0;
145373
+ let sawContent = false;
145374
+ let pixelsEverMoved = false;
145375
+ let comparedAPair = false;
145376
+ let firstCapture = true;
145377
+ for (; ; ) {
145378
+ if (env.signal?.aborted) return ABORTED_OUTCOME;
145379
+ const roundBudget = Math.max(1, deadline - Date.now());
145380
+ const roundStartedAt = Date.now();
145381
+ let answeredReadMs;
145382
+ const [read, frame] = await Promise.all([
145383
+ settleWithin(fetchFlowTree(env.registry, env.device), roundBudget, env.signal).then((r) => {
145384
+ answeredReadMs = Date.now() - roundStartedAt;
145385
+ return r;
145386
+ }),
145387
+ capturePixelsWithin(env, deadline, firstCapture)
145388
+ ]);
145389
+ firstCapture = false;
145390
+ if (env.signal?.aborted || read.type === "aborted") return ABORTED_OUTCOME;
145391
+ if (read.type !== "timeout" && answeredReadMs !== void 0) {
145392
+ slowestAnsweredReadMs = Math.max(slowestAnsweredReadMs, answeredReadMs);
145393
+ }
145394
+ if (read.type === "timeout") {
145395
+ lastRead = "timeout";
145396
+ darkReads += 1;
145397
+ if (roundBudget >= HUNG_TREE_READ_MS && roundBudget > slowestAnsweredReadMs + HUNG_TREE_READ_MS) {
145398
+ treeReadHung = true;
145399
+ }
145400
+ } else if (read.type === "value" && isBlindTreeRead(read.value)) {
145401
+ lastRead = "blind";
145402
+ darkReads += 1;
145403
+ treeReadBlind = true;
145404
+ blindHint = read.value.hint;
145405
+ } else if (read.type === "error") {
145406
+ lastRead = "error";
145407
+ darkReads += 1;
145408
+ treeErrorMessage = read.error;
145409
+ treeSignature2 = void 0;
145410
+ previousFrame = void 0;
145411
+ treeSince = 0;
145412
+ treeStillIntervals = 0;
145413
+ treeSettledAtLastRead = false;
145414
+ bothSince = 0;
145415
+ stillIntervals = 0;
145416
+ } else {
145417
+ lastRead = "value";
145418
+ readsSucceeded += 1;
145419
+ darkReads = 0;
145420
+ treeErrorMessage = void 0;
145421
+ treeReadBlind = false;
145422
+ blindHint = void 0;
145423
+ treeReadHung = false;
145424
+ const tree = read.value.tree;
145425
+ if (tree.children.length === 0) {
145426
+ treeSignature2 = void 0;
145427
+ previousFrame = void 0;
145428
+ treeSince = 0;
145429
+ treeStillIntervals = 0;
145430
+ treeSettledAtLastRead = false;
145431
+ bothSince = 0;
145432
+ stillIntervals = 0;
145433
+ } else {
145434
+ sawContent = true;
145435
+ contentReads += 1;
145436
+ const signature = treeFingerprint(tree);
145437
+ const now = Date.now();
145438
+ const treeHeld = signature === treeSignature2;
145439
+ treeSignature2 = signature;
145440
+ if (!treeHeld) {
145441
+ treeSince = now;
145442
+ treeStillIntervals = 0;
145443
+ } else {
145444
+ treeStillIntervals += 1;
145445
+ }
145446
+ treeSettledAtLastRead = treeStillIntervals >= MIN_STILL_INTERVALS && now - treeSince >= stableFor;
145447
+ let pixelsHeld;
145448
+ let localizedThisInterval = false;
145449
+ if (frame !== void 0) {
145450
+ if (previousFrame !== void 0) {
145451
+ comparedAPair = true;
145452
+ const change = comparePixels(previousFrame, frame, maskTopFraction);
145453
+ if (change === "moving") {
145454
+ pixelsEverMoved = true;
145455
+ pixelsHeld = false;
145456
+ } else {
145457
+ pixelsHeld = true;
145458
+ localizedThisInterval = change === "localized";
145459
+ }
145460
+ }
145461
+ previousFrame = frame;
145462
+ }
145463
+ if (!treeHeld || pixelsHeld === false) {
145464
+ bothSince = now;
145465
+ stillIntervals = 0;
145466
+ heldForMs = 0;
145467
+ localizedMotionDuringHold = false;
145468
+ } else if (pixelsHeld === true) {
145469
+ stillIntervals += 1;
145470
+ heldForMs = now - bothSince;
145471
+ if (localizedThisInterval) localizedMotionDuringHold = true;
145472
+ if (stillIntervals >= MIN_STILL_INTERVALS && heldForMs >= stableFor) {
145473
+ return localizedMotionDuringHold ? { ok: true, warning: LOCALIZED_MOTION_WARNING } : { ok: true };
145474
+ }
145475
+ }
145476
+ }
145477
+ }
145478
+ if (env.signal?.aborted) return ABORTED_OUTCOME;
145479
+ const left = deadline - Date.now();
145480
+ if (left < MIN_ROUND_BUDGET_MS) break;
145481
+ if (!await sleepOrAbort(Math.min(IDLE_POLL_MS, left), env.signal)) return ABORTED_OUTCOME;
145482
+ }
145483
+ const unreadable = (underlying) => ({
145484
+ ok: false,
145485
+ indeterminate: true,
145486
+ // The underlying reader reports an instrumentation failure, whose remedy
145487
+ // (relaunch the app) is the wrong repair for the commonest cause of it
145488
+ // here: the app is simply not in the foreground, which reads exactly the
145489
+ // same from the tree source. Name that first so the author checks it
145490
+ // before relaunching anything.
145491
+ reason: `could not read the UI tree while waiting for the screen to settle \u2014 check the app is still in the foreground (a backgrounded app reads the same as an uninstrumented one). Underlying error: ${underlying}`
145492
+ });
145493
+ const degraded = () => ({
145494
+ ok: false,
145495
+ indeterminate: true,
145496
+ reason: `the UI tree read back empty and degraded while waiting for the screen to settle, so the screen was never observed \u2014 this is the reader reporting it could not see the app, not the app rendering nothing` + (blindHint === void 0 ? "" : `. ${blindHint}`)
145497
+ });
145498
+ if (readsSucceeded === 0) {
145499
+ if (treeErrorMessage !== void 0) return unreadable(treeErrorMessage);
145500
+ if (treeReadBlind) return degraded();
145501
+ return {
145502
+ ok: false,
145503
+ indeterminate: true,
145504
+ reason: `the tree source never answered within the step's ${timeoutMs}ms \u2014 raise this step's \`timeout:\` if it is merely slow (a tree read on a busy screen can take seconds), or repair it if it has stopped answering altogether`
145505
+ };
145506
+ }
145507
+ if (treeErrorMessage !== void 0 && darkReads > IDLE_TOLERATED_DARK_READS) {
145508
+ return unreadable(treeErrorMessage);
145509
+ }
145510
+ if (treeReadBlind && darkReads > IDLE_TOLERATED_DARK_READS) {
145511
+ return degraded();
145512
+ }
145513
+ if (lastRead === "timeout" && treeReadHung) {
145514
+ return {
145515
+ ok: false,
145516
+ indeterminate: true,
145517
+ reason: `the UI tree source answered and then stopped: a read given at least ${HUNG_TREE_READ_MS}ms never came back, so the screen could not be observed for the rest of the wait \u2014 check the app is still in the foreground and responding (a wedged app reads the same as a backgrounded one)`
145518
+ };
145519
+ }
145520
+ const blipNote = treeErrorMessage !== void 0 ? ` (the last read that came back failed: ${treeErrorMessage})` : "";
145521
+ if (!sawContent) {
145522
+ return {
145523
+ ok: true,
145524
+ warning: `the UI tree stayed empty for ${timeoutMs}ms \u2014 the screen never rendered content, so there was nothing to settle. If the screen is meant to render accessible content, this is where it did not; if it is a canvas or a video surface, it has none to read. Gate the next action on an element check either way.` + blipNote
145525
+ };
145526
+ }
145527
+ if (contentReads <= MIN_STILL_INTERVALS) {
145528
+ return {
145529
+ ok: true,
145530
+ warning: `the screen came back with content on ${contentReads} read${contentReads === 1 ? "" : "s"} in ${timeoutMs}ms, and a settle takes ${MIN_STILL_INTERVALS + 1} of them spanning ${MIN_STILL_INTERVALS} ${IDLE_POLL_MS}ms polls \u2014 so this step ended without ever being able to tell whether the screen was moving. Raise its \`timeout:\`, and gate the next action on a stable element rather than on stillness.` + blipNote
145531
+ };
145532
+ }
145533
+ if (treeSettledAtLastRead && !pixelsEverMoved && !comparedAPair) {
145534
+ return {
145535
+ ok: true,
145536
+ warning: `settled on the UI tree alone \u2014 this screen could not be screenshotted on enough polls to compare a pair of them, so animation that moves pixels without moving nodes (a push, a fade, a dismissing modal) was not waited out. Follow this with the element check the next step actually needs.`
145537
+ };
145538
+ }
145539
+ if (stillIntervals > 0) {
145540
+ const shortOf = stillIntervals < MIN_STILL_INTERVALS ? `a settle takes ${MIN_STILL_INTERVALS} consecutive ones \u2014 a single agreeing interval can be two samples either side of an animation's turning point` : `the hold asks for ${stableFor}ms of it`;
145541
+ return {
145542
+ ok: true,
145543
+ warning: `the screen was still for the last ${heldForMs}ms of the ${timeoutMs}ms wait, over ${stillIntervals} ${IDLE_POLL_MS}ms interval${stillIntervals === 1 ? "" : "s"} \u2014 but ${shortOf}, so the wait ran out before the settle could be confirmed rather than because the screen never stopped. Raise this step's \`timeout:\`, and gate the next action on a stable element rather than on stillness.` + blipNote
145544
+ };
145545
+ }
145546
+ return {
145547
+ ok: true,
145548
+ warning: `the screen never held still for ${MIN_STILL_INTERVALS} consecutive ${IDLE_POLL_MS}ms intervals${stableFor > 0 ? ` spanning ${stableFor}ms` : ""} within ${timeoutMs}ms, and was moving again on the last one, so this step went ahead without waiting it out. Either something on it never stops (a video, a looping animation, a carousel, live-updating text) or the screen never finished loading. Look at what is moving, and make sure the next action is gated on a stable element rather than on stillness.` + blipNote
145549
+ };
145550
+ }
145134
145551
  function assertReason(condition, selector, expectedText, textMatch, matches2) {
145135
145552
  const sel = describeSelector(selector);
145136
145553
  switch (condition) {
@@ -145156,15 +145573,15 @@ function assertReason(condition, selector, expectedText, textMatch, matches2) {
145156
145573
 
145157
145574
  // ../tool-server/src/tools/flows/flow-visual.ts
145158
145575
  var import_node_crypto8 = require("node:crypto");
145159
- var fs47 = __toESM(require("node:fs/promises"));
145576
+ var fs48 = __toESM(require("node:fs/promises"));
145160
145577
  var os12 = __toESM(require("node:os"));
145161
145578
  var path34 = __toESM(require("node:path"));
145162
- var import_pngjs3 = __toESM(require_png());
145579
+ var import_pngjs4 = __toESM(require_png());
145163
145580
 
145164
145581
  // ../tool-server/src/tools/screenshot-diff/screenshot-diff.ts
145165
145582
  var import_promises11 = __toESM(require("fs/promises"));
145166
145583
  var import_path9 = __toESM(require("path"));
145167
- var import_pngjs2 = __toESM(require_png());
145584
+ var import_pngjs3 = __toESM(require_png());
145168
145585
 
145169
145586
  // ../tool-server/src/tools/screenshot-diff/screenshot-diff-ocr.ts
145170
145587
  var import_child_process8 = require("child_process");
@@ -146709,7 +147126,7 @@ function formatPercentage(value) {
146709
147126
  }
146710
147127
 
146711
147128
  // ../tool-server/src/tools/screenshot-diff/screenshot-diff.ts
146712
- var MAX_RGB_DISTANCE_SQUARED = 255 * 255 * 3;
147129
+ var MAX_RGB_DISTANCE_SQUARED2 = 255 * 255 * 3;
146713
147130
  var DEFAULT_THRESHOLD = 0.1;
146714
147131
  var DEFAULT_IGNORE_TOP_NORMALIZED_Y = 0.06;
146715
147132
  var DEFAULT_REGION_MERGE_DISTANCE = 8;
@@ -146795,7 +147212,7 @@ async function diffPngFiles(options) {
146795
147212
  }
146796
147213
  function resolveDiffSettings(topMask) {
146797
147214
  return {
146798
- thresholdSquared: DEFAULT_THRESHOLD * DEFAULT_THRESHOLD * MAX_RGB_DISTANCE_SQUARED,
147215
+ thresholdSquared: DEFAULT_THRESHOLD * DEFAULT_THRESHOLD * MAX_RGB_DISTANCE_SQUARED2,
146799
147216
  ignoreTopNormalizedY: topMask === "none" ? 0 : DEFAULT_IGNORE_TOP_NORMALIZED_Y,
146800
147217
  joinGapPixels: DEFAULT_REGION_MERGE_DISTANCE,
146801
147218
  contextDiffScale: DEFAULT_CONTEXT_DIFF_SCALE
@@ -146900,7 +147317,7 @@ async function writeDiffArtifacts(params) {
146900
147317
  }
146901
147318
  async function decodePngFile(filePath) {
146902
147319
  const buffer = await import_promises11.default.readFile(filePath);
146903
- const png = import_pngjs2.PNG.sync.read(buffer);
147320
+ const png = import_pngjs3.PNG.sync.read(buffer);
146904
147321
  return {
146905
147322
  width: png.width,
146906
147323
  height: png.height,
@@ -146919,7 +147336,7 @@ async function analyzeScreenshotTextChangesSafely(options) {
146919
147336
  }
146920
147337
  }
146921
147338
  function buildContextDiff(params) {
146922
- const output = new import_pngjs2.PNG({ width: params.current.width, height: params.current.height });
147339
+ const output = new import_pngjs3.PNG({ width: params.current.width, height: params.current.height });
146923
147340
  for (let pixelIndex = 0; pixelIndex < params.mask.length; pixelIndex++) {
146924
147341
  const offset = pixelIndex * 4;
146925
147342
  if (params.mask[pixelIndex]) {
@@ -146944,7 +147361,7 @@ function luminanceFromOffset(data, offset) {
146944
147361
  }
146945
147362
  async function writePngFile(filePath, png) {
146946
147363
  await import_promises11.default.mkdir(import_path9.default.dirname(filePath), { recursive: true });
146947
- await import_promises11.default.writeFile(filePath, import_pngjs2.PNG.sync.write(png));
147364
+ await import_promises11.default.writeFile(filePath, import_pngjs3.PNG.sync.write(png));
146948
147365
  }
146949
147366
  function downscalePng(source, scale) {
146950
147367
  const resized = resizeDecodedPng(
@@ -146952,7 +147369,7 @@ function downscalePng(source, scale) {
146952
147369
  source.width * scale,
146953
147370
  source.height * scale
146954
147371
  );
146955
- const target = new import_pngjs2.PNG({ width: resized.width, height: resized.height });
147372
+ const target = new import_pngjs3.PNG({ width: resized.width, height: resized.height });
146956
147373
  resized.data.copy(target.data);
146957
147374
  return target;
146958
147375
  }
@@ -147217,7 +147634,7 @@ function roundToOne(value) {
147217
147634
  // ../tool-server/src/tools/flows/flow-visual.ts
147218
147635
  var DEFAULT_MAX_MISMATCH = 0.5;
147219
147636
  async function pngDimensions(file2) {
147220
- const fh = await fs47.open(file2, "r");
147637
+ const fh = await fs48.open(file2, "r");
147221
147638
  try {
147222
147639
  const buf = Buffer.alloc(24);
147223
147640
  await fh.read(buf, 0, 24, 0);
@@ -147241,18 +147658,18 @@ function baselineDir(flowsDir, flowName) {
147241
147658
  async function cleanupDiffDir(dir, keep) {
147242
147659
  try {
147243
147660
  if (!keep) {
147244
- await fs47.rm(dir, { recursive: true, force: true });
147661
+ await fs48.rm(dir, { recursive: true, force: true });
147245
147662
  return;
147246
147663
  }
147247
- for (const entry of await fs47.readdir(dir)) {
147664
+ for (const entry of await fs48.readdir(dir)) {
147248
147665
  const entryPath = path34.join(dir, entry);
147249
- if (entryPath !== keep) await fs47.rm(entryPath, { recursive: true, force: true });
147666
+ if (entryPath !== keep) await fs48.rm(entryPath, { recursive: true, force: true });
147250
147667
  }
147251
147668
  } catch {
147252
147669
  }
147253
147670
  }
147254
147671
  async function cropPngFile(src, dest, frame) {
147255
- const png = import_pngjs3.PNG.sync.read(await fs47.readFile(src));
147672
+ const png = import_pngjs4.PNG.sync.read(await fs48.readFile(src));
147256
147673
  const left = Math.max(0, Math.round(frame.x * png.width));
147257
147674
  const top = Math.max(0, Math.round(frame.y * png.height));
147258
147675
  const right = Math.min(png.width, Math.round((frame.x + frame.width) * png.width));
@@ -147260,9 +147677,9 @@ async function cropPngFile(src, dest, frame) {
147260
147677
  const w = right - left;
147261
147678
  const h = bottom - top;
147262
147679
  if (w < 1 || h < 1) return null;
147263
- const out = new import_pngjs3.PNG({ width: w, height: h });
147264
- import_pngjs3.PNG.bitblt(png, out, left, top, w, h, 0, 0);
147265
- await fs47.writeFile(dest, import_pngjs3.PNG.sync.write(out));
147680
+ const out = new import_pngjs4.PNG({ width: w, height: h });
147681
+ import_pngjs4.PNG.bitblt(png, out, left, top, w, h, 0, 0);
147682
+ await fs48.writeFile(dest, import_pngjs4.PNG.sync.write(out));
147266
147683
  return { w, h };
147267
147684
  }
147268
147685
  async function runSnapshot(env, opts) {
@@ -147319,7 +147736,7 @@ async function runSnapshot(env, opts) {
147319
147736
  };
147320
147737
  try {
147321
147738
  if (cropFrame !== void 0) {
147322
- cropDir = await fs47.mkdtemp(path34.join(os12.tmpdir(), "argent-flow-crop-"));
147739
+ cropDir = await fs48.mkdtemp(path34.join(os12.tmpdir(), "argent-flow-crop-"));
147323
147740
  const croppedPath = path34.join(cropDir, key2);
147324
147741
  const cropped = await cropPngFile(shot.image.hostPath, croppedPath, cropFrame);
147325
147742
  if (cropped === null) {
@@ -147333,10 +147750,10 @@ async function runSnapshot(env, opts) {
147333
147750
  }
147334
147751
  currentPath = croppedPath;
147335
147752
  }
147336
- const exists2 = await fs47.access(baselinePath).then(() => true).catch(() => false);
147753
+ const exists2 = await fs48.access(baselinePath).then(() => true).catch(() => false);
147337
147754
  if (opts.updateBaselines) {
147338
- await fs47.mkdir(dir, { recursive: true });
147339
- await fs47.copyFile(currentPath, baselinePath);
147755
+ await fs48.mkdir(dir, { recursive: true });
147756
+ await fs48.copyFile(currentPath, baselinePath);
147340
147757
  const baseline = await store.register(baselinePath, { mimeType: "image/png" });
147341
147758
  return {
147342
147759
  status: "pass",
@@ -147353,7 +147770,7 @@ async function runSnapshot(env, opts) {
147353
147770
  artifacts: { current: await currentArtifact() }
147354
147771
  };
147355
147772
  }
147356
- const outputDir = await fs47.mkdtemp(path34.join(os12.tmpdir(), "argent-flow-diff-"));
147773
+ const outputDir = await fs48.mkdtemp(path34.join(os12.tmpdir(), "argent-flow-diff-"));
147357
147774
  let keepInOutputDir;
147358
147775
  try {
147359
147776
  const result = await diffPngFiles({
@@ -147819,7 +148236,13 @@ reads "inside card inside list", each container's frame inside the next);
147819
148236
  (\`pinch: { on?, scale }\` \u2014 scale > 1 in, < 1 out; screen center when \`on\` is omitted); \`rotate\` is the
147820
148237
  two-finger rotation gesture (\`rotate: { on?, by }\` \u2014 degrees, + clockwise, within \xB13000\xB0; screen center
147821
148238
  when \`on\` is omitted; distinct from the \`rotate\` tool, which changes device orientation); \`await\` waits
147822
- for a UI condition; \`wait\` pauses for a fixed number of milliseconds; \`assert\` checks one now; \`snapshot\`
148239
+ for a UI condition, and additionally takes the one condition that has no selector: \`idle: true\` waits
148240
+ until the screen has content and stops moving in BOTH the UI tree and the rendered pixels (it never
148241
+ fails a run \u2014 a screen that never settles passes carrying a \`warning\`, which is what makes it safe to
148242
+ persist; the one outcome that does stop the run is an \`error\` for a tree source that could not be read
148243
+ at all \u2014 a broken window rather than a verdict about the app, which leaves the run not-ok and skips
148244
+ every later step; it says nothing about WHICH screen settled \u2014 a dropped tap leaves the source screen
148245
+ perfectly idle \u2014 so pair it with the element check that names the destination); \`wait\` pauses for a fixed number of milliseconds; \`assert\` checks one now; \`snapshot\`
147823
148246
  diffs a screenshot \u2014 or, with \`cropOn: <selector>\`, one element's cropped region \u2014 against a stored
147824
148247
  baseline (a missing baseline fails the step \u2014 set updateBaselines to adopt the current screen; a
147825
148248
  cropped element whose size drifted fails on dimensions); \`echo\` annotates; \`run\` executes another flow
@@ -147863,7 +148286,7 @@ returns a notice with the prerequisite instead of running.`,
147863
148286
  );
147864
148287
  const canonicalPath = await canonicalFlowPath2(filePath);
147865
148288
  const flowsDir = path35.dirname(canonicalPath);
147866
- const flow = parseFlow(await fs48.readFile(canonicalPath, "utf8"));
148289
+ const flow = parseFlow(await fs49.readFile(canonicalPath, "utf8"));
147867
148290
  if (viaUpload) assertUploadSelfContained(flow);
147868
148291
  const rootEntry = { canonical: canonicalPath, display: flowName };
147869
148292
  if (flow.executionPrerequisite && !pinnedToChromium(params.device)) {
@@ -148007,7 +148430,7 @@ async function scanLeadingLaunch(flow, stack) {
148007
148430
  const supplied = path35.posix.basename(step.flow);
148008
148431
  const spelling = await classifyOnDiskSpelling(path35.dirname(spelled), supplied);
148009
148432
  if (spelling.state === "case_folded") return null;
148010
- nested = parseFlow(await fs48.readFile(canonical, "utf8"));
148433
+ nested = parseFlow(await fs49.readFile(canonical, "utf8"));
148011
148434
  } catch {
148012
148435
  return null;
148013
148436
  }
@@ -148034,7 +148457,7 @@ function launchTargetPlatform(launch, platform) {
148034
148457
  async function resolveAppPath(specPath, flowDir) {
148035
148458
  const lexical = path35.resolve(flowDir, specPath);
148036
148459
  try {
148037
- return await fs48.realpath(lexical);
148460
+ return await fs49.realpath(lexical);
148038
148461
  } catch {
148039
148462
  return lexical;
148040
148463
  }
@@ -148142,6 +148565,8 @@ function stepTarget(step) {
148142
148565
  case "await":
148143
148566
  case "assert":
148144
148567
  return conditionLabel(step, selectorLabel2);
148568
+ case "idle":
148569
+ return void 0;
148145
148570
  case "when":
148146
148571
  return step.condition.kind === "platform" ? `platform ${step.condition.platform}` : conditionLabel(step.condition, selectorLabel2);
148147
148572
  case "scroll-to": {
@@ -148320,10 +148745,10 @@ async function execWhenStep(state3, step, scope) {
148320
148745
  }
148321
148746
  async function canonicalFlowPath2(p) {
148322
148747
  try {
148323
- return await fs48.realpath(p);
148748
+ return await fs49.realpath(p);
148324
148749
  } catch {
148325
148750
  try {
148326
- return path35.join(await fs48.realpath(path35.dirname(p)), path35.basename(p));
148751
+ return path35.join(await fs49.realpath(path35.dirname(p)), path35.basename(p));
148327
148752
  } catch {
148328
148753
  return p;
148329
148754
  }
@@ -148371,7 +148796,7 @@ async function execRunStep(state3, step, scope) {
148371
148796
  }
148372
148797
  let fragment;
148373
148798
  try {
148374
- fragment = parseFlow(await fs48.readFile(canonical, "utf8"));
148799
+ fragment = parseFlow(await fs49.readFile(canonical, "utf8"));
148375
148800
  } catch (err) {
148376
148801
  return fail(`could not load fragment "${target}": ${errMsg2(err)}`);
148377
148802
  }
@@ -148411,13 +148836,22 @@ async function execLeafStep(state3, step, index, scope) {
148411
148836
  case "type":
148412
148837
  case "await":
148413
148838
  case "assert":
148839
+ case "idle":
148414
148840
  case "scroll-to":
148415
148841
  case "pinch":
148416
148842
  case "rotate": {
148417
148843
  try {
148418
148844
  const r = await runDirective(deviceEnv(state3), step);
148419
148845
  if (r.aborted) return { ...base, status: "skip", reason: r.reason };
148420
- return { ...base, status: r.ok ? "pass" : "fail", reason: r.reason };
148846
+ if (!r.ok && r.indeterminate && step.kind === "idle") {
148847
+ return { ...base, status: "error", reason: r.reason };
148848
+ }
148849
+ return {
148850
+ ...base,
148851
+ status: r.ok ? "pass" : "fail",
148852
+ reason: r.reason,
148853
+ ...r.warning !== void 0 ? { warning: r.warning } : {}
148854
+ };
148421
148855
  } catch (err) {
148422
148856
  return { ...base, status: "error", reason: errMsg2(err) };
148423
148857
  }
@@ -148618,7 +149052,7 @@ async function resolveFlowSource(params, fileInput, flowPathInput) {
148618
149052
 
148619
149053
  // ../tool-server/src/tools/flows/flow-read-prerequisite.ts
148620
149054
  init_zod();
148621
- var fs49 = __toESM(require("node:fs/promises"));
149055
+ var fs50 = __toESM(require("node:fs/promises"));
148622
149056
  init_src();
148623
149057
  var zodSchema66 = external_exports.object({
148624
149058
  name: external_exports.string().optional().describe(
@@ -148688,7 +149122,7 @@ Fails if the flow file does not exist.`,
148688
149122
  ctx?.fileInputs?.flow_file,
148689
149123
  ctx?.fileInputs?.flow_path
148690
149124
  );
148691
- const flow = parseFlow(await fs49.readFile(filePath, "utf8"));
149125
+ const flow = parseFlow(await fs50.readFile(filePath, "utf8"));
148692
149126
  return {
148693
149127
  flow: flowName,
148694
149128
  executionPrerequisite: flow.executionPrerequisite
@@ -149036,13 +149470,13 @@ Fails if the workspacePath is not an absolute path or the directory cannot be ac
149036
149470
 
149037
149471
  // ../tool-server/src/tools/system/update-argent.ts
149038
149472
  var import_node_child_process29 = require("node:child_process");
149039
- var fs50 = __toESM(require("node:fs"));
149473
+ var fs51 = __toESM(require("node:fs"));
149040
149474
  var path36 = __toESM(require("node:path"));
149041
149475
  init_zod();
149042
149476
  function resolveCliEntry() {
149043
149477
  try {
149044
149478
  const entry = path36.join(__dirname, "cli.js");
149045
- return fs50.existsSync(entry) ? entry : null;
149479
+ return fs51.existsSync(entry) ? entry : null;
149046
149480
  } catch {
149047
149481
  return null;
149048
149482
  }
@@ -149056,14 +149490,14 @@ function classifyRunningInstall() {
149056
149490
  }
149057
149491
  let runningRoot;
149058
149492
  try {
149059
- runningRoot = fs50.realpathSync(path36.dirname(__dirname));
149493
+ runningRoot = fs51.realpathSync(path36.dirname(__dirname));
149060
149494
  } catch {
149061
149495
  return { kind: "global", projectRoot: null };
149062
149496
  }
149063
149497
  let dir = process.cwd();
149064
149498
  while (true) {
149065
149499
  try {
149066
- const nmReal = fs50.realpathSync(path36.join(dir, "node_modules"));
149500
+ const nmReal = fs51.realpathSync(path36.join(dir, "node_modules"));
149067
149501
  if (runningRoot === nmReal || runningRoot.startsWith(nmReal + path36.sep)) {
149068
149502
  return { kind: "local", projectRoot: dir };
149069
149503
  }
@@ -149078,14 +149512,14 @@ function classifyRunningInstall() {
149078
149512
  function findDeclaringProjectRoot(startDir) {
149079
149513
  let dir;
149080
149514
  try {
149081
- dir = fs50.realpathSync(startDir);
149515
+ dir = fs51.realpathSync(startDir);
149082
149516
  } catch {
149083
149517
  return null;
149084
149518
  }
149085
149519
  while (true) {
149086
- if (fs50.existsSync(path36.join(dir, ".argent", "install.json"))) return dir;
149520
+ if (fs51.existsSync(path36.join(dir, ".argent", "install.json"))) return dir;
149087
149521
  try {
149088
- const manifest = JSON.parse(fs50.readFileSync(path36.join(dir, "package.json"), "utf8"));
149522
+ const manifest = JSON.parse(fs51.readFileSync(path36.join(dir, "package.json"), "utf8"));
149089
149523
  if (manifest.devDependencies?.[PACKAGE_NAME2] || manifest.dependencies?.[PACKAGE_NAME2] || manifest.optionalDependencies?.[PACKAGE_NAME2]) {
149090
149524
  return dir;
149091
149525
  }
@@ -149124,7 +149558,7 @@ var updateArgentTool = {
149124
149558
  let projectRoot = null;
149125
149559
  let effectiveTarget = resolved;
149126
149560
  if (resolved === "local" || resolved === "both") {
149127
- const recordedRoot = running.projectRoot && fs50.existsSync(running.projectRoot) ? running.projectRoot : null;
149561
+ const recordedRoot = running.projectRoot && fs51.existsSync(running.projectRoot) ? running.projectRoot : null;
149128
149562
  projectRoot = recordedRoot ?? (running.kind === "local" ? findDeclaringProjectRoot(process.cwd()) : null);
149129
149563
  if (!projectRoot) {
149130
149564
  if (resolved === "local") {
@@ -149166,7 +149600,7 @@ var updateArgentTool = {
149166
149600
  if (targetsOnlyRunningInstall && installableVersion) {
149167
149601
  updateArgs.push("--version", installableVersion);
149168
149602
  }
149169
- const spawnRoot = projectRoot ?? (running.projectRoot && fs50.existsSync(running.projectRoot) ? running.projectRoot : null);
149603
+ const spawnRoot = projectRoot ?? (running.projectRoot && fs51.existsSync(running.projectRoot) ? running.projectRoot : null);
149170
149604
  if (spawnRoot) updateArgs.push("--project-root", spawnRoot);
149171
149605
  const cmd = cliEntry ? process.execPath : "argent";
149172
149606
  const args = cliEntry ? [cliEntry, ...updateArgs] : updateArgs;
@@ -150086,7 +150520,7 @@ function probeArgentToolServer(host, port, timeoutMs = 500) {
150086
150520
  }
150087
150521
 
150088
150522
  // ../tool-server/src/utils/simulator-watcher.ts
150089
- var fs52 = __toESM(require("node:fs"));
150523
+ var fs53 = __toESM(require("node:fs"));
150090
150524
  var import_node_child_process30 = require("node:child_process");
150091
150525
  var import_node_util21 = require("node:util");
150092
150526
  var execFileAsync23 = (0, import_node_util21.promisify)(import_node_child_process30.execFile);
@@ -150113,7 +150547,7 @@ async function getBootedUdidsInSet(deviceSet) {
150113
150547
  async function getBootedUdids() {
150114
150548
  const sets = [
150115
150549
  null,
150116
- ...configuredAdditionalDeviceSets().filter((p) => fs52.existsSync(p))
150550
+ ...configuredAdditionalDeviceSets().filter((p) => fs53.existsSync(p))
150117
150551
  ];
150118
150552
  const perSet = await Promise.all(sets.map(getBootedUdidsInSet));
150119
150553
  return new Set(perSet.flatMap((s) => [...s]));
@@ -150166,7 +150600,7 @@ function startSimulatorWatcher(registry2) {
150166
150600
 
150167
150601
  // ../tool-server/src/utils/preview-window.ts
150168
150602
  var import_node_child_process31 = require("node:child_process");
150169
- var fs53 = __toESM(require("node:fs"));
150603
+ var fs54 = __toESM(require("node:fs"));
150170
150604
  var os14 = __toESM(require("node:os"));
150171
150605
  var path38 = __toESM(require("node:path"));
150172
150606
  function ensureLensAppBundle(electronBin) {
@@ -150183,18 +150617,18 @@ function ensureLensAppBundle(electronBin) {
150183
150617
  );
150184
150618
  const wrapperExec = path38.join(wrapperContents, "MacOS", "Electron");
150185
150619
  try {
150186
- if (fs53.realpathSync(wrapperExec) === fs53.realpathSync(electronBin)) return wrapperExec;
150620
+ if (fs54.realpathSync(wrapperExec) === fs54.realpathSync(electronBin)) return wrapperExec;
150187
150621
  } catch {
150188
150622
  }
150189
- fs53.rmSync(path38.dirname(wrapperContents), { recursive: true, force: true });
150190
- fs53.mkdirSync(path38.join(wrapperContents, "MacOS"), { recursive: true });
150191
- fs53.symlinkSync(path38.join(realContents, "Frameworks"), path38.join(wrapperContents, "Frameworks"));
150192
- fs53.symlinkSync(path38.join(realContents, "Resources"), path38.join(wrapperContents, "Resources"));
150193
- fs53.symlinkSync(electronBin, wrapperExec);
150623
+ fs54.rmSync(path38.dirname(wrapperContents), { recursive: true, force: true });
150624
+ fs54.mkdirSync(path38.join(wrapperContents, "MacOS"), { recursive: true });
150625
+ fs54.symlinkSync(path38.join(realContents, "Frameworks"), path38.join(wrapperContents, "Frameworks"));
150626
+ fs54.symlinkSync(path38.join(realContents, "Resources"), path38.join(wrapperContents, "Resources"));
150627
+ fs54.symlinkSync(electronBin, wrapperExec);
150194
150628
  const pkgInfo = path38.join(realContents, "PkgInfo");
150195
- if (fs53.existsSync(pkgInfo)) fs53.copyFileSync(pkgInfo, path38.join(wrapperContents, "PkgInfo"));
150629
+ if (fs54.existsSync(pkgInfo)) fs54.copyFileSync(pkgInfo, path38.join(wrapperContents, "PkgInfo"));
150196
150630
  const plist = path38.join(wrapperContents, "Info.plist");
150197
- fs53.copyFileSync(path38.join(realContents, "Info.plist"), plist);
150631
+ fs54.copyFileSync(path38.join(realContents, "Info.plist"), plist);
150198
150632
  const setPlist = (entry, value) => {
150199
150633
  try {
150200
150634
  (0, import_node_child_process31.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
@@ -150236,7 +150670,7 @@ function createPreviewWindowManager(opts = {}) {
150236
150670
  const resolveMainScript = () => {
150237
150671
  if (opts.mainScript) return opts.mainScript;
150238
150672
  const bundled = path38.join(__dirname, "preview-window", "main.cjs");
150239
- if (fs53.existsSync(bundled)) return bundled;
150673
+ if (fs54.existsSync(bundled)) return bundled;
150240
150674
  return require.resolve("@argent/preview-window/dist/main.js");
150241
150675
  };
150242
150676
  const isAlive = (c) => c !== null && c.exitCode === null && !c.killed;