@validate.qa/runner 1.0.68 → 1.0.69
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.js +278 -208
- package/dist/cli.mjs +274 -204
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -11298,7 +11298,7 @@ var require_thread_stream = __commonJS({
|
|
|
11298
11298
|
var { version } = require_package();
|
|
11299
11299
|
var { EventEmitter: EventEmitter2 } = __require("events");
|
|
11300
11300
|
var { Worker } = __require("worker_threads");
|
|
11301
|
-
var { join:
|
|
11301
|
+
var { join: join8 } = __require("path");
|
|
11302
11302
|
var { pathToFileURL } = __require("url");
|
|
11303
11303
|
var { wait } = require_wait();
|
|
11304
11304
|
var {
|
|
@@ -11349,7 +11349,7 @@ var require_thread_stream = __commonJS({
|
|
|
11349
11349
|
function createWorker(stream, opts) {
|
|
11350
11350
|
const { filename, workerData } = opts;
|
|
11351
11351
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
11352
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
11352
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join8(__dirname, "lib", "worker.js");
|
|
11353
11353
|
const worker = new Worker(toExecute, {
|
|
11354
11354
|
...opts.workerOpts,
|
|
11355
11355
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -11817,7 +11817,7 @@ var require_transport = __commonJS({
|
|
|
11817
11817
|
var { createRequire } = __require("module");
|
|
11818
11818
|
var { existsSync: existsSync3 } = __require("fs");
|
|
11819
11819
|
var getCallers = require_caller();
|
|
11820
|
-
var { join:
|
|
11820
|
+
var { join: join8, isAbsolute: isAbsolute2, sep } = __require("path");
|
|
11821
11821
|
var { fileURLToPath } = __require("url");
|
|
11822
11822
|
var sleep = require_atomic_sleep();
|
|
11823
11823
|
var onExit = require_on_exit_leak_free();
|
|
@@ -11889,7 +11889,7 @@ var require_transport = __commonJS({
|
|
|
11889
11889
|
return false;
|
|
11890
11890
|
}
|
|
11891
11891
|
}
|
|
11892
|
-
return
|
|
11892
|
+
return isAbsolute2(path) && !existsSync3(path);
|
|
11893
11893
|
}
|
|
11894
11894
|
function stripQuotes(value) {
|
|
11895
11895
|
const first = value[0];
|
|
@@ -11970,7 +11970,7 @@ var require_transport = __commonJS({
|
|
|
11970
11970
|
throw new Error("only one of target or targets can be specified");
|
|
11971
11971
|
}
|
|
11972
11972
|
if (targets) {
|
|
11973
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
11973
|
+
target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
|
|
11974
11974
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
11975
11975
|
return {
|
|
11976
11976
|
...dest,
|
|
@@ -11988,7 +11988,7 @@ var require_transport = __commonJS({
|
|
|
11988
11988
|
});
|
|
11989
11989
|
});
|
|
11990
11990
|
} else if (pipeline) {
|
|
11991
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
11991
|
+
target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
|
|
11992
11992
|
options.pipelines = [pipeline.map((dest) => {
|
|
11993
11993
|
return {
|
|
11994
11994
|
...dest,
|
|
@@ -12007,11 +12007,11 @@ var require_transport = __commonJS({
|
|
|
12007
12007
|
return buildStream(fixTarget(target), options, worker, sync, name);
|
|
12008
12008
|
function fixTarget(origin) {
|
|
12009
12009
|
origin = bundlerOverrides[origin] || origin;
|
|
12010
|
-
if (
|
|
12010
|
+
if (isAbsolute2(origin) || origin.indexOf("file://") === 0) {
|
|
12011
12011
|
return origin;
|
|
12012
12012
|
}
|
|
12013
12013
|
if (origin === "pino/file") {
|
|
12014
|
-
return
|
|
12014
|
+
return join8(__dirname, "..", "file.js");
|
|
12015
12015
|
}
|
|
12016
12016
|
let fixTarget2;
|
|
12017
12017
|
for (const filePath of callers) {
|
|
@@ -12992,7 +12992,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
12992
12992
|
return circularValue;
|
|
12993
12993
|
}
|
|
12994
12994
|
let res = "";
|
|
12995
|
-
let
|
|
12995
|
+
let join8 = ",";
|
|
12996
12996
|
const originalIndentation = indentation;
|
|
12997
12997
|
if (Array.isArray(value)) {
|
|
12998
12998
|
if (value.length === 0) {
|
|
@@ -13006,7 +13006,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
13006
13006
|
indentation += spacer;
|
|
13007
13007
|
res += `
|
|
13008
13008
|
${indentation}`;
|
|
13009
|
-
|
|
13009
|
+
join8 = `,
|
|
13010
13010
|
${indentation}`;
|
|
13011
13011
|
}
|
|
13012
13012
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -13014,13 +13014,13 @@ ${indentation}`;
|
|
|
13014
13014
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13015
13015
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
13016
13016
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
13017
|
-
res +=
|
|
13017
|
+
res += join8;
|
|
13018
13018
|
}
|
|
13019
13019
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
13020
13020
|
res += tmp !== void 0 ? tmp : "null";
|
|
13021
13021
|
if (value.length - 1 > maximumBreadth) {
|
|
13022
13022
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13023
|
-
res += `${
|
|
13023
|
+
res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13024
13024
|
}
|
|
13025
13025
|
if (spacer !== "") {
|
|
13026
13026
|
res += `
|
|
@@ -13041,7 +13041,7 @@ ${originalIndentation}`;
|
|
|
13041
13041
|
let separator = "";
|
|
13042
13042
|
if (spacer !== "") {
|
|
13043
13043
|
indentation += spacer;
|
|
13044
|
-
|
|
13044
|
+
join8 = `,
|
|
13045
13045
|
${indentation}`;
|
|
13046
13046
|
whitespace = " ";
|
|
13047
13047
|
}
|
|
@@ -13055,13 +13055,13 @@ ${indentation}`;
|
|
|
13055
13055
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
13056
13056
|
if (tmp !== void 0) {
|
|
13057
13057
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
13058
|
-
separator =
|
|
13058
|
+
separator = join8;
|
|
13059
13059
|
}
|
|
13060
13060
|
}
|
|
13061
13061
|
if (keyLength > maximumBreadth) {
|
|
13062
13062
|
const removedKeys = keyLength - maximumBreadth;
|
|
13063
13063
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
13064
|
-
separator =
|
|
13064
|
+
separator = join8;
|
|
13065
13065
|
}
|
|
13066
13066
|
if (spacer !== "" && separator.length > 1) {
|
|
13067
13067
|
res = `
|
|
@@ -13102,7 +13102,7 @@ ${originalIndentation}`;
|
|
|
13102
13102
|
}
|
|
13103
13103
|
const originalIndentation = indentation;
|
|
13104
13104
|
let res = "";
|
|
13105
|
-
let
|
|
13105
|
+
let join8 = ",";
|
|
13106
13106
|
if (Array.isArray(value)) {
|
|
13107
13107
|
if (value.length === 0) {
|
|
13108
13108
|
return "[]";
|
|
@@ -13115,7 +13115,7 @@ ${originalIndentation}`;
|
|
|
13115
13115
|
indentation += spacer;
|
|
13116
13116
|
res += `
|
|
13117
13117
|
${indentation}`;
|
|
13118
|
-
|
|
13118
|
+
join8 = `,
|
|
13119
13119
|
${indentation}`;
|
|
13120
13120
|
}
|
|
13121
13121
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -13123,13 +13123,13 @@ ${indentation}`;
|
|
|
13123
13123
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13124
13124
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
13125
13125
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
13126
|
-
res +=
|
|
13126
|
+
res += join8;
|
|
13127
13127
|
}
|
|
13128
13128
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
13129
13129
|
res += tmp !== void 0 ? tmp : "null";
|
|
13130
13130
|
if (value.length - 1 > maximumBreadth) {
|
|
13131
13131
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13132
|
-
res += `${
|
|
13132
|
+
res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13133
13133
|
}
|
|
13134
13134
|
if (spacer !== "") {
|
|
13135
13135
|
res += `
|
|
@@ -13142,7 +13142,7 @@ ${originalIndentation}`;
|
|
|
13142
13142
|
let whitespace = "";
|
|
13143
13143
|
if (spacer !== "") {
|
|
13144
13144
|
indentation += spacer;
|
|
13145
|
-
|
|
13145
|
+
join8 = `,
|
|
13146
13146
|
${indentation}`;
|
|
13147
13147
|
whitespace = " ";
|
|
13148
13148
|
}
|
|
@@ -13151,7 +13151,7 @@ ${indentation}`;
|
|
|
13151
13151
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
13152
13152
|
if (tmp !== void 0) {
|
|
13153
13153
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
13154
|
-
separator =
|
|
13154
|
+
separator = join8;
|
|
13155
13155
|
}
|
|
13156
13156
|
}
|
|
13157
13157
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -13209,20 +13209,20 @@ ${originalIndentation}`;
|
|
|
13209
13209
|
indentation += spacer;
|
|
13210
13210
|
let res2 = `
|
|
13211
13211
|
${indentation}`;
|
|
13212
|
-
const
|
|
13212
|
+
const join9 = `,
|
|
13213
13213
|
${indentation}`;
|
|
13214
13214
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
13215
13215
|
let i = 0;
|
|
13216
13216
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13217
13217
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
13218
13218
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
13219
|
-
res2 +=
|
|
13219
|
+
res2 += join9;
|
|
13220
13220
|
}
|
|
13221
13221
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
13222
13222
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
13223
13223
|
if (value.length - 1 > maximumBreadth) {
|
|
13224
13224
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13225
|
-
res2 += `${
|
|
13225
|
+
res2 += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13226
13226
|
}
|
|
13227
13227
|
res2 += `
|
|
13228
13228
|
${originalIndentation}`;
|
|
@@ -13238,16 +13238,16 @@ ${originalIndentation}`;
|
|
|
13238
13238
|
return '"[Object]"';
|
|
13239
13239
|
}
|
|
13240
13240
|
indentation += spacer;
|
|
13241
|
-
const
|
|
13241
|
+
const join8 = `,
|
|
13242
13242
|
${indentation}`;
|
|
13243
13243
|
let res = "";
|
|
13244
13244
|
let separator = "";
|
|
13245
13245
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
13246
13246
|
if (isTypedArrayWithEntries(value)) {
|
|
13247
|
-
res += stringifyTypedArray(value,
|
|
13247
|
+
res += stringifyTypedArray(value, join8, maximumBreadth);
|
|
13248
13248
|
keys = keys.slice(value.length);
|
|
13249
13249
|
maximumPropertiesToStringify -= value.length;
|
|
13250
|
-
separator =
|
|
13250
|
+
separator = join8;
|
|
13251
13251
|
}
|
|
13252
13252
|
if (deterministic) {
|
|
13253
13253
|
keys = sort(keys, comparator);
|
|
@@ -13258,13 +13258,13 @@ ${indentation}`;
|
|
|
13258
13258
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
13259
13259
|
if (tmp !== void 0) {
|
|
13260
13260
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
13261
|
-
separator =
|
|
13261
|
+
separator = join8;
|
|
13262
13262
|
}
|
|
13263
13263
|
}
|
|
13264
13264
|
if (keyLength > maximumBreadth) {
|
|
13265
13265
|
const removedKeys = keyLength - maximumBreadth;
|
|
13266
13266
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
13267
|
-
separator =
|
|
13267
|
+
separator = join8;
|
|
13268
13268
|
}
|
|
13269
13269
|
if (separator !== "") {
|
|
13270
13270
|
res = `
|
|
@@ -61940,11 +61940,11 @@ var require_core = __commonJS({
|
|
|
61940
61940
|
function mapOuter(r, f) {
|
|
61941
61941
|
return r.matched ? f(r) : r;
|
|
61942
61942
|
}
|
|
61943
|
-
function ab(pa, pb,
|
|
61944
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) =>
|
|
61943
|
+
function ab(pa, pb, join8) {
|
|
61944
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join8(ma.value, vb, data, i, j)));
|
|
61945
61945
|
}
|
|
61946
|
-
function abc(pa, pb, pc,
|
|
61947
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) =>
|
|
61946
|
+
function abc(pa, pb, pc, join8) {
|
|
61947
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) => join8(ma.value, mb.value, vc, data, i, j))));
|
|
61948
61948
|
}
|
|
61949
61949
|
function action(f) {
|
|
61950
61950
|
return (data, i) => {
|
|
@@ -83529,48 +83529,29 @@ ${statePacket}`, redactionCredentials) },
|
|
|
83529
83529
|
log2(" app data reset skipped by policy \u2014 scenario records after relaunch with preserved data.");
|
|
83530
83530
|
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: false, coldResetUnavailable: false, refuseGenerate: false, reason: "preserve_policy" }, log2);
|
|
83531
83531
|
}
|
|
83532
|
-
|
|
83533
|
-
|
|
83534
|
-
|
|
83535
|
-
|
|
83536
|
-
|
|
83537
|
-
|
|
83538
|
-
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: true, coldResetUnavailable: false, refuseGenerate: false }, log2);
|
|
83539
|
-
}
|
|
83540
|
-
await driver.relaunch();
|
|
83541
|
-
if (resetPolicy === "CLEAR_APP_DATA") {
|
|
83542
|
-
log2(" CLEAR_APP_DATA required but app-data reset was unavailable \u2014 refusing to generate from warm state.");
|
|
83543
|
-
return {
|
|
83544
|
-
appDataCleared: false,
|
|
83545
|
-
coldResetUnavailable: true,
|
|
83546
|
-
refuseGenerate: true,
|
|
83547
|
-
reason: "clear_app_data_unavailable"
|
|
83548
|
-
};
|
|
83549
|
-
}
|
|
83550
|
-
log2(" app-data reset unavailable \u2014 generating with @warm-state (relaunch only; may not match cold-boot replay).");
|
|
83551
|
-
return applyScenarioEntryDeepLink(driver, target, {
|
|
83552
|
-
appDataCleared: false,
|
|
83553
|
-
coldResetUnavailable: true,
|
|
83554
|
-
refuseGenerate: false,
|
|
83555
|
-
reason: platform3 === "ANDROID" ? "android_reset_unavailable" : "reset_unavailable"
|
|
83556
|
-
}, log2);
|
|
83532
|
+
const appDataCleared = await driver.resetAppState?.().catch((err) => {
|
|
83533
|
+
log2(` app-data reset failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
83534
|
+
return false;
|
|
83535
|
+
}) ?? false;
|
|
83536
|
+
if (appDataCleared) {
|
|
83537
|
+
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: true, coldResetUnavailable: false, refuseGenerate: false }, log2);
|
|
83557
83538
|
}
|
|
83558
83539
|
await driver.relaunch();
|
|
83559
83540
|
if (resetPolicy === "CLEAR_APP_DATA") {
|
|
83560
|
-
log2(" CLEAR_APP_DATA required but iOS
|
|
83541
|
+
log2(platform3 === "IOS" ? " CLEAR_APP_DATA required but this iOS device cannot be cleared (simulator required) \u2014 refusing to generate from warm state." : " CLEAR_APP_DATA required but app-data reset was unavailable \u2014 refusing to generate from warm state.");
|
|
83561
83542
|
return {
|
|
83562
83543
|
appDataCleared: false,
|
|
83563
83544
|
coldResetUnavailable: true,
|
|
83564
83545
|
refuseGenerate: true,
|
|
83565
|
-
reason: "ios_clear_app_data_unavailable"
|
|
83546
|
+
reason: platform3 === "IOS" ? "ios_clear_app_data_unavailable" : "clear_app_data_unavailable"
|
|
83566
83547
|
};
|
|
83567
83548
|
}
|
|
83568
|
-
log2(" iOS
|
|
83549
|
+
log2(platform3 === "IOS" ? " iOS app-data reset unavailable (physical device or simctl failure) \u2014 generating with @warm-state (relaunch only; may not match cold-boot replay)." : " app-data reset unavailable \u2014 generating with @warm-state (relaunch only; may not match cold-boot replay).");
|
|
83569
83550
|
return applyScenarioEntryDeepLink(driver, target, {
|
|
83570
83551
|
appDataCleared: false,
|
|
83571
83552
|
coldResetUnavailable: true,
|
|
83572
83553
|
refuseGenerate: false,
|
|
83573
|
-
reason: "ios_no_clear_app"
|
|
83554
|
+
reason: platform3 === "IOS" ? "ios_no_clear_app" : platform3 === "ANDROID" ? "android_reset_unavailable" : "reset_unavailable"
|
|
83574
83555
|
}, log2);
|
|
83575
83556
|
}
|
|
83576
83557
|
async function runMobileGeneratePhase(args) {
|
|
@@ -89031,7 +89012,7 @@ var require_kill_tree = __commonJS({
|
|
|
89031
89012
|
var node_child_process_1 = __require("child_process");
|
|
89032
89013
|
var node_util_1 = __require("util");
|
|
89033
89014
|
var node_fs_1 = __require("fs");
|
|
89034
|
-
var
|
|
89015
|
+
var execFileAsync4 = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
89035
89016
|
var PS_TIMEOUT_MS = 2e3;
|
|
89036
89017
|
var PS_BUFFER = 1024 * 1024;
|
|
89037
89018
|
async function gracefulCloseWithTreeKill(options) {
|
|
@@ -89085,7 +89066,7 @@ var require_kill_tree = __commonJS({
|
|
|
89085
89066
|
timer.unref?.();
|
|
89086
89067
|
let stdout;
|
|
89087
89068
|
try {
|
|
89088
|
-
const result = await
|
|
89069
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid=,command="], {
|
|
89089
89070
|
maxBuffer: PS_BUFFER,
|
|
89090
89071
|
signal: controller.signal
|
|
89091
89072
|
});
|
|
@@ -89123,7 +89104,7 @@ var require_kill_tree = __commonJS({
|
|
|
89123
89104
|
timer.unref?.();
|
|
89124
89105
|
let stdout;
|
|
89125
89106
|
try {
|
|
89126
|
-
const result = await
|
|
89107
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid=,command="], {
|
|
89127
89108
|
maxBuffer: PS_BUFFER,
|
|
89128
89109
|
signal: controller.signal
|
|
89129
89110
|
});
|
|
@@ -89200,7 +89181,7 @@ var require_kill_tree = __commonJS({
|
|
|
89200
89181
|
timer.unref?.();
|
|
89201
89182
|
let stdout;
|
|
89202
89183
|
try {
|
|
89203
|
-
const result = await
|
|
89184
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid="], {
|
|
89204
89185
|
maxBuffer: PS_BUFFER,
|
|
89205
89186
|
signal: controller.signal
|
|
89206
89187
|
});
|
|
@@ -98750,8 +98731,8 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
|
|
|
98750
98731
|
onRetry: (attempt, reason, delayMs) => logs2.push(` \u26A0 scenario-gen AI call retry ${attempt} (${reason}) \u2014 waiting ${delayMs}ms`)
|
|
98751
98732
|
});
|
|
98752
98733
|
} catch (aiErr) {
|
|
98753
|
-
const
|
|
98754
|
-
logs2.push(` AI call failed at iteration ${iteration} (after retries): ${
|
|
98734
|
+
const errMsg3 = aiErr instanceof Error ? aiErr.message : String(aiErr);
|
|
98735
|
+
logs2.push(` AI call failed at iteration ${iteration} (after retries): ${errMsg3}`);
|
|
98755
98736
|
throw (0, ai_retry_js_1.markAIProviderError)(aiErr);
|
|
98756
98737
|
}
|
|
98757
98738
|
const iterDuration = Date.now() - iterStart;
|
|
@@ -98794,8 +98775,8 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
|
|
|
98794
98775
|
try {
|
|
98795
98776
|
toolArgs = JSON.parse(toolCall.function.arguments);
|
|
98796
98777
|
} catch (parseErr) {
|
|
98797
|
-
const
|
|
98798
|
-
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content:
|
|
98778
|
+
const errMsg3 = `Invalid tool arguments: ${parseErr.message}`;
|
|
98779
|
+
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: errMsg3 });
|
|
98799
98780
|
continue;
|
|
98800
98781
|
}
|
|
98801
98782
|
if (toolName === "finish_generate") {
|
|
@@ -100013,7 +99994,7 @@ var require_util4 = __commonJS({
|
|
|
100013
99994
|
}
|
|
100014
99995
|
path = url.path;
|
|
100015
99996
|
}
|
|
100016
|
-
var
|
|
99997
|
+
var isAbsolute2 = exports.isAbsolute(path);
|
|
100017
99998
|
var parts = path.split(/\/+/);
|
|
100018
99999
|
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
|
|
100019
100000
|
part = parts[i];
|
|
@@ -100033,7 +100014,7 @@ var require_util4 = __commonJS({
|
|
|
100033
100014
|
}
|
|
100034
100015
|
path = parts.join("/");
|
|
100035
100016
|
if (path === "") {
|
|
100036
|
-
path =
|
|
100017
|
+
path = isAbsolute2 ? "/" : ".";
|
|
100037
100018
|
}
|
|
100038
100019
|
if (url) {
|
|
100039
100020
|
url.path = path;
|
|
@@ -100042,7 +100023,7 @@ var require_util4 = __commonJS({
|
|
|
100042
100023
|
return path;
|
|
100043
100024
|
}
|
|
100044
100025
|
exports.normalize = normalize;
|
|
100045
|
-
function
|
|
100026
|
+
function join8(aRoot, aPath) {
|
|
100046
100027
|
if (aRoot === "") {
|
|
100047
100028
|
aRoot = ".";
|
|
100048
100029
|
}
|
|
@@ -100074,7 +100055,7 @@ var require_util4 = __commonJS({
|
|
|
100074
100055
|
}
|
|
100075
100056
|
return joined;
|
|
100076
100057
|
}
|
|
100077
|
-
exports.join =
|
|
100058
|
+
exports.join = join8;
|
|
100078
100059
|
exports.isAbsolute = function(aPath) {
|
|
100079
100060
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
100080
100061
|
};
|
|
@@ -100247,7 +100228,7 @@ var require_util4 = __commonJS({
|
|
|
100247
100228
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
100248
100229
|
}
|
|
100249
100230
|
}
|
|
100250
|
-
sourceURL =
|
|
100231
|
+
sourceURL = join8(urlGenerate(parsed), sourceURL);
|
|
100251
100232
|
}
|
|
100252
100233
|
return normalize(sourceURL);
|
|
100253
100234
|
}
|
|
@@ -313959,8 +313940,8 @@ Try a different fix approach. This is NOT your final script-driven attempt yet,
|
|
|
313959
313940
|
...(0, ai_provider_js_1.getJsonObjectResponseFormat)(agentModel)
|
|
313960
313941
|
})), { label: `script-heal-${attempt}` });
|
|
313961
313942
|
} catch (aiErr) {
|
|
313962
|
-
const
|
|
313963
|
-
logs2.push(`\u26A0 AI call failed: ${
|
|
313943
|
+
const errMsg3 = aiErr instanceof Error ? aiErr.message : String(aiErr);
|
|
313944
|
+
logs2.push(`\u26A0 AI call failed: ${errMsg3}`);
|
|
313964
313945
|
attemptHistory.push({
|
|
313965
313946
|
phase: "script",
|
|
313966
313947
|
attempt,
|
|
@@ -313968,13 +313949,13 @@ Try a different fix approach. This is NOT your final script-driven attempt yet,
|
|
|
313968
313949
|
passed: false,
|
|
313969
313950
|
changedCode: false,
|
|
313970
313951
|
summary: "AI call failed before returning a heal result",
|
|
313971
|
-
errorSummary: truncateForPrompt(
|
|
313952
|
+
errorSummary: truncateForPrompt(errMsg3),
|
|
313972
313953
|
failedStep: summarizeFailedStep(currentStepResults)
|
|
313973
313954
|
});
|
|
313974
313955
|
if (feedbackEnabled) {
|
|
313975
|
-
lastTransportFailure = truncateForPrompt(
|
|
313956
|
+
lastTransportFailure = truncateForPrompt(errMsg3, 200) ?? "the AI request failed";
|
|
313976
313957
|
} else {
|
|
313977
|
-
currentError = `AI call failed on attempt ${attempt}: ${
|
|
313958
|
+
currentError = `AI call failed on attempt ${attempt}: ${errMsg3}`;
|
|
313978
313959
|
}
|
|
313979
313960
|
markRecoverableTurn();
|
|
313980
313961
|
continue;
|
|
@@ -314224,8 +314205,8 @@ ${currentError.slice(0, 2e3)}`
|
|
|
314224
314205
|
// item 5b
|
|
314225
314206
|
});
|
|
314226
314207
|
} catch (runErr) {
|
|
314227
|
-
const
|
|
314228
|
-
logs2.push(`\u{1F4A5} Native execution threw: ${
|
|
314208
|
+
const errMsg3 = runErr instanceof Error ? runErr.message : String(runErr);
|
|
314209
|
+
logs2.push(`\u{1F4A5} Native execution threw: ${errMsg3}`);
|
|
314229
314210
|
attemptHistory.push({
|
|
314230
314211
|
phase: "script",
|
|
314231
314212
|
attempt,
|
|
@@ -314233,9 +314214,9 @@ ${currentError.slice(0, 2e3)}`
|
|
|
314233
314214
|
passed: false,
|
|
314234
314215
|
changedCode: true,
|
|
314235
314216
|
summary: truncateForPrompt(changeDesc) ?? "Applied code fix, but native execution threw before verification completed",
|
|
314236
|
-
errorSummary: truncateForPrompt(
|
|
314217
|
+
errorSummary: truncateForPrompt(errMsg3)
|
|
314237
314218
|
});
|
|
314238
|
-
currentError = `Native execution threw: ${
|
|
314219
|
+
currentError = `Native execution threw: ${errMsg3}`;
|
|
314239
314220
|
currentStepResults = [];
|
|
314240
314221
|
continue;
|
|
314241
314222
|
}
|
|
@@ -314991,9 +314972,9 @@ Last error (after heal attempts): ${lastErrorSnippet}` : `Heal aborted: same err
|
|
|
314991
314972
|
previousErrorSignature = errorSig;
|
|
314992
314973
|
}
|
|
314993
314974
|
} catch (runErr) {
|
|
314994
|
-
const
|
|
314995
|
-
logs2.push(`\u{1F4A5} Native run threw: ${
|
|
314996
|
-
currentError =
|
|
314975
|
+
const errMsg3 = runErr instanceof Error ? runErr.message : String(runErr);
|
|
314976
|
+
logs2.push(`\u{1F4A5} Native run threw: ${errMsg3}`);
|
|
314977
|
+
currentError = errMsg3;
|
|
314997
314978
|
currentStepResults = [];
|
|
314998
314979
|
}
|
|
314999
314980
|
} else {
|
|
@@ -315555,8 +315536,8 @@ When you call finish_fix, preserve locators only when they are stable structural
|
|
|
315555
315536
|
}
|
|
315556
315537
|
}
|
|
315557
315538
|
} catch (toolErr) {
|
|
315558
|
-
const
|
|
315559
|
-
let errorContent = `Error: ${
|
|
315539
|
+
const errMsg3 = toolErr instanceof Error ? toolErr.message : String(toolErr);
|
|
315540
|
+
let errorContent = `Error: ${errMsg3}`;
|
|
315560
315541
|
try {
|
|
315561
315542
|
const consoleResult = await mcpClient.callTool({ name: "browser_console_messages", arguments: {} });
|
|
315562
315543
|
const consoleText = Array.isArray(consoleResult.content) ? consoleResult.content.map((c) => c.type === "text" ? c.text ?? "" : "").join("\n") : String(consoleResult.content ?? "");
|
|
@@ -315577,8 +315558,8 @@ ${errorContent}`;
|
|
|
315577
315558
|
}
|
|
315578
315559
|
}
|
|
315579
315560
|
} catch (mcpErr) {
|
|
315580
|
-
const
|
|
315581
|
-
logs2.push(`\u{1F4A5} MCP exploration failed: ${
|
|
315561
|
+
const errMsg3 = mcpErr instanceof Error ? mcpErr.message : String(mcpErr);
|
|
315562
|
+
logs2.push(`\u{1F4A5} MCP exploration failed: ${errMsg3}`);
|
|
315582
315563
|
}
|
|
315583
315564
|
if (verdict === "app_bug") {
|
|
315584
315565
|
phase2AttemptHistory.push({
|
|
@@ -316141,9 +316122,9 @@ ${testBlocks}
|
|
|
316141
316122
|
}
|
|
316142
316123
|
emit(` \u2713 ${toolResultContent.slice(0, 200)}${toolResultContent.length > 200 ? "..." : ""}`);
|
|
316143
316124
|
} catch (err) {
|
|
316144
|
-
const
|
|
316145
|
-
toolResultContent = `ERROR: ${
|
|
316146
|
-
emit(` \u2717 ${
|
|
316125
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
316126
|
+
toolResultContent = `ERROR: ${errMsg3}`;
|
|
316127
|
+
emit(` \u2717 ${errMsg3}`);
|
|
316147
316128
|
}
|
|
316148
316129
|
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
316149
316130
|
}
|
|
@@ -321998,8 +321979,8 @@ var require_capture_page_normalizer = __commonJS({
|
|
|
321998
321979
|
const snapItems = Array.isArray(snapResult.content) ? snapResult.content : [];
|
|
321999
321980
|
snapshotText = extractInlineSnapshotYaml(snapItems.find((c) => c.type === "text")?.text || null);
|
|
322000
321981
|
} catch (err) {
|
|
322001
|
-
const
|
|
322002
|
-
const isTimeout = /timeout|timed out|TimeoutError/i.test(
|
|
321982
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
321983
|
+
const isTimeout = /timeout|timed out|TimeoutError/i.test(errMsg3);
|
|
322003
321984
|
return {
|
|
322004
321985
|
snapshotText: null,
|
|
322005
321986
|
meta: {
|
|
@@ -326021,9 +326002,9 @@ ${currentSummary}`;
|
|
|
326021
326002
|
});
|
|
326022
326003
|
}
|
|
326023
326004
|
} catch (err) {
|
|
326024
|
-
const
|
|
326025
|
-
logs2.push(` Error persisting page: ${
|
|
326026
|
-
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: `ERROR persisting page: ${
|
|
326005
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326006
|
+
logs2.push(` Error persisting page: ${errMsg3}`);
|
|
326007
|
+
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: `ERROR persisting page: ${errMsg3}` });
|
|
326027
326008
|
}
|
|
326028
326009
|
continue;
|
|
326029
326010
|
}
|
|
@@ -326225,12 +326206,12 @@ ${currentSummary}`;
|
|
|
326225
326206
|
})
|
|
326226
326207
|
});
|
|
326227
326208
|
} catch (err) {
|
|
326228
|
-
const
|
|
326229
|
-
logs2.push(` Error persisting page: ${
|
|
326209
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326210
|
+
logs2.push(` Error persisting page: ${errMsg3}`);
|
|
326230
326211
|
toolResults.push({
|
|
326231
326212
|
role: "tool",
|
|
326232
326213
|
tool_call_id: toolCall.id,
|
|
326233
|
-
content: `ERROR persisting page: ${
|
|
326214
|
+
content: `ERROR persisting page: ${errMsg3}`
|
|
326234
326215
|
});
|
|
326235
326216
|
}
|
|
326236
326217
|
continue;
|
|
@@ -326265,12 +326246,12 @@ ${currentSummary}`;
|
|
|
326265
326246
|
content: JSON.stringify({ acknowledged: true })
|
|
326266
326247
|
});
|
|
326267
326248
|
} catch (err) {
|
|
326268
|
-
const
|
|
326269
|
-
logs2.push(` Error persisting transition: ${
|
|
326249
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326250
|
+
logs2.push(` Error persisting transition: ${errMsg3}`);
|
|
326270
326251
|
toolResults.push({
|
|
326271
326252
|
role: "tool",
|
|
326272
326253
|
tool_call_id: toolCall.id,
|
|
326273
|
-
content: `ERROR persisting transition: ${
|
|
326254
|
+
content: `ERROR persisting transition: ${errMsg3}`
|
|
326274
326255
|
});
|
|
326275
326256
|
}
|
|
326276
326257
|
continue;
|
|
@@ -326925,15 +326906,15 @@ Exploration complete: ${summary}`);
|
|
|
326925
326906
|
toolResultContent = (0, snapshot_context_compactor_js_1.formatMCPToolResult)(toolResultContent, MAX_TOOL_RESULT_CHARS);
|
|
326926
326907
|
logs2.push(` OK: ${toolResultContent.slice(0, 200)}${toolResultContent.length > 200 ? "..." : ""}`);
|
|
326927
326908
|
} catch (err) {
|
|
326928
|
-
const
|
|
326929
|
-
toolResultContent = `ERROR: ${
|
|
326930
|
-
logs2.push(` Error: ${
|
|
326909
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326910
|
+
toolResultContent = `ERROR: ${errMsg3}`;
|
|
326911
|
+
logs2.push(` Error: ${errMsg3}`);
|
|
326931
326912
|
if (useV2) {
|
|
326932
326913
|
(0, exploration_state_js_1.reduceEvent)(state2, {
|
|
326933
326914
|
type: "ACTION_FAILED",
|
|
326934
326915
|
route: state2.currentRoute,
|
|
326935
326916
|
action: `${toolName}(${JSON.stringify(toolArgs).slice(0, 100)})`,
|
|
326936
|
-
error:
|
|
326917
|
+
error: errMsg3
|
|
326937
326918
|
});
|
|
326938
326919
|
}
|
|
326939
326920
|
}
|
|
@@ -329779,10 +329760,10 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
329779
329760
|
onLog: options.onLog,
|
|
329780
329761
|
onProvenCommands: recordProvenCommands
|
|
329781
329762
|
});
|
|
329782
|
-
const
|
|
329763
|
+
const errMsg3 = firstError?.message ?? (grokError instanceof Error ? grokError.message : "unknown error");
|
|
329783
329764
|
const fixPrompt = [
|
|
329784
329765
|
"Your previous attempt did not produce a valid result file.",
|
|
329785
|
-
`Error: ${
|
|
329766
|
+
`Error: ${errMsg3}`,
|
|
329786
329767
|
`Re-read BRIEF.md and write a valid SurveyorOutput JSON to ${resultFilePath}.`,
|
|
329787
329768
|
"Single JSON object. No prose. Then exit."
|
|
329788
329769
|
].join("\n");
|
|
@@ -331923,7 +331904,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
331923
331904
|
log2(`First-pass discovery-result invalid or missing: ${firstError.message}`);
|
|
331924
331905
|
}
|
|
331925
331906
|
if (!parsedResult) {
|
|
331926
|
-
const
|
|
331907
|
+
const errMsg3 = firstError?.message ?? (grokError instanceof Error ? grokError.message : "unknown error");
|
|
331927
331908
|
if (planDebounceTimerRef.current) {
|
|
331928
331909
|
clearTimeout(planDebounceTimerRef.current);
|
|
331929
331910
|
planDebounceTimerRef.current = void 0;
|
|
@@ -331948,7 +331929,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
331948
331929
|
""
|
|
331949
331930
|
].join("\n");
|
|
331950
331931
|
const fixPrompt = [
|
|
331951
|
-
`Your previous attempt did not produce a valid result file. Error: ${
|
|
331932
|
+
`Your previous attempt did not produce a valid result file. Error: ${errMsg3}`,
|
|
331952
331933
|
"Re-read BRIEF.md.",
|
|
331953
331934
|
phaseContext,
|
|
331954
331935
|
`Continue from where you left off \u2014 already verified tests are in ${testsDirPath}/`,
|
|
@@ -333577,10 +333558,10 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
333577
333558
|
onLog: parserLog,
|
|
333578
333559
|
onProvenCommands: recordProvenCommands
|
|
333579
333560
|
});
|
|
333580
|
-
const
|
|
333561
|
+
const errMsg3 = firstError?.message ?? (claudeError instanceof Error ? claudeError.message : "unknown error");
|
|
333581
333562
|
const fixPrompt = [
|
|
333582
333563
|
"Your previous attempt did not leave a valid result file.",
|
|
333583
|
-
`Error: ${
|
|
333564
|
+
`Error: ${errMsg3}`,
|
|
333584
333565
|
`Writing a valid SurveyorOutput JSON object to ${resultFilePath} is your ONLY priority now.`,
|
|
333585
333566
|
"Procedure: navigate to at most 6-8 of the main pages, then IMMEDIATELY use",
|
|
333586
333567
|
`the Write tool to save the SurveyorOutput JSON to ${resultFilePath}. Do this`,
|
|
@@ -339958,8 +339939,8 @@ var require_adm_zip = __commonJS({
|
|
|
339958
339939
|
return null;
|
|
339959
339940
|
}
|
|
339960
339941
|
function fixPath(zipPath) {
|
|
339961
|
-
const { join:
|
|
339962
|
-
return
|
|
339942
|
+
const { join: join8, normalize, sep } = pth.posix;
|
|
339943
|
+
return join8(pth.isAbsolute(zipPath) ? "/" : ".", normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
339963
339944
|
}
|
|
339964
339945
|
function filenameFilter(filterfn) {
|
|
339965
339946
|
if (filterfn instanceof RegExp) {
|
|
@@ -342794,11 +342775,11 @@ var require_winchars = __commonJS({
|
|
|
342794
342775
|
var require_strip_absolute_path = __commonJS({
|
|
342795
342776
|
"../../node_modules/tar/lib/strip-absolute-path.js"(exports, module) {
|
|
342796
342777
|
"use strict";
|
|
342797
|
-
var { isAbsolute, parse } = __require("path").win32;
|
|
342778
|
+
var { isAbsolute: isAbsolute2, parse } = __require("path").win32;
|
|
342798
342779
|
module.exports = (path) => {
|
|
342799
342780
|
let r = "";
|
|
342800
342781
|
let parsed = parse(path);
|
|
342801
|
-
while (
|
|
342782
|
+
while (isAbsolute2(path) || parsed.root) {
|
|
342802
342783
|
const root = path.charAt(0) === "/" && path.slice(0, 4) !== "//?/" ? "/" : parsed.root;
|
|
342803
342784
|
path = path.slice(root.length);
|
|
342804
342785
|
r += root;
|
|
@@ -345310,7 +345291,7 @@ var require_update = __commonJS({
|
|
|
345310
345291
|
var require_opts_arg = __commonJS({
|
|
345311
345292
|
"../../node_modules/tar/node_modules/mkdirp/lib/opts-arg.js"(exports, module) {
|
|
345312
345293
|
"use strict";
|
|
345313
|
-
var { promisify:
|
|
345294
|
+
var { promisify: promisify4 } = __require("util");
|
|
345314
345295
|
var fs = __require("fs");
|
|
345315
345296
|
var optsArg = (opts) => {
|
|
345316
345297
|
if (!opts)
|
|
@@ -345324,9 +345305,9 @@ var require_opts_arg = __commonJS({
|
|
|
345324
345305
|
else
|
|
345325
345306
|
throw new TypeError("invalid options argument");
|
|
345326
345307
|
opts.mkdir = opts.mkdir || opts.fs.mkdir || fs.mkdir;
|
|
345327
|
-
opts.mkdirAsync =
|
|
345308
|
+
opts.mkdirAsync = promisify4(opts.mkdir);
|
|
345328
345309
|
opts.stat = opts.stat || opts.fs.stat || fs.stat;
|
|
345329
|
-
opts.statAsync =
|
|
345310
|
+
opts.statAsync = promisify4(opts.stat);
|
|
345330
345311
|
opts.statSync = opts.statSync || opts.fs.statSync || fs.statSync;
|
|
345331
345312
|
opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs.mkdirSync;
|
|
345332
345313
|
return opts;
|
|
@@ -345579,10 +345560,10 @@ var require_chownr = __commonJS({
|
|
|
345579
345560
|
}
|
|
345580
345561
|
} : (path2, uid, gid) => lchownSync(path2, uid, gid);
|
|
345581
345562
|
var nodeVersion = process.version;
|
|
345582
|
-
var
|
|
345563
|
+
var readdir3 = (path2, options, cb) => fs.readdir(path2, options, cb);
|
|
345583
345564
|
var readdirSync = (path2, options) => fs.readdirSync(path2, options);
|
|
345584
345565
|
if (/^v4\./.test(nodeVersion))
|
|
345585
|
-
|
|
345566
|
+
readdir3 = (path2, options, cb) => fs.readdir(path2, cb);
|
|
345586
345567
|
var chown = (cpath, uid, gid, cb) => {
|
|
345587
345568
|
fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, (er) => {
|
|
345588
345569
|
cb(er && er.code !== "ENOENT" ? er : null);
|
|
@@ -345609,7 +345590,7 @@ var require_chownr = __commonJS({
|
|
|
345609
345590
|
}
|
|
345610
345591
|
};
|
|
345611
345592
|
var chownr = (p, uid, gid, cb) => {
|
|
345612
|
-
|
|
345593
|
+
readdir3(p, { withFileTypes: true }, (er, children) => {
|
|
345613
345594
|
if (er) {
|
|
345614
345595
|
if (er.code === "ENOENT")
|
|
345615
345596
|
return cb();
|
|
@@ -345883,7 +345864,7 @@ var require_path_reservations = __commonJS({
|
|
|
345883
345864
|
var assert = __require("assert");
|
|
345884
345865
|
var normalize = require_normalize_unicode();
|
|
345885
345866
|
var stripSlashes = require_strip_trailing_slashes();
|
|
345886
|
-
var { join:
|
|
345867
|
+
var { join: join8 } = __require("path");
|
|
345887
345868
|
var platform3 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
345888
345869
|
var isWindows = platform3 === "win32";
|
|
345889
345870
|
module.exports = () => {
|
|
@@ -345892,7 +345873,7 @@ var require_path_reservations = __commonJS({
|
|
|
345892
345873
|
const getDirs = (path) => {
|
|
345893
345874
|
const dirs = path.split("/").slice(0, -1).reduce((set, path2) => {
|
|
345894
345875
|
if (set.length) {
|
|
345895
|
-
path2 =
|
|
345876
|
+
path2 = join8(set[set.length - 1], path2);
|
|
345896
345877
|
}
|
|
345897
345878
|
set.push(path2 || "/");
|
|
345898
345879
|
return set;
|
|
@@ -345960,7 +345941,7 @@ var require_path_reservations = __commonJS({
|
|
|
345960
345941
|
};
|
|
345961
345942
|
const reserve = (paths, fn) => {
|
|
345962
345943
|
paths = isWindows ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
345963
|
-
return stripSlashes(
|
|
345944
|
+
return stripSlashes(join8(normalize(p))).toLowerCase();
|
|
345964
345945
|
});
|
|
345965
345946
|
const dirs = new Set(
|
|
345966
345947
|
paths.map((path) => getDirs(path)).reduce((a, b) => a.concat(b))
|
|
@@ -350175,7 +350156,7 @@ var require_process_inventory = __commonJS({
|
|
|
350175
350156
|
var node_child_process_1 = __require("child_process");
|
|
350176
350157
|
var node_os_1 = __importDefault(__require("os"));
|
|
350177
350158
|
var node_util_1 = __require("util");
|
|
350178
|
-
var
|
|
350159
|
+
var execFileAsync4 = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
350179
350160
|
var DEFAULT_LIMIT = 60;
|
|
350180
350161
|
var DEFAULT_TIMEOUT_MS2 = 800;
|
|
350181
350162
|
var MAX_COMMAND_LENGTH = 320;
|
|
@@ -350237,7 +350218,7 @@ var require_process_inventory = __commonJS({
|
|
|
350237
350218
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
350238
350219
|
timer.unref?.();
|
|
350239
350220
|
try {
|
|
350240
|
-
const { stdout } = await
|
|
350221
|
+
const { stdout } = await execFileAsync4(command, args, {
|
|
350241
350222
|
maxBuffer: 1024 * 1024,
|
|
350242
350223
|
signal: controller.signal
|
|
350243
350224
|
});
|
|
@@ -351373,7 +351354,7 @@ var require_package4 = __commonJS({
|
|
|
351373
351354
|
"package.json"(exports, module) {
|
|
351374
351355
|
module.exports = {
|
|
351375
351356
|
name: "@validate.qa/runner",
|
|
351376
|
-
version: "1.0.
|
|
351357
|
+
version: "1.0.69",
|
|
351377
351358
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
351378
351359
|
bin: {
|
|
351379
351360
|
"validate-runner": "dist/cli.js"
|
|
@@ -351460,7 +351441,7 @@ function getConfigDir() {
|
|
|
351460
351441
|
}
|
|
351461
351442
|
|
|
351462
351443
|
// src/runner.ts
|
|
351463
|
-
import { join as
|
|
351444
|
+
import { join as join7 } from "path";
|
|
351464
351445
|
import { homedir as homedir3 } from "os";
|
|
351465
351446
|
import { createHash } from "crypto";
|
|
351466
351447
|
|
|
@@ -352055,6 +352036,66 @@ function resetServerState(port = APPIUM_PORT, restartCount = 0) {
|
|
|
352055
352036
|
};
|
|
352056
352037
|
}
|
|
352057
352038
|
|
|
352039
|
+
// src/services/mobile/ios-simulator-reset.ts
|
|
352040
|
+
import { execFile } from "child_process";
|
|
352041
|
+
import { promisify } from "util";
|
|
352042
|
+
import { readdir, rm } from "fs/promises";
|
|
352043
|
+
import { join as join3, isAbsolute } from "path";
|
|
352044
|
+
var execFileAsync = promisify(execFile);
|
|
352045
|
+
var SIMCTL_TIMEOUT_MS = 15e3;
|
|
352046
|
+
var SIMULATOR_UDID_RE = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;
|
|
352047
|
+
function isIosSimulatorUdid(udid) {
|
|
352048
|
+
return typeof udid === "string" && SIMULATOR_UDID_RE.test(udid.trim());
|
|
352049
|
+
}
|
|
352050
|
+
function errMsg(err) {
|
|
352051
|
+
return err instanceof Error ? err.message : String(err);
|
|
352052
|
+
}
|
|
352053
|
+
async function simctl(args) {
|
|
352054
|
+
const { stdout } = await execFileAsync("xcrun", ["simctl", ...args], {
|
|
352055
|
+
timeout: SIMCTL_TIMEOUT_MS,
|
|
352056
|
+
encoding: "utf-8"
|
|
352057
|
+
});
|
|
352058
|
+
return stdout.trim();
|
|
352059
|
+
}
|
|
352060
|
+
async function clearIosSimulatorAppData(udid, bundleId, env = process.env) {
|
|
352061
|
+
if (!isIosSimulatorUdid(udid)) {
|
|
352062
|
+
return { ok: false, detail: `'${udid}' is not a simulator UDID \u2014 physical iOS devices cannot be cleared` };
|
|
352063
|
+
}
|
|
352064
|
+
let container;
|
|
352065
|
+
try {
|
|
352066
|
+
container = await simctl(["get_app_container", udid, bundleId, "data"]);
|
|
352067
|
+
} catch (err) {
|
|
352068
|
+
return { ok: false, detail: `simctl get_app_container failed (app not installed?): ${errMsg(err)}` };
|
|
352069
|
+
}
|
|
352070
|
+
if (!isAbsolute(container) || !container.includes("/Containers/Data/Application/")) {
|
|
352071
|
+
return { ok: false, detail: `unexpected app container path: ${container}` };
|
|
352072
|
+
}
|
|
352073
|
+
try {
|
|
352074
|
+
await simctl(["spawn", udid, "defaults", "delete", bundleId]);
|
|
352075
|
+
} catch {
|
|
352076
|
+
}
|
|
352077
|
+
try {
|
|
352078
|
+
const entries = await readdir(container);
|
|
352079
|
+
for (const entry of entries) {
|
|
352080
|
+
await rm(join3(container, entry), { recursive: true, force: true });
|
|
352081
|
+
}
|
|
352082
|
+
} catch (err) {
|
|
352083
|
+
return { ok: false, detail: `app container wipe failed: ${errMsg(err)}` };
|
|
352084
|
+
}
|
|
352085
|
+
const keychainPolicy = (env.VALIDATEQA_MOBILE_IOS_KEYCHAIN_RESET ?? "").trim().toLowerCase();
|
|
352086
|
+
if (keychainPolicy !== "never") {
|
|
352087
|
+
try {
|
|
352088
|
+
await simctl(["keychain", udid, "reset"]);
|
|
352089
|
+
} catch (err) {
|
|
352090
|
+
return {
|
|
352091
|
+
ok: false,
|
|
352092
|
+
detail: `simulator keychain reset failed (${errMsg(err)}) \u2014 app data was wiped but keychain items (e.g. auth tokens) may survive. Set VALIDATEQA_MOBILE_IOS_KEYCHAIN_RESET=never to skip the keychain step.`
|
|
352093
|
+
};
|
|
352094
|
+
}
|
|
352095
|
+
}
|
|
352096
|
+
return { ok: true };
|
|
352097
|
+
}
|
|
352098
|
+
|
|
352058
352099
|
// src/services/mobile/appium-actions.ts
|
|
352059
352100
|
var APPIUM_REQUEST_TIMEOUT_MS = 1e4;
|
|
352060
352101
|
var APPIUM_WEBVIEW_CONTEXT_TIMEOUT_MS = 12e4;
|
|
@@ -352237,9 +352278,12 @@ async function tapAt(sessionPath, bounds) {
|
|
|
352237
352278
|
}
|
|
352238
352279
|
}
|
|
352239
352280
|
function shouldResetMobileAppData(platform3, deviceId, env = process.env) {
|
|
352240
|
-
if (platform3 !== "ANDROID") return false;
|
|
352241
352281
|
const policy = (env.VALIDATEQA_MOBILE_APP_RESET ?? "").trim().toLowerCase();
|
|
352242
352282
|
if (policy === "never") return false;
|
|
352283
|
+
if (platform3 === "IOS") {
|
|
352284
|
+
return isIosSimulatorUdid(deviceId);
|
|
352285
|
+
}
|
|
352286
|
+
if (platform3 !== "ANDROID") return false;
|
|
352243
352287
|
if (policy === "always") return true;
|
|
352244
352288
|
return !!deviceId && deviceId.startsWith("emulator-");
|
|
352245
352289
|
}
|
|
@@ -353120,10 +353164,10 @@ async function pressHome(sessionPath, platform3) {
|
|
|
353120
353164
|
|
|
353121
353165
|
// src/services/appium-executor.ts
|
|
353122
353166
|
var import_runner_core8 = __toESM(require_dist2());
|
|
353123
|
-
import { execFile as
|
|
353124
|
-
import { promisify as
|
|
353167
|
+
import { execFile as execFile3 } from "child_process";
|
|
353168
|
+
import { promisify as promisify3 } from "util";
|
|
353125
353169
|
import { tmpdir as tmpdir3 } from "os";
|
|
353126
|
-
import { join as
|
|
353170
|
+
import { join as join5 } from "path";
|
|
353127
353171
|
|
|
353128
353172
|
// src/services/device-discovery.ts
|
|
353129
353173
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -353430,9 +353474,6 @@ function countReadyDevicesByKind(platform3, snapshot = getCachedDeviceSnapshot()
|
|
|
353430
353474
|
function selectFreeDevice(platform3, leased, snapshot = getCachedDeviceSnapshot(), requirements = {}) {
|
|
353431
353475
|
const ready = snapshot.filter((d) => d.platform === platform3 && d.isAvailable && d.state === "BOOTED");
|
|
353432
353476
|
if (ready.length === 0) return { kind: "busy", reason: `no booted ${platform3} device` };
|
|
353433
|
-
if (requirements.resetPolicy === "CLEAR_APP_DATA" && platform3 !== "ANDROID") {
|
|
353434
|
-
return { kind: "unsatisfiable", reason: "CLEAR_APP_DATA is unsupported on iOS" };
|
|
353435
|
-
}
|
|
353436
353477
|
let candidates = requirements.resetPolicy === "CLEAR_APP_DATA" ? ready.filter((d) => !d.isPhysical) : [...ready];
|
|
353437
353478
|
const appId = requirements.appId?.trim();
|
|
353438
353479
|
if (appId) {
|
|
@@ -353481,23 +353522,23 @@ function pickFreeDevice(platform3, leased, snapshot = getCachedDeviceSnapshot(),
|
|
|
353481
353522
|
|
|
353482
353523
|
// src/services/mobile/mobile-network-capture.ts
|
|
353483
353524
|
var import_runner_core7 = __toESM(require_dist2());
|
|
353484
|
-
import { execFile, execFileSync as execFileSync3 } from "child_process";
|
|
353525
|
+
import { execFile as execFile2, execFileSync as execFileSync3 } from "child_process";
|
|
353485
353526
|
import { randomUUID } from "crypto";
|
|
353486
|
-
import { mkdtemp, rm, writeFile, readFile, readdir, mkdir, unlink } from "fs/promises";
|
|
353527
|
+
import { mkdtemp, rm as rm2, writeFile, readFile, readdir as readdir2, mkdir, unlink } from "fs/promises";
|
|
353487
353528
|
import { tmpdir as tmpdir2, networkInterfaces } from "os";
|
|
353488
|
-
import { join as
|
|
353489
|
-
import { promisify } from "util";
|
|
353529
|
+
import { join as join4 } from "path";
|
|
353530
|
+
import { promisify as promisify2 } from "util";
|
|
353490
353531
|
import {
|
|
353491
353532
|
getLocal,
|
|
353492
353533
|
generateCACertificate
|
|
353493
353534
|
} from "mockttp";
|
|
353494
|
-
var
|
|
353535
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
353495
353536
|
var MAX_CALLS = 1e3;
|
|
353496
353537
|
var MAX_BODY_CAPTURE_BYTES = 64 * 1024;
|
|
353497
353538
|
var DEVICE_CMD_TIMEOUT_MS = 15e3;
|
|
353498
353539
|
var CA_KEY_BITS = 2048;
|
|
353499
353540
|
var ANDROID_EMULATOR_HOST_LOOPBACK = "10.0.2.2";
|
|
353500
|
-
var PENDING_CLEANUP_DIR =
|
|
353541
|
+
var PENDING_CLEANUP_DIR = join4(tmpdir2(), "validateqa-mobile-capture-pending");
|
|
353501
353542
|
var IOS_SIM_HOST_PROXY_ENV = "VALIDATEQA_MOBILE_IOS_SIM_HOST_PROXY";
|
|
353502
353543
|
var STALE_MARKER_RECONCILE_MS = 6 * 60 * 60 * 1e3;
|
|
353503
353544
|
function envFlag(name) {
|
|
@@ -353679,7 +353720,7 @@ var MitmProxy = class {
|
|
|
353679
353720
|
try {
|
|
353680
353721
|
await server3.stop();
|
|
353681
353722
|
} catch (err) {
|
|
353682
|
-
this.onLog?.(`[mobile-net] proxy stop error (ignored): ${
|
|
353723
|
+
this.onLog?.(`[mobile-net] proxy stop error (ignored): ${errMsg2(err)}`);
|
|
353683
353724
|
}
|
|
353684
353725
|
this.onLog?.(
|
|
353685
353726
|
`[mobile-net] proxy closed: ${this.calls.length} calls captured` + (this.dropped > 0 ? ` (${this.dropped} dropped over cap)` : "")
|
|
@@ -353704,7 +353745,7 @@ var MitmProxy = class {
|
|
|
353704
353745
|
isHttps
|
|
353705
353746
|
});
|
|
353706
353747
|
} catch (err) {
|
|
353707
|
-
this.onLog?.(`[mobile-net] request capture error (ignored): ${
|
|
353748
|
+
this.onLog?.(`[mobile-net] request capture error (ignored): ${errMsg2(err)}`);
|
|
353708
353749
|
}
|
|
353709
353750
|
}
|
|
353710
353751
|
// ── response → finalize the matched request ───────────────────────────────
|
|
@@ -353747,7 +353788,7 @@ var MitmProxy = class {
|
|
|
353747
353788
|
intercepted: true
|
|
353748
353789
|
});
|
|
353749
353790
|
} catch (err) {
|
|
353750
|
-
this.onLog?.(`[mobile-net] response capture error (ignored): ${
|
|
353791
|
+
this.onLog?.(`[mobile-net] response capture error (ignored): ${errMsg2(err)}`);
|
|
353751
353792
|
}
|
|
353752
353793
|
}
|
|
353753
353794
|
// ── tls-client-error → record WHY interception failed ─────────────────────
|
|
@@ -353824,17 +353865,17 @@ async function generateCaCert(dir, onLog) {
|
|
|
353824
353865
|
// rely on stop() to remove the cert from the device promptly after the run
|
|
353825
353866
|
// rather than on a short expiry.
|
|
353826
353867
|
});
|
|
353827
|
-
const caCertPath =
|
|
353868
|
+
const caCertPath = join4(dir, "validateqa-mobile-ca.pem");
|
|
353828
353869
|
await writeFile(caCertPath, cert, "utf-8");
|
|
353829
353870
|
return { caCertPath, caKeyPem: key, caCertPem: cert };
|
|
353830
353871
|
} catch (err) {
|
|
353831
|
-
onLog?.(`[mobile-net] CA generation failed; running plaintext-only: ${
|
|
353872
|
+
onLog?.(`[mobile-net] CA generation failed; running plaintext-only: ${errMsg2(err)}`);
|
|
353832
353873
|
return null;
|
|
353833
353874
|
}
|
|
353834
353875
|
}
|
|
353835
353876
|
async function androidReadProxy(deviceId) {
|
|
353836
353877
|
try {
|
|
353837
|
-
const { stdout } = await
|
|
353878
|
+
const { stdout } = await execFileAsync2(
|
|
353838
353879
|
"adb",
|
|
353839
353880
|
["-s", deviceId, "shell", "settings", "get", "global", "http_proxy"],
|
|
353840
353881
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
@@ -353847,33 +353888,33 @@ async function androidReadProxy(deviceId) {
|
|
|
353847
353888
|
}
|
|
353848
353889
|
async function androidSetProxy(deviceId, hostPort, onLog) {
|
|
353849
353890
|
try {
|
|
353850
|
-
await
|
|
353891
|
+
await execFileAsync2(
|
|
353851
353892
|
"adb",
|
|
353852
353893
|
["-s", deviceId, "shell", "settings", "put", "global", "http_proxy", hostPort],
|
|
353853
353894
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353854
353895
|
);
|
|
353855
353896
|
return true;
|
|
353856
353897
|
} catch (err) {
|
|
353857
|
-
onLog?.(`[mobile-net] adb set http_proxy failed: ${
|
|
353898
|
+
onLog?.(`[mobile-net] adb set http_proxy failed: ${errMsg2(err)}`);
|
|
353858
353899
|
return false;
|
|
353859
353900
|
}
|
|
353860
353901
|
}
|
|
353861
353902
|
async function androidClearProxy(deviceId, originalProxy, onLog) {
|
|
353862
353903
|
const restoreValue = originalProxy && originalProxy.length > 0 ? originalProxy : ":0";
|
|
353863
353904
|
try {
|
|
353864
|
-
await
|
|
353905
|
+
await execFileAsync2(
|
|
353865
353906
|
"adb",
|
|
353866
353907
|
["-s", deviceId, "shell", "settings", "put", "global", "http_proxy", restoreValue],
|
|
353867
353908
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353868
353909
|
);
|
|
353869
353910
|
} catch (err) {
|
|
353870
|
-
onLog?.(`[mobile-net] adb restore http_proxy failed: ${
|
|
353911
|
+
onLog?.(`[mobile-net] adb restore http_proxy failed: ${errMsg2(err)}`);
|
|
353871
353912
|
}
|
|
353872
353913
|
}
|
|
353873
353914
|
async function androidInstallCa(deviceId, caCertPath) {
|
|
353874
353915
|
const devicePath = "/sdcard/validateqa-mobile-ca.pem";
|
|
353875
353916
|
try {
|
|
353876
|
-
await
|
|
353917
|
+
await execFileAsync2("adb", ["-s", deviceId, "push", caCertPath, devicePath], {
|
|
353877
353918
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353878
353919
|
});
|
|
353879
353920
|
return {
|
|
@@ -353881,23 +353922,23 @@ async function androidInstallCa(deviceId, caCertPath) {
|
|
|
353881
353922
|
note: `CA copied from ${caCertPath} to ${devicePath} but NOT auto-trusted: Android 7+ apps must opt into user CAs (network_security_config), and the system store requires a rooted/writable image. HTTPS bodies decrypt only for apps that trust user CAs; pinned apps never decrypt.`
|
|
353882
353923
|
};
|
|
353883
353924
|
} catch (err) {
|
|
353884
|
-
return { installed: false, note: `CA push failed: ${
|
|
353925
|
+
return { installed: false, note: `CA push failed: ${errMsg2(err)}` };
|
|
353885
353926
|
}
|
|
353886
353927
|
}
|
|
353887
353928
|
async function androidRemoveCa(deviceId, onLog) {
|
|
353888
353929
|
try {
|
|
353889
|
-
await
|
|
353930
|
+
await execFileAsync2(
|
|
353890
353931
|
"adb",
|
|
353891
353932
|
["-s", deviceId, "shell", "rm", "-f", "/sdcard/validateqa-mobile-ca.pem"],
|
|
353892
353933
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353893
353934
|
);
|
|
353894
353935
|
} catch (err) {
|
|
353895
|
-
onLog?.(`[mobile-net] adb remove CA failed: ${
|
|
353936
|
+
onLog?.(`[mobile-net] adb remove CA failed: ${errMsg2(err)}`);
|
|
353896
353937
|
}
|
|
353897
353938
|
}
|
|
353898
353939
|
async function iosSimTrustCa(deviceId, caCertPath) {
|
|
353899
353940
|
try {
|
|
353900
|
-
await
|
|
353941
|
+
await execFileAsync2("xcrun", ["simctl", "keychain", deviceId, "add-root-cert", caCertPath], {
|
|
353901
353942
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353902
353943
|
});
|
|
353903
353944
|
return {
|
|
@@ -353905,18 +353946,18 @@ async function iosSimTrustCa(deviceId, caCertPath) {
|
|
|
353905
353946
|
note: "CA added to simulator keychain (add-root-cert). NOTE: the simulator has no per-app HTTP proxy setting controllable via simctl \u2014 it shares the host network, so only traffic that actually routes through the proxy is intercepted; pinned apps still never decrypt."
|
|
353906
353947
|
};
|
|
353907
353948
|
} catch (err) {
|
|
353908
|
-
return { trusted: false, note: `simctl add-root-cert failed: ${
|
|
353949
|
+
return { trusted: false, note: `simctl add-root-cert failed: ${errMsg2(err)}` };
|
|
353909
353950
|
}
|
|
353910
353951
|
}
|
|
353911
353952
|
async function iosSimRemoveCa(deviceId, onLog) {
|
|
353912
353953
|
if (process.env.VALIDATEQA_MOBILE_SIM_KEYCHAIN_RESET === "1") {
|
|
353913
353954
|
try {
|
|
353914
|
-
await
|
|
353955
|
+
await execFileAsync2("xcrun", ["simctl", "keychain", deviceId, "reset"], {
|
|
353915
353956
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353916
353957
|
});
|
|
353917
353958
|
onLog?.(`[mobile-net] simctl keychain reset run for ${deviceId} (opt-in; cleared ALL sim certs).`);
|
|
353918
353959
|
} catch (err) {
|
|
353919
|
-
onLog?.(`[mobile-net] simctl keychain reset failed: ${
|
|
353960
|
+
onLog?.(`[mobile-net] simctl keychain reset failed: ${errMsg2(err)}`);
|
|
353920
353961
|
}
|
|
353921
353962
|
return;
|
|
353922
353963
|
}
|
|
@@ -353924,7 +353965,7 @@ async function iosSimRemoveCa(deviceId, onLog) {
|
|
|
353924
353965
|
`[mobile-net] NOTE: the validate.qa capture CA remains TRUSTED in simulator ${deviceId}. simctl has no scoped remove (only a full keychain reset that wipes ALL certs), so we leave the single CA in place. Use a throwaway simulator, or set VALIDATEQA_MOBILE_SIM_KEYCHAIN_RESET=1 to reset the whole sim keychain on teardown.`
|
|
353925
353966
|
);
|
|
353926
353967
|
}
|
|
353927
|
-
function
|
|
353968
|
+
function errMsg2(err) {
|
|
353928
353969
|
return err instanceof Error ? err.message : String(err);
|
|
353929
353970
|
}
|
|
353930
353971
|
function isProcessAlive(pid) {
|
|
@@ -354015,7 +354056,7 @@ async function iosSimConfigureHostProxy(host, port, onLog) {
|
|
|
354015
354056
|
let service;
|
|
354016
354057
|
let prior;
|
|
354017
354058
|
try {
|
|
354018
|
-
const { stdout: order } = await
|
|
354059
|
+
const { stdout: order } = await execFileAsync2("networksetup", ["-listnetworkserviceorder"], {
|
|
354019
354060
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
354020
354061
|
});
|
|
354021
354062
|
const svc = parsePrimaryNetworkService(order);
|
|
@@ -354024,26 +354065,26 @@ async function iosSimConfigureHostProxy(host, port, onLog) {
|
|
|
354024
354065
|
}
|
|
354025
354066
|
service = svc;
|
|
354026
354067
|
const [{ stdout: webOut }, { stdout: secureOut }] = await Promise.all([
|
|
354027
|
-
|
|
354028
|
-
|
|
354068
|
+
execFileAsync2("networksetup", ["-getwebproxy", service], { timeout: DEVICE_CMD_TIMEOUT_MS }),
|
|
354069
|
+
execFileAsync2("networksetup", ["-getsecurewebproxy", service], { timeout: DEVICE_CMD_TIMEOUT_MS })
|
|
354029
354070
|
]);
|
|
354030
354071
|
prior = { web: parseWebProxyState(webOut), secure: parseWebProxyState(secureOut) };
|
|
354031
354072
|
for (const args of buildHostProxySetCommands(service, host, port)) {
|
|
354032
|
-
await
|
|
354073
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354033
354074
|
}
|
|
354034
354075
|
onLog?.(`[mobile-net] macOS host proxy set on "${service}" \u2192 ${host}:${port} (iOS simulator shares the host network).`);
|
|
354035
354076
|
return { configured: true, service, prior };
|
|
354036
354077
|
} catch (err) {
|
|
354037
354078
|
if (service && prior) {
|
|
354038
|
-
onLog?.(`[mobile-net] host proxy set failed mid-way \u2014 rolling back "${service}" to prior state: ${
|
|
354079
|
+
onLog?.(`[mobile-net] host proxy set failed mid-way \u2014 rolling back "${service}" to prior state: ${errMsg2(err)}`);
|
|
354039
354080
|
for (const args of buildHostProxyRestoreCommands(service, prior)) {
|
|
354040
354081
|
try {
|
|
354041
|
-
await
|
|
354082
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354042
354083
|
} catch {
|
|
354043
354084
|
}
|
|
354044
354085
|
}
|
|
354045
354086
|
}
|
|
354046
|
-
return { configured: false, reason: `iOS simulator host proxy could not be configured: ${
|
|
354087
|
+
return { configured: false, reason: `iOS simulator host proxy could not be configured: ${errMsg2(err)}` };
|
|
354047
354088
|
}
|
|
354048
354089
|
}
|
|
354049
354090
|
async function iosSimRestoreHostProxy(service, prior, onLog) {
|
|
@@ -354053,9 +354094,9 @@ async function iosSimRestoreHostProxy(service, prior, onLog) {
|
|
|
354053
354094
|
};
|
|
354054
354095
|
for (const args of buildHostProxyRestoreCommands(service, restore)) {
|
|
354055
354096
|
try {
|
|
354056
|
-
await
|
|
354097
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354057
354098
|
} catch (err) {
|
|
354058
|
-
onLog?.(`[mobile-net] networksetup restore (${args[0]}) failed: ${
|
|
354099
|
+
onLog?.(`[mobile-net] networksetup restore (${args[0]}) failed: ${errMsg2(err)}`);
|
|
354059
354100
|
}
|
|
354060
354101
|
}
|
|
354061
354102
|
onLog?.(`[mobile-net] macOS host proxy restored on "${service}".`);
|
|
@@ -354063,7 +354104,7 @@ async function iosSimRestoreHostProxy(service, prior, onLog) {
|
|
|
354063
354104
|
var activeCleanups = /* @__PURE__ */ new Map();
|
|
354064
354105
|
var exitHandlersInstalled = false;
|
|
354065
354106
|
function markerPath(sessionKey) {
|
|
354066
|
-
return
|
|
354107
|
+
return join4(PENDING_CLEANUP_DIR, `${sessionKey}.json`);
|
|
354067
354108
|
}
|
|
354068
354109
|
async function writePendingCleanup(sessionKey, marker) {
|
|
354069
354110
|
try {
|
|
@@ -354107,7 +354148,7 @@ function restoreDeviceSync(marker, onLog) {
|
|
|
354107
354148
|
async function reconcilePendingCleanups(onLog) {
|
|
354108
354149
|
let files;
|
|
354109
354150
|
try {
|
|
354110
|
-
files = await
|
|
354151
|
+
files = await readdir2(PENDING_CLEANUP_DIR);
|
|
354111
354152
|
} catch {
|
|
354112
354153
|
return;
|
|
354113
354154
|
}
|
|
@@ -354115,7 +354156,7 @@ async function reconcilePendingCleanups(onLog) {
|
|
|
354115
354156
|
if (!file.endsWith(".json")) continue;
|
|
354116
354157
|
const sessionKey = file.slice(0, -".json".length);
|
|
354117
354158
|
if (activeCleanups.has(sessionKey)) continue;
|
|
354118
|
-
const full =
|
|
354159
|
+
const full = join4(PENDING_CLEANUP_DIR, file);
|
|
354119
354160
|
try {
|
|
354120
354161
|
const raw = await readFile(full, "utf-8");
|
|
354121
354162
|
const marker = JSON.parse(raw);
|
|
@@ -354168,7 +354209,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354168
354209
|
let caKeyPem = null;
|
|
354169
354210
|
let caCertPem = null;
|
|
354170
354211
|
try {
|
|
354171
|
-
tmpDir = await mkdtemp(
|
|
354212
|
+
tmpDir = await mkdtemp(join4(tmpdir2(), "validateqa-mobile-ca-"));
|
|
354172
354213
|
const ca = await generateCaCert(tmpDir, onLog);
|
|
354173
354214
|
if (ca) {
|
|
354174
354215
|
caCertPath = ca.caCertPath;
|
|
@@ -354176,7 +354217,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354176
354217
|
caCertPem = ca.caCertPem;
|
|
354177
354218
|
}
|
|
354178
354219
|
} catch (err) {
|
|
354179
|
-
onLog?.(`[mobile-net] CA setup degraded: ${
|
|
354220
|
+
onLog?.(`[mobile-net] CA setup degraded: ${errMsg2(err)}`);
|
|
354180
354221
|
}
|
|
354181
354222
|
if (!caKeyPem || !caCertPem) {
|
|
354182
354223
|
try {
|
|
@@ -354184,9 +354225,9 @@ async function startMobileNetworkCapture(options) {
|
|
|
354184
354225
|
caKeyPem = fallback.key;
|
|
354185
354226
|
caCertPem = fallback.cert;
|
|
354186
354227
|
} catch (err) {
|
|
354187
|
-
onLog?.(`[mobile-net] fatal CA failure, cannot start proxy: ${
|
|
354228
|
+
onLog?.(`[mobile-net] fatal CA failure, cannot start proxy: ${errMsg2(err)}`);
|
|
354188
354229
|
if (tmpDir) {
|
|
354189
|
-
await
|
|
354230
|
+
await rm2(tmpDir, { recursive: true, force: true }).catch(() => void 0);
|
|
354190
354231
|
}
|
|
354191
354232
|
throw err instanceof Error ? err : new Error(String(err));
|
|
354192
354233
|
}
|
|
@@ -354241,7 +354282,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354241
354282
|
}
|
|
354242
354283
|
}
|
|
354243
354284
|
} catch (err) {
|
|
354244
|
-
wiringReason = `device wiring degraded: ${
|
|
354285
|
+
wiringReason = `device wiring degraded: ${errMsg2(err)}`;
|
|
354245
354286
|
onLog?.(`[mobile-net] ${wiringReason}`);
|
|
354246
354287
|
}
|
|
354247
354288
|
if (proxySet || caInstalledOnDevice || hostProxySet) {
|
|
@@ -354330,9 +354371,9 @@ async function startMobileNetworkCapture(options) {
|
|
|
354330
354371
|
await proxy.close();
|
|
354331
354372
|
if (capturedTmpDir) {
|
|
354332
354373
|
try {
|
|
354333
|
-
await
|
|
354374
|
+
await rm2(capturedTmpDir, { recursive: true, force: true });
|
|
354334
354375
|
} catch (err) {
|
|
354335
|
-
onLog?.(`[mobile-net] temp CA cleanup failed: ${
|
|
354376
|
+
onLog?.(`[mobile-net] temp CA cleanup failed: ${errMsg2(err)}`);
|
|
354336
354377
|
}
|
|
354337
354378
|
}
|
|
354338
354379
|
const apiCount = finalCalls.filter((c) => c.isApi).length;
|
|
@@ -354369,7 +354410,7 @@ var WD_SESSION_CREATE_TIMEOUT_MS = 12e4;
|
|
|
354369
354410
|
var WD_ACTION_TIMEOUT_MS = 3e4;
|
|
354370
354411
|
var APPIUM_DRIVER_DEAD_RE2 = /instrumentation process is not running|cannot be proxied to UiAutomator2 server|socket hang up|ECONNRESET/i;
|
|
354371
354412
|
var MAX_SESSION_CREATE_ATTEMPTS = 3;
|
|
354372
|
-
var
|
|
354413
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
354373
354414
|
var MOBILE_TEXT_ATTRIBUTE_NAMES = ["text", "content-desc", "contentDescription", "name", "label", "value"];
|
|
354374
354415
|
var WebDriverTransportError = class extends Error {
|
|
354375
354416
|
isTransport = true;
|
|
@@ -354498,11 +354539,11 @@ function mobileParallelSessionCapabilities(platform3, portOffset = 0, deviceId =
|
|
|
354498
354539
|
return { "appium:systemPort": readPort("APPIUM_SYSTEM_PORT", 8200) };
|
|
354499
354540
|
}
|
|
354500
354541
|
const safeDevice = deviceId.replace(/[^A-Za-z0-9._-]+/g, "-") || `device-${offset}`;
|
|
354501
|
-
const derivedDataRoot = env.APPIUM_DERIVED_DATA_PATH?.trim() ||
|
|
354542
|
+
const derivedDataRoot = env.APPIUM_DERIVED_DATA_PATH?.trim() || join5(tmpdir3(), "validateqa-wda");
|
|
354502
354543
|
return {
|
|
354503
354544
|
"appium:wdaLocalPort": readPort("APPIUM_WDA_LOCAL_PORT", 8100),
|
|
354504
354545
|
"appium:mjpegServerPort": readPort("APPIUM_MJPEG_SERVER_PORT", 9100),
|
|
354505
|
-
"appium:derivedDataPath":
|
|
354546
|
+
"appium:derivedDataPath": join5(derivedDataRoot, safeDevice)
|
|
354506
354547
|
};
|
|
354507
354548
|
}
|
|
354508
354549
|
function isAndroidSystemPortBusyError(error2) {
|
|
@@ -354586,7 +354627,7 @@ async function removeStaleAndroidSystemPortForward(target, error2) {
|
|
|
354586
354627
|
const args = androidSystemPortForwardRemovalArgs(target, error2);
|
|
354587
354628
|
if (!args) return false;
|
|
354588
354629
|
try {
|
|
354589
|
-
await
|
|
354630
|
+
await execFileAsync3("adb", args, { timeout: 1e4, windowsHide: true });
|
|
354590
354631
|
return true;
|
|
354591
354632
|
} catch {
|
|
354592
354633
|
return false;
|
|
@@ -355060,7 +355101,7 @@ async function prepareAndroidInputEnvironment(deviceId) {
|
|
|
355060
355101
|
];
|
|
355061
355102
|
for (const [namespace, key, value] of settingsToDisable) {
|
|
355062
355103
|
try {
|
|
355063
|
-
await
|
|
355104
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "settings", "put", namespace, key, value], {
|
|
355064
355105
|
timeout: 8e3,
|
|
355065
355106
|
windowsHide: true
|
|
355066
355107
|
});
|
|
@@ -355072,14 +355113,14 @@ async function sendAndroidTextToFocusedInput(deviceId, value) {
|
|
|
355072
355113
|
if (!deviceId) {
|
|
355073
355114
|
throw new Error("Android keyboard fallback requires a device id");
|
|
355074
355115
|
}
|
|
355075
|
-
await
|
|
355116
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "input", "text", encodeAndroidInputText(value)], {
|
|
355076
355117
|
timeout: 1e4,
|
|
355077
355118
|
windowsHide: true
|
|
355078
355119
|
});
|
|
355079
355120
|
}
|
|
355080
355121
|
async function pressAndroidKeyboardEnter(deviceId) {
|
|
355081
355122
|
if (!deviceId) throw new Error("Android keyboard Enter fallback requires a device id");
|
|
355082
|
-
await
|
|
355123
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "input", "keyevent", "66"], {
|
|
355083
355124
|
timeout: 1e4,
|
|
355084
355125
|
windowsHide: true
|
|
355085
355126
|
});
|
|
@@ -355600,7 +355641,14 @@ async function executeMobileTest(options) {
|
|
|
355600
355641
|
const resetAllowed = shouldResetMobileAppData(options.target.platform, selectedDevice.id);
|
|
355601
355642
|
if (resetAllowed) {
|
|
355602
355643
|
try {
|
|
355603
|
-
|
|
355644
|
+
if (options.target.platform === "IOS") {
|
|
355645
|
+
await terminateTargetApp(sessionId, "IOS", options.target.appId).catch(() => {
|
|
355646
|
+
});
|
|
355647
|
+
const wiped = await clearIosSimulatorAppData(selectedDevice.id, options.target.appId);
|
|
355648
|
+
if (!wiped.ok) throw new Error(wiped.detail);
|
|
355649
|
+
} else {
|
|
355650
|
+
await executeMobileScript(sessionId, "mobile: clearApp", [{ appId: options.target.appId }]);
|
|
355651
|
+
}
|
|
355604
355652
|
clearedAppDataBeforeLaunch = true;
|
|
355605
355653
|
log2(resetPolicy === "CLEAR_APP_DATA" ? "App data cleared before launch (target resetPolicy=CLEAR_APP_DATA)." : "App data cleared before launch (test was recorded from a cold logged-out state).");
|
|
355606
355654
|
} catch (err) {
|
|
@@ -356261,7 +356309,7 @@ import { createServer } from "http";
|
|
|
356261
356309
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
356262
356310
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
356263
356311
|
import { homedir as homedir2 } from "os";
|
|
356264
|
-
import { join as
|
|
356312
|
+
import { join as join6, dirname } from "path";
|
|
356265
356313
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
356266
356314
|
init_dist();
|
|
356267
356315
|
var MOBILE_BRIDGE_PORT2 = 9515;
|
|
@@ -356368,7 +356416,7 @@ async function getWindowSize3() {
|
|
|
356368
356416
|
}
|
|
356369
356417
|
var BRIDGE_PROCESS_MARKER = "validateqa-mobile-bridge";
|
|
356370
356418
|
var BRIDGE_PORT = MOBILE_BRIDGE_PORT2;
|
|
356371
|
-
var BRIDGE_PID_FILE =
|
|
356419
|
+
var BRIDGE_PID_FILE = join6(homedir2(), ".validate.qa", "mobile-bridge.pid");
|
|
356372
356420
|
function readBridgePidFile() {
|
|
356373
356421
|
try {
|
|
356374
356422
|
const raw = readFileSync2(BRIDGE_PID_FILE, "utf-8").trim();
|
|
@@ -357506,6 +357554,7 @@ var MobileBridgeDriver = class {
|
|
|
357506
357554
|
sessionId;
|
|
357507
357555
|
platform;
|
|
357508
357556
|
appId;
|
|
357557
|
+
deviceId;
|
|
357509
357558
|
allowAppReset;
|
|
357510
357559
|
recoverSession;
|
|
357511
357560
|
maxSessionRecoveries;
|
|
@@ -357526,6 +357575,7 @@ var MobileBridgeDriver = class {
|
|
|
357526
357575
|
this.sessionId = config.sessionId;
|
|
357527
357576
|
this.platform = config.platform;
|
|
357528
357577
|
this.appId = config.appId;
|
|
357578
|
+
this.deviceId = config.deviceId;
|
|
357529
357579
|
this.allowAppReset = config.allowAppReset === true;
|
|
357530
357580
|
this.recoverSession = config.recoverSession;
|
|
357531
357581
|
this.maxSessionRecoveries = Math.max(0, Math.floor(config.maxSessionRecoveries ?? 1));
|
|
@@ -357823,17 +357873,34 @@ var MobileBridgeDriver = class {
|
|
|
357823
357873
|
});
|
|
357824
357874
|
}
|
|
357825
357875
|
/**
|
|
357826
|
-
* Deterministic state reset: clear app data + relaunch
|
|
357827
|
-
*
|
|
357828
|
-
*
|
|
357829
|
-
*
|
|
357830
|
-
*
|
|
357876
|
+
* Deterministic state reset: clear app data + relaunch, per the
|
|
357877
|
+
* runner-computed allowAppReset policy (Android emulators / iOS simulators
|
|
357878
|
+
* only — a personal physical device is never wiped). Android clears via
|
|
357879
|
+
* `mobile: clearApp`; iOS terminates the app and wipes its simulator data
|
|
357880
|
+
* container + keychain through `simctl` (see ios-simulator-reset.ts).
|
|
357881
|
+
* Returns false when unsupported/disallowed or when the clear fails —
|
|
357882
|
+
* callers fall back to relaunch(), preserving today's behavior. On success,
|
|
357883
|
+
* waits for cold-boot content so recording and replay agree on the true
|
|
357884
|
+
* entry screen.
|
|
357831
357885
|
*/
|
|
357832
357886
|
async resetAppState() {
|
|
357833
|
-
if (!this.allowAppReset
|
|
357887
|
+
if (!this.allowAppReset) return false;
|
|
357888
|
+
if (this.platform === "IOS" && !isIosSimulatorUdid(this.deviceId)) return false;
|
|
357834
357889
|
return this.withSessionRecovery("app data reset", async () => {
|
|
357835
357890
|
try {
|
|
357836
|
-
|
|
357891
|
+
if (this.platform === "IOS") {
|
|
357892
|
+
try {
|
|
357893
|
+
await this.executeScript("mobile: terminateApp", [{ ...this.appLifecycleArgs(), timeout: 5e3 }]);
|
|
357894
|
+
} catch (err) {
|
|
357895
|
+
if (isRecoverableAppiumSessionFailure(err)) throw err;
|
|
357896
|
+
}
|
|
357897
|
+
const wiped = await clearIosSimulatorAppData(this.deviceId ?? "", this.appId);
|
|
357898
|
+
if (!wiped.ok) {
|
|
357899
|
+
throw new Error(`iOS simulator app-data reset failed: ${wiped.detail}`);
|
|
357900
|
+
}
|
|
357901
|
+
} else {
|
|
357902
|
+
await this.executeScript("mobile: clearApp", [{ appId: this.appId }]);
|
|
357903
|
+
}
|
|
357837
357904
|
await this.executeScript("mobile: activateApp", [this.appLifecycleArgs()]);
|
|
357838
357905
|
try {
|
|
357839
357906
|
await waitForColdBootSettle(this.sessionPath);
|
|
@@ -358499,7 +358566,7 @@ var log = {
|
|
|
358499
358566
|
dim: (msg) => console.log(`${C2.gray}${msg}${C2.reset}`)
|
|
358500
358567
|
};
|
|
358501
358568
|
function getRunsDir() {
|
|
358502
|
-
const dir = process.env.RUNS_DIR ||
|
|
358569
|
+
const dir = process.env.RUNS_DIR || join7(homedir3(), ".validate.qa", "runs");
|
|
358503
358570
|
(0, import_runner_core12.ensurePrivateDirectory)(dir);
|
|
358504
358571
|
return dir;
|
|
358505
358572
|
}
|
|
@@ -360431,9 +360498,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
360431
360498
|
sessionId: session.sessionId,
|
|
360432
360499
|
platform: platform3,
|
|
360433
360500
|
appId: session.appId,
|
|
360434
|
-
|
|
360435
|
-
//
|
|
360436
|
-
//
|
|
360501
|
+
deviceId: session.deviceId,
|
|
360502
|
+
// Deterministic-state authorization: Android emulators / iOS
|
|
360503
|
+
// simulators only (VALIDATEQA_MOBILE_APP_RESET overrides the
|
|
360504
|
+
// Android default) — a personal physical device must never have
|
|
360505
|
+
// its app data wiped.
|
|
360437
360506
|
allowAppReset: mobileTarget.resetPolicy !== "PRESERVE_APP_DATA" && shouldResetMobileAppData(platform3, session.deviceId),
|
|
360438
360507
|
maxSessionRecoveries: 1,
|
|
360439
360508
|
recoverSession: async (cause) => {
|
|
@@ -360949,6 +361018,7 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
360949
361018
|
sessionId: opened.sessionId,
|
|
360950
361019
|
platform: target.platform,
|
|
360951
361020
|
appId: opened.appId,
|
|
361021
|
+
deviceId: opened.deviceId,
|
|
360952
361022
|
allowAppReset: target.resetPolicy !== "PRESERVE_APP_DATA" && shouldResetMobileAppData(target.platform, opened.deviceId)
|
|
360953
361023
|
});
|
|
360954
361024
|
};
|