@fasttest-ai/qa-agent 0.1.3 → 0.3.0
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/bin/qa-agent-ci.js +3 -0
- package/dist/actions.d.ts +3 -0
- package/dist/actions.js +38 -4
- package/dist/actions.js.map +1 -1
- package/dist/browser.d.ts +30 -0
- package/dist/browser.js +120 -6
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +182 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud.d.ts +134 -6
- package/dist/cloud.js +150 -21
- package/dist/cloud.js.map +1 -1
- package/dist/config.d.ts +21 -0
- package/dist/config.js +49 -0
- package/dist/config.js.map +1 -0
- package/dist/healer.d.ts +1 -1
- package/dist/healer.js +56 -68
- package/dist/healer.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +893 -54
- package/dist/index.js.map +1 -1
- package/dist/runner.d.ts +3 -0
- package/dist/runner.js +245 -19
- package/dist/runner.js.map +1 -1
- package/dist/variables.d.ts +30 -0
- package/dist/variables.js +104 -0
- package/dist/variables.js.map +1 -0
- package/package.json +8 -4
package/dist/cloud.d.ts
CHANGED
|
@@ -5,6 +5,18 @@ export interface CloudClientOptions {
|
|
|
5
5
|
apiKey: string;
|
|
6
6
|
baseUrl?: string;
|
|
7
7
|
}
|
|
8
|
+
export interface DeviceCodeResponse {
|
|
9
|
+
code: string;
|
|
10
|
+
poll_token: string;
|
|
11
|
+
expires_in: number;
|
|
12
|
+
verification_url: string;
|
|
13
|
+
}
|
|
14
|
+
export interface DeviceCodeStatusResponse {
|
|
15
|
+
status: "pending" | "completed" | "expired";
|
|
16
|
+
api_key?: string;
|
|
17
|
+
org_name?: string;
|
|
18
|
+
org_slug?: string;
|
|
19
|
+
}
|
|
8
20
|
export interface RunResponse {
|
|
9
21
|
execution_id: string;
|
|
10
22
|
status: string;
|
|
@@ -18,6 +30,7 @@ export interface TestCasePayload {
|
|
|
18
30
|
assertions: TestAssertion[];
|
|
19
31
|
test_data: Record<string, unknown>[];
|
|
20
32
|
timeout_seconds: number;
|
|
33
|
+
retry_count: number;
|
|
21
34
|
}
|
|
22
35
|
export interface TestStep {
|
|
23
36
|
action: string;
|
|
@@ -31,6 +44,9 @@ export interface TestStep {
|
|
|
31
44
|
key?: string;
|
|
32
45
|
file_paths?: string[];
|
|
33
46
|
expression?: string;
|
|
47
|
+
target?: string;
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
34
50
|
type?: string;
|
|
35
51
|
text?: string;
|
|
36
52
|
count?: number;
|
|
@@ -51,6 +67,16 @@ export declare class CloudClient {
|
|
|
51
67
|
private apiKey;
|
|
52
68
|
private baseUrl;
|
|
53
69
|
constructor(options: CloudClientOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Request a device code for browser-based authentication.
|
|
72
|
+
* Unauthenticated — no API key needed.
|
|
73
|
+
*/
|
|
74
|
+
static requestDeviceCode(baseUrl: string): Promise<DeviceCodeResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* Poll for device code status. Returns when completed or expired.
|
|
77
|
+
* Unauthenticated — uses the poll_token for identity.
|
|
78
|
+
*/
|
|
79
|
+
static pollDeviceCode(baseUrl: string, pollToken: string): Promise<DeviceCodeStatusResponse>;
|
|
54
80
|
private request;
|
|
55
81
|
get<T>(path: string): Promise<T>;
|
|
56
82
|
post<T>(path: string, body?: unknown): Promise<T>;
|
|
@@ -59,17 +85,85 @@ export declare class CloudClient {
|
|
|
59
85
|
}>;
|
|
60
86
|
getOrg(): Promise<Record<string, unknown>>;
|
|
61
87
|
listProjects(): Promise<Record<string, unknown>>;
|
|
88
|
+
/** Get-or-create a project by name. Returns project with id. */
|
|
89
|
+
resolveProject(name: string, baseUrl?: string): Promise<{
|
|
90
|
+
id: string;
|
|
91
|
+
name: string;
|
|
92
|
+
}>;
|
|
93
|
+
/** List all test suites across all projects for the org. */
|
|
94
|
+
listSuites(search?: string): Promise<Array<Record<string, unknown>>>;
|
|
95
|
+
/** Resolve a suite by name (case-insensitive). Returns the best match. */
|
|
96
|
+
resolveSuite(name: string, projectId?: string): Promise<{
|
|
97
|
+
id: string;
|
|
98
|
+
name: string;
|
|
99
|
+
}>;
|
|
100
|
+
/** Create a test suite under a project. */
|
|
101
|
+
createSuite(projectId: string, body: {
|
|
102
|
+
name: string;
|
|
103
|
+
description?: string;
|
|
104
|
+
test_type?: string;
|
|
105
|
+
auto_generated?: boolean;
|
|
106
|
+
tags?: string[];
|
|
107
|
+
}): Promise<{
|
|
108
|
+
id: string;
|
|
109
|
+
name: string;
|
|
110
|
+
}>;
|
|
111
|
+
/** Update an existing test suite. */
|
|
112
|
+
updateSuite(projectId: string, suiteId: string, body: {
|
|
113
|
+
name?: string;
|
|
114
|
+
description?: string;
|
|
115
|
+
tags?: string[];
|
|
116
|
+
}): Promise<{
|
|
117
|
+
id: string;
|
|
118
|
+
name: string;
|
|
119
|
+
}>;
|
|
120
|
+
/** Create a test case and link it to suite(s). */
|
|
121
|
+
createTestCase(body: {
|
|
122
|
+
name: string;
|
|
123
|
+
description?: string;
|
|
124
|
+
priority?: string;
|
|
125
|
+
steps: Array<Record<string, unknown>>;
|
|
126
|
+
assertions: Array<Record<string, unknown>>;
|
|
127
|
+
tags?: string[];
|
|
128
|
+
test_suite_ids: string[];
|
|
129
|
+
auto_generated?: boolean;
|
|
130
|
+
generated_by_agent?: boolean;
|
|
131
|
+
natural_language_source?: string;
|
|
132
|
+
}): Promise<{
|
|
133
|
+
id: string;
|
|
134
|
+
name: string;
|
|
135
|
+
}>;
|
|
136
|
+
/** Update an existing test case. */
|
|
137
|
+
updateTestCase(testCaseId: string, body: {
|
|
138
|
+
name?: string;
|
|
139
|
+
description?: string;
|
|
140
|
+
priority?: string;
|
|
141
|
+
steps?: Array<Record<string, unknown>>;
|
|
142
|
+
assertions?: Array<Record<string, unknown>>;
|
|
143
|
+
tags?: string[];
|
|
144
|
+
}): Promise<{
|
|
145
|
+
id: string;
|
|
146
|
+
name: string;
|
|
147
|
+
}>;
|
|
148
|
+
/** Get a suite with its test cases. */
|
|
149
|
+
getSuiteWithCases(projectId: string, suiteId: string): Promise<{
|
|
150
|
+
id: string;
|
|
151
|
+
name: string;
|
|
152
|
+
description?: string;
|
|
153
|
+
test_cases: Array<{
|
|
154
|
+
id: string;
|
|
155
|
+
name: string;
|
|
156
|
+
steps: Array<Record<string, unknown>>;
|
|
157
|
+
assertions: Array<Record<string, unknown>>;
|
|
158
|
+
}>;
|
|
159
|
+
}>;
|
|
160
|
+
/** @deprecated Cloud exploration endpoints removed. Exploration runs via local skill. */
|
|
62
161
|
startExploration(body: {
|
|
63
162
|
url: string;
|
|
64
163
|
max_pages?: number;
|
|
65
164
|
focus?: string;
|
|
165
|
+
project_id?: string;
|
|
66
166
|
}): Promise<Record<string, unknown>>;
|
|
67
|
-
startConversation(body: {
|
|
68
|
-
description: string;
|
|
69
|
-
url?: string;
|
|
70
|
-
}): Promise<Record<string, unknown>>;
|
|
71
|
-
answerConversation(sessionId: string, answers: string): Promise<Record<string, unknown>>;
|
|
72
|
-
approveConversation(sessionId: string, exclude?: number[]): Promise<Record<string, unknown>>;
|
|
73
167
|
/** Start a test run — returns execution_id + test cases to execute locally. */
|
|
74
168
|
startRun(body: {
|
|
75
169
|
suite_id: string;
|
|
@@ -86,6 +180,15 @@ export declare class CloudClient {
|
|
|
86
180
|
screenshots?: string[];
|
|
87
181
|
console_logs?: string[];
|
|
88
182
|
step_results?: Record<string, unknown>[];
|
|
183
|
+
retry_attempt?: number;
|
|
184
|
+
network_summary?: Array<{
|
|
185
|
+
url: string;
|
|
186
|
+
method: string;
|
|
187
|
+
status: number;
|
|
188
|
+
duration: number;
|
|
189
|
+
mimeType: string;
|
|
190
|
+
responseSize: number;
|
|
191
|
+
}>;
|
|
89
192
|
}): Promise<{
|
|
90
193
|
status: string;
|
|
91
194
|
}>;
|
|
@@ -95,6 +198,12 @@ export declare class CloudClient {
|
|
|
95
198
|
cancelExecution(executionId: string): Promise<Record<string, unknown>>;
|
|
96
199
|
/** Get execution status. */
|
|
97
200
|
getExecutionStatus(executionId: string): Promise<Record<string, unknown>>;
|
|
201
|
+
/** Notify that a test case is about to start executing. Non-fatal. */
|
|
202
|
+
notifyTestStarted(executionId: string, testCaseId: string, testCaseName: string): Promise<void>;
|
|
203
|
+
/** Notify that selector healing is being attempted. Non-fatal. */
|
|
204
|
+
notifyHealingStarted(executionId: string, testCaseId: string, originalSelector: string): Promise<void>;
|
|
205
|
+
/** Lightweight check for control signals (pause/cancel) from the dashboard. */
|
|
206
|
+
checkControlStatus(executionId: string): Promise<string>;
|
|
98
207
|
/** Set the org's GitHub token. */
|
|
99
208
|
setGithubToken(token: string): Promise<Record<string, unknown>>;
|
|
100
209
|
/** Post test results as a PR comment. */
|
|
@@ -118,5 +227,24 @@ export declare class CloudClient {
|
|
|
118
227
|
strategy?: string;
|
|
119
228
|
confidence?: number;
|
|
120
229
|
}>;
|
|
230
|
+
flaky_retries?: Array<{
|
|
231
|
+
name?: string;
|
|
232
|
+
retry_attempts?: number;
|
|
233
|
+
}>;
|
|
234
|
+
}): Promise<Record<string, unknown>>;
|
|
235
|
+
/** Save a chaos report with adversarial findings. */
|
|
236
|
+
saveChaosReport(projectId: string | undefined, body: {
|
|
237
|
+
url: string;
|
|
238
|
+
findings: Array<{
|
|
239
|
+
severity: string;
|
|
240
|
+
category: string;
|
|
241
|
+
description: string;
|
|
242
|
+
reproduction_steps: string[];
|
|
243
|
+
console_errors?: string[];
|
|
244
|
+
}>;
|
|
121
245
|
}): Promise<Record<string, unknown>>;
|
|
246
|
+
/** List chaos reports for the org. */
|
|
247
|
+
listChaosReports(projectId?: string): Promise<Record<string, unknown>>;
|
|
248
|
+
/** Get a single chaos report. */
|
|
249
|
+
getChaosReport(reportId: string): Promise<Record<string, unknown>>;
|
|
122
250
|
}
|
package/dist/cloud.js
CHANGED
|
@@ -6,7 +6,33 @@ export class CloudClient {
|
|
|
6
6
|
baseUrl;
|
|
7
7
|
constructor(options) {
|
|
8
8
|
this.apiKey = options.apiKey;
|
|
9
|
-
this.baseUrl = (options.baseUrl ?? "https://api.
|
|
9
|
+
this.baseUrl = (options.baseUrl ?? "https://api.fasttest.ai").replace(/\/$/, "");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Request a device code for browser-based authentication.
|
|
13
|
+
* Unauthenticated — no API key needed.
|
|
14
|
+
*/
|
|
15
|
+
static async requestDeviceCode(baseUrl) {
|
|
16
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/auth/device-code`;
|
|
17
|
+
const resp = await fetch(url, { method: "POST" });
|
|
18
|
+
if (!resp.ok) {
|
|
19
|
+
const text = await resp.text();
|
|
20
|
+
throw new Error(`Device code request failed (${resp.status}): ${text}`);
|
|
21
|
+
}
|
|
22
|
+
return (await resp.json());
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Poll for device code status. Returns when completed or expired.
|
|
26
|
+
* Unauthenticated — uses the poll_token for identity.
|
|
27
|
+
*/
|
|
28
|
+
static async pollDeviceCode(baseUrl, pollToken) {
|
|
29
|
+
const url = `${baseUrl.replace(/\/$/, "")}/api/v1/auth/device-code/status?poll_token=${encodeURIComponent(pollToken)}`;
|
|
30
|
+
const resp = await fetch(url);
|
|
31
|
+
if (!resp.ok) {
|
|
32
|
+
const text = await resp.text();
|
|
33
|
+
throw new Error(`Device code poll failed (${resp.status}): ${text}`);
|
|
34
|
+
}
|
|
35
|
+
return (await resp.json());
|
|
10
36
|
}
|
|
11
37
|
async request(method, path, body) {
|
|
12
38
|
const url = `${this.baseUrl}/api/v1${path}`;
|
|
@@ -14,16 +40,40 @@ export class CloudClient {
|
|
|
14
40
|
"x-api-key": this.apiKey,
|
|
15
41
|
"Content-Type": "application/json",
|
|
16
42
|
};
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
43
|
+
const maxRetries = 2;
|
|
44
|
+
const baseDelay = 1000;
|
|
45
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
const timeoutId = setTimeout(() => controller.abort(), 30_000);
|
|
48
|
+
try {
|
|
49
|
+
const init = { method, headers, signal: controller.signal };
|
|
50
|
+
if (body !== undefined) {
|
|
51
|
+
init.body = JSON.stringify(body);
|
|
52
|
+
}
|
|
53
|
+
const resp = await fetch(url, init);
|
|
54
|
+
clearTimeout(timeoutId);
|
|
55
|
+
if (!resp.ok) {
|
|
56
|
+
const text = await resp.text();
|
|
57
|
+
if (resp.status >= 500 && attempt < maxRetries) {
|
|
58
|
+
await new Promise((r) => setTimeout(r, baseDelay * 2 ** attempt));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Cloud API ${method} ${path} → ${resp.status}: ${text}`);
|
|
62
|
+
}
|
|
63
|
+
return (await resp.json());
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
clearTimeout(timeoutId);
|
|
67
|
+
const isRetryable = err instanceof Error &&
|
|
68
|
+
(err.name === "AbortError" || err.message.includes("fetch failed"));
|
|
69
|
+
if (isRetryable && attempt < maxRetries) {
|
|
70
|
+
await new Promise((r) => setTimeout(r, baseDelay * 2 ** attempt));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
20
75
|
}
|
|
21
|
-
|
|
22
|
-
if (!resp.ok) {
|
|
23
|
-
const text = await resp.text();
|
|
24
|
-
throw new Error(`Cloud API ${method} ${path} → ${resp.status}: ${text}`);
|
|
25
|
-
}
|
|
26
|
-
return (await resp.json());
|
|
76
|
+
throw new Error(`Cloud API ${method} ${path}: max retries exceeded`);
|
|
27
77
|
}
|
|
28
78
|
async get(path) {
|
|
29
79
|
return this.request("GET", path);
|
|
@@ -45,20 +95,55 @@ export class CloudClient {
|
|
|
45
95
|
async listProjects() {
|
|
46
96
|
return this.get("/qa/projects/");
|
|
47
97
|
}
|
|
48
|
-
|
|
98
|
+
/** Get-or-create a project by name. Returns project with id. */
|
|
99
|
+
async resolveProject(name, baseUrl) {
|
|
100
|
+
const body = { name };
|
|
101
|
+
if (baseUrl)
|
|
102
|
+
body.base_url = baseUrl;
|
|
103
|
+
return this.post("/qa/projects/resolve", body);
|
|
104
|
+
}
|
|
105
|
+
// --- Suites ---
|
|
106
|
+
/** List all test suites across all projects for the org. */
|
|
107
|
+
async listSuites(search) {
|
|
108
|
+
const qs = search ? `?search=${encodeURIComponent(search)}` : "";
|
|
109
|
+
return this.get(`/qa/projects/suites/all${qs}`);
|
|
110
|
+
}
|
|
111
|
+
/** Resolve a suite by name (case-insensitive). Returns the best match. */
|
|
112
|
+
async resolveSuite(name, projectId) {
|
|
113
|
+
const body = { name };
|
|
114
|
+
if (projectId)
|
|
115
|
+
body.project_id = projectId;
|
|
116
|
+
return this.post("/qa/projects/suites/resolve", body);
|
|
117
|
+
}
|
|
118
|
+
// --- Suite + Test Case Management ---
|
|
119
|
+
/** Create a test suite under a project. */
|
|
120
|
+
async createSuite(projectId, body) {
|
|
121
|
+
return this.post(`/qa/projects/${projectId}/test-suites`, {
|
|
122
|
+
...body,
|
|
123
|
+
project_id: projectId,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/** Update an existing test suite. */
|
|
127
|
+
async updateSuite(projectId, suiteId, body) {
|
|
128
|
+
return this.request("PUT", `/qa/projects/${projectId}/test-suites/${suiteId}`, body);
|
|
129
|
+
}
|
|
130
|
+
/** Create a test case and link it to suite(s). */
|
|
131
|
+
async createTestCase(body) {
|
|
132
|
+
return this.post("/qa/test-cases/", body);
|
|
133
|
+
}
|
|
134
|
+
/** Update an existing test case. */
|
|
135
|
+
async updateTestCase(testCaseId, body) {
|
|
136
|
+
return this.request("PUT", `/qa/test-cases/${testCaseId}`, body);
|
|
137
|
+
}
|
|
138
|
+
/** Get a suite with its test cases. */
|
|
139
|
+
async getSuiteWithCases(projectId, suiteId) {
|
|
140
|
+
return this.get(`/qa/projects/${projectId}/suites/${suiteId}/details`);
|
|
141
|
+
}
|
|
142
|
+
// --- Exploration (DEPRECATED — cloud exploration endpoints no longer served) ---
|
|
143
|
+
/** @deprecated Cloud exploration endpoints removed. Exploration runs via local skill. */
|
|
49
144
|
async startExploration(body) {
|
|
50
145
|
return this.post("/explore/", body);
|
|
51
146
|
}
|
|
52
|
-
// --- Conversation (Phase 4) ---
|
|
53
|
-
async startConversation(body) {
|
|
54
|
-
return this.post("/conversation/start", body);
|
|
55
|
-
}
|
|
56
|
-
async answerConversation(sessionId, answers) {
|
|
57
|
-
return this.post(`/conversation/${sessionId}/answer`, { answers });
|
|
58
|
-
}
|
|
59
|
-
async approveConversation(sessionId, exclude) {
|
|
60
|
-
return this.post(`/conversation/${sessionId}/approve`, { exclude });
|
|
61
|
-
}
|
|
62
147
|
// --- Execution (Phase 3) ---
|
|
63
148
|
/** Start a test run — returns execution_id + test cases to execute locally. */
|
|
64
149
|
async startRun(body) {
|
|
@@ -80,6 +165,35 @@ export class CloudClient {
|
|
|
80
165
|
async getExecutionStatus(executionId) {
|
|
81
166
|
return this.get(`/qa/execution/executions/${executionId}`);
|
|
82
167
|
}
|
|
168
|
+
/** Notify that a test case is about to start executing. Non-fatal. */
|
|
169
|
+
async notifyTestStarted(executionId, testCaseId, testCaseName) {
|
|
170
|
+
try {
|
|
171
|
+
await this.post(`/qa/execution/executions/${executionId}/test-started`, {
|
|
172
|
+
test_case_id: testCaseId,
|
|
173
|
+
test_case_name: testCaseName,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Non-fatal — War Room will just miss the "running" indicator
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Notify that selector healing is being attempted. Non-fatal. */
|
|
181
|
+
async notifyHealingStarted(executionId, testCaseId, originalSelector) {
|
|
182
|
+
try {
|
|
183
|
+
await this.post(`/qa/execution/executions/${executionId}/healing-started`, {
|
|
184
|
+
test_case_id: testCaseId,
|
|
185
|
+
original_selector: originalSelector,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Non-fatal — War Room will just miss the "healing..." indicator
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Lightweight check for control signals (pause/cancel) from the dashboard. */
|
|
193
|
+
async checkControlStatus(executionId) {
|
|
194
|
+
const resp = await this.get(`/qa/execution/executions/${executionId}/control-status`);
|
|
195
|
+
return resp.status;
|
|
196
|
+
}
|
|
83
197
|
// --- GitHub (Phase 6) ---
|
|
84
198
|
/** Set the org's GitHub token. */
|
|
85
199
|
async setGithubToken(token) {
|
|
@@ -89,5 +203,20 @@ export class CloudClient {
|
|
|
89
203
|
async postPrComment(body) {
|
|
90
204
|
return this.post("/qa/github/pr-comment", body);
|
|
91
205
|
}
|
|
206
|
+
// --- Chaos (Break My App) ---
|
|
207
|
+
/** Save a chaos report with adversarial findings. */
|
|
208
|
+
async saveChaosReport(projectId, body) {
|
|
209
|
+
const qs = projectId ? `?project_id=${projectId}` : "";
|
|
210
|
+
return this.post(`/qa/chaos/reports${qs}`, body);
|
|
211
|
+
}
|
|
212
|
+
/** List chaos reports for the org. */
|
|
213
|
+
async listChaosReports(projectId) {
|
|
214
|
+
const qs = projectId ? `?project_id=${projectId}` : "";
|
|
215
|
+
return this.get(`/qa/chaos/reports${qs}`);
|
|
216
|
+
}
|
|
217
|
+
/** Get a single chaos report. */
|
|
218
|
+
async getChaosReport(reportId) {
|
|
219
|
+
return this.get(`/qa/chaos/reports/${reportId}`);
|
|
220
|
+
}
|
|
92
221
|
}
|
|
93
222
|
//# sourceMappingURL=cloud.js.map
|
package/dist/cloud.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud.js","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"cloud.js","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global config manager — reads/writes ~/.fasttest/config.json
|
|
3
|
+
* Stores API key and base URL so the MCP server can boot without CLI args.
|
|
4
|
+
* Falls back to legacy ~/.qa-agent/config.json for backward compatibility.
|
|
5
|
+
*/
|
|
6
|
+
declare const CONFIG_PATH: string;
|
|
7
|
+
export interface GlobalConfig {
|
|
8
|
+
api_key?: string;
|
|
9
|
+
base_url?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Load config from ~/.fasttest/config.json (or legacy ~/.qa-agent/config.json).
|
|
13
|
+
* Returns empty object if file doesn't exist or is malformed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadGlobalConfig(): GlobalConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Merge new values into ~/.fasttest/config.json and write with 0o600 permissions.
|
|
18
|
+
* Always writes to the new location (~/.fasttest/).
|
|
19
|
+
*/
|
|
20
|
+
export declare function saveGlobalConfig(updates: Partial<GlobalConfig>): void;
|
|
21
|
+
export { CONFIG_PATH };
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global config manager — reads/writes ~/.fasttest/config.json
|
|
3
|
+
* Stores API key and base URL so the MCP server can boot without CLI args.
|
|
4
|
+
* Falls back to legacy ~/.qa-agent/config.json for backward compatibility.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import * as os from "node:os";
|
|
9
|
+
const NEW_CONFIG_DIR = path.join(os.homedir(), ".fasttest");
|
|
10
|
+
const OLD_CONFIG_DIR = path.join(os.homedir(), ".qa-agent");
|
|
11
|
+
/** Resolve config dir: prefer ~/.fasttest/, fall back to ~/.qa-agent/ */
|
|
12
|
+
function resolveConfigDir() {
|
|
13
|
+
if (fs.existsSync(path.join(NEW_CONFIG_DIR, "config.json")))
|
|
14
|
+
return NEW_CONFIG_DIR;
|
|
15
|
+
if (fs.existsSync(path.join(OLD_CONFIG_DIR, "config.json")))
|
|
16
|
+
return OLD_CONFIG_DIR;
|
|
17
|
+
return NEW_CONFIG_DIR;
|
|
18
|
+
}
|
|
19
|
+
const CONFIG_DIR = resolveConfigDir();
|
|
20
|
+
const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
21
|
+
/**
|
|
22
|
+
* Load config from ~/.fasttest/config.json (or legacy ~/.qa-agent/config.json).
|
|
23
|
+
* Returns empty object if file doesn't exist or is malformed.
|
|
24
|
+
*/
|
|
25
|
+
export function loadGlobalConfig() {
|
|
26
|
+
if (!fs.existsSync(CONFIG_PATH))
|
|
27
|
+
return {};
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Merge new values into ~/.fasttest/config.json and write with 0o600 permissions.
|
|
37
|
+
* Always writes to the new location (~/.fasttest/).
|
|
38
|
+
*/
|
|
39
|
+
export function saveGlobalConfig(updates) {
|
|
40
|
+
const existing = loadGlobalConfig();
|
|
41
|
+
const merged = { ...existing, ...updates };
|
|
42
|
+
const saveDir = NEW_CONFIG_DIR;
|
|
43
|
+
const savePath = path.join(saveDir, "config.json");
|
|
44
|
+
fs.mkdirSync(saveDir, { recursive: true });
|
|
45
|
+
const content = JSON.stringify(merged, null, 2) + "\n";
|
|
46
|
+
fs.writeFileSync(savePath, content, { mode: 0o600 });
|
|
47
|
+
}
|
|
48
|
+
export { CONFIG_PATH };
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAC5D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAE5D,yEAAyE;AACzE,SAAS,gBAAgB;IACvB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QAAE,OAAO,cAAc,CAAC;IACnF,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;QAAE,OAAO,cAAc,CAAC;IACnF,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAOzD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAiB,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA8B;IAC7D,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,cAAc,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IACvD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/healer.d.ts
CHANGED
|
@@ -24,4 +24,4 @@ export interface HealResult {
|
|
|
24
24
|
* Attempt to heal a broken selector by trying 5 strategies in order.
|
|
25
25
|
* Returns the first working selector with its confidence score.
|
|
26
26
|
*/
|
|
27
|
-
export declare function healSelector(page: Page, cloud: CloudClient, originalSelector: string, failureType: string, errorMessage: string, pageUrl: string): Promise<HealResult>;
|
|
27
|
+
export declare function healSelector(page: Page, cloud: CloudClient | null, originalSelector: string, failureType: string, errorMessage: string, pageUrl: string): Promise<HealResult>;
|