@swmansion/argent 0.30.2-next.9 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/cli-cmds.mjs CHANGED
@@ -9085,6 +9085,7 @@ function spawnToolsServer(paths, port, options = {}) {
9085
9085
  stdio: ["ignore", "pipe", logFd],
9086
9086
  env: buildToolsServerEnv(paths, port, process.env, options)
9087
9087
  });
9088
+ fs.closeSync(logFd);
9088
9089
  child.unref();
9089
9090
  const pid = child.pid;
9090
9091
  if (!pid) {
@@ -9854,6 +9855,7 @@ var FAILURE_CODES = {
9854
9855
  REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
9855
9856
  REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
9856
9857
  REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
9858
+ REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
9857
9859
  REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
9858
9860
  REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
9859
9861
  NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
@@ -30809,8 +30811,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
30809
30811
  if (msg.event === "progress") {
30810
30812
  progress++;
30811
30813
  onProgress(msg.data);
30812
- } else if (msg.event === "result") final = { data: msg.data, note: msg.note };
30813
- else if (msg.event === "error") {
30814
+ } else if (msg.event === "result") {
30815
+ final = {
30816
+ data: msg.data,
30817
+ note: msg.note,
30818
+ ...msg.profiling === true ? { profiling: true } : {}
30819
+ };
30820
+ } else if (msg.event === "error") {
30814
30821
  throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
30815
30822
  errorCode: msg.error_code,
30816
30823
  errorKind: msg.error_kind
@@ -30857,7 +30864,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
30857
30864
  if (!final) {
30858
30865
  throw brokenStream(name, "the stream ended without a result", progress);
30859
30866
  }
30860
- return { data: final.data, note: final.note };
30867
+ return {
30868
+ data: final.data,
30869
+ note: final.note,
30870
+ ...final.profiling ? { profiling: true } : {}
30871
+ };
30861
30872
  }
30862
30873
  function errorBodyMessage(body) {
30863
30874
  if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
@@ -31030,7 +31041,8 @@ function createToolsClient(options = {}) {
31030
31041
  return {
31031
31042
  data: await settle2(streamed.data),
31032
31043
  note: streamed.note,
31033
- outputHint: meta3?.outputHint
31044
+ outputHint: meta3?.outputHint,
31045
+ ...streamed.profiling ? { profiling: true } : {}
31034
31046
  };
31035
31047
  }
31036
31048
  let json2;
@@ -31055,7 +31067,12 @@ function createToolsClient(options = {}) {
31055
31067
  });
31056
31068
  }
31057
31069
  opts?.signal?.throwIfAborted();
31058
- return { data: await settle2(json2.data), note: json2.note, outputHint: meta3?.outputHint };
31070
+ return {
31071
+ data: await settle2(json2.data),
31072
+ note: json2.note,
31073
+ outputHint: meta3?.outputHint,
31074
+ ...json2.profiling === true ? { profiling: true } : {}
31075
+ };
31059
31076
  }
31060
31077
  return { fetchTools, fetchTool, callTool, baseUrl };
31061
31078
  }
@@ -35577,7 +35594,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
35577
35594
  var SESSION_ID2 = randomUUID5();
35578
35595
  function readCliVersion() {
35579
35596
  if (true) {
35580
- return "0.30.2-next.9";
35597
+ return "0.31.0";
35581
35598
  }
35582
35599
  return "0.0.0";
35583
35600
  }
@@ -38102,7 +38119,7 @@ function parseStartFlags(argv) {
38102
38119
  }
