@swmansion/argent 0.25.1-next.33 → 0.25.1-next.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli-cmds.mjs
CHANGED
|
@@ -2372,6 +2372,8 @@ var FAILURE_CODES = {
|
|
|
2372
2372
|
ANDROID_DEVTOOLS_WRONG_PLATFORM: "ANDROID_DEVTOOLS_WRONG_PLATFORM",
|
|
2373
2373
|
ANDROID_DEVTOOLS_DEVICE_ID_INVALID: "ANDROID_DEVTOOLS_DEVICE_ID_INVALID",
|
|
2374
2374
|
ANDROID_DEVTOOLS_HELPER_TERMINATED: "ANDROID_DEVTOOLS_HELPER_TERMINATED",
|
|
2375
|
+
ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED: "ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED",
|
|
2376
|
+
ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED: "ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED",
|
|
2375
2377
|
ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED: "ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED",
|
|
2376
2378
|
ANDROID_DEVTOOLS_RPC_ERROR: "ANDROID_DEVTOOLS_RPC_ERROR",
|
|
2377
2379
|
ANDROID_DEVTOOLS_RPC_TIMEOUT: "ANDROID_DEVTOOLS_RPC_TIMEOUT",
|
|
@@ -21857,7 +21859,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
21857
21859
|
var SESSION_ID2 = randomUUID5();
|
|
21858
21860
|
function readCliVersion() {
|
|
21859
21861
|
if (true) {
|
|
21860
|
-
return "0.25.1-next.
|
|
21862
|
+
return "0.25.1-next.35";
|
|
21861
21863
|
}
|
|
21862
21864
|
return "0.0.0";
|
|
21863
21865
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -15744,6 +15744,8 @@ var FAILURE_CODES = {
|
|
|
15744
15744
|
ANDROID_DEVTOOLS_WRONG_PLATFORM: "ANDROID_DEVTOOLS_WRONG_PLATFORM",
|
|
15745
15745
|
ANDROID_DEVTOOLS_DEVICE_ID_INVALID: "ANDROID_DEVTOOLS_DEVICE_ID_INVALID",
|
|
15746
15746
|
ANDROID_DEVTOOLS_HELPER_TERMINATED: "ANDROID_DEVTOOLS_HELPER_TERMINATED",
|
|
15747
|
+
ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED: "ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED",
|
|
15748
|
+
ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED: "ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED",
|
|
15747
15749
|
ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED: "ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED",
|
|
15748
15750
|
ANDROID_DEVTOOLS_RPC_ERROR: "ANDROID_DEVTOOLS_RPC_ERROR",
|
|
15749
15751
|
ANDROID_DEVTOOLS_RPC_TIMEOUT: "ANDROID_DEVTOOLS_RPC_TIMEOUT",
|
|
@@ -16710,7 +16712,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16710
16712
|
var SESSION_ID = randomUUID4();
|
|
16711
16713
|
function readCliVersion() {
|
|
16712
16714
|
if (true) {
|
|
16713
|
-
return "0.25.1-next.
|
|
16715
|
+
return "0.25.1-next.35";
|
|
16714
16716
|
}
|
|
16715
16717
|
return "0.0.0";
|
|
16716
16718
|
}
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -16552,6 +16552,8 @@ var FAILURE_CODES = {
|
|
|
16552
16552
|
ANDROID_DEVTOOLS_WRONG_PLATFORM: "ANDROID_DEVTOOLS_WRONG_PLATFORM",
|
|
16553
16553
|
ANDROID_DEVTOOLS_DEVICE_ID_INVALID: "ANDROID_DEVTOOLS_DEVICE_ID_INVALID",
|
|
16554
16554
|
ANDROID_DEVTOOLS_HELPER_TERMINATED: "ANDROID_DEVTOOLS_HELPER_TERMINATED",
|
|
16555
|
+
ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED: "ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED",
|
|
16556
|
+
ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED: "ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED",
|
|
16555
16557
|
ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED: "ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED",
|
|
16556
16558
|
ANDROID_DEVTOOLS_RPC_ERROR: "ANDROID_DEVTOOLS_RPC_ERROR",
|
|
16557
16559
|
ANDROID_DEVTOOLS_RPC_TIMEOUT: "ANDROID_DEVTOOLS_RPC_TIMEOUT",
|
package/dist/tool-server.cjs
CHANGED
|
@@ -698,6 +698,8 @@ var init_failure_codes = __esm({
|
|
|
698
698
|
ANDROID_DEVTOOLS_WRONG_PLATFORM: "ANDROID_DEVTOOLS_WRONG_PLATFORM",
|
|
699
699
|
ANDROID_DEVTOOLS_DEVICE_ID_INVALID: "ANDROID_DEVTOOLS_DEVICE_ID_INVALID",
|
|
700
700
|
ANDROID_DEVTOOLS_HELPER_TERMINATED: "ANDROID_DEVTOOLS_HELPER_TERMINATED",
|
|
701
|
+
ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED: "ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED",
|
|
702
|
+
ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED: "ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED",
|
|
701
703
|
ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED: "ANDROID_DEVTOOLS_RPC_CLIENT_CLOSED",
|
|
702
704
|
ANDROID_DEVTOOLS_RPC_ERROR: "ANDROID_DEVTOOLS_RPC_ERROR",
|
|
703
705
|
ANDROID_DEVTOOLS_RPC_TIMEOUT: "ANDROID_DEVTOOLS_RPC_TIMEOUT",
|
|
@@ -77006,8 +77008,8 @@ async function emulatorSupportsFlag(flag, options = {}) {
|
|
|
77006
77008
|
} catch {
|
|
77007
77009
|
return false;
|
|
77008
77010
|
}
|
|
77009
|
-
const
|
|
77010
|
-
const cached3 = emulatorFlagSupportCache.get(
|
|
77011
|
+
const cacheKey2 = `${emulatorPath}|${flag}`;
|
|
77012
|
+
const cached3 = emulatorFlagSupportCache.get(cacheKey2);
|
|
77011
77013
|
if (cached3 !== void 0) return cached3;
|
|
77012
77014
|
let output;
|
|
77013
77015
|
let failure = null;
|
|
@@ -77034,7 +77036,7 @@ async function emulatorSupportsFlag(flag, options = {}) {
|
|
|
77034
77036
|
return false;
|
|
77035
77037
|
}
|
|
77036
77038
|
const supported = output.includes(flag);
|
|
77037
|
-
emulatorFlagSupportCache.set(
|
|
77039
|
+
emulatorFlagSupportCache.set(cacheKey2, supported);
|
|
77038
77040
|
return supported;
|
|
77039
77041
|
}
|
|
77040
77042
|
function describeAdbFailure(args, err) {
|
|
@@ -94704,7 +94706,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
94704
94706
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
94705
94707
|
function readCliVersion() {
|
|
94706
94708
|
if (true) {
|
|
94707
|
-
return "0.25.1-next.
|
|
94709
|
+
return "0.25.1-next.35";
|
|
94708
94710
|
}
|
|
94709
94711
|
return "0.0.0";
|
|
94710
94712
|
}
|
|
@@ -107264,6 +107266,7 @@ async function openMoqClient(udid) {
|
|
|
107264
107266
|
async function openMoqClientFromInfo(info) {
|
|
107265
107267
|
await installNodeWebTransport();
|
|
107266
107268
|
const session = new MoqDeviceSession(await connectMoq(info), { publishPath: PUBLISH_PATH });
|
|
107269
|
+
disposeWhenTransportDies(session);
|
|
107267
107270
|
return {
|
|
107268
107271
|
sendControl: (payload) => session.sendControl(payload),
|
|
107269
107272
|
async screenshot(opts) {
|
|
@@ -107274,6 +107277,15 @@ async function openMoqClientFromInfo(info) {
|
|
|
107274
107277
|
}
|
|
107275
107278
|
};
|
|
107276
107279
|
}
|
|
107280
|
+
function disposeWhenTransportDies(session) {
|
|
107281
|
+
const dispose = () => {
|
|
107282
|
+
try {
|
|
107283
|
+
session.close();
|
|
107284
|
+
} catch {
|
|
107285
|
+
}
|
|
107286
|
+
};
|
|
107287
|
+
void session.closed.then(dispose, dispose);
|
|
107288
|
+
}
|
|
107277
107289
|
|
|
107278
107290
|
// ../tool-server/src/utils/simulator-client.ts
|
|
107279
107291
|
init_wrapper();
|
|
@@ -107342,17 +107354,26 @@ function failAllPending(conn, makeError) {
|
|
|
107342
107354
|
conn.pending.clear();
|
|
107343
107355
|
for (const entry of entries) entry.settle(makeError(entry.cmd));
|
|
107344
107356
|
}
|
|
107357
|
+
var COMMAND_TRANSPORT_FAILURE = {
|
|
107358
|
+
error_code: FAILURE_CODES.SIMULATOR_COMMAND_TRANSPORT_FAILED,
|
|
107359
|
+
failure_stage: "simulator_command_transport",
|
|
107360
|
+
failure_area: "tool_server",
|
|
107361
|
+
error_kind: "network",
|
|
107362
|
+
network_failure: "connection_reset",
|
|
107363
|
+
failure_command: "simulator_server"
|
|
107364
|
+
};
|
|
107345
107365
|
function transportError(cmd, apiUrl, detail) {
|
|
107346
107366
|
return new FailureError(
|
|
107347
107367
|
`simulator-server did not accept the '${cmd}' command: ${detail}. The command was NOT delivered to the device. Check that the simulator is still booted and the simulator-server for ${apiUrl} is running.`,
|
|
107348
|
-
|
|
107349
|
-
|
|
107350
|
-
|
|
107351
|
-
|
|
107352
|
-
|
|
107353
|
-
|
|
107354
|
-
|
|
107355
|
-
|
|
107368
|
+
COMMAND_TRANSPORT_FAILURE
|
|
107369
|
+
);
|
|
107370
|
+
}
|
|
107371
|
+
function remoteTransportError(cmd, cause) {
|
|
107372
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
107373
|
+
return wrapFailure(
|
|
107374
|
+
cause,
|
|
107375
|
+
COMMAND_TRANSPORT_FAILURE,
|
|
107376
|
+
`The remote simulator did not accept the '${cmd}' command: ${detail}. The command was NOT delivered to the device. Call stop-simulator-server for this device and retry - the next call opens a new cloud session. If the machine itself was released, acquire one again before retrying.`
|
|
107356
107377
|
);
|
|
107357
107378
|
}
|
|
107358
107379
|
function getOrCreateConnection(api) {
|
|
@@ -107408,13 +107429,10 @@ function getOrCreateConnection(api) {
|
|
|
107408
107429
|
return conn;
|
|
107409
107430
|
}
|
|
107410
107431
|
function sendCommand(api, cmd) {
|
|
107411
|
-
|
|
107412
|
-
|
|
107413
|
-
return Promise.resolve();
|
|
107414
|
-
}
|
|
107432
|
+
const cmdName = typeof cmd.cmd === "string" ? cmd.cmd : "unknown";
|
|
107433
|
+
if (api.transport) return sendViaTransport(api.transport, cmd, cmdName);
|
|
107415
107434
|
const conn = getOrCreateConnection(api);
|
|
107416
107435
|
const id = String(++cmdId);
|
|
107417
|
-
const cmdName = typeof cmd.cmd === "string" ? cmd.cmd : "unknown";
|
|
107418
107436
|
const payload = JSON.stringify({ id, ...cmd });
|
|
107419
107437
|
return new Promise((resolve14, reject) => {
|
|
107420
107438
|
let done = false;
|
|
@@ -107616,32 +107634,36 @@ async function httpScreenshot(api, rotation, signal, scale) {
|
|
|
107616
107634
|
);
|
|
107617
107635
|
}
|
|
107618
107636
|
}
|
|
107637
|
+
async function sendViaTransport(transport, cmd, cmdName) {
|
|
107638
|
+
const sent = routeViaTransport(transport, cmd);
|
|
107639
|
+
try {
|
|
107640
|
+
await sent;
|
|
107641
|
+
} catch (cause) {
|
|
107642
|
+
throw remoteTransportError(cmdName, cause);
|
|
107643
|
+
}
|
|
107644
|
+
}
|
|
107619
107645
|
function routeViaTransport(transport, cmd) {
|
|
107620
107646
|
switch (cmd.cmd) {
|
|
107621
107647
|
case "touch": {
|
|
107622
107648
|
const sx = cmd.second_x ?? cmd.secondX;
|
|
107623
107649
|
const sy = cmd.second_y ?? cmd.secondY;
|
|
107624
|
-
transport.touch({
|
|
107650
|
+
return transport.touch({
|
|
107625
107651
|
type: cmd.type,
|
|
107626
107652
|
x: cmd.x,
|
|
107627
107653
|
y: cmd.y,
|
|
107628
107654
|
secondX: sx == null ? void 0 : sx,
|
|
107629
107655
|
secondY: sy == null ? void 0 : sy
|
|
107630
107656
|
});
|
|
107631
|
-
return;
|
|
107632
107657
|
}
|
|
107633
107658
|
case "button":
|
|
107634
|
-
transport.button({
|
|
107659
|
+
return transport.button({
|
|
107635
107660
|
direction: cmd.direction,
|
|
107636
107661
|
button: cmd.button
|
|
107637
107662
|
});
|
|
107638
|
-
return;
|
|
107639
107663
|
case "rotate":
|
|
107640
|
-
transport.rotate(cmd.direction);
|
|
107641
|
-
return;
|
|
107664
|
+
return transport.rotate(cmd.direction);
|
|
107642
107665
|
case "key":
|
|
107643
|
-
transport.pressKey(cmd.direction, cmd.code);
|
|
107644
|
-
return;
|
|
107666
|
+
return transport.pressKey(cmd.direction, cmd.code);
|
|
107645
107667
|
default:
|
|
107646
107668
|
throw new Error(`MoQ transport does not implement sendCommand cmd '${String(cmd.cmd)}'`);
|
|
107647
107669
|
}
|
|
@@ -107655,8 +107677,8 @@ function createMoqTransport(moq, options) {
|
|
|
107655
107677
|
return { url: (0, import_node_url.pathToFileURL)(file2).toString(), path: file2 };
|
|
107656
107678
|
};
|
|
107657
107679
|
return {
|
|
107658
|
-
touch(opts) {
|
|
107659
|
-
|
|
107680
|
+
async touch(opts) {
|
|
107681
|
+
await moq.sendControl(
|
|
107660
107682
|
encodeTouch({
|
|
107661
107683
|
action: opts.type,
|
|
107662
107684
|
x: opts.x,
|
|
@@ -107666,17 +107688,17 @@ function createMoqTransport(moq, options) {
|
|
|
107666
107688
|
})
|
|
107667
107689
|
);
|
|
107668
107690
|
},
|
|
107669
|
-
button(opts) {
|
|
107670
|
-
|
|
107691
|
+
async button(opts) {
|
|
107692
|
+
await moq.sendControl(encodeButton({ action: opts.direction, button: opts.button }));
|
|
107671
107693
|
},
|
|
107672
|
-
rotate(direction) {
|
|
107673
|
-
|
|
107694
|
+
async rotate(direction) {
|
|
107695
|
+
await moq.sendControl(encodeRotate(direction));
|
|
107674
107696
|
},
|
|
107675
107697
|
async paste(text) {
|
|
107676
107698
|
await options.pasteText(text);
|
|
107677
107699
|
},
|
|
107678
|
-
pressKey(direction, keyCode) {
|
|
107679
|
-
|
|
107700
|
+
async pressKey(direction, keyCode) {
|
|
107701
|
+
await moq.sendControl(encodeKey({ action: direction, code: keyCode }));
|
|
107680
107702
|
},
|
|
107681
107703
|
async screenshot(opts) {
|
|
107682
107704
|
const scale = opts?.scale ?? getScreenshotScale();
|
|
@@ -107709,17 +107731,20 @@ async function buildRemoteInstance(device) {
|
|
|
107709
107731
|
await simctlPbcopy(device.id, text);
|
|
107710
107732
|
const CMD = 227;
|
|
107711
107733
|
const V = 25;
|
|
107712
|
-
await
|
|
107713
|
-
await
|
|
107714
|
-
await
|
|
107715
|
-
await
|
|
107734
|
+
await api.pressKey("Down", CMD);
|
|
107735
|
+
await api.pressKey("Down", V);
|
|
107736
|
+
await api.pressKey("Up", V);
|
|
107737
|
+
await api.pressKey("Up", CMD);
|
|
107716
107738
|
}
|
|
107717
107739
|
});
|
|
107718
107740
|
const stubUrl = `moq+remote://${device.id}`;
|
|
107719
107741
|
const api = {
|
|
107720
107742
|
apiUrl: stubUrl,
|
|
107721
107743
|
streamUrl: stubUrl,
|
|
107722
|
-
|
|
107744
|
+
// Through `sendCommand`, as the attached instance below does, so a key the
|
|
107745
|
+
// session refuses reports the same failure as a refused touch instead of a
|
|
107746
|
+
// bare SDK error the caller cannot classify.
|
|
107747
|
+
pressKey: (direction, keyCode) => sendCommand(api, { cmd: "key", code: keyCode, direction }),
|
|
107723
107748
|
transport
|
|
107724
107749
|
};
|
|
107725
107750
|
return {
|
|
@@ -112874,10 +112899,6 @@ init_android_binary();
|
|
|
112874
112899
|
|
|
112875
112900
|
// ../tool-server/src/utils/android-helper-install.ts
|
|
112876
112901
|
init_adb();
|
|
112877
|
-
var installedHelpers = /* @__PURE__ */ new Map();
|
|
112878
|
-
function cacheKey(serial, versionCode) {
|
|
112879
|
-
return `${serial}|${versionCode}`;
|
|
112880
|
-
}
|
|
112881
112902
|
async function probeInstalledVersion(serial, packageName) {
|
|
112882
112903
|
let out;
|
|
112883
112904
|
try {
|
|
@@ -112900,17 +112921,17 @@ async function probeInstalledVersion(serial, packageName) {
|
|
|
112900
112921
|
}
|
|
112901
112922
|
return { installed: false, versionCode: null };
|
|
112902
112923
|
}
|
|
112903
|
-
async function ensureAndroidDevtoolsInstalled(serial) {
|
|
112924
|
+
async function ensureAndroidDevtoolsInstalled(serial, options = {}) {
|
|
112904
112925
|
const manifest = helperManifest();
|
|
112905
|
-
|
|
112906
|
-
|
|
112907
|
-
|
|
112908
|
-
|
|
112909
|
-
|
|
112910
|
-
return;
|
|
112926
|
+
if (!options.force) {
|
|
112927
|
+
const probe3 = await probeInstalledVersion(serial, manifest.packageName);
|
|
112928
|
+
if (probe3.installed && (probe3.versionCode === null || probe3.versionCode >= manifest.versionCode)) {
|
|
112929
|
+
return;
|
|
112930
|
+
}
|
|
112911
112931
|
}
|
|
112912
112932
|
const apkPath = bundledHelperApkPath();
|
|
112913
|
-
const
|
|
112933
|
+
const flags = options.force ? [...manifest.installFlags, "-d"] : manifest.installFlags;
|
|
112934
|
+
const args = ["-s", serial, "install", ...flags, apkPath];
|
|
112914
112935
|
try {
|
|
112915
112936
|
await runAdb(args, { timeoutMs: 6e4 });
|
|
112916
112937
|
} catch (err) {
|
|
@@ -112925,7 +112946,6 @@ async function ensureAndroidDevtoolsInstalled(serial) {
|
|
|
112925
112946
|
throw err;
|
|
112926
112947
|
}
|
|
112927
112948
|
}
|
|
112928
|
-
installedHelpers.set(key2, true);
|
|
112929
112949
|
}
|
|
112930
112950
|
|
|
112931
112951
|
// ../tool-server/src/utils/android-devtools-client.ts
|
|
@@ -113069,14 +113089,28 @@ function androidDevtoolsRef(device) {
|
|
|
113069
113089
|
};
|
|
113070
113090
|
}
|
|
113071
113091
|
var READY_TIMEOUT_MS2 = 3e4;
|
|
113092
|
+
var EXIT_GRACE_MS = 200;
|
|
113072
113093
|
var HELPER_PORT_MARKER = /^INSTRUMENTATION_STATUS:\s*port=(\d+)/;
|
|
113073
113094
|
var ADB_FORWARD_PORT_MARKER = /^(\d+)\s*$/;
|
|
113095
|
+
var HELPER_STATUS_MARKER = /^INSTRUMENTATION_STATUS:\s*Error=/;
|
|
113096
|
+
var HELPER_STATUS_MAX_CHARS = 400;
|
|
113097
|
+
function classifyHelperSpawnFault(text) {
|
|
113098
|
+
return /Unable to find instrumentation (?:info|target package)/i.test(text) ? "instrumentation-missing" : "unknown";
|
|
113099
|
+
}
|
|
113100
|
+
var HelperSpawnError = class extends FailureError {
|
|
113101
|
+
fault;
|
|
113102
|
+
constructor(message, signal, fault) {
|
|
113103
|
+
super(message, signal);
|
|
113104
|
+
this.name = "HelperSpawnError";
|
|
113105
|
+
this.fault = fault;
|
|
113106
|
+
}
|
|
113107
|
+
};
|
|
113074
113108
|
async function spawnHelper(serial) {
|
|
113075
113109
|
const manifest = helperManifest();
|
|
113076
113110
|
const adbPath = await resolveAndroidBinary("adb");
|
|
113077
113111
|
if (!adbPath) {
|
|
113078
113112
|
throw new FailureError(
|
|
113079
|
-
"`adb` not found on PATH or under `$ANDROID_HOME/platform-tools` while spawning android
|
|
113113
|
+
"`adb` not found on PATH or under `$ANDROID_HOME/platform-tools` while spawning the argent android helper.",
|
|
113080
113114
|
{
|
|
113081
113115
|
error_code: FAILURE_CODES.ANDROID_DEVTOOLS_ADB_NOT_FOUND,
|
|
113082
113116
|
failure_stage: "android_devtools_spawn_helper",
|
|
@@ -113095,10 +113129,13 @@ async function spawnHelper(serial) {
|
|
|
113095
113129
|
let localPort = null;
|
|
113096
113130
|
let settled = false;
|
|
113097
113131
|
let stderrBuf = "";
|
|
113132
|
+
let statusBuf = "";
|
|
113133
|
+
let exitGrace;
|
|
113098
113134
|
const settle = (fn, cleanup) => {
|
|
113099
113135
|
if (settled) return;
|
|
113100
113136
|
settled = true;
|
|
113101
113137
|
clearTimeout(timer);
|
|
113138
|
+
clearTimeout(exitGrace);
|
|
113102
113139
|
rl.close();
|
|
113103
113140
|
cleanup?.();
|
|
113104
113141
|
fn();
|
|
@@ -113106,6 +113143,9 @@ async function spawnHelper(serial) {
|
|
|
113106
113143
|
const rl = readline2.createInterface({ input: proc.stdout });
|
|
113107
113144
|
rl.on("line", async (rawLine) => {
|
|
113108
113145
|
const line = rawLine.trim();
|
|
113146
|
+
if (statusBuf.length < HELPER_STATUS_MAX_CHARS && HELPER_STATUS_MARKER.test(line)) {
|
|
113147
|
+
statusBuf = (statusBuf ? `${statusBuf} ${line}` : line).slice(0, HELPER_STATUS_MAX_CHARS);
|
|
113148
|
+
}
|
|
113109
113149
|
const portMatch = HELPER_PORT_MARKER.exec(line);
|
|
113110
113150
|
if (!portMatch || devicePort !== null) return;
|
|
113111
113151
|
devicePort = parseInt(portMatch[1], 10);
|
|
@@ -113135,25 +113175,32 @@ async function spawnHelper(serial) {
|
|
|
113135
113175
|
stderrBuf += data.toString("utf-8");
|
|
113136
113176
|
if (stderrBuf.length > 4 * 1024) stderrBuf = stderrBuf.slice(-4 * 1024);
|
|
113137
113177
|
});
|
|
113138
|
-
|
|
113139
|
-
|
|
113140
|
-
|
|
113141
|
-
|
|
113142
|
-
|
|
113143
|
-
|
|
113144
|
-
|
|
113145
|
-
|
|
113146
|
-
|
|
113147
|
-
|
|
113148
|
-
|
|
113149
|
-
|
|
113150
|
-
|
|
113151
|
-
|
|
113152
|
-
}
|
|
113153
|
-
|
|
113178
|
+
let exitCode = null;
|
|
113179
|
+
let exitSignal = null;
|
|
113180
|
+
const rejectExited = () => {
|
|
113181
|
+
const detail = statusBuf ? statusBuf : stderrBuf.trim() ? `code=${exitCode} signal=${exitSignal}. stderr=${stderrBuf.trim().slice(0, 200)}` : `code=${exitCode} signal=${exitSignal}`;
|
|
113182
|
+
reject(
|
|
113183
|
+
new HelperSpawnError(
|
|
113184
|
+
`am instrument exited before becoming ready: ${detail}`,
|
|
113185
|
+
{
|
|
113186
|
+
error_code: FAILURE_CODES.ANDROID_DEVTOOLS_HELPER_EXITED_BEFORE_READY,
|
|
113187
|
+
failure_stage: "android_devtools_helper_ready",
|
|
113188
|
+
failure_area: "tool_server",
|
|
113189
|
+
error_kind: "subprocess",
|
|
113190
|
+
failure_command: "android_devtools",
|
|
113191
|
+
...typeof exitCode === "number" ? { failure_exit_code: exitCode } : {},
|
|
113192
|
+
...exitSignal === "SIGABRT" || exitSignal === "SIGHUP" || exitSignal === "SIGINT" || exitSignal === "SIGKILL" || exitSignal === "SIGQUIT" || exitSignal === "SIGTERM" ? { failure_signal: exitSignal } : {}
|
|
113193
|
+
},
|
|
113194
|
+
classifyHelperSpawnFault(statusBuf)
|
|
113154
113195
|
)
|
|
113155
113196
|
);
|
|
113197
|
+
};
|
|
113198
|
+
proc.on("exit", (code, signal) => {
|
|
113199
|
+
exitCode = code;
|
|
113200
|
+
exitSignal = signal;
|
|
113201
|
+
exitGrace = setTimeout(() => settle(rejectExited), EXIT_GRACE_MS);
|
|
113156
113202
|
});
|
|
113203
|
+
proc.on("close", () => settle(rejectExited));
|
|
113157
113204
|
proc.on("error", (err) => {
|
|
113158
113205
|
settle(
|
|
113159
113206
|
() => reject(
|
|
@@ -113188,6 +113235,50 @@ async function spawnHelper(serial) {
|
|
|
113188
113235
|
}, READY_TIMEOUT_MS2);
|
|
113189
113236
|
});
|
|
113190
113237
|
}
|
|
113238
|
+
async function installHelper(serial, options) {
|
|
113239
|
+
try {
|
|
113240
|
+
await ensureAndroidDevtoolsInstalled(serial, options);
|
|
113241
|
+
} catch (err) {
|
|
113242
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
113243
|
+
const reason = cause.message.replace(/^.*? failed: /s, "").replace(/\s+/g, " ").trim().slice(0, 200);
|
|
113244
|
+
throw new FailureError(
|
|
113245
|
+
`the argent android helper is not installed on ${serial} and could not be installed: ${reason}`,
|
|
113246
|
+
{
|
|
113247
|
+
error_code: FAILURE_CODES.ANDROID_DEVTOOLS_HELPER_INSTALL_FAILED,
|
|
113248
|
+
failure_stage: "android_devtools_helper_install",
|
|
113249
|
+
failure_area: "tool_server",
|
|
113250
|
+
error_kind: "subprocess",
|
|
113251
|
+
failure_command: "adb"
|
|
113252
|
+
},
|
|
113253
|
+
{ cause }
|
|
113254
|
+
);
|
|
113255
|
+
}
|
|
113256
|
+
}
|
|
113257
|
+
async function spawnHelperWithRepair(serial) {
|
|
113258
|
+
await installHelper(serial, {});
|
|
113259
|
+
try {
|
|
113260
|
+
return await spawnHelper(serial);
|
|
113261
|
+
} catch (err) {
|
|
113262
|
+
if (!(err instanceof HelperSpawnError) || err.fault !== "instrumentation-missing") throw err;
|
|
113263
|
+
await installHelper(serial, { force: true });
|
|
113264
|
+
try {
|
|
113265
|
+
return await spawnHelper(serial);
|
|
113266
|
+
} catch (repairErr) {
|
|
113267
|
+
if (!(repairErr instanceof HelperSpawnError)) throw repairErr;
|
|
113268
|
+
throw new FailureError(
|
|
113269
|
+
`the argent android helper could not start on ${serial} even after reinstalling it: ${repairErr.message}`,
|
|
113270
|
+
{
|
|
113271
|
+
error_code: FAILURE_CODES.ANDROID_DEVTOOLS_HELPER_REPAIR_FAILED,
|
|
113272
|
+
failure_stage: "android_devtools_helper_repair",
|
|
113273
|
+
failure_area: "tool_server",
|
|
113274
|
+
error_kind: "subprocess",
|
|
113275
|
+
failure_command: "android_devtools"
|
|
113276
|
+
},
|
|
113277
|
+
{ cause: repairErr }
|
|
113278
|
+
);
|
|
113279
|
+
}
|
|
113280
|
+
}
|
|
113281
|
+
}
|
|
113191
113282
|
async function removeAdbForward(serial, localPort) {
|
|
113192
113283
|
try {
|
|
113193
113284
|
await runAdb(["-s", serial, "forward", "--remove", `tcp:${localPort}`], { timeoutMs: 5e3 });
|
|
@@ -113237,8 +113328,7 @@ var androidDevtoolsBlueprint = {
|
|
|
113237
113328
|
}
|
|
113238
113329
|
const serial = device.id;
|
|
113239
113330
|
const events = new TypedEventEmitter();
|
|
113240
|
-
await
|
|
113241
|
-
const spawned = await spawnHelper(serial);
|
|
113331
|
+
const spawned = await spawnHelperWithRepair(serial);
|
|
113242
113332
|
let ready2 = false;
|
|
113243
113333
|
let disposed = false;
|
|
113244
113334
|
let client2;
|
|
@@ -115505,13 +115595,13 @@ async function ensureRunnerArtifact(config2, opts = {}) {
|
|
|
115505
115595
|
xcodeVersionFingerprint()
|
|
115506
115596
|
]);
|
|
115507
115597
|
const staticArgs = runnerBuildStaticArgs(projectPath, config2);
|
|
115508
|
-
const
|
|
115598
|
+
const cacheKey2 = computeRunnerCacheKey(sourcesHash, xcodeVersion, staticArgs);
|
|
115509
115599
|
const derivedDataPath = derivedDir();
|
|
115510
115600
|
const build = opts.build ?? buildRunnerArtifact;
|
|
115511
115601
|
return withRunnerBuildLock(async () => {
|
|
115512
115602
|
const stampPath = path21.join(derivedDataPath, CACHE_KEY_FILE);
|
|
115513
115603
|
const stamped = await fsp.readFile(stampPath, "utf8").catch(() => null);
|
|
115514
|
-
if (!opts.force && stamped ===
|
|
115604
|
+
if (!opts.force && stamped === cacheKey2) {
|
|
115515
115605
|
const cached3 = findBaseXctestrun(derivedDataPath);
|
|
115516
115606
|
const expiresAt = await readRunnerExpiryDate(derivedDataPath);
|
|
115517
115607
|
const needsRenew = expiresAt !== null && profileNeedsRenewal(expiresAt, /* @__PURE__ */ new Date());
|
|
@@ -115523,14 +115613,14 @@ async function ensureRunnerArtifact(config2, opts = {}) {
|
|
|
115523
115613
|
};
|
|
115524
115614
|
}
|
|
115525
115615
|
}
|
|
115526
|
-
if (stamped !==
|
|
115616
|
+
if (stamped !== cacheKey2) {
|
|
115527
115617
|
await fsp.rm(derivedDataPath, {
|
|
115528
115618
|
recursive: true,
|
|
115529
115619
|
force: true
|
|
115530
115620
|
});
|
|
115531
115621
|
}
|
|
115532
115622
|
const built = await build(derivedDataPath, staticArgs, opts.destinationUdid);
|
|
115533
|
-
await fsp.writeFile(stampPath,
|
|
115623
|
+
await fsp.writeFile(stampPath, cacheKey2);
|
|
115534
115624
|
return built;
|
|
115535
115625
|
});
|
|
115536
115626
|
}
|
|
@@ -119829,17 +119919,17 @@ var reactProfilerSessionBlueprint = {
|
|
|
119829
119919
|
}
|
|
119830
119920
|
};
|
|
119831
119921
|
var profilerPathsCache = /* @__PURE__ */ new Map();
|
|
119832
|
-
function
|
|
119922
|
+
function cacheKey(port, deviceId) {
|
|
119833
119923
|
return `${port}:${deviceId}`;
|
|
119834
119924
|
}
|
|
119835
119925
|
function cacheProfilerPaths(port, paths, deviceId) {
|
|
119836
|
-
profilerPathsCache.set(
|
|
119926
|
+
profilerPathsCache.set(cacheKey(port, deviceId), paths);
|
|
119837
119927
|
}
|
|
119838
119928
|
function getCachedProfilerPaths(port, deviceId) {
|
|
119839
|
-
return profilerPathsCache.get(
|
|
119929
|
+
return profilerPathsCache.get(cacheKey(port, deviceId));
|
|
119840
119930
|
}
|
|
119841
119931
|
function clearCachedProfilerPaths(port, deviceId) {
|
|
119842
|
-
profilerPathsCache.delete(
|
|
119932
|
+
profilerPathsCache.delete(cacheKey(port, deviceId));
|
|
119843
119933
|
}
|
|
119844
119934
|
|
|
119845
119935
|
// ../tool-server/src/tools/devices/boot-device.ts
|
|
@@ -148067,10 +148157,7 @@ async function queryAndroidFullHierarchy(registry2, device) {
|
|
|
148067
148157
|
devtools = await registry2.resolveService(ref.urn, ref.options);
|
|
148068
148158
|
} catch (err) {
|
|
148069
148159
|
const msg = err instanceof Error ? err.message : String(err);
|
|
148070
|
-
throw new Error(
|
|
148071
|
-
`the android devtools helper is unavailable (${msg}) \u2014 flows resolve testID selectors against the full hierarchy it serves; confirm the device is unlocked and the helper can be installed (\`adb install -t\`)`,
|
|
148072
|
-
{ cause: err }
|
|
148073
|
-
);
|
|
148160
|
+
throw new Error(`the argent android helper is unavailable: ${msg}`, { cause: err });
|
|
148074
148161
|
}
|
|
148075
148162
|
const [{ xml }, size] = await Promise.all([
|
|
148076
148163
|
// clearCache: await/assert polls must see text changes, not cached reads.
|
|
@@ -149661,6 +149748,10 @@ function roleOnlySelectorWarning(selector) {
|
|
|
149661
149748
|
if (selector.text !== void 0 || selector.textMatches !== void 0) return void 0;
|
|
149662
149749
|
return `selector ${describeSelector(selector)} matches by role alone (the tapped element has no id or visible text) \u2014 replay takes whichever element of that role ranks first, so re-record against a labelled element if that is not reliably this one`;
|
|
149663
149750
|
}
|
|
149751
|
+
function innermostTreeReason(message) {
|
|
149752
|
+
const unwrapped = /helper is unavailable:\s*(.+)/s.exec(message)?.[1] ?? message;
|
|
149753
|
+
return unwrapped.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
149754
|
+
}
|
|
149664
149755
|
async function captureTapSelector(registry2, session, udid, point) {
|
|
149665
149756
|
try {
|
|
149666
149757
|
const device = resolveDevice(udid);
|
|
@@ -149692,8 +149783,9 @@ async function captureTapSelector(registry2, session, udid, point) {
|
|
|
149692
149783
|
].filter((w) => w !== void 0);
|
|
149693
149784
|
return { selector, ...warnings.length > 0 ? { warning: warnings.join("; ") } : {} };
|
|
149694
149785
|
} catch (err) {
|
|
149786
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
149695
149787
|
return {
|
|
149696
|
-
warning: `selector capture failed (${
|
|
149788
|
+
warning: `selector capture failed (${innermostTreeReason(message)}); kept coordinates`
|
|
149697
149789
|
};
|
|
149698
149790
|
}
|
|
149699
149791
|
}
|
|
@@ -154201,9 +154293,9 @@ async function androidDevtoolsReady(registry2, device) {
|
|
|
154201
154293
|
try {
|
|
154202
154294
|
const ref = androidDevtoolsRef(device);
|
|
154203
154295
|
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
154204
|
-
return api.isReady();
|
|
154205
|
-
} catch {
|
|
154206
|
-
return false;
|
|
154296
|
+
return { ready: api.isReady() };
|
|
154297
|
+
} catch (err) {
|
|
154298
|
+
return { ready: false, reason: err instanceof Error ? err.message : String(err) };
|
|
154207
154299
|
}
|
|
154208
154300
|
}
|
|
154209
154301
|
async function treeSourceGate(registry2, device, bundleId, signal) {
|
|
@@ -154223,9 +154315,9 @@ async function treeSourceGate(registry2, device, bundleId, signal) {
|
|
|
154223
154315
|
}
|
|
154224
154316
|
}
|
|
154225
154317
|
if (device.platform === "android" && !signal?.aborted) {
|
|
154226
|
-
const ready2 = await androidDevtoolsReady(registry2, device);
|
|
154318
|
+
const { ready: ready2, reason } = await androidDevtoolsReady(registry2, device);
|
|
154227
154319
|
if (!ready2 && !signal?.aborted) {
|
|
154228
|
-
return
|
|
154320
|
+
return reason ? `the argent android helper is unavailable: ${reason}` : `the argent android helper is unavailable (full-hierarchy source for testID selectors).`;
|
|
154229
154321
|
}
|
|
154230
154322
|
}
|
|
154231
154323
|
if (device.platform === "vega" && !signal?.aborted) {
|
package/package.json
CHANGED
|
@@ -74,11 +74,11 @@ A normally injectable app that is broken in the environment gets the same coordi
|
|
|
74
74
|
|
|
75
75
|
While the required source is down, selector failures and raw-point capture are void. Restore the source and re-record affected taps.
|
|
76
76
|
|
|
77
|
-
| Platform | Symptom
|
|
78
|
-
| -------- |
|
|
79
|
-
| Android | Cannot reach the
|
|
80
|
-
| Chromium | No reachable CDP session
|
|
81
|
-
| Vega | Toolkit returns no page source
|
|
77
|
+
| Platform | Symptom | Recovery |
|
|
78
|
+
| -------- | -------------------------------------- | -------------------------------------------------------------------------------- |
|
|
79
|
+
| Android | Cannot reach the argent android helper | Argent reinstalls it once; if it persists, read the device's reason in the error |
|
|
80
|
+
| Chromium | No reachable CDP session | Boot again with `electronAppPath` and remote debugging |
|
|
81
|
+
| Vega | Toolkit returns no page source | Relaunch an app built with automation support |
|
|
82
82
|
|
|
83
83
|
On Android, healthy `describe` output does not prove the flow tree is available. It can fall back to legacy `uiautomator`, while the runner refuses that trimmed fallback.
|
|
84
84
|
|