@swmansion/argent 0.21.1-next.1 → 0.21.1-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli-cmds.mjs CHANGED
@@ -7214,7 +7214,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
7214
7214
  var SESSION_ID2 = randomUUID5();
7215
7215
  function readCliVersion() {
7216
7216
  if (true) {
7217
- return "0.21.0";
7217
+ return "0.21.1-next.10";
7218
7218
  }
7219
7219
  return "0.0.0";
7220
7220
  }
@@ -16434,7 +16434,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
16434
16434
  var SESSION_ID = randomUUID4();
16435
16435
  function readCliVersion() {
16436
16436
  if (true) {
16437
- return "0.21.0";
16437
+ return "0.21.1-next.10";
16438
16438
  }
16439
16439
  return "0.0.0";
16440
16440
  }
@@ -95690,7 +95690,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
95690
95690
  var SESSION_ID = (0, import_node_crypto3.randomUUID)();
95691
95691
  function readCliVersion() {
95692
95692
  if (true) {
95693
- return "0.21.0";
95693
+ return "0.21.1-next.10";
95694
95694
  }
95695
95695
  return "0.0.0";
95696
95696
  }
@@ -111799,7 +111799,21 @@ function adaptAXDescribeToDescribeResult(response) {
111799
111799
  }
111800
111800
 
111801
111801
  // ../tool-server/src/tools/describe/platforms/ios/index.ts