38103
38120
  return {
38104
38121
  port: options.port === void 0 ? null : parsePort(options.port),
38105
- host: options.host ?? "127.0.0.1",
38122
+ host: options.host?.trim() || "127.0.0.1",
38106
38123
  idleTimeoutMinutes: options["idle-timeout"] === void 0 ? 0 : parseIdle(options["idle-timeout"]),
38107
38124
  detach: options.detach === true,
38108
38125
  force: options.force === true,
@@ -38159,7 +38176,7 @@ function isLoopback(host) {
38159
38176
  return host === "127.0.0.1" || host === "localhost" || host === "::1";
38160
38177
  }
38161
38178
  function isWildcard(host) {
38162
- return host === "0.0.0.0" || host === "::" || host === "::0" || host === "";
38179
+ return host === "0.0.0.0" || host === "::" || host === "::0";
38163
38180
  }
38164
38181
  function primaryLanIPv4() {
38165
38182
  const ifaces = networkInterfaces();
package/dist/client.js CHANGED
@@ -8301,6 +8301,7 @@ function spawnToolsServer(paths, port, options = {}) {
8301
8301
  stdio: ["ignore", "pipe", logFd],
8302
8302
  env: buildToolsServerEnv(paths, port, process.env, options)
8303
8303
  });
8304
+ fs4.closeSync(logFd);
8304
8305
  child.unref();
8305
8306
  const pid = child.pid;
8306
8307
  if (!pid) {
@@ -9058,6 +9059,7 @@ var FAILURE_CODES = {
9058
9059
  REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
9059
9060
  REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
9060
9061
  REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
9062
+ REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
9061
9063
  REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
9062
9064
  REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
9063
9065
  NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
@@ -10189,8 +10191,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
10189
10191
  if (msg.event === "progress") {
10190
10192
  progress++;
10191
10193
  onProgress(msg.data);
10192
- } else if (msg.event === "result") final = { data: msg.data, note: msg.note };
10193
- else if (msg.event === "error") {
10194
+ } else if (msg.event === "result") {
10195
+ final = {
10196
+ data: msg.data,
10197
+ note: msg.note,
10198
+ ...msg.profiling === true ? { profiling: true } : {}
10199
+ };
10200
+ } else if (msg.event === "error") {
10194
10201
  throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
10195
10202
  errorCode: msg.error_code,
10196
10203
  errorKind: msg.error_kind
@@ -10237,7 +10244,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
10237
10244
  if (!final) {
10238
10245
  throw brokenStream(name, "the stream ended without a result", progress);
10239
10246
  }
10240
- return { data: final.data, note: final.note };
10247
+ return {
10248
+ data: final.data,
10249
+ note: final.note,
10250
+ ...final.profiling ? { profiling: true } : {}
10251
+ };
10241
10252
  }
10242
10253
  function errorBodyMessage(body) {
10243
10254
  if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
@@ -10410,7 +10421,8 @@ function createToolsClient(options = {}) {
10410
10421
  return {
10411
10422
  data: await settle(streamed.data),
10412
10423
  note: streamed.note,
10413
- outputHint: meta?.outputHint
10424
+ outputHint: meta?.outputHint,
10425
+ ...streamed.profiling ? { profiling: true } : {}
10414
10426
  };
10415
10427
  }
10416
10428
  let json;
@@ -10435,7 +10447,12 @@ function createToolsClient(options = {}) {
10435
10447
  });
10436
10448
  }
10437
10449
  opts?.signal?.throwIfAborted();
10438
- return { data: await settle(json.data), note: json.note, outputHint: meta?.outputHint };
10450
+ return {
10451
+ data: await settle(json.data),
10452
+ note: json.note,
10453
+ outputHint: meta?.outputHint,
10454
+ ...json.profiling === true ? { profiling: true } : {}
10455
+ };
10439
10456
  }
10440
10457
  return { fetchTools, fetchTool, callTool, baseUrl };
10441
10458
  }
