@swmansion/argent 0.32.1-next.18 → 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.
@@ -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);
@@ -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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.32.1-next.18",
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",
@@ -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