@swmansion/argent 0.32.1-next.17 → 0.32.1-next.19

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
@@ -35871,7 +35871,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
35871
35871
  var SESSION_ID2 = randomUUID5();
35872
35872
  function readCliVersion() {
35873
35873
  if (true) {
35874
- return "0.32.1-next.17";
35874
+ return "0.32.1-next.18";
35875
35875
  }
35876
35876
  return "0.0.0";
35877
35877
  }
@@ -16981,7 +16981,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
16981
16981
  var SESSION_ID = randomUUID4();
16982
16982
  function readCliVersion() {
16983
16983
  if (true) {
16984
- return "0.32.1-next.17";
16984
+ return "0.32.1-next.18";
16985
16985
  }
16986
16986
  return "0.0.0";
16987
16987
  }
@@ -29170,6 +29170,78 @@ function toMcpToolList(tools, options = {}) {
29170
29170
  return tools.filter((t) => !t.hideFromMcp).map((t) => toMcpTool(t, options));
29171
29171
  }
29172
29172
 
29173
+ // ../argent-mcp/src/list-devices-text.ts
29174
+ var RUNTIME_PREFIX = "com.apple.CoreSimulator.SimRuntime.";
29175
+ var STOPPED_SIMULATORS_HEADER = "iOS simulators that are shut down, one per line (platform, udid, name, runtime, state, tags); start one with boot-device:";
29176
+ function isRecord3(value) {
29177
+ return value !== null && typeof value === "object" && !Array.isArray(value);
29178
+ }
29179
+ function shortRuntime(runtime) {
29180
+ if (!runtime.startsWith(RUNTIME_PREFIX)) return runtime;
29181
+ const rest = runtime.slice(RUNTIME_PREFIX.length);
29182
+ const match = /^([A-Za-z]+)-(\d+(?:-\d+)*)$/.exec(rest);
29183
+ return match ? `${match[1]} ${match[2].replace(/-/g, ".")}` : rest;
29184
+ }
29185
+ function cleanEntry(device) {
29186
+ const out = {};
29187
+ for (const [key, value] of Object.entries(device)) {
29188
+ if (value === null || value === void 0) continue;
29189
+ if (key === "isEmulator") continue;
29190
+ if (key === "runtimeKind" && value === "mobile") continue;
29191
+ out[key] = key === "runtime" && typeof value === "string" ? shortRuntime(value) : value;
29192
+ }
29193
+ return out;
29194
+ }
29195
+ function isStoppedSimulator(device) {
29196
+ if (device.platform !== "ios" && device.platform !== "ios-remote") return false;
29197
+ if ("kind" in device || "external" in device) return false;
29198
+ return typeof device.udid === "string" && device.state === "Shutdown";
29199
+ }
29200
+ var ONE_LINE_FIELDS = /* @__PURE__ */ new Set(["platform", "udid", "name", "runtime", "state"]);
29201
+ function quoteIfNeeded(value) {
29202
+ return value === "" || /[\s"\\]/.test(value) ? JSON.stringify(value) : value;
29203
+ }
29204
+ function stoppedSimulatorLine(device) {
29205
+ const d = cleanEntry(device);
29206
+ const name = typeof d.name === "string" ? d.name : "";
29207
+ const parts = [String(d.platform), String(d.udid), JSON.stringify(name)];
29208
+ if (typeof d.runtime === "string") parts.push(d.runtime);
29209
+ if (typeof d.state === "string") parts.push(quoteIfNeeded(d.state));
29210
+ for (const [key, value] of Object.entries(d)) {
29211
+ if (ONE_LINE_FIELDS.has(key)) continue;
29212
+ if (value === true) parts.push(key);
29213
+ else if (typeof value === "string" || typeof value === "number")
29214
+ parts.push(`${key}=${quoteIfNeeded(String(value))}`);
29215
+ else parts.push(`${key}=${JSON.stringify(value)}`);
29216
+ }
29217
+ return parts.join(" ");
29218
+ }
29219
+ function listDevicesText(result) {
29220
+ if (!isRecord3(result) || !Array.isArray(result.devices)) return void 0;
29221
+ if (!result.devices.every(isRecord3)) return void 0;
29222
+ const devices = result.devices;
29223
+ const listed = [];
29224
+ const stopped = [];
29225
+ for (const device of devices) {
29226
+ if (isStoppedSimulator(device)) stopped.push(stoppedSimulatorLine(device));
29227
+ else listed.push(JSON.stringify(cleanEntry(device)));
29228
+ }
29229
+ const rest = [];
29230
+ for (const [key, value] of Object.entries(result)) {
29231
+ if (key === "devices") continue;
29232
+ rest.push(`${JSON.stringify(key)}:${JSON.stringify(value)}`);
29233
+ }
29234
+ const devicesPart = listed.length > 0 ? `[
29235
+ ${listed.join(",\n")}
29236
+ ]` : "[]";
29237
+ const object3 = `{"devices":${devicesPart}${rest.map((r) => `,
29238
+ ${r}`).join("")}}`;
29239
+ if (stopped.length === 0) return object3;
29240
+ return `${object3}
29241
+ ${STOPPED_SIMULATORS_HEADER}
29242
+ ${stopped.join("\n")}`;
29243
+ }
29244
+
29173
29245
  // ../argent-mcp/src/instructions.ts
29174
29246
  var SERVER_INSTRUCTIONS = "Argent \u2014 iOS Simulator, Android Emulator, and Chromium app control for interacting, testing, profiling and debugging mobile and Chromium applications. Interaction tools return the screen after the action: a screenshot plus the accessibility element tree with normalized tap frames. Take coordinates from that tree; call describe only when no fresh tree is available \u2014 never guess coordinates from pixels. Do not stop simulator servers when a task finishes: the next task reuses them. Call stop-all-simulator-servers when the user asks to clean up or ends the session, or when a skill tells you to recycle a device's services, always with devices: [...] naming the devices this session used. Never stop a Metro the user started unless they ask. One tool-server is shared by every agent using this argent install, so an unscoped call tears down their devices too \u2014 reserve it for a deliberate machine-wide cleanup.";
29175
29247
 
@@ -29480,8 +29552,11 @@ ${hintLine}${desc}` }];
29480
29552
  authToken: AUTH_TOKEN,
29481
29553
  deviceId: getDeviceIdFromArgs(params.arguments)
29482
29554
  };
29555
+ const devicesText = canonicalToolId(params.name) === "list-devices" ? listDevicesText(result) : void 0;
29483
29556
  let content;
29484
- if (canonicalToolId(params.name) === "e2e-execute" && result && typeof result === "object" && ("e2eTest" in result || "flow" in result) && "steps" in result) {
29557
+ if (devicesText !== void 0) {
29558
+ content = [{ type: "text", text: devicesText }];
29559
+ } else if (canonicalToolId(params.name) === "e2e-execute" && result && typeof result === "object" && ("e2eTest" in result || "flow" in result) && "steps" in result) {
29485
29560
  content = await flowRunToMcpContent(result, ctx);
29486
29561
  } else if (params.name === "screenshot-diff" && isScreenshotDiffResult(result)) {
29487
29562
  content = await screenshotDiffToMcpContent(result, ctx);
@@ -506,7 +506,7 @@ export interface ArgentToolArgs {
506
506
  includeAncestors?: boolean;
507
507
  /** Include child views for each matched view (default true) */
508
508
  includeChildren?: boolean;
509
- /** View fields to include. Defaults: className, frame, hidden, alpha, identifier, label, nativeID, userInteractionEnabled, depth. Additional: pointer, tag, windowFrame, screenFrame, bounds, center, opaque, clipsToBounds, transform, contentMode, backgroundColor, tintColor, layerName */
509
+ /** View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder */
510
510
  fields?: Array<string>;
511
511
  };
512
512
  "native-full-hierarchy": {
@@ -514,7 +514,7 @@ export interface ArgentToolArgs {
514
514
  udid: string;
515
515
  /** Bundle ID of the app (on a Mac app, the bundle id in the device id) */
516
516
  bundleId: string;
517
- /** View fields to include. Use EXACT names: className, frame, hidden, alpha, identifier, label, nativeID, userInteractionEnabled, depth, pointer, tag, windowFrame, screenFrame, bounds, center, opaque, clipsToBounds, transform, contentMode, backgroundColor, tintColor, layerName. Defaults to all of the first group when omitted. */
517
+ /** View fields to include. Use EXACT names. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder */
518
518
  fields?: Array<string>;
519
519
  /** Exact UIView class names whose entire subtree should be pruned (e.g. ["UIImageView"] to drop image leaf nodes) */
520
520
  skipClasses?: Array<string>;
@@ -560,7 +560,7 @@ export interface ArgentToolArgs {
560
560
  udid: string;
561
561
  /** Bundle ID of the app (on a Mac app, the bundle id in the device id) */
562
562
  bundleId: string;
563
- /** Raw X coordinate in points, on the portrait axes of the screen (the axes of native-describe-screen frames); on a Mac app, points from the top-left of the area describe reports. NOT normalized [0,1] tap space. */
563
+ /** Raw X coordinate in points, on the portrait axes of the screen; on a Mac app, points from the top-left of the area describe reports. NOT normalized [0,1] tap space. */
564
564
  x: number;
565
565
  /** Raw Y coordinate in points, on the same axes as x. NOT normalized [0,1] tap space. */
566
566
  y: number;
@@ -568,7 +568,7 @@ export interface ArgentToolArgs {
568
568
  includeAncestors?: boolean;
569
569
  /** Include child views for the matched view (default false) */
570
570
  includeChildren?: boolean;
571
- /** View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor */
571
+ /** View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder */
572
572
  fields?: Array<string>;
573
573
  /** Exact UIView class names whose entire subtree should be pruned */
574
574
  skipClasses?: Array<string>;
@@ -582,7 +582,7 @@ export interface ArgentToolArgs {
582
582
  udid: string;
583
583
  /** Bundle ID of the app (on a Mac app, the bundle id in the device id) */
584
584
  bundleId: string;
585
- /** Raw X coordinate in points, on the portrait axes of the screen (the axes of native-describe-screen frames); on a Mac app, points from the top-left of the area describe reports. NOT normalized [0,1] tap space. */
585
+ /** Raw X coordinate in points, on the portrait axes of the screen; on a Mac app, points from the top-left of the area describe reports. NOT normalized [0,1] tap space. */
586
586
  x: number;
587
587
  /** Raw Y coordinate in points, on the same axes as x. NOT normalized [0,1] tap space. */
588
588
  y: number;
@@ -590,7 +590,7 @@ export interface ArgentToolArgs {
590
590
  includeAncestors?: boolean;
591
591
  /** Include child views for the matched view (default false) */
592
592
  includeChildren?: boolean;
593
- /** View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor */
593
+ /** View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder */
594
594
  fields?: Array<string>;
595
595
  /** Exact UIView class names whose entire subtree should be pruned */
596
596
  skipClasses?: Array<string>;
@@ -101252,7 +101252,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
101252
101252
  var SESSION_ID = (0, import_node_crypto3.randomUUID)();
101253
101253
  function readCliVersion() {
101254
101254
  if (true) {
101255
- return "0.32.1-next.17";
101255
+ return "0.32.1-next.18";
101256
101256
  }
101257
101257
  return "0.0.0";
101258
101258
  }
@@ -123698,7 +123698,7 @@ var NATIVE_DEVTOOLS_NAMESPACE = "NativeDevtools";
123698
123698
  function isInjectableBundleId(bundleId) {
123699
123699
  return !bundleId.toLowerCase().startsWith("com.apple.");
123700
123700
  }
123701
- var NON_INJECTABLE_NATIVE_WARNING = "Do not fall back to the native-devtools feature tools (native-describe-screen, native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.";
123701
+ var NON_INJECTABLE_NATIVE_WARNING = "Do not fall back to the native-devtools feature tools (native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.";
123702
123702
  var NON_INJECTABLE_RECOVERY = "Use the standard `describe` tool (its accessibility path reads the screen without injection) or `screenshot` (then interact by coordinate). " + NON_INJECTABLE_NATIVE_WARNING;
123703
123703
  var MAX_NATIVE_DEVTOOLS_INIT_ATTEMPTS = 3;
123704
123704
  var NATIVE_DEVTOOLS_AGE_SLOP_MS = 3e3;
@@ -123865,7 +123865,7 @@ var nativeDevtoolsBlueprint = {
123865
123865
  const { device } = opts;
123866
123866
  if (device.platform !== "ios" && device.platform !== "ios-remote") {
123867
123867
  throw new FailureError(
123868
- `${NATIVE_DEVTOOLS_NAMESPACE} is iOS-only. The target '${device.id}' classifies as ${device.platform} \u2014 native-devtools tools (native-describe-screen, native-find-views, etc.) only drive iOS simulators. Pick an iOS udid from list-devices.`,
123868
+ `${NATIVE_DEVTOOLS_NAMESPACE} is iOS-only. The target '${device.id}' classifies as ${device.platform} \u2014 native-devtools tools (native-find-views, native-view-at-point, etc.) only drive iOS simulators. Pick an iOS udid from list-devices.`,
123869
123869
  {
123870
123870
  error_code: FAILURE_CODES.NATIVE_DEVTOOLS_WRONG_PLATFORM,
123871
123871
  failure_stage: "native_devtools_factory_options",
@@ -128234,6 +128234,8 @@ async function listRemoteIosSimulators() {
128234
128234
  const result = await simctlListDevices();
128235
128235
  const out = [];
128236
128236
  for (const [runtime, devices] of Object.entries(result.devices)) {
128237
+ const runtimeKind = simulatorRuntimeKind(runtime);
128238
+ if (!runtimeKind) continue;
128237
128239
  for (const d of devices) {
128238
128240
  if (d.isAvailable === false) continue;
128239
128241
  out.push({
@@ -128242,7 +128244,7 @@ async function listRemoteIosSimulators() {
128242
128244
  name: d.name,
128243
128245
  state: d.state,
128244
128246
  runtime,
128245
- runtimeKind: simulatorRuntimeKind(runtime)
128247
+ runtimeKind
128246
128248
  });
128247
128249
  }
128248
128250
  }
@@ -129112,6 +129114,7 @@ var describeNodeSchema = external_exports.lazy(
129112
129114
  frame: describeFrameSchema,
129113
129115
  children: external_exports.array(describeNodeSchema),
129114
129116
  label: external_exports.string().optional(),
129117
+ hint: external_exports.string().optional(),
129115
129118
  identifier: external_exports.string().optional(),
129116
129119
  value: external_exports.string().optional(),
129117
129120
  subtreeText: external_exports.string().optional(),
@@ -129191,8 +129194,11 @@ function adaptNativeDescribeElementToDescribeNode(element) {
129191
129194
  frame: frame2,
129192
129195
  children: [],
129193
129196
  label: element.label,
129197
+ hint: element.hint,
129194
129198
  identifier: element.identifier,
129195
- value: element.value
129199
+ value: element.value,
129200
+ ...element.traits.includes("notEnabled") ? { disabled: true } : {},
129201
+ ...element.traits.includes("selected") ? { selected: true } : {}
129196
129202
  };
129197
129203
  }
129198
129204
  function adaptNativeDescribeToDescribeResult(result) {
@@ -129236,10 +129242,13 @@ function adaptAXElement(el) {
129236
129242
  },
129237
129243
  children: [],
129238
129244
  label: el.label,
129245
+ hint: el.hint,
129239
129246
  value: el.value,
129240
129247
  identifier: el.identifier,
129241
129248
  // The text input that has the keyboard.
129242
- ...traits.includes("isEditing") ? { focused: true } : {}
129249
+ ...traits.includes("isEditing") ? { focused: true } : {},
129250
+ ...traits.includes("notEnabled") ? { disabled: true } : {},
129251
+ ...traits.includes("selected") ? { selected: true } : {}
129243
129252
  };
129244
129253
  }
129245
129254
  function adaptAXDescribeToDescribeResult(response) {
@@ -146136,7 +146145,7 @@ Returns { envSetup, appRunning, connected, requiresRestart, state, message, next
146136
146145
  - nextLaunchWillBeInjected: if you launch this bundle now, native devtools env setup is already in place (always false for a non-injectable app)
146137
146146
  - injectable: false for Apple system apps (bundle ids under com.apple.), which the native tools refuse to read.
146138
146147
 
146139
- If injectable is false: treat this as TERMINAL. The app is not a supported native-devtools target, and no relaunch changes that. Do NOT restart/retry. Use the standard \`describe\` tool (its accessibility path reads the screen without injection) or \`screenshot\` (then interact by coordinate). Do not fall back to the native-devtools feature tools (native-describe-screen, native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.
146148
+ If injectable is false: treat this as TERMINAL. The app is not a supported native-devtools target, and no relaunch changes that. Do NOT restart/retry. Use the standard \`describe\` tool (its accessibility path reads the screen without injection) or \`screenshot\` (then interact by coordinate). Do not fall back to the native-devtools feature tools (native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.
146140
146149
  If appRunning is false and nextLaunchWillBeInjected is true: use launch-app normally.
146141
146150
  If requiresRestart is true: call restart-app once, then proceed with the native feature. Read state before acting on a second such reading. Indeterminate reaches this rule too, and its line below bounds it at that one restart.
146142
146151
  If state is unregistered: do NOT restart the app again: it already launched under the terms a restart would recreate. Restart the tool-server (\`argent server stop && argent server start --detach\`), then retry. If it reads unregistered again after that restart, stop: the process loads argent's dylib but never dials, and no further restart on either side changes it. Treat native devtools as unavailable, then use \`describe\` or \`screenshot\` and drive by coordinate.
@@ -146508,15 +146517,15 @@ var zodSchema5 = external_exports.object({
146508
146517
  includeAncestors: external_exports.boolean().optional().describe("Include ancestor chain for each matched view (default true)"),
146509
146518
  includeChildren: external_exports.boolean().optional().describe("Include child views for each matched view (default true)"),
146510
146519
  fields: external_exports.array(external_exports.string()).optional().describe(
146511
- "View fields to include. Defaults: className, frame, hidden, alpha, identifier, label, nativeID, userInteractionEnabled, depth. Additional: pointer, tag, windowFrame, screenFrame, bounds, center, opaque, clipsToBounds, transform, contentMode, backgroundColor, tintColor, layerName"
146520
+ "View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder"
146512
146521
  )
146513
146522
  });
146514
146523
  var nativeFindViewsTool = {
146515
146524
  id: "native-find-views",
146516
146525
  description: `Search for specific UIViews in the running app by class name, accessibility identifier, accessibility label, tag or React Native nativeID; at least one of these params is required.
146517
146526
  Use when you need to locate a specific view by its properties without dumping the entire native-full-hierarchy.
146518
- Returns { status: "ok", matches }: the matching views with their frames, properties, optional ancestors and optional children.
146519
- <flag:macos-apps>On a Mac app it searches the NSViews of every visible window: className is the NSView class, and identifier matches the accessibility identifier or the view identifier. The statuses below are iOS only.
146527
+ Returns { status: "ok", matches }: the matching views with their frames, properties, optional ancestors and optional children. Frames are in points. frame and center are relative to the superview, and windowFrame turns with the UI. To tap a view, divide the centre of its screenFrame by the screen size in points, which native-full-hierarchy returns as screen (maxDepth: 1 is enough), and pass the result to gesture-tap. Matches are not filtered for visibility. Before tapping, call native-user-interactable-view-at-point at that centre with skipClasses ["UITextEffectsWindow"]. If it does not return the match or a descendant, check a screenshot.
146528
+ <flag:macos-apps>On a Mac app it searches the NSViews of every visible window: className is the NSView class, and identifier matches the accessibility identifier or the view identifier. The tap recipe above and the statuses below are iOS only.
146520
146529
  </flag:macos-apps>If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: follow the message (re-boot the simulator) rather than retrying.
146521
146530
  An Apple system app is rejected outright (terminal: never retry it).`,
146522
146531
  zodSchema: zodSchema5,
@@ -146553,7 +146562,7 @@ init_zod();
146553
146562
  var zodSchema6 = external_exports.object({
146554
146563
  ...nativeAppTarget,
146555
146564
  fields: external_exports.array(external_exports.string()).optional().describe(
146556
- "View fields to include. Use EXACT names: className, frame, hidden, alpha, identifier, label, nativeID, userInteractionEnabled, depth, pointer, tag, windowFrame, screenFrame, bounds, center, opaque, clipsToBounds, transform, contentMode, backgroundColor, tintColor, layerName. Defaults to all of the first group when omitted."
146565
+ "View fields to include. Use EXACT names. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder"
146557
146566
  ),
146558
146567
  skipClasses: external_exports.array(external_exports.string()).optional().describe(
146559
146568
  'Exact UIView class names whose entire subtree should be pruned (e.g. ["UIImageView"] to drop image leaf nodes)'
@@ -146636,6 +146645,10 @@ normalized contract.
146636
146645
  An Apple system app is rejected outright (terminal: never retry it).`,
146637
146646
  zodSchema: zodSchema7,
146638
146647
  readOnly: true,
146648
+ // Agents get the disabled and selected states and the VoiceOver hint from
146649
+ // `describe`, which falls back to this RPC (ViewHierarchy.describeScreen) when
146650
+ // the ax-service returns nothing. The SDK still calls this tool directly.
146651
+ hideFromMcp: true,
146639
146652
  interaction: {
146640
146653
  startedMsg: ({ params }) => `Reading native screen for ${params.bundleId}`,
146641
146654
  completedMsg: ({ params }) => `Read native screen for ${params.bundleId}`,
@@ -146663,13 +146676,13 @@ init_src2();
146663
146676
  var zodSchema8 = external_exports.object({
146664
146677
  ...nativeAppTarget,
146665
146678
  x: external_exports.number().describe(
146666
- "Raw X coordinate in points, on the portrait axes of the screen (the axes of native-describe-screen frames)<flag:macos-apps>; on a Mac app, points from the top-left of the area describe reports</flag:macos-apps>. NOT normalized [0,1] tap space."
146679
+ "Raw X coordinate in points, on the portrait axes of the screen<flag:macos-apps>; on a Mac app, points from the top-left of the area describe reports</flag:macos-apps>. NOT normalized [0,1] tap space."
146667
146680
  ),
146668
146681
  y: external_exports.number().describe("Raw Y coordinate in points, on the same axes as x. NOT normalized [0,1] tap space."),
146669
146682
  includeAncestors: external_exports.boolean().optional().describe("Include ancestor chain for the matched view (default true)"),
146670
146683
  includeChildren: external_exports.boolean().optional().describe("Include child views for the matched view (default false)"),
146671
146684
  fields: external_exports.array(external_exports.string()).optional().describe(
146672
- "View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor"
146685
+ "View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder"
146673
146686
  ),
146674
146687
  skipClasses: external_exports.array(external_exports.string()).optional().describe("Exact UIView class names whose entire subtree should be pruned"),
146675
146688
  skipClassPrefixes: external_exports.array(external_exports.string()).optional().describe("Class name prefixes to prune entire subtrees"),
@@ -146691,7 +146704,8 @@ identifier, label and layer name, plus its ancestors and subviews as requested.
146691
146704
  view is null when nothing is drawn at that point.
146692
146705
 
146693
146706
  To get x and y from a normalized describe frame, multiply its values by the
146694
- screen size in points, also when the UI is landscape.<flag:macos-apps> On a Mac app,
146707
+ screen size in points, also when the UI is landscape.
146708
+ native-full-hierarchy returns that size as screen (pass maxDepth: 1 and fields: ["className"] to keep it small).<flag:macos-apps> On a Mac app,
146695
146709
  multiply them by the size of the area describe reports instead.</flag:macos-apps>
146696
146710
 
146697
146711
  If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: follow the message (re-boot the simulator) rather than retrying.
@@ -146725,13 +146739,13 @@ init_src2();
146725
146739
  var zodSchema9 = external_exports.object({
146726
146740
  ...nativeAppTarget,
146727
146741
  x: external_exports.number().describe(
146728
- "Raw X coordinate in points, on the portrait axes of the screen (the axes of native-describe-screen frames)<flag:macos-apps>; on a Mac app, points from the top-left of the area describe reports</flag:macos-apps>. NOT normalized [0,1] tap space."
146742
+ "Raw X coordinate in points, on the portrait axes of the screen<flag:macos-apps>; on a Mac app, points from the top-left of the area describe reports</flag:macos-apps>. NOT normalized [0,1] tap space."
146729
146743
  ),
146730
146744
  y: external_exports.number().describe("Raw Y coordinate in points, on the same axes as x. NOT normalized [0,1] tap space."),
146731
146745
  includeAncestors: external_exports.boolean().optional().describe("Include ancestor chain for the matched view (default true)"),
146732
146746
  includeChildren: external_exports.boolean().optional().describe("Include child views for the matched view (default false)"),
146733
146747
  fields: external_exports.array(external_exports.string()).optional().describe(
146734
- "View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor"
146748
+ "View fields to include. Defaults: pointer, className, tag, frame, windowFrame, screenFrame, bounds, hidden, alpha, opaque, clipsToBounds, userInteractionEnabled, depth, identifier, label, layerName, nativeID. Additional: center, transform, contentMode, backgroundColor, tintColor, value, firstResponder"
146735
146749
  ),
146736
146750
  skipClasses: external_exports.array(external_exports.string()).optional().describe("Exact UIView class names whose entire subtree should be pruned"),
146737
146751
  skipClassPrefixes: external_exports.array(external_exports.string()).optional().describe("Class name prefixes to prune entire subtrees"),
@@ -146753,7 +146767,8 @@ identifier, label and layer name, plus its ancestors and subviews as requested.
146753
146767
  view is null when no touchable view sits under that point.
146754
146768
 
146755
146769
  To get x and y from a normalized describe frame, multiply its values by the
146756
- screen size in points, also when the UI is landscape.<flag:macos-apps> On a Mac app,
146770
+ screen size in points, also when the UI is landscape.
146771
+ native-full-hierarchy returns that size as screen (pass maxDepth: 1 and fields: ["className"] to keep it small).<flag:macos-apps> On a Mac app,
146757
146772
  multiply them by the size of the area describe reports instead.</flag:macos-apps>
146758
146773
 
146759
146774
  If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: follow the message (re-boot the simulator) rather than retrying.
@@ -154084,8 +154099,7 @@ var gestureTapTool = {
154084
154099
  description: `Press the device screen (iOS simulator or physical device, Android emulator, <flag:harmonyos>HarmonyOS device, </flag:harmonyos><flag:macos-apps>Mac app, </flag:macos-apps>or Chromium app) at a point given as fractions of the screen width and height (not pixels): a Down event followed by an Up event at the same spot.<flag:macos-apps> On a Mac app it is a click, and x/y are fractions of the area describe reports, not of the window.</flag:macos-apps>
154085
154100
  Use when tapping a button, link, or any tappable element on the screen.
154086
154101
  Returns { tapped: true, timestampMs }. On physical iOS, reactivated: true = app was re-fronted; re-describe. Fails if the device backend (simulator-server / emulator / Chromium CDP<flag:harmonyos> / \`hdc\`</flag:harmonyos>) is unreachable.
154087
- On a physical iPhone use \`describe\`; \`native-describe-screen\` is simulator-only.
154088
- Before tapping, determine the correct coordinates by using discovery tools. Pick by platform: iOS / Android use \`describe\` (on an iOS simulator, also \`native-describe-screen\`); Chromium uses \`describe\` (the DOM walker)<flag:harmonyos> and HarmonyOS uses \`describe\` (the \`uitest\` layout dump)</flag:harmonyos>, since the native discovery tools don't apply<flag:harmonyos> to either</flag:harmonyos><flag:macos-apps>; a Mac app uses \`describe\`</flag:macos-apps>. More information in \`argent-device-interact\` skill`,
154102
+ Before tapping, take the coordinates from \`describe\` on every platform (on Chromium it walks the DOM<flag:harmonyos>, on HarmonyOS it reads the \`uitest\` layout dump</flag:harmonyos>). More information in \`argent-device-interact\` skill`,
154089
154103
  zodSchema: zodSchema18,
154090
154104
  alwaysLoad: true,
154091
154105
  // A physical iPhone's first call waits out the runner build, past the MCP fetch timeout,
@@ -160089,19 +160103,24 @@ function hasContent(n) {
160089
160103
  function shouldEmit(n, contentRoles) {
160090
160104
  return hasContent(n) || contentRoles.has(n.role);
160091
160105
  }
160106
+ function hasIosState(n) {
160107
+ return Boolean(n.hint || n.disabled || n.selected);
160108
+ }
160092
160109
  function formatLine(n, indent, source) {
160093
160110
  const pad = " ".repeat(indent);
160094
160111
  const dedupedValue = n.value && n.value !== n.label ? n.value : void 0;
160112
+ const dedupedHint = n.hint && n.hint !== n.label ? n.hint : void 0;
160095
160113
  const labelPart = formatLabel(n.label);
160096
160114
  const valuePart = formatAttr("value", dedupedValue);
160097
160115
  const idPart = formatAttr("id", n.identifier);
160116
+ const hintPart = formatAttr("hint", dedupedHint);
160098
160117
  const flagPart = formatFlags(n, source);
160099
- const annotations = `${labelPart}${valuePart}${idPart}${flagPart}`.trim();
160118
+ const annotations = `${labelPart}${valuePart}${idPart}${hintPart}${flagPart}`.trim();
160100
160119
  const annotated = annotations ? ` ${annotations}` : "";
160101
160120
  return `${pad}${n.role}${annotated} ${fmtFrame(n.frame)}`;
160102
160121
  }
160103
160122
  function renderFlat(root, contentRoles, source) {
160104
- return root.children.filter((n) => shouldEmit(n, contentRoles)).slice().sort((a, b) => a.frame.y - b.frame.y || a.frame.x - b.frame.x).map((n) => formatLine(n, 1, source));
160123
+ return root.children.filter((n) => shouldEmit(n, contentRoles) || hasIosState(n)).slice().sort((a, b) => a.frame.y - b.frame.y || a.frame.x - b.frame.x).map((n) => formatLine(n, 1, source));
160105
160124
  }
160106
160125
  function renderNested(root, contentRoles, source) {
160107
160126
  const lines = [];
@@ -160317,11 +160336,10 @@ On HarmonyOS it runs the device's \`uitest dumpLayout\` (\`source: "harmony-uite
160317
160336
  On a Mac app it reads the app's accessibility tree with web view content and React Native testIDs merged in; frames are fractions of the app window, grown to include sheets and menus past it.</flag:macos-apps>
160318
160337
  On a TV target (Apple TV / Android TV: a \`list-devices\` entry with runtimeKind 'tv') it returns the FOCUSED element and the FOCUSABLE elements instead, since a TV UI has no tap coordinates. Move the highlight with \`tv-remote\`, then call describe again to confirm where focus landed.
160319
160338
 
160320
- Returns \`{ description, source }\`: \`description\` renders the tree one line per element, with its role, label/value/id, interactivity flags and frame. Frames are normalized [0,1] fractions of the screen / window width and height (not pixels); tap an element at the centre of its frame. The tree has no z-order or occlusion information: an element may be covered by an overlay (e.g. a toolbar over list rows), so check a screenshot when a tap lands unexpectedly.
160339
+ Returns \`{ description, source }\`: \`description\` renders the tree one line per element, with its role, label/value/id, VoiceOver hint (iOS simulator), interactivity flags and frame. Frames are normalized [0,1] fractions of the screen / window width and height (not pixels); tap an element at the centre of its frame. The tree has no z-order or occlusion information: an element may be covered by an overlay (e.g. a toolbar over list rows), so check a screenshot when a tap lands unexpectedly.
160321
160340
  Fails if the tree cannot be read, e.g. on a physical iOS device before launch-app has started an app.
160322
160341
 
160323
- For app-scoped inspection with full UIKit properties (accessibilityIdentifier, viewClassName),
160324
- use native-describe-screen with an explicit bundleId instead (iOS simulator only).
160342
+ For UIKit properties of a view (class name, accessibilityIdentifier), use native-find-views (iOS simulator only).
160325
160343
  For React Native component names, or a testID describe does not list, use debugger-component-tree.`,
160326
160344
  zodSchema: zodSchema40,
160327
160345
  alwaysLoad: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.32.1-next.17",
3
+ "version": "0.32.1-next.19",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator, Android Emulator, Chromium app and Mac app control",
6
6
  "license": "Apache-2.0",
@@ -26,7 +26,7 @@ Convert element-seeking swipes to `scroll-to`. Keep a coordinate swipe only when
26
26
 
27
27
  Work this gate as soon as capture warns that it kept a raw point or recorded a role-only selector. Keep the source screen available and do these checks:
28
28
 
29
- 1. **iOS:** query plausible ids or labels with `native-find-views`. If no term is useful, call `native-full-hierarchy` with narrow fields and `maxDepth: 100`. `describe` and `native-describe-screen` are accessibility projections. They cannot prove that no YAML selector exists.
29
+ 1. **iOS:** query plausible ids or labels with `native-find-views`. If no term is useful, call `native-full-hierarchy` with narrow fields and `maxDepth: 100`. `describe` is an accessibility projection. It cannot prove that no YAML selector exists.
30
30
  2. **Other platforms:** use `describe`; for React Native on Android, also `debugger-component-tree`, for testIDs `describe` omits. Verify Android and Chromium candidates in step 3. Their discovery trees can omit runner elements.
31
31
  3. Test each candidate in a scratch fragment with `assert: { visible: <candidate> }` on the valid screen. Inspect every failure before trying a better id, label, app, or container.
32
32
  4. If source is available, inspect its `testID`, `accessibilityIdentifier`, or `resource-id`. If none exists, report the missing stable id as the real fix.
@@ -45,7 +45,7 @@ After an action moves you to a different screen, or whenever you don't know an e
45
45
  | Need | Tool |
46
46
  | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
47
47
  | Any screen: app, system dialog, Home screen | `describe` |
48
- | App-scoped UIKit properties (iOS simulator) | `native-describe-screen` (needs `bundleId`) |
48
+ | UIKit properties of a view (iOS simulator) | `native-find-views` (needs `bundleId` and a class, id, label, tag or `nativeID` to match) |
49
49
  | What sits at a known raw point (iOS simulator) | `native-user-interactable-view-at-point` (the view that receives touch) or `native-view-at-point` (the visually deepest view) |
50
50
  | Final visual fallback | `screenshot`, only when the tools above cannot expose the control. Do not derive routine in-app navigation targets from pixels |
51
51
 
@@ -17,7 +17,7 @@ Refused as unsupported on harmony:
17
17
 
18
18
  - `gesture-rotate` and `gesture-custom`: the device moves each contact along one straight line per call, so there is no arc and no long-press. There is no long-press tool on HarmonyOS.
19
19
  - `gesture-drag` and `gesture-scroll` (Chromium-only), and `rotate`: the device has no orientation command.
20
- - `native-describe-screen`, `native-view-at-point`, `native-user-interactable-view-at-point`, `debugger-component-tree`, the rest of the debugger (`debugger-evaluate`, `debugger-log-registry`), `view-network-logs` and the profilers.
20
+ - `native-view-at-point`, `native-user-interactable-view-at-point`, `debugger-component-tree`, the rest of the debugger (`debugger-evaluate`, `debugger-log-registry`), `view-network-logs` and the profilers.
21
21
  - `paste`, so a `{{secret:...}}` placeholder goes through `keyboard` only.
22
22
  - Screen recording: HarmonyOS exposes no readable frame stream. Use `screenshot` for a still frame.
23
23
 
@@ -5,7 +5,7 @@ description: Set up and connect to an iOS simulator using argent MCP tools. Use
5
5
 
6
6
  ## 1. Setup Steps
7
7
 
8
- 1. **Find a booted simulator.** Use `list-devices`. Filter for entries with `platform: "ios"` and skip `kind: "device"` (a physical iPhone): booted simulators are listed first. If no fitting simulator is booted, call `boot-device` with `udid: <chosen UDID>`.
8
+ 1. **Find a booted simulator.** Use `list-devices`. Filter for entries with `platform: "ios"` and skip `kind: "device"` (a physical iPhone): booted simulators are listed first. Through MCP, simulators that are shut down follow the JSON object, one line each, with the udid second. If no fitting simulator is booted, call `boot-device` with `udid: <chosen UDID>`.
9
9
  2. **No connect step.** Interaction tools (`gesture-tap`, `describe`, `screenshot`, …) auto-start the simulator server on first use.
10
10
 
11
11
  ## 2. Notes
@@ -7,7 +7,7 @@ description: Compare saved or live app screenshots with the argent screenshot-di
7
7
 
8
8
  Use `screenshot-diff` as supporting visual evidence for UI QA and visual regression checks. It highlights pixel-visible change or stability; it does not replace visual inspection, accessibility/component-tree state, frame/attribute checks, logs, network evidence, or app behavior. Its description covers the input combinations, physical-iPhone captures and the result.
9
9
 
10
- Do not use screenshot diffing for tap-coordinate discovery. Use `describe` or `native-describe-screen` to find targets first.
10
+ Do not use screenshot diffing for tap-coordinate discovery. Use `describe` to find targets first.
11
11
 
12
12
  ## 2. When To Use
13
13
 
@@ -20,7 +20,7 @@ For implementation tasks that modify visible UI, this workflow also serves as a
20
20
  3. **Interact**: perform the action (`gesture-tap`, `gesture-swipe`, `keyboard`, `button`, ...); you receive a screenshot automatically.
21
21
  4. **Verify**: check the returned screenshot. If it shows a loading/transitional state, block with `await-ui-element` (expected element `visible`, or a spinner `hidden`) rather than a guessed delay (its result carries the new screenshot and element tree), but only with a selector you can trust (`text`/`identifier`/`role`) that the screen is known to have or that you saw in a prior `describe`; a guessed one just times out. Otherwise use a short fixed wait. Pick evidence by what's being asserted:
22
22
  - **Visual** (layout, spacing, color, typography, image/icon rendering, clipping, overflow, text rendering): prefer `screenshot-diff` against the step 1 baseline: it surfaces pixel-visible changes the auto-screenshot might miss. Fall back to inspecting the auto-screenshot only when a stable baseline isn't available.
23
- - **Structural** (navigation state, element existence, accessibility labels/values, selection, hierarchy, route): verify with `describe`, `debugger-component-tree`, or `native-describe-screen`.
23
+ - **Structural** (navigation state, element existence, accessibility labels/values, selection, hierarchy, route): verify with `describe` or `debugger-component-tree`.
24
24
  - **Runtime / log / network** (console errors, API calls, persistence, timing): verify with `view-network-logs`, `debugger-log-registry`, `debugger-evaluate`, or targeted tests. A `not_connected` result from the debugger tools is not evidence about the app: follow its `guidance`, then re-verify.
25
25
  - **Mixed**: collect evidence for each relevant class.
26
26
  - Report the combined verdict: expected behavior, observed behavior, evidence used, and any blocker for requested visual diffing.