111802
- var DEGRADED_HINT = "This simulator was not booted through argent \u2014 system dialogs and native modals may not appear. You MUST call boot-device with force=true now to restart the simulator and apply full accessibility settings before continuing.";
111802
+ var DEGRADED_BLIND_HINT = "The accessibility read returned no elements, and this simulator was not booted through argent, so the pre-boot accessibility settings were never applied. Unless the screen is genuinely blank, call boot-device with force=true to reboot it with those settings \u2014 this restarts the simulator";
111803
+ var DEGRADED_STANDING_HINT = "This simulator was not booted through argent, so system dialogs and native modals may not appear in this tree; everything else reads normally. If something you expect is missing, boot-device with force=true reboots the simulator with the full accessibility settings";
111804
+ var bootCaveatToldDevices = /* @__PURE__ */ new Set();
111805
+ function withBootCaveatOncePerDevice(deviceId, data) {
111806
+ if (data.hint !== DEGRADED_STANDING_HINT) {
111807
+ if (data.hint !== DEGRADED_BLIND_HINT) bootCaveatToldDevices.delete(deviceId);
111808
+ return data;
111809
+ }
111810
+ if (!bootCaveatToldDevices.has(deviceId)) {
111811
+ bootCaveatToldDevices.add(deviceId);
111812
+ return data;
111813
+ }
111814
+ const { hint: _alreadyTold, ...rest } = data;
111815
+ return rest;
111816
+ }
111803
111817
  function tcpArtifactHint(err) {
111804
111818
  const message = err instanceof Error ? err.message : typeof err === "string" ? err : "";
111805
111819
  return /TCP-transport (?:binary|dylib) not found/.test(message) ? message : void 0;
@@ -111820,17 +111834,21 @@ async function describeIos(registry2, device, params, options = {}) {
111820
111834
  return { tree: emptyTree(), source: "ax-service", hint: TVOS_HINT };
111821
111835
  }
111822
111836
  let tree;
111823
- let hint;
111837
+ let degraded;
111838
+ let resolverHint;
111824
111839
  try {
111825
111840
  const axRef = axServiceRef(device);
111826
111841
  const axApi = await registry2.resolveService(axRef.urn, axRef.options);
111827
111842
  const response = await axApi.describe();
111828
111843
  tree = adaptAXDescribeToDescribeResult(response);
111829
- hint = axApi.degraded ? DEGRADED_HINT : void 0;
111844
+ degraded = axApi.degraded;
111830
111845
  } catch (err) {
111831
111846
  tree = emptyTree();
111832
- hint = tcpArtifactHint(err) ?? DEGRADED_HINT;
111847
+ resolverHint = tcpArtifactHint(err);
111848
+ degraded = resolverHint === void 0;
111833
111849
  }
111850
+ const degradedHint = !degraded ? void 0 : tree.children.length === 0 ? DEGRADED_BLIND_HINT : DEGRADED_STANDING_HINT;
111851
+ const hint = resolverHint ?? degradedHint;
111834
111852
  if (tree.children.length > 0) {
111835
111853
  return { tree, source: "ax-service", hint };
111836
111854
  }
@@ -131784,7 +131802,12 @@ function makeDescribeExecute(registry2) {
131784
131802
  requires: iosRequires,
131785
131803
  handler: async (_services, params, device) => (
131786
131804
  // Probe tvOS once here, then pass the verdict into describeIos.
131787
- await isTvOsSimulator(device.id) ? describeTv(registry2, device) : withDescription(await describeIos(registry2, device, params, { isTvOs: false }))
131805
+ await isTvOsSimulator(device.id) ? describeTv(registry2, device) : withDescription(
131806
+ withBootCaveatOncePerDevice(
131807
+ device.id,
131808
+ await describeIos(registry2, device, params, { isTvOs: false })
131809
+ )
131810
+ )
131788
131811
  )
131789
131812
  },
131790
131813
  iosRemote: {
@@ -131793,7 +131816,12 @@ function makeDescribeExecute(registry2) {
131793
131816
  // ios-remote. Only the preflight dep differs. Remote sims are iOS-only
131794
131817
  // (never tvOS), so the isTvOs verdict is always false.
131795
131818
  requires: ["sim-remote"],
131796
- handler: async (_services, params, device) => withDescription(await describeIos(registry2, device, params, { isTvOs: false }))
131819
+ handler: async (_services, params, device) => withDescription(
131820
+ withBootCaveatOncePerDevice(
131821
+ device.id,
131822
+ await describeIos(registry2, device, params, { isTvOs: false })
131823
+ )
131824
+ )
131797
131825
  },
131798
131826
  android: {
131799
131827
  requires: androidRequires,
@@ -136339,13 +136367,13 @@ function summarizeHangBlocking(states) {
136339
136367
  var MAX_INLINE_HOTSPOTS = 5;
136340
136368
  var MAX_INLINE_HANGS = 3;
136341
136369
  async function renderNativeProfilerReport(input) {
136342
- const { payload, traceFile, freshnessNote, mallocStackLogging } = input;
136370
+ const { payload, traceFile, freshnessNote, cpuDiagnostic, mallocStackLogging } = input;
136343
136371
  const exportErrors = input.exportErrors ?? {};
136344
136372
  const bottlenecksTotal = payload.bottlenecks.length;
136345
136373
  const status = Object.keys(exportErrors).length > 0 ? "analysis_failed" : "ok";
136346
136374
  const cpuHotspotsCount = payload.bottlenecks.filter((b) => b.type === "cpu_hotspot").length;
136347
136375
  const uiHangsCount = payload.bottlenecks.filter((b) => b.type === "ui_hang").length;
136348
- const fullReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote) : renderFullReport(
136376
+ const fullReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) : renderFullReport(
136349
136377
  payload,
136350
136378
  exportErrors,
136351
136379
  {
@@ -136353,11 +136381,12 @@ async function renderNativeProfilerReport(input) {
136353
136381
  hangLimit: Infinity
136354
136382
  },
136355
136383
  freshnessNote,
136356
- mallocStackLogging
136384
+ mallocStackLogging,
136385
+ cpuDiagnostic
136357
136386
  );
136358
136387
  const reportFile = traceFile ? deriveReportPath(traceFile) : null;
136359
136388
  const wroteFile = reportFile ? await writeReport2(reportFile, fullReport) : false;
136360
- const inlineReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote) : renderFullReport(
136389
+ const inlineReport = bottlenecksTotal === 0 ? renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) : renderFullReport(
136361
136390
  payload,
136362
136391
  exportErrors,
136363
136392
  {
@@ -136365,13 +136394,19 @@ async function renderNativeProfilerReport(input) {
136365
136394
  hangLimit: MAX_INLINE_HANGS
136366
136395
  },
136367
136396
  freshnessNote,
136368
- mallocStackLogging
136397
+ mallocStackLogging,
136398
+ cpuDiagnostic
136369
136399
  );
136370
136400
  const shownHotspots = Math.min(MAX_INLINE_HOTSPOTS, cpuHotspotsCount);
136371
136401
  const shownHangs = Math.min(MAX_INLINE_HANGS, uiHangsCount);
136402
+ const shownParts = [
136403
+ ...shownHotspots > 0 ? [`top ${shownHotspots} CPU hotspots`] : [],
136404
+ ...shownHangs > 0 ? [`top ${shownHangs} hangs`] : []
136405
+ ];
136406
+ const shownSummary = shownParts.length > 0 ? `showing ${shownParts.join(" and ")} inline` : `summary inline`;
136372
136407
  const report = wroteFile && reportFile ? inlineReport + `
136373
136408
 
136374
- > Full report saved \u2014 ${bottlenecksTotal} bottleneck(s) total, showing top ${shownHotspots} CPU hotspots and top ${shownHangs} hangs inline. Use the Read tool on the \`reportFile\` path in this result to view all details.` : inlineReport;
136409
+ > Full report saved \u2014 ${bottlenecksTotal} bottleneck(s) total, ${shownSummary}. Use the Read tool on the \`reportFile\` path in this result to view all details.` : inlineReport;
136375
136410
  return {
136376
136411
  report,
136377
136412
  reportFile: wroteFile ? reportFile : null,
@@ -136411,7 +136446,7 @@ function renderTraceProcessorUnavailable(err) {
136411
136446
  function reportTitle(payload) {
136412
136447
  return payload.metadata.platform.toLowerCase() === "android" ? "Android Perfetto Analysis" : "iOS Instruments Analysis";
136413
136448
  }
136414
- function renderAllClear2(payload, exportErrors, freshnessNote) {
136449
+ function renderAllClear2(payload, exportErrors, freshnessNote, cpuDiagnostic) {
136415
136450
  const traceName = payload.metadata.traceFile ? `\`${path24.basename(payload.metadata.traceFile)}\`` : "unknown";
136416
136451
  const lines = [
136417
136452
  `# ${reportTitle(payload)}`,
@@ -136420,6 +136455,7 @@ function renderAllClear2(payload, exportErrors, freshnessNote) {
136420
136455
  ``
136421
136456
  ];
136422
136457
  if (freshnessNote) lines.push(freshnessNote, ``);
136458
+ if (cpuDiagnostic) lines.push(`> \u26A0\uFE0F **CPU sampling:** ${cpuDiagnostic}`, ``);
136423
136459
  const errorLines = renderExportErrors(exportErrors);
136424
136460
  if (errorLines.length > 0) {
136425
136461
  lines.push(...errorLines, ``);
@@ -136439,7 +136475,7 @@ function renderAllClear2(payload, exportErrors, freshnessNote) {
136439
136475
  }
136440
136476
  return lines.join("\n");
136441
136477
  }
136442
- function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity, hangLimit: Infinity }, freshnessNote, mallocStackLogging) {
136478
+ function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity, hangLimit: Infinity }, freshnessNote, mallocStackLogging, cpuDiagnostic) {
136443
136479
  const traceName = payload.metadata.traceFile ? `\`${path24.basename(payload.metadata.traceFile)}\`` : "unknown";
136444
136480
  const cpuHotspots = payload.bottlenecks.filter((b) => b.type === "cpu_hotspot");
136445
136481
  const uiHangs = payload.bottlenecks.filter((b) => b.type === "ui_hang");
@@ -136454,6 +136490,7 @@ function renderFullReport(payload, exportErrors, cap = { hotspotLimit: Infinity,
136454
136490
  ``
136455
136491
  ];
136456
136492
  if (freshnessNote) lines.push(freshnessNote, ``);
136493
+ if (cpuDiagnostic) lines.push(`> \u26A0\uFE0F **CPU sampling:** ${cpuDiagnostic}`, ``);
136457
136494
  const errorLines = renderExportErrors(exportErrors);
136458
136495
  if (errorLines.length > 0) {
136459
136496
  lines.push(...errorLines, ``);
@@ -138044,8 +138081,13 @@ async function runAndroidProfilerPipeline(tracePath, appPackage) {
138044
138081
  exportErrors.rss = msg;
138045
138082
  });
138046
138083
  if (cpuRows.length === 0 && hangRows.length === 0 && !exportErrors.cpu) {
138047
- exportErrors.cpu = `No CPU samples were captured for cmdline \`${appPackage}\`. The most common cause is the target app being non-debuggable (release build) without a \`<profileable shell="true">\` entry in its AndroidManifest.xml. Without that, Perfetto silently drops the linux.perf data source. Add \`<profileable android:shell="true"/>\` to the \`<application>\` element and rebuild, or run a debug variant of the app.`;
138084
+ exportErrors.cpu = `No CPU samples were captured for cmdline \`${appPackage}\`. The trace contains no perf_sample rows for a process with that name, so no CPU analysis is possible. Either the name never matched a running process (it must equal the process cmdline exactly), or the app was never scheduled on-CPU during the recording. If it was running, it must be a debug build or declare \`<profileable android:shell="true"/>\` under \`<application>\` in its AndroidManifest.xml \u2014 then re-record.`;
138048
138085
  }
138086
+ const stacklessSamples = cpuRows.reduce(
138087
+ (sum, r) => r.leaf_function ? sum : sum + Number(r.sample_count),
138088
+ 0
138089
+ );
138090
+ const cpuDiagnostic = cpuRows.length > 0 && !cpuRows.some((r) => r.leaf_function) && stacklessSamples > 0 ? describeStacklessSamples(appPackage, cpuRows, stacklessSamples) : void 0;
138049
138091
  const cpuHotspots = aggregateCpuHotspots(cpuRowsToAggregatorRows(cpuRows, traceStartNs), {
138050
138092
  platform: "android"
138051
138093
  });
@@ -138073,7 +138115,14 @@ async function runAndroidProfilerPipeline(tracePath, appPackage) {
138073
138115
  });
138074
138116
  const rssGrowth = rssRowsToBottlenecks(rssRows);
138075
138117
  const bottlenecks = [...cpuHotspots, ...uiHangs, ...rssGrowth];
138076
- return { bottlenecks, cpuHotspots, uiHangs, rssGrowth, exportErrors };
138118
+ return {
138119
+ bottlenecks,
138120
+ cpuHotspots,
138121
+ uiHangs,
138122
+ rssGrowth,
138123
+ exportErrors,
138124
+ ...cpuDiagnostic ? { cpuDiagnostic } : {}
138125
+ };
138077
138126
  }
138078
138127
  async function loadAndroidCombinedData(tracePath, appPackage) {
138079
138128
  const target = sanitizeProcessName(appPackage);
@@ -138306,6 +138355,11 @@ async function renderThreadBreakdownAndroid(opts, target) {
138306
138355
  }
138307
138356
  return lines.join("\n");
138308
138357
  }
138358
+ function describeStacklessSamples(appPackage, cpuRows, stacklessSamples) {
138359
+ const unwound = cpuRows.some((r) => r.leaf_mapping);
138360
+ const head = `${stacklessSamples} CPU sample${stacklessSamples === 1 ? "" : "s"} were captured for \`${appPackage}\`, but none carry a usable call stack, so no CPU hotspots could be computed and \`profiler-stack-query\` mode=\`function_callers\` / mode=\`hang_stacks\` will find nothing. The app was running \u2014 this is a capture limitation, not an idle app. mode=\`thread_breakdown\` still works, since it counts samples and needs no stacks.`;
138361
+ return unwound ? `${head} The stacks were unwound but no frame resolved to a symbol, which points at stripped native libraries. Profile a build that keeps its symbols (a debug build, or a release build with unstripped \`.so\`s).` : `${head} No stack was unwound at all: Perfetto only unwinds a process it can read \`/proc/<pid>/mem\` for. Profile a debug build, or add \`<profileable android:shell="true"/>\` to \`<application>\` and rebuild \u2014 verify with \`adb shell dumpsys package ${appPackage}\`, which shows \`DEBUGGABLE\` for a profileable target. Platform packages such as \`com.android.settings\` are never profileable.`;
138362
+ }
138309
138363
  function cpuRowsToAggregatorRows(rows, traceStartNs) {
138310
138364
  const traceStartMs = Math.round(traceStartNs / 1e6);
138311
138365
  const out = [];
@@ -138647,7 +138701,9 @@ async function analyzeNativeProfilerAndroid(api) {
138647
138701
  // wallClockStartMs is the recording's start time (set at start, persisted in
138648
138702
  // the metadata sidecar, restored by profiler-load). A large gap to "now"
138649
138703
  // means we're analyzing a trace from an earlier session, not a fresh capture.
138650
- freshnessNote: formatTraceFreshness(api.wallClockStartMs, Date.now()) ?? void 0
138704
+ freshnessNote: formatTraceFreshness(api.wallClockStartMs, Date.now()) ?? void 0,
138705
+ // Explains an absent CPU section when samples exist but carry no stacks.
138706
+ cpuDiagnostic: pipelineResult.cpuDiagnostic
138651
138707
  });
138652
138708
  }
138653
138709
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.21.1-next.1",
3
+ "version": "0.21.1-next.10",
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",