@swmansion/argent 0.20.1-next.12 → 0.20.1-next.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
Binary file
Binary file
package/dist/cli-cmds.mjs CHANGED
@@ -1802,6 +1802,10 @@ var FLAG_REGISTRY = [
1802
1802
  name: "tool-server-event-log",
1803
1803
  description: "Write structured tool-server lifecycle events to a JSONL file."
1804
1804
  },
1805
+ {
1806
+ name: "microinteractions",
1807
+ description: "Amplify device actions with matching animations of the host window, so what happens on the guest is also visible on the desktop. Purely cosmetic, macOS only, and never affects whether the underlying action succeeds. Off by default."
1808
+ },
1805
1809
  {
1806
1810
  name: "video-watermark",
1807
1811
  description: "Overlay the argent corner watermark on recorded screen videos. On by default; turn it off with `argent disable video-watermark`.",
@@ -85071,7 +85071,7 @@ var require_log = __commonJS({
85071
85071
  if (logLevel === "debug")
85072
85072
  console.log(...messages);
85073
85073
  }
85074
- function warn(logLevel, warning) {
85074
+ function warn2(logLevel, warning) {
85075
85075
  if (logLevel === "debug" || logLevel === "warn") {
85076
85076
  if (typeof node_process.emitWarning === "function")
85077
85077
  node_process.emitWarning(warning);
@@ -85080,7 +85080,7 @@ var require_log = __commonJS({
85080
85080
  }
85081
85081
  }
85082
85082
  exports2.debug = debug;
85083
- exports2.warn = warn;
85083
+ exports2.warn = warn2;
85084
85084
  }
85085
85085
  });
85086
85086
 
@@ -90786,6 +90786,10 @@ var FLAG_REGISTRY = [
90786
90786
  name: "tool-server-event-log",
90787
90787
  description: "Write structured tool-server lifecycle events to a JSONL file."
90788
90788
  },
90789
+ {
90790
+ name: "microinteractions",
90791
+ description: "Amplify device actions with matching animations of the host window, so what happens on the guest is also visible on the desktop. Purely cosmetic, macOS only, and never affects whether the underlying action succeeds. Off by default."
90792
+ },
90789
90793
  {
90790
90794
  name: "video-watermark",
90791
90795
  description: "Overlay the argent corner watermark on recorded screen videos. On by default; turn it off with `argent disable video-watermark`.",
@@ -99605,9 +99609,9 @@ ${debugInfo}`);
99605
99609
  this.#dispose.length = 0;
99606
99610
  if (this.#async.length > 0) {
99607
99611
  try {
99608
- let warn;
99612
+ let warn2;
99609
99613
  const timeout = new Promise((resolve11) => {
99610
- warn = setTimeout(() => {
99614
+ warn2 = setTimeout(() => {
99611
99615
  if (DEV) {
99612
99616
  console.warn("spawn is still running after 5s; continuing anyway", this.#stack);
99613
99617
  }
@@ -99615,8 +99619,8 @@ ${debugInfo}`);
99615
99619
  }, 5e3);
99616
99620
  });
