@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.js
CHANGED
|
@@ -11293,7 +11293,7 @@ var require_thread_stream = __commonJS({
|
|
|
11293
11293
|
var { version } = require_package();
|
|
11294
11294
|
var { EventEmitter: EventEmitter2 } = require("events");
|
|
11295
11295
|
var { Worker } = require("worker_threads");
|
|
11296
|
-
var { join:
|
|
11296
|
+
var { join: join8 } = require("path");
|
|
11297
11297
|
var { pathToFileURL } = require("url");
|
|
11298
11298
|
var { wait } = require_wait();
|
|
11299
11299
|
var {
|
|
@@ -11344,7 +11344,7 @@ var require_thread_stream = __commonJS({
|
|
|
11344
11344
|
function createWorker(stream, opts) {
|
|
11345
11345
|
const { filename, workerData } = opts;
|
|
11346
11346
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
11347
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
11347
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join8(__dirname, "lib", "worker.js");
|
|
11348
11348
|
const worker = new Worker(toExecute, {
|
|
11349
11349
|
...opts.workerOpts,
|
|
11350
11350
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -11812,7 +11812,7 @@ var require_transport = __commonJS({
|
|
|
11812
11812
|
var { createRequire } = require("module");
|
|
11813
11813
|
var { existsSync: existsSync3 } = require("fs");
|
|
11814
11814
|
var getCallers = require_caller();
|
|
11815
|
-
var { join:
|
|
11815
|
+
var { join: join8, isAbsolute: isAbsolute2, sep } = require("path");
|
|
11816
11816
|
var { fileURLToPath } = require("url");
|
|
11817
11817
|
var sleep = require_atomic_sleep();
|
|
11818
11818
|
var onExit = require_on_exit_leak_free();
|
|
@@ -11884,7 +11884,7 @@ var require_transport = __commonJS({
|
|
|
11884
11884
|
return false;
|
|
11885
11885
|
}
|
|
11886
11886
|
}
|
|
11887
|
-
return
|
|
11887
|
+
return isAbsolute2(path) && !existsSync3(path);
|
|
11888
11888
|
}
|
|
11889
11889
|
function stripQuotes(value) {
|
|
11890
11890
|
const first = value[0];
|
|
@@ -11965,7 +11965,7 @@ var require_transport = __commonJS({
|
|
|
11965
11965
|
throw new Error("only one of target or targets can be specified");
|
|
11966
11966
|
}
|
|
11967
11967
|
if (targets) {
|
|
11968
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
11968
|
+
target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
|
|
11969
11969
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
11970
11970
|
return {
|
|
11971
11971
|
...dest,
|
|
@@ -11983,7 +11983,7 @@ var require_transport = __commonJS({
|
|
|
11983
11983
|
});
|
|
11984
11984
|
});
|
|
11985
11985
|
} else if (pipeline) {
|
|
11986
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
11986
|
+
target = bundlerOverrides["pino-worker"] || join8(__dirname, "worker.js");
|
|
11987
11987
|
options.pipelines = [pipeline.map((dest) => {
|
|
11988
11988
|
return {
|
|
11989
11989
|
...dest,
|
|
@@ -12002,11 +12002,11 @@ var require_transport = __commonJS({
|
|
|
12002
12002
|
return buildStream(fixTarget(target), options, worker, sync, name);
|
|
12003
12003
|
function fixTarget(origin) {
|
|
12004
12004
|
origin = bundlerOverrides[origin] || origin;
|
|
12005
|
-
if (
|
|
12005
|
+
if (isAbsolute2(origin) || origin.indexOf("file://") === 0) {
|
|
12006
12006
|
return origin;
|
|
12007
12007
|
}
|
|
12008
12008
|
if (origin === "pino/file") {
|
|
12009
|
-
return
|
|
12009
|
+
return join8(__dirname, "..", "file.js");
|
|
12010
12010
|
}
|
|
12011
12011
|
let fixTarget2;
|
|
12012
12012
|
for (const filePath of callers) {
|
|
@@ -12987,7 +12987,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
12987
12987
|
return circularValue;
|
|
12988
12988
|
}
|
|
12989
12989
|
let res = "";
|
|
12990
|
-
let
|
|
12990
|
+
let join8 = ",";
|
|
12991
12991
|
const originalIndentation = indentation;
|
|
12992
12992
|
if (Array.isArray(value)) {
|
|
12993
12993
|
if (value.length === 0) {
|
|
@@ -13001,7 +13001,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
13001
13001
|
indentation += spacer;
|
|
13002
13002
|
res += `
|
|
13003
13003
|
${indentation}`;
|
|
13004
|
-
|
|
13004
|
+
join8 = `,
|
|
13005
13005
|
${indentation}`;
|
|
13006
13006
|
}
|
|
13007
13007
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -13009,13 +13009,13 @@ ${indentation}`;
|
|
|
13009
13009
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13010
13010
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
13011
13011
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
13012
|
-
res +=
|
|
13012
|
+
res += join8;
|
|
13013
13013
|
}
|
|
13014
13014
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
13015
13015
|
res += tmp !== void 0 ? tmp : "null";
|
|
13016
13016
|
if (value.length - 1 > maximumBreadth) {
|
|
13017
13017
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13018
|
-
res += `${
|
|
13018
|
+
res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13019
13019
|
}
|
|
13020
13020
|
if (spacer !== "") {
|
|
13021
13021
|
res += `
|
|
@@ -13036,7 +13036,7 @@ ${originalIndentation}`;
|
|
|
13036
13036
|
let separator = "";
|
|
13037
13037
|
if (spacer !== "") {
|
|
13038
13038
|
indentation += spacer;
|
|
13039
|
-
|
|
13039
|
+
join8 = `,
|
|
13040
13040
|
${indentation}`;
|
|
13041
13041
|
whitespace = " ";
|
|
13042
13042
|
}
|
|
@@ -13050,13 +13050,13 @@ ${indentation}`;
|
|
|
13050
13050
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
13051
13051
|
if (tmp !== void 0) {
|
|
13052
13052
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
13053
|
-
separator =
|
|
13053
|
+
separator = join8;
|
|
13054
13054
|
}
|
|
13055
13055
|
}
|
|
13056
13056
|
if (keyLength > maximumBreadth) {
|
|
13057
13057
|
const removedKeys = keyLength - maximumBreadth;
|
|
13058
13058
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
13059
|
-
separator =
|
|
13059
|
+
separator = join8;
|
|
13060
13060
|
}
|
|
13061
13061
|
if (spacer !== "" && separator.length > 1) {
|
|
13062
13062
|
res = `
|
|
@@ -13097,7 +13097,7 @@ ${originalIndentation}`;
|
|
|
13097
13097
|
}
|
|
13098
13098
|
const originalIndentation = indentation;
|
|
13099
13099
|
let res = "";
|
|
13100
|
-
let
|
|
13100
|
+
let join8 = ",";
|
|
13101
13101
|
if (Array.isArray(value)) {
|
|
13102
13102
|
if (value.length === 0) {
|
|
13103
13103
|
return "[]";
|
|
@@ -13110,7 +13110,7 @@ ${originalIndentation}`;
|
|
|
13110
13110
|
indentation += spacer;
|
|
13111
13111
|
res += `
|
|
13112
13112
|
${indentation}`;
|
|
13113
|
-
|
|
13113
|
+
join8 = `,
|
|
13114
13114
|
${indentation}`;
|
|
13115
13115
|
}
|
|
13116
13116
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -13118,13 +13118,13 @@ ${indentation}`;
|
|
|
13118
13118
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13119
13119
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
13120
13120
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
13121
|
-
res +=
|
|
13121
|
+
res += join8;
|
|
13122
13122
|
}
|
|
13123
13123
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
13124
13124
|
res += tmp !== void 0 ? tmp : "null";
|
|
13125
13125
|
if (value.length - 1 > maximumBreadth) {
|
|
13126
13126
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13127
|
-
res += `${
|
|
13127
|
+
res += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13128
13128
|
}
|
|
13129
13129
|
if (spacer !== "") {
|
|
13130
13130
|
res += `
|
|
@@ -13137,7 +13137,7 @@ ${originalIndentation}`;
|
|
|
13137
13137
|
let whitespace = "";
|
|
13138
13138
|
if (spacer !== "") {
|
|
13139
13139
|
indentation += spacer;
|
|
13140
|
-
|
|
13140
|
+
join8 = `,
|
|
13141
13141
|
${indentation}`;
|
|
13142
13142
|
whitespace = " ";
|
|
13143
13143
|
}
|
|
@@ -13146,7 +13146,7 @@ ${indentation}`;
|
|
|
13146
13146
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
13147
13147
|
if (tmp !== void 0) {
|
|
13148
13148
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
13149
|
-
separator =
|
|
13149
|
+
separator = join8;
|
|
13150
13150
|
}
|
|
13151
13151
|
}
|
|
13152
13152
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -13204,20 +13204,20 @@ ${originalIndentation}`;
|
|
|
13204
13204
|
indentation += spacer;
|
|
13205
13205
|
let res2 = `
|
|
13206
13206
|
${indentation}`;
|
|
13207
|
-
const
|
|
13207
|
+
const join9 = `,
|
|
13208
13208
|
${indentation}`;
|
|
13209
13209
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
13210
13210
|
let i = 0;
|
|
13211
13211
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
13212
13212
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
13213
13213
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
13214
|
-
res2 +=
|
|
13214
|
+
res2 += join9;
|
|
13215
13215
|
}
|
|
13216
13216
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
13217
13217
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
13218
13218
|
if (value.length - 1 > maximumBreadth) {
|
|
13219
13219
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
13220
|
-
res2 += `${
|
|
13220
|
+
res2 += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
13221
13221
|
}
|
|
13222
13222
|
res2 += `
|
|
13223
13223
|
${originalIndentation}`;
|
|
@@ -13233,16 +13233,16 @@ ${originalIndentation}`;
|
|
|
13233
13233
|
return '"[Object]"';
|
|
13234
13234
|
}
|
|
13235
13235
|
indentation += spacer;
|
|
13236
|
-
const
|
|
13236
|
+
const join8 = `,
|
|
13237
13237
|
${indentation}`;
|
|
13238
13238
|
let res = "";
|
|
13239
13239
|
let separator = "";
|
|
13240
13240
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
13241
13241
|
if (isTypedArrayWithEntries(value)) {
|
|
13242
|
-
res += stringifyTypedArray(value,
|
|
13242
|
+
res += stringifyTypedArray(value, join8, maximumBreadth);
|
|
13243
13243
|
keys = keys.slice(value.length);
|
|
13244
13244
|
maximumPropertiesToStringify -= value.length;
|
|
13245
|
-
separator =
|
|
13245
|
+
separator = join8;
|
|
13246
13246
|
}
|
|
13247
13247
|
if (deterministic) {
|
|
13248
13248
|
keys = sort(keys, comparator);
|
|
@@ -13253,13 +13253,13 @@ ${indentation}`;
|
|
|
13253
13253
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
13254
13254
|
if (tmp !== void 0) {
|
|
13255
13255
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
13256
|
-
separator =
|
|
13256
|
+
separator = join8;
|
|
13257
13257
|
}
|
|
13258
13258
|
}
|
|
13259
13259
|
if (keyLength > maximumBreadth) {
|
|
13260
13260
|
const removedKeys = keyLength - maximumBreadth;
|
|
13261
13261
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
13262
|
-
separator =
|
|
13262
|
+
separator = join8;
|
|
13263
13263
|
}
|
|
13264
13264
|
if (separator !== "") {
|
|
13265
13265
|
res = `
|
|
@@ -61935,11 +61935,11 @@ var require_core = __commonJS({
|
|
|
61935
61935
|
function mapOuter(r, f) {
|
|
61936
61936
|
return r.matched ? f(r) : r;
|
|
61937
61937
|
}
|
|
61938
|
-
function ab(pa, pb,
|
|
61939
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) =>
|
|
61938
|
+
function ab(pa, pb, join8) {
|
|
61939
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join8(ma.value, vb, data, i, j)));
|
|
61940
61940
|
}
|
|
61941
|
-
function abc(pa, pb, pc,
|
|
61942
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) =>
|
|
61941
|
+
function abc(pa, pb, pc, join8) {
|
|
61942
|
+
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))));
|
|
61943
61943
|
}
|
|
61944
61944
|
function action(f) {
|
|
61945
61945
|
return (data, i) => {
|
|
@@ -83524,48 +83524,29 @@ ${statePacket}`, redactionCredentials) },
|
|
|
83524
83524
|
log2(" app data reset skipped by policy \u2014 scenario records after relaunch with preserved data.");
|
|
83525
83525
|
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: false, coldResetUnavailable: false, refuseGenerate: false, reason: "preserve_policy" }, log2);
|
|
83526
83526
|
}
|
|
83527
|
-
|
|
83528
|
-
|
|
83529
|
-
|
|
83530
|
-
|
|
83531
|
-
|
|
83532
|
-
|
|
83533
|
-
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: true, coldResetUnavailable: false, refuseGenerate: false }, log2);
|
|
83534
|
-
}
|
|
83535
|
-
await driver.relaunch();
|
|
83536
|
-
if (resetPolicy === "CLEAR_APP_DATA") {
|
|
83537
|
-
log2(" CLEAR_APP_DATA required but app-data reset was unavailable \u2014 refusing to generate from warm state.");
|
|
83538
|
-
return {
|
|
83539
|
-
appDataCleared: false,
|
|
83540
|
-
coldResetUnavailable: true,
|
|
83541
|
-
refuseGenerate: true,
|
|
83542
|
-
reason: "clear_app_data_unavailable"
|
|
83543
|
-
};
|
|
83544
|
-
}
|
|
83545
|
-
log2(" app-data reset unavailable \u2014 generating with @warm-state (relaunch only; may not match cold-boot replay).");
|
|
83546
|
-
return applyScenarioEntryDeepLink(driver, target, {
|
|
83547
|
-
appDataCleared: false,
|
|
83548
|
-
coldResetUnavailable: true,
|
|
83549
|
-
refuseGenerate: false,
|
|
83550
|
-
reason: platform3 === "ANDROID" ? "android_reset_unavailable" : "reset_unavailable"
|
|
83551
|
-
}, log2);
|
|
83527
|
+
const appDataCleared = await driver.resetAppState?.().catch((err) => {
|
|
83528
|
+
log2(` app-data reset failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
83529
|
+
return false;
|
|
83530
|
+
}) ?? false;
|
|
83531
|
+
if (appDataCleared) {
|
|
83532
|
+
return applyScenarioEntryDeepLink(driver, target, { appDataCleared: true, coldResetUnavailable: false, refuseGenerate: false }, log2);
|
|
83552
83533
|
}
|
|
83553
83534
|
await driver.relaunch();
|
|
83554
83535
|
if (resetPolicy === "CLEAR_APP_DATA") {
|
|
83555
|
-
log2(" CLEAR_APP_DATA required but iOS
|
|
83536
|
+
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.");
|
|
83556
83537
|
return {
|
|
83557
83538
|
appDataCleared: false,
|
|
83558
83539
|
coldResetUnavailable: true,
|
|
83559
83540
|
refuseGenerate: true,
|
|
83560
|
-
reason: "ios_clear_app_data_unavailable"
|
|
83541
|
+
reason: platform3 === "IOS" ? "ios_clear_app_data_unavailable" : "clear_app_data_unavailable"
|
|
83561
83542
|
};
|
|
83562
83543
|
}
|
|
83563
|
-
log2(" iOS
|
|
83544
|
+
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).");
|
|
83564
83545
|
return applyScenarioEntryDeepLink(driver, target, {
|
|
83565
83546
|
appDataCleared: false,
|
|
83566
83547
|
coldResetUnavailable: true,
|
|
83567
83548
|
refuseGenerate: false,
|
|
83568
|
-
reason: "ios_no_clear_app"
|
|
83549
|
+
reason: platform3 === "IOS" ? "ios_no_clear_app" : platform3 === "ANDROID" ? "android_reset_unavailable" : "reset_unavailable"
|
|
83569
83550
|
}, log2);
|
|
83570
83551
|
}
|
|
83571
83552
|
async function runMobileGeneratePhase(args) {
|
|
@@ -89026,7 +89007,7 @@ var require_kill_tree = __commonJS({
|
|
|
89026
89007
|
var node_child_process_1 = require("child_process");
|
|
89027
89008
|
var node_util_1 = require("util");
|
|
89028
89009
|
var node_fs_1 = require("fs");
|
|
89029
|
-
var
|
|
89010
|
+
var execFileAsync4 = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
89030
89011
|
var PS_TIMEOUT_MS = 2e3;
|
|
89031
89012
|
var PS_BUFFER = 1024 * 1024;
|
|
89032
89013
|
async function gracefulCloseWithTreeKill(options) {
|
|
@@ -89080,7 +89061,7 @@ var require_kill_tree = __commonJS({
|
|
|
89080
89061
|
timer.unref?.();
|
|
89081
89062
|
let stdout;
|
|
89082
89063
|
try {
|
|
89083
|
-
const result = await
|
|
89064
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid=,command="], {
|
|
89084
89065
|
maxBuffer: PS_BUFFER,
|
|
89085
89066
|
signal: controller.signal
|
|
89086
89067
|
});
|
|
@@ -89118,7 +89099,7 @@ var require_kill_tree = __commonJS({
|
|
|
89118
89099
|
timer.unref?.();
|
|
89119
89100
|
let stdout;
|
|
89120
89101
|
try {
|
|
89121
|
-
const result = await
|
|
89102
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid=,command="], {
|
|
89122
89103
|
maxBuffer: PS_BUFFER,
|
|
89123
89104
|
signal: controller.signal
|
|
89124
89105
|
});
|
|
@@ -89195,7 +89176,7 @@ var require_kill_tree = __commonJS({
|
|
|
89195
89176
|
timer.unref?.();
|
|
89196
89177
|
let stdout;
|
|
89197
89178
|
try {
|
|
89198
|
-
const result = await
|
|
89179
|
+
const result = await execFileAsync4("ps", ["-A", "-o", "pid=,ppid="], {
|
|
89199
89180
|
maxBuffer: PS_BUFFER,
|
|
89200
89181
|
signal: controller.signal
|
|
89201
89182
|
});
|
|
@@ -98745,8 +98726,8 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
|
|
|
98745
98726
|
onRetry: (attempt, reason, delayMs) => logs2.push(` \u26A0 scenario-gen AI call retry ${attempt} (${reason}) \u2014 waiting ${delayMs}ms`)
|
|
98746
98727
|
});
|
|
98747
98728
|
} catch (aiErr) {
|
|
98748
|
-
const
|
|
98749
|
-
logs2.push(` AI call failed at iteration ${iteration} (after retries): ${
|
|
98729
|
+
const errMsg3 = aiErr instanceof Error ? aiErr.message : String(aiErr);
|
|
98730
|
+
logs2.push(` AI call failed at iteration ${iteration} (after retries): ${errMsg3}`);
|
|
98750
98731
|
throw (0, ai_retry_js_1.markAIProviderError)(aiErr);
|
|
98751
98732
|
}
|
|
98752
98733
|
const iterDuration = Date.now() - iterStart;
|
|
@@ -98789,8 +98770,8 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
|
|
|
98789
98770
|
try {
|
|
98790
98771
|
toolArgs = JSON.parse(toolCall.function.arguments);
|
|
98791
98772
|
} catch (parseErr) {
|
|
98792
|
-
const
|
|
98793
|
-
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content:
|
|
98773
|
+
const errMsg3 = `Invalid tool arguments: ${parseErr.message}`;
|
|
98774
|
+
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: errMsg3 });
|
|
98794
98775
|
continue;
|
|
98795
98776
|
}
|
|
98796
98777
|
if (toolName === "finish_generate") {
|
|
@@ -100008,7 +99989,7 @@ var require_util4 = __commonJS({
|
|
|
100008
99989
|
}
|
|
100009
99990
|
path = url.path;
|
|
100010
99991
|
}
|
|
100011
|
-
var
|
|
99992
|
+
var isAbsolute2 = exports2.isAbsolute(path);
|
|
100012
99993
|
var parts = path.split(/\/+/);
|
|
100013
99994
|
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
|
|
100014
99995
|
part = parts[i];
|
|
@@ -100028,7 +100009,7 @@ var require_util4 = __commonJS({
|
|
|
100028
100009
|
}
|
|
100029
100010
|
path = parts.join("/");
|
|
100030
100011
|
if (path === "") {
|
|
100031
|
-
path =
|
|
100012
|
+
path = isAbsolute2 ? "/" : ".";
|
|
100032
100013
|
}
|
|
100033
100014
|
if (url) {
|
|
100034
100015
|
url.path = path;
|
|
@@ -100037,7 +100018,7 @@ var require_util4 = __commonJS({
|
|
|
100037
100018
|
return path;
|
|
100038
100019
|
}
|
|
100039
100020
|
exports2.normalize = normalize;
|
|
100040
|
-
function
|
|
100021
|
+
function join8(aRoot, aPath) {
|
|
100041
100022
|
if (aRoot === "") {
|
|
100042
100023
|
aRoot = ".";
|
|
100043
100024
|
}
|
|
@@ -100069,7 +100050,7 @@ var require_util4 = __commonJS({
|
|
|
100069
100050
|
}
|
|
100070
100051
|
return joined;
|
|
100071
100052
|
}
|
|
100072
|
-
exports2.join =
|
|
100053
|
+
exports2.join = join8;
|
|
100073
100054
|
exports2.isAbsolute = function(aPath) {
|
|
100074
100055
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
100075
100056
|
};
|
|
@@ -100242,7 +100223,7 @@ var require_util4 = __commonJS({
|
|
|
100242
100223
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
100243
100224
|
}
|
|
100244
100225
|
}
|
|
100245
|
-
sourceURL =
|
|
100226
|
+
sourceURL = join8(urlGenerate(parsed), sourceURL);
|
|
100246
100227
|
}
|
|
100247
100228
|
return normalize(sourceURL);
|
|
100248
100229
|
}
|
|
@@ -313954,8 +313935,8 @@ Try a different fix approach. This is NOT your final script-driven attempt yet,
|
|
|
313954
313935
|
...(0, ai_provider_js_1.getJsonObjectResponseFormat)(agentModel)
|
|
313955
313936
|
})), { label: `script-heal-${attempt}` });
|
|
313956
313937
|
} catch (aiErr) {
|
|
313957
|
-
const
|
|
313958
|
-
logs2.push(`\u26A0 AI call failed: ${
|
|
313938
|
+
const errMsg3 = aiErr instanceof Error ? aiErr.message : String(aiErr);
|
|
313939
|
+
logs2.push(`\u26A0 AI call failed: ${errMsg3}`);
|
|
313959
313940
|
attemptHistory.push({
|
|
313960
313941
|
phase: "script",
|
|
313961
313942
|
attempt,
|
|
@@ -313963,13 +313944,13 @@ Try a different fix approach. This is NOT your final script-driven attempt yet,
|
|
|
313963
313944
|
passed: false,
|
|
313964
313945
|
changedCode: false,
|
|
313965
313946
|
summary: "AI call failed before returning a heal result",
|
|
313966
|
-
errorSummary: truncateForPrompt(
|
|
313947
|
+
errorSummary: truncateForPrompt(errMsg3),
|
|
313967
313948
|
failedStep: summarizeFailedStep(currentStepResults)
|
|
313968
313949
|
});
|
|
313969
313950
|
if (feedbackEnabled) {
|
|
313970
|
-
lastTransportFailure = truncateForPrompt(
|
|
313951
|
+
lastTransportFailure = truncateForPrompt(errMsg3, 200) ?? "the AI request failed";
|
|
313971
313952
|
} else {
|
|
313972
|
-
currentError = `AI call failed on attempt ${attempt}: ${
|
|
313953
|
+
currentError = `AI call failed on attempt ${attempt}: ${errMsg3}`;
|
|
313973
313954
|
}
|
|
313974
313955
|
markRecoverableTurn();
|
|
313975
313956
|
continue;
|
|
@@ -314219,8 +314200,8 @@ ${currentError.slice(0, 2e3)}`
|
|
|
314219
314200
|
// item 5b
|
|
314220
314201
|
});
|
|
314221
314202
|
} catch (runErr) {
|
|
314222
|
-
const
|
|
314223
|
-
logs2.push(`\u{1F4A5} Native execution threw: ${
|
|
314203
|
+
const errMsg3 = runErr instanceof Error ? runErr.message : String(runErr);
|
|
314204
|
+
logs2.push(`\u{1F4A5} Native execution threw: ${errMsg3}`);
|
|
314224
314205
|
attemptHistory.push({
|
|
314225
314206
|
phase: "script",
|
|
314226
314207
|
attempt,
|
|
@@ -314228,9 +314209,9 @@ ${currentError.slice(0, 2e3)}`
|
|
|
314228
314209
|
passed: false,
|
|
314229
314210
|
changedCode: true,
|
|
314230
314211
|
summary: truncateForPrompt(changeDesc) ?? "Applied code fix, but native execution threw before verification completed",
|
|
314231
|
-
errorSummary: truncateForPrompt(
|
|
314212
|
+
errorSummary: truncateForPrompt(errMsg3)
|
|
314232
314213
|
});
|
|
314233
|
-
currentError = `Native execution threw: ${
|
|
314214
|
+
currentError = `Native execution threw: ${errMsg3}`;
|
|
314234
314215
|
currentStepResults = [];
|
|
314235
314216
|
continue;
|
|
314236
314217
|
}
|
|
@@ -314986,9 +314967,9 @@ Last error (after heal attempts): ${lastErrorSnippet}` : `Heal aborted: same err
|
|
|
314986
314967
|
previousErrorSignature = errorSig;
|
|
314987
314968
|
}
|
|
314988
314969
|
} catch (runErr) {
|
|
314989
|
-
const
|
|
314990
|
-
logs2.push(`\u{1F4A5} Native run threw: ${
|
|
314991
|
-
currentError =
|
|
314970
|
+
const errMsg3 = runErr instanceof Error ? runErr.message : String(runErr);
|
|
314971
|
+
logs2.push(`\u{1F4A5} Native run threw: ${errMsg3}`);
|
|
314972
|
+
currentError = errMsg3;
|
|
314992
314973
|
currentStepResults = [];
|
|
314993
314974
|
}
|
|
314994
314975
|
} else {
|
|
@@ -315550,8 +315531,8 @@ When you call finish_fix, preserve locators only when they are stable structural
|
|
|
315550
315531
|
}
|
|
315551
315532
|
}
|
|
315552
315533
|
} catch (toolErr) {
|
|
315553
|
-
const
|
|
315554
|
-
let errorContent = `Error: ${
|
|
315534
|
+
const errMsg3 = toolErr instanceof Error ? toolErr.message : String(toolErr);
|
|
315535
|
+
let errorContent = `Error: ${errMsg3}`;
|
|
315555
315536
|
try {
|
|
315556
315537
|
const consoleResult = await mcpClient.callTool({ name: "browser_console_messages", arguments: {} });
|
|
315557
315538
|
const consoleText = Array.isArray(consoleResult.content) ? consoleResult.content.map((c) => c.type === "text" ? c.text ?? "" : "").join("\n") : String(consoleResult.content ?? "");
|
|
@@ -315572,8 +315553,8 @@ ${errorContent}`;
|
|
|
315572
315553
|
}
|
|
315573
315554
|
}
|
|
315574
315555
|
} catch (mcpErr) {
|
|
315575
|
-
const
|
|
315576
|
-
logs2.push(`\u{1F4A5} MCP exploration failed: ${
|
|
315556
|
+
const errMsg3 = mcpErr instanceof Error ? mcpErr.message : String(mcpErr);
|
|
315557
|
+
logs2.push(`\u{1F4A5} MCP exploration failed: ${errMsg3}`);
|
|
315577
315558
|
}
|
|
315578
315559
|
if (verdict === "app_bug") {
|
|
315579
315560
|
phase2AttemptHistory.push({
|
|
@@ -316136,9 +316117,9 @@ ${testBlocks}
|
|
|
316136
316117
|
}
|
|
316137
316118
|
emit(` \u2713 ${toolResultContent.slice(0, 200)}${toolResultContent.length > 200 ? "..." : ""}`);
|
|
316138
316119
|
} catch (err) {
|
|
316139
|
-
const
|
|
316140
|
-
toolResultContent = `ERROR: ${
|
|
316141
|
-
emit(` \u2717 ${
|
|
316120
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
316121
|
+
toolResultContent = `ERROR: ${errMsg3}`;
|
|
316122
|
+
emit(` \u2717 ${errMsg3}`);
|
|
316142
316123
|
}
|
|
316143
316124
|
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
316144
316125
|
}
|
|
@@ -321993,8 +321974,8 @@ var require_capture_page_normalizer = __commonJS({
|
|
|
321993
321974
|
const snapItems = Array.isArray(snapResult.content) ? snapResult.content : [];
|
|
321994
321975
|
snapshotText = extractInlineSnapshotYaml(snapItems.find((c) => c.type === "text")?.text || null);
|
|
321995
321976
|
} catch (err) {
|
|
321996
|
-
const
|
|
321997
|
-
const isTimeout = /timeout|timed out|TimeoutError/i.test(
|
|
321977
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
321978
|
+
const isTimeout = /timeout|timed out|TimeoutError/i.test(errMsg3);
|
|
321998
321979
|
return {
|
|
321999
321980
|
snapshotText: null,
|
|
322000
321981
|
meta: {
|
|
@@ -326016,9 +325997,9 @@ ${currentSummary}`;
|
|
|
326016
325997
|
});
|
|
326017
325998
|
}
|
|
326018
325999
|
} catch (err) {
|
|
326019
|
-
const
|
|
326020
|
-
logs2.push(` Error persisting page: ${
|
|
326021
|
-
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: `ERROR persisting page: ${
|
|
326000
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326001
|
+
logs2.push(` Error persisting page: ${errMsg3}`);
|
|
326002
|
+
toolResults.push({ role: "tool", tool_call_id: toolCall.id, content: `ERROR persisting page: ${errMsg3}` });
|
|
326022
326003
|
}
|
|
326023
326004
|
continue;
|
|
326024
326005
|
}
|
|
@@ -326220,12 +326201,12 @@ ${currentSummary}`;
|
|
|
326220
326201
|
})
|
|
326221
326202
|
});
|
|
326222
326203
|
} catch (err) {
|
|
326223
|
-
const
|
|
326224
|
-
logs2.push(` Error persisting page: ${
|
|
326204
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326205
|
+
logs2.push(` Error persisting page: ${errMsg3}`);
|
|
326225
326206
|
toolResults.push({
|
|
326226
326207
|
role: "tool",
|
|
326227
326208
|
tool_call_id: toolCall.id,
|
|
326228
|
-
content: `ERROR persisting page: ${
|
|
326209
|
+
content: `ERROR persisting page: ${errMsg3}`
|
|
326229
326210
|
});
|
|
326230
326211
|
}
|
|
326231
326212
|
continue;
|
|
@@ -326260,12 +326241,12 @@ ${currentSummary}`;
|
|
|
326260
326241
|
content: JSON.stringify({ acknowledged: true })
|
|
326261
326242
|
});
|
|
326262
326243
|
} catch (err) {
|
|
326263
|
-
const
|
|
326264
|
-
logs2.push(` Error persisting transition: ${
|
|
326244
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326245
|
+
logs2.push(` Error persisting transition: ${errMsg3}`);
|
|
326265
326246
|
toolResults.push({
|
|
326266
326247
|
role: "tool",
|
|
326267
326248
|
tool_call_id: toolCall.id,
|
|
326268
|
-
content: `ERROR persisting transition: ${
|
|
326249
|
+
content: `ERROR persisting transition: ${errMsg3}`
|
|
326269
326250
|
});
|
|
326270
326251
|
}
|
|
326271
326252
|
continue;
|
|
@@ -326920,15 +326901,15 @@ Exploration complete: ${summary}`);
|
|
|
326920
326901
|
toolResultContent = (0, snapshot_context_compactor_js_1.formatMCPToolResult)(toolResultContent, MAX_TOOL_RESULT_CHARS);
|
|
326921
326902
|
logs2.push(` OK: ${toolResultContent.slice(0, 200)}${toolResultContent.length > 200 ? "..." : ""}`);
|
|
326922
326903
|
} catch (err) {
|
|
326923
|
-
const
|
|
326924
|
-
toolResultContent = `ERROR: ${
|
|
326925
|
-
logs2.push(` Error: ${
|
|
326904
|
+
const errMsg3 = err instanceof Error ? err.message : String(err);
|
|
326905
|
+
toolResultContent = `ERROR: ${errMsg3}`;
|
|
326906
|
+
logs2.push(` Error: ${errMsg3}`);
|
|
326926
326907
|
if (useV2) {
|
|
326927
326908
|
(0, exploration_state_js_1.reduceEvent)(state2, {
|
|
326928
326909
|
type: "ACTION_FAILED",
|
|
326929
326910
|
route: state2.currentRoute,
|
|
326930
326911
|
action: `${toolName}(${JSON.stringify(toolArgs).slice(0, 100)})`,
|
|
326931
|
-
error:
|
|
326912
|
+
error: errMsg3
|
|
326932
326913
|
});
|
|
326933
326914
|
}
|
|
326934
326915
|
}
|
|
@@ -329774,10 +329755,10 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
329774
329755
|
onLog: options.onLog,
|
|
329775
329756
|
onProvenCommands: recordProvenCommands
|
|
329776
329757
|
});
|
|
329777
|
-
const
|
|
329758
|
+
const errMsg3 = firstError?.message ?? (grokError instanceof Error ? grokError.message : "unknown error");
|
|
329778
329759
|
const fixPrompt = [
|
|
329779
329760
|
"Your previous attempt did not produce a valid result file.",
|
|
329780
|
-
`Error: ${
|
|
329761
|
+
`Error: ${errMsg3}`,
|
|
329781
329762
|
`Re-read BRIEF.md and write a valid SurveyorOutput JSON to ${resultFilePath}.`,
|
|
329782
329763
|
"Single JSON object. No prose. Then exit."
|
|
329783
329764
|
].join("\n");
|
|
@@ -331918,7 +331899,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
331918
331899
|
log2(`First-pass discovery-result invalid or missing: ${firstError.message}`);
|
|
331919
331900
|
}
|
|
331920
331901
|
if (!parsedResult) {
|
|
331921
|
-
const
|
|
331902
|
+
const errMsg3 = firstError?.message ?? (grokError instanceof Error ? grokError.message : "unknown error");
|
|
331922
331903
|
if (planDebounceTimerRef.current) {
|
|
331923
331904
|
clearTimeout(planDebounceTimerRef.current);
|
|
331924
331905
|
planDebounceTimerRef.current = void 0;
|
|
@@ -331943,7 +331924,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
331943
331924
|
""
|
|
331944
331925
|
].join("\n");
|
|
331945
331926
|
const fixPrompt = [
|
|
331946
|
-
`Your previous attempt did not produce a valid result file. Error: ${
|
|
331927
|
+
`Your previous attempt did not produce a valid result file. Error: ${errMsg3}`,
|
|
331947
331928
|
"Re-read BRIEF.md.",
|
|
331948
331929
|
phaseContext,
|
|
331949
331930
|
`Continue from where you left off \u2014 already verified tests are in ${testsDirPath}/`,
|
|
@@ -333572,10 +333553,10 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
333572
333553
|
onLog: parserLog,
|
|
333573
333554
|
onProvenCommands: recordProvenCommands
|
|
333574
333555
|
});
|
|
333575
|
-
const
|
|
333556
|
+
const errMsg3 = firstError?.message ?? (claudeError instanceof Error ? claudeError.message : "unknown error");
|
|
333576
333557
|
const fixPrompt = [
|
|
333577
333558
|
"Your previous attempt did not leave a valid result file.",
|
|
333578
|
-
`Error: ${
|
|
333559
|
+
`Error: ${errMsg3}`,
|
|
333579
333560
|
`Writing a valid SurveyorOutput JSON object to ${resultFilePath} is your ONLY priority now.`,
|
|
333580
333561
|
"Procedure: navigate to at most 6-8 of the main pages, then IMMEDIATELY use",
|
|
333581
333562
|
`the Write tool to save the SurveyorOutput JSON to ${resultFilePath}. Do this`,
|
|
@@ -339953,8 +339934,8 @@ var require_adm_zip = __commonJS({
|
|
|
339953
339934
|
return null;
|
|
339954
339935
|
}
|
|
339955
339936
|
function fixPath(zipPath) {
|
|
339956
|
-
const { join:
|
|
339957
|
-
return
|
|
339937
|
+
const { join: join8, normalize, sep } = pth.posix;
|
|
339938
|
+
return join8(pth.isAbsolute(zipPath) ? "/" : ".", normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
339958
339939
|
}
|
|
339959
339940
|
function filenameFilter(filterfn) {
|
|
339960
339941
|
if (filterfn instanceof RegExp) {
|
|
@@ -342789,11 +342770,11 @@ var require_winchars = __commonJS({
|
|
|
342789
342770
|
var require_strip_absolute_path = __commonJS({
|
|
342790
342771
|
"../../node_modules/tar/lib/strip-absolute-path.js"(exports2, module2) {
|
|
342791
342772
|
"use strict";
|
|
342792
|
-
var { isAbsolute, parse } = require("path").win32;
|
|
342773
|
+
var { isAbsolute: isAbsolute2, parse } = require("path").win32;
|
|
342793
342774
|
module2.exports = (path) => {
|
|
342794
342775
|
let r = "";
|
|
342795
342776
|
let parsed = parse(path);
|
|
342796
|
-
while (
|
|
342777
|
+
while (isAbsolute2(path) || parsed.root) {
|
|
342797
342778
|
const root = path.charAt(0) === "/" && path.slice(0, 4) !== "//?/" ? "/" : parsed.root;
|
|
342798
342779
|
path = path.slice(root.length);
|
|
342799
342780
|
r += root;
|
|
@@ -345305,7 +345286,7 @@ var require_update = __commonJS({
|
|
|
345305
345286
|
var require_opts_arg = __commonJS({
|
|
345306
345287
|
"../../node_modules/tar/node_modules/mkdirp/lib/opts-arg.js"(exports2, module2) {
|
|
345307
345288
|
"use strict";
|
|
345308
|
-
var { promisify:
|
|
345289
|
+
var { promisify: promisify4 } = require("util");
|
|
345309
345290
|
var fs = require("fs");
|
|
345310
345291
|
var optsArg = (opts) => {
|
|
345311
345292
|
if (!opts)
|
|
@@ -345319,9 +345300,9 @@ var require_opts_arg = __commonJS({
|
|
|
345319
345300
|
else
|
|
345320
345301
|
throw new TypeError("invalid options argument");
|
|
345321
345302
|
opts.mkdir = opts.mkdir || opts.fs.mkdir || fs.mkdir;
|
|
345322
|
-
opts.mkdirAsync =
|
|
345303
|
+
opts.mkdirAsync = promisify4(opts.mkdir);
|
|
345323
345304
|
opts.stat = opts.stat || opts.fs.stat || fs.stat;
|
|
345324
|
-
opts.statAsync =
|
|
345305
|
+
opts.statAsync = promisify4(opts.stat);
|
|
345325
345306
|
opts.statSync = opts.statSync || opts.fs.statSync || fs.statSync;
|
|
345326
345307
|
opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs.mkdirSync;
|
|
345327
345308
|
return opts;
|
|
@@ -345574,10 +345555,10 @@ var require_chownr = __commonJS({
|
|
|
345574
345555
|
}
|
|
345575
345556
|
} : (path2, uid, gid) => lchownSync(path2, uid, gid);
|
|
345576
345557
|
var nodeVersion = process.version;
|
|
345577
|
-
var
|
|
345558
|
+
var readdir3 = (path2, options, cb) => fs.readdir(path2, options, cb);
|
|
345578
345559
|
var readdirSync = (path2, options) => fs.readdirSync(path2, options);
|
|
345579
345560
|
if (/^v4\./.test(nodeVersion))
|
|
345580
|
-
|
|
345561
|
+
readdir3 = (path2, options, cb) => fs.readdir(path2, cb);
|
|
345581
345562
|
var chown = (cpath, uid, gid, cb) => {
|
|
345582
345563
|
fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, (er) => {
|
|
345583
345564
|
cb(er && er.code !== "ENOENT" ? er : null);
|
|
@@ -345604,7 +345585,7 @@ var require_chownr = __commonJS({
|
|
|
345604
345585
|
}
|
|
345605
345586
|
};
|
|
345606
345587
|
var chownr = (p, uid, gid, cb) => {
|
|
345607
|
-
|
|
345588
|
+
readdir3(p, { withFileTypes: true }, (er, children) => {
|
|
345608
345589
|
if (er) {
|
|
345609
345590
|
if (er.code === "ENOENT")
|
|
345610
345591
|
return cb();
|
|
@@ -345878,7 +345859,7 @@ var require_path_reservations = __commonJS({
|
|
|
345878
345859
|
var assert = require("assert");
|
|
345879
345860
|
var normalize = require_normalize_unicode();
|
|
345880
345861
|
var stripSlashes = require_strip_trailing_slashes();
|
|
345881
|
-
var { join:
|
|
345862
|
+
var { join: join8 } = require("path");
|
|
345882
345863
|
var platform3 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
345883
345864
|
var isWindows = platform3 === "win32";
|
|
345884
345865
|
module2.exports = () => {
|
|
@@ -345887,7 +345868,7 @@ var require_path_reservations = __commonJS({
|
|
|
345887
345868
|
const getDirs = (path) => {
|
|
345888
345869
|
const dirs = path.split("/").slice(0, -1).reduce((set, path2) => {
|
|
345889
345870
|
if (set.length) {
|
|
345890
|
-
path2 =
|
|
345871
|
+
path2 = join8(set[set.length - 1], path2);
|
|
345891
345872
|
}
|
|
345892
345873
|
set.push(path2 || "/");
|
|
345893
345874
|
return set;
|
|
@@ -345955,7 +345936,7 @@ var require_path_reservations = __commonJS({
|
|
|
345955
345936
|
};
|
|
345956
345937
|
const reserve = (paths, fn) => {
|
|
345957
345938
|
paths = isWindows ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
345958
|
-
return stripSlashes(
|
|
345939
|
+
return stripSlashes(join8(normalize(p))).toLowerCase();
|
|
345959
345940
|
});
|
|
345960
345941
|
const dirs = new Set(
|
|
345961
345942
|
paths.map((path) => getDirs(path)).reduce((a, b) => a.concat(b))
|
|
@@ -350170,7 +350151,7 @@ var require_process_inventory = __commonJS({
|
|
|
350170
350151
|
var node_child_process_1 = require("child_process");
|
|
350171
350152
|
var node_os_1 = __importDefault(require("os"));
|
|
350172
350153
|
var node_util_1 = require("util");
|
|
350173
|
-
var
|
|
350154
|
+
var execFileAsync4 = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
350174
350155
|
var DEFAULT_LIMIT = 60;
|
|
350175
350156
|
var DEFAULT_TIMEOUT_MS2 = 800;
|
|
350176
350157
|
var MAX_COMMAND_LENGTH = 320;
|
|
@@ -350232,7 +350213,7 @@ var require_process_inventory = __commonJS({
|
|
|
350232
350213
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
350233
350214
|
timer.unref?.();
|
|
350234
350215
|
try {
|
|
350235
|
-
const { stdout } = await
|
|
350216
|
+
const { stdout } = await execFileAsync4(command, args, {
|
|
350236
350217
|
maxBuffer: 1024 * 1024,
|
|
350237
350218
|
signal: controller.signal
|
|
350238
350219
|
});
|
|
@@ -351368,7 +351349,7 @@ var require_package4 = __commonJS({
|
|
|
351368
351349
|
"package.json"(exports2, module2) {
|
|
351369
351350
|
module2.exports = {
|
|
351370
351351
|
name: "@validate.qa/runner",
|
|
351371
|
-
version: "1.0.
|
|
351352
|
+
version: "1.0.69",
|
|
351372
351353
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
351373
351354
|
bin: {
|
|
351374
351355
|
"validate-runner": "dist/cli.js"
|
|
@@ -351455,7 +351436,7 @@ function getConfigDir() {
|
|
|
351455
351436
|
}
|
|
351456
351437
|
|
|
351457
351438
|
// src/runner.ts
|
|
351458
|
-
var
|
|
351439
|
+
var import_path5 = require("path");
|
|
351459
351440
|
var import_os6 = require("os");
|
|
351460
351441
|
var import_node_crypto2 = require("crypto");
|
|
351461
351442
|
|
|
@@ -352050,6 +352031,66 @@ function resetServerState(port = APPIUM_PORT, restartCount = 0) {
|
|
|
352050
352031
|
};
|
|
352051
352032
|
}
|
|
352052
352033
|
|
|
352034
|
+
// src/services/mobile/ios-simulator-reset.ts
|
|
352035
|
+
var import_child_process2 = require("child_process");
|
|
352036
|
+
var import_util = require("util");
|
|
352037
|
+
var import_promises = require("fs/promises");
|
|
352038
|
+
var import_path3 = require("path");
|
|
352039
|
+
var execFileAsync = (0, import_util.promisify)(import_child_process2.execFile);
|
|
352040
|
+
var SIMCTL_TIMEOUT_MS = 15e3;
|
|
352041
|
+
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;
|
|
352042
|
+
function isIosSimulatorUdid(udid) {
|
|
352043
|
+
return typeof udid === "string" && SIMULATOR_UDID_RE.test(udid.trim());
|
|
352044
|
+
}
|
|
352045
|
+
function errMsg(err) {
|
|
352046
|
+
return err instanceof Error ? err.message : String(err);
|
|
352047
|
+
}
|
|
352048
|
+
async function simctl(args) {
|
|
352049
|
+
const { stdout } = await execFileAsync("xcrun", ["simctl", ...args], {
|
|
352050
|
+
timeout: SIMCTL_TIMEOUT_MS,
|
|
352051
|
+
encoding: "utf-8"
|
|
352052
|
+
});
|
|
352053
|
+
return stdout.trim();
|
|
352054
|
+
}
|
|
352055
|
+
async function clearIosSimulatorAppData(udid, bundleId, env = process.env) {
|
|
352056
|
+
if (!isIosSimulatorUdid(udid)) {
|
|
352057
|
+
return { ok: false, detail: `'${udid}' is not a simulator UDID \u2014 physical iOS devices cannot be cleared` };
|
|
352058
|
+
}
|
|
352059
|
+
let container;
|
|
352060
|
+
try {
|
|
352061
|
+
container = await simctl(["get_app_container", udid, bundleId, "data"]);
|
|
352062
|
+
} catch (err) {
|
|
352063
|
+
return { ok: false, detail: `simctl get_app_container failed (app not installed?): ${errMsg(err)}` };
|
|
352064
|
+
}
|
|
352065
|
+
if (!(0, import_path3.isAbsolute)(container) || !container.includes("/Containers/Data/Application/")) {
|
|
352066
|
+
return { ok: false, detail: `unexpected app container path: ${container}` };
|
|
352067
|
+
}
|
|
352068
|
+
try {
|
|
352069
|
+
await simctl(["spawn", udid, "defaults", "delete", bundleId]);
|
|
352070
|
+
} catch {
|
|
352071
|
+
}
|
|
352072
|
+
try {
|
|
352073
|
+
const entries = await (0, import_promises.readdir)(container);
|
|
352074
|
+
for (const entry of entries) {
|
|
352075
|
+
await (0, import_promises.rm)((0, import_path3.join)(container, entry), { recursive: true, force: true });
|
|
352076
|
+
}
|
|
352077
|
+
} catch (err) {
|
|
352078
|
+
return { ok: false, detail: `app container wipe failed: ${errMsg(err)}` };
|
|
352079
|
+
}
|
|
352080
|
+
const keychainPolicy = (env.VALIDATEQA_MOBILE_IOS_KEYCHAIN_RESET ?? "").trim().toLowerCase();
|
|
352081
|
+
if (keychainPolicy !== "never") {
|
|
352082
|
+
try {
|
|
352083
|
+
await simctl(["keychain", udid, "reset"]);
|
|
352084
|
+
} catch (err) {
|
|
352085
|
+
return {
|
|
352086
|
+
ok: false,
|
|
352087
|
+
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.`
|
|
352088
|
+
};
|
|
352089
|
+
}
|
|
352090
|
+
}
|
|
352091
|
+
return { ok: true };
|
|
352092
|
+
}
|
|
352093
|
+
|
|
352053
352094
|
// src/services/mobile/appium-actions.ts
|
|
352054
352095
|
var APPIUM_REQUEST_TIMEOUT_MS = 1e4;
|
|
352055
352096
|
var APPIUM_WEBVIEW_CONTEXT_TIMEOUT_MS = 12e4;
|
|
@@ -352232,9 +352273,12 @@ async function tapAt(sessionPath, bounds) {
|
|
|
352232
352273
|
}
|
|
352233
352274
|
}
|
|
352234
352275
|
function shouldResetMobileAppData(platform3, deviceId, env = process.env) {
|
|
352235
|
-
if (platform3 !== "ANDROID") return false;
|
|
352236
352276
|
const policy = (env.VALIDATEQA_MOBILE_APP_RESET ?? "").trim().toLowerCase();
|
|
352237
352277
|
if (policy === "never") return false;
|
|
352278
|
+
if (platform3 === "IOS") {
|
|
352279
|
+
return isIosSimulatorUdid(deviceId);
|
|
352280
|
+
}
|
|
352281
|
+
if (platform3 !== "ANDROID") return false;
|
|
352238
352282
|
if (policy === "always") return true;
|
|
352239
352283
|
return !!deviceId && deviceId.startsWith("emulator-");
|
|
352240
352284
|
}
|
|
@@ -353121,11 +353165,11 @@ var import_node_path2 = require("path");
|
|
|
353121
353165
|
var import_runner_core8 = __toESM(require_dist2());
|
|
353122
353166
|
|
|
353123
353167
|
// src/services/device-discovery.ts
|
|
353124
|
-
var
|
|
353168
|
+
var import_child_process3 = require("child_process");
|
|
353125
353169
|
var import_os3 = require("os");
|
|
353126
353170
|
function runCommand(command, args, timeout = 1e4) {
|
|
353127
353171
|
try {
|
|
353128
|
-
return (0,
|
|
353172
|
+
return (0, import_child_process3.execFileSync)(command, args, {
|
|
353129
353173
|
encoding: "utf-8",
|
|
353130
353174
|
timeout,
|
|
353131
353175
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -353425,9 +353469,6 @@ function countReadyDevicesByKind(platform3, snapshot = getCachedDeviceSnapshot()
|
|
|
353425
353469
|
function selectFreeDevice(platform3, leased, snapshot = getCachedDeviceSnapshot(), requirements = {}) {
|
|
353426
353470
|
const ready = snapshot.filter((d) => d.platform === platform3 && d.isAvailable && d.state === "BOOTED");
|
|
353427
353471
|
if (ready.length === 0) return { kind: "busy", reason: `no booted ${platform3} device` };
|
|
353428
|
-
if (requirements.resetPolicy === "CLEAR_APP_DATA" && platform3 !== "ANDROID") {
|
|
353429
|
-
return { kind: "unsatisfiable", reason: "CLEAR_APP_DATA is unsupported on iOS" };
|
|
353430
|
-
}
|
|
353431
353472
|
let candidates = requirements.resetPolicy === "CLEAR_APP_DATA" ? ready.filter((d) => !d.isPhysical) : [...ready];
|
|
353432
353473
|
const appId = requirements.appId?.trim();
|
|
353433
353474
|
if (appId) {
|
|
@@ -353477,13 +353518,13 @@ function pickFreeDevice(platform3, leased, snapshot = getCachedDeviceSnapshot(),
|
|
|
353477
353518
|
// src/services/mobile/mobile-network-capture.ts
|
|
353478
353519
|
var import_node_child_process = require("child_process");
|
|
353479
353520
|
var import_node_crypto = require("crypto");
|
|
353480
|
-
var
|
|
353521
|
+
var import_promises2 = require("fs/promises");
|
|
353481
353522
|
var import_node_os = require("os");
|
|
353482
353523
|
var import_node_path = require("path");
|
|
353483
353524
|
var import_node_util = require("util");
|
|
353484
353525
|
var import_mockttp = require("mockttp");
|
|
353485
353526
|
var import_runner_core7 = __toESM(require_dist2());
|
|
353486
|
-
var
|
|
353527
|
+
var execFileAsync2 = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
353487
353528
|
var MAX_CALLS = 1e3;
|
|
353488
353529
|
var MAX_BODY_CAPTURE_BYTES = 64 * 1024;
|
|
353489
353530
|
var DEVICE_CMD_TIMEOUT_MS = 15e3;
|
|
@@ -353671,7 +353712,7 @@ var MitmProxy = class {
|
|
|
353671
353712
|
try {
|
|
353672
353713
|
await server3.stop();
|
|
353673
353714
|
} catch (err) {
|
|
353674
|
-
this.onLog?.(`[mobile-net] proxy stop error (ignored): ${
|
|
353715
|
+
this.onLog?.(`[mobile-net] proxy stop error (ignored): ${errMsg2(err)}`);
|
|
353675
353716
|
}
|
|
353676
353717
|
this.onLog?.(
|
|
353677
353718
|
`[mobile-net] proxy closed: ${this.calls.length} calls captured` + (this.dropped > 0 ? ` (${this.dropped} dropped over cap)` : "")
|
|
@@ -353696,7 +353737,7 @@ var MitmProxy = class {
|
|
|
353696
353737
|
isHttps
|
|
353697
353738
|
});
|
|
353698
353739
|
} catch (err) {
|
|
353699
|
-
this.onLog?.(`[mobile-net] request capture error (ignored): ${
|
|
353740
|
+
this.onLog?.(`[mobile-net] request capture error (ignored): ${errMsg2(err)}`);
|
|
353700
353741
|
}
|
|
353701
353742
|
}
|
|
353702
353743
|
// ── response → finalize the matched request ───────────────────────────────
|
|
@@ -353739,7 +353780,7 @@ var MitmProxy = class {
|
|
|
353739
353780
|
intercepted: true
|
|
353740
353781
|
});
|
|
353741
353782
|
} catch (err) {
|
|
353742
|
-
this.onLog?.(`[mobile-net] response capture error (ignored): ${
|
|
353783
|
+
this.onLog?.(`[mobile-net] response capture error (ignored): ${errMsg2(err)}`);
|
|
353743
353784
|
}
|
|
353744
353785
|
}
|
|
353745
353786
|
// ── tls-client-error → record WHY interception failed ─────────────────────
|
|
@@ -353817,16 +353858,16 @@ async function generateCaCert(dir, onLog) {
|
|
|
353817
353858
|
// rather than on a short expiry.
|
|
353818
353859
|
});
|
|
353819
353860
|
const caCertPath = (0, import_node_path.join)(dir, "validateqa-mobile-ca.pem");
|
|
353820
|
-
await (0,
|
|
353861
|
+
await (0, import_promises2.writeFile)(caCertPath, cert, "utf-8");
|
|
353821
353862
|
return { caCertPath, caKeyPem: key, caCertPem: cert };
|
|
353822
353863
|
} catch (err) {
|
|
353823
|
-
onLog?.(`[mobile-net] CA generation failed; running plaintext-only: ${
|
|
353864
|
+
onLog?.(`[mobile-net] CA generation failed; running plaintext-only: ${errMsg2(err)}`);
|
|
353824
353865
|
return null;
|
|
353825
353866
|
}
|
|
353826
353867
|
}
|
|
353827
353868
|
async function androidReadProxy(deviceId) {
|
|
353828
353869
|
try {
|
|
353829
|
-
const { stdout } = await
|
|
353870
|
+
const { stdout } = await execFileAsync2(
|
|
353830
353871
|
"adb",
|
|
353831
353872
|
["-s", deviceId, "shell", "settings", "get", "global", "http_proxy"],
|
|
353832
353873
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
@@ -353839,33 +353880,33 @@ async function androidReadProxy(deviceId) {
|
|
|
353839
353880
|
}
|
|
353840
353881
|
async function androidSetProxy(deviceId, hostPort, onLog) {
|
|
353841
353882
|
try {
|
|
353842
|
-
await
|
|
353883
|
+
await execFileAsync2(
|
|
353843
353884
|
"adb",
|
|
353844
353885
|
["-s", deviceId, "shell", "settings", "put", "global", "http_proxy", hostPort],
|
|
353845
353886
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353846
353887
|
);
|
|
353847
353888
|
return true;
|
|
353848
353889
|
} catch (err) {
|
|
353849
|
-
onLog?.(`[mobile-net] adb set http_proxy failed: ${
|
|
353890
|
+
onLog?.(`[mobile-net] adb set http_proxy failed: ${errMsg2(err)}`);
|
|
353850
353891
|
return false;
|
|
353851
353892
|
}
|
|
353852
353893
|
}
|
|
353853
353894
|
async function androidClearProxy(deviceId, originalProxy, onLog) {
|
|
353854
353895
|
const restoreValue = originalProxy && originalProxy.length > 0 ? originalProxy : ":0";
|
|
353855
353896
|
try {
|
|
353856
|
-
await
|
|
353897
|
+
await execFileAsync2(
|
|
353857
353898
|
"adb",
|
|
353858
353899
|
["-s", deviceId, "shell", "settings", "put", "global", "http_proxy", restoreValue],
|
|
353859
353900
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353860
353901
|
);
|
|
353861
353902
|
} catch (err) {
|
|
353862
|
-
onLog?.(`[mobile-net] adb restore http_proxy failed: ${
|
|
353903
|
+
onLog?.(`[mobile-net] adb restore http_proxy failed: ${errMsg2(err)}`);
|
|
353863
353904
|
}
|
|
353864
353905
|
}
|
|
353865
353906
|
async function androidInstallCa(deviceId, caCertPath) {
|
|
353866
353907
|
const devicePath = "/sdcard/validateqa-mobile-ca.pem";
|
|
353867
353908
|
try {
|
|
353868
|
-
await
|
|
353909
|
+
await execFileAsync2("adb", ["-s", deviceId, "push", caCertPath, devicePath], {
|
|
353869
353910
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353870
353911
|
});
|
|
353871
353912
|
return {
|
|
@@ -353873,23 +353914,23 @@ async function androidInstallCa(deviceId, caCertPath) {
|
|
|
353873
353914
|
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.`
|
|
353874
353915
|
};
|
|
353875
353916
|
} catch (err) {
|
|
353876
|
-
return { installed: false, note: `CA push failed: ${
|
|
353917
|
+
return { installed: false, note: `CA push failed: ${errMsg2(err)}` };
|
|
353877
353918
|
}
|
|
353878
353919
|
}
|
|
353879
353920
|
async function androidRemoveCa(deviceId, onLog) {
|
|
353880
353921
|
try {
|
|
353881
|
-
await
|
|
353922
|
+
await execFileAsync2(
|
|
353882
353923
|
"adb",
|
|
353883
353924
|
["-s", deviceId, "shell", "rm", "-f", "/sdcard/validateqa-mobile-ca.pem"],
|
|
353884
353925
|
{ timeout: DEVICE_CMD_TIMEOUT_MS }
|
|
353885
353926
|
);
|
|
353886
353927
|
} catch (err) {
|
|
353887
|
-
onLog?.(`[mobile-net] adb remove CA failed: ${
|
|
353928
|
+
onLog?.(`[mobile-net] adb remove CA failed: ${errMsg2(err)}`);
|
|
353888
353929
|
}
|
|
353889
353930
|
}
|
|
353890
353931
|
async function iosSimTrustCa(deviceId, caCertPath) {
|
|
353891
353932
|
try {
|
|
353892
|
-
await
|
|
353933
|
+
await execFileAsync2("xcrun", ["simctl", "keychain", deviceId, "add-root-cert", caCertPath], {
|
|
353893
353934
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353894
353935
|
});
|
|
353895
353936
|
return {
|
|
@@ -353897,18 +353938,18 @@ async function iosSimTrustCa(deviceId, caCertPath) {
|
|
|
353897
353938
|
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."
|
|
353898
353939
|
};
|
|
353899
353940
|
} catch (err) {
|
|
353900
|
-
return { trusted: false, note: `simctl add-root-cert failed: ${
|
|
353941
|
+
return { trusted: false, note: `simctl add-root-cert failed: ${errMsg2(err)}` };
|
|
353901
353942
|
}
|
|
353902
353943
|
}
|
|
353903
353944
|
async function iosSimRemoveCa(deviceId, onLog) {
|
|
353904
353945
|
if (process.env.VALIDATEQA_MOBILE_SIM_KEYCHAIN_RESET === "1") {
|
|
353905
353946
|
try {
|
|
353906
|
-
await
|
|
353947
|
+
await execFileAsync2("xcrun", ["simctl", "keychain", deviceId, "reset"], {
|
|
353907
353948
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
353908
353949
|
});
|
|
353909
353950
|
onLog?.(`[mobile-net] simctl keychain reset run for ${deviceId} (opt-in; cleared ALL sim certs).`);
|
|
353910
353951
|
} catch (err) {
|
|
353911
|
-
onLog?.(`[mobile-net] simctl keychain reset failed: ${
|
|
353952
|
+
onLog?.(`[mobile-net] simctl keychain reset failed: ${errMsg2(err)}`);
|
|
353912
353953
|
}
|
|
353913
353954
|
return;
|
|
353914
353955
|
}
|
|
@@ -353916,7 +353957,7 @@ async function iosSimRemoveCa(deviceId, onLog) {
|
|
|
353916
353957
|
`[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.`
|
|
353917
353958
|
);
|
|
353918
353959
|
}
|
|
353919
|
-
function
|
|
353960
|
+
function errMsg2(err) {
|
|
353920
353961
|
return err instanceof Error ? err.message : String(err);
|
|
353921
353962
|
}
|
|
353922
353963
|
function isProcessAlive(pid) {
|
|
@@ -354007,7 +354048,7 @@ async function iosSimConfigureHostProxy(host, port, onLog) {
|
|
|
354007
354048
|
let service;
|
|
354008
354049
|
let prior;
|
|
354009
354050
|
try {
|
|
354010
|
-
const { stdout: order } = await
|
|
354051
|
+
const { stdout: order } = await execFileAsync2("networksetup", ["-listnetworkserviceorder"], {
|
|
354011
354052
|
timeout: DEVICE_CMD_TIMEOUT_MS
|
|
354012
354053
|
});
|
|
354013
354054
|
const svc = parsePrimaryNetworkService(order);
|
|
@@ -354016,26 +354057,26 @@ async function iosSimConfigureHostProxy(host, port, onLog) {
|
|
|
354016
354057
|
}
|
|
354017
354058
|
service = svc;
|
|
354018
354059
|
const [{ stdout: webOut }, { stdout: secureOut }] = await Promise.all([
|
|
354019
|
-
|
|
354020
|
-
|
|
354060
|
+
execFileAsync2("networksetup", ["-getwebproxy", service], { timeout: DEVICE_CMD_TIMEOUT_MS }),
|
|
354061
|
+
execFileAsync2("networksetup", ["-getsecurewebproxy", service], { timeout: DEVICE_CMD_TIMEOUT_MS })
|
|
354021
354062
|
]);
|
|
354022
354063
|
prior = { web: parseWebProxyState(webOut), secure: parseWebProxyState(secureOut) };
|
|
354023
354064
|
for (const args of buildHostProxySetCommands(service, host, port)) {
|
|
354024
|
-
await
|
|
354065
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354025
354066
|
}
|
|
354026
354067
|
onLog?.(`[mobile-net] macOS host proxy set on "${service}" \u2192 ${host}:${port} (iOS simulator shares the host network).`);
|
|
354027
354068
|
return { configured: true, service, prior };
|
|
354028
354069
|
} catch (err) {
|
|
354029
354070
|
if (service && prior) {
|
|
354030
|
-
onLog?.(`[mobile-net] host proxy set failed mid-way \u2014 rolling back "${service}" to prior state: ${
|
|
354071
|
+
onLog?.(`[mobile-net] host proxy set failed mid-way \u2014 rolling back "${service}" to prior state: ${errMsg2(err)}`);
|
|
354031
354072
|
for (const args of buildHostProxyRestoreCommands(service, prior)) {
|
|
354032
354073
|
try {
|
|
354033
|
-
await
|
|
354074
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354034
354075
|
} catch {
|
|
354035
354076
|
}
|
|
354036
354077
|
}
|
|
354037
354078
|
}
|
|
354038
|
-
return { configured: false, reason: `iOS simulator host proxy could not be configured: ${
|
|
354079
|
+
return { configured: false, reason: `iOS simulator host proxy could not be configured: ${errMsg2(err)}` };
|
|
354039
354080
|
}
|
|
354040
354081
|
}
|
|
354041
354082
|
async function iosSimRestoreHostProxy(service, prior, onLog) {
|
|
@@ -354045,9 +354086,9 @@ async function iosSimRestoreHostProxy(service, prior, onLog) {
|
|
|
354045
354086
|
};
|
|
354046
354087
|
for (const args of buildHostProxyRestoreCommands(service, restore)) {
|
|
354047
354088
|
try {
|
|
354048
|
-
await
|
|
354089
|
+
await execFileAsync2("networksetup", args, { timeout: DEVICE_CMD_TIMEOUT_MS });
|
|
354049
354090
|
} catch (err) {
|
|
354050
|
-
onLog?.(`[mobile-net] networksetup restore (${args[0]}) failed: ${
|
|
354091
|
+
onLog?.(`[mobile-net] networksetup restore (${args[0]}) failed: ${errMsg2(err)}`);
|
|
354051
354092
|
}
|
|
354052
354093
|
}
|
|
354053
354094
|
onLog?.(`[mobile-net] macOS host proxy restored on "${service}".`);
|
|
@@ -354059,14 +354100,14 @@ function markerPath(sessionKey) {
|
|
|
354059
354100
|
}
|
|
354060
354101
|
async function writePendingCleanup(sessionKey, marker) {
|
|
354061
354102
|
try {
|
|
354062
|
-
await (0,
|
|
354063
|
-
await (0,
|
|
354103
|
+
await (0, import_promises2.mkdir)(PENDING_CLEANUP_DIR, { recursive: true });
|
|
354104
|
+
await (0, import_promises2.writeFile)(markerPath(sessionKey), JSON.stringify(marker), "utf-8");
|
|
354064
354105
|
} catch {
|
|
354065
354106
|
}
|
|
354066
354107
|
}
|
|
354067
354108
|
async function removePendingCleanup(sessionKey) {
|
|
354068
354109
|
try {
|
|
354069
|
-
await (0,
|
|
354110
|
+
await (0, import_promises2.unlink)(markerPath(sessionKey));
|
|
354070
354111
|
} catch {
|
|
354071
354112
|
}
|
|
354072
354113
|
}
|
|
@@ -354099,7 +354140,7 @@ function restoreDeviceSync(marker, onLog) {
|
|
|
354099
354140
|
async function reconcilePendingCleanups(onLog) {
|
|
354100
354141
|
let files;
|
|
354101
354142
|
try {
|
|
354102
|
-
files = await (0,
|
|
354143
|
+
files = await (0, import_promises2.readdir)(PENDING_CLEANUP_DIR);
|
|
354103
354144
|
} catch {
|
|
354104
354145
|
return;
|
|
354105
354146
|
}
|
|
@@ -354109,7 +354150,7 @@ async function reconcilePendingCleanups(onLog) {
|
|
|
354109
354150
|
if (activeCleanups.has(sessionKey)) continue;
|
|
354110
354151
|
const full = (0, import_node_path.join)(PENDING_CLEANUP_DIR, file);
|
|
354111
354152
|
try {
|
|
354112
|
-
const raw = await (0,
|
|
354153
|
+
const raw = await (0, import_promises2.readFile)(full, "utf-8");
|
|
354113
354154
|
const marker = JSON.parse(raw);
|
|
354114
354155
|
if (marker && typeof marker.deviceId === "string" && marker.platform) {
|
|
354115
354156
|
if (!shouldReconcilePendingCleanup(marker)) {
|
|
@@ -354122,7 +354163,7 @@ async function reconcilePendingCleanups(onLog) {
|
|
|
354122
354163
|
} catch {
|
|
354123
354164
|
}
|
|
354124
354165
|
try {
|
|
354125
|
-
await (0,
|
|
354166
|
+
await (0, import_promises2.unlink)(full);
|
|
354126
354167
|
} catch {
|
|
354127
354168
|
}
|
|
354128
354169
|
}
|
|
@@ -354160,7 +354201,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354160
354201
|
let caKeyPem = null;
|
|
354161
354202
|
let caCertPem = null;
|
|
354162
354203
|
try {
|
|
354163
|
-
tmpDir = await (0,
|
|
354204
|
+
tmpDir = await (0, import_promises2.mkdtemp)((0, import_node_path.join)((0, import_node_os.tmpdir)(), "validateqa-mobile-ca-"));
|
|
354164
354205
|
const ca = await generateCaCert(tmpDir, onLog);
|
|
354165
354206
|
if (ca) {
|
|
354166
354207
|
caCertPath = ca.caCertPath;
|
|
@@ -354168,7 +354209,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354168
354209
|
caCertPem = ca.caCertPem;
|
|
354169
354210
|
}
|
|
354170
354211
|
} catch (err) {
|
|
354171
|
-
onLog?.(`[mobile-net] CA setup degraded: ${
|
|
354212
|
+
onLog?.(`[mobile-net] CA setup degraded: ${errMsg2(err)}`);
|
|
354172
354213
|
}
|
|
354173
354214
|
if (!caKeyPem || !caCertPem) {
|
|
354174
354215
|
try {
|
|
@@ -354176,9 +354217,9 @@ async function startMobileNetworkCapture(options) {
|
|
|
354176
354217
|
caKeyPem = fallback.key;
|
|
354177
354218
|
caCertPem = fallback.cert;
|
|
354178
354219
|
} catch (err) {
|
|
354179
|
-
onLog?.(`[mobile-net] fatal CA failure, cannot start proxy: ${
|
|
354220
|
+
onLog?.(`[mobile-net] fatal CA failure, cannot start proxy: ${errMsg2(err)}`);
|
|
354180
354221
|
if (tmpDir) {
|
|
354181
|
-
await (0,
|
|
354222
|
+
await (0, import_promises2.rm)(tmpDir, { recursive: true, force: true }).catch(() => void 0);
|
|
354182
354223
|
}
|
|
354183
354224
|
throw err instanceof Error ? err : new Error(String(err));
|
|
354184
354225
|
}
|
|
@@ -354233,7 +354274,7 @@ async function startMobileNetworkCapture(options) {
|
|
|
354233
354274
|
}
|
|
354234
354275
|
}
|
|
354235
354276
|
} catch (err) {
|
|
354236
|
-
wiringReason = `device wiring degraded: ${
|
|
354277
|
+
wiringReason = `device wiring degraded: ${errMsg2(err)}`;
|
|
354237
354278
|
onLog?.(`[mobile-net] ${wiringReason}`);
|
|
354238
354279
|
}
|
|
354239
354280
|
if (proxySet || caInstalledOnDevice || hostProxySet) {
|
|
@@ -354322,9 +354363,9 @@ async function startMobileNetworkCapture(options) {
|
|
|
354322
354363
|
await proxy.close();
|
|
354323
354364
|
if (capturedTmpDir) {
|
|
354324
354365
|
try {
|
|
354325
|
-
await (0,
|
|
354366
|
+
await (0, import_promises2.rm)(capturedTmpDir, { recursive: true, force: true });
|
|
354326
354367
|
} catch (err) {
|
|
354327
|
-
onLog?.(`[mobile-net] temp CA cleanup failed: ${
|
|
354368
|
+
onLog?.(`[mobile-net] temp CA cleanup failed: ${errMsg2(err)}`);
|
|
354328
354369
|
}
|
|
354329
354370
|
}
|
|
354330
354371
|
const apiCount = finalCalls.filter((c) => c.isApi).length;
|
|
@@ -354361,7 +354402,7 @@ var WD_SESSION_CREATE_TIMEOUT_MS = 12e4;
|
|
|
354361
354402
|
var WD_ACTION_TIMEOUT_MS = 3e4;
|
|
354362
354403
|
var APPIUM_DRIVER_DEAD_RE2 = /instrumentation process is not running|cannot be proxied to UiAutomator2 server|socket hang up|ECONNRESET/i;
|
|
354363
354404
|
var MAX_SESSION_CREATE_ATTEMPTS = 3;
|
|
354364
|
-
var
|
|
354405
|
+
var execFileAsync3 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
354365
354406
|
var MOBILE_TEXT_ATTRIBUTE_NAMES = ["text", "content-desc", "contentDescription", "name", "label", "value"];
|
|
354366
354407
|
var WebDriverTransportError = class extends Error {
|
|
354367
354408
|
isTransport = true;
|
|
@@ -354578,7 +354619,7 @@ async function removeStaleAndroidSystemPortForward(target, error2) {
|
|
|
354578
354619
|
const args = androidSystemPortForwardRemovalArgs(target, error2);
|
|
354579
354620
|
if (!args) return false;
|
|
354580
354621
|
try {
|
|
354581
|
-
await
|
|
354622
|
+
await execFileAsync3("adb", args, { timeout: 1e4, windowsHide: true });
|
|
354582
354623
|
return true;
|
|
354583
354624
|
} catch {
|
|
354584
354625
|
return false;
|
|
@@ -355052,7 +355093,7 @@ async function prepareAndroidInputEnvironment(deviceId) {
|
|
|
355052
355093
|
];
|
|
355053
355094
|
for (const [namespace, key, value] of settingsToDisable) {
|
|
355054
355095
|
try {
|
|
355055
|
-
await
|
|
355096
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "settings", "put", namespace, key, value], {
|
|
355056
355097
|
timeout: 8e3,
|
|
355057
355098
|
windowsHide: true
|
|
355058
355099
|
});
|
|
@@ -355064,14 +355105,14 @@ async function sendAndroidTextToFocusedInput(deviceId, value) {
|
|
|
355064
355105
|
if (!deviceId) {
|
|
355065
355106
|
throw new Error("Android keyboard fallback requires a device id");
|
|
355066
355107
|
}
|
|
355067
|
-
await
|
|
355108
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "input", "text", encodeAndroidInputText(value)], {
|
|
355068
355109
|
timeout: 1e4,
|
|
355069
355110
|
windowsHide: true
|
|
355070
355111
|
});
|
|
355071
355112
|
}
|
|
355072
355113
|
async function pressAndroidKeyboardEnter(deviceId) {
|
|
355073
355114
|
if (!deviceId) throw new Error("Android keyboard Enter fallback requires a device id");
|
|
355074
|
-
await
|
|
355115
|
+
await execFileAsync3("adb", ["-s", deviceId, "shell", "input", "keyevent", "66"], {
|
|
355075
355116
|
timeout: 1e4,
|
|
355076
355117
|
windowsHide: true
|
|
355077
355118
|
});
|
|
@@ -355592,7 +355633,14 @@ async function executeMobileTest(options) {
|
|
|
355592
355633
|
const resetAllowed = shouldResetMobileAppData(options.target.platform, selectedDevice.id);
|
|
355593
355634
|
if (resetAllowed) {
|
|
355594
355635
|
try {
|
|
355595
|
-
|
|
355636
|
+
if (options.target.platform === "IOS") {
|
|
355637
|
+
await terminateTargetApp(sessionId, "IOS", options.target.appId).catch(() => {
|
|
355638
|
+
});
|
|
355639
|
+
const wiped = await clearIosSimulatorAppData(selectedDevice.id, options.target.appId);
|
|
355640
|
+
if (!wiped.ok) throw new Error(wiped.detail);
|
|
355641
|
+
} else {
|
|
355642
|
+
await executeMobileScript(sessionId, "mobile: clearApp", [{ appId: options.target.appId }]);
|
|
355643
|
+
}
|
|
355596
355644
|
clearedAppDataBeforeLaunch = true;
|
|
355597
355645
|
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).");
|
|
355598
355646
|
} catch (err) {
|
|
@@ -356250,10 +356298,10 @@ function decideMobileDeviceGate(input) {
|
|
|
356250
356298
|
|
|
356251
356299
|
// src/services/mobile-bridge.ts
|
|
356252
356300
|
var import_http = require("http");
|
|
356253
|
-
var
|
|
356301
|
+
var import_child_process4 = require("child_process");
|
|
356254
356302
|
var import_crypto = require("crypto");
|
|
356255
356303
|
var import_os4 = require("os");
|
|
356256
|
-
var
|
|
356304
|
+
var import_path4 = require("path");
|
|
356257
356305
|
var import_fs3 = require("fs");
|
|
356258
356306
|
init_dist();
|
|
356259
356307
|
var MOBILE_BRIDGE_PORT2 = 9515;
|
|
@@ -356360,7 +356408,7 @@ async function getWindowSize3() {
|
|
|
356360
356408
|
}
|
|
356361
356409
|
var BRIDGE_PROCESS_MARKER = "validateqa-mobile-bridge";
|
|
356362
356410
|
var BRIDGE_PORT = MOBILE_BRIDGE_PORT2;
|
|
356363
|
-
var BRIDGE_PID_FILE = (0,
|
|
356411
|
+
var BRIDGE_PID_FILE = (0, import_path4.join)((0, import_os4.homedir)(), ".validate.qa", "mobile-bridge.pid");
|
|
356364
356412
|
function readBridgePidFile() {
|
|
356365
356413
|
try {
|
|
356366
356414
|
const raw = (0, import_fs3.readFileSync)(BRIDGE_PID_FILE, "utf-8").trim();
|
|
@@ -356372,7 +356420,7 @@ function readBridgePidFile() {
|
|
|
356372
356420
|
}
|
|
356373
356421
|
function writeBridgePidFile(pid) {
|
|
356374
356422
|
try {
|
|
356375
|
-
(0, import_fs3.mkdirSync)((0,
|
|
356423
|
+
(0, import_fs3.mkdirSync)((0, import_path4.dirname)(BRIDGE_PID_FILE), { recursive: true, mode: 448 });
|
|
356376
356424
|
(0, import_fs3.writeFileSync)(BRIDGE_PID_FILE, String(pid), { mode: 384 });
|
|
356377
356425
|
} catch {
|
|
356378
356426
|
}
|
|
@@ -356387,19 +356435,19 @@ function killStaleBridge() {
|
|
|
356387
356435
|
const pid = readBridgePidFile();
|
|
356388
356436
|
if (!pid) return;
|
|
356389
356437
|
try {
|
|
356390
|
-
(0,
|
|
356438
|
+
(0, import_child_process4.execFileSync)("kill", ["-0", String(pid)], { stdio: "ignore" });
|
|
356391
356439
|
} catch {
|
|
356392
356440
|
clearBridgePidFile();
|
|
356393
356441
|
return;
|
|
356394
356442
|
}
|
|
356395
356443
|
try {
|
|
356396
|
-
const pidsOnPort = (0,
|
|
356444
|
+
const pidsOnPort = (0, import_child_process4.execFileSync)("lsof", ["-ti", `:${BRIDGE_PORT}`], { encoding: "utf-8" }).trim();
|
|
356397
356445
|
const pidList = pidsOnPort.split("\n").filter(Boolean);
|
|
356398
356446
|
if (!pidList.includes(String(pid))) {
|
|
356399
356447
|
return;
|
|
356400
356448
|
}
|
|
356401
|
-
(0,
|
|
356402
|
-
(0,
|
|
356449
|
+
(0, import_child_process4.execFileSync)("kill", ["-9", String(pid)], { stdio: "ignore" });
|
|
356450
|
+
(0, import_child_process4.execFileSync)("sleep", ["1"], { stdio: "ignore" });
|
|
356403
356451
|
} catch {
|
|
356404
356452
|
} finally {
|
|
356405
356453
|
clearBridgePidFile();
|
|
@@ -357498,6 +357546,7 @@ var MobileBridgeDriver = class {
|
|
|
357498
357546
|
sessionId;
|
|
357499
357547
|
platform;
|
|
357500
357548
|
appId;
|
|
357549
|
+
deviceId;
|
|
357501
357550
|
allowAppReset;
|
|
357502
357551
|
recoverSession;
|
|
357503
357552
|
maxSessionRecoveries;
|
|
@@ -357518,6 +357567,7 @@ var MobileBridgeDriver = class {
|
|
|
357518
357567
|
this.sessionId = config.sessionId;
|
|
357519
357568
|
this.platform = config.platform;
|
|
357520
357569
|
this.appId = config.appId;
|
|
357570
|
+
this.deviceId = config.deviceId;
|
|
357521
357571
|
this.allowAppReset = config.allowAppReset === true;
|
|
357522
357572
|
this.recoverSession = config.recoverSession;
|
|
357523
357573
|
this.maxSessionRecoveries = Math.max(0, Math.floor(config.maxSessionRecoveries ?? 1));
|
|
@@ -357815,17 +357865,34 @@ var MobileBridgeDriver = class {
|
|
|
357815
357865
|
});
|
|
357816
357866
|
}
|
|
357817
357867
|
/**
|
|
357818
|
-
* Deterministic state reset: clear app data + relaunch
|
|
357819
|
-
*
|
|
357820
|
-
*
|
|
357821
|
-
*
|
|
357822
|
-
*
|
|
357868
|
+
* Deterministic state reset: clear app data + relaunch, per the
|
|
357869
|
+
* runner-computed allowAppReset policy (Android emulators / iOS simulators
|
|
357870
|
+
* only — a personal physical device is never wiped). Android clears via
|
|
357871
|
+
* `mobile: clearApp`; iOS terminates the app and wipes its simulator data
|
|
357872
|
+
* container + keychain through `simctl` (see ios-simulator-reset.ts).
|
|
357873
|
+
* Returns false when unsupported/disallowed or when the clear fails —
|
|
357874
|
+
* callers fall back to relaunch(), preserving today's behavior. On success,
|
|
357875
|
+
* waits for cold-boot content so recording and replay agree on the true
|
|
357876
|
+
* entry screen.
|
|
357823
357877
|
*/
|
|
357824
357878
|
async resetAppState() {
|
|
357825
|
-
if (!this.allowAppReset
|
|
357879
|
+
if (!this.allowAppReset) return false;
|
|
357880
|
+
if (this.platform === "IOS" && !isIosSimulatorUdid(this.deviceId)) return false;
|
|
357826
357881
|
return this.withSessionRecovery("app data reset", async () => {
|
|
357827
357882
|
try {
|
|
357828
|
-
|
|
357883
|
+
if (this.platform === "IOS") {
|
|
357884
|
+
try {
|
|
357885
|
+
await this.executeScript("mobile: terminateApp", [{ ...this.appLifecycleArgs(), timeout: 5e3 }]);
|
|
357886
|
+
} catch (err) {
|
|
357887
|
+
if (isRecoverableAppiumSessionFailure(err)) throw err;
|
|
357888
|
+
}
|
|
357889
|
+
const wiped = await clearIosSimulatorAppData(this.deviceId ?? "", this.appId);
|
|
357890
|
+
if (!wiped.ok) {
|
|
357891
|
+
throw new Error(`iOS simulator app-data reset failed: ${wiped.detail}`);
|
|
357892
|
+
}
|
|
357893
|
+
} else {
|
|
357894
|
+
await this.executeScript("mobile: clearApp", [{ appId: this.appId }]);
|
|
357895
|
+
}
|
|
357829
357896
|
await this.executeScript("mobile: activateApp", [this.appLifecycleArgs()]);
|
|
357830
357897
|
try {
|
|
357831
357898
|
await waitForColdBootSettle(this.sessionPath);
|
|
@@ -357964,7 +358031,7 @@ function readActiveBundleId2(result) {
|
|
|
357964
358031
|
}
|
|
357965
358032
|
|
|
357966
358033
|
// src/services/doctor.ts
|
|
357967
|
-
var
|
|
358034
|
+
var import_child_process5 = require("child_process");
|
|
357968
358035
|
var import_fs4 = require("fs");
|
|
357969
358036
|
var import_os5 = require("os");
|
|
357970
358037
|
var C = {
|
|
@@ -357984,7 +358051,7 @@ function computeDoctorReadiness(web, ios, android) {
|
|
|
357984
358051
|
}
|
|
357985
358052
|
function run(cmd) {
|
|
357986
358053
|
try {
|
|
357987
|
-
return (0,
|
|
358054
|
+
return (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
357988
358055
|
} catch {
|
|
357989
358056
|
return null;
|
|
357990
358057
|
}
|
|
@@ -358491,7 +358558,7 @@ var log = {
|
|
|
358491
358558
|
dim: (msg) => console.log(`${C2.gray}${msg}${C2.reset}`)
|
|
358492
358559
|
};
|
|
358493
358560
|
function getRunsDir() {
|
|
358494
|
-
const dir = process.env.RUNS_DIR || (0,
|
|
358561
|
+
const dir = process.env.RUNS_DIR || (0, import_path5.join)((0, import_os6.homedir)(), ".validate.qa", "runs");
|
|
358495
358562
|
(0, import_runner_core12.ensurePrivateDirectory)(dir);
|
|
358496
358563
|
return dir;
|
|
358497
358564
|
}
|
|
@@ -360423,9 +360490,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
360423
360490
|
sessionId: session.sessionId,
|
|
360424
360491
|
platform: platform3,
|
|
360425
360492
|
appId: session.appId,
|
|
360426
|
-
|
|
360427
|
-
//
|
|
360428
|
-
//
|
|
360493
|
+
deviceId: session.deviceId,
|
|
360494
|
+
// Deterministic-state authorization: Android emulators / iOS
|
|
360495
|
+
// simulators only (VALIDATEQA_MOBILE_APP_RESET overrides the
|
|
360496
|
+
// Android default) — a personal physical device must never have
|
|
360497
|
+
// its app data wiped.
|
|
360429
360498
|
allowAppReset: mobileTarget.resetPolicy !== "PRESERVE_APP_DATA" && shouldResetMobileAppData(platform3, session.deviceId),
|
|
360430
360499
|
maxSessionRecoveries: 1,
|
|
360431
360500
|
recoverSession: async (cause) => {
|
|
@@ -360941,6 +361010,7 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
360941
361010
|
sessionId: opened.sessionId,
|
|
360942
361011
|
platform: target.platform,
|
|
360943
361012
|
appId: opened.appId,
|
|
361013
|
+
deviceId: opened.deviceId,
|
|
360944
361014
|
allowAppReset: target.resetPolicy !== "PRESERVE_APP_DATA" && shouldResetMobileAppData(target.platform, opened.deviceId)
|
|
360945
361015
|
});
|
|
360946
361016
|
};
|