@vostride/agent-qa-core 0.1.9 → 0.1.11
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/index.cjs +182 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +135 -103
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -93,14 +93,14 @@ function toObservationFrontmatter(data) {
|
|
|
93
93
|
}
|
|
94
94
|
async function ensureMemoryDirs(root) {
|
|
95
95
|
await Promise.all(
|
|
96
|
-
MEMORY_TIERS.map((tier) => (0, import_promises8.mkdir)((0,
|
|
96
|
+
MEMORY_TIERS.map((tier) => (0, import_promises8.mkdir)((0, import_node_path12.join)(root, tier), { recursive: true }))
|
|
97
97
|
);
|
|
98
98
|
}
|
|
99
99
|
async function writeObservation(root, tier, scope, data) {
|
|
100
|
-
const dir = (0,
|
|
101
|
-
const resolved = (0,
|
|
102
|
-
const boundary = (0,
|
|
103
|
-
if (!resolved.startsWith(boundary +
|
|
100
|
+
const dir = (0, import_node_path12.join)(root, tier, scope);
|
|
101
|
+
const resolved = (0, import_node_path12.resolve)(dir);
|
|
102
|
+
const boundary = (0, import_node_path12.resolve)(root);
|
|
103
|
+
if (!resolved.startsWith(boundary + import_node_path12.sep)) {
|
|
104
104
|
throw new Error(`Scope "${scope}" escapes memory root`);
|
|
105
105
|
}
|
|
106
106
|
const schema = "position" in data ? SuiteObservationWriteSchema : BaseObservationWriteSchema;
|
|
@@ -111,7 +111,7 @@ async function writeObservation(root, tier, scope, data) {
|
|
|
111
111
|
${(0, import_yaml3.stringify)({ ...frontmatter }, { lineWidth: 0 })}---
|
|
112
112
|
${validated.content}
|
|
113
113
|
`;
|
|
114
|
-
const filePath = (0,
|
|
114
|
+
const filePath = (0, import_node_path12.join)(dir, `${data.id}.md`);
|
|
115
115
|
await (0, import_promises8.writeFile)(filePath, content, "utf-8");
|
|
116
116
|
return filePath;
|
|
117
117
|
}
|
|
@@ -158,13 +158,13 @@ async function listObservations(dir) {
|
|
|
158
158
|
}
|
|
159
159
|
return entries.filter((f) => f.startsWith("obs_") && f.endsWith(".md")).sort();
|
|
160
160
|
}
|
|
161
|
-
var import_yaml3, import_promises8,
|
|
161
|
+
var import_yaml3, import_promises8, import_node_path12, MEMORY_TIERS;
|
|
162
162
|
var init_observation_io = __esm({
|
|
163
163
|
"src/memory/observation-io.ts"() {
|
|
164
164
|
"use strict";
|
|
165
165
|
import_yaml3 = require("yaml");
|
|
166
166
|
import_promises8 = require("fs/promises");
|
|
167
|
-
|
|
167
|
+
import_node_path12 = require("path");
|
|
168
168
|
init_schema();
|
|
169
169
|
MEMORY_TIERS = ["products", "suites", "tests"];
|
|
170
170
|
}
|
|
@@ -238,14 +238,14 @@ function isBetterSqlite3NodeGypSymlinkConflict(error) {
|
|
|
238
238
|
return message.includes("node_gyp_bins/python3") && message.includes("EEXIST");
|
|
239
239
|
}
|
|
240
240
|
function resolveCurrentRuntimeNpmCliPath() {
|
|
241
|
-
const nodeInstallRoot = (0,
|
|
242
|
-
const npmCliPath = (0,
|
|
243
|
-
return (0,
|
|
241
|
+
const nodeInstallRoot = (0, import_node_path19.dirname)((0, import_node_path19.dirname)(process.execPath));
|
|
242
|
+
const npmCliPath = (0, import_node_path19.join)(nodeInstallRoot, "lib", "node_modules", "npm", "bin", "npm-cli.js");
|
|
243
|
+
return (0, import_node_fs7.existsSync)(npmCliPath) ? npmCliPath : null;
|
|
244
244
|
}
|
|
245
245
|
function resolveCurrentRuntimeNodeDir() {
|
|
246
|
-
const nodeInstallRoot = (0,
|
|
247
|
-
const nodeHeaderPath = (0,
|
|
248
|
-
return (0,
|
|
246
|
+
const nodeInstallRoot = (0, import_node_path19.dirname)((0, import_node_path19.dirname)(process.execPath));
|
|
247
|
+
const nodeHeaderPath = (0, import_node_path19.join)(nodeInstallRoot, "include", "node", "node.h");
|
|
248
|
+
return (0, import_node_fs7.existsSync)(nodeHeaderPath) ? nodeInstallRoot : null;
|
|
249
249
|
}
|
|
250
250
|
function resolveBetterSqliteRebuildCommand() {
|
|
251
251
|
const npmCliPath = resolveCurrentRuntimeNpmCliPath();
|
|
@@ -266,31 +266,31 @@ function sleepSync(milliseconds) {
|
|
|
266
266
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
267
267
|
}
|
|
268
268
|
function waitForBetterSqlite3BuildOutput(installRoot, timeoutMs = 3e4) {
|
|
269
|
-
const bindingPath = (0,
|
|
269
|
+
const bindingPath = (0, import_node_path19.join)(installRoot, "build", "Release", "better_sqlite3.node");
|
|
270
270
|
const deadline = Date.now() + timeoutMs;
|
|
271
271
|
while (Date.now() < deadline) {
|
|
272
|
-
if ((0,
|
|
272
|
+
if ((0, import_node_fs7.existsSync)(bindingPath)) {
|
|
273
273
|
return true;
|
|
274
274
|
}
|
|
275
275
|
sleepSync(200);
|
|
276
276
|
}
|
|
277
|
-
return (0,
|
|
277
|
+
return (0, import_node_fs7.existsSync)(bindingPath);
|
|
278
278
|
}
|
|
279
279
|
function acquireBetterSqlite3RebuildLock(installRoot) {
|
|
280
|
-
const lockRoot = (0,
|
|
280
|
+
const lockRoot = (0, import_node_path19.join)((0, import_node_os3.tmpdir)(), "agent-qa-better-sqlite3-rebuild-locks");
|
|
281
281
|
const lockKey = (0, import_node_crypto6.createHash)("sha256").update(`${installRoot}\0${process.version}`).digest("hex");
|
|
282
|
-
const lockDir = (0,
|
|
282
|
+
const lockDir = (0, import_node_path19.join)(lockRoot, lockKey);
|
|
283
283
|
const deadline = Date.now() + 12e4;
|
|
284
|
-
(0,
|
|
284
|
+
(0, import_node_fs7.mkdirSync)(lockRoot, { recursive: true });
|
|
285
285
|
while (true) {
|
|
286
286
|
try {
|
|
287
|
-
(0,
|
|
288
|
-
(0,
|
|
287
|
+
(0, import_node_fs7.mkdirSync)(lockDir);
|
|
288
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path19.join)(lockDir, "owner"), `${process.pid}
|
|
289
289
|
${(/* @__PURE__ */ new Date()).toISOString()}
|
|
290
290
|
${installRoot}
|
|
291
291
|
`);
|
|
292
292
|
return () => {
|
|
293
|
-
(0,
|
|
293
|
+
(0, import_node_fs7.rmSync)(lockDir, { recursive: true, force: true });
|
|
294
294
|
};
|
|
295
295
|
} catch (error) {
|
|
296
296
|
const code = error instanceof Error && "code" in error ? error.code : void 0;
|
|
@@ -298,7 +298,7 @@ ${installRoot}
|
|
|
298
298
|
throw error;
|
|
299
299
|
}
|
|
300
300
|
if (Date.now() > deadline) {
|
|
301
|
-
(0,
|
|
301
|
+
(0, import_node_fs7.rmSync)(lockDir, { recursive: true, force: true });
|
|
302
302
|
continue;
|
|
303
303
|
}
|
|
304
304
|
sleepSync(200);
|
|
@@ -314,13 +314,13 @@ function rebuildBetterSqlite3ForCurrentRuntime(originalError) {
|
|
|
314
314
|
}
|
|
315
315
|
rebuildAttempted = true;
|
|
316
316
|
const packageJsonPath = require2.resolve("better-sqlite3/package.json");
|
|
317
|
-
const installRoot = (0,
|
|
317
|
+
const installRoot = (0, import_node_path19.dirname)(packageJsonPath);
|
|
318
318
|
const rebuildCommand = resolveBetterSqliteRebuildCommand();
|
|
319
|
-
const nodeGypDevDir = (0,
|
|
320
|
-
const npmCacheDir = (0,
|
|
319
|
+
const nodeGypDevDir = (0, import_node_path19.join)((0, import_node_os3.tmpdir)(), "agent-qa-node-gyp", process.version.replace(/^v/, ""));
|
|
320
|
+
const npmCacheDir = (0, import_node_path19.join)((0, import_node_os3.tmpdir)(), "agent-qa-npm-cache");
|
|
321
321
|
const nodeDir = resolveCurrentRuntimeNodeDir();
|
|
322
|
-
const nodeGypBinsPath = (0,
|
|
323
|
-
const buildRoot = (0,
|
|
322
|
+
const nodeGypBinsPath = (0, import_node_path19.join)(installRoot, "build", "node_gyp_bins");
|
|
323
|
+
const buildRoot = (0, import_node_path19.join)(installRoot, "build");
|
|
324
324
|
const releaseLock = acquireBetterSqlite3RebuildLock(installRoot);
|
|
325
325
|
try {
|
|
326
326
|
clearBetterSqlite3Cache();
|
|
@@ -333,10 +333,10 @@ function rebuildBetterSqlite3ForCurrentRuntime(originalError) {
|
|
|
333
333
|
throw error;
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
|
-
(0,
|
|
337
|
-
(0,
|
|
338
|
-
(0,
|
|
339
|
-
(0,
|
|
336
|
+
(0, import_node_fs7.mkdirSync)(nodeGypDevDir, { recursive: true });
|
|
337
|
+
(0, import_node_fs7.mkdirSync)(npmCacheDir, { recursive: true });
|
|
338
|
+
(0, import_node_fs7.rmSync)(buildRoot, { recursive: true, force: true });
|
|
339
|
+
(0, import_node_fs7.rmSync)(nodeGypBinsPath, { recursive: true, force: true });
|
|
340
340
|
if (!process.env.VITEST) {
|
|
341
341
|
console.warn(`[agent-qa] Rebuilding better-sqlite3 for Node ${process.version} in ${installRoot}`);
|
|
342
342
|
}
|
|
@@ -390,16 +390,16 @@ function createBetterSqlite3Database(path5) {
|
|
|
390
390
|
return openBetterSqlite3Database(path5);
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
|
-
var import_node_child_process2,
|
|
393
|
+
var import_node_child_process2, import_node_fs7, import_node_crypto6, import_node_module3, import_node_os3, import_node_path19, import_meta3, require2, sqliteConstructor, rebuildAttempted, rebuildFailureMessage;
|
|
394
394
|
var init_sqlite = __esm({
|
|
395
395
|
"src/sqlite.ts"() {
|
|
396
396
|
"use strict";
|
|
397
397
|
import_node_child_process2 = require("child_process");
|
|
398
|
-
|
|
398
|
+
import_node_fs7 = require("fs");
|
|
399
399
|
import_node_crypto6 = require("crypto");
|
|
400
400
|
import_node_module3 = require("module");
|
|
401
401
|
import_node_os3 = require("os");
|
|
402
|
-
|
|
402
|
+
import_node_path19 = require("path");
|
|
403
403
|
import_meta3 = {};
|
|
404
404
|
require2 = (0, import_node_module3.createRequire)(import_meta3.url);
|
|
405
405
|
sqliteConstructor = null;
|
|
@@ -430,13 +430,13 @@ async function buildMemoryIndex(params) {
|
|
|
430
430
|
const insert = db.prepare("INSERT INTO observations(title, content, id, trust) VALUES (?, ?, ?, ?)");
|
|
431
431
|
const dirs = [];
|
|
432
432
|
if (validatePathComponent(params.product)) {
|
|
433
|
-
dirs.push({ path: (0,
|
|
433
|
+
dirs.push({ path: (0, import_node_path20.join)(params.memoryRoot, "products", params.product), isSuite: false });
|
|
434
434
|
}
|
|
435
435
|
if (params.suiteId && validatePathComponent(params.suiteId)) {
|
|
436
|
-
dirs.push({ path: (0,
|
|
436
|
+
dirs.push({ path: (0, import_node_path20.join)(params.memoryRoot, "suites", params.suiteId), isSuite: true });
|
|
437
437
|
}
|
|
438
438
|
if (validatePathComponent(params.testId)) {
|
|
439
|
-
dirs.push({ path: (0,
|
|
439
|
+
dirs.push({ path: (0, import_node_path20.join)(params.memoryRoot, "tests", params.testId), isSuite: false });
|
|
440
440
|
}
|
|
441
441
|
if (dirs.length === 0) {
|
|
442
442
|
console.warn("[memory-index] All path components failed validation", {
|
|
@@ -455,7 +455,7 @@ async function buildMemoryIndex(params) {
|
|
|
455
455
|
for (const { path: dirPath, isSuite } of dirs) {
|
|
456
456
|
const filenames = await listObservations(dirPath);
|
|
457
457
|
for (const filename of filenames) {
|
|
458
|
-
const filePath = (0,
|
|
458
|
+
const filePath = (0, import_node_path20.join)(dirPath, filename);
|
|
459
459
|
let raw;
|
|
460
460
|
try {
|
|
461
461
|
raw = await (0, import_promises14.readFile)(filePath, "utf-8");
|
|
@@ -485,12 +485,12 @@ async function buildMemoryIndex(params) {
|
|
|
485
485
|
return null;
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
|
-
var import_promises14,
|
|
488
|
+
var import_promises14, import_node_path20;
|
|
489
489
|
var init_memory_index = __esm({
|
|
490
490
|
"src/memory/memory-index.ts"() {
|
|
491
491
|
"use strict";
|
|
492
492
|
import_promises14 = require("fs/promises");
|
|
493
|
-
|
|
493
|
+
import_node_path20 = require("path");
|
|
494
494
|
init_observation_io();
|
|
495
495
|
init_security_scanner();
|
|
496
496
|
init_sqlite();
|
|
@@ -508,12 +508,12 @@ var init_xml_escape = __esm({
|
|
|
508
508
|
});
|
|
509
509
|
|
|
510
510
|
// src/memory/lock-manager.ts
|
|
511
|
-
var import_promises15,
|
|
511
|
+
var import_promises15, import_node_path21, LockManager;
|
|
512
512
|
var init_lock_manager = __esm({
|
|
513
513
|
"src/memory/lock-manager.ts"() {
|
|
514
514
|
"use strict";
|
|
515
515
|
import_promises15 = require("fs/promises");
|
|
516
|
-
|
|
516
|
+
import_node_path21 = require("path");
|
|
517
517
|
LockManager = class {
|
|
518
518
|
lockPath;
|
|
519
519
|
timeout;
|
|
@@ -522,7 +522,7 @@ var init_lock_manager = __esm({
|
|
|
522
522
|
this.timeout = timeout;
|
|
523
523
|
}
|
|
524
524
|
async acquire() {
|
|
525
|
-
await (0, import_promises15.mkdir)((0,
|
|
525
|
+
await (0, import_promises15.mkdir)((0, import_node_path21.dirname)(this.lockPath), { recursive: true });
|
|
526
526
|
const deadline = Date.now() + this.timeout;
|
|
527
527
|
while (Date.now() < deadline) {
|
|
528
528
|
try {
|
|
@@ -654,12 +654,12 @@ var local_provider_exports = {};
|
|
|
654
654
|
__export(local_provider_exports, {
|
|
655
655
|
LocalMemoryProvider: () => LocalMemoryProvider
|
|
656
656
|
});
|
|
657
|
-
var
|
|
657
|
+
var import_node_path22, import_node_fs8, import_promises16, LocalMemoryProvider;
|
|
658
658
|
var init_local_provider = __esm({
|
|
659
659
|
"src/memory/local-provider.ts"() {
|
|
660
660
|
"use strict";
|
|
661
|
-
|
|
662
|
-
|
|
661
|
+
import_node_path22 = require("path");
|
|
662
|
+
import_node_fs8 = require("fs");
|
|
663
663
|
import_promises16 = require("fs/promises");
|
|
664
664
|
init_memory_index();
|
|
665
665
|
init_xml_escape();
|
|
@@ -681,7 +681,7 @@ var init_local_provider = __esm({
|
|
|
681
681
|
this.minTrust = opts?.minTrust ?? 0.3;
|
|
682
682
|
this.maxInjections = opts?.maxInjections ?? 3;
|
|
683
683
|
this.lockManager = new LockManager(
|
|
684
|
-
(0,
|
|
684
|
+
(0, import_node_path22.join)(this.memoryRoot, ".curator.lock"),
|
|
685
685
|
opts?.curatorLockTimeout ?? 12e4
|
|
686
686
|
);
|
|
687
687
|
}
|
|
@@ -751,9 +751,9 @@ ${lines.join("\n")}
|
|
|
751
751
|
return writeObservation(this.memoryRoot, tier, scope, data);
|
|
752
752
|
}
|
|
753
753
|
async deleteObservation(tier, scope, id) {
|
|
754
|
-
const filePath = (0,
|
|
755
|
-
const resolved = (0,
|
|
756
|
-
if (!resolved.startsWith((0,
|
|
754
|
+
const filePath = (0, import_node_path22.join)(this.memoryRoot, tier, scope, `${id}.md`);
|
|
755
|
+
const resolved = (0, import_node_path22.resolve)(filePath);
|
|
756
|
+
if (!resolved.startsWith((0, import_node_path22.resolve)(this.memoryRoot) + import_node_path22.sep)) {
|
|
757
757
|
throw new Error("Path escapes memory root");
|
|
758
758
|
}
|
|
759
759
|
try {
|
|
@@ -770,25 +770,25 @@ ${lines.join("\n")}
|
|
|
770
770
|
const results = [];
|
|
771
771
|
const tiers = ["products", "suites", "tests"];
|
|
772
772
|
for (const tier of tiers) {
|
|
773
|
-
const tierDir = (0,
|
|
773
|
+
const tierDir = (0, import_node_path22.join)(this.memoryRoot, tier);
|
|
774
774
|
let scopes;
|
|
775
775
|
try {
|
|
776
|
-
scopes = (0,
|
|
776
|
+
scopes = (0, import_node_fs8.readdirSync)(tierDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
777
777
|
} catch {
|
|
778
778
|
continue;
|
|
779
779
|
}
|
|
780
780
|
for (const scope of scopes) {
|
|
781
|
-
const scopeDir = (0,
|
|
781
|
+
const scopeDir = (0, import_node_path22.join)(tierDir, scope);
|
|
782
782
|
let files;
|
|
783
783
|
try {
|
|
784
|
-
files = (0,
|
|
784
|
+
files = (0, import_node_fs8.readdirSync)(scopeDir).filter((f) => f.startsWith("obs_") && f.endsWith(".md"));
|
|
785
785
|
} catch {
|
|
786
786
|
continue;
|
|
787
787
|
}
|
|
788
788
|
for (const file of files) {
|
|
789
789
|
let raw;
|
|
790
790
|
try {
|
|
791
|
-
raw = (0,
|
|
791
|
+
raw = (0, import_node_fs8.readFileSync)((0, import_node_path22.join)(scopeDir, file), "utf-8");
|
|
792
792
|
} catch {
|
|
793
793
|
continue;
|
|
794
794
|
}
|
|
@@ -823,25 +823,25 @@ ${lines.join("\n")}
|
|
|
823
823
|
const tiers = ["products", "suites", "tests"];
|
|
824
824
|
const toInsert = [];
|
|
825
825
|
for (const tier of tiers) {
|
|
826
|
-
const tierDir = (0,
|
|
826
|
+
const tierDir = (0, import_node_path22.join)(this.memoryRoot, tier);
|
|
827
827
|
let scopes;
|
|
828
828
|
try {
|
|
829
|
-
scopes = (0,
|
|
829
|
+
scopes = (0, import_node_fs8.readdirSync)(tierDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
830
830
|
} catch {
|
|
831
831
|
continue;
|
|
832
832
|
}
|
|
833
833
|
for (const scope of scopes) {
|
|
834
|
-
const scopeDir = (0,
|
|
834
|
+
const scopeDir = (0, import_node_path22.join)(tierDir, scope);
|
|
835
835
|
let files;
|
|
836
836
|
try {
|
|
837
|
-
files = (0,
|
|
837
|
+
files = (0, import_node_fs8.readdirSync)(scopeDir).filter((f) => f.startsWith("obs_") && f.endsWith(".md"));
|
|
838
838
|
} catch {
|
|
839
839
|
continue;
|
|
840
840
|
}
|
|
841
841
|
for (const file of files) {
|
|
842
842
|
let raw;
|
|
843
843
|
try {
|
|
844
|
-
raw = (0,
|
|
844
|
+
raw = (0, import_node_fs8.readFileSync)((0, import_node_path22.join)(scopeDir, file), "utf-8");
|
|
845
845
|
} catch {
|
|
846
846
|
continue;
|
|
847
847
|
}
|
|
@@ -1068,6 +1068,7 @@ __export(index_exports, {
|
|
|
1068
1068
|
findSecretTemplates: () => findSecretTemplates,
|
|
1069
1069
|
findUnresolvedTemplates: () => findUnresolvedTemplates,
|
|
1070
1070
|
flushAnalytics: () => flushAnalytics,
|
|
1071
|
+
formatAppiumInstallGuidance: () => formatAppiumInstallGuidance,
|
|
1071
1072
|
formatDiagnostics: () => formatDiagnostics,
|
|
1072
1073
|
formatDiagnosticsPlain: () => formatDiagnosticsPlain,
|
|
1073
1074
|
formatLogEntry: () => formatLogEntry,
|
|
@@ -1102,6 +1103,7 @@ __export(index_exports, {
|
|
|
1102
1103
|
listObservations: () => listObservations,
|
|
1103
1104
|
listProviders: () => listProviders,
|
|
1104
1105
|
loadLLMAuthPlugins: () => loadLLMAuthPlugins,
|
|
1106
|
+
localAppiumBinaryNames: () => localAppiumBinaryNames,
|
|
1105
1107
|
mapMobileCapabilities: () => mapMobileCapabilities,
|
|
1106
1108
|
mapWebCapabilities: () => mapWebCapabilities,
|
|
1107
1109
|
mergeRunAttributes: () => mergeRunAttributes,
|
|
@@ -1128,6 +1130,7 @@ __export(index_exports, {
|
|
|
1128
1130
|
resolveAnalyticsAgentProduct: () => resolveAnalyticsAgentProduct,
|
|
1129
1131
|
resolveAnalyticsIdentity: () => resolveAnalyticsIdentity,
|
|
1130
1132
|
resolveAnalyticsStandardProperties: () => resolveAnalyticsStandardProperties,
|
|
1133
|
+
resolveAppiumExecutable: () => resolveAppiumExecutable,
|
|
1131
1134
|
resolveBetterSqliteRebuildCommand: () => resolveBetterSqliteRebuildCommand,
|
|
1132
1135
|
resolveFarmCredentials: () => resolveFarmCredentials,
|
|
1133
1136
|
resolveFileReferences: () => resolveFileReferences,
|
|
@@ -4974,9 +4977,9 @@ function getHookCommand(runtime, entryFile) {
|
|
|
4974
4977
|
}
|
|
4975
4978
|
}
|
|
4976
4979
|
async function checkDockerAvailable(dockerBin = DEFAULT_DOCKER_BIN) {
|
|
4977
|
-
return new Promise((
|
|
4980
|
+
return new Promise((resolve8) => {
|
|
4978
4981
|
(0, import_node_child_process.execFile)(dockerBin, ["info", "--format", "{{.ID}}"], { timeout: 5e3 }, (err) => {
|
|
4979
|
-
|
|
4982
|
+
resolve8(!err);
|
|
4980
4983
|
});
|
|
4981
4984
|
});
|
|
4982
4985
|
}
|
|
@@ -5089,22 +5092,22 @@ function filterSecretVariables(variables, secretStore) {
|
|
|
5089
5092
|
);
|
|
5090
5093
|
}
|
|
5091
5094
|
function imageExists(dockerBin, image) {
|
|
5092
|
-
return new Promise((
|
|
5095
|
+
return new Promise((resolve8) => {
|
|
5093
5096
|
(0, import_node_child_process.execFile)(dockerBin, ["image", "inspect", image], { timeout: 1e4 }, (err) => {
|
|
5094
|
-
|
|
5097
|
+
resolve8(!err);
|
|
5095
5098
|
});
|
|
5096
5099
|
});
|
|
5097
5100
|
}
|
|
5098
5101
|
function pullImage(dockerBin, image) {
|
|
5099
|
-
return new Promise((
|
|
5102
|
+
return new Promise((resolve8, reject) => {
|
|
5100
5103
|
(0, import_node_child_process.execFile)(dockerBin, ["pull", image], { timeout: 12e4 }, (err) => {
|
|
5101
5104
|
if (err) reject(new Error(`Failed to pull image ${image}: ${err.message}`));
|
|
5102
|
-
else
|
|
5105
|
+
else resolve8();
|
|
5103
5106
|
});
|
|
5104
5107
|
});
|
|
5105
5108
|
}
|
|
5106
5109
|
function execDocker(dockerBin, args, timeout) {
|
|
5107
|
-
return new Promise((
|
|
5110
|
+
return new Promise((resolve8, reject) => {
|
|
5108
5111
|
let stdout = "";
|
|
5109
5112
|
let stderr = "";
|
|
5110
5113
|
let resolved = false;
|
|
@@ -5114,11 +5117,11 @@ function execDocker(dockerBin, args, timeout) {
|
|
|
5114
5117
|
stdout = out ?? "";
|
|
5115
5118
|
stderr = errOut ?? "";
|
|
5116
5119
|
if (err && "killed" in err && err.killed) {
|
|
5117
|
-
|
|
5120
|
+
resolve8({ stdout, stderr: `Hook timed out after ${timeout}ms`, exitCode: 124 });
|
|
5118
5121
|
return;
|
|
5119
5122
|
}
|
|
5120
5123
|
const exitCode = err?.code ?? 0;
|
|
5121
|
-
|
|
5124
|
+
resolve8({ stdout, stderr, exitCode: typeof exitCode === "number" ? exitCode : 1 });
|
|
5122
5125
|
});
|
|
5123
5126
|
});
|
|
5124
5127
|
}
|
|
@@ -7194,14 +7197,41 @@ function resolveMobileRunConfig(input) {
|
|
|
7194
7197
|
};
|
|
7195
7198
|
}
|
|
7196
7199
|
|
|
7200
|
+
// src/mobile/appium-executable.ts
|
|
7201
|
+
var import_node_fs2 = require("fs");
|
|
7202
|
+
var import_node_path8 = require("path");
|
|
7203
|
+
function localAppiumBinaryNames(platform = process.platform) {
|
|
7204
|
+
return platform === "win32" ? ["appium.cmd", "appium.exe", "appium"] : ["appium"];
|
|
7205
|
+
}
|
|
7206
|
+
function resolveAppiumExecutable(opts = {}) {
|
|
7207
|
+
const exists = opts.exists ?? import_node_fs2.existsSync;
|
|
7208
|
+
const names = localAppiumBinaryNames(opts.platform ?? process.platform);
|
|
7209
|
+
let current = (0, import_node_path8.resolve)(opts.cwd ?? process.cwd());
|
|
7210
|
+
const root = (0, import_node_path8.parse)(current).root;
|
|
7211
|
+
while (true) {
|
|
7212
|
+
for (const name of names) {
|
|
7213
|
+
const candidate = (0, import_node_path8.join)(current, "node_modules", ".bin", name);
|
|
7214
|
+
if (exists(candidate)) {
|
|
7215
|
+
return { command: candidate, source: "local" };
|
|
7216
|
+
}
|
|
7217
|
+
}
|
|
7218
|
+
if (current === root) break;
|
|
7219
|
+
current = (0, import_node_path8.dirname)(current);
|
|
7220
|
+
}
|
|
7221
|
+
return { command: "appium", source: "path" };
|
|
7222
|
+
}
|
|
7223
|
+
function formatAppiumInstallGuidance() {
|
|
7224
|
+
return "Install Appium locally with `npm install -D appium` (or `pnpm add -D appium` / `yarn add -D appium`). If you prefer a machine-wide setup, use `npm install -g appium`.";
|
|
7225
|
+
}
|
|
7226
|
+
|
|
7197
7227
|
// src/auth/store.ts
|
|
7198
7228
|
var import_promises7 = require("fs/promises");
|
|
7199
|
-
var
|
|
7229
|
+
var import_node_path9 = require("path");
|
|
7200
7230
|
var import_node_os2 = require("os");
|
|
7201
7231
|
function getAuthPath() {
|
|
7202
7232
|
const xdg = process.env.XDG_DATA_HOME;
|
|
7203
|
-
if (xdg) return (0,
|
|
7204
|
-
return (0,
|
|
7233
|
+
if (xdg) return (0, import_node_path9.join)(xdg, "agent-qa", "auth.json");
|
|
7234
|
+
return (0, import_node_path9.join)((0, import_node_os2.homedir)(), ".agent-qa", "auth.json");
|
|
7205
7235
|
}
|
|
7206
7236
|
async function readAuth(path5) {
|
|
7207
7237
|
const authPath = path5 ?? getAuthPath();
|
|
@@ -7216,7 +7246,7 @@ async function writeAuth(provider, credential, path5) {
|
|
|
7216
7246
|
const authPath = path5 ?? getAuthPath();
|
|
7217
7247
|
const store = await readAuth(authPath);
|
|
7218
7248
|
store[provider] = credential;
|
|
7219
|
-
await (0, import_promises7.mkdir)((0,
|
|
7249
|
+
await (0, import_promises7.mkdir)((0, import_node_path9.dirname)(authPath), { recursive: true });
|
|
7220
7250
|
await (0, import_promises7.writeFile)(authPath, JSON.stringify(store, null, 2), { mode: 384 });
|
|
7221
7251
|
}
|
|
7222
7252
|
async function removeAuth(provider, path5) {
|
|
@@ -7394,17 +7424,17 @@ async function resolveLLMAuth(configName, llmConfig, authPath) {
|
|
|
7394
7424
|
|
|
7395
7425
|
// src/auth/plugin-loader.ts
|
|
7396
7426
|
var import_node_module = require("module");
|
|
7397
|
-
var
|
|
7398
|
-
var
|
|
7427
|
+
var import_node_fs3 = require("fs");
|
|
7428
|
+
var import_node_path10 = require("path");
|
|
7399
7429
|
var import_node_url = require("url");
|
|
7400
7430
|
var import_meta = {};
|
|
7401
7431
|
var loadedDeclarations = /* @__PURE__ */ new Set();
|
|
7402
7432
|
function findPackageJson(packageName, baseDir) {
|
|
7403
|
-
let current = (0,
|
|
7433
|
+
let current = (0, import_node_path10.resolve)(baseDir);
|
|
7404
7434
|
while (true) {
|
|
7405
|
-
const candidate = (0,
|
|
7406
|
-
if ((0,
|
|
7407
|
-
const parent = (0,
|
|
7435
|
+
const candidate = (0, import_node_path10.resolve)(current, "node_modules", ...packageName.split("/"), "package.json");
|
|
7436
|
+
if ((0, import_node_fs3.existsSync)(candidate)) return candidate;
|
|
7437
|
+
const parent = (0, import_node_path10.dirname)(current);
|
|
7408
7438
|
if (parent === current) return null;
|
|
7409
7439
|
current = parent;
|
|
7410
7440
|
}
|
|
@@ -7429,10 +7459,10 @@ function exportTargetFromPackageJson(pkg) {
|
|
|
7429
7459
|
function resolvePackageImportFromBase(packageName, baseDir) {
|
|
7430
7460
|
const packageJsonPath = findPackageJson(packageName, baseDir);
|
|
7431
7461
|
if (!packageJsonPath) return null;
|
|
7432
|
-
const pkg = JSON.parse((0,
|
|
7462
|
+
const pkg = JSON.parse((0, import_node_fs3.readFileSync)(packageJsonPath, "utf-8"));
|
|
7433
7463
|
const target = exportTargetFromPackageJson(pkg);
|
|
7434
7464
|
if (!target || !target.startsWith(".")) return null;
|
|
7435
|
-
return (0, import_node_url.pathToFileURL)((0,
|
|
7465
|
+
return (0, import_node_url.pathToFileURL)((0, import_node_path10.resolve)((0, import_node_path10.dirname)(packageJsonPath), target)).href;
|
|
7436
7466
|
}
|
|
7437
7467
|
function packageDeclarationValue(declaration) {
|
|
7438
7468
|
return "package" in declaration && typeof declaration.package === "string" ? declaration.package.trim() : "";
|
|
@@ -7443,24 +7473,24 @@ function pathDeclarationValue(declaration) {
|
|
|
7443
7473
|
function declarationKey(declaration, baseDir) {
|
|
7444
7474
|
const packageName = packageDeclarationValue(declaration);
|
|
7445
7475
|
if (packageName) return `package:${packageName}`;
|
|
7446
|
-
return `path:${(0,
|
|
7476
|
+
return `path:${(0, import_node_path10.resolve)(baseDir, pathDeclarationValue(declaration))}`;
|
|
7447
7477
|
}
|
|
7448
7478
|
function resolveModuleSpecifier(declaration, baseDir) {
|
|
7449
7479
|
const packageName = packageDeclarationValue(declaration);
|
|
7450
7480
|
if (packageName) {
|
|
7451
7481
|
const packageImport = resolvePackageImportFromBase(packageName, baseDir);
|
|
7452
7482
|
if (packageImport) return packageImport;
|
|
7453
|
-
const parentUrl = (0, import_node_url.pathToFileURL)((0,
|
|
7483
|
+
const parentUrl = (0, import_node_url.pathToFileURL)((0, import_node_path10.resolve)(baseDir, "agent-qa.config.yaml")).href;
|
|
7454
7484
|
try {
|
|
7455
7485
|
const resolveImport = import_meta.resolve;
|
|
7456
7486
|
return resolveImport(packageName, parentUrl);
|
|
7457
7487
|
} catch {
|
|
7458
|
-
const require3 = (0, import_node_module.createRequire)((0,
|
|
7488
|
+
const require3 = (0, import_node_module.createRequire)((0, import_node_path10.resolve)(baseDir, "agent-qa.config.yaml"));
|
|
7459
7489
|
return (0, import_node_url.pathToFileURL)(require3.resolve(packageName)).href;
|
|
7460
7490
|
}
|
|
7461
7491
|
}
|
|
7462
7492
|
const pluginPath = pathDeclarationValue(declaration);
|
|
7463
|
-
const absolutePath = (0,
|
|
7493
|
+
const absolutePath = (0, import_node_path10.isAbsolute)(pluginPath) ? pluginPath : (0, import_node_path10.resolve)(baseDir, pluginPath);
|
|
7464
7494
|
return (0, import_node_url.pathToFileURL)(absolutePath).href;
|
|
7465
7495
|
}
|
|
7466
7496
|
async function resolvePluginBundle(module2, source) {
|
|
@@ -7850,8 +7880,8 @@ function mapMobileCapabilities(match, platform, credentials, opts) {
|
|
|
7850
7880
|
}
|
|
7851
7881
|
|
|
7852
7882
|
// src/farm/browserstack.ts
|
|
7853
|
-
var
|
|
7854
|
-
var
|
|
7883
|
+
var import_node_fs4 = require("fs");
|
|
7884
|
+
var import_node_path11 = require("path");
|
|
7855
7885
|
function isAbsoluteAppValue(value) {
|
|
7856
7886
|
return value.startsWith("/") || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
7857
7887
|
}
|
|
@@ -7870,9 +7900,9 @@ async function resolveBrowserStackApp(config) {
|
|
|
7870
7900
|
});
|
|
7871
7901
|
}
|
|
7872
7902
|
const appBaseDir = config.appBaseDir ?? process.cwd();
|
|
7873
|
-
const resolvedPath = (0,
|
|
7903
|
+
const resolvedPath = (0, import_node_path11.resolve)(appBaseDir, config.app);
|
|
7874
7904
|
const mustExist = isExplicitRelativePath(config.app);
|
|
7875
|
-
if (!(0,
|
|
7905
|
+
if (!(0, import_node_fs4.existsSync)(resolvedPath)) {
|
|
7876
7906
|
if (mustExist) {
|
|
7877
7907
|
throw new MobileSetupError({
|
|
7878
7908
|
category: "app-install",
|
|
@@ -7886,7 +7916,7 @@ async function resolveBrowserStackApp(config) {
|
|
|
7886
7916
|
}
|
|
7887
7917
|
const auth = Buffer.from(`${config.credentials.username}:${config.credentials.accessKey}`).toString("base64");
|
|
7888
7918
|
const form = new FormData();
|
|
7889
|
-
form.append("file", new Blob([(0,
|
|
7919
|
+
form.append("file", new Blob([(0, import_node_fs4.readFileSync)(resolvedPath)]), (0, import_node_path11.basename)(resolvedPath));
|
|
7890
7920
|
let res;
|
|
7891
7921
|
try {
|
|
7892
7922
|
res = await fetch("https://api-cloud.browserstack.com/app-automate/upload", {
|
|
@@ -8063,7 +8093,7 @@ async function runHooks(hooks, options = {}) {
|
|
|
8063
8093
|
// src/memory/curator.ts
|
|
8064
8094
|
var import_ai7 = require("ai");
|
|
8065
8095
|
var import_zod19 = require("zod");
|
|
8066
|
-
var
|
|
8096
|
+
var import_node_path13 = require("path");
|
|
8067
8097
|
var import_promises9 = require("fs/promises");
|
|
8068
8098
|
init_observation_io();
|
|
8069
8099
|
|
|
@@ -8212,7 +8242,7 @@ function collectKnownObservationIds(injectedObservationIds, dedupMatches) {
|
|
|
8212
8242
|
async function findObservationFile(memoryRoot, id) {
|
|
8213
8243
|
const tiers = ["products", "suites", "tests"];
|
|
8214
8244
|
for (const tier of tiers) {
|
|
8215
|
-
const tierDir = (0,
|
|
8245
|
+
const tierDir = (0, import_node_path13.join)(memoryRoot, tier);
|
|
8216
8246
|
let scopes;
|
|
8217
8247
|
try {
|
|
8218
8248
|
scopes = await (0, import_promises9.readdir)(tierDir);
|
|
@@ -8220,7 +8250,7 @@ async function findObservationFile(memoryRoot, id) {
|
|
|
8220
8250
|
continue;
|
|
8221
8251
|
}
|
|
8222
8252
|
for (const scope of scopes) {
|
|
8223
|
-
const filePath = (0,
|
|
8253
|
+
const filePath = (0, import_node_path13.join)(tierDir, scope, `${id}.md`);
|
|
8224
8254
|
try {
|
|
8225
8255
|
await (0, import_promises9.access)(filePath);
|
|
8226
8256
|
return { tier, scope, filePath };
|
|
@@ -8449,11 +8479,11 @@ ${userMessage}`;
|
|
|
8449
8479
|
}
|
|
8450
8480
|
if (ctx.suiteId && ctx.suiteContext) {
|
|
8451
8481
|
try {
|
|
8452
|
-
const suiteDir = (0,
|
|
8482
|
+
const suiteDir = (0, import_node_path13.join)(ctx.memoryRoot, "suites", ctx.suiteId);
|
|
8453
8483
|
const files = await listObservations(suiteDir);
|
|
8454
8484
|
for (const file of files) {
|
|
8455
8485
|
try {
|
|
8456
|
-
const filePath = (0,
|
|
8486
|
+
const filePath = (0, import_node_path13.join)(suiteDir, file);
|
|
8457
8487
|
const raw = await (0, import_promises9.readFile)(filePath, "utf-8");
|
|
8458
8488
|
const { data } = parseObservation(raw, file);
|
|
8459
8489
|
if (!data || !("suite_snapshot" in data)) continue;
|
|
@@ -8917,6 +8947,7 @@ async function runSuite(suite, testEntries, config) {
|
|
|
8917
8947
|
inlineHookSandboxOptions: config.sandboxOptions,
|
|
8918
8948
|
secretStore: config.secretStore,
|
|
8919
8949
|
secretRedactor: config.secretRedactor,
|
|
8950
|
+
accessibility: config.accessibility,
|
|
8920
8951
|
logCapture: config.logCapture,
|
|
8921
8952
|
screenshotSize: config.screenshotSize,
|
|
8922
8953
|
effectiveResolution: config.effectiveResolution,
|
|
@@ -8984,7 +9015,8 @@ async function runSuite(suite, testEntries, config) {
|
|
|
8984
9015
|
timeouts: config.timeouts,
|
|
8985
9016
|
logger: config.logger,
|
|
8986
9017
|
secretStore: config.secretStore,
|
|
8987
|
-
secretRedactor: config.secretRedactor
|
|
9018
|
+
secretRedactor: config.secretRedactor,
|
|
9019
|
+
accessibility: config.accessibility
|
|
8988
9020
|
}, filePath);
|
|
8989
9021
|
if (config.circuitBreaker) {
|
|
8990
9022
|
config.circuitBreaker.record({ withMemory: false, passed: ablationResult.status === "passed" });
|
|
@@ -9155,14 +9187,14 @@ async function runSuite(suite, testEntries, config) {
|
|
|
9155
9187
|
|
|
9156
9188
|
// src/validation/validate.ts
|
|
9157
9189
|
var import_promises12 = require("fs/promises");
|
|
9158
|
-
var
|
|
9159
|
-
var
|
|
9190
|
+
var import_node_fs6 = require("fs");
|
|
9191
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
9160
9192
|
var import_yaml5 = require("yaml");
|
|
9161
9193
|
var import_glob2 = require("glob");
|
|
9162
9194
|
|
|
9163
9195
|
// src/hooks/parser.ts
|
|
9164
9196
|
var import_promises11 = require("fs/promises");
|
|
9165
|
-
var
|
|
9197
|
+
var import_node_path14 = require("path");
|
|
9166
9198
|
var import_yaml4 = require("yaml");
|
|
9167
9199
|
async function parseHooksFile(filePath) {
|
|
9168
9200
|
let raw;
|
|
@@ -9184,31 +9216,31 @@ async function parseHooksFile(filePath) {
|
|
|
9184
9216
|
);
|
|
9185
9217
|
return { hooks: [], errors };
|
|
9186
9218
|
}
|
|
9187
|
-
const dir = (0,
|
|
9219
|
+
const dir = (0, import_node_path14.dirname)(filePath);
|
|
9188
9220
|
const hooks = result.data.hooks.map((h) => ({
|
|
9189
9221
|
...h,
|
|
9190
|
-
file: (0,
|
|
9191
|
-
deps: h.deps.map((d) => (0,
|
|
9192
|
-
packageFile: h.packageFile ? (0,
|
|
9222
|
+
file: (0, import_node_path14.resolve)(dir, h.file),
|
|
9223
|
+
deps: h.deps.map((d) => (0, import_node_path14.resolve)(dir, d)),
|
|
9224
|
+
packageFile: h.packageFile ? (0, import_node_path14.resolve)(dir, h.packageFile) : void 0
|
|
9193
9225
|
}));
|
|
9194
9226
|
return { hooks, errors: [] };
|
|
9195
9227
|
}
|
|
9196
9228
|
|
|
9197
9229
|
// src/utils/path-validation.ts
|
|
9198
|
-
var
|
|
9230
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
9199
9231
|
function isPathInsideDir(childPath, parentDir) {
|
|
9200
9232
|
if (!childPath) return false;
|
|
9201
|
-
const resolved =
|
|
9202
|
-
const relative2 =
|
|
9203
|
-
return !!relative2 && !relative2.startsWith("..") && !
|
|
9233
|
+
const resolved = import_node_path15.default.resolve(parentDir, childPath);
|
|
9234
|
+
const relative2 = import_node_path15.default.relative(parentDir, resolved);
|
|
9235
|
+
return !!relative2 && !relative2.startsWith("..") && !import_node_path15.default.isAbsolute(relative2);
|
|
9204
9236
|
}
|
|
9205
9237
|
|
|
9206
9238
|
// src/workspace/workspace-paths.ts
|
|
9207
|
-
var
|
|
9208
|
-
var
|
|
9239
|
+
var import_node_fs5 = require("fs");
|
|
9240
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
9209
9241
|
var import_glob = require("glob");
|
|
9210
9242
|
function toForwardSlash(value) {
|
|
9211
|
-
return value.split(
|
|
9243
|
+
return value.split(import_node_path16.default.sep).join("/");
|
|
9212
9244
|
}
|
|
9213
9245
|
function trimLeadingCurrentDir(value) {
|
|
9214
9246
|
return toForwardSlash(value).replace(/^\.\//, "");
|
|
@@ -9227,16 +9259,16 @@ function assertNonEmptyString(value, key) {
|
|
|
9227
9259
|
}
|
|
9228
9260
|
function resolveWorkspaceScalar(configDir, key, configuredPath) {
|
|
9229
9261
|
const value = assertNonEmptyString(configuredPath, key);
|
|
9230
|
-
const absolutePath =
|
|
9262
|
+
const absolutePath = import_node_path16.default.isAbsolute(value) ? import_node_path16.default.resolve(value) : import_node_path16.default.resolve(configDir, value);
|
|
9231
9263
|
return {
|
|
9232
9264
|
configuredPath: value,
|
|
9233
9265
|
absolutePath,
|
|
9234
|
-
workspaceRelativePath: trimLeadingCurrentDir(
|
|
9266
|
+
workspaceRelativePath: trimLeadingCurrentDir(import_node_path16.default.relative(configDir, absolutePath))
|
|
9235
9267
|
};
|
|
9236
9268
|
}
|
|
9237
9269
|
function assertInsideWorkspace(configDir, absolutePath, filePath) {
|
|
9238
|
-
const relativePath =
|
|
9239
|
-
if (!relativePath || relativePath.startsWith("..") ||
|
|
9270
|
+
const relativePath = import_node_path16.default.relative(configDir, absolutePath);
|
|
9271
|
+
if (!relativePath || relativePath.startsWith("..") || import_node_path16.default.isAbsolute(relativePath)) {
|
|
9240
9272
|
throw new Error(`Workspace file path escapes config directory: ${filePath}`);
|
|
9241
9273
|
}
|
|
9242
9274
|
return trimLeadingCurrentDir(relativePath);
|
|
@@ -9293,8 +9325,8 @@ function isIgnored(workspace, workspaceRelativePath) {
|
|
|
9293
9325
|
return workspace.testPathIgnore.length > 0 && matchesAnyPattern(workspaceRelativePath, workspace.testPathIgnore);
|
|
9294
9326
|
}
|
|
9295
9327
|
function resolveWorkspacePaths(input) {
|
|
9296
|
-
const configPath =
|
|
9297
|
-
const configDir =
|
|
9328
|
+
const configPath = import_node_path16.default.resolve(input.configPath);
|
|
9329
|
+
const configDir = import_node_path16.default.dirname(configPath);
|
|
9298
9330
|
const workspace = input.config.workspace;
|
|
9299
9331
|
if (!workspace) {
|
|
9300
9332
|
throw new Error("Missing required workspace config key: workspace");
|
|
@@ -9317,7 +9349,7 @@ function resolveWorkspacePaths(input) {
|
|
|
9317
9349
|
["workspace.envFile", resolved.envFile],
|
|
9318
9350
|
["workspace.secretsFile", resolved.secretsFile]
|
|
9319
9351
|
]) {
|
|
9320
|
-
if (!(0,
|
|
9352
|
+
if (!(0, import_node_fs5.existsSync)(file.absolutePath)) {
|
|
9321
9353
|
throw new Error(`Configured workspace file not found: ${key} -> ${file.absolutePath}`);
|
|
9322
9354
|
}
|
|
9323
9355
|
}
|
|
@@ -9332,14 +9364,14 @@ async function discoverWorkspaceFiles(input) {
|
|
|
9332
9364
|
absolute: true,
|
|
9333
9365
|
nodir: true
|
|
9334
9366
|
});
|
|
9335
|
-
return matches.map((match) =>
|
|
9367
|
+
return matches.map((match) => import_node_path16.default.resolve(match)).map((absolutePath) => ({
|
|
9336
9368
|
kind: input.kind,
|
|
9337
9369
|
absolutePath,
|
|
9338
|
-
workspaceRelativePath: trimLeadingCurrentDir(
|
|
9370
|
+
workspaceRelativePath: trimLeadingCurrentDir(import_node_path16.default.relative(input.workspace.configDir, absolutePath))
|
|
9339
9371
|
})).sort((a, b) => a.workspaceRelativePath.localeCompare(b.workspaceRelativePath));
|
|
9340
9372
|
}
|
|
9341
9373
|
async function resolveWorkspaceFileTarget(input) {
|
|
9342
|
-
const absolutePath =
|
|
9374
|
+
const absolutePath = import_node_path16.default.isAbsolute(input.filePath) ? import_node_path16.default.resolve(input.filePath) : import_node_path16.default.resolve(input.workspace.configDir, input.filePath);
|
|
9343
9375
|
const workspaceRelativePath = assertInsideWorkspace(input.workspace.configDir, absolutePath, input.filePath);
|
|
9344
9376
|
if (!isWorkspacePathMatch({
|
|
9345
9377
|
workspace: input.workspace,
|
|
@@ -9348,7 +9380,7 @@ async function resolveWorkspaceFileTarget(input) {
|
|
|
9348
9380
|
})) {
|
|
9349
9381
|
throw new Error(`Workspace ${input.kind} file is not matched by configured workspace patterns: ${workspaceRelativePath}`);
|
|
9350
9382
|
}
|
|
9351
|
-
if (input.requireExisting && !(0,
|
|
9383
|
+
if (input.requireExisting && !(0, import_node_fs5.existsSync)(absolutePath)) {
|
|
9352
9384
|
throw new Error(`Workspace ${input.kind} file not found: ${workspaceRelativePath}`);
|
|
9353
9385
|
}
|
|
9354
9386
|
return {
|
|
@@ -9469,8 +9501,8 @@ function validateSuiteFile(filePath, content, basedir) {
|
|
|
9469
9501
|
});
|
|
9470
9502
|
continue;
|
|
9471
9503
|
}
|
|
9472
|
-
const resolved =
|
|
9473
|
-
if (!(0,
|
|
9504
|
+
const resolved = import_node_path17.default.resolve(basedir, testPath);
|
|
9505
|
+
if (!(0, import_node_fs6.existsSync)(resolved)) {
|
|
9474
9506
|
let line = 1;
|
|
9475
9507
|
let column = 1;
|
|
9476
9508
|
const seqNode = testsNode;
|
|
@@ -9491,7 +9523,7 @@ function validateSuiteFile(filePath, content, basedir) {
|
|
|
9491
9523
|
return diagnostics;
|
|
9492
9524
|
}
|
|
9493
9525
|
function validateFilename(filePath) {
|
|
9494
|
-
const basename3 =
|
|
9526
|
+
const basename3 = import_node_path17.default.basename(filePath);
|
|
9495
9527
|
if (!VALID_FILENAME_RE.test(basename3)) {
|
|
9496
9528
|
return [{
|
|
9497
9529
|
file: filePath,
|
|
@@ -9505,7 +9537,7 @@ function validateFilename(filePath) {
|
|
|
9505
9537
|
}
|
|
9506
9538
|
async function validateHooksFile(hooksFilePath, options = {}) {
|
|
9507
9539
|
const diagnostics = [];
|
|
9508
|
-
if (!(0,
|
|
9540
|
+
if (!(0, import_node_fs6.existsSync)(hooksFilePath)) {
|
|
9509
9541
|
if (options.required) {
|
|
9510
9542
|
return [buildDiagnostic(hooksFilePath, `Configured hooks file not found: ${hooksFilePath}`)];
|
|
9511
9543
|
}
|
|
@@ -9525,7 +9557,7 @@ async function validateHooksFile(hooksFilePath, options = {}) {
|
|
|
9525
9557
|
return diagnostics;
|
|
9526
9558
|
}
|
|
9527
9559
|
for (const hook of hooks) {
|
|
9528
|
-
if (!(0,
|
|
9560
|
+
if (!(0, import_node_fs6.existsSync)(hook.file)) {
|
|
9529
9561
|
diagnostics.push({
|
|
9530
9562
|
file: hooksFilePath,
|
|
9531
9563
|
line: 1,
|
|
@@ -9535,7 +9567,7 @@ async function validateHooksFile(hooksFilePath, options = {}) {
|
|
|
9535
9567
|
});
|
|
9536
9568
|
}
|
|
9537
9569
|
for (const dep of hook.deps) {
|
|
9538
|
-
if (!(0,
|
|
9570
|
+
if (!(0, import_node_fs6.existsSync)(dep)) {
|
|
9539
9571
|
diagnostics.push({
|
|
9540
9572
|
file: hooksFilePath,
|
|
9541
9573
|
line: 1,
|
|
@@ -9545,7 +9577,7 @@ async function validateHooksFile(hooksFilePath, options = {}) {
|
|
|
9545
9577
|
});
|
|
9546
9578
|
}
|
|
9547
9579
|
}
|
|
9548
|
-
if (hook.packageFile && !(0,
|
|
9580
|
+
if (hook.packageFile && !(0, import_node_fs6.existsSync)(hook.packageFile)) {
|
|
9549
9581
|
diagnostics.push({
|
|
9550
9582
|
file: hooksFilePath,
|
|
9551
9583
|
line: 1,
|
|
@@ -9660,7 +9692,7 @@ function validateRequiredWorkspaceFiles(workspace) {
|
|
|
9660
9692
|
["workspace.envFile", workspace.envFile],
|
|
9661
9693
|
["workspace.secretsFile", workspace.secretsFile]
|
|
9662
9694
|
]) {
|
|
9663
|
-
if (!(0,
|
|
9695
|
+
if (!(0, import_node_fs6.existsSync)(file.absolutePath)) {
|
|
9664
9696
|
diagnostics.push(buildDiagnostic(file.absolutePath, `Configured workspace file not found: ${key} -> ${file.absolutePath}`));
|
|
9665
9697
|
}
|
|
9666
9698
|
}
|
|
@@ -9678,7 +9710,7 @@ async function validateProject(options = {}) {
|
|
|
9678
9710
|
}
|
|
9679
9711
|
filePaths = resolvedFiles;
|
|
9680
9712
|
} else if (options.files && options.files.length > 0) {
|
|
9681
|
-
filePaths = options.files.map((f) =>
|
|
9713
|
+
filePaths = options.files.map((f) => import_node_path17.default.resolve(f));
|
|
9682
9714
|
} else if (options.workspace) {
|
|
9683
9715
|
const [testFiles, suiteFiles] = await Promise.all([
|
|
9684
9716
|
discoverWorkspaceFiles({ workspace: options.workspace, kind: "test" }),
|
|
@@ -9721,11 +9753,11 @@ async function validateProject(options = {}) {
|
|
|
9721
9753
|
if (d.severity === "error") result.errorCount++;
|
|
9722
9754
|
else result.warningCount++;
|
|
9723
9755
|
}
|
|
9724
|
-
if (hooksFilePath && hooksDiags.length === 0 && (0,
|
|
9756
|
+
if (hooksFilePath && hooksDiags.length === 0 && (0, import_node_fs6.existsSync)(hooksFilePath)) {
|
|
9725
9757
|
const { hooks } = await parseHooksFile(hooksFilePath);
|
|
9726
9758
|
const hookIds = new Set(hooks.map((h) => h.id));
|
|
9727
9759
|
for (const filePath of filePaths) {
|
|
9728
|
-
const workspaceRelativePath = options.workspace ?
|
|
9760
|
+
const workspaceRelativePath = options.workspace ? import_node_path17.default.relative(options.workspace.configDir, filePath).split(import_node_path17.default.sep).join("/") : filePath;
|
|
9729
9761
|
const isWorkspaceFile = options.workspace ? isWorkspacePathMatch({ workspace: options.workspace, kind: isSuiteFile(filePath) ? "suite" : "test", workspaceRelativePath }) : true;
|
|
9730
9762
|
if (!isWorkspaceFile) continue;
|
|
9731
9763
|
try {
|
|
@@ -9827,7 +9859,7 @@ function warnIfOutOfBounds(coords, viewport, actionType) {
|
|
|
9827
9859
|
|
|
9828
9860
|
// src/hooks/migrate-hook-refs.ts
|
|
9829
9861
|
var import_promises13 = require("fs/promises");
|
|
9830
|
-
var
|
|
9862
|
+
var import_node_path18 = require("path");
|
|
9831
9863
|
var import_yaml6 = require("yaml");
|
|
9832
9864
|
var import_zod20 = require("zod");
|
|
9833
9865
|
var import_agent_qa_ids8 = require("@vostride/agent-qa-ids");
|
|
@@ -9933,7 +9965,7 @@ function rewriteSteps(owner, filePath, hookNameToId, hookIds, errors) {
|
|
|
9933
9965
|
return changed;
|
|
9934
9966
|
}
|
|
9935
9967
|
async function resolveWorkspaceMigrationContext(workspaceDir, configPath) {
|
|
9936
|
-
const resolvedConfigPath = configPath ? (0,
|
|
9968
|
+
const resolvedConfigPath = configPath ? (0, import_node_path18.resolve)(configPath) : (0, import_node_path18.resolve)(workspaceDir, "agent-qa.config.yaml");
|
|
9937
9969
|
const rawConfig = await (0, import_promises13.readFile)(resolvedConfigPath, "utf-8");
|
|
9938
9970
|
const parsedConfig = (0, import_yaml6.parse)(rawConfig);
|
|
9939
9971
|
const configResult = AgentQaConfigSchema.safeParse(parsedConfig);
|
|
@@ -9960,7 +9992,7 @@ async function resolveWorkspaceMigrationContext(workspaceDir, configPath) {
|
|
|
9960
9992
|
};
|
|
9961
9993
|
}
|
|
9962
9994
|
async function auditWorkspaceHookReferenceMigration(options) {
|
|
9963
|
-
const workspaceDir = (0,
|
|
9995
|
+
const workspaceDir = (0, import_node_path18.resolve)(options.workspaceDir);
|
|
9964
9996
|
const errors = [];
|
|
9965
9997
|
let context;
|
|
9966
9998
|
try {
|
|
@@ -10023,12 +10055,12 @@ async function auditWorkspaceHookReferenceMigration(options) {
|
|
|
10023
10055
|
const hookIds = new Set(Object.values(hookNameToId));
|
|
10024
10056
|
if (hooksChanged) {
|
|
10025
10057
|
rewriteFiles.push({
|
|
10026
|
-
path: (0,
|
|
10058
|
+
path: (0, import_node_path18.relative)(context.configDir, context.hooksFilePath),
|
|
10027
10059
|
content: (0, import_yaml6.stringify)({ hooks: normalizedHooks })
|
|
10028
10060
|
});
|
|
10029
10061
|
}
|
|
10030
10062
|
for (const relativePath of context.targetFiles) {
|
|
10031
|
-
const absolutePath = (0,
|
|
10063
|
+
const absolutePath = (0, import_node_path18.resolve)(context.configDir, relativePath);
|
|
10032
10064
|
let parsedFile;
|
|
10033
10065
|
try {
|
|
10034
10066
|
parsedFile = (0, import_yaml6.parse)(await (0, import_promises13.readFile)(absolutePath, "utf-8"));
|
|
@@ -10069,14 +10101,14 @@ async function applyWorkspaceHookReferenceMigration(options) {
|
|
|
10069
10101
|
if (!audit.ok) {
|
|
10070
10102
|
throw new HookReferenceMigrationError(audit.errors);
|
|
10071
10103
|
}
|
|
10072
|
-
const workspaceDir = options.configPath ? (0,
|
|
10104
|
+
const workspaceDir = options.configPath ? (0, import_node_path18.dirname)((0, import_node_path18.resolve)(options.configPath)) : (0, import_node_path18.resolve)(options.workspaceDir);
|
|
10073
10105
|
for (const rewrite of audit.rewriteFiles) {
|
|
10074
|
-
const outputPath = (0,
|
|
10075
|
-
await (0, import_promises13.mkdir)((0,
|
|
10106
|
+
const outputPath = (0, import_node_path18.resolve)(workspaceDir, rewrite.path);
|
|
10107
|
+
await (0, import_promises13.mkdir)((0, import_node_path18.dirname)(outputPath), { recursive: true });
|
|
10076
10108
|
await (0, import_promises13.writeFile)(outputPath, rewrite.content, "utf-8");
|
|
10077
10109
|
}
|
|
10078
10110
|
for (const cleanupTarget of audit.cleanupTargets) {
|
|
10079
|
-
await (0, import_promises13.rm)((0,
|
|
10111
|
+
await (0, import_promises13.rm)((0, import_node_path18.resolve)(workspaceDir, cleanupTarget), { recursive: true, force: true });
|
|
10080
10112
|
}
|
|
10081
10113
|
return audit;
|
|
10082
10114
|
}
|
|
@@ -10147,12 +10179,12 @@ var RUN_ARTIFACT_SCHEMA_VERSION = 1;
|
|
|
10147
10179
|
// src/analytics/identity.ts
|
|
10148
10180
|
var import_promises17 = require("fs/promises");
|
|
10149
10181
|
var import_node_os4 = require("os");
|
|
10150
|
-
var
|
|
10182
|
+
var import_node_path23 = require("path");
|
|
10151
10183
|
var import_id_agent = require("id-agent");
|
|
10152
10184
|
var LOCAL_ANALYTICS_ID_PATTERN = /^u_([a-z]+-){9}[a-z]+$/;
|
|
10153
10185
|
function getAnalyticsIdentityPath(env = process.env, homeDir = (0, import_node_os4.homedir)()) {
|
|
10154
|
-
if (env.XDG_DATA_HOME) return (0,
|
|
10155
|
-
return (0,
|
|
10186
|
+
if (env.XDG_DATA_HOME) return (0, import_node_path23.join)(env.XDG_DATA_HOME, "agent-qa", "analytics.json");
|
|
10187
|
+
return (0, import_node_path23.join)(homeDir, ".agent-qa", "analytics.json");
|
|
10156
10188
|
}
|
|
10157
10189
|
function generateAnalyticsUserId() {
|
|
10158
10190
|
return (0, import_id_agent.idAgent)({ prefix: "u", words: 10 });
|
|
@@ -10184,7 +10216,7 @@ async function readAnalyticsIdentity(path5) {
|
|
|
10184
10216
|
}
|
|
10185
10217
|
async function writeAnalyticsIdentity(distinctId, path5, isInternal = false) {
|
|
10186
10218
|
const identityPath = path5 ?? getAnalyticsIdentityPath();
|
|
10187
|
-
await (0, import_promises17.mkdir)((0,
|
|
10219
|
+
await (0, import_promises17.mkdir)((0, import_node_path23.dirname)(identityPath), { recursive: true });
|
|
10188
10220
|
await (0, import_promises17.writeFile)(identityPath, JSON.stringify({
|
|
10189
10221
|
distinctId,
|
|
10190
10222
|
is_internal: isInternal
|
|
@@ -11295,6 +11327,7 @@ function isMacPlatform() {
|
|
|
11295
11327
|
findSecretTemplates,
|
|
11296
11328
|
findUnresolvedTemplates,
|
|
11297
11329
|
flushAnalytics,
|
|
11330
|
+
formatAppiumInstallGuidance,
|
|
11298
11331
|
formatDiagnostics,
|
|
11299
11332
|
formatDiagnosticsPlain,
|
|
11300
11333
|
formatLogEntry,
|
|
@@ -11329,6 +11362,7 @@ function isMacPlatform() {
|
|
|
11329
11362
|
listObservations,
|
|
11330
11363
|
listProviders,
|
|
11331
11364
|
loadLLMAuthPlugins,
|
|
11365
|
+
localAppiumBinaryNames,
|
|
11332
11366
|
mapMobileCapabilities,
|
|
11333
11367
|
mapWebCapabilities,
|
|
11334
11368
|
mergeRunAttributes,
|
|
@@ -11355,6 +11389,7 @@ function isMacPlatform() {
|
|
|
11355
11389
|
resolveAnalyticsAgentProduct,
|
|
11356
11390
|
resolveAnalyticsIdentity,
|
|
11357
11391
|
resolveAnalyticsStandardProperties,
|
|
11392
|
+
resolveAppiumExecutable,
|
|
11358
11393
|
resolveBetterSqliteRebuildCommand,
|
|
11359
11394
|
resolveFarmCredentials,
|
|
11360
11395
|
resolveFileReferences,
|