@@ -15962,6 +15962,7 @@ var FAILURE_CODES = {
15962
15962
  REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
15963
15963
  REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
15964
15964
  REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
15965
+ REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
15965
15966
  REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
15966
15967
  REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
15967
15968
  NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
@@ -16899,7 +16900,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
16899
16900
  var SESSION_ID = randomUUID4();
16900
16901
  function readCliVersion() {
16901
16902
  if (true) {
16902
- return "0.30.2-next.9";
16903
+ return "0.31.0";
16903
16904
  }
16904
16905
  return "0.0.0";
16905
16906
  }
@@ -24566,6 +24566,7 @@ function spawnToolsServer(paths, port, options = {}) {
24566
24566
  stdio: ["ignore", "pipe", logFd],
24567
24567
  env: buildToolsServerEnv(paths, port, process.env, options)
24568
24568
  });
24569
+ fs.closeSync(logFd);
24569
24570
  child.unref();
24570
24571
  const pid = child.pid;
24571
24572
  if (!pid) {
@@ -25313,6 +25314,7 @@ var FAILURE_CODES = {
25313
25314
  REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
25314
25315
  REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
25315
25316
  REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
25317
+ REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
25316
25318
  REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
25317
25319
  REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
25318
25320
  NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
@@ -26485,8 +26487,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
26485
26487
  if (msg.event === "progress") {
26486
26488
  progress++;
26487
26489
  onProgress(msg.data);
26488
- } else if (msg.event === "result") final = { data: msg.data, note: msg.note };
26489
- else if (msg.event === "error") {
26490
+ } else if (msg.event === "result") {
26491
+ final = {
26492
+ data: msg.data,
26493
+ note: msg.note,
26494
+ ...msg.profiling === true ? { profiling: true } : {}
26495
+ };
26496
+ } else if (msg.event === "error") {
26490
26497
  throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
26491
26498
  errorCode: msg.error_code,
26492
26499
  errorKind: msg.error_kind
@@ -26533,7 +26540,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
26533
26540
  if (!final) {
26534
26541
  throw brokenStream(name, "the stream ended without a result", progress);
26535
26542
  }
26536
- return { data: final.data, note: final.note };
26543
+ return {
26544
+ data: final.data,
26545
+ note: final.note,
26546
+ ...final.profiling ? { profiling: true } : {}
26547
+ };
26537
26548
  }
26538
26549
  function errorBodyMessage(body) {
26539
26550
  if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
@@ -26706,7 +26717,8 @@ function createToolsClient(options = {}) {
26706
26717
  return {
26707
26718
  data: await settle2(streamed.data),
26708
26719
  note: streamed.note,
26709
- outputHint: meta2?.outputHint
26720
+ outputHint: meta2?.outputHint,
26721
+ ...streamed.profiling ? { profiling: true } : {}
26710
26722
  };
26711
26723
  }
26712
26724
  let json;
@@ -26731,7 +26743,12 @@ function createToolsClient(options = {}) {
26731
26743
  });
26732
26744
  }
26733
26745
  opts?.signal?.throwIfAborted();
26734
- return { data: await settle2(json.data), note: json.note, outputHint: meta2?.outputHint };
26746
+ return {
26747
+ data: await settle2(json.data),
26748
+ note: json.note,
26749
+ outputHint: meta2?.outputHint,
26750
+ ...json.profiling === true ? { profiling: true } : {}
26751
+ };
26735
26752
  }
26736
26753
  return { fetchTools, fetchTool, callTool, baseUrl };
26737
26754
  }
@@ -28514,6 +28531,7 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
28514
28531
  "await-ui-element": 1500
28515
28532
  };
28516
28533
  var DEFAULT_DELAY_MS = 1400;
28534
+ var CAPTURE_TIMEOUT_MS = 15e3;
28517
28535
  function autoScreenshotEnabled(options) {
28518
28536
  return !isFlagEnabled("disable-auto-screenshot", options);
28519
28537
  }
