@swmansion/argent 0.30.2-next.9 → 0.31.1-next.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.
- package/bin/darwin/simulator-server +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/bin/win32/simulator-server.exe +0 -0
- package/dist/cli-cmds.mjs +25 -8
- package/dist/client.js +22 -5
- package/dist/installer.mjs +2 -1
- package/dist/mcp-server.mjs +83 -22
- package/dist/tool-args.generated.d.ts +2 -0
- package/dist/tool-server.cjs +521 -139
- package/package.json +1 -1
- package/skills/argent-device-interact/references/harmonyos.md +43 -0
- package/skills/argent-native-profiler/SKILL.md +1 -0
- package/skills/argent-react-native-profiler/SKILL.md +2 -0
package/dist/tool-server.cjs
CHANGED
|
@@ -1584,6 +1584,7 @@ var init_failure_codes = __esm({
|
|
|
1584
1584
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
1585
1585
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
1586
1586
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
1587
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
1587
1588
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
1588
1589
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
1589
1590
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -83678,6 +83679,7 @@ __export(adb_exports, {
|
|
|
83678
83679
|
listAndroidDevices: () => listAndroidDevices,
|
|
83679
83680
|
listAvds: () => listAvds,
|
|
83680
83681
|
parseAdbDevices: () => parseAdbDevices,
|
|
83682
|
+
readEmulatorConsoleAvdName: () => readEmulatorConsoleAvdName,
|
|
83681
83683
|
resolveAvdPath: () => resolveAvdPath,
|
|
83682
83684
|
resolveEmulatorOrThrow: () => resolveEmulatorOrThrow,
|
|
83683
83685
|
runAdb: () => runAdb,
|
|
@@ -83845,6 +83847,21 @@ async function readAvdName(serial) {
|
|
|
83845
83847
|
]);
|
|
83846
83848
|
return modern.trim() || legacy.trim() || null;
|
|
83847
83849
|
}
|
|
83850
|
+
async function readEmulatorConsoleAvdName(serial, options = {}) {
|
|
83851
|
+
try {
|
|
83852
|
+
const { stdout } = await runAdb(["-s", serial, "emu", "avd", "name"], {
|
|
83853
|
+
timeoutMs: options.timeoutMs ?? 2e3
|
|
83854
|
+
});
|
|
83855
|
+
const lines = stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
83856
|
+
const name = lines.find((line) => line !== "OK" && !line.startsWith("KO"));
|
|
83857
|
+
if (name && lines.includes("OK")) return { status: "ok", avdName: name };
|
|
83858
|
+
return { status: "unknown" };
|
|
83859
|
+
} catch (err) {
|
|
83860
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
83861
|
+
if (/Connection refused/i.test(message)) return { status: "unreachable" };
|
|
83862
|
+
return { status: "unknown" };
|
|
83863
|
+
}
|
|
83864
|
+
}
|
|
83848
83865
|
async function readRuntimeKind(serial) {
|
|
83849
83866
|
const features = await adbShell(serial, "pm list features", {
|
|
83850
83867
|
timeoutMs: ENRICH_TIMEOUT_MS
|
|
@@ -100944,7 +100961,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
100944
100961
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
100945
100962
|
function readCliVersion() {
|
|
100946
100963
|
if (true) {
|
|
100947
|
-
return "0.
|
|
100964
|
+
return "0.31.1-next.0";
|
|
100948
100965
|
}
|
|
100949
100966
|
return "0.0.0";
|
|
100950
100967
|
}
|
|
@@ -102555,7 +102572,7 @@ var import_node_path8 = __toESM(require("node:path"));
|
|
|
102555
102572
|
var import_semver2 = __toESM(require_semver2());
|
|
102556
102573
|
|
|
102557
102574
|
// ../tool-server/package.json
|
|
102558
|
-
var version2 = "0.
|
|
102575
|
+
var version2 = "0.31.0";
|
|
102559
102576
|
|
|
102560
102577
|
// ../tool-server/src/utils/update-checker.ts
|
|
102561
102578
|
var import_update_core = __toESM(require_dist7());
|
|
@@ -122147,19 +122164,23 @@ async function openMoqClient(udid) {
|
|
|
122147
122164
|
async function openMoqClientFromInfo(info) {
|
|
122148
122165
|
await installNodeWebTransport();
|
|
122149
122166
|
const session = new MoqDeviceSession(await connectMoq(info), { publishPath: PUBLISH_PATH });
|
|
122150
|
-
|
|
122167
|
+
let closed = false;
|
|
122168
|
+
disposeWhenTransportDies(session, () => closed = true);
|
|
122151
122169
|
return {
|
|
122152
|
-
|
|
122170
|
+
// The SDK resolves sends on a closed session, reporting undelivered input as sent.
|
|
122171
|
+
sendControl: (payload) => closed ? Promise.reject(new Error("MoQ session is closed")) : session.sendControl(payload),
|
|
122153
122172
|
async screenshot(opts) {
|
|
122154
122173
|
return Buffer.from(await session.screenshot({ scale: opts?.scale }));
|
|
122155
122174
|
},
|
|
122156
122175
|
async close() {
|
|
122176
|
+
closed = true;
|
|
122157
122177
|
session.close();
|
|
122158
122178
|
}
|
|
122159
122179
|
};
|
|
122160
122180
|
}
|
|
122161
|
-
function disposeWhenTransportDies(session) {
|
|
122181
|
+
function disposeWhenTransportDies(session, onDispose) {
|
|
122162
122182
|
const dispose = () => {
|
|
122183
|
+
onDispose();
|
|
122163
122184
|
try {
|
|
122164
122185
|
session.close();
|
|
122165
122186
|
} catch {
|
|
@@ -122219,6 +122240,52 @@ function settleWithin(p, ms, signal) {
|
|
|
122219
122240
|
// ../tool-server/src/utils/simulator-client.ts
|
|
122220
122241
|
init_external_devices();
|
|
122221
122242
|
|
|
122243
|
+
// ../tool-server/src/utils/profiling-devices.ts
|
|
122244
|
+
var runs = /* @__PURE__ */ new Map();
|
|
122245
|
+
var servers = /* @__PURE__ */ new Map();
|
|
122246
|
+
function trackProfilingRun(deviceId, run2) {
|
|
122247
|
+
let set2 = runs.get(deviceId);
|
|
122248
|
+
if (!set2) {
|
|
122249
|
+
set2 = /* @__PURE__ */ new Set();
|
|
122250
|
+
runs.set(deviceId, set2);
|
|
122251
|
+
}
|
|
122252
|
+
set2.add(run2);
|
|
122253
|
+
syncCaptureOnDemand();
|
|
122254
|
+
}
|
|
122255
|
+
function isProfiling(deviceId) {
|
|
122256
|
+
syncCaptureOnDemand();
|
|
122257
|
+
return runs.has(deviceId);
|
|
122258
|
+
}
|
|
122259
|
+
function syncCaptureOnDemand() {
|
|
122260
|
+
for (const [deviceId, set2] of runs) {
|
|
122261
|
+
for (const run2 of set2) {
|
|
122262
|
+
if (!run2.profilingActive) set2.delete(run2);
|
|
122263
|
+
}
|
|
122264
|
+
if (set2.size === 0) runs.delete(deviceId);
|
|
122265
|
+
}
|
|
122266
|
+
for (const [deviceId, server] of servers) {
|
|
122267
|
+
const profiling = runs.has(deviceId);
|
|
122268
|
+
if (server.onDemand !== profiling) {
|
|
122269
|
+
server.onDemand = profiling;
|
|
122270
|
+
server.send(profiling);
|
|
122271
|
+
}
|
|
122272
|
+
}
|
|
122273
|
+
}
|
|
122274
|
+
function registerCaptureOnDemandSender(deviceId, endpoint, send) {
|
|
122275
|
+
const entry = { endpoint, send, onDemand: false };
|
|
122276
|
+
servers.set(deviceId, entry);
|
|
122277
|
+
syncCaptureOnDemand();
|
|
122278
|
+
return () => {
|
|
122279
|
+
if (servers.get(deviceId) !== entry) return;
|
|
122280
|
+
servers.delete(deviceId);
|
|
122281
|
+
if (entry.onDemand) entry.send(false);
|
|
122282
|
+
};
|
|
122283
|
+
}
|
|
122284
|
+
function captureOnDemandDropped(deviceId, endpoint) {
|
|
122285
|
+
const server = servers.get(deviceId);
|
|
122286
|
+
if (server?.endpoint === endpoint) server.onDemand = false;
|
|
122287
|
+
}
|
|
122288
|
+
|
|
122222
122289
|
// ../tool-server/src/utils/foldable.ts
|
|
122223
122290
|
var import_node_child_process13 = require("node:child_process");
|
|
122224
122291
|
var fs17 = __toESM(require("node:fs"));
|
|
@@ -122461,6 +122528,14 @@ var FIRST_FRAME_POLL_MS = 250;
|
|
|
122461
122528
|
var COMMAND_ACK_TIMEOUT_MS = 5e3;
|
|
122462
122529
|
var connections = /* @__PURE__ */ new Map();
|
|
122463
122530
|
var cmdId = 0;
|
|
122531
|
+
function pendingIdNamedBy(conn, message) {
|
|
122532
|
+
const named = message?.match(/unknown variant `([^`]+)`/)?.[1];
|
|
122533
|
+
if (named === void 0) return void 0;
|
|
122534
|
+
for (const [id, entry] of conn.pending) {
|
|
122535
|
+
if (entry.cmd === named) return id;
|
|
122536
|
+
}
|
|
122537
|
+
return void 0;
|
|
122538
|
+
}
|
|
122464
122539
|
function failAllPending(conn, makeError) {
|
|
122465
122540
|
const entries = [...conn.pending.values()];
|
|
122466
122541
|
conn.pending.clear();
|
|
@@ -122507,7 +122582,7 @@ function getOrCreateConnection(api) {
|
|
|
122507
122582
|
}
|
|
122508
122583
|
if (ack.status !== "ok" && ack.status !== "error") return;
|
|
122509
122584
|
if (ack.id != null && !conn.pending.has(ack.id)) return;
|
|
122510
|
-
const id = ack.id ?? conn.pending.keys().next().value;
|
|
122585
|
+
const id = ack.id ?? pendingIdNamedBy(conn, ack.message) ?? conn.pending.keys().next().value;
|
|
122511
122586
|
if (id == null) return;
|
|
122512
122587
|
const entry = conn.pending.get(id);
|
|
122513
122588
|
if (entry == null) return;
|
|
@@ -122536,6 +122611,7 @@ function getOrCreateConnection(api) {
|
|
|
122536
122611
|
ws.on("close", () => {
|
|
122537
122612
|
connections.delete(key2);
|
|
122538
122613
|
failAllPending(conn, (cmd) => transportError(cmd, key2, "the connection closed"));
|
|
122614
|
+
if (api.deviceId) captureOnDemandDropped(api.deviceId, key2);
|
|
122539
122615
|
});
|
|
122540
122616
|
connections.set(key2, conn);
|
|
122541
122617
|
return conn;
|
|
@@ -123211,6 +123287,19 @@ async function spawnSimulatorServerProcess(udid, subcommand) {
|
|
|
123211
123287
|
}, READY_TIMEOUT_MS);
|
|
123212
123288
|
});
|
|
123213
123289
|
}
|
|
123290
|
+
function withCaptureOnDemand(deviceId, instance) {
|
|
123291
|
+
const unregister = registerCaptureOnDemandSender(deviceId, instance.api.apiUrl, (enabled) => {
|
|
123292
|
+
sendCommand(instance.api, { cmd: "capture_on_demand", enabled }).catch(() => {
|
|
123293
|
+
});
|
|
123294
|
+
});
|
|
123295
|
+
return {
|
|
123296
|
+
...instance,
|
|
123297
|
+
dispose: async () => {
|
|
123298
|
+
unregister();
|
|
123299
|
+
await instance.dispose();
|
|
123300
|
+
}
|
|
123301
|
+
};
|
|
123302
|
+
}
|
|
123214
123303
|
var simulatorServerBlueprint = {
|
|
123215
123304
|
namespace: SIMULATOR_SERVER_NAMESPACE,
|
|
123216
123305
|
getURN(device) {
|
|
@@ -123255,7 +123344,7 @@ var simulatorServerBlueprint = {
|
|
|
123255
123344
|
}
|
|
123256
123345
|
const claim2 = externalClaimForAnyId(device.id);
|
|
123257
123346
|
if (claim2) {
|
|
123258
|
-
return buildAttachedInstance(device, claim2);
|
|
123347
|
+
return withCaptureOnDemand(device.id, await buildAttachedInstance(device, claim2));
|
|
123259
123348
|
}
|
|
123260
123349
|
if (device.platform === "ios-remote") {
|
|
123261
123350
|
return buildRemoteInstance(device);
|
|
@@ -123313,7 +123402,7 @@ var simulatorServerBlueprint = {
|
|
|
123313
123402
|
events
|
|
123314
123403
|
};
|
|
123315
123404
|
await attachFoldableDisplay(instance.api, device);
|
|
123316
|
-
return instance;
|
|
123405
|
+
return withCaptureOnDemand(device.id, instance);
|
|
123317
123406
|
}
|
|
123318
123407
|
};
|
|
123319
123408
|
|
|
@@ -125977,6 +126066,7 @@ Chromium apps are discovered by probing CDP debugging ports (default 9222; exten
|
|
|
125977
126066
|
Booted/ready devices are listed first. Platforms whose CLI is unavailable are silently omitted; an empty result usually means xcode-select, Android platform-tools, <flag:harmonyos>DevEco Studio, </flag:harmonyos>or the Vega SDK is not installed.`,
|
|
125978
126067
|
alwaysLoad: true,
|
|
125979
126068
|
searchHint: "list devices simulators emulators avd serial udid ios android chromium vega <flag:harmonyos>harmony harmonyos </flag:harmonyos>app fire tv session start",
|
|
126069
|
+
readOnly: true,
|
|
125980
126070
|
zodSchema,
|
|
125981
126071
|
services: () => ({}),
|
|
125982
126072
|
async execute(_services, _params) {
|
|
@@ -130727,6 +130817,7 @@ function createHttpApp(registry2, options) {
|
|
|
130727
130817
|
if (def.searchHint) entry.searchHint = renderFlagGated(def.searchHint, isFlagEnabled);
|
|
130728
130818
|
if (def.longRunning) entry.longRunning = true;
|
|
130729
130819
|
if (def.hideFromMcp) entry.hideFromMcp = true;
|
|
130820
|
+
if (def.readOnly) entry.readOnly = true;
|
|
130730
130821
|
const aliases = (def.aliases ?? []).map((alias) => ({
|
|
130731
130822
|
...entry,
|
|
130732
130823
|
name: alias,
|
|
@@ -130974,11 +131065,12 @@ function createHttpApp(registry2, options) {
|
|
|
130974
131065
|
const toolNote = takeToolNote(data);
|
|
130975
131066
|
if (toolNote) notes.push(toolNote);
|
|
130976
131067
|
const notePayload = notes.length > 0 ? { note: notes.join("\n\n") } : {};
|
|
131068
|
+
const profilingPayload = deviceArg && isProfiling(canonicalDeviceId(deviceArg) ?? deviceArg) ? { profiling: true } : {};
|
|
130977
131069
|
if (wantsStream) {
|
|
130978
|
-
writeLine({ event: "result", data, ...notePayload });
|
|
131070
|
+
writeLine({ event: "result", data, ...notePayload, ...profilingPayload });
|
|
130979
131071
|
res.end();
|
|
130980
131072
|
} else {
|
|
130981
|
-
res.json({ data, ...notePayload });
|
|
131073
|
+
res.json({ data, ...notePayload, ...profilingPayload });
|
|
130982
131074
|
}
|
|
130983
131075
|
} catch (err) {
|
|
130984
131076
|
const attribute = (message) => {
|
|
@@ -133830,6 +133922,7 @@ If state is connecting: do NOT restart the app. Launching it is what starts the
|
|
|
133830
133922
|
If state is indeterminate: the process could not be inspected, so restart-app is worth one attempt. If this call still reports it after that restart, do NOT restart the app again: the service is stale rather than the app uninjected, so restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. Remote simulators can never inspect the process, so this is the only unconnected state a running app reaches there.
|
|
133831
133923
|
Returns { status: "init_failed", message, attempts } instead when the simulator's native-devtools environment failed to initialize.
|
|
133832
133924
|
Fails if the simulator server is not running for the given UDID.`,
|
|
133925
|
+
readOnly: true,
|
|
133833
133926
|
zodSchema: zodSchema2,
|
|
133834
133927
|
services: (params) => ({
|
|
133835
133928
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -133987,6 +134080,7 @@ Returns { status: "ok", matches } with matching views including their frames, pr
|
|
|
133987
134080
|
At least one of className, identifier, label, tag, or nativeID must be provided.
|
|
133988
134081
|
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: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
133989
134082
|
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the hierarchy query itself can error or time out.`,
|
|
134083
|
+
readOnly: true,
|
|
133990
134084
|
zodSchema: zodSchema4,
|
|
133991
134085
|
services: (params) => ({
|
|
133992
134086
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -134057,6 +134151,7 @@ Use when you need deep layout debugging, finding views with no accessibility lab
|
|
|
134057
134151
|
Returns { status: "ok", windows, screen } with the full view hierarchy. screen gives the screen size in points on its portrait axes, and the interfaceOrientation of the UI (portrait, portraitUpsideDown, landscapeLeft, landscapeRight). Each screenFrame uses the portrait axes of the screen. Each windowFrame uses the axes of its window, which turn with the UI.
|
|
134058
134152
|
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: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
134059
134153
|
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the hierarchy query itself can error or time out.`,
|
|
134154
|
+
readOnly: true,
|
|
134060
134155
|
zodSchema: zodSchema5,
|
|
134061
134156
|
services: (params) => ({
|
|
134062
134157
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -134126,6 +134221,7 @@ normalized contract.
|
|
|
134126
134221
|
|
|
134127
134222
|
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: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
134128
134223
|
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the screen query itself can error or time out.`,
|
|
134224
|
+
readOnly: true,
|
|
134129
134225
|
zodSchema: zodSchema6,
|
|
134130
134226
|
services: (params) => ({
|
|
134131
134227
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -134208,6 +134304,7 @@ the UI is landscape.
|
|
|
134208
134304
|
|
|
134209
134305
|
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: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
134210
134306
|
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the point query itself can error or time out.`,
|
|
134307
|
+
readOnly: true,
|
|
134211
134308
|
zodSchema: zodSchema7,
|
|
134212
134309
|
services: (params) => ({
|
|
134213
134310
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -134296,6 +134393,7 @@ the UI is landscape.
|
|
|
134296
134393
|
|
|
134297
134394
|
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: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
134298
134395
|
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the point query itself can error or time out.`,
|
|
134396
|
+
readOnly: true,
|
|
134299
134397
|
zodSchema: zodSchema8,
|
|
134300
134398
|
services: (params) => ({
|
|
134301
134399
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -136753,6 +136851,7 @@ var reactProfilerSessionBlueprint = {
|
|
|
136753
136851
|
profileStartWallMs: null,
|
|
136754
136852
|
sessionId: null,
|
|
136755
136853
|
ownerToolServerPid: null,
|
|
136854
|
+
disposed: false,
|
|
136756
136855
|
disposeSession: () => events.emit("terminated")
|
|
136757
136856
|
};
|
|
136758
136857
|
await cdp.send("Profiler.enable").catch(warnOnError("Profiler.enable"));
|
|
@@ -136815,11 +136914,25 @@ var reactProfilerSessionBlueprint = {
|
|
|
136815
136914
|
);
|
|
136816
136915
|
};
|
|
136817
136916
|
cdp.events.on("disconnected", onDisconnected);
|
|
136917
|
+
const onCdpEvent = (method) => {
|
|
136918
|
+
if (method !== "Runtime.executionContextDestroyed" && method !== "Runtime.executionContextsCleared") {
|
|
136919
|
+
return;
|
|
136920
|
+
}
|
|
136921
|
+
if (state3.profilingActive) {
|
|
136922
|
+
state3.profilingActive = false;
|
|
136923
|
+
clearCachedProfilerPaths(state3.port, state3.deviceId);
|
|
136924
|
+
stopSamplerInNextRuntime(cdp);
|
|
136925
|
+
}
|
|
136926
|
+
events.emit("terminated");
|
|
136927
|
+
};
|
|
136928
|
+
cdp.events.on("event", onCdpEvent);
|
|
136818
136929
|
return {
|
|
136819
136930
|
api: state3,
|
|
136820
136931
|
dispose: async () => {
|
|
136932
|
+
state3.disposed = true;
|
|
136821
136933
|
cdp.events.off("scriptParsed", onScriptParsed);
|
|
136822
136934
|
cdp.events.off("disconnected", onDisconnected);
|
|
136935
|
+
cdp.events.off("event", onCdpEvent);
|
|
136823
136936
|
if (state3.profilingActive) {
|
|
136824
136937
|
state3.profilingActive = false;
|
|
136825
136938
|
await cdp.send("Runtime.evaluate", {
|
|
@@ -136834,6 +136947,20 @@ var reactProfilerSessionBlueprint = {
|
|
|
136834
136947
|
};
|
|
136835
136948
|
}
|
|
136836
136949
|
};
|
|
136950
|
+
function stopSamplerInNextRuntime(cdp) {
|
|
136951
|
+
const onEvent = (method) => {
|
|
136952
|
+
if (method !== "Runtime.executionContextCreated") return;
|
|
136953
|
+
disarm();
|
|
136954
|
+
void cdp.send("Profiler.stop").catch(() => {
|
|
136955
|
+
});
|
|
136956
|
+
};
|
|
136957
|
+
const disarm = () => {
|
|
136958
|
+
cdp.events.off("event", onEvent);
|
|
136959
|
+
cdp.events.off("disconnected", disarm);
|
|
136960
|
+
};
|
|
136961
|
+
cdp.events.on("event", onEvent);
|
|
136962
|
+
cdp.events.on("disconnected", disarm);
|
|
136963
|
+
}
|
|
136837
136964
|
var profilerPathsCache = /* @__PURE__ */ new Map();
|
|
136838
136965
|
function cacheKey(port, deviceId) {
|
|
136839
136966
|
return `${port}:${deviceId}`;
|
|
@@ -136849,17 +136976,54 @@ function clearCachedProfilerPaths(port, deviceId) {
|
|
|
136849
136976
|
}
|
|
136850
136977
|
|
|
136851
136978
|
// ../tool-server/src/tools/devices/boot-device.ts
|
|
136852
|
-
var
|
|
136979
|
+
var import_node_child_process28 = require("node:child_process");
|
|
136853
136980
|
var import_node_fs12 = require("node:fs");
|
|
136854
136981
|
var import_promises12 = require("node:fs/promises");
|
|
136855
136982
|
var import_node_os11 = require("node:os");
|
|
136856
136983
|
var import_node_path17 = require("node:path");
|
|
136857
|
-
var
|
|
136984
|
+
var import_node_util21 = require("node:util");
|
|
136858
136985
|
init_zod();
|
|
136859
136986
|
init_src();
|
|
136860
136987
|
init_src2();
|
|
136861
136988
|
init_adb();
|
|
136862
136989
|
|
|
136990
|
+
// ../tool-server/src/utils/emulator-process.ts
|
|
136991
|
+
var import_node_child_process26 = require("node:child_process");
|
|
136992
|
+
var import_node_util20 = require("node:util");
|
|
136993
|
+
var execFileAsync20 = (0, import_node_util20.promisify)(import_node_child_process26.execFile);
|
|
136994
|
+
var EMULATOR_PROCESS_RE = /(?:^|\/)(?:qemu-system-[\w-]+|emulator|emulator64-[\w-]+)\s/;
|
|
136995
|
+
function escapeRegExp(value) {
|
|
136996
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
136997
|
+
}
|
|
136998
|
+
function parseEmulatorPidsForAvd(psOutput, avdName) {
|
|
136999
|
+
const avdArg = new RegExp(`(?:^|\\s)-avd\\s+${escapeRegExp(avdName)}(?:\\s|$)`);
|
|
137000
|
+
const pids = [];
|
|
137001
|
+
for (const line of psOutput.split("\n")) {
|
|
137002
|
+
const m = line.match(/^\s*(\d+)\s+(.*)$/);
|
|
137003
|
+
if (!m) continue;
|
|
137004
|
+
const argv = m[2];
|
|
137005
|
+
if (!EMULATOR_PROCESS_RE.test(argv) || !avdArg.test(argv)) continue;
|
|
137006
|
+
pids.push(parseInt(m[1], 10));
|
|
137007
|
+
}
|
|
137008
|
+
return pids;
|
|
137009
|
+
}
|
|
137010
|
+
async function listEmulatorPidsForAvd(avdName) {
|
|
137011
|
+
if (process.platform === "win32") return [];
|
|
137012
|
+
try {
|
|
137013
|
+
const { stdout } = await execFileAsync20(PS_BIN, [...PS_ARGS_WITH_PID], {
|
|
137014
|
+
timeout: 5e3,
|
|
137015
|
+
maxBuffer: 16 * 1024 * 1024
|
|
137016
|
+
});
|
|
137017
|
+
return parseEmulatorPidsForAvd(stdout, avdName);
|
|
137018
|
+
} catch (err) {
|
|
137019
|
+
process.stderr.write(
|
|
137020
|
+
`[emulator-process] ps probe failed; assuming no emulator runs "${avdName}": ${String(err)}
|
|
137021
|
+
`
|
|
137022
|
+
);
|
|
137023
|
+
return [];
|
|
137024
|
+
}
|
|
137025
|
+
}
|
|
137026
|
+
|
|
136863
137027
|
// ../tool-server/src/utils/linux-preflight.ts
|
|
136864
137028
|
var fs33 = __toESM(require("node:fs"));
|
|
136865
137029
|
var import_node_os10 = require("node:os");
|
|
@@ -136935,6 +137099,9 @@ function iosHeadlessFromEnv() {
|
|
|
136935
137099
|
function androidHeadlessFromEnv() {
|
|
136936
137100
|
return truthyEnv("ARGENT_EMULATOR_NO_WINDOW");
|
|
136937
137101
|
}
|
|
137102
|
+
function androidGuestVulkanFromEnv() {
|
|
137103
|
+
return truthyEnv("ARGENT_EMULATOR_GUEST_VULKAN");
|
|
137104
|
+
}
|
|
136938
137105
|
|
|
136939
137106
|
// ../tool-server/src/tools/devices/boot-device.ts
|
|
136940
137107
|
init_device_info();
|
|
@@ -137342,7 +137509,7 @@ async function harmonyDumpLayout(connectKey, localPath, timeoutMs = UITEST_TIMEO
|
|
|
137342
137509
|
}
|
|
137343
137510
|
|
|
137344
137511
|
// ../tool-server/src/tools/devices/boot-electron.ts
|
|
137345
|
-
var
|
|
137512
|
+
var import_node_child_process27 = require("node:child_process");
|
|
137346
137513
|
var fs34 = __toESM(require("node:fs"));
|
|
137347
137514
|
var path29 = __toESM(require("node:path"));
|
|
137348
137515
|
init_src2();
|
|
@@ -137538,7 +137705,7 @@ async function bootElectronApp(options) {
|
|
|
137538
137705
|
];
|
|
137539
137706
|
let child;
|
|
137540
137707
|
try {
|
|
137541
|
-
child = (0,
|
|
137708
|
+
child = (0, import_node_child_process27.spawn)(launcher.command, args, {
|
|
137542
137709
|
detached: true,
|
|
137543
137710
|
// stdout is discarded, not piped: nothing reads it, and an unread pipe
|
|
137544
137711
|
// blocks the child's writes once the OS buffer fills. The
|
|
@@ -137664,7 +137831,7 @@ async function bootElectronApp(options) {
|
|
|
137664
137831
|
}
|
|
137665
137832
|
|
|
137666
137833
|
// ../tool-server/src/tools/devices/boot-device.ts
|
|
137667
|
-
var
|
|
137834
|
+
var execFileAsync21 = (0, import_node_util21.promisify)(import_node_child_process28.execFile);
|
|
137668
137835
|
var zodSchema9 = external_exports.object({
|
|
137669
137836
|
udid: external_exports.string().optional().describe(
|
|
137670
137837
|
"iOS: simulator UDID to boot (from `list-devices`). Provide exactly one of `udid`, `avdName`, `vvdImage`, <flag:harmonyos>`harmonyInstance`, </flag:harmonyos>or `electronAppPath`."
|
|
@@ -137687,6 +137854,9 @@ var zodSchema9 = external_exports.object({
|
|
|
137687
137854
|
sound: external_exports.boolean().optional().describe(
|
|
137688
137855
|
"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<flag:harmonyos>/HarmonyOS</flag:harmonyos>/Electron, which argent never mutes."
|
|
137689
137856
|
),
|
|
137857
|
+
guestVulkan: external_exports.boolean().optional().describe(
|
|
137858
|
+
"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."
|
|
137859
|
+
),
|
|
137690
137860
|
headless: external_exports.boolean().optional().describe(
|
|
137691
137861
|
"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<flag:harmonyos>/HarmonyOS</flag:harmonyos>/Electron, which have no equivalent GUI step."
|
|
137692
137862
|
),
|
|
@@ -137754,14 +137924,27 @@ function selectGpuMode() {
|
|
|
137754
137924
|
}
|
|
137755
137925
|
return process.platform === "linux" ? "swiftshader" : "auto";
|
|
137756
137926
|
}
|
|
137927
|
+
function guestVulkanArgs(guestVulkan) {
|
|
137928
|
+
if (process.platform !== "darwin") return [];
|
|
137929
|
+
return ["-feature", guestVulkan ? "Vulkan" : "-Vulkan"];
|
|
137930
|
+
}
|
|
137931
|
+
async function runningGuestVulkanNote(serial, guestVulkan) {
|
|
137932
|
+
if (process.platform !== "darwin") return void 0;
|
|
137933
|
+
const prop = await adbShell(serial, "getprop ro.boot.hardware.vulkan", { timeoutMs: 5e3 }).then((out) => out.trim()).catch(() => null);
|
|
137934
|
+
if (prop === null || prop !== "" === guestVulkan) return void 0;
|
|
137935
|
+
return guestVulkan ? "This emulator was already running without guest Vulkan, so apps find no Vulkan device. Pass `force: true` to reboot it with guest Vulkan." : "This emulator was already running with guest Vulkan, which can crash Chrome's GPU process. Pass `force: true` to reboot it without guest Vulkan.";
|
|
137936
|
+
}
|
|
137757
137937
|
var BOOT_POLL_INTERVALS_MS = {
|
|
137758
137938
|
serialByAvd: 1500,
|
|
137759
137939
|
// findSerialByAvdName: re-scan when >1 new emulator appeared
|
|
137760
137940
|
adbRegister: 1e3,
|
|
137761
137941
|
// attemptBoot stage 2: re-scan adb devices for the new serial
|
|
137762
|
-
earlyExit: 500
|
|
137942
|
+
earlyExit: 500,
|
|
137763
137943
|
// createEarlyExitRacer: re-check the crash latch during a blocking adb call
|
|
137944
|
+
serialGone: 500
|
|
137945
|
+
// awaitEmulatorsGone, awaitOwnEmulatorSettled: re-check for a dying emulator
|
|
137764
137946
|
};
|
|
137947
|
+
var EMULATOR_GONE_BUDGET_MS = 3e4;
|
|
137765
137948
|
var FRAME_PROBE = "screencap -p 2>/dev/null | wc -c | awk '$1>20000{print 1;exit} {print 0}'";
|
|
137766
137949
|
async function killEmulatorQuietly(serial, child) {
|
|
137767
137950
|
if (serial) {
|
|
@@ -137841,18 +138024,70 @@ async function findSerialByAvdName(avdName, deadline) {
|
|
|
137841
138024
|
}
|
|
137842
138025
|
return null;
|
|
137843
138026
|
}
|
|
137844
|
-
async function
|
|
138027
|
+
async function listEmulatorSerials() {
|
|
137845
138028
|
const { stdout } = await runAdb(["devices"], { timeoutMs: 3e3 }).catch(() => ({
|
|
137846
138029
|
stdout: "",
|
|
137847
138030
|
stderr: ""
|
|
137848
138031
|
}));
|
|
137849
|
-
const lines = stdout.split("\n");
|
|
137850
138032
|
const now = [];
|
|
137851
|
-
for (const line of
|
|
138033
|
+
for (const line of stdout.split("\n")) {
|
|
137852
138034
|
const m = line.match(/^(emulator-\d+)\s+/);
|
|
137853
138035
|
if (m) now.push(m[1]);
|
|
137854
138036
|
}
|
|
137855
|
-
return now
|
|
138037
|
+
return now;
|
|
138038
|
+
}
|
|
138039
|
+
async function listNewEmulatorSerials(before) {
|
|
138040
|
+
return (await listEmulatorSerials()).filter((s) => !before.has(s));
|
|
138041
|
+
}
|
|
138042
|
+
async function awaitEmulatorsGone(serials) {
|
|
138043
|
+
const deadline = Date.now() + EMULATOR_GONE_BUDGET_MS;
|
|
138044
|
+
while (serials.length > 0 && Date.now() < deadline) {
|
|
138045
|
+
const listed = await listEmulatorSerials();
|
|
138046
|
+
if (!serials.some((s) => listed.includes(s))) return;
|
|
138047
|
+
await new Promise((r) => setTimeout(r, BOOT_POLL_INTERVALS_MS.serialGone));
|
|
138048
|
+
}
|
|
138049
|
+
}
|
|
138050
|
+
function isRunningAvd(device, avdName) {
|
|
138051
|
+
return device.isEmulator && device.avdName === avdName && device.state === "device";
|
|
138052
|
+
}
|
|
138053
|
+
async function awaitOwnEmulatorSettled(avdName, deadline) {
|
|
138054
|
+
let healthy = null;
|
|
138055
|
+
let listing = null;
|
|
138056
|
+
while (Date.now() < deadline) {
|
|
138057
|
+
if (healthy) return healthy;
|
|
138058
|
+
if ((await listEmulatorPidsForAvd(avdName)).length === 0) return null;
|
|
138059
|
+
listing ??= listAndroidDevices().then((devices) => {
|
|
138060
|
+
if (devices.some((d) => isRunningAvd(d, avdName))) healthy = devices;
|
|
138061
|
+
}).catch(() => {
|
|
138062
|
+
}).finally(() => {
|
|
138063
|
+
listing = null;
|
|
138064
|
+
});
|
|
138065
|
+
await new Promise(
|
|
138066
|
+
(r) => setTimeout(r, Math.min(BOOT_POLL_INTERVALS_MS.serialGone, deadline - Date.now()))
|
|
138067
|
+
);
|
|
138068
|
+
}
|
|
138069
|
+
return healthy;
|
|
138070
|
+
}
|
|
138071
|
+
async function dropUnreachableSerials(devices, serialsBefore) {
|
|
138072
|
+
await Promise.all(
|
|
138073
|
+
devices.filter((d) => d.isEmulator && !(d.state === "device" && d.avdName !== null)).map(async (d) => {
|
|
138074
|
+
if ((await readEmulatorConsoleAvdName(d.serial)).status === "unreachable") {
|
|
138075
|
+
serialsBefore.delete(d.serial);
|
|
138076
|
+
}
|
|
138077
|
+
})
|
|
138078
|
+
);
|
|
138079
|
+
}
|
|
138080
|
+
async function pickOwnSerial(avdName, newSerials) {
|
|
138081
|
+
const names = await Promise.all(newSerials.map((s) => readEmulatorConsoleAvdName(s)));
|
|
138082
|
+
const own2 = newSerials.find((_, i) => {
|
|
138083
|
+
const answer = names[i];
|
|
138084
|
+
return answer.status === "ok" && answer.avdName === avdName;
|
|
138085
|
+
});
|
|
138086
|
+
if (own2) return own2;
|
|
138087
|
+
const unnamed = newSerials.filter((_, i) => names[i].status !== "ok");
|
|
138088
|
+
if (unnamed.length === 0) return null;
|
|
138089
|
+
if (unnamed.length === 1) return unnamed[0];
|
|
138090
|
+
return findSerialByAvdName(avdName, Date.now() + 3e3);
|
|
137856
138091
|
}
|
|
137857
138092
|
async function bootIos(udid, registry2, force, headless) {
|
|
137858
138093
|
if (process.platform !== "darwin") {
|
|
@@ -137873,7 +138108,7 @@ async function bootIos(udid, registry2, force, headless) {
|
|
|
137873
138108
|
const deviceSet = await deviceSetForUdid(udid);
|
|
137874
138109
|
const prefix = simctlPrefix(deviceSet);
|
|
137875
138110
|
if (force && simState === "Booted") {
|
|
137876
|
-
await
|
|
138111
|
+
await execFileAsync21("xcrun", [...prefix, "shutdown", udid]);
|
|
137877
138112
|
}
|
|
137878
138113
|
const needsPreBoot = simState === "Shutdown" || force && simState === "Booted";
|
|
137879
138114
|
if (needsPreBoot) {
|
|
@@ -137884,13 +138119,13 @@ async function bootIos(udid, registry2, force, headless) {
|
|
|
137884
138119
|
);
|
|
137885
138120
|
});
|
|
137886
138121
|
}
|
|
137887
|
-
await
|
|
138122
|
+
await execFileAsync21("xcrun", [...prefix, "boot", udid]).catch((err) => {
|
|
137888
138123
|
const message = err instanceof Error ? err.message : String(err);
|
|
137889
138124
|
if (!message.includes("Unable to boot device in current state: Booted")) {
|
|
137890
138125
|
throw err;
|
|
137891
138126
|
}
|
|
137892
138127
|
});
|
|
137893
|
-
await
|
|
138128
|
+
await execFileAsync21("xcrun", [...prefix, "bootstatus", udid, "-b"]);
|
|
137894
138129
|
if (isTvOs && needsPreBoot) {
|
|
137895
138130
|
await registry2.disposeService(`${TV_CONTROL_NAMESPACE}:${udid}`).catch((err) => {
|
|
137896
138131
|
if (err instanceof ServiceNotFoundError) return;
|
|
@@ -137918,7 +138153,7 @@ async function bootIos(udid, registry2, force, headless) {
|
|
|
137918
138153
|
return buildInitFailedResult(udid, initFailure);
|
|
137919
138154
|
}
|
|
137920
138155
|
if (!deviceSet) {
|
|
137921
|
-
await
|
|
138156
|
+
await execFileAsync21("defaults", [
|
|
137922
138157
|
"write",
|
|
137923
138158
|
"com.apple.iphonesimulator",
|
|
137924
138159
|
"CurrentDeviceUDID",
|
|
@@ -137934,17 +138169,17 @@ async function bootIos(udid, registry2, force, headless) {
|
|
|
137934
138169
|
}
|
|
137935
138170
|
async function openSimulatorWindow(udid) {
|
|
137936
138171
|
const timeout = 5e3;
|
|
137937
|
-
const { stdout } = await
|
|
138172
|
+
const { stdout } = await execFileAsync21("xcode-select", ["-p"], { timeout });
|
|
137938
138173
|
const developerDir2 = (0, import_node_fs12.realpathSync)(stdout.trim());
|
|
137939
138174
|
const simulatorApp = (0, import_node_path17.join)(developerDir2, "Applications", "Simulator.app");
|
|
137940
138175
|
if ((0, import_node_fs12.existsSync)(simulatorApp)) {
|
|
137941
|
-
await
|
|
138176
|
+
await execFileAsync21("open", ["-a", simulatorApp], { timeout });
|
|
137942
138177
|
return;
|
|
137943
138178
|
}
|
|
137944
138179
|
const deviceHubApp = (0, import_node_path17.join)(developerDir2, "..", "Applications", "DeviceHub.app");
|
|
137945
138180
|
if ((0, import_node_fs12.existsSync)(deviceHubApp)) {
|
|
137946
138181
|
const url2 = `devices://device/open?id=${encodeURIComponent(udid)}`;
|
|
137947
|
-
await
|
|
138182
|
+
await execFileAsync21("open", ["-a", deviceHubApp, url2], { timeout });
|
|
137948
138183
|
}
|
|
137949
138184
|
}
|
|
137950
138185
|
async function bootIosRemote(id, registry2, force) {
|
|
@@ -137989,7 +138224,7 @@ async function attemptBoot(params) {
|
|
|
137989
138224
|
emulatorLogFd = (0, import_node_fs12.openSync)(logPath, "w");
|
|
137990
138225
|
stdio = ["ignore", emulatorLogFd, emulatorLogFd];
|
|
137991
138226
|
}
|
|
137992
|
-
const child = (0,
|
|
138227
|
+
const child = (0, import_node_child_process28.spawn)(params.emulatorBinary, params.emulatorArgs, {
|
|
137993
138228
|
detached: true,
|
|
137994
138229
|
stdio
|
|
137995
138230
|
});
|
|
@@ -138028,13 +138263,9 @@ async function attemptBoot(params) {
|
|
|
138028
138263
|
if (launchError) throw launchError;
|
|
138029
138264
|
const newSerials = await listNewEmulatorSerials(params.serialsBefore);
|
|
138030
138265
|
if (newSerials.length >= 1) {
|
|
138031
|
-
|
|
138032
|
-
|
|
138033
|
-
|
|
138034
|
-
}
|
|
138035
|
-
const byAvd = await findSerialByAvdName(params.avdName, Date.now() + 3e3);
|
|
138036
|
-
if (byAvd) {
|
|
138037
|
-
serial = byAvd;
|
|
138266
|
+
const own2 = await pickOwnSerial(params.avdName, newSerials);
|
|
138267
|
+
if (own2) {
|
|
138268
|
+
serial = own2;
|
|
138038
138269
|
break;
|
|
138039
138270
|
}
|
|
138040
138271
|
}
|
|
@@ -138152,7 +138383,10 @@ async function bootAndroidImpl(params) {
|
|
|
138152
138383
|
await ensureDep("adb");
|
|
138153
138384
|
await ensureDep("emulator");
|
|
138154
138385
|
const gpuMode = selectGpuMode();
|
|
138155
|
-
const extraEmulatorArgs =
|
|
138386
|
+
const extraEmulatorArgs = [
|
|
138387
|
+
...androidHeadlessFromEnv() ? ["-no-window"] : [],
|
|
138388
|
+
...guestVulkanArgs(params.guestVulkan)
|
|
138389
|
+
];
|
|
138156
138390
|
const hardeningArgs = launchHardeningArgs(params.sound);
|
|
138157
138391
|
for (const msg of linuxBootDiagnostics(params.avdName) ?? []) {
|
|
138158
138392
|
console.warn(`[boot-device:linux] ${msg}`);
|
|
@@ -138200,31 +138434,42 @@ async function bootAndroidImpl(params) {
|
|
|
138200
138434
|
await runAdb(["start-server"], { timeoutMs: 1e4 }).catch(() => {
|
|
138201
138435
|
});
|
|
138202
138436
|
const existingDevices = await listAndroidDevices().catch(() => []);
|
|
138437
|
+
if (!existingDevices.some((d) => isRunningAvd(d, params.avdName))) {
|
|
138438
|
+
const settled = await awaitOwnEmulatorSettled(
|
|
138439
|
+
params.avdName,
|
|
138440
|
+
Math.min(overallDeadline, Date.now() + EMULATOR_GONE_BUDGET_MS)
|
|
138441
|
+
);
|
|
138442
|
+
if (settled) existingDevices.splice(0, existingDevices.length, ...settled);
|
|
138443
|
+
}
|
|
138203
138444
|
let hotBootFailureReason;
|
|
138204
|
-
const
|
|
138205
|
-
(
|
|
138206
|
-
|
|
138445
|
+
const dropKilledEmulator = async (serial) => {
|
|
138446
|
+
await awaitEmulatorsGone([serial]);
|
|
138447
|
+
const refreshed = await listAndroidDevices().catch(() => existingDevices);
|
|
138448
|
+
existingDevices.splice(0, existingDevices.length, ...refreshed);
|
|
138449
|
+
};
|
|
138450
|
+
const alreadyRunning = existingDevices.find((d) => isRunningAvd(d, params.avdName));
|
|
138207
138451
|
if (alreadyRunning) {
|
|
138208
138452
|
if (params.force) {
|
|
138209
138453
|
await killEmulatorQuietly(alreadyRunning.serial);
|
|
138210
|
-
|
|
138211
|
-
existingDevices.splice(0, existingDevices.length, ...refreshed);
|
|
138454
|
+
await dropKilledEmulator(alreadyRunning.serial);
|
|
138212
138455
|
} else {
|
|
138213
138456
|
try {
|
|
138214
138457
|
await assertScreencapAlive(alreadyRunning.serial);
|
|
138458
|
+
const note = await runningGuestVulkanNote(alreadyRunning.serial, params.guestVulkan);
|
|
138215
138459
|
return {
|
|
138216
138460
|
platform: "android",
|
|
138217
138461
|
serial: alreadyRunning.serial,
|
|
138218
138462
|
avdName: params.avdName,
|
|
138219
|
-
booted: true
|
|
138463
|
+
booted: true,
|
|
138464
|
+
...note ? { note } : {}
|
|
138220
138465
|
};
|
|
138221
138466
|
} catch (_err) {
|
|
138222
|
-
|
|
138223
|
-
existingDevices.splice(0, existingDevices.length, ...refreshed);
|
|
138467
|
+
await dropKilledEmulator(alreadyRunning.serial);
|
|
138224
138468
|
}
|
|
138225
138469
|
}
|
|
138226
138470
|
}
|
|
138227
138471
|
const serialsBefore = new Set(existingDevices.map((d) => d.serial));
|
|
138472
|
+
await dropUnreachableSerials(existingDevices, serialsBefore);
|
|
138228
138473
|
const crashReportArgs = await emulatorSupportsFlag("-crash-report-mode") ? ["-crash-report-mode", "never"] : [];
|
|
138229
138474
|
const hasSnapshot = await hasDefaultBootSnapshot(params.avdName);
|
|
138230
138475
|
if (!hasSnapshot) {
|
|
@@ -138273,6 +138518,7 @@ async function bootAndroidImpl(params) {
|
|
|
138273
138518
|
};
|
|
138274
138519
|
} catch (err) {
|
|
138275
138520
|
hotBootFailureReason = err instanceof Error ? err.message : String(err);
|
|
138521
|
+
await awaitEmulatorsGone(await listNewEmulatorSerials(serialsBefore));
|
|
138276
138522
|
const refreshed = new Set(
|
|
138277
138523
|
(await listAndroidDevices().catch(() => [])).map((d) => d.serial)
|
|
138278
138524
|
);
|
|
@@ -138522,7 +138768,7 @@ async function startHarmonyEmulator(instanceName) {
|
|
|
138522
138768
|
} catch {
|
|
138523
138769
|
logFd = null;
|
|
138524
138770
|
}
|
|
138525
|
-
const child = (0,
|
|
138771
|
+
const child = (0, import_node_child_process28.spawn)(bin, ["-start", instanceName], {
|
|
138526
138772
|
detached: true,
|
|
138527
138773
|
stdio: logFd === null ? "ignore" : ["ignore", logFd, logFd]
|
|
138528
138774
|
});
|
|
@@ -138838,7 +139084,7 @@ function createBootDeviceTool(registry2) {
|
|
|
138838
139084
|
description: `Start an iOS simulator, launch an Android emulator, start a Vega (Fire TV) Virtual Device, <flag:harmonyos>start a HarmonyOS emulator, </flag:harmonyos>or spawn an Electron app and wait until it is ready to accept interactions.
|
|
138839
139085
|
Pick the platform by which argument you pass: 'udid' for an iOS simulator from list-devices, 'avdName' for an Android AVD (a serial is assigned automatically), 'vvdImage' for a Vega VVD (the 'vvdImage' of a vega device from list-devices, e.g. 'tv'), <flag:harmonyos>'harmonyInstance' for a HarmonyOS emulator instance (the 'name' of a harmony device from list-devices), </flag:harmonyos>or 'electronAppPath' for an Electron app (a CDP remote-debugging port is picked automatically, or pass 'electronPort' to fix one).
|
|
138840
139086
|
Use at the start of a session once you have picked a target.
|
|
138841
|
-
Returns a tagged payload: { platform: 'ios', udid, booted } or { platform: 'android', serial, avdName, booted } or { platform: 'vega', serial, vvdImage, booted } or <flag:harmonyos>{ platform: 'harmony', udid, instanceName, booted, note? } or </flag:harmonyos>{ platform: 'chromium', id, port, pid, booted } (an Electron app boots as a Chromium/CDP device).
|
|
139087
|
+
Returns a tagged payload: { platform: 'ios', udid, booted } or { platform: 'android', serial, avdName, booted, note? } or { platform: 'vega', serial, vvdImage, booted } or <flag:harmonyos>{ platform: 'harmony', udid, instanceName, booted, note? } or </flag:harmonyos>{ platform: 'chromium', id, port, pid, booted } (an Electron app boots as a Chromium/CDP device).
|
|
138842
139088
|
Android boots take 2\u201310 minutes depending on machine and cold/warm state; the tool transparently hot-boots from the AVD's default_boot snapshot when usable and falls back to cold boot otherwise. Vega starts the single SDK-managed VVD via the vega CLI (~10s) and returns once it reports running. If an Android/Electron boot stage fails, the tool terminates the device it spawned so the next retry starts clean.<flag:harmonyos>
|
|
138843
139089
|
HarmonyOS hands the instance to DevEco Studio's Emulator manager, then waits for it to register with 'hdc' and returns its connect key as 'udid', the id the interaction tools drive. The manager itself reports no readiness signal and never names a port, so an instance that is already running is left alone unless you pass 'force: true'; when the key could not be resolved the payload names the instance instead, and a 'note' is present whenever the boot left something unproven: no key and why, or a key that is not yet answering or could not be checked against the instance. Huawei serves the emulator images only within mainland China, so a host outside it usually has no instance to start; one that already has an image is started like any other.</flag:harmonyos>`,
|
|
138844
139090
|
alwaysLoad: true,
|
|
@@ -138901,7 +139147,8 @@ HarmonyOS hands the instance to DevEco Studio's Emulator manager, then waits for
|
|
|
138901
139147
|
// An explicit argument always wins; the `boot-sound` flag only moves
|
|
138902
139148
|
// the default when the caller left `sound` unset. Read live per call
|
|
138903
139149
|
// so `argent enable/disable boot-sound` applies without a restart.
|
|
138904
|
-
sound: params.sound ?? isFlagEnabled("boot-sound")
|
|
139150
|
+
sound: params.sound ?? isFlagEnabled("boot-sound"),
|
|
139151
|
+
guestVulkan: params.guestVulkan ?? androidGuestVulkanFromEnv()
|
|
138905
139152
|
});
|
|
138906
139153
|
}
|
|
138907
139154
|
if (hasVega) {
|
|
@@ -139037,11 +139284,11 @@ var BUNDLE_ID_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
|
|
|
139037
139284
|
var BUNDLE_ID_MESSAGE = "bundleId may only contain letters, digits, '.', '_' and '-', and may not start with '-' or '.'";
|
|
139038
139285
|
|
|
139039
139286
|
// ../tool-server/src/tools/launch-app/platforms/ios.ts
|
|
139040
|
-
var
|
|
139041
|
-
var
|
|
139287
|
+
var import_node_child_process29 = require("node:child_process");
|
|
139288
|
+
var import_node_util22 = require("node:util");
|
|
139042
139289
|
init_src2();
|
|
139043
139290
|
init_external_devices();
|
|
139044
|
-
var
|
|
139291
|
+
var execFileAsync22 = (0, import_node_util22.promisify)(import_node_child_process29.execFile);
|
|
139045
139292
|
function makeIosImpl(registry2) {
|
|
139046
139293
|
return {
|
|
139047
139294
|
requires: ["xcrun"],
|
|
@@ -139057,7 +139304,7 @@ function makeIosImpl(registry2) {
|
|
|
139057
139304
|
}
|
|
139058
139305
|
if (params.launchArgs?.length) {
|
|
139059
139306
|
try {
|
|
139060
|
-
await
|
|
139307
|
+
await execFileAsync22(
|
|
139061
139308
|
"xcrun",
|
|
139062
139309
|
await simctlArgsForUdid(params.udid, ["terminate", params.udid, params.bundleId])
|
|
139063
139310
|
);
|
|
@@ -139065,7 +139312,7 @@ function makeIosImpl(registry2) {
|
|
|
139065
139312
|
}
|
|
139066
139313
|
}
|
|
139067
139314
|
try {
|
|
139068
|
-
await
|
|
139315
|
+
await execFileAsync22(
|
|
139069
139316
|
"xcrun",
|
|
139070
139317
|
await simctlArgsForUdid(params.udid, [
|
|
139071
139318
|
"launch",
|
|
@@ -139534,11 +139781,11 @@ init_zod();
|
|
|
139534
139781
|
init_device_info();
|
|
139535
139782
|
|
|
139536
139783
|
// ../tool-server/src/tools/restart-app/platforms/ios.ts
|
|
139537
|
-
var
|
|
139538
|
-
var
|
|
139784
|
+
var import_node_child_process30 = require("node:child_process");
|
|
139785
|
+
var import_node_util23 = require("node:util");
|
|
139539
139786
|
init_src2();
|
|
139540
139787
|
init_external_devices();
|
|
139541
|
-
var
|
|
139788
|
+
var execFileAsync23 = (0, import_node_util23.promisify)(import_node_child_process30.execFile);
|
|
139542
139789
|
function makeIosImpl2(registry2) {
|
|
139543
139790
|
return {
|
|
139544
139791
|
requires: ["xcrun"],
|
|
@@ -139554,11 +139801,11 @@ function makeIosImpl2(registry2) {
|
|
|
139554
139801
|
if (blocked) return blocked;
|
|
139555
139802
|
}
|
|
139556
139803
|
try {
|
|
139557
|
-
await
|
|
139804
|
+
await execFileAsync23("xcrun", await simctlArgsForUdid(udid, ["terminate", udid, bundleId]));
|
|
139558
139805
|
} catch {
|
|
139559
139806
|
}
|
|
139560
139807
|
try {
|
|
139561
|
-
await
|
|
139808
|
+
await execFileAsync23(
|
|
139562
139809
|
"xcrun",
|
|
139563
139810
|
await simctlArgsForUdid(udid, ["launch", udid, bundleId, ...params.launchArgs ?? []])
|
|
139564
139811
|
);
|
|
@@ -139761,11 +140008,11 @@ Returns { restarted, bundleId }. Fails if the app is not installed.`,
|
|
|
139761
140008
|
}
|
|
139762
140009
|
|
|
139763
140010
|
// ../tool-server/src/tools/terminate-app/index.ts
|
|
139764
|
-
var
|
|
139765
|
-
var
|
|
140011
|
+
var import_node_child_process31 = require("node:child_process");
|
|
140012
|
+
var import_node_util24 = require("node:util");
|
|
139766
140013
|
init_zod();
|
|
139767
140014
|
init_adb();
|
|
139768
|
-
var
|
|
140015
|
+
var execFileAsync24 = (0, import_node_util24.promisify)(import_node_child_process31.execFile);
|
|
139769
140016
|
var zodSchema12 = external_exports.object({
|
|
139770
140017
|
udid: external_exports.string().min(1).describe("Target device id from `list-devices`."),
|
|
139771
140018
|
bundleId: external_exports.string().min(1).regex(BUNDLE_ID_PATTERN, BUNDLE_ID_MESSAGE).describe("App identifier. iOS: bundle id. Android: package name.")
|
|
@@ -139808,7 +140055,7 @@ Succeeds when the app is not running or not installed.`,
|
|
|
139808
140055
|
requires: ["xcrun"],
|
|
139809
140056
|
handler: async (_services, { udid, bundleId }) => {
|
|
139810
140057
|
const args = await simctlArgsForUdid(udid, ["terminate", udid, bundleId]);
|
|
139811
|
-
const terminated = await tolerateNotRunning(
|
|
140058
|
+
const terminated = await tolerateNotRunning(execFileAsync24("xcrun", args));
|
|
139812
140059
|
return { terminated, bundleId };
|
|
139813
140060
|
}
|
|
139814
140061
|
},
|
|
@@ -139840,16 +140087,16 @@ Succeeds when the app is not running or not installed.`,
|
|
|
139840
140087
|
init_zod();
|
|
139841
140088
|
|
|
139842
140089
|
// ../tool-server/src/tools/reinstall-app/platforms/ios.ts
|
|
139843
|
-
var
|
|
139844
|
-
var
|
|
140090
|
+
var import_node_child_process33 = require("node:child_process");
|
|
140091
|
+
var import_node_util26 = require("node:util");
|
|
139845
140092
|
var import_node_path19 = require("node:path");
|
|
139846
140093
|
init_src2();
|
|
139847
140094
|
|
|
139848
140095
|
// ../tool-server/src/tools/reinstall-app/validate-app.ts
|
|
139849
|
-
var
|
|
140096
|
+
var import_node_child_process32 = require("node:child_process");
|
|
139850
140097
|
var import_promises14 = require("node:fs/promises");
|
|
139851
140098
|
var import_node_path18 = require("node:path");
|
|
139852
|
-
var
|
|
140099
|
+
var import_node_util25 = require("node:util");
|
|
139853
140100
|
init_capability();
|
|
139854
140101
|
|
|
139855
140102
|
// ../tool-server/src/utils/apk-package.ts
|
|
@@ -139948,7 +140195,7 @@ function readStringPool(xml, chunk) {
|
|
|
139948
140195
|
}
|
|
139949
140196
|
|
|
139950
140197
|
// ../tool-server/src/tools/reinstall-app/validate-app.ts
|
|
139951
|
-
var
|
|
140198
|
+
var execFileAsync25 = (0, import_node_util25.promisify)(import_node_child_process32.execFile);
|
|
139952
140199
|
async function requirePath(absolute, kind, what) {
|
|
139953
140200
|
const info = await (0, import_promises14.stat)(absolute).catch(() => null);
|
|
139954
140201
|
if (!info) {
|
|
@@ -139972,7 +140219,7 @@ async function assertIosAppBundle(absolute, bundleId, { readBundleId = true } =
|
|
|
139972
140219
|
);
|
|
139973
140220
|
}
|
|
139974
140221
|
if (!readBundleId) return;
|
|
139975
|
-
const actual = await
|
|
140222
|
+
const actual = await execFileAsync25("plutil", [
|
|
139976
140223
|
"-extract",
|
|
139977
140224
|
"CFBundleIdentifier",
|
|
139978
140225
|
"raw",
|
|
@@ -140025,7 +140272,7 @@ async function assertHap(absolute, bundleName) {
|
|
|
140025
140272
|
}
|
|
140026
140273
|
|
|
140027
140274
|
// ../tool-server/src/tools/reinstall-app/platforms/ios.ts
|
|
140028
|
-
var
|
|
140275
|
+
var execFileAsync26 = (0, import_node_util26.promisify)(import_node_child_process33.execFile);
|
|
140029
140276
|
var iosImpl = {
|
|
140030
140277
|
requires: ["xcrun"],
|
|
140031
140278
|
handler: async (_services, params) => {
|
|
@@ -140034,11 +140281,11 @@ var iosImpl = {
|
|
|
140034
140281
|
await assertIosAppBundle(absolute, bundleId);
|
|
140035
140282
|
const { nativeId, prefix } = await simctlTargetForUdid(udid);
|
|
140036
140283
|
try {
|
|
140037
|
-
await
|
|
140284
|
+
await execFileAsync26("xcrun", [...prefix, "uninstall", nativeId, bundleId]);
|
|
140038
140285
|
} catch {
|
|
140039
140286
|
}
|
|
140040
140287
|
try {
|
|
140041
|
-
await
|
|
140288
|
+
await execFileAsync26("xcrun", [...prefix, "install", nativeId, absolute]);
|
|
140042
140289
|
} catch (err) {
|
|
140043
140290
|
throw new FailureError(
|
|
140044
140291
|
`Failed to install iOS app bundle on ${udid}.`,
|
|
@@ -140265,11 +140512,11 @@ var PERMISSION_NAMES = [
|
|
|
140265
140512
|
];
|
|
140266
140513
|
|
|
140267
140514
|
// ../tool-server/src/tools/settings-permissions/platforms/ios.ts
|
|
140268
|
-
var
|
|
140269
|
-
var
|
|
140515
|
+
var import_node_child_process34 = require("node:child_process");
|
|
140516
|
+
var import_node_util27 = require("node:util");
|
|
140270
140517
|
init_src2();
|
|
140271
140518
|
init_capability();
|
|
140272
|
-
var
|
|
140519
|
+
var execFileAsync27 = (0, import_node_util27.promisify)(import_node_child_process34.execFile);
|
|
140273
140520
|
var SIMCTL_ACTION = {
|
|
140274
140521
|
grant: "grant",
|
|
140275
140522
|
deny: "revoke",
|
|
@@ -140294,7 +140541,7 @@ var NON_TCC_GRANT_NEEDS_INSTALL = /* @__PURE__ */ new Set([
|
|
|
140294
140541
|
]);
|
|
140295
140542
|
var localBackend = {
|
|
140296
140543
|
async run(udid, simctlAction, service, bundleId) {
|
|
140297
|
-
await
|
|
140544
|
+
await execFileAsync27(
|
|
140298
140545
|
"xcrun",
|
|
140299
140546
|
await simctlArgsForUdid(udid, ["privacy", udid, simctlAction, service, bundleId]),
|
|
140300
140547
|
{ timeout: 3e4 }
|
|
@@ -140302,7 +140549,7 @@ var localBackend = {
|
|
|
140302
140549
|
},
|
|
140303
140550
|
async isInstalled(udid, bundleId) {
|
|
140304
140551
|
try {
|
|
140305
|
-
await
|
|
140552
|
+
await execFileAsync27(
|
|
140306
140553
|
"xcrun",
|
|
140307
140554
|
await simctlArgsForUdid(udid, ["get_app_container", udid, bundleId]),
|
|
140308
140555
|
{ timeout: 15e3 }
|
|
@@ -140586,8 +140833,8 @@ init_zod();
|
|
|
140586
140833
|
init_device_info();
|
|
140587
140834
|
|
|
140588
140835
|
// ../tool-server/src/tools/open-url/platforms/ios.ts
|
|
140589
|
-
var
|
|
140590
|
-
var
|
|
140836
|
+
var import_node_child_process35 = require("node:child_process");
|
|
140837
|
+
var import_node_util28 = require("node:util");
|
|
140591
140838
|
init_src2();
|
|
140592
140839
|
|
|
140593
140840
|
// ../tool-server/src/tools/open-url/deep-link-note.ts
|
|
@@ -140597,12 +140844,12 @@ function httpDeepLinkNote(url2) {
|
|
|
140597
140844
|
}
|
|
140598
140845
|
|
|
140599
140846
|
// ../tool-server/src/tools/open-url/platforms/ios.ts
|
|
140600
|
-
var
|
|
140847
|
+
var execFileAsync28 = (0, import_node_util28.promisify)(import_node_child_process35.execFile);
|
|
140601
140848
|
var iosImpl3 = {
|
|
140602
140849
|
requires: ["xcrun"],
|
|
140603
140850
|
handler: async (_services, params) => {
|
|
140604
140851
|
try {
|
|
140605
|
-
await
|
|
140852
|
+
await execFileAsync28(
|
|
140606
140853
|
"xcrun",
|
|
140607
140854
|
await simctlArgsForUdid(params.udid, ["openurl", params.udid, params.url])
|
|
140608
140855
|
);
|
|
@@ -140779,8 +141026,8 @@ Returns { opened, url, note? }. note carries the deep-linking caveat when a web
|
|
|
140779
141026
|
};
|
|
140780
141027
|
|
|
140781
141028
|
// ../tool-server/src/tools/screenshot/index.ts
|
|
140782
|
-
var
|
|
140783
|
-
var
|
|
141029
|
+
var import_node_child_process36 = require("node:child_process");
|
|
141030
|
+
var import_node_util29 = require("node:util");
|
|
140784
141031
|
var os13 = __toESM(require("node:os"));
|
|
140785
141032
|
var path30 = __toESM(require("node:path"));
|
|
140786
141033
|
init_zod();
|
|
@@ -141405,7 +141652,7 @@ async function captureHarmonyScreenshotPng(opts) {
|
|
|
141405
141652
|
// ../tool-server/src/tools/screenshot/index.ts
|
|
141406
141653
|
init_capability();
|
|
141407
141654
|
var fs36 = __toESM(require("node:fs/promises"));
|
|
141408
|
-
var
|
|
141655
|
+
var execFileAsync29 = (0, import_node_util29.promisify)(import_node_child_process36.execFile);
|
|
141409
141656
|
var zodSchema16 = external_exports.object({
|
|
141410
141657
|
udid: external_exports.string().describe(
|
|
141411
141658
|
"Target device id from `list-devices` (iOS UDID, Android serial, Apple TV UDID, Vega serial, <flag:harmonyos>HarmonyOS id, </flag:harmonyos>or Chromium id)."
|
|
@@ -141447,11 +141694,11 @@ async function tvScreenshot(udid, scale, signal) {
|
|
|
141447
141694
|
os13.tmpdir(),
|
|
141448
141695
|
`argent-tv-screenshot-${udid.slice(0, 8)}-${process.hrtime.bigint()}.png`
|
|
141449
141696
|
);
|
|
141450
|
-
await
|
|
141697
|
+
await execFileAsync29("xcrun", await simctlArgsForUdid(udid, ["io", udid, "screenshot", file2]), {
|
|
141451
141698
|
signal
|
|
141452
141699
|
});
|
|
141453
141700
|
if (scale === void 0 || scale < 1) {
|
|
141454
|
-
await
|
|
141701
|
+
await execFileAsync29("sips", ["-Z", String(await tvTargetLongSide(file2, scale)), file2], {
|
|
141455
141702
|
signal
|
|
141456
141703
|
}).catch(() => {
|
|
141457
141704
|
});
|
|
@@ -141461,7 +141708,7 @@ async function tvScreenshot(udid, scale, signal) {
|
|
|
141461
141708
|
async function tvTargetLongSide(file2, scale) {
|
|
141462
141709
|
let longSide = 3840;
|
|
141463
141710
|
try {
|
|
141464
|
-
const { stdout } = await
|
|
141711
|
+
const { stdout } = await execFileAsync29("sips", ["-g", "pixelWidth", "-g", "pixelHeight", file2]);
|
|
141465
141712
|
const width = Number(/pixelWidth:\s*(\d+)/.exec(stdout)?.[1]);
|
|
141466
141713
|
const height = Number(/pixelHeight:\s*(\d+)/.exec(stdout)?.[1]);
|
|
141467
141714
|
if (Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0) {
|
|
@@ -141496,7 +141743,7 @@ async function downscalePngInPlace(file2, scale, signal) {
|
|
|
141496
141743
|
if (scale >= 1) {
|
|
141497
141744
|
return;
|
|
141498
141745
|
}
|
|
141499
|
-
await
|
|
141746
|
+
await execFileAsync29("sips", ["-Z", String(await tvTargetLongSide(file2, scale)), file2], {
|
|
141500
141747
|
signal
|
|
141501
141748
|
}).catch(() => {
|
|
141502
141749
|
});
|
|
@@ -141514,6 +141761,7 @@ Use when you need a baseline image before an interaction or to inspect the curre
|
|
|
141514
141761
|
Fails if the simulator-server / emulator backend / Chromium CDP <flag:harmonyos>/ \`hdc\` </flag:harmonyos>is not reachable for the given device.`,
|
|
141515
141762
|
alwaysLoad: true,
|
|
141516
141763
|
searchHint: "device simulator emulator chromium screen image capture baseline tvos apple tv",
|
|
141764
|
+
readOnly: true,
|
|
141517
141765
|
zodSchema: zodSchema16,
|
|
141518
141766
|
outputHint: "image",
|
|
141519
141767
|
capability: capability8,
|
|
@@ -143840,13 +144088,13 @@ var shakeZodSchema = external_exports.object({
|
|
|
143840
144088
|
});
|
|
143841
144089
|
|
|
143842
144090
|
// ../tool-server/src/tools/shake/platforms/ios.ts
|
|
143843
|
-
var
|
|
143844
|
-
var
|
|
144091
|
+
var import_node_child_process38 = require("node:child_process");
|
|
144092
|
+
var import_node_util30 = require("node:util");
|
|
143845
144093
|
init_src2();
|
|
143846
144094
|
init_capability();
|
|
143847
144095
|
|
|
143848
144096
|
// ../tool-server/src/utils/window-shake.ts
|
|
143849
|
-
var
|
|
144097
|
+
var import_node_child_process37 = require("node:child_process");
|
|
143850
144098
|
init_src();
|
|
143851
144099
|
var MICROINTERACTIONS_FLAG = "microinteractions";
|
|
143852
144100
|
var AMPLITUDE = 22;
|
|
@@ -143953,7 +144201,7 @@ end run
|
|
|
143953
144201
|
}
|
|
143954
144202
|
function runOsascript(script) {
|
|
143955
144203
|
return new Promise((resolve16, reject) => {
|
|
143956
|
-
const child = (0,
|
|
144204
|
+
const child = (0, import_node_child_process37.execFile)(
|
|
143957
144205
|
"/usr/bin/osascript",
|
|
143958
144206
|
["-"],
|
|
143959
144207
|
{ timeout: OSASCRIPT_TIMEOUT_MS },
|
|
@@ -144046,7 +144294,7 @@ async function prepareHostWindowShake(target) {
|
|
|
144046
144294
|
}
|
|
144047
144295
|
|
|
144048
144296
|
// ../tool-server/src/tools/shake/platforms/ios.ts
|
|
144049
|
-
var
|
|
144297
|
+
var execFileAsync30 = (0, import_node_util30.promisify)(import_node_child_process38.execFile);
|
|
144050
144298
|
var SHAKE_NOTIFICATION = "com.apple.UIKit.SimulatorShake";
|
|
144051
144299
|
var SHAKE_INTERVAL_MS = 400;
|
|
144052
144300
|
var sleep11 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -144088,7 +144336,7 @@ var iosImpl4 = {
|
|
|
144088
144336
|
if (i > 0) await sleep11(SHAKE_INTERVAL_MS);
|
|
144089
144337
|
shaker.begin();
|
|
144090
144338
|
try {
|
|
144091
|
-
await
|
|
144339
|
+
await execFileAsync30("xcrun", args, { timeout: 15e3 });
|
|
144092
144340
|
} catch (err) {
|
|
144093
144341
|
const error63 = err instanceof Error ? err : new Error(String(err));
|
|
144094
144342
|
throw shakeFailure(udid, error63.message, error63);
|
|
@@ -150783,6 +151031,7 @@ after a tap/navigation to wait for the next screen, or before tapping an element
|
|
|
150783
151031
|
alwaysLoad: true,
|
|
150784
151032
|
searchHint: "wait await poll until visible hidden exists text appears disappears timeout element condition settle",
|
|
150785
151033
|
longRunning: true,
|
|
151034
|
+
readOnly: true,
|
|
150786
151035
|
zodSchema: zodSchema29,
|
|
150787
151036
|
capability: capability23,
|
|
150788
151037
|
services: (params) => {
|
|
@@ -151214,6 +151463,7 @@ function createDebuggerStatusTool(registry2) {
|
|
|
151214
151463
|
Use when you need to verify connectivity before using other debugger tools. Never fails when the runtime is simply unreachable: it returns a discriminated result instead:
|
|
151215
151464
|
- { status: "connected", ... } with port, projectRoot (empty on Chromium and on legacy Metro, e.g. Vega), deviceName, appName, logicalDeviceId (absent on Vega), isNewDebugger (false on the legacy inspector), connected flag, loadedScripts count, and sourceMapReady (always true: waits for pending source maps before returning; no-op on Chromium).
|
|
151216
151465
|
- { status: "not_connected", connected: false, reason, detail, guidance } (port omitted on Chromium) when Metro is not running (reason "metro_not_running"), no app is attached ("no_app_connected"), the device_id matches no target ("device_mismatch"), the CDP endpoint is unreachable or answered malformed ("cdp_unreachable"), the runtime accepted the connection but never answered ("runtime_unresponsive"), the cached connection went stale ("stale_connection"), or a reconnect is in flight ("reconnecting"). Follow the guidance field; do not retry in a loop.`,
|
|
151466
|
+
readOnly: true,
|
|
151217
151467
|
zodSchema: zodSchema32,
|
|
151218
151468
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
151219
151469
|
// Resolved manually in execute so a not-connected precondition becomes a
|
|
@@ -152325,6 +152575,7 @@ Set includeSkipped=true to see a summary of all filtered components.
|
|
|
152325
152575
|
Use when you need tap coordinates for a React Native UI element. Returns a compact text tree with (tap: x,y) coords. Fails if Metro debugger is not connected.`,
|
|
152326
152576
|
alwaysLoad: true,
|
|
152327
152577
|
searchHint: "react native component tree discovery tap coordinates",
|
|
152578
|
+
readOnly: true,
|
|
152328
152579
|
zodSchema: zodSchema35,
|
|
152329
152580
|
// RN-only: needs the React DevTools backend from the dev JS bundle. Chromium has
|
|
152330
152581
|
// no equivalent — use `describe` there.
|
|
@@ -152841,6 +153092,7 @@ Uses getInspectorDataForViewAtPoint + _debugStack + Metro /symbolicate.
|
|
|
152841
153092
|
Set resolveSourceMaps to false to skip symbolication and get raw bundled locations instead.
|
|
152842
153093
|
Set includeSkipped=true to see filtered items annotated with skip reasons.
|
|
152843
153094
|
Use when you need the source file and line for a component at a tap coordinate. Fails if the app is not connected or the coordinate is outside the screen.`,
|
|
153095
|
+
readOnly: true,
|
|
152844
153096
|
zodSchema: zodSchema36,
|
|
152845
153097
|
// RN-only: needs React Native's internal getInspectorDataForViewAtPoint and
|
|
152846
153098
|
// Metro's /symbolicate; the Chromium session has no source resolver.
|
|
@@ -152958,6 +153210,7 @@ function createDebuggerLogRegistryTool(registry2) {
|
|
|
152958
153210
|
Returns the log file path, entry counts by level, and message clusters (grouped by similarity). Works against Hermes (iOS / Android / Vega) and V8 (Chromium).
|
|
152959
153211
|
Use when investigating warnings, errors, or unexpected output. Call this first for an overview, then read the returned file for details. Returns empty stats if no log data has been captured yet, but check { note }, which is present only when the stats are empty BECAUSE the previous debugger session ended: torn down (e.g. by stop-all-simulator-servers) with its log file deleted, or cut off by the app crashing with its log file kept at the path the note names. Absent that note, empty really does mean the app has logged nothing.
|
|
152960
153212
|
When the debugger cannot be reached, this tool does not fail: it returns { status: "not_connected", reason, detail, guidance } with NO log file. Follow the guidance (do not retry in a loop). Read a log file in this state only when a { note } names one kept from before the app crashed. A "connected" result's stats may come from a session whose socket has since died. Use debugger-status, not this tool, to judge debugger health.`,
|
|
153213
|
+
readOnly: true,
|
|
152961
153214
|
zodSchema: zodSchema37,
|
|
152962
153215
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
152963
153216
|
// Resolved manually in execute so a not-connected precondition becomes a
|
|
@@ -153137,6 +153390,7 @@ Each entry includes a requestId that can be passed to view-network-request-detai
|
|
|
153137
153390
|
On React Native (iOS / Android / Vega) interception is injected into the JS runtime: it records each request once: XMLHttpRequest (axios included), React Native's fetch, Expo's fetch, and a fetch library that sends through React Native's network module itself, such as react-native-fetch-api (found in a Metro development build). Capture starts at the first network-tool call; a reload clears it. On Chromium it reads the browser's native CDP Network domain (the active tab; all request types).
|
|
153138
153391
|
Use when inspecting outbound HTTP traffic or debugging API calls in the running app.
|
|
153139
153392
|
Fails if the app is not connected (RN) or the device is not reachable (Chromium).`,
|
|
153393
|
+
readOnly: true,
|
|
153140
153394
|
zodSchema: zodSchema38,
|
|
153141
153395
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
153142
153396
|
services: (params) => {
|
|
@@ -153254,6 +153508,7 @@ var networkRequestTool = {
|
|
|
153254
153508
|
Returns request/response headers (sensitive headers redacted), status, timing, the request body, and optionally the response body.
|
|
153255
153509
|
Request and response bodies over 1000 chars are cut to 1000 under a "[TRUNCATED: ...]" line that gives the full size; a binary response body is replaced by "[body omitted: binary <mime>, N bytes]". Use when you need headers, body, or timing for a specific request after listing logs.
|
|
153256
153510
|
Returns an error message string if the requestId is not found: use view-network-logs to get valid requestId values.`,
|
|
153511
|
+
readOnly: true,
|
|
153257
153512
|
zodSchema: zodSchema39,
|
|
153258
153513
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
153259
153514
|
services: (params) => {
|
|
@@ -153700,6 +153955,7 @@ since a TV UI has no tap coordinates. Move the highlight with \`tv-remote\` (up/
|
|
|
153700
153955
|
back/menu/home), then call describe again to confirm where focus landed.`,
|
|
153701
153956
|
alwaysLoad: true,
|
|
153702
153957
|
searchHint: "accessibility element tree ui hierarchy tap coordinates ios android chromium vega <flag:harmonyos>harmony harmonyos </flag:harmonyos>dom tv tvos apple tv android tv fire tv focus focusable remote dpad",
|
|
153958
|
+
readOnly: true,
|
|
153703
153959
|
zodSchema: zodSchema40,
|
|
153704
153960
|
capability: capability25,
|
|
153705
153961
|
services: (params) => {
|
|
@@ -154200,6 +154456,7 @@ Use when a program needs element ancestry, such as an e2e engine's scoped select
|
|
|
154200
154456
|
Returns { schemaVersion, roots, truncated, alertVisible, keyboardVisible, foregroundApp, unsupportedFields }.
|
|
154201
154457
|
Fails if the iOS ax-service predates the tree command; update argent.`,
|
|
154202
154458
|
hideFromMcp: true,
|
|
154459
|
+
readOnly: true,
|
|
154203
154460
|
zodSchema: zodSchema41,
|
|
154204
154461
|
capability: capability26,
|
|
154205
154462
|
services: () => ({}),
|
|
@@ -154270,6 +154527,7 @@ function createForegroundAppTool(registry2) {
|
|
|
154270
154527
|
Returns { bundleId, name, alertVisible }; under a system alert, bundleId is the app it covers.
|
|
154271
154528
|
A field is unset when it is unknown.`,
|
|
154272
154529
|
hideFromMcp: true,
|
|
154530
|
+
readOnly: true,
|
|
154273
154531
|
zodSchema: zodSchema42,
|
|
154274
154532
|
capability: capability27,
|
|
154275
154533
|
services: () => ({}),
|
|
@@ -154756,6 +155014,7 @@ panel settles instantly on its last frame, and taps land nowhere until it is wok
|
|
|
154756
155014
|
</flag:harmonyos>Use after a launch/navigation to wait for the UI to render before screenshotting or tapping.`,
|
|
154757
155015
|
searchHint: "wait until screen settles idle stable stops changing animation transition rendered ready before screenshot",
|
|
154758
155016
|
longRunning: true,
|
|
155017
|
+
readOnly: true,
|
|
154759
155018
|
zodSchema: zodSchema44,
|
|
154760
155019
|
capability: capability29,
|
|
154761
155020
|
services: (params) => {
|
|
@@ -154839,6 +155098,96 @@ function classifyStaleness({
|
|
|
154839
155098
|
};
|
|
154840
155099
|
}
|
|
154841
155100
|
|
|
155101
|
+
// ../tool-server/src/utils/debugger/runtime-device.ts
|
|
155102
|
+
var import_node_crypto12 = require("node:crypto");
|
|
155103
|
+
var import_node_child_process39 = require("node:child_process");
|
|
155104
|
+
var import_node_util31 = require("node:util");
|
|
155105
|
+
init_adb();
|
|
155106
|
+
var execFileAsync31 = (0, import_node_util31.promisify)(import_node_child_process39.execFile);
|
|
155107
|
+
var LOG_READ_TIMEOUT_MS = 5e3;
|
|
155108
|
+
var RETRY_DELAY_MS = 300;
|
|
155109
|
+
async function findRuntimeDevice(cdp) {
|
|
155110
|
+
const marker = `argent-device-probe:${(0, import_node_crypto12.randomUUID)()}`;
|
|
155111
|
+
const logged = await cdp.evaluate(
|
|
155112
|
+
`(function () {
|
|
155113
|
+
if (typeof nativeLoggingHook !== "function") return false;
|
|
155114
|
+
nativeLoggingHook(${JSON.stringify(marker)}, 1);
|
|
155115
|
+
return true;
|
|
155116
|
+
})()`
|
|
155117
|
+
).catch(() => false);
|
|
155118
|
+
if (logged !== true) return void 0;
|
|
155119
|
+
const checks = [
|
|
155120
|
+
async () => firstFound((await androidSerials()).map((serial) => () => logcatHolds(serial, marker))),
|
|
155121
|
+
async () => firstFound((await bootedSimulators()).map((udid) => () => simulatorLogHolds(udid, marker)))
|
|
155122
|
+
];
|
|
155123
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
155124
|
+
if (attempt > 0) await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
155125
|
+
const found = await firstFound(checks);
|
|
155126
|
+
if (found !== void 0) return found;
|
|
155127
|
+
}
|
|
155128
|
+
return void 0;
|
|
155129
|
+
}
|
|
155130
|
+
function firstFound(checks) {
|
|
155131
|
+
return new Promise((resolve16) => {
|
|
155132
|
+
let left = checks.length;
|
|
155133
|
+
if (left === 0) resolve16(void 0);
|
|
155134
|
+
for (const check3 of checks) {
|
|
155135
|
+
void check3().then((id) => {
|
|
155136
|
+
if (id !== void 0) resolve16(id);
|
|
155137
|
+
else if (--left === 0) resolve16(void 0);
|
|
155138
|
+
});
|
|
155139
|
+
}
|
|
155140
|
+
});
|
|
155141
|
+
}
|
|
155142
|
+
async function androidSerials() {
|
|
155143
|
+
try {
|
|
155144
|
+
const { stdout } = await runAdb(["devices"], { timeoutMs: ADB_DEVICES_TIMEOUT_MS });
|
|
155145
|
+
return parseAdbDevices(stdout).filter((d) => d.state === "device").map((d) => d.serial);
|
|
155146
|
+
} catch {
|
|
155147
|
+
return [];
|
|
155148
|
+
}
|
|
155149
|
+
}
|
|
155150
|
+
async function bootedSimulators() {
|
|
155151
|
+
const simulators = await listIosSimulators();
|
|
155152
|
+
return simulators.filter((s) => s.state === "Booted").map((s) => s.udid);
|
|
155153
|
+
}
|
|
155154
|
+
async function logcatHolds(serial, marker) {
|
|
155155
|
+
try {
|
|
155156
|
+
const { stdout } = await runAdb(
|
|
155157
|
+
["-s", serial, "logcat", "-d", "-s", "ReactNativeJS", "-e", marker],
|
|
155158
|
+
{ timeoutMs: LOG_READ_TIMEOUT_MS }
|
|
155159
|
+
);
|
|
155160
|
+
return stdout.includes(marker) ? serial : void 0;
|
|
155161
|
+
} catch {
|
|
155162
|
+
return void 0;
|
|
155163
|
+
}
|
|
155164
|
+
}
|
|
155165
|
+
async function simulatorLogHolds(udid, marker) {
|
|
155166
|
+
try {
|
|
155167
|
+
const args = await simctlArgsForUdid(udid, [
|
|
155168
|
+
"spawn",
|
|
155169
|
+
udid,
|
|
155170
|
+
"log",
|
|
155171
|
+
"show",
|
|
155172
|
+
"--info",
|
|
155173
|
+
"--last",
|
|
155174
|
+
"1m",
|
|
155175
|
+
"--style",
|
|
155176
|
+
"compact",
|
|
155177
|
+
"--predicate",
|
|
155178
|
+
`eventMessage CONTAINS ${JSON.stringify(marker)} AND process != "log"`
|
|
155179
|
+
]);
|
|
155180
|
+
const { stdout } = await execFileAsync31("xcrun", args, {
|
|
155181
|
+
timeout: LOG_READ_TIMEOUT_MS,
|
|
155182
|
+
killSignal: SIMCTL_KILL_SIGNAL,
|
|
155183
|
+
encoding: "utf-8"
|
|
155184
|
+
});
|
|
155185
|
+
return stdout.includes(marker) ? udid : void 0;
|
|
155186
|
+
} catch {
|
|
155187
|
+
return void 0;
|
|
155188
|
+
}
|
|
155189
|
+
}
|
|
155190
|
+
|
|
154842
155191
|
// ../tool-server/src/utils/react-profiler/devtools-bootstrap.ts
|
|
154843
155192
|
function bootstrapFailureMessage(bootstrap) {
|
|
154844
155193
|
switch (bootstrap.reason) {
|
|
@@ -154861,6 +155210,7 @@ function bootstrapFailureMessage(bootstrap) {
|
|
|
154861
155210
|
// ../tool-server/src/tools/profiler/react/react-profiler-start.ts
|
|
154862
155211
|
var NO_DEVTOOLS_HOOK_ERROR = "React DevTools hook (__REACT_DEVTOOLS_GLOBAL_HOOK__) is not present in this app's JavaScript runtime. React profiling requires a development build with React DevTools enabled. Likely causes: (1) the app is a release/production build \u2014 DevTools is stripped to reduce bundle size; (2) you connected to the wrong JS runtime; (3) this isn't a React (Native) app. Fix: rebuild in debug/dev mode (e.g. `npx react-native run-ios` without --configuration Release; for Expo, run a dev client). Once the app is running with DevTools attached, call react-profiler-start again.";
|
|
154863
155212
|
var NO_RENDERERS_ATTACHED_ERROR = "React DevTools hook is present but no React renderer has registered yet. The hook is loaded but no fiber renderer has attached \u2014 typically because the app has not committed its first render, or the DevTools backend has not been bootstrapped on a bridgeless React Native dev build. Fix: ensure the app has rendered (interact with it once, then retry); if it stays empty, call react-profiler-start first \u2014 it will attempt to attach the DevTools backend automatically.";
|
|
155213
|
+
var UNKNOWN_DEVICE_NOTE = "Two or more devices share this Metro, and Argent could not tell which of them runs this app. So taps and swipes on that device still return a screenshot and an element tree, and the capture loads the app while the profiler records. To avoid this, run the app on its own Metro port.";
|
|
154864
155214
|
var zodSchema45 = external_exports.object({
|
|
154865
155215
|
port: metroPortField,
|
|
154866
155216
|
device_id: external_exports.string().describe(
|
|
@@ -155036,6 +155386,7 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155036
155386
|
await cdp.send("Profiler.stop").catch(ignore);
|
|
155037
155387
|
api.profilingActive = false;
|
|
155038
155388
|
}
|
|
155389
|
+
const runtimeDevice = isLogicalKeyedDevice(api.deviceId) ? await findRuntimeDevice(cdp) : void 0;
|
|
155039
155390
|
const sessionId = crypto6.randomUUID();
|
|
155040
155391
|
const ownerPayload = {
|
|
155041
155392
|
sessionId,
|
|
@@ -155080,6 +155431,19 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155080
155431
|
}
|
|
155081
155432
|
);
|
|
155082
155433
|
}
|
|
155434
|
+
if (api.disposed) {
|
|
155435
|
+
await cdp.evaluate(STOP_FOR_TAKEOVER_SCRIPT).catch(ignore);
|
|
155436
|
+
await cdp.send("Profiler.stop").catch(ignore);
|
|
155437
|
+
throw new FailureError(
|
|
155438
|
+
`The React profiler session for ${api.deviceId} was torn down while the profiler was starting, so nothing is recorded. One tool-server serves every agent using this argent install, so another agent may have run stop-all-simulator-servers. Call react-profiler-start again.`,
|
|
155439
|
+
{
|
|
155440
|
+
error_code: FAILURE_CODES.REACT_PROFILER_SESSION_TORN_DOWN,
|
|
155441
|
+
failure_stage: "react_profiler_start_session_torn_down",
|
|
155442
|
+
failure_area: "tool_server",
|
|
155443
|
+
error_kind: "not_found"
|
|
155444
|
+
}
|
|
155445
|
+
);
|
|
155446
|
+
}
|
|
155083
155447
|
const startedAtEpochMs = startResult.startedAtEpochMs ?? Date.now();
|
|
155084
155448
|
clearCachedProfilerPaths(api.port, api.deviceId);
|
|
155085
155449
|
api.sessionPaths = null;
|
|
@@ -155090,11 +155454,14 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155090
155454
|
api.profileStartWallMs = startedAtEpochMs;
|
|
155091
155455
|
api.sessionId = sessionId;
|
|
155092
155456
|
api.ownerToolServerPid = process.pid;
|
|
155457
|
+
trackProfilingRun(api.deviceId, api);
|
|
155458
|
+
if (runtimeDevice) trackProfilingRun(runtimeDevice, api);
|
|
155093
155459
|
return {
|
|
155094
155460
|
started_at: new Date(startedAtEpochMs).toISOString(),
|
|
155095
155461
|
startedAtEpochMs,
|
|
155096
155462
|
hermes_version: api.hermesVersion,
|
|
155097
|
-
detected_architecture: api.detectedArchitecture
|
|
155463
|
+
detected_architecture: api.detectedArchitecture,
|
|
155464
|
+
...isLogicalKeyedDevice(api.deviceId) && !runtimeDevice ? { [RESULT_NOTE_KEY]: UNKNOWN_DEVICE_NOTE } : {}
|
|
155098
155465
|
};
|
|
155099
155466
|
}
|
|
155100
155467
|
};
|
|
@@ -155287,7 +155654,7 @@ Fails if no active profiling session exists or the CDP connection was lost durin
|
|
|
155287
155654
|
}
|
|
155288
155655
|
if (!api.profilingActive) {
|
|
155289
155656
|
throw new FailureError(
|
|
155290
|
-
"No active profiling run to stop.
|
|
155657
|
+
"No active profiling run to stop. Either the run ended without its data (a JS reload ends it: Metro's `r`, a red-box Reload, debugger-reload-metro), or Hermes CPU sampling was never started \u2014 typically because react-profiler-start failed before reaching the sampler (often on release builds without React DevTools). After a reload, call react-profiler-start again. Otherwise check the error react-profiler-start returned, address the underlying cause (rebuild in dev mode, reconnect the debugger, etc.), then call react-profiler-start again.",
|
|
155291
155658
|
{
|
|
155292
155659
|
error_code: FAILURE_CODES.REACT_PROFILER_NO_ACTIVE_SESSION,
|
|
155293
155660
|
failure_stage: "react_profiler_stop_inactive",
|
|
@@ -155493,6 +155860,7 @@ function createReactProfilerStatusTool(registry2) {
|
|
|
155493
155860
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to check React profiler: ${failureSignal2.error_code}`
|
|
155494
155861
|
},
|
|
155495
155862
|
description: `Check the state of the React profiler session without side effects. Use after an interruption (debugger disconnect, unexpected error, agent pause) to decide whether to continue with react-profiler-stop, start a new session, or reconnect the debugger. Ownership is verified server-side against this tool-server's in-memory session, so no token-threading is required. Returns { session_status, is_running, current_owner, \u2026 }. If this tool-server process restarted after react-profiler-start, status will report 'taken_over'; use react-profiler-start { force: true } to reclaim.`,
|
|
155863
|
+
readOnly: true,
|
|
155496
155864
|
zodSchema: zodSchema47,
|
|
155497
155865
|
// RN-only: companion to react-profiler-start.
|
|
155498
155866
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -157295,6 +157663,7 @@ var reactProfilerComponentSourceTool = {
|
|
|
157295
157663
|
Call this per-finding after react-profiler-analyze to inspect source before proposing a fix.
|
|
157296
157664
|
Returns found: false if the component is not found in user-owned code (e.g. lives in node_modules).
|
|
157297
157665
|
When several files define a component with the same name (e.g. platform variants like List.tsx and List.web.tsx), returns the primary match and lists the rest under otherMatches[] (file/line/col). Check it before assuming the returned file is the one you meant.`,
|
|
157666
|
+
readOnly: true,
|
|
157298
157667
|
zodSchema: zodSchema49,
|
|
157299
157668
|
// Declared so the tool catalogue groups this with the other react-profiler-*
|
|
157300
157669
|
// tools; the HTTP gate itself is a no-op here, as there is no device arg to
|
|
@@ -157433,6 +157802,7 @@ Use when you specifically need to investigate JS CPU hotspots that are NOT tied
|
|
|
157433
157802
|
Call react-profiler-stop first. Reads directly from the stored cpuProfile.
|
|
157434
157803
|
Returns a markdown table of the top hotspot functions with self-time, total-time, and location.
|
|
157435
157804
|
Fails if react-profiler-stop has not been called or no CPU profile is stored.`,
|
|
157805
|
+
readOnly: true,
|
|
157436
157806
|
zodSchema: zodSchema50,
|
|
157437
157807
|
// RN-only: reads a Hermes CPU profile; Chromium's V8 sample format differs.
|
|
157438
157808
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -157547,6 +157917,7 @@ var reactProfilerRendersTool = {
|
|
|
157547
157917
|
Returns a markdown table of the top re-rendering components. No profiling session required; works on a live connected app.
|
|
157548
157918
|
Use when you want a quick snapshot of render counts without a full profiling session.
|
|
157549
157919
|
Fails if the React DevTools hook is not present in the runtime or the app is not connected.`,
|
|
157920
|
+
readOnly: true,
|
|
157550
157921
|
zodSchema: zodSchema51,
|
|
157551
157922
|
// RN-only: queries the React DevTools backend hook on the live runtime.
|
|
157552
157923
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -157723,6 +158094,7 @@ var reactProfilerFiberTreeTool = {
|
|
|
157723
158094
|
Use when tracing ancestry of a library component or checking for useMemoCache hook (confirms React Compiler is active on a component).
|
|
157724
158095
|
Returns a nested JSON tree of fiber nodes with name, tag, actualDuration, selfBaseDuration, and children.
|
|
157725
158096
|
Fails if the React DevTools hook is not present or no fiber roots have been committed yet.`,
|
|
158097
|
+
readOnly: true,
|
|
157726
158098
|
zodSchema: zodSchema52,
|
|
157727
158099
|
// RN-only: walks the fiber tree via the React DevTools backend hook.
|
|
157728
158100
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -158146,8 +158518,8 @@ var import_util14 = require("util");
|
|
|
158146
158518
|
var DEFAULT_EXEC_TIMEOUT_MS = 6e4;
|
|
158147
158519
|
var DEFAULT_EXEC_MAX_BUFFER = 256 * 1024 * 1024;
|
|
158148
158520
|
async function execFileAsyncWithTimeout(file2, args, options = {}) {
|
|
158149
|
-
const
|
|
158150
|
-
const { stdout, stderr } = await
|
|
158521
|
+
const execFileAsync36 = (0, import_util14.promisify)(import_child_process2.execFile);
|
|
158522
|
+
const { stdout, stderr } = await execFileAsync36(file2, args, {
|
|
158151
158523
|
encoding: "utf-8",
|
|
158152
158524
|
...options,
|
|
158153
158525
|
// Applied after ...options so a caller cannot weaken the guards; maxBuffer
|
|
@@ -159679,7 +160051,7 @@ var STARTUP_TIMEOUT_MS = 1e4;
|
|
|
159679
160051
|
var DETECT_RUNNING_APP_TIMEOUT_MS = 1e4;
|
|
159680
160052
|
var NOTIFY_REGISTER_TIMEOUT_MS = 2e3;
|
|
159681
160053
|
var MAX_START_ATTEMPTS = 2;
|
|
159682
|
-
var
|
|
160054
|
+
var RETRY_DELAY_MS2 = 1200;
|
|
159683
160055
|
var COLD_START_SIGNATURE = "Cannot find process matching name:";
|
|
159684
160056
|
var STOP_GRACE_MS = 3e5;
|
|
159685
160057
|
var STOP_TERM_MS = 5e3;
|
|
@@ -160103,10 +160475,10 @@ async function startNativeProfilerIos(api, params) {
|
|
|
160103
160475
|
if (!isColdStart) throw err;
|
|
160104
160476
|
if (attempt >= MAX_START_ATTEMPTS) break;
|
|
160105
160477
|
process.stderr.write(
|
|
160106
|
-
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${
|
|
160478
|
+
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${RETRY_DELAY_MS2} ms for cold-start to settle, then retrying.
|
|
160107
160479
|
`
|
|
160108
160480
|
);
|
|
160109
|
-
await new Promise((r) => setTimeout(r,
|
|
160481
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS2));
|
|
160110
160482
|
}
|
|
160111
160483
|
}
|
|
160112
160484
|
const totalMs = Date.now() - startMs;
|
|
@@ -161564,12 +161936,16 @@ Fails if no app is running on the device, or the profiler cannot attach to the p
|
|
|
161564
161936
|
const api = services.session;
|
|
161565
161937
|
const device = resolveDevice(params.device_id);
|
|
161566
161938
|
assertSupported("native-profiler-start", capability30, device);
|
|
161939
|
+
let started;
|
|
161567
161940
|
if (api.platform === "ios") {
|
|
161568
161941
|
await ensureDeps(["xcrun"]);
|
|
161569
|
-
|
|
161942
|
+
started = await startNativeProfilerIos(api, params);
|
|
161943
|
+
} else {
|
|
161944
|
+
await ensureDeps(["adb"]);
|
|
161945
|
+
started = await startNativeProfilerAndroid(api, params);
|
|
161570
161946
|
}
|
|
161571
|
-
|
|
161572
|
-
return
|
|
161947
|
+
trackProfilingRun(device.id, api);
|
|
161948
|
+
return started;
|
|
161573
161949
|
}
|
|
161574
161950
|
};
|
|
161575
161951
|
|
|
@@ -162196,7 +162572,7 @@ var WATERMARK_PNG_HEIGHT = 277;
|
|
|
162196
162572
|
var WATERMARK_PNG_BASE64 = "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";
|
|
162197
162573
|
|
|
162198
162574
|
// ../tool-server/src/tools/screen-recording/watermark.ts
|
|
162199
|
-
var
|
|
162575
|
+
var execFileAsync32 = (0, import_util15.promisify)(import_child_process6.execFile);
|
|
162200
162576
|
var OUTPUT_FPS = 30;
|
|
162201
162577
|
var FFMPEG_FALLBACK_PATHS = [
|
|
162202
162578
|
"/opt/homebrew/bin/ffmpeg",
|
|
@@ -162213,7 +162589,7 @@ var MASK_DARK_MAX_LUMA = 90;
|
|
|
162213
162589
|
var MASK_LIGHT_MIN_LUMA = 165;
|
|
162214
162590
|
async function resolveBinary(name, fallbacks) {
|
|
162215
162591
|
try {
|
|
162216
|
-
await
|
|
162592
|
+
await execFileAsync32("/bin/sh", ["-c", `command -v ${name}`], { timeout: 2e3 });
|
|
162217
162593
|
return name;
|
|
162218
162594
|
} catch {
|
|
162219
162595
|
}
|
|
@@ -163239,6 +163615,7 @@ Every table states how many samples it covers and how much of that was idle.
|
|
|
163239
163615
|
Use when investigating JS CPU hotspots or correlating CPU cost with specific components.
|
|
163240
163616
|
Returns a markdown table of CPU hotspots, call tree, or per-component CPU breakdown.
|
|
163241
163617
|
Fails if no CPU profile is stored; run react-profiler-stop first.`,
|
|
163618
|
+
readOnly: true,
|
|
163242
163619
|
zodSchema: zodSchema58,
|
|
163243
163620
|
// RN-only: reads Hermes-format CPU profiles; Chromium's V8 sample format differs.
|
|
163244
163621
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -163598,6 +163975,7 @@ Modes:
|
|
|
163598
163975
|
Use when drilling into specific components or time windows after react-profiler-analyze.
|
|
163599
163976
|
Returns a markdown table or tree of commit data matching the requested mode.
|
|
163600
163977
|
Fails if react-profiler-stop has not been called or no commit data is stored.`,
|
|
163978
|
+
readOnly: true,
|
|
163601
163979
|
zodSchema: zodSchema59,
|
|
163602
163980
|
// Reads React commit data captured via the React DevTools backend.
|
|
163603
163981
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -163987,6 +164365,7 @@ Modes:
|
|
|
163987
164365
|
Use when drilling into native hang stacks, thread CPU breakdown, or memory leaks after native-profiler-analyze.
|
|
163988
164366
|
Returns a markdown report with native call stacks, thread weights, or leak details for the selected mode.
|
|
163989
164367
|
Fails if native-profiler-analyze has not been run or no parsed trace data is in memory.`,
|
|
164368
|
+
readOnly: true,
|
|
163990
164369
|
zodSchema: zodSchema60,
|
|
163991
164370
|
// No chromium entry: it has no native trace capture.
|
|
163992
164371
|
capability: {
|
|
@@ -164074,6 +164453,7 @@ Requires both react-profiler-analyze and native-profiler-analyze to have been ca
|
|
|
164074
164453
|
Call this tool when both profilers were run in parallel on the same session.
|
|
164075
164454
|
Returns a markdown report correlating hangs with React commits, memory leaks, and investigation hints.
|
|
164076
164455
|
Fails if either react-profiler-analyze or native-profiler-analyze has not been called first.`,
|
|
164456
|
+
readOnly: true,
|
|
164077
164457
|
zodSchema: zodSchema61,
|
|
164078
164458
|
// iOS reads xctrace output; Android re-queries the Perfetto .pftrace via
|
|
164079
164459
|
// loadAndroidCombinedData. Chromium has no native trace capture.
|
|
@@ -165020,7 +165400,7 @@ Returns { stopped } - the URNs of the services that were actually live and got s
|
|
|
165020
165400
|
|
|
165021
165401
|
// ../tool-server/src/tools/simulator/stop-metro.ts
|
|
165022
165402
|
init_zod();
|
|
165023
|
-
var
|
|
165403
|
+
var import_node_child_process40 = require("node:child_process");
|
|
165024
165404
|
function parseNetstatListeningPids(netstatOutput, port) {
|
|
165025
165405
|
const pids = /* @__PURE__ */ new Set();
|
|
165026
165406
|
for (const line of netstatOutput.split(/\r?\n/)) {
|
|
@@ -165036,7 +165416,7 @@ function parseNetstatListeningPids(netstatOutput, port) {
|
|
|
165036
165416
|
}
|
|
165037
165417
|
function listeningPids(port) {
|
|
165038
165418
|
if (process.platform === "win32") {
|
|
165039
|
-
const output3 = (0,
|
|
165419
|
+
const output3 = (0, import_node_child_process40.execFileSync)("netstat", ["-ano"], {
|
|
165040
165420
|
encoding: "utf-8",
|
|
165041
165421
|
timeout: 5e3,
|
|
165042
165422
|
// `netstat -ano` dumps every socket on the host; overflowing Node's
|
|
@@ -165045,7 +165425,7 @@ function listeningPids(port) {
|
|
|
165045
165425
|
});
|
|
165046
165426
|
return parseNetstatListeningPids(output3, port);
|
|
165047
165427
|
}
|
|
165048
|
-
const output2 = (0,
|
|
165428
|
+
const output2 = (0, import_node_child_process40.execFileSync)("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"], {
|
|
165049
165429
|
encoding: "utf-8",
|
|
165050
165430
|
timeout: 5e3
|
|
165051
165431
|
}).trim();
|
|
@@ -170802,7 +171182,7 @@ var import_node_url4 = require("node:url");
|
|
|
170802
171182
|
init_src2();
|
|
170803
171183
|
|
|
170804
171184
|
// ../tool-server/src/tools/flows/script/flow-script-executor.ts
|
|
170805
|
-
var
|
|
171185
|
+
var import_node_child_process41 = require("node:child_process");
|
|
170806
171186
|
var fs59 = __toESM(require("node:fs"));
|
|
170807
171187
|
var os17 = __toESM(require("node:os"));
|
|
170808
171188
|
var path45 = __toESM(require("node:path"));
|
|
@@ -171187,7 +171567,7 @@ var FlowScriptExecutor = class {
|
|
|
171187
171567
|
detached: process.platform !== "win32",
|
|
171188
171568
|
windowsHide: process.platform === "win32"
|
|
171189
171569
|
};
|
|
171190
|
-
child = (0,
|
|
171570
|
+
child = (0, import_node_child_process41.fork)(scriptPath, [], forkOptions);
|
|
171191
171571
|
} catch (err) {
|
|
171192
171572
|
return emptyResult(
|
|
171193
171573
|
{ kind: "spawn", message: `Could not start the script process: ${errorMessage(err)}` },
|
|
@@ -171631,7 +172011,7 @@ async function stopProcessTree(child, graceMs) {
|
|
|
171631
172011
|
if (process.platform === "win32") {
|
|
171632
172012
|
if (hasExited(child)) return;
|
|
171633
172013
|
tryKill(() => {
|
|
171634
|
-
const killer = (0,
|
|
172014
|
+
const killer = (0, import_node_child_process41.spawn)("taskkill", ["/pid", String(pid), "/t", "/f"], {
|
|
171635
172015
|
windowsHide: true,
|
|
171636
172016
|
stdio: "ignore"
|
|
171637
172017
|
});
|
|
@@ -172337,7 +172717,7 @@ init_src2();
|
|
|
172337
172717
|
init_device_info();
|
|
172338
172718
|
|
|
172339
172719
|
// ../tool-server/src/tools/flows/flow-visual.ts
|
|
172340
|
-
var
|
|
172720
|
+
var import_node_crypto13 = require("node:crypto");
|
|
172341
172721
|
var fs63 = __toESM(require("node:fs/promises"));
|
|
172342
172722
|
var os18 = __toESM(require("node:os"));
|
|
172343
172723
|
var path48 = __toESM(require("node:path"));
|
|
@@ -172353,7 +172733,7 @@ init_src2();
|
|
|
172353
172733
|
// ../tool-server/src/tools/screenshot-diff/screenshot-diff-ocr.ts
|
|
172354
172734
|
var import_child_process8 = require("child_process");
|
|
172355
172735
|
var import_util16 = require("util");
|
|
172356
|
-
var
|
|
172736
|
+
var execFileAsync33 = (0, import_util16.promisify)(import_child_process8.execFile);
|
|
172357
172737
|
var OCR_TIMEOUT_MS = 1e4;
|
|
172358
172738
|
var OCR_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
|
|
172359
172739
|
var TESSERACT_BINARY = "tesseract";
|
|
@@ -172398,7 +172778,7 @@ async function extractOcrTextBlocks(imagePath) {
|
|
|
172398
172778
|
}
|
|
172399
172779
|
}
|
|
172400
172780
|
async function recognizeTsv(imagePath) {
|
|
172401
|
-
const { stdout } = await
|
|
172781
|
+
const { stdout } = await execFileAsync33(
|
|
172402
172782
|
TESSERACT_BINARY,
|
|
172403
172783
|
[
|
|
172404
172784
|
imagePath,
|
|
@@ -174508,7 +174888,7 @@ async function runSnapshot(env, opts) {
|
|
|
174508
174888
|
});
|
|
174509
174889
|
const captureWarned = shot.warning !== void 0 ? { warning: shot.warning } : {};
|
|
174510
174890
|
const { w, h } = await pngDimensions(shot.image.hostPath);
|
|
174511
|
-
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0,
|
|
174891
|
+
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0, import_node_crypto13.createHash)("sha256").update(cropIdentity(opts.cropOn)).digest("hex").slice(0, 8)}`;
|
|
174512
174892
|
const snapshotKey = `${opts.name}__${authoringPlatform(env.device.platform)}-${w}x${h}${cropSuffix}`;
|
|
174513
174893
|
const key2 = `${snapshotKey}.png`;
|
|
174514
174894
|
const baselinePath = opts.clientFlowPath === void 0 ? path48.join(baselineDir(opts.flowsDir, opts.flowName), key2) : clientBaselinePath(opts.clientFlowPath, opts.flowName, key2);
|
|
@@ -174644,7 +175024,7 @@ async function runSnapshot(env, opts) {
|
|
|
174644
175024
|
}
|
|
174645
175025
|
};
|
|
174646
175026
|
}
|
|
174647
|
-
const within = result.mismatchPercentage <= opts.maxMismatch;
|
|
175027
|
+
const within = result.mismatchPercentage <= opts.maxMismatch * (1 + 1e-14);
|
|
174648
175028
|
const reason2 = `diff ${result.mismatchPercentage.toFixed(2)}% ${within ? "\u2264" : ">"} ${opts.maxMismatch}% (${key2})`;
|
|
174649
175029
|
if (within) {
|
|
174650
175030
|
return { status: "pass", reason: reason2, ...captureWarned };
|
|
@@ -174680,11 +175060,11 @@ async function runSnapshot(env, opts) {
|
|
|
174680
175060
|
}
|
|
174681
175061
|
|
|
174682
175062
|
// ../tool-server/src/utils/status-bar.ts
|
|
174683
|
-
var
|
|
174684
|
-
var
|
|
175063
|
+
var import_node_child_process42 = require("node:child_process");
|
|
175064
|
+
var import_node_util32 = require("node:util");
|
|
174685
175065
|
init_adb();
|
|
174686
175066
|
init_device_info();
|
|
174687
|
-
var
|
|
175067
|
+
var execFileAsync34 = (0, import_node_util32.promisify)(import_node_child_process42.execFile);
|
|
174688
175068
|
var DEMO_BROADCAST = "am broadcast -a com.android.systemui.demo";
|
|
174689
175069
|
var IOS_STATUS_BAR_OVERRIDE = [
|
|
174690
175070
|
"override",
|
|
@@ -174708,7 +175088,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174708
175088
|
if (isIosPhysicalDevice(device)) return false;
|
|
174709
175089
|
try {
|
|
174710
175090
|
if (device.platform === "ios") {
|
|
174711
|
-
await
|
|
175091
|
+
await execFileAsync34(
|
|
174712
175092
|
"xcrun",
|
|
174713
175093
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, ...IOS_STATUS_BAR_OVERRIDE])
|
|
174714
175094
|
);
|
|
@@ -174744,7 +175124,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174744
175124
|
async function restoreStatusBar(device) {
|
|
174745
175125
|
try {
|
|
174746
175126
|
if (device.platform === "ios") {
|
|
174747
|
-
await
|
|
175127
|
+
await execFileAsync34(
|
|
174748
175128
|
"xcrun",
|
|
174749
175129
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, "clear"])
|
|
174750
175130
|
);
|
|
@@ -176328,6 +176708,7 @@ Touches no device: nothing is launched, tapped, dispatched or torn down, and no
|
|
|
176328
176708
|
needs booting, so calling this costs nothing but a file read.
|
|
176329
176709
|
Fails if the e2e test file does not exist.
|
|
176330
176710
|
Address the e2e test exactly as you will address it in e2e-execute: name or flow_path, one and only one; supplying both or neither is rejected. The name goes in \`name\`, which resolves <project_root>/.argent/e2e/<name>.yaml, else .argent/flows/<name>.yaml.`,
|
|
176711
|
+
readOnly: true,
|
|
176331
176712
|
zodSchema: zodSchema72,
|
|
176332
176713
|
fileInputs: fileInputs5,
|
|
176333
176714
|
services: () => ({}),
|
|
@@ -176352,7 +176733,7 @@ init_zod();
|
|
|
176352
176733
|
// ../tool-server/src/utils/workspace-reader.ts
|
|
176353
176734
|
var import_promises19 = require("node:fs/promises");
|
|
176354
176735
|
var import_node_path29 = require("node:path");
|
|
176355
|
-
var
|
|
176736
|
+
var import_node_child_process43 = require("node:child_process");
|
|
176356
176737
|
var import_dotenv2 = __toESM(require_dist());
|
|
176357
176738
|
async function exists2(path54) {
|
|
176358
176739
|
try {
|
|
@@ -176396,7 +176777,7 @@ async function listDir(path54) {
|
|
|
176396
176777
|
var COMMAND_TIMEOUT_MS = 3e3;
|
|
176397
176778
|
function runVersionCommand(cmd, args, cwd) {
|
|
176398
176779
|
return new Promise((resolve16) => {
|
|
176399
|
-
const child = (0,
|
|
176780
|
+
const child = (0, import_node_child_process43.execFile)(cmd, args, { cwd, timeout: COMMAND_TIMEOUT_MS }, (err, stdout) => {
|
|
176400
176781
|
if (err) {
|
|
176401
176782
|
resolve16(null);
|
|
176402
176783
|
return;
|
|
@@ -176676,6 +177057,7 @@ exploration of anything the snapshot surfaces.
|
|
|
176676
177057
|
Use when you need to inspect project configuration without manually reading multiple files.
|
|
176677
177058
|
Returns partial data if workspacePath does not exist or is not readable; missing items are represented as null or empty collections.
|
|
176678
177059
|
Fails if the workspacePath is not an absolute path or the directory cannot be accessed.`,
|
|
177060
|
+
readOnly: true,
|
|
176679
177061
|
zodSchema: zodSchema73,
|
|
176680
177062
|
fileInputs: fileInputs6,
|
|
176681
177063
|
services: () => ({}),
|
|
@@ -176685,7 +177067,7 @@ Fails if the workspacePath is not an absolute path or the directory cannot be ac
|
|
|
176685
177067
|
};
|
|
176686
177068
|
|
|
176687
177069
|
// ../tool-server/src/tools/system/update-argent.ts
|
|
176688
|
-
var
|
|
177070
|
+
var import_node_child_process44 = require("node:child_process");
|
|
176689
177071
|
var fs66 = __toESM(require("node:fs"));
|
|
176690
177072
|
var path50 = __toESM(require("node:path"));
|
|
176691
177073
|
init_zod();
|
|
@@ -176820,7 +177202,7 @@ var updateArgentTool = {
|
|
|
176820
177202
|
if (spawnRoot) updateArgs.push("--project-root", spawnRoot);
|
|
176821
177203
|
const cmd = cliEntry ? process.execPath : "argent";
|
|
176822
177204
|
const args = cliEntry ? [cliEntry, ...updateArgs] : updateArgs;
|
|
176823
|
-
const child = (0,
|
|
177205
|
+
const child = (0, import_node_child_process44.spawn)(cmd, args, {
|
|
176824
177206
|
detached: true,
|
|
176825
177207
|
stdio: "ignore",
|
|
176826
177208
|
env: { ...process.env, ARGENT_UPDATE_TRIGGER: "mcp_update" }
|
|
@@ -176872,7 +177254,7 @@ var dismissUpdateTool = {
|
|
|
176872
177254
|
};
|
|
176873
177255
|
|
|
176874
177256
|
// ../tool-server/src/tools/screenshot-diff/index.ts
|
|
176875
|
-
var
|
|
177257
|
+
var import_node_crypto14 = __toESM(require("node:crypto"));
|
|
176876
177258
|
var import_promises20 = __toESM(require("fs/promises"));
|
|
176877
177259
|
var import_node_os15 = __toESM(require("node:os"));
|
|
176878
177260
|
var import_path8 = __toESM(require("path"));
|
|
@@ -176886,10 +177268,10 @@ var zodSchema76 = external_exports.object({
|
|
|
176886
177268
|
udid: external_exports.string().min(1).describe(
|
|
176887
177269
|
"Target device id from `list-devices` (iOS UDID<flag:harmonyos>, HarmonyOS id,</flag:harmonyos> or Android serial)."
|
|
176888
177270
|
),
|
|
176889
|
-
captureBaseline: external_exports.
|
|
177271
|
+
captureBaseline: external_exports.boolean().optional().describe(
|
|
176890
177272
|
"Capture the baseline screenshot live at full resolution before diffing. Cannot be combined with captureCurrent."
|
|
176891
177273
|
),
|
|
176892
|
-
captureCurrent: external_exports.
|
|
177274
|
+
captureCurrent: external_exports.boolean().optional().describe(
|
|
176893
177275
|
"Capture the current screenshot live at full resolution before diffing. Cannot be combined with captureBaseline."
|
|
176894
177276
|
),
|
|
176895
177277
|
rotation: external_exports.enum(["Portrait", "LandscapeLeft", "LandscapeRight", "PortraitUpsideDown"]).optional().describe(
|
|
@@ -177019,7 +177401,7 @@ async function resolveOutputDir(params, options) {
|
|
|
177019
177401
|
const dir = import_path8.default.join(
|
|
177020
177402
|
import_node_os15.default.tmpdir(),
|
|
177021
177403
|
"argent-screenshot-diff",
|
|
177022
|
-
|
|
177404
|
+
import_node_crypto14.default.randomBytes(6).toString("hex")
|
|
177023
177405
|
);
|
|
177024
177406
|
await import_promises20.default.mkdir(dir, { recursive: true });
|
|
177025
177407
|
return dir;
|
|
@@ -177117,7 +177499,7 @@ function requireIosDeviceRunner(services) {
|
|
|
177117
177499
|
}
|
|
177118
177500
|
async function captureIosDeviceLiveInput(params) {
|
|
177119
177501
|
const png = await captureRunnerScreenshotPng(params.runner, RUNNER_COMMAND_TIMEOUT_MS);
|
|
177120
|
-
const suffix =
|
|
177502
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177121
177503
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177122
177504
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177123
177505
|
await import_promises20.default.writeFile(destination, png);
|
|
@@ -177135,7 +177517,7 @@ async function captureHarmonyLiveInput(params) {
|
|
|
177135
177517
|
}
|
|
177136
177518
|
await ensureDep("hdc");
|
|
177137
177519
|
const captured = await captureHarmonyScreenshotPng({ connectKey: params.connectKey, scale: 1 });
|
|
177138
|
-
const suffix =
|
|
177520
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177139
177521
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177140
177522
|
try {
|
|
177141
177523
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
@@ -177171,7 +177553,7 @@ async function captureLiveInput(params) {
|
|
|
177171
177553
|
params.peekFor?.(params.device)
|
|
177172
177554
|
);
|
|
177173
177555
|
}
|
|
177174
|
-
const suffix =
|
|
177556
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177175
177557
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177176
177558
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177177
177559
|
await import_promises20.default.copyFile(capture.path, destination);
|
|
@@ -177890,13 +178272,13 @@ function probeArgentToolServer(host, port, timeoutMs = 500) {
|
|
|
177890
178272
|
|
|
177891
178273
|
// ../tool-server/src/utils/simulator-watcher.ts
|
|
177892
178274
|
var fs68 = __toESM(require("node:fs"));
|
|
177893
|
-
var
|
|
177894
|
-
var
|
|
178275
|
+
var import_node_child_process45 = require("node:child_process");
|
|
178276
|
+
var import_node_util33 = require("node:util");
|
|
177895
178277
|
init_external_devices();
|
|
177896
|
-
var
|
|
178278
|
+
var execFileAsync35 = (0, import_node_util33.promisify)(import_node_child_process45.execFile);
|
|
177897
178279
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
177898
178280
|
async function getBootedUdidsInSet(deviceSet) {
|
|
177899
|
-
const { stdout } = await
|
|
178281
|
+
const { stdout } = await execFileAsync35("xcrun", [
|
|
177900
178282
|
...simctlPrefix(deviceSet),
|
|
177901
178283
|
"list",
|
|
177902
178284
|
"devices",
|
|
@@ -178015,7 +178397,7 @@ function startSimulatorWatcher(registry2) {
|
|
|
178015
178397
|
}
|
|
178016
178398
|
|
|
178017
178399
|
// ../tool-server/src/utils/preview-window.ts
|
|
178018
|
-
var
|
|
178400
|
+
var import_node_child_process46 = require("node:child_process");
|
|
178019
178401
|
var fs69 = __toESM(require("node:fs"));
|
|
178020
178402
|
var os20 = __toESM(require("node:os"));
|
|
178021
178403
|
var path52 = __toESM(require("node:path"));
|
|
@@ -178047,10 +178429,10 @@ function ensureLensAppBundle(electronBin) {
|
|
|
178047
178429
|
fs69.copyFileSync(path52.join(realContents, "Info.plist"), plist);
|
|
178048
178430
|
const setPlist = (entry, value) => {
|
|
178049
178431
|
try {
|
|
178050
|
-
(0,
|
|
178432
|
+
(0, import_node_child_process46.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
|
|
178051
178433
|
} catch {
|
|
178052
178434
|
try {
|
|
178053
|
-
(0,
|
|
178435
|
+
(0, import_node_child_process46.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Add :${entry} string ${value}`, plist]);
|
|
178054
178436
|
} catch {
|
|
178055
178437
|
}
|
|
178056
178438
|
}
|
|
@@ -178109,7 +178491,7 @@ function createPreviewWindowManager(opts = {}) {
|
|
|
178109
178491
|
const wrapperBin = ensureLensAppBundle(electronBin);
|
|
178110
178492
|
const launchBin = wrapperBin ?? electronBin;
|
|
178111
178493
|
const launchArgs = wrapperBin ? ["--no-sandbox", mainScript] : [mainScript];
|
|
178112
|
-
const next = (0,
|
|
178494
|
+
const next = (0, import_node_child_process46.spawn)(launchBin, launchArgs, {
|
|
178113
178495
|
// Strips ELECTRON_RUN_AS_NODE, which an Electron-based MCP host leaves in
|
|
178114
178496
|
// our env, so the child boots as a GUI app instead of bare Node.
|
|
178115
178497
|
env: electronGuiChildEnv({ ARGENT_PREVIEW_URL: url2 }),
|