99617
99621
  await Promise.race([Promise.all(this.#async), timeout]);
99618
- if (warn)
99619
- clearTimeout(warn);
99622
+ if (warn2)
99623
+ clearTimeout(warn2);
99620
99624
  this.#async.length = 0;
99621
99625
  } catch (error52) {
99622
99626
  console.error("async effect error", error52);
@@ -119223,6 +119227,18 @@ function readMb(config2, key2) {
119223
119227
  return (m[2] || "M").toLowerCase().startsWith("g") ? n * 1024 : n;
119224
119228
  }
119225
119229
 
119230
+ // ../tool-server/src/utils/no-window-env.ts
119231
+ var TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes"]);
119232
+ function truthyEnv(name) {
119233
+ return TRUTHY.has((process.env[name] ?? "").trim().toLowerCase());
119234
+ }
119235
+ function iosHeadlessFromEnv() {
119236
+ return truthyEnv("ARGENT_SIMULATOR_NO_WINDOW");
119237
+ }
119238
+ function androidHeadlessFromEnv() {
119239
+ return truthyEnv("ARGENT_EMULATOR_NO_WINDOW");
119240
+ }
119241
+
119226
119242
  // ../tool-server/src/utils/vega-vvd.ts
119227
119243
  init_src();
119228
119244
  init_adb();
@@ -119765,14 +119781,6 @@ function selectGpuMode() {
119765
119781
  }
119766
119782
  return process.platform === "linux" ? "swiftshader" : "auto";
119767
119783
  }
119768
- function selectExtraEmulatorArgs() {
119769
- const trimmed = (process.env.ARGENT_EMULATOR_NO_WINDOW ?? "").trim().toLowerCase();
119770
- return ["1", "true", "yes"].includes(trimmed) ? ["-no-window"] : [];
119771
- }
119772
- function iosHeadlessFromEnv() {
119773
- const trimmed = (process.env.ARGENT_SIMULATOR_NO_WINDOW ?? "").trim().toLowerCase();
119774
- return ["1", "true", "yes"].includes(trimmed);
119775
- }
119776
119784
  var BOOT_POLL_INTERVALS_MS = {
119777
119785
  serialByAvd: 1500,
119778
119786
  // findSerialByAvdName: re-scan when >1 new emulator appeared
@@ -120156,7 +120164,7 @@ async function bootAndroidImpl(params) {
120156
120164
  await ensureDep("adb");
120157
120165
  await ensureDep("emulator");
120158
120166
  const gpuMode = selectGpuMode();
120159
- const extraEmulatorArgs = selectExtraEmulatorArgs();
120167
+ const extraEmulatorArgs = androidHeadlessFromEnv() ? ["-no-window"] : [];
120160
120168
  for (const msg of linuxBootDiagnostics(params.avdName) ?? []) {
120161
120169
  console.warn(`[boot-device:linux] ${msg}`);
120162
120170
  }
@@ -123335,10 +123343,211 @@ var shakeZodSchema = external_exports.object({
123335
123343
  });
123336
123344
 
123337
123345
  // ../tool-server/src/tools/shake/platforms/ios.ts
123338
- var import_node_child_process26 = require("node:child_process");
123346
+ var import_node_child_process27 = require("node:child_process");
123339
123347
  var import_node_util20 = require("node:util");
123340
123348
  init_src();
123341
- var execFileAsync20 = (0, import_node_util20.promisify)(import_node_child_process26.execFile);
123349
+
123350
+ // ../tool-server/src/utils/window-shake.ts
123351
+ var import_node_child_process26 = require("node:child_process");
123352
+ var MICROINTERACTIONS_FLAG = "microinteractions";
123353
+ var AMPLITUDE = 22;
123354
+ var STEPS = 60;
123355
+ var OSASCRIPT_TIMEOUT_MS = 5e3;
123356
+ var ORIGIN_MARKER = "ARGENT_WINDOW_ORIGIN:";
123357
+ function warn(detail) {
123358
+ process.stderr.write(`[shake:window] skipped the window animation: ${detail}
123359
+ `);
123360
+ }
123361
+ function asStringLiteral(value) {
123362
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
123363
+ }
123364
+ function titleMatchLookup(procNamesExpr, needles) {
123365
+ return `
123366
+ set win to missing value
123367
+ set needles to {${needles.map(asStringLiteral).join(", ")}}
123368
+ set procNames to ${procNamesExpr}
123369
+ repeat with procRef in procNames
123370
+ set procName to contents of procRef
123371
+ set winTitles to {}
123372
+ try
123373
+ tell process procName to set winTitles to name of every window
123374
+ end try
123375
+ repeat with idx from 1 to (count of winTitles)
123376
+ set winTitle to item idx of winTitles
123377
+ -- A GUI app can carry an unnamed helper window alongside the real one.
123378
+ if winTitle is not missing value then
123379
+ repeat with needle in needles
123380
+ if winTitle contains (contents of needle) then
123381
+ set win to window idx of process procName
123382
+ exit repeat
123383
+ end if
123384
+ end repeat
123385
+ end if
123386
+ if win is not missing value then exit repeat
123387
+ end repeat
123388
+ if win is not missing value then exit repeat
123389
+ end repeat`;
123390
+ }
123391
+ function windowLookup(needles) {
123392
+ if (needles.length === 0) {
123393
+ return `
123394
+ set win to missing value
123395
+ repeat with procRef in {"Simulator", "Device Hub"}
123396
+ -- A repeat variable is a reference into the list and "process <ref>"
123397
+ -- will not coerce one, so without "contents of" the lookup misses.
123398
+ set procName to contents of procRef
123399
+ if exists (process procName) then
123400
+ tell process procName
123401
+ if (count of windows) > 0 then set win to window 1
123402
+ end tell
123403
+ end if
123404
+ if win is not missing value then exit repeat
123405
+ end repeat`;
123406
+ }
123407
+ return titleMatchLookup(
123408
+ `name of every process whose name is "Simulator" or name is "Device Hub"`,
123409
+ needles
123410
+ );
123411
+ }
123412
+ var WOBBLE_OFFSETS = Array.from(
123413
+ { length: STEPS + 1 },
123414
+ (_, i) => {
123415
+ const t = i / STEPS;
123416
+ const decay = Math.exp(-4 * t);
123417
+ const phase = 2 * Math.PI * 3.5 * t;
123418
+ return [
123419
+ Math.round(AMPLITUDE * decay * Math.sin(phase)),
123420
+ Math.round(AMPLITUDE / 3 * decay * Math.sin(2 * phase))
123421
+ ];
123422
+ }
123423
+ );
123424
+ var OFFSETS_LITERAL = WOBBLE_OFFSETS.map(([dx, dy]) => `{${dx}, ${dy}}`).join(", ");
123425
+ function animationScript(needles) {
123426
+ return `on run
123427
+ tell application "System Events"${windowLookup(needles)}
123428
+ if win is missing value then error "no matching window"
123429
+ set origin to position of win
123430
+ set ox to item 1 of origin
123431
+ set oy to item 2 of origin
123432
+ log "${ORIGIN_MARKER}" & ox & "," & oy
123433
+
123434
+ set offsets to {${OFFSETS_LITERAL}}
123435
+ repeat with pair in offsets
123436
+ set position of win to {ox + (item 1 of pair), oy + (item 2 of pair)}
123437
+ end repeat
123438
+
123439
+ set position of win to {ox, oy}
123440
+ delay 0.05
123441
+ set position of win to {ox, oy}
123442
+ end tell
123443
+ end run
123444
+ `;
123445
+ }
123446
+ function restoreScript(needles, ox, oy) {
123447
+ return `on run
123448
+ tell application "System Events"${windowLookup(needles)}
123449
+ if win is missing value then error "no matching window"
123450
+ set position of win to {${ox}, ${oy}}
123451
+ end tell
123452
+ end run
123453
+ `;
123454
+ }
123455
+ function runOsascript(script) {
123456
+ return new Promise((resolve11, reject) => {
123457
+ const child = (0, import_node_child_process26.execFile)(
123458
+ "/usr/bin/osascript",
123459
+ ["-"],
123460
+ { timeout: OSASCRIPT_TIMEOUT_MS },
123461
+ (err, _stdout, stderr) => {
123462
+ if (err) {
123463
+ const raw = String(stderr ?? "");
123464
+ const detail = raw.split("\n").filter((line) => !line.includes(ORIGIN_MARKER)).join("\n").trim() || err.message || "osascript failed";
123465
+ const failure = new Error(detail);
123466
+ failure.wasKilled = Boolean(
123467
+ err.killed || err.signal
123468
+ );
123469
+ failure.rawStderr = raw;
123470
+ reject(failure);
123471
+ return;
123472
+ }
123473
+ resolve11();
123474
+ }
123475
+ );
123476
+ child.on("error", (err) => reject(err));
123477
+ child.stdin?.on("error", () => {
123478
+ });
123479
+ child.stdin?.end(script);
123480
+ });
123481
+ }
123482
+ async function restoreOriginAfterKill(needles, rawStderr) {
123483
+ const match = rawStderr.match(new RegExp(`${ORIGIN_MARKER}\\s*(-?\\d+)\\s*,\\s*(-?\\d+)`));
123484
+ if (!match) return;
123485
+ try {
123486
+ await runOsascript(restoreScript(needles, Number(match[1]), Number(match[2])));
123487
+ } catch {
123488
+ }
123489
+ }
123490
+ async function prepareHostWindowShake(target) {
123491
+ const inert = { begin: () => {
123492
+ }, settle: () => Promise.resolve() };
123493
+ try {
123494
+ if (!isFeatureEnabled(MICROINTERACTIONS_FLAG)) return inert;
123495
+ if (process.platform !== "darwin") return inert;
123496
+ if (iosHeadlessFromEnv()) return inert;
123497
+ let deviceSet = null;
123498
+ try {
123499
+ deviceSet = await deviceSetForUdid(target.udid);
123500
+ } catch {
123501
+ }
123502
+ if (deviceSet !== null) return inert;
123503
+ const needles = target.name ? [target.name] : [];
123504
+ const script = animationScript(needles);
123505
+ let inFlight = null;
123506
+ let dead = false;
123507
+ let warned2 = false;
123508
+ const warnOnce = (detail) => {
123509
+ if (warned2) return;
123510
+ warned2 = true;
123511
+ warn(detail);
123512
+ };
123513
+ return {
123514
+ begin() {
123515
+ if (dead || inFlight !== null) return;
123516
+ let run2;
123517
+ try {
123518
+ run2 = runOsascript(script);
123519
+ } catch (err) {
123520
+ dead = true;
123521
+ warnOnce(err instanceof Error ? err.message : String(err));
123522
+ return;
123523
+ }
123524
+ inFlight = run2.then(
123525
+ () => {
123526
+ inFlight = null;
123527
+ },
123528
+ async (err) => {
123529
+ dead = true;
123530
+ const failure = err;
123531
+ if (failure.wasKilled && typeof failure.rawStderr === "string") {
123532
+ await restoreOriginAfterKill(needles, failure.rawStderr);
123533
+ }
123534
+ warnOnce(err instanceof Error ? err.message : String(err));
123535
+ inFlight = null;
123536
+ }
123537
+ );
123538
+ },
123539
+ settle() {
123540
+ return inFlight ?? Promise.resolve();
123541
+ }
123542
+ };
123543
+ } catch (err) {
123544
+ warn(err instanceof Error ? err.message : String(err));
123545
+ return inert;
123546
+ }
123547
+ }
123548
+
123549
+ // ../tool-server/src/tools/shake/platforms/ios.ts
123550
+ var execFileAsync20 = (0, import_node_util20.promisify)(import_node_child_process27.execFile);
123342
123551
  var SHAKE_NOTIFICATION = "com.apple.UIKit.SimulatorShake";
123343
123552
  var SHAKE_INTERVAL_MS = 400;
123344
123553
  var sleep10 = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -123374,8 +123583,10 @@ var iosImpl4 = {
123374
123583
  const count2 = params.count ?? 1;
123375
123584
  if (await isTvOsSimulator(udid)) rejectTv("shake", device);
123376
123585
  const args = await simctlArgsForUdid(udid, ["spawn", udid, ...NOTIFYUTIL_ARGV]);
123586
+ const shaker = await prepareHostWindowShake({ kind: "ios", udid, name: device.name });
123377
123587
  for (let i = 0; i < count2; i++) {
123378
123588
  if (i > 0) await sleep10(SHAKE_INTERVAL_MS);
123589
+ shaker.begin();
123379
123590
  try {
123380
123591
  await execFileAsync20("xcrun", args, { timeout: 15e3 });
123381
123592
  } catch (err) {
@@ -123383,6 +123594,7 @@ var iosImpl4 = {
123383
123594
  throw shakeFailure(udid, error52.message, error52);
123384
123595
  }
123385
123596
  }
123597
+ await shaker.settle();
123386
123598
  return { shaken: true, count: count2 };
123387
123599
  }
123388
123600
  };
@@ -142770,7 +142982,7 @@ Returns { stopped } - the URNs of the services that were actually live and got s
142770
142982
 
142771
142983
  // ../tool-server/src/tools/simulator/stop-metro.ts
142772
142984
  init_zod();
142773
- var import_node_child_process27 = require("node:child_process");
142985
+ var import_node_child_process28 = require("node:child_process");
142774
142986
  function parseNetstatListeningPids(netstatOutput, port) {
142775
142987
  const pids = /* @__PURE__ */ new Set();
142776
142988
  for (const line of netstatOutput.split(/\r?\n/)) {
@@ -142786,7 +142998,7 @@ function parseNetstatListeningPids(netstatOutput, port) {
142786
142998
  }
142787
142999
  function listeningPids(port) {
142788
143000
  if (process.platform === "win32") {
142789
- const output2 = (0, import_node_child_process27.execFileSync)("netstat", ["-ano"], {
143001
+ const output2 = (0, import_node_child_process28.execFileSync)("netstat", ["-ano"], {
142790
143002
  encoding: "utf-8",
142791
143003
  timeout: 5e3,
142792
143004
  // `netstat -ano` dumps every socket on the host; a busy box easily
@@ -142796,7 +143008,7 @@ function listeningPids(port) {
142796
143008
  });
142797
143009
  return parseNetstatListeningPids(output2, port);
142798
143010
  }
142799
- const output = (0, import_node_child_process27.execFileSync)("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"], {
143011
+ const output = (0, import_node_child_process28.execFileSync)("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"], {
142800
143012
  encoding: "utf-8",
142801
143013
  timeout: 5e3
142802
143014
  }).trim();
@@ -148797,10 +149009,10 @@ async function runSnapshot(env, opts) {
148797
149009
  }
148798
149010
 
148799
149011
  // ../tool-server/src/utils/status-bar.ts
148800
- var import_node_child_process28 = require("node:child_process");
149012
+ var import_node_child_process29 = require("node:child_process");
148801
149013
  var import_node_util21 = require("node:util");
148802
149014
  init_adb();
148803
- var execFileAsync23 = (0, import_node_util21.promisify)(import_node_child_process28.execFile);
149015
+ var execFileAsync23 = (0, import_node_util21.promisify)(import_node_child_process29.execFile);
148804
149016
  var DEMO_BROADCAST = "am broadcast -a com.android.systemui.demo";
148805
149017
  async function pinStatusBar(device) {
148806
149018
  try {
@@ -150152,7 +150364,7 @@ init_zod();
150152
150364
  // ../tool-server/src/utils/workspace-reader.ts
150153
150365
  var import_promises12 = require("node:fs/promises");
150154
150366
  var import_node_path21 = require("node:path");
150155
- var import_node_child_process29 = require("node:child_process");
150367
+ var import_node_child_process30 = require("node:child_process");
150156
150368
  var import_dotenv2 = __toESM(require_main());
150157
150369
  async function exists(path40) {
150158
150370
  try {
@@ -150196,7 +150408,7 @@ async function listDir(path40) {
150196
150408
  var COMMAND_TIMEOUT_MS = 3e3;
150197
150409
  function runVersionCommand(cmd, args, cwd) {
150198
150410
  return new Promise((resolve11) => {
150199
- const child = (0, import_node_child_process29.execFile)(cmd, args, { cwd, timeout: COMMAND_TIMEOUT_MS }, (err, stdout) => {
150411
+ const child = (0, import_node_child_process30.execFile)(cmd, args, { cwd, timeout: COMMAND_TIMEOUT_MS }, (err, stdout) => {
150200
150412
  if (err) {
150201
150413
  resolve11(null);
150202
150414
  return;
@@ -150485,7 +150697,7 @@ Fails if the workspacePath is not an absolute path or the directory cannot be ac
150485
150697
  };
150486
150698
 
150487
150699
  // ../tool-server/src/tools/system/update-argent.ts
150488
- var import_node_child_process30 = require("node:child_process");
150700
+ var import_node_child_process31 = require("node:child_process");
150489
150701
  var fs51 = __toESM(require("node:fs"));
150490
150702
  var path36 = __toESM(require("node:path"));
150491
150703
  init_zod();
@@ -150620,7 +150832,7 @@ var updateArgentTool = {
150620
150832
  if (spawnRoot) updateArgs.push("--project-root", spawnRoot);
150621
150833
  const cmd = cliEntry ? process.execPath : "argent";
150622
150834
  const args = cliEntry ? [cliEntry, ...updateArgs] : updateArgs;
150623
- const child = (0, import_node_child_process30.spawn)(cmd, args, {
150835
+ const child = (0, import_node_child_process31.spawn)(cmd, args, {
150624
150836
  detached: true,
150625
150837
  stdio: "ignore",
150626
150838
  env: { ...process.env, ARGENT_UPDATE_TRIGGER: "mcp_update" }
@@ -151546,9 +151758,9 @@ function probeArgentToolServer(host, port, timeoutMs = 500) {
151546
151758
 
151547
151759
  // ../tool-server/src/utils/simulator-watcher.ts
151548
151760
  var fs53 = __toESM(require("node:fs"));
151549
- var import_node_child_process31 = require("node:child_process");
151761
+ var import_node_child_process32 = require("node:child_process");
151550
151762
  var import_node_util22 = require("node:util");
151551
- var execFileAsync24 = (0, import_node_util22.promisify)(import_node_child_process31.execFile);
151763
+ var execFileAsync24 = (0, import_node_util22.promisify)(import_node_child_process32.execFile);
151552
151764
  var POLL_INTERVAL_MS2 = 1e4;
151553
151765
  async function getBootedUdidsInSet(deviceSet) {
151554
151766
  const { stdout } = await execFileAsync24("xcrun", [
@@ -151624,7 +151836,7 @@ function startSimulatorWatcher(registry2) {
151624
151836
  }
151625
151837
 
151626
151838
  // ../tool-server/src/utils/preview-window.ts
151627
- var import_node_child_process32 = require("node:child_process");
151839
+ var import_node_child_process33 = require("node:child_process");
151628
151840
  var fs54 = __toESM(require("node:fs"));
151629
151841
  var os14 = __toESM(require("node:os"));
151630
151842
  var path38 = __toESM(require("node:path"));
@@ -151656,10 +151868,10 @@ function ensureLensAppBundle(electronBin) {
151656
151868
  fs54.copyFileSync(path38.join(realContents, "Info.plist"), plist);
151657
151869
  const setPlist = (entry, value) => {
151658
151870
  try {
151659
- (0, import_node_child_process32.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
151871
+ (0, import_node_child_process33.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
151660
151872
  } catch {
151661
151873
  try {
151662
- (0, import_node_child_process32.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Add :${entry} string ${value}`, plist]);
151874
+ (0, import_node_child_process33.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Add :${entry} string ${value}`, plist]);
151663
151875
  } catch {
151664
151876
  }
151665
151877
  }
@@ -151718,7 +151930,7 @@ function createPreviewWindowManager(opts = {}) {
151718
151930
  const wrapperBin = ensureLensAppBundle(electronBin);
151719
151931
  const launchBin = wrapperBin ?? electronBin;
151720
151932
  const launchArgs = wrapperBin ? ["--no-sandbox", mainScript] : [mainScript];
151721
- const next = (0, import_node_child_process32.spawn)(launchBin, launchArgs, {
151933
+ const next = (0, import_node_child_process33.spawn)(launchBin, launchArgs, {
151722
151934
  // Strip ELECTRON_RUN_AS_NODE so the child boots as a GUI Electron app, not
151723
151935
  // a bare Node runtime (see electronGuiChildEnv). An Electron-based MCP
151724
151936
  // host puts it in our env, and inheriting it makes main.cjs crash at
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.20.1-next.12",
3
+ "version": "0.20.1-next.13",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator and Android Emulator control",
6
6
  "license": "Apache-2.0",