@@ -28539,6 +28557,7 @@ var AUTO_DESCRIBE_TOOLS = /* @__PURE__ */ new Set([
28539
28557
  function autoDescribeEnabled(options) {
28540
28558
  return !isFlagEnabled("disable-auto-describe", options);
28541
28559
  }
28560
+ var PROFILING_CAPTURE_SKIPPED_NOTE = "Auto-screenshot and element tree skipped while a profiler is recording on this device. Call screenshot or describe if you need to see the screen.";
28542
28561
  var AUTO_DESCRIBE_HEADER = "--- Elements after action (describe) ---";
28543
28562
  function shouldAutoDescribe(toolName) {
28544
28563
  return AUTO_DESCRIBE_TOOLS.has(normalizeToolName(toolName));
@@ -28594,6 +28613,7 @@ function toMcpTool(t) {
28594
28613
  name: t.name,
28595
28614
  description: t.description,
28596
28615
  inputSchema: { type: "object", ...withoutRetiredParams(t.inputSchema) },
28616
+ ...t.readOnly ? { annotations: { readOnlyHint: true } } : {},
28597
28617
  ...Object.keys(meta2).length > 0 ? { _meta: meta2 } : {}
28598
28618
  };
28599
28619
  }
@@ -28629,22 +28649,50 @@ async function fetchWithReconnect(getUrl, reconnect, config2) {
28629
28649
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
28630
28650
  const controller = new AbortController();
28631
28651
  const timer = fetchTimeoutMs !== null ? setTimeout(() => controller.abort(), fetchTimeoutMs) : void 0;
28652
+ let callerSignal;
28632
28653
  try {
28633
28654
  const attemptInit = typeof init === "function" ? init() : init;
28634
- return await fetch(getUrl(), { ...attemptInit, signal: controller.signal });
28655
+ callerSignal = attemptInit?.signal;
28656
+ const signal = callerSignal ? AbortSignal.any([controller.signal, callerSignal]) : controller.signal;
28657
+ return await fetch(getUrl(), { ...attemptInit, signal });
28635
28658
  } catch (err) {
28636
28659
  lastError = err;
28637
- if (attempt === maxRetries) break;
28638
- if (attempt === 0) {
28639
- await reconnect();
28660
+ if (callerSignal?.aborted || attempt === maxRetries) break;
28661
+ const pause = (async () => {
28662
+ if (attempt === 0) {
28663
+ await reconnect();
28664
+ }
28665
+ await new Promise((r) => setTimeout(r, expBackoffBase * Math.pow(2, attempt)));
28666
+ })();
28667
+ await untilAborted(pause, callerSignal);
28668
+ if (callerSignal?.aborted) {
28669
+ lastError = callerSignal.reason;
28670
+ break;
28640
28671
  }
28641
- await new Promise((r) => setTimeout(r, expBackoffBase * Math.pow(2, attempt)));
28642
28672
  } finally {
28643
28673
  clearTimeout(timer);
28644
28674
  }
28645
28675
  }
28646
28676
  throw lastError;
28647
28677
  }
28678
+ async function untilAborted(work, signal) {
28679
+ if (!signal) {
28680
+ await work;
28681
+ return;
28682
+ }
28683
+ let onAbort = () => {
28684
+ };
28685
+ const aborted2 = new Promise((resolve10) => {
28686
+ onAbort = resolve10;
28687
+ if (signal.aborted) resolve10();
28688
+ else signal.addEventListener("abort", onAbort, { once: true });
28689
+ });
28690
+ try {
28691
+ await Promise.race([work, aborted2]);
28692
+ } finally {
28693
+ signal.removeEventListener("abort", onAbort);
28694
+ }
28695
+ }
28648
28696
  function parseUrl(url) {
28649
28697
  let parsed;
28650
28698
  try {
@@ -28689,9 +28737,9 @@ function createToolCaller(deps) {
28689
28737
  });
28690
28738
  return {
28691
28739
  fetchTools: client.fetchTools,
28692
- async callTool(name, args) {
28693
- const { data, note, outputHint } = await client.callTool(name, args);
28694
- return { result: data, outputHint, note };
28740
+ async callTool(name, args, opts) {
28741
+ const { data, note, outputHint, profiling } = await client.callTool(name, args, opts);
28742
+ return { result: data, outputHint, note, ...profiling ? { profiling } : {} };
28695
28743
  }
28696
28744
  };
28697
28745
  }
@@ -28705,6 +28753,7 @@ async function startMcpServer(options) {
28705
28753
  }
28706
28754
  const autoScreenshotOn = autoScreenshotEnabled();
28707
28755
  const autoDescribeOn = autoDescribeEnabled();
28756
+ const captureTimeoutMs = options.captureTimeoutMs ?? CAPTURE_TIMEOUT_MS;
28708
28757
  let TOOLS_URL;
28709
28758
  let AUTH_TOKEN;
28710
28759
  const resolved = await getResolvedToolsUrl();
@@ -28767,8 +28816,14 @@ async function startMcpServer(options) {
28767
28816
  async function awaitScreenSettled(udid, toolName) {
28768
28817
  const maxWaitMs = getAutoScreenshotDelayMs(toolName);
28769
28818
  if (maxWaitMs === 0) return true;
28819
+ const started = Date.now();
28770
28820
  try {
28771
- const idle = await callTool("await-screen-idle", { udid, timeoutMs: maxWaitMs });
28821
+ const idle = await callTool(
28822
+ "await-screen-idle",
28823
+ { udid, timeoutMs: maxWaitMs },
28824
+ // The tool bounds its poll to maxWaitMs; the rest covers its setup.
28825
+ { signal: AbortSignal.timeout(maxWaitMs + captureTimeoutMs) }
28826
+ );
28772
28827
  await spyLog({
28773
28828
  ts: (/* @__PURE__ */ new Date()).toISOString(),
28774
28829
  event: "auto_screenshot_readiness",
@@ -28778,13 +28833,13 @@ async function startMcpServer(options) {
28778
28833
  });
28779
28834
  return idle.result?.settled === true;
28780
28835
  } catch {
28781
- await new Promise((r) => setTimeout(r, maxWaitMs));
28836
+ await new Promise((r) => setTimeout(r, Math.max(0, maxWaitMs - (Date.now() - started))));
28782
28837
  return false;
28783
28838
  }
28784
28839
  }
28785
- async function captureScreenshotBlocks(udid) {
28840
+ async function captureScreenshotBlocks(udid, signal) {
28786
28841
  try {
28787
- const { result } = await callTool("screenshot", { udid });
28842
+ const { result } = await callTool("screenshot", { udid }, { signal });
28788
28843
  const blocks = await toMcpContent(result, "image", {
28789
28844
  toolsUrl: TOOLS_URL,
28790
28845
  authToken: AUTH_TOKEN,
@@ -28796,10 +28851,10 @@ async function startMcpServer(options) {
28796
28851
  return [];
28797
28852
  }
28798
28853
  }
28799
- async function captureTreeBlocks(udid, toolName) {
28854
+ async function captureTreeBlocks(udid, toolName, signal) {
28800
28855
  const t1 = Date.now();
28801
28856
  try {
28802
- const d = await callTool("describe", { udid });
28857
+ const d = await callTool("describe", { udid }, { signal });
28803
28858
  const desc = d.result?.description;
28804
28859
  await spyLog({
28805
28860
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -28855,7 +28910,7 @@ ${desc}` }];
28855
28910
  args: params.arguments
28856
28911
  });
28857
28912
  try {
28858
- const { result, outputHint, note } = await callTool(params.name, params.arguments);
28913
+ const { result, outputHint, note, profiling } = await callTool(params.name, params.arguments);
28859
28914
  await spyLog({
28860
28915
  ts: (/* @__PURE__ */ new Date()).toISOString(),
28861
28916
  event: "tool_result",
@@ -28888,11 +28943,17 @@ ${desc}` }];
28888
28943
  text: "Auto-screenshot and element tree skipped: the input contains a {{secret:\u2026}} placeholder, and a capture of this screen could reveal the typed secret. The secret is already typed \u2014 do not send the typing step again, or the field will hold two copies of it. Submit or navigate away, then verify the resulting screen as usual. Only this call is covered: the next call is captured normally, and shows the secret if the field is still on screen. To cover the submit as well, put the typing and the submit in ONE `run-sequence` the next time you type a secret."
28889
28944
  }
28890
28945
  ];
28946
+ } else if (udid && (wantScreenshot || wantTree) && profiling) {
28947
+ if (params.name !== "describe") {
28948
+ await awaitScreenSettled(udid, params.name);
28949
+ content = [...content, { type: "text", text: PROFILING_CAPTURE_SKIPPED_NOTE }];
28950
+ }
28891
28951
  } else if (udid && (wantScreenshot || wantTree)) {
28892
28952
  const screenSettled = await awaitScreenSettled(udid, params.name);
28893
- const screenshot = wantScreenshot ? captureScreenshotBlocks(udid) : Promise.resolve([]);
28953
+ const signal = AbortSignal.timeout(captureTimeoutMs);
28954
+ const screenshot = wantScreenshot ? captureScreenshotBlocks(udid, signal) : Promise.resolve([]);
28894
28955
  if (!screenSettled) await screenshot;
28895
- const tree = wantTree ? captureTreeBlocks(udid, params.name) : Promise.resolve([]);
28956
+ const tree = wantTree ? captureTreeBlocks(udid, params.name, signal) : Promise.resolve([]);
28896
28957
  content = [...content, ...await screenshot, ...await tree];
28897
28958
  }
28898
28959
  if (note) {
@@ -53,6 +53,8 @@ export interface ArgentToolArgs {
53
53
  force?: boolean;
54
54
  /** Android only: boot the emulator with audio output enabled. Defaults to false: argent boots emulators MUTED so several agent-driven devices don't all play sound on the host machine; pass `true` when the task involves playing, hearing, or testing audio. Takes effect at boot: if the emulator is already running muted, add `force: true` to reboot it with sound. A boot snapshot saved in the other audio mode can't be reused, so the first boot after toggling is a slower cold boot. The `boot-sound` argent flag flips this default to true. Ignored on iOS/Vega/HarmonyOS/Electron, which argent never mutes. */
55
55
  sound?: boolean;
56
+ /** Android on a macOS host only: boot the emulator with guest Vulkan. Defaults to false: guest Vulkan crashes Chrome's GPU process, which breaks Chrome and Custom Tab sign-in flows. Without it apps find no Vulkan device, although the guest still lists the Vulkan features, so a Vulkan-only renderer such as WebGPU (react-native-wgpu) draws nothing; pass `true` to test one. Takes effect at boot: an emulator already running in the other mode is reused with a `note`, and `force: true` reboots it. A boot snapshot saved in the other mode can't be reused, so the first boot after toggling is a slower cold boot. The `ARGENT_EMULATOR_GUEST_VULKAN` env var flips this default to true. Ignored on other hosts and platforms. */
57
+ guestVulkan?: boolean;
56
58
  /** iOS only: boot the simulator core WITHOUT opening its GUI window (Simulator.app, or Device Hub on Xcode 27+). The device still streams via simulator-server; used by Argent Lens. Set the `ARGENT_SIMULATOR_NO_WINDOW` env var (1/true/yes) to force this host-wide without passing the flag per call (the iOS analog of `ARGENT_EMULATOR_NO_WINDOW`). Ignored on Android/Vega/HarmonyOS/Electron, which have no equivalent GUI step. */
57
59
  headless?: boolean;
58
60
  /** Electron: path to the Electron app to launch. Either a packaged .app bundle / executable, or a project directory whose package.json points the Electron binary at the entry script. Provide exactly one of `udid`, `avdName`, `vvdImage`, `harmonyInstance`, or `electronAppPath`. */