@vostride/agent-qa-dashboard 0.1.13 → 0.1.15
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-BL7OautO.d.cts → index-ygQLgXzT.d.cts} +6 -1
- package/dist/{index-BL7OautO.d.ts → index-ygQLgXzT.d.ts} +6 -1
- package/dist/index.cjs +206 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +209 -21
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +205 -21
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +207 -19
- package/dist/server/index.js.map +1 -1
- package/package.json +7 -7
package/dist/server/index.cjs
CHANGED
|
@@ -39,7 +39,7 @@ module.exports = __toCommonJS(server_exports);
|
|
|
39
39
|
// src/server/server.ts
|
|
40
40
|
var import_node_http2 = require("http");
|
|
41
41
|
var import_promises9 = require("fs/promises");
|
|
42
|
-
var
|
|
42
|
+
var import_node_path10 = require("path");
|
|
43
43
|
var import_node_os2 = require("os");
|
|
44
44
|
|
|
45
45
|
// src/server/routes.ts
|
|
@@ -1885,6 +1885,41 @@ function cors(res) {
|
|
|
1885
1885
|
function isPlainRecord(value) {
|
|
1886
1886
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1887
1887
|
}
|
|
1888
|
+
function getConfiguredAuthStateDir(config) {
|
|
1889
|
+
const services = isPlainRecord(config.services) ? config.services : void 0;
|
|
1890
|
+
const authState = services && isPlainRecord(services.authState) ? services.authState : void 0;
|
|
1891
|
+
return typeof authState?.dir === "string" ? authState.dir : void 0;
|
|
1892
|
+
}
|
|
1893
|
+
function getSessionTargetNameForAuthState(session) {
|
|
1894
|
+
if (!session || typeof session.getState !== "function") return "selected target";
|
|
1895
|
+
try {
|
|
1896
|
+
const state = session.getState();
|
|
1897
|
+
if (isPlainRecord(state) && typeof state.targetName === "string" && state.targetName.trim().length > 0) {
|
|
1898
|
+
return state.targetName.trim();
|
|
1899
|
+
}
|
|
1900
|
+
} catch {
|
|
1901
|
+
}
|
|
1902
|
+
return "selected target";
|
|
1903
|
+
}
|
|
1904
|
+
function buildAuthStateSaveErrorMessage(stateName, targetName, error) {
|
|
1905
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
1906
|
+
if (/already exists/i.test(raw)) {
|
|
1907
|
+
return {
|
|
1908
|
+
status: 409,
|
|
1909
|
+
message: `Auth state "${stateName}" for target "${targetName}" already exists. Use replace=true to replace it.`
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
if (/web Live Mode|not ready|executing|busy/i.test(raw)) {
|
|
1913
|
+
return {
|
|
1914
|
+
status: 409,
|
|
1915
|
+
message: `Could not save auth state "${stateName}" for target "${targetName}".`
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1918
|
+
return {
|
|
1919
|
+
status: 500,
|
|
1920
|
+
message: `Could not save auth state "${stateName}" for target "${targetName}".`
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1888
1923
|
function isDashboardProductEventName(value) {
|
|
1889
1924
|
return typeof value === "string" && DASHBOARD_PRODUCT_EVENT_NAME_SET.has(value);
|
|
1890
1925
|
}
|
|
@@ -2284,7 +2319,7 @@ function sanitizeSecretsFileMetadata(value) {
|
|
|
2284
2319
|
};
|
|
2285
2320
|
}
|
|
2286
2321
|
function sanitizeArtifactPayloadForResponse(payload) {
|
|
2287
|
-
const sanitized = sanitizeSecretTemplates(payload);
|
|
2322
|
+
const sanitized = (0, import_agent_qa_core5.redactAuthStateValue)(sanitizeSecretTemplates(payload));
|
|
2288
2323
|
if (!isRecord(sanitized)) return payload;
|
|
2289
2324
|
const config = sanitized.config;
|
|
2290
2325
|
if (!isRecord(config) || !("secretsFile" in config)) return sanitized;
|
|
@@ -2303,6 +2338,9 @@ function sanitizeArtifactForResponse(artifact) {
|
|
|
2303
2338
|
payload: sanitizeArtifactPayloadForResponse(artifact.payload)
|
|
2304
2339
|
};
|
|
2305
2340
|
}
|
|
2341
|
+
function sanitizeAuthStateForResponse(value) {
|
|
2342
|
+
return (0, import_agent_qa_core5.redactAuthStateValue)(value);
|
|
2343
|
+
}
|
|
2306
2344
|
async function normalizeDashboardWorkspacePath(filePath, workspacePaths, kind, requireExisting = true) {
|
|
2307
2345
|
if (!workspacePaths) {
|
|
2308
2346
|
throw new Error("Workspace path resolution is required for dashboard-triggered runs");
|
|
@@ -2527,6 +2565,28 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2527
2565
|
}
|
|
2528
2566
|
const url = parseUrl(req);
|
|
2529
2567
|
const path = url.pathname;
|
|
2568
|
+
if (path === "/api/auth-states" && req.method === "GET") {
|
|
2569
|
+
if (!configManager || !deps.configPath) {
|
|
2570
|
+
json(res, { error: "Auth-state metadata not available" }, 503);
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
;
|
|
2574
|
+
(async () => {
|
|
2575
|
+
try {
|
|
2576
|
+
const config = await configManager.read();
|
|
2577
|
+
const targetName = url.searchParams.get("target") ?? void 0;
|
|
2578
|
+
const authStates = await (0, import_agent_qa_core5.listAuthStateMetadata)({
|
|
2579
|
+
configDir: (0, import_node_path5.dirname)((0, import_node_path5.resolve)(deps.configPath)),
|
|
2580
|
+
authStateDir: getConfiguredAuthStateDir(config),
|
|
2581
|
+
targetName
|
|
2582
|
+
});
|
|
2583
|
+
json(res, { authStates });
|
|
2584
|
+
} catch {
|
|
2585
|
+
json(res, { error: "Could not list auth states." }, 500);
|
|
2586
|
+
}
|
|
2587
|
+
})();
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2530
2590
|
if (path === "/api/analytics/events" && req.method === "POST") {
|
|
2531
2591
|
readJsonBody(req).then((body) => {
|
|
2532
2592
|
if (!isPlainRecord(body) || !isDashboardProductEventName(body.name) || Object.prototype.hasOwnProperty.call(body, "properties") && body.properties !== void 0 && !isPlainRecord(body.properties)) {
|
|
@@ -2640,7 +2700,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2640
2700
|
return;
|
|
2641
2701
|
}
|
|
2642
2702
|
const bundle = db.getRunArtifactBundle(runId);
|
|
2643
|
-
json(res, {
|
|
2703
|
+
json(res, sanitizeAuthStateForResponse({
|
|
2644
2704
|
run,
|
|
2645
2705
|
artifact: sanitizeArtifactForResponse(bundle.artifact),
|
|
2646
2706
|
children: bundle.children.map((child) => ({
|
|
@@ -2648,7 +2708,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2648
2708
|
artifact: sanitizeArtifactForResponse(child.artifact)
|
|
2649
2709
|
})),
|
|
2650
2710
|
missingSections: getArtifactMissingSections(bundle.artifact)
|
|
2651
|
-
});
|
|
2711
|
+
}));
|
|
2652
2712
|
return;
|
|
2653
2713
|
}
|
|
2654
2714
|
if (path.startsWith("/api/runs/") && path.endsWith("/accessibility") && req.method === "GET") {
|
|
@@ -2674,7 +2734,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2674
2734
|
const stepOrder = parseInt(stepOrderStr, 10);
|
|
2675
2735
|
const trace = db.getReasoningTrace(runId, stepOrder);
|
|
2676
2736
|
if (trace) {
|
|
2677
|
-
json(res, { trace });
|
|
2737
|
+
json(res, sanitizeAuthStateForResponse({ trace }));
|
|
2678
2738
|
return;
|
|
2679
2739
|
}
|
|
2680
2740
|
const steps = db.getSteps(runId);
|
|
@@ -2683,7 +2743,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2683
2743
|
notFound(res, "Step not found");
|
|
2684
2744
|
return;
|
|
2685
2745
|
}
|
|
2686
|
-
json(res, {
|
|
2746
|
+
json(res, sanitizeAuthStateForResponse({
|
|
2687
2747
|
trace: {
|
|
2688
2748
|
id: null,
|
|
2689
2749
|
stepId: step.id,
|
|
@@ -2704,7 +2764,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2704
2764
|
screenStateAfter: null,
|
|
2705
2765
|
createdAt: step.createdAt
|
|
2706
2766
|
}
|
|
2707
|
-
});
|
|
2767
|
+
}));
|
|
2708
2768
|
return;
|
|
2709
2769
|
}
|
|
2710
2770
|
if (path.startsWith("/api/runs/") && path.endsWith("/execution-logs") && req.method === "GET") {
|
|
@@ -2724,11 +2784,11 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2724
2784
|
for (const rid of allRunIds) {
|
|
2725
2785
|
allLogs.push(...db.getExecutionLogs({ runId: rid, stepId, type }));
|
|
2726
2786
|
}
|
|
2727
|
-
json(res, { logs: allLogs });
|
|
2787
|
+
json(res, sanitizeAuthStateForResponse({ logs: allLogs }));
|
|
2728
2788
|
return;
|
|
2729
2789
|
}
|
|
2730
2790
|
const logs = db.getExecutionLogs({ runId: id, stepId, type });
|
|
2731
|
-
json(res, { logs });
|
|
2791
|
+
json(res, sanitizeAuthStateForResponse({ logs }));
|
|
2732
2792
|
return;
|
|
2733
2793
|
}
|
|
2734
2794
|
if (path.startsWith("/api/runs/") && path.endsWith("/logs") && req.method === "GET") {
|
|
@@ -2745,7 +2805,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2745
2805
|
const limit = url.searchParams.has("limit") ? parseInt(url.searchParams.get("limit"), 10) : 500;
|
|
2746
2806
|
const offset = url.searchParams.has("offset") ? parseInt(url.searchParams.get("offset"), 10) : 0;
|
|
2747
2807
|
const logs = db.getLogs({ runId: id, stepId, level, source, limit, offset });
|
|
2748
|
-
json(res, { logs, total: logs.length });
|
|
2808
|
+
json(res, sanitizeAuthStateForResponse({ logs, total: logs.length }));
|
|
2749
2809
|
return;
|
|
2750
2810
|
}
|
|
2751
2811
|
if (path.startsWith("/api/runs/") && path.endsWith("/steps") && req.method === "GET") {
|
|
@@ -2757,7 +2817,7 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2757
2817
|
return;
|
|
2758
2818
|
}
|
|
2759
2819
|
const steps = db.getSteps(id);
|
|
2760
|
-
json(res, { steps });
|
|
2820
|
+
json(res, sanitizeAuthStateForResponse({ steps }));
|
|
2761
2821
|
return;
|
|
2762
2822
|
}
|
|
2763
2823
|
if (path.startsWith("/api/runs/") && path.endsWith("/cancel") && req.method === "POST") {
|
|
@@ -2831,9 +2891,9 @@ function createRouter(dbOrDeps, artifactsDir) {
|
|
|
2831
2891
|
const attempts = db.getRunsByParent(id);
|
|
2832
2892
|
if (run.suiteId && !run.parentRunId) {
|
|
2833
2893
|
const tests = db.getRunsByParent(id);
|
|
2834
|
-
json(res, { run, steps, attempts, tests });
|
|
2894
|
+
json(res, sanitizeAuthStateForResponse({ run, steps, attempts, tests }));
|
|
2835
2895
|
} else {
|
|
2836
|
-
json(res, { run, steps, attempts });
|
|
2896
|
+
json(res, sanitizeAuthStateForResponse({ run, steps, attempts }));
|
|
2837
2897
|
}
|
|
2838
2898
|
return;
|
|
2839
2899
|
}
|
|
@@ -3623,6 +3683,11 @@ data: ${JSON.stringify(event)}
|
|
|
3623
3683
|
});
|
|
3624
3684
|
return;
|
|
3625
3685
|
}
|
|
3686
|
+
if (path === "/api/app-metadata" && req.method === "GET") {
|
|
3687
|
+
const version = (0, import_agent_qa_core5.getAgentQaVersion)().trim() || "0.0.0";
|
|
3688
|
+
json(res, { version });
|
|
3689
|
+
return;
|
|
3690
|
+
}
|
|
3626
3691
|
if (path === "/api/config/targets" && req.method === "GET") {
|
|
3627
3692
|
if (!configManager) {
|
|
3628
3693
|
json(res, { error: "Config management not available" }, 501);
|
|
@@ -4441,7 +4506,7 @@ data: ${JSON.stringify(event)}
|
|
|
4441
4506
|
const networkLogs = summarizeHookNetworkLogs(
|
|
4442
4507
|
result.networkLogs
|
|
4443
4508
|
);
|
|
4444
|
-
json(res, {
|
|
4509
|
+
json(res, sanitizeAuthStateForResponse({
|
|
4445
4510
|
success: result.success,
|
|
4446
4511
|
status: result.success ? "passed" : "failed",
|
|
4447
4512
|
executedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -4459,9 +4524,9 @@ data: ${JSON.stringify(event)}
|
|
|
4459
4524
|
networkLogsAvailable: networkLogs.length > 0,
|
|
4460
4525
|
networkLogs
|
|
4461
4526
|
}
|
|
4462
|
-
});
|
|
4527
|
+
}));
|
|
4463
4528
|
} catch (err) {
|
|
4464
|
-
json(res, { error: err instanceof Error ? err.message : "Failed to run hook" }, 500);
|
|
4529
|
+
json(res, sanitizeAuthStateForResponse({ error: err instanceof Error ? err.message : "Failed to run hook" }), 500);
|
|
4465
4530
|
}
|
|
4466
4531
|
}).catch(() => json(res, { error: "Invalid request body" }, 400));
|
|
4467
4532
|
return;
|
|
@@ -4710,6 +4775,45 @@ data: ${JSON.stringify(event)}
|
|
|
4710
4775
|
})();
|
|
4711
4776
|
return;
|
|
4712
4777
|
}
|
|
4778
|
+
const liveEditorAuthStateMatch = path.match(/^\/api\/live-editor\/sessions\/([^/]+)\/auth-state$/);
|
|
4779
|
+
if (liveEditorAuthStateMatch && req.method === "POST") {
|
|
4780
|
+
if (!sessionManager) {
|
|
4781
|
+
json(res, { error: "Live editor not available" }, 503);
|
|
4782
|
+
return;
|
|
4783
|
+
}
|
|
4784
|
+
;
|
|
4785
|
+
(async () => {
|
|
4786
|
+
let stateName = "";
|
|
4787
|
+
let session;
|
|
4788
|
+
try {
|
|
4789
|
+
const body = await readJsonBody(req);
|
|
4790
|
+
const parsedName = import_agent_qa_core5.AuthStateNameSchema.safeParse(typeof body?.name === "string" ? body.name : "");
|
|
4791
|
+
if (!parsedName.success) {
|
|
4792
|
+
json(res, { error: "Auth state name must be a lowercase slug." }, 400);
|
|
4793
|
+
return;
|
|
4794
|
+
}
|
|
4795
|
+
stateName = parsedName.data;
|
|
4796
|
+
session = sessionManager.getSession(decodeURIComponent(liveEditorAuthStateMatch[1]));
|
|
4797
|
+
if (!session) {
|
|
4798
|
+
notFound(res, "Session not found");
|
|
4799
|
+
return;
|
|
4800
|
+
}
|
|
4801
|
+
if (typeof session.captureWebAuthState !== "function") {
|
|
4802
|
+
json(res, {
|
|
4803
|
+
error: `Could not save auth state "${stateName}" for target "${getSessionTargetNameForAuthState(session)}".`
|
|
4804
|
+
}, 500);
|
|
4805
|
+
return;
|
|
4806
|
+
}
|
|
4807
|
+
const authState = await session.captureWebAuthState(stateName, { replace: body?.replace === true });
|
|
4808
|
+
json(res, { authState });
|
|
4809
|
+
} catch (err) {
|
|
4810
|
+
const targetName = getSessionTargetNameForAuthState(session);
|
|
4811
|
+
const response = buildAuthStateSaveErrorMessage(stateName || "unknown", targetName, err);
|
|
4812
|
+
json(res, { error: response.message }, response.status);
|
|
4813
|
+
}
|
|
4814
|
+
})();
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4713
4817
|
if (path === "/api/live-editor/sessions" && req.method === "POST") {
|
|
4714
4818
|
if (!sessionManager) {
|
|
4715
4819
|
json(res, { error: "Live editor not available" }, 503);
|
|
@@ -5914,6 +6018,7 @@ var import_node_crypto3 = require("crypto");
|
|
|
5914
6018
|
|
|
5915
6019
|
// src/live-editor/live-session.ts
|
|
5916
6020
|
var import_node_crypto2 = require("crypto");
|
|
6021
|
+
var import_node_path9 = require("path");
|
|
5917
6022
|
var import_agent_qa_core9 = require("@vostride/agent-qa-core");
|
|
5918
6023
|
|
|
5919
6024
|
// src/live-editor/mobile-bootstrap.ts
|
|
@@ -6065,6 +6170,26 @@ function coerceRunJSResult(value) {
|
|
|
6065
6170
|
}
|
|
6066
6171
|
return JSON.stringify(value);
|
|
6067
6172
|
}
|
|
6173
|
+
function getWebStorageStateContext(adapter) {
|
|
6174
|
+
if (!adapter || !("getPage" in adapter)) return null;
|
|
6175
|
+
const page = adapter.getPage?.();
|
|
6176
|
+
if (!page || typeof page !== "object") return null;
|
|
6177
|
+
const contextFactory = page.context;
|
|
6178
|
+
if (typeof contextFactory !== "function") return null;
|
|
6179
|
+
const context = contextFactory.call(page);
|
|
6180
|
+
if (!context || typeof context !== "object") return null;
|
|
6181
|
+
const storageState = context.storageState;
|
|
6182
|
+
if (typeof storageState !== "function") return null;
|
|
6183
|
+
return context;
|
|
6184
|
+
}
|
|
6185
|
+
function getConfiguredAuthStateDir2(config) {
|
|
6186
|
+
const services = config.services;
|
|
6187
|
+
if (!services || typeof services !== "object") return void 0;
|
|
6188
|
+
const authState = services.authState;
|
|
6189
|
+
if (!authState || typeof authState !== "object") return void 0;
|
|
6190
|
+
const dir = authState.dir;
|
|
6191
|
+
return typeof dir === "string" ? dir : void 0;
|
|
6192
|
+
}
|
|
6068
6193
|
function toLiveSubActionData(result) {
|
|
6069
6194
|
return result.trace?.subActions?.map((subAction) => ({
|
|
6070
6195
|
index: subAction.index,
|
|
@@ -6142,6 +6267,7 @@ var LiveSession = class {
|
|
|
6142
6267
|
previousSteps = [];
|
|
6143
6268
|
currentStep = null;
|
|
6144
6269
|
platform = "web";
|
|
6270
|
+
targetName = null;
|
|
6145
6271
|
currentUrl = null;
|
|
6146
6272
|
executing = false;
|
|
6147
6273
|
idleTimer = null;
|
|
@@ -6179,7 +6305,7 @@ var LiveSession = class {
|
|
|
6179
6305
|
this.pendingMessages.push(message);
|
|
6180
6306
|
}
|
|
6181
6307
|
redact(value) {
|
|
6182
|
-
return (0, import_agent_qa_core9.
|
|
6308
|
+
return (0, import_agent_qa_core9.redactAuthStateValue)(value, { secretRedactor: this.secretRedactor });
|
|
6183
6309
|
}
|
|
6184
6310
|
resolveSecrets(value) {
|
|
6185
6311
|
return (0, import_agent_qa_core9.resolveSecretTemplatesInValue)(value, this.secretStore);
|
|
@@ -6409,6 +6535,7 @@ var LiveSession = class {
|
|
|
6409
6535
|
}
|
|
6410
6536
|
async initialize(config) {
|
|
6411
6537
|
this.platform = config.platform;
|
|
6538
|
+
this.targetName = typeof config.targetName === "string" && config.targetName.trim().length > 0 ? config.targetName.trim() : null;
|
|
6412
6539
|
this._modelName = config.llmConfig.model ?? "unknown";
|
|
6413
6540
|
this.variableStore = new import_agent_qa_core9.VariableStore();
|
|
6414
6541
|
this.secretStore = config.secretStore;
|
|
@@ -6899,6 +7026,62 @@ ${errorLines.join("\n")}`;
|
|
|
6899
7026
|
this.messageSink = originalSink;
|
|
6900
7027
|
}
|
|
6901
7028
|
}
|
|
7029
|
+
async captureWebAuthState(name, options = {}) {
|
|
7030
|
+
if (this.platform !== "web") {
|
|
7031
|
+
throw new Error("Auth-state capture is only available for web Live Mode sessions.");
|
|
7032
|
+
}
|
|
7033
|
+
if (!this.readyForInteraction || !this.adapter) {
|
|
7034
|
+
throw new Error(this.terminalError ?? "Live session is not ready for auth-state capture.");
|
|
7035
|
+
}
|
|
7036
|
+
if (this.adapter.platform !== "web") {
|
|
7037
|
+
throw new Error("Auth-state capture is only available for web Live Mode sessions.");
|
|
7038
|
+
}
|
|
7039
|
+
if (this.executing) {
|
|
7040
|
+
throw new Error("Cannot save auth state while the Live Mode session is executing.");
|
|
7041
|
+
}
|
|
7042
|
+
if (!this.targetName) {
|
|
7043
|
+
throw new Error("Cannot save auth state because this Live Mode session has no configured target.");
|
|
7044
|
+
}
|
|
7045
|
+
if (!this.deps.configManager || !this.deps.configPath) {
|
|
7046
|
+
throw new Error("Cannot save auth state because workspace config is unavailable.");
|
|
7047
|
+
}
|
|
7048
|
+
const context = getWebStorageStateContext(this.adapter);
|
|
7049
|
+
if (!context) {
|
|
7050
|
+
throw new Error("Cannot save auth state because the active browser context is unavailable.");
|
|
7051
|
+
}
|
|
7052
|
+
const config = await this.deps.configManager.read();
|
|
7053
|
+
const authStateDir = getConfiguredAuthStateDir2(config);
|
|
7054
|
+
const paths = (0, import_agent_qa_core9.resolveAuthStatePaths)({
|
|
7055
|
+
configDir: (0, import_node_path9.dirname)((0, import_node_path9.resolve)(this.deps.configPath)),
|
|
7056
|
+
authStateDir,
|
|
7057
|
+
targetName: this.targetName,
|
|
7058
|
+
stateName: name,
|
|
7059
|
+
target: { platform: "web" }
|
|
7060
|
+
});
|
|
7061
|
+
let existing = null;
|
|
7062
|
+
try {
|
|
7063
|
+
existing = await (0, import_agent_qa_core9.readAuthStateMetadata)(paths);
|
|
7064
|
+
} catch {
|
|
7065
|
+
existing = null;
|
|
7066
|
+
}
|
|
7067
|
+
if (existing && options.replace !== true) {
|
|
7068
|
+
throw new Error(`Auth state "${paths.stateName}" for target "${paths.targetName}" already exists. Use replace=true to replace it.`);
|
|
7069
|
+
}
|
|
7070
|
+
const payload = await context.storageState({ indexedDB: true });
|
|
7071
|
+
const metadata = {
|
|
7072
|
+
version: import_agent_qa_core9.AUTH_STATE_SCHEMA_VERSION,
|
|
7073
|
+
kind: "web",
|
|
7074
|
+
target: paths.targetName,
|
|
7075
|
+
name: paths.stateName,
|
|
7076
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7077
|
+
};
|
|
7078
|
+
try {
|
|
7079
|
+
await (0, import_agent_qa_core9.writeAuthStateFiles)(paths, { payload, metadata });
|
|
7080
|
+
} catch {
|
|
7081
|
+
throw new Error(`Could not save auth state "${paths.stateName}" for target "${paths.targetName}".`);
|
|
7082
|
+
}
|
|
7083
|
+
return metadata;
|
|
7084
|
+
}
|
|
6902
7085
|
cancelStep() {
|
|
6903
7086
|
this.abortController?.abort();
|
|
6904
7087
|
}
|
|
@@ -6959,6 +7142,7 @@ ${errorLines.join("\n")}`;
|
|
|
6959
7142
|
return {
|
|
6960
7143
|
sessionId: this.sessionId,
|
|
6961
7144
|
platform: this.adapter?.platform ?? this.platform,
|
|
7145
|
+
targetName: this.targetName,
|
|
6962
7146
|
status: this.status === "terminated" ? "idle" : this.status === "executing" ? "executing" : this.status,
|
|
6963
7147
|
currentStep: this.currentStep,
|
|
6964
7148
|
currentUrl: this.currentUrl,
|
|
@@ -7437,7 +7621,7 @@ function isAnalyticsPrivacyEnabled(config) {
|
|
|
7437
7621
|
}
|
|
7438
7622
|
async function startServer(opts) {
|
|
7439
7623
|
const { db, port = 3470, uiDir, artifactsDir, workspacePaths, configPath, mcp, llmConfig, authFetch } = opts;
|
|
7440
|
-
const resolvedConfigPath = configPath ?? (0,
|
|
7624
|
+
const resolvedConfigPath = configPath ?? (0, import_node_path10.resolve)("agent-qa.config.yaml");
|
|
7441
7625
|
const configManager = new ConfigManager(resolvedConfigPath);
|
|
7442
7626
|
const config = await configManager.read().catch(() => ({}));
|
|
7443
7627
|
const concurrency = typeof config.concurrency === "number" ? config.concurrency : (0, import_node_os2.cpus)().length;
|
|
@@ -7757,12 +7941,12 @@ async function startServer(opts) {
|
|
|
7757
7941
|
return;
|
|
7758
7942
|
}
|
|
7759
7943
|
if (uiDir) {
|
|
7760
|
-
const filePath = path === "/" ? (0,
|
|
7944
|
+
const filePath = path === "/" ? (0, import_node_path10.join)(uiDir, "index.html") : (0, import_node_path10.join)(uiDir, path);
|
|
7761
7945
|
try {
|
|
7762
7946
|
const fileStat = await (0, import_promises9.stat)(filePath);
|
|
7763
7947
|
if (fileStat.isFile()) {
|
|
7764
7948
|
const content = await (0, import_promises9.readFile)(filePath);
|
|
7765
|
-
const ext = (0,
|
|
7949
|
+
const ext = (0, import_node_path10.extname)(filePath);
|
|
7766
7950
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
7767
7951
|
res.writeHead(200, {
|
|
7768
7952
|
"Content-Type": contentType,
|
|
@@ -7775,7 +7959,7 @@ async function startServer(opts) {
|
|
|
7775
7959
|
} catch {
|
|
7776
7960
|
}
|
|
7777
7961
|
try {
|
|
7778
|
-
const indexPath = (0,
|
|
7962
|
+
const indexPath = (0, import_node_path10.join)(uiDir, "index.html");
|
|
7779
7963
|
const content = await (0, import_promises9.readFile)(indexPath);
|
|
7780
7964
|
res.writeHead(200, {
|
|
7781
7965
|
"Content-Type": "text/html",
|