@openqa/cli 1.3.4 → 2.0.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/README.md +1 -1
- package/dist/agent/brain/diff-analyzer.js +140 -0
- package/dist/agent/brain/diff-analyzer.js.map +1 -0
- package/dist/agent/brain/llm-cache.js +47 -0
- package/dist/agent/brain/llm-cache.js.map +1 -0
- package/dist/agent/brain/llm-resilience.js +252 -0
- package/dist/agent/brain/llm-resilience.js.map +1 -0
- package/dist/agent/config/index.js +588 -0
- package/dist/agent/config/index.js.map +1 -0
- package/dist/agent/coverage/index.js +74 -0
- package/dist/agent/coverage/index.js.map +1 -0
- package/dist/agent/export/index.js +158 -0
- package/dist/agent/export/index.js.map +1 -0
- package/dist/agent/index-v2.js +2795 -0
- package/dist/agent/index-v2.js.map +1 -0
- package/dist/agent/index.js +369 -105
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/logger.js +41 -0
- package/dist/agent/logger.js.map +1 -0
- package/dist/agent/metrics.js +39 -0
- package/dist/agent/metrics.js.map +1 -0
- package/dist/agent/notifications/index.js +106 -0
- package/dist/agent/notifications/index.js.map +1 -0
- package/dist/agent/openapi/spec.js +338 -0
- package/dist/agent/openapi/spec.js.map +1 -0
- package/dist/agent/tools/project-runner.js +481 -0
- package/dist/agent/tools/project-runner.js.map +1 -0
- package/dist/cli/config.html.js +454 -0
- package/dist/cli/daemon.js +7572 -0
- package/dist/cli/dashboard.html.js +1619 -0
- package/dist/cli/index.js +3492 -1622
- package/dist/cli/kanban.html.js +577 -0
- package/dist/cli/routes.js +895 -0
- package/dist/cli/routes.js.map +1 -0
- package/dist/cli/server.js +3469 -1630
- package/dist/database/index.js +485 -60
- package/dist/database/index.js.map +1 -1
- package/dist/database/sqlite.js +281 -0
- package/dist/database/sqlite.js.map +1 -0
- package/package.json +18 -5
package/dist/agent/index.js
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res) => function __init() {
|
|
3
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
// node_modules/tsup/assets/esm_shims.js
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
var init_esm_shims = __esm({
|
|
10
|
+
"node_modules/tsup/assets/esm_shims.js"() {
|
|
11
|
+
"use strict";
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// database/sqlite.ts
|
|
16
|
+
import Database from "better-sqlite3";
|
|
17
|
+
var init_sqlite = __esm({
|
|
18
|
+
"database/sqlite.ts"() {
|
|
19
|
+
"use strict";
|
|
20
|
+
init_esm_shims();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
1
24
|
// agent/index.ts
|
|
25
|
+
init_esm_shims();
|
|
2
26
|
import { ReActAgent as ReActAgent2 } from "@orka-js/agent";
|
|
3
27
|
import { OpenAIAdapter as OpenAIAdapter2 } from "@orka-js/openai";
|
|
4
28
|
import { AnthropicAdapter as AnthropicAdapter2 } from "@orka-js/anthropic";
|
|
@@ -7,13 +31,15 @@ import { Tracer } from "@orka-js/observability";
|
|
|
7
31
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
8
32
|
|
|
9
33
|
// database/index.ts
|
|
34
|
+
init_esm_shims();
|
|
35
|
+
init_sqlite();
|
|
10
36
|
import { Low } from "lowdb";
|
|
11
37
|
import { JSONFile } from "lowdb/node";
|
|
12
38
|
import { dirname } from "path";
|
|
13
|
-
import { fileURLToPath } from "url";
|
|
39
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14
40
|
import { mkdirSync } from "fs";
|
|
15
|
-
var
|
|
16
|
-
var
|
|
41
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
42
|
+
var __dirname2 = dirname(__filename2);
|
|
17
43
|
var OpenQADatabase = class {
|
|
18
44
|
constructor(dbPath = "./data/openqa.json") {
|
|
19
45
|
this.dbPath = dbPath;
|
|
@@ -29,7 +55,8 @@ var OpenQADatabase = class {
|
|
|
29
55
|
test_sessions: [],
|
|
30
56
|
actions: [],
|
|
31
57
|
bugs: [],
|
|
32
|
-
kanban_tickets: []
|
|
58
|
+
kanban_tickets: [],
|
|
59
|
+
users: []
|
|
33
60
|
});
|
|
34
61
|
this.db.read();
|
|
35
62
|
if (!this.db.data) {
|
|
@@ -38,7 +65,8 @@ var OpenQADatabase = class {
|
|
|
38
65
|
test_sessions: [],
|
|
39
66
|
actions: [],
|
|
40
67
|
bugs: [],
|
|
41
|
-
kanban_tickets: []
|
|
68
|
+
kanban_tickets: [],
|
|
69
|
+
users: []
|
|
42
70
|
};
|
|
43
71
|
this.db.write();
|
|
44
72
|
}
|
|
@@ -48,6 +76,12 @@ var OpenQADatabase = class {
|
|
|
48
76
|
this.initialize();
|
|
49
77
|
}
|
|
50
78
|
await this.db.read();
|
|
79
|
+
let migrated = false;
|
|
80
|
+
if (!this.db.data.users) {
|
|
81
|
+
this.db.data.users = [];
|
|
82
|
+
migrated = true;
|
|
83
|
+
}
|
|
84
|
+
if (migrated) await this.db.write();
|
|
51
85
|
}
|
|
52
86
|
async getConfig(key) {
|
|
53
87
|
await this.ensureInitialized();
|
|
@@ -171,85 +205,297 @@ var OpenQADatabase = class {
|
|
|
171
205
|
await this.ensureInitialized();
|
|
172
206
|
return this.db.data.kanban_tickets.filter((t) => t.column === column).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
173
207
|
}
|
|
208
|
+
async deleteKanbanTicket(id) {
|
|
209
|
+
await this.ensureInitialized();
|
|
210
|
+
const index = this.db.data.kanban_tickets.findIndex((t) => t.id === id);
|
|
211
|
+
if (index !== -1) {
|
|
212
|
+
this.db.data.kanban_tickets.splice(index, 1);
|
|
213
|
+
await this.db.write();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
174
216
|
async clearAllConfig() {
|
|
175
217
|
await this.ensureInitialized();
|
|
176
218
|
this.db.data.config = {};
|
|
177
219
|
await this.db.write();
|
|
178
220
|
}
|
|
179
|
-
// Get real data methods
|
|
221
|
+
// Get real data methods - connected to actual database records
|
|
180
222
|
async getActiveAgents() {
|
|
181
223
|
await this.ensureInitialized();
|
|
182
224
|
const sessions = await this.getRecentSessions(1);
|
|
183
225
|
const currentSession = sessions[0];
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
226
|
+
const isRunning = currentSession?.status === "running";
|
|
227
|
+
const totalActions = currentSession?.total_actions || 0;
|
|
228
|
+
const agents = [
|
|
229
|
+
{
|
|
230
|
+
name: "Main Agent",
|
|
231
|
+
status: isRunning ? "running" : "idle",
|
|
232
|
+
purpose: "Autonomous QA orchestration",
|
|
233
|
+
performance: totalActions > 0 ? Math.min(100, Math.round(totalActions / 100 * 100)) : 0,
|
|
234
|
+
tasks: totalActions
|
|
235
|
+
}
|
|
194
236
|
];
|
|
237
|
+
if (currentSession && totalActions > 0) {
|
|
238
|
+
const actions = await this.getSessionActions(currentSession.id);
|
|
239
|
+
const actionTypes = actions.reduce((acc, action) => {
|
|
240
|
+
const type = action.type || "unknown";
|
|
241
|
+
acc[type] = (acc[type] || 0) + 1;
|
|
242
|
+
return acc;
|
|
243
|
+
}, {});
|
|
244
|
+
if (actionTypes["navigate"] || actionTypes["click"] || actionTypes["screenshot"]) {
|
|
245
|
+
agents.push({
|
|
246
|
+
name: "Browser Specialist",
|
|
247
|
+
status: isRunning ? "running" : "idle",
|
|
248
|
+
purpose: "UI navigation and interaction",
|
|
249
|
+
performance: Math.round(((actionTypes["navigate"] || 0) + (actionTypes["click"] || 0)) / totalActions * 100),
|
|
250
|
+
tasks: (actionTypes["navigate"] || 0) + (actionTypes["click"] || 0)
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (actionTypes["api_call"] || actionTypes["request"]) {
|
|
254
|
+
agents.push({
|
|
255
|
+
name: "API Tester",
|
|
256
|
+
status: isRunning ? "running" : "idle",
|
|
257
|
+
purpose: "API endpoint testing",
|
|
258
|
+
performance: Math.round((actionTypes["api_call"] || actionTypes["request"] || 0) / totalActions * 100),
|
|
259
|
+
tasks: actionTypes["api_call"] || actionTypes["request"] || 0
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
if (actionTypes["auth"] || actionTypes["login"]) {
|
|
263
|
+
agents.push({
|
|
264
|
+
name: "Auth Specialist",
|
|
265
|
+
status: isRunning ? "running" : "idle",
|
|
266
|
+
purpose: "Authentication testing",
|
|
267
|
+
performance: Math.round((actionTypes["auth"] || actionTypes["login"] || 0) / totalActions * 100),
|
|
268
|
+
tasks: actionTypes["auth"] || actionTypes["login"] || 0
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return agents;
|
|
195
273
|
}
|
|
196
274
|
async getCurrentTasks() {
|
|
197
275
|
await this.ensureInitialized();
|
|
198
276
|
const sessions = await this.getRecentSessions(1);
|
|
199
277
|
const currentSession = sessions[0];
|
|
200
|
-
if (!currentSession
|
|
278
|
+
if (!currentSession) {
|
|
201
279
|
return [];
|
|
202
280
|
}
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
agent: ["Main Agent", "Browser Specialist", "API Tester", "UI Tester"][i % 4],
|
|
215
|
-
started_at: new Date(Date.now() - i * 10 * 60 * 1e3).toISOString(),
|
|
216
|
-
result: status === "completed" ? "Successfully completed task execution" : null
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
return tasks;
|
|
281
|
+
const actions = await this.getSessionActions(currentSession.id);
|
|
282
|
+
const recentActions = actions.slice(-10).reverse();
|
|
283
|
+
return recentActions.map((action, index) => ({
|
|
284
|
+
id: action.id,
|
|
285
|
+
name: action.type || "Unknown Action",
|
|
286
|
+
status: index === 0 && currentSession.status === "running" ? "running" : "completed",
|
|
287
|
+
progress: index === 0 && currentSession.status === "running" ? "65%" : "100%",
|
|
288
|
+
agent: "Main Agent",
|
|
289
|
+
started_at: action.timestamp,
|
|
290
|
+
result: action.output || action.description || "Completed"
|
|
291
|
+
}));
|
|
220
292
|
}
|
|
221
293
|
async getCurrentIssues() {
|
|
222
294
|
await this.ensureInitialized();
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
295
|
+
const bugs = await this.getAllBugs();
|
|
296
|
+
return bugs.slice(0, 10).map((bug) => ({
|
|
297
|
+
id: bug.id,
|
|
298
|
+
title: bug.title,
|
|
299
|
+
description: bug.description,
|
|
300
|
+
severity: bug.severity || "medium",
|
|
301
|
+
status: bug.status || "open",
|
|
302
|
+
discovered_at: bug.created_at,
|
|
303
|
+
agent: "Main Agent"
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
async pruneOldSessions(maxAgeDays) {
|
|
307
|
+
await this.ensureInitialized();
|
|
308
|
+
const cutoff = new Date(Date.now() - maxAgeDays * 864e5).toISOString();
|
|
309
|
+
const oldSessions = this.db.data.test_sessions.filter((s) => s.started_at < cutoff);
|
|
310
|
+
const oldSessionIds = new Set(oldSessions.map((s) => s.id));
|
|
311
|
+
const actionsBefore = this.db.data.actions.length;
|
|
312
|
+
this.db.data.actions = this.db.data.actions.filter((a) => !oldSessionIds.has(a.session_id));
|
|
313
|
+
const actionsRemoved = actionsBefore - this.db.data.actions.length;
|
|
314
|
+
this.db.data.test_sessions = this.db.data.test_sessions.filter((s) => s.started_at >= cutoff);
|
|
315
|
+
await this.db.write();
|
|
316
|
+
return { sessionsRemoved: oldSessions.length, actionsRemoved };
|
|
317
|
+
}
|
|
318
|
+
async getStorageStats() {
|
|
319
|
+
await this.ensureInitialized();
|
|
320
|
+
return {
|
|
321
|
+
sessions: this.db.data.test_sessions.length,
|
|
322
|
+
actions: this.db.data.actions.length,
|
|
323
|
+
bugs: this.db.data.bugs.length,
|
|
324
|
+
tickets: this.db.data.kanban_tickets.length
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// ── User management ──────────────────────────────────────────────────────────
|
|
328
|
+
async countUsers() {
|
|
329
|
+
await this.ensureInitialized();
|
|
330
|
+
return this.db.data.users.length;
|
|
331
|
+
}
|
|
332
|
+
async findUserByUsername(username) {
|
|
333
|
+
await this.ensureInitialized();
|
|
334
|
+
return this.db.data.users.find((u) => u.username === username) ?? null;
|
|
335
|
+
}
|
|
336
|
+
async getUserById(id) {
|
|
337
|
+
await this.ensureInitialized();
|
|
338
|
+
return this.db.data.users.find((u) => u.id === id) ?? null;
|
|
339
|
+
}
|
|
340
|
+
async getAllUsers() {
|
|
341
|
+
await this.ensureInitialized();
|
|
342
|
+
return [...this.db.data.users];
|
|
343
|
+
}
|
|
344
|
+
async createUser(data) {
|
|
345
|
+
await this.ensureInitialized();
|
|
346
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
347
|
+
const user = {
|
|
348
|
+
id: `user_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
349
|
+
username: data.username,
|
|
350
|
+
passwordHash: data.passwordHash,
|
|
351
|
+
role: data.role,
|
|
352
|
+
createdAt: now,
|
|
353
|
+
updatedAt: now
|
|
354
|
+
};
|
|
355
|
+
this.db.data.users.push(user);
|
|
356
|
+
await this.db.write();
|
|
357
|
+
return user;
|
|
358
|
+
}
|
|
359
|
+
async updateUser(id, updates) {
|
|
360
|
+
await this.ensureInitialized();
|
|
361
|
+
const idx = this.db.data.users.findIndex((u) => u.id === id);
|
|
362
|
+
if (idx !== -1) {
|
|
363
|
+
this.db.data.users[idx] = {
|
|
364
|
+
...this.db.data.users[idx],
|
|
365
|
+
...updates,
|
|
366
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
367
|
+
};
|
|
368
|
+
await this.db.write();
|
|
227
369
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
id: `issue_${i + 1}`,
|
|
236
|
-
title: issueTypes[i % issueTypes.length],
|
|
237
|
-
description: `Issue detected during automated testing session`,
|
|
238
|
-
severity: severities[i % severities.length],
|
|
239
|
-
status: "open",
|
|
240
|
-
discovered_at: new Date(Date.now() - i * 30 * 60 * 1e3).toISOString(),
|
|
241
|
-
agent: ["Main Agent", "Browser Specialist", "API Tester"][i % 3]
|
|
242
|
-
});
|
|
243
|
-
}
|
|
370
|
+
}
|
|
371
|
+
async deleteUser(id) {
|
|
372
|
+
await this.ensureInitialized();
|
|
373
|
+
const idx = this.db.data.users.findIndex((u) => u.id === id);
|
|
374
|
+
if (idx !== -1) {
|
|
375
|
+
this.db.data.users.splice(idx, 1);
|
|
376
|
+
await this.db.write();
|
|
244
377
|
}
|
|
245
|
-
return issues;
|
|
246
378
|
}
|
|
247
379
|
async close() {
|
|
248
380
|
}
|
|
249
381
|
};
|
|
250
382
|
|
|
251
383
|
// agent/config/index.ts
|
|
384
|
+
init_esm_shims();
|
|
252
385
|
import { config as dotenvConfig } from "dotenv";
|
|
386
|
+
|
|
387
|
+
// agent/config/schema.ts
|
|
388
|
+
init_esm_shims();
|
|
389
|
+
import { z } from "zod";
|
|
390
|
+
var llmConfigSchema = z.object({
|
|
391
|
+
provider: z.enum(["openai", "anthropic", "ollama"]).default("openai"),
|
|
392
|
+
apiKey: z.string().optional(),
|
|
393
|
+
model: z.string().optional(),
|
|
394
|
+
baseUrl: z.string().url().optional()
|
|
395
|
+
});
|
|
396
|
+
var saasConfigSchema = z.object({
|
|
397
|
+
url: z.string().default(""),
|
|
398
|
+
authType: z.enum(["none", "basic", "bearer", "session"]).default("none"),
|
|
399
|
+
username: z.string().optional(),
|
|
400
|
+
password: z.string().optional()
|
|
401
|
+
});
|
|
402
|
+
var githubConfigSchema = z.object({
|
|
403
|
+
token: z.string().min(1, "GITHUB_TOKEN is required when GitHub is configured"),
|
|
404
|
+
owner: z.string().default(""),
|
|
405
|
+
repo: z.string().default("")
|
|
406
|
+
});
|
|
407
|
+
var agentConfigSchema = z.object({
|
|
408
|
+
intervalMs: z.number().int().positive().default(36e5),
|
|
409
|
+
maxIterations: z.number().int().positive().default(20),
|
|
410
|
+
autoStart: z.boolean().default(false)
|
|
411
|
+
});
|
|
412
|
+
var webConfigSchema = z.object({
|
|
413
|
+
port: z.number().int().min(1).max(65535).default(4242),
|
|
414
|
+
host: z.string().default("0.0.0.0")
|
|
415
|
+
});
|
|
416
|
+
var databaseConfigSchema = z.object({
|
|
417
|
+
path: z.string().default("./data/openqa.db")
|
|
418
|
+
});
|
|
419
|
+
var notificationsConfigSchema = z.object({
|
|
420
|
+
slack: z.string().url().optional(),
|
|
421
|
+
discord: z.string().url().optional()
|
|
422
|
+
});
|
|
423
|
+
var openQAConfigSchema = z.object({
|
|
424
|
+
llm: llmConfigSchema,
|
|
425
|
+
saas: saasConfigSchema,
|
|
426
|
+
github: githubConfigSchema.optional(),
|
|
427
|
+
agent: agentConfigSchema,
|
|
428
|
+
web: webConfigSchema,
|
|
429
|
+
database: databaseConfigSchema,
|
|
430
|
+
notifications: notificationsConfigSchema.optional()
|
|
431
|
+
});
|
|
432
|
+
var saasAppConfigSchema = z.object({
|
|
433
|
+
name: z.string().min(1, "SaaS application name is required"),
|
|
434
|
+
description: z.string().min(1, "SaaS application description is required"),
|
|
435
|
+
url: z.string().url("SaaS application URL must be a valid URL"),
|
|
436
|
+
repoUrl: z.string().url().optional(),
|
|
437
|
+
localPath: z.string().optional(),
|
|
438
|
+
techStack: z.array(z.string()).optional(),
|
|
439
|
+
authInfo: z.object({
|
|
440
|
+
type: z.enum(["none", "basic", "oauth", "session"]),
|
|
441
|
+
testCredentials: z.object({
|
|
442
|
+
username: z.string(),
|
|
443
|
+
password: z.string()
|
|
444
|
+
}).optional()
|
|
445
|
+
}).optional(),
|
|
446
|
+
directives: z.array(z.string()).optional()
|
|
447
|
+
});
|
|
448
|
+
function validateConfigSafe(config) {
|
|
449
|
+
const result = openQAConfigSchema.safeParse(config);
|
|
450
|
+
if (result.success) {
|
|
451
|
+
return { success: true, data: result.data };
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
success: false,
|
|
455
|
+
errors: result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`)
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// agent/logger.ts
|
|
460
|
+
init_esm_shims();
|
|
461
|
+
var LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
462
|
+
var MIN_LEVEL = process.env.LOG_LEVEL || "info";
|
|
463
|
+
function shouldLog(level) {
|
|
464
|
+
return LEVELS[level] >= LEVELS[MIN_LEVEL];
|
|
465
|
+
}
|
|
466
|
+
function format(level, message, context) {
|
|
467
|
+
const entry = {
|
|
468
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
469
|
+
level,
|
|
470
|
+
msg: message,
|
|
471
|
+
...context
|
|
472
|
+
};
|
|
473
|
+
return JSON.stringify(entry);
|
|
474
|
+
}
|
|
475
|
+
var logger = {
|
|
476
|
+
debug(message, context) {
|
|
477
|
+
if (shouldLog("debug")) process.stdout.write(format("debug", message, context) + "\n");
|
|
478
|
+
},
|
|
479
|
+
info(message, context) {
|
|
480
|
+
if (shouldLog("info")) process.stdout.write(format("info", message, context) + "\n");
|
|
481
|
+
},
|
|
482
|
+
warn(message, context) {
|
|
483
|
+
if (shouldLog("warn")) process.stderr.write(format("warn", message, context) + "\n");
|
|
484
|
+
},
|
|
485
|
+
error(message, context) {
|
|
486
|
+
if (shouldLog("error")) process.stderr.write(format("error", message, context) + "\n");
|
|
487
|
+
},
|
|
488
|
+
child(defaults) {
|
|
489
|
+
return {
|
|
490
|
+
debug: (msg, ctx) => logger.debug(msg, { ...defaults, ...ctx }),
|
|
491
|
+
info: (msg, ctx) => logger.info(msg, { ...defaults, ...ctx }),
|
|
492
|
+
warn: (msg, ctx) => logger.warn(msg, { ...defaults, ...ctx }),
|
|
493
|
+
error: (msg, ctx) => logger.error(msg, { ...defaults, ...ctx })
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
// agent/config/index.ts
|
|
253
499
|
dotenvConfig();
|
|
254
500
|
var ConfigManager = class {
|
|
255
501
|
db = null;
|
|
@@ -258,7 +504,7 @@ var ConfigManager = class {
|
|
|
258
504
|
this.envConfig = this.loadFromEnv();
|
|
259
505
|
}
|
|
260
506
|
loadFromEnv() {
|
|
261
|
-
|
|
507
|
+
const raw = {
|
|
262
508
|
llm: {
|
|
263
509
|
provider: process.env.LLM_PROVIDER || "openai",
|
|
264
510
|
apiKey: process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY,
|
|
@@ -293,6 +539,12 @@ var ConfigManager = class {
|
|
|
293
539
|
discord: process.env.DISCORD_WEBHOOK_URL
|
|
294
540
|
}
|
|
295
541
|
};
|
|
542
|
+
const result = validateConfigSafe(raw);
|
|
543
|
+
if (!result.success) {
|
|
544
|
+
logger.warn("Config validation warnings", { errors: result.errors });
|
|
545
|
+
return raw;
|
|
546
|
+
}
|
|
547
|
+
return result.data;
|
|
296
548
|
}
|
|
297
549
|
getDB() {
|
|
298
550
|
if (!this.db) {
|
|
@@ -306,9 +558,13 @@ var ConfigManager = class {
|
|
|
306
558
|
const keys = key.split(".");
|
|
307
559
|
let value = this.envConfig;
|
|
308
560
|
for (const k of keys) {
|
|
309
|
-
value
|
|
561
|
+
if (value && typeof value === "object") {
|
|
562
|
+
value = value[k];
|
|
563
|
+
} else {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
310
566
|
}
|
|
311
|
-
return value
|
|
567
|
+
return value != null ? String(value) : null;
|
|
312
568
|
}
|
|
313
569
|
async set(key, value) {
|
|
314
570
|
await this.getDB().setConfig(key, value);
|
|
@@ -320,7 +576,7 @@ var ConfigManager = class {
|
|
|
320
576
|
const keys = key.split(".");
|
|
321
577
|
let obj = merged;
|
|
322
578
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
323
|
-
if (!obj[keys[i]]) obj[keys[i]] = {};
|
|
579
|
+
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") obj[keys[i]] = {};
|
|
324
580
|
obj = obj[keys[i]];
|
|
325
581
|
}
|
|
326
582
|
obj[keys[keys.length - 1]] = value;
|
|
@@ -337,6 +593,7 @@ var ConfigManager = class {
|
|
|
337
593
|
};
|
|
338
594
|
|
|
339
595
|
// agent/tools/browser.ts
|
|
596
|
+
init_esm_shims();
|
|
340
597
|
import { chromium } from "playwright";
|
|
341
598
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
342
599
|
import { join as join2 } from "path";
|
|
@@ -385,7 +642,7 @@ var BrowserTools = class {
|
|
|
385
642
|
});
|
|
386
643
|
return `Successfully navigated to ${url}. Page title: "${title}"`;
|
|
387
644
|
} catch (error) {
|
|
388
|
-
return `Failed to navigate: ${error.message}`;
|
|
645
|
+
return `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`;
|
|
389
646
|
}
|
|
390
647
|
}
|
|
391
648
|
},
|
|
@@ -411,7 +668,7 @@ var BrowserTools = class {
|
|
|
411
668
|
});
|
|
412
669
|
return `Successfully clicked element: ${selector}`;
|
|
413
670
|
} catch (error) {
|
|
414
|
-
return `Failed to click element: ${error.message}`;
|
|
671
|
+
return `Failed to click element: ${error instanceof Error ? error.message : String(error)}`;
|
|
415
672
|
}
|
|
416
673
|
}
|
|
417
674
|
},
|
|
@@ -438,7 +695,7 @@ var BrowserTools = class {
|
|
|
438
695
|
});
|
|
439
696
|
return `Successfully filled input ${selector} with text`;
|
|
440
697
|
} catch (error) {
|
|
441
|
-
return `Failed to fill input: ${error.message}`;
|
|
698
|
+
return `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`;
|
|
442
699
|
}
|
|
443
700
|
}
|
|
444
701
|
},
|
|
@@ -456,17 +713,17 @@ var BrowserTools = class {
|
|
|
456
713
|
if (!this.page) return "Browser not initialized. Navigate to a page first.";
|
|
457
714
|
try {
|
|
458
715
|
const filename = `${Date.now()}_${name}.png`;
|
|
459
|
-
const
|
|
460
|
-
await this.page.screenshot({ path, fullPage: true });
|
|
716
|
+
const path2 = join2(this.screenshotDir, filename);
|
|
717
|
+
await this.page.screenshot({ path: path2, fullPage: true });
|
|
461
718
|
this.db.createAction({
|
|
462
719
|
session_id: this.sessionId,
|
|
463
720
|
type: "screenshot",
|
|
464
721
|
description: `Screenshot: ${name}`,
|
|
465
|
-
screenshot_path:
|
|
722
|
+
screenshot_path: path2
|
|
466
723
|
});
|
|
467
|
-
return `Screenshot saved: ${
|
|
724
|
+
return `Screenshot saved: ${path2}`;
|
|
468
725
|
} catch (error) {
|
|
469
|
-
return `Failed to take screenshot: ${error.message}`;
|
|
726
|
+
return `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`;
|
|
470
727
|
}
|
|
471
728
|
}
|
|
472
729
|
},
|
|
@@ -483,7 +740,7 @@ var BrowserTools = class {
|
|
|
483
740
|
const content = await this.page.textContent("body");
|
|
484
741
|
return content?.slice(0, 1e3) || "No content found";
|
|
485
742
|
} catch (error) {
|
|
486
|
-
return `Failed to get content: ${error.message}`;
|
|
743
|
+
return `Failed to get content: ${error instanceof Error ? error.message : String(error)}`;
|
|
487
744
|
}
|
|
488
745
|
}
|
|
489
746
|
},
|
|
@@ -522,6 +779,7 @@ ${errors.join("\n")}`;
|
|
|
522
779
|
};
|
|
523
780
|
|
|
524
781
|
// agent/tools/github.ts
|
|
782
|
+
init_esm_shims();
|
|
525
783
|
import { Octokit } from "@octokit/rest";
|
|
526
784
|
var GitHubTools = class {
|
|
527
785
|
octokit = null;
|
|
@@ -598,7 +856,7 @@ ${screenshot_path ? `**Screenshot:** ${screenshot_path}` : ""}
|
|
|
598
856
|
URL: ${issue.data.html_url}
|
|
599
857
|
Issue #${issue.data.number}`;
|
|
600
858
|
} catch (error) {
|
|
601
|
-
return `\u274C Failed to create GitHub issue: ${error.message}`;
|
|
859
|
+
return `\u274C Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`;
|
|
602
860
|
}
|
|
603
861
|
}
|
|
604
862
|
}
|
|
@@ -607,6 +865,7 @@ Issue #${issue.data.number}`;
|
|
|
607
865
|
};
|
|
608
866
|
|
|
609
867
|
// agent/tools/kanban.ts
|
|
868
|
+
init_esm_shims();
|
|
610
869
|
var KanbanTools = class {
|
|
611
870
|
db;
|
|
612
871
|
sessionId;
|
|
@@ -634,7 +893,7 @@ var KanbanTools = class {
|
|
|
634
893
|
execute: async ({ title, description, priority, column = "to-do", tags = [], screenshot_path }) => {
|
|
635
894
|
try {
|
|
636
895
|
const allTags = ["automated-qa", ...tags];
|
|
637
|
-
const ticket = this.db.createKanbanTicket({
|
|
896
|
+
const ticket = await this.db.createKanbanTicket({
|
|
638
897
|
title,
|
|
639
898
|
description,
|
|
640
899
|
priority,
|
|
@@ -642,7 +901,7 @@ var KanbanTools = class {
|
|
|
642
901
|
tags: JSON.stringify(allTags),
|
|
643
902
|
screenshot_url: screenshot_path
|
|
644
903
|
});
|
|
645
|
-
this.db.createAction({
|
|
904
|
+
await this.db.createAction({
|
|
646
905
|
session_id: this.sessionId,
|
|
647
906
|
type: "kanban_ticket",
|
|
648
907
|
description: `Created Kanban ticket: ${title}`,
|
|
@@ -654,7 +913,7 @@ ID: ${ticket.id}
|
|
|
654
913
|
Column: ${column}
|
|
655
914
|
Priority: ${priority}`;
|
|
656
915
|
} catch (error) {
|
|
657
|
-
return `\u274C Failed to create Kanban ticket: ${error.message}`;
|
|
916
|
+
return `\u274C Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
|
|
658
917
|
}
|
|
659
918
|
}
|
|
660
919
|
},
|
|
@@ -675,10 +934,10 @@ Priority: ${priority}`;
|
|
|
675
934
|
const updates = {};
|
|
676
935
|
if (column) updates.column = column;
|
|
677
936
|
if (priority) updates.priority = priority;
|
|
678
|
-
this.db.updateKanbanTicket(ticket_id, updates);
|
|
937
|
+
await this.db.updateKanbanTicket(ticket_id, updates);
|
|
679
938
|
return `\u2705 Kanban ticket ${ticket_id} updated successfully!`;
|
|
680
939
|
} catch (error) {
|
|
681
|
-
return `\u274C Failed to update Kanban ticket: ${error.message}`;
|
|
940
|
+
return `\u274C Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
|
|
682
941
|
}
|
|
683
942
|
}
|
|
684
943
|
},
|
|
@@ -691,7 +950,7 @@ Priority: ${priority}`;
|
|
|
691
950
|
},
|
|
692
951
|
execute: async () => {
|
|
693
952
|
try {
|
|
694
|
-
const tickets = this.db.getKanbanTickets();
|
|
953
|
+
const tickets = await this.db.getKanbanTickets();
|
|
695
954
|
const byColumn = {
|
|
696
955
|
backlog: tickets.filter((t) => t.column === "backlog"),
|
|
697
956
|
"to-do": tickets.filter((t) => t.column === "to-do"),
|
|
@@ -709,7 +968,7 @@ Total: ${tickets.length} tickets
|
|
|
709
968
|
`.trim();
|
|
710
969
|
return summary;
|
|
711
970
|
} catch (error) {
|
|
712
|
-
return `\u274C Failed to get Kanban board: ${error.message}`;
|
|
971
|
+
return `\u274C Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`;
|
|
713
972
|
}
|
|
714
973
|
}
|
|
715
974
|
}
|
|
@@ -718,6 +977,7 @@ Total: ${tickets.length} tickets
|
|
|
718
977
|
};
|
|
719
978
|
|
|
720
979
|
// agent/webhooks/git-listener.ts
|
|
980
|
+
init_esm_shims();
|
|
721
981
|
import { EventEmitter } from "events";
|
|
722
982
|
import { Octokit as Octokit2 } from "@octokit/rest";
|
|
723
983
|
var GitListener = class extends EventEmitter {
|
|
@@ -742,10 +1002,10 @@ var GitListener = class extends EventEmitter {
|
|
|
742
1002
|
async start() {
|
|
743
1003
|
if (this.isRunning) return;
|
|
744
1004
|
this.isRunning = true;
|
|
745
|
-
|
|
1005
|
+
logger.info("GitListener started", { provider: this.config.provider, owner: this.config.owner, repo: this.config.repo });
|
|
746
1006
|
await this.checkInitialState();
|
|
747
1007
|
this.pollInterval = setInterval(() => {
|
|
748
|
-
this.poll().catch(
|
|
1008
|
+
this.poll().catch((e) => logger.error("Poll error", { error: e instanceof Error ? e.message : String(e) }));
|
|
749
1009
|
}, this.config.pollIntervalMs);
|
|
750
1010
|
}
|
|
751
1011
|
stop() {
|
|
@@ -754,7 +1014,7 @@ var GitListener = class extends EventEmitter {
|
|
|
754
1014
|
clearInterval(this.pollInterval);
|
|
755
1015
|
this.pollInterval = null;
|
|
756
1016
|
}
|
|
757
|
-
|
|
1017
|
+
logger.info("GitListener stopped");
|
|
758
1018
|
}
|
|
759
1019
|
async checkInitialState() {
|
|
760
1020
|
try {
|
|
@@ -764,7 +1024,7 @@ var GitListener = class extends EventEmitter {
|
|
|
764
1024
|
await this.checkGitLabState();
|
|
765
1025
|
}
|
|
766
1026
|
} catch (error) {
|
|
767
|
-
|
|
1027
|
+
logger.error("Failed to check initial state", { error: error instanceof Error ? error.message : String(error) });
|
|
768
1028
|
}
|
|
769
1029
|
}
|
|
770
1030
|
async poll() {
|
|
@@ -775,7 +1035,7 @@ var GitListener = class extends EventEmitter {
|
|
|
775
1035
|
await this.pollGitLab();
|
|
776
1036
|
}
|
|
777
1037
|
} catch (error) {
|
|
778
|
-
|
|
1038
|
+
logger.error("Poll error", { error: error instanceof Error ? error.message : String(error) });
|
|
779
1039
|
}
|
|
780
1040
|
}
|
|
781
1041
|
async checkGitHubState() {
|
|
@@ -825,7 +1085,7 @@ var GitListener = class extends EventEmitter {
|
|
|
825
1085
|
this.emit("git-event", event);
|
|
826
1086
|
if (isMerge) {
|
|
827
1087
|
this.emit("merge", event);
|
|
828
|
-
|
|
1088
|
+
logger.info("Merge detected", { branch: this.config.branch, sha: commit.sha.slice(0, 7) });
|
|
829
1089
|
}
|
|
830
1090
|
}
|
|
831
1091
|
if (commits.length > 0) {
|
|
@@ -855,10 +1115,10 @@ var GitListener = class extends EventEmitter {
|
|
|
855
1115
|
this.emit("git-event", event);
|
|
856
1116
|
if (run.conclusion === "success") {
|
|
857
1117
|
this.emit("pipeline-success", event);
|
|
858
|
-
|
|
1118
|
+
logger.info("Pipeline success", { name: run.name, id: run.id });
|
|
859
1119
|
} else {
|
|
860
1120
|
this.emit("pipeline-failure", event);
|
|
861
|
-
|
|
1121
|
+
logger.warn("Pipeline failure", { name: run.name, id: run.id });
|
|
862
1122
|
}
|
|
863
1123
|
}
|
|
864
1124
|
}
|
|
@@ -890,7 +1150,7 @@ var GitListener = class extends EventEmitter {
|
|
|
890
1150
|
this.lastPipelineId = pipelines[0].id.toString();
|
|
891
1151
|
}
|
|
892
1152
|
} catch (error) {
|
|
893
|
-
|
|
1153
|
+
logger.error("GitLab initial state error", { error: error instanceof Error ? error.message : String(error) });
|
|
894
1154
|
}
|
|
895
1155
|
}
|
|
896
1156
|
async pollGitLab() {
|
|
@@ -918,7 +1178,7 @@ var GitListener = class extends EventEmitter {
|
|
|
918
1178
|
this.emit("git-event", event);
|
|
919
1179
|
if (isMerge) {
|
|
920
1180
|
this.emit("merge", event);
|
|
921
|
-
|
|
1181
|
+
logger.info("Merge detected", { branch: this.config.branch, id: commit.id.slice(0, 7) });
|
|
922
1182
|
}
|
|
923
1183
|
}
|
|
924
1184
|
if (commits.length > 0) {
|
|
@@ -946,10 +1206,10 @@ var GitListener = class extends EventEmitter {
|
|
|
946
1206
|
this.emit("git-event", event);
|
|
947
1207
|
if (pipeline.status === "success") {
|
|
948
1208
|
this.emit("pipeline-success", event);
|
|
949
|
-
|
|
1209
|
+
logger.info("Pipeline success", { id: pipeline.id });
|
|
950
1210
|
} else {
|
|
951
1211
|
this.emit("pipeline-failure", event);
|
|
952
|
-
|
|
1212
|
+
logger.warn("Pipeline failure", { id: pipeline.id });
|
|
953
1213
|
}
|
|
954
1214
|
}
|
|
955
1215
|
}
|
|
@@ -957,7 +1217,7 @@ var GitListener = class extends EventEmitter {
|
|
|
957
1217
|
this.lastPipelineId = pipelines[0].id.toString();
|
|
958
1218
|
}
|
|
959
1219
|
} catch (error) {
|
|
960
|
-
|
|
1220
|
+
logger.error("GitLab poll error", { error: error instanceof Error ? error.message : String(error) });
|
|
961
1221
|
}
|
|
962
1222
|
}
|
|
963
1223
|
async setupWebhook(webhookUrl) {
|
|
@@ -1005,6 +1265,7 @@ var GitListener = class extends EventEmitter {
|
|
|
1005
1265
|
};
|
|
1006
1266
|
|
|
1007
1267
|
// agent/specialists/index.ts
|
|
1268
|
+
init_esm_shims();
|
|
1008
1269
|
import { ReActAgent } from "@orka-js/agent";
|
|
1009
1270
|
import { OpenAIAdapter } from "@orka-js/openai";
|
|
1010
1271
|
import { AnthropicAdapter } from "@orka-js/anthropic";
|
|
@@ -1126,8 +1387,8 @@ var SpecialistAgentManager = class extends EventEmitter2 {
|
|
|
1126
1387
|
createSpecialist(type, customPrompt) {
|
|
1127
1388
|
const agentId = `${type}_${Date.now()}`;
|
|
1128
1389
|
const systemPrompt = customPrompt || SPECIALIST_PROMPTS[type];
|
|
1390
|
+
const llm = this.createLLMAdapter();
|
|
1129
1391
|
const agent = new ReActAgent({
|
|
1130
|
-
llm: this.createLLMAdapter(),
|
|
1131
1392
|
tools: this.browserTools.getTools(),
|
|
1132
1393
|
maxIterations: 15,
|
|
1133
1394
|
systemPrompt: `${systemPrompt}
|
|
@@ -1138,7 +1399,7 @@ IMPORTANT RULES:
|
|
|
1138
1399
|
- Create GitHub issues for critical/high severity bugs
|
|
1139
1400
|
- Be thorough but efficient
|
|
1140
1401
|
- Stop when you've tested the main scenarios for your specialty`
|
|
1141
|
-
});
|
|
1402
|
+
}, llm);
|
|
1142
1403
|
this.agents.set(agentId, agent);
|
|
1143
1404
|
const status = {
|
|
1144
1405
|
id: agentId,
|
|
@@ -1173,7 +1434,7 @@ IMPORTANT RULES:
|
|
|
1173
1434
|
} catch (error) {
|
|
1174
1435
|
status.status = "failed";
|
|
1175
1436
|
status.completedAt = /* @__PURE__ */ new Date();
|
|
1176
|
-
this.emit("agent-failed", { ...status, error: error.message });
|
|
1437
|
+
this.emit("agent-failed", { ...status, error: error instanceof Error ? error.message : String(error) });
|
|
1177
1438
|
}
|
|
1178
1439
|
}
|
|
1179
1440
|
async runAllSpecialists(targetUrl, types) {
|
|
@@ -1219,6 +1480,7 @@ IMPORTANT RULES:
|
|
|
1219
1480
|
};
|
|
1220
1481
|
|
|
1221
1482
|
// agent/skills/index.ts
|
|
1483
|
+
init_esm_shims();
|
|
1222
1484
|
var DEFAULT_SKILLS = [
|
|
1223
1485
|
{
|
|
1224
1486
|
name: "GDPR Compliance Check",
|
|
@@ -1466,9 +1728,7 @@ var OpenQAAgent = class extends EventEmitter3 {
|
|
|
1466
1728
|
this.sessionId = `session_${Date.now()}`;
|
|
1467
1729
|
await this.db.createSession(this.sessionId, {
|
|
1468
1730
|
config: cfg,
|
|
1469
|
-
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1470
|
-
trigger_type: triggerType,
|
|
1471
|
-
trigger_data: triggerData ? JSON.stringify(triggerData) : null
|
|
1731
|
+
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1472
1732
|
});
|
|
1473
1733
|
this.browserTools = new BrowserTools(this.db, this.sessionId);
|
|
1474
1734
|
const githubTools = new GitHubTools(this.db, this.sessionId, cfg.github || {});
|
|
@@ -1519,7 +1779,11 @@ ${skillPrompt}
|
|
|
1519
1779
|
|
|
1520
1780
|
Always provide clear, actionable information with steps to reproduce. Think step by step like a human QA expert.`
|
|
1521
1781
|
};
|
|
1522
|
-
this.agent = new ReActAgent2(
|
|
1782
|
+
this.agent = new ReActAgent2({
|
|
1783
|
+
tools: allTools,
|
|
1784
|
+
maxIterations: cfg.agent.maxIterations,
|
|
1785
|
+
systemPrompt: agentConfig.systemPrompt
|
|
1786
|
+
}, llm, memory);
|
|
1523
1787
|
this.specialistManager = new SpecialistAgentManager(
|
|
1524
1788
|
this.db,
|
|
1525
1789
|
this.sessionId,
|
|
@@ -1536,13 +1800,13 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1536
1800
|
if (!this.agent) {
|
|
1537
1801
|
await this.initialize();
|
|
1538
1802
|
}
|
|
1539
|
-
const cfg = this.config.getConfig();
|
|
1803
|
+
const cfg = await this.config.getConfig();
|
|
1540
1804
|
console.log(`\u{1F680} Starting test session for ${cfg.saas.url}`);
|
|
1541
1805
|
try {
|
|
1542
1806
|
const result = await this.agent.run(
|
|
1543
1807
|
`Continue testing the application at ${cfg.saas.url}. Review previous findings, create new test scenarios, and report any issues discovered. Focus on areas not yet tested.`
|
|
1544
1808
|
);
|
|
1545
|
-
this.db.updateSession(this.sessionId, {
|
|
1809
|
+
await this.db.updateSession(this.sessionId, {
|
|
1546
1810
|
status: "completed",
|
|
1547
1811
|
ended_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1548
1812
|
});
|
|
@@ -1550,7 +1814,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1550
1814
|
return result;
|
|
1551
1815
|
} catch (error) {
|
|
1552
1816
|
console.error("\u274C Session error:", error);
|
|
1553
|
-
this.db.updateSession(this.sessionId, {
|
|
1817
|
+
await this.db.updateSession(this.sessionId, {
|
|
1554
1818
|
status: "failed",
|
|
1555
1819
|
ended_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1556
1820
|
});
|
|
@@ -1567,7 +1831,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1567
1831
|
return;
|
|
1568
1832
|
}
|
|
1569
1833
|
this.isRunning = true;
|
|
1570
|
-
const cfg = this.config.getConfig();
|
|
1834
|
+
const cfg = await this.config.getConfig();
|
|
1571
1835
|
console.log(`\u{1F916} OpenQA Agent starting in autonomous mode`);
|
|
1572
1836
|
console.log(`\u{1F4CD} Target: ${cfg.saas.url}`);
|
|
1573
1837
|
console.log(`\u23F1\uFE0F Interval: ${cfg.agent.intervalMs}ms (${cfg.agent.intervalMs / 1e3 / 60} minutes)`);
|
|
@@ -1608,7 +1872,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1608
1872
|
}
|
|
1609
1873
|
// Git integration
|
|
1610
1874
|
async startGitListener() {
|
|
1611
|
-
const cfg = this.config.getConfig();
|
|
1875
|
+
const cfg = await this.config.getConfig();
|
|
1612
1876
|
if (cfg.github?.token && cfg.github?.owner && cfg.github?.repo) {
|
|
1613
1877
|
this.gitListener = new GitListener({
|
|
1614
1878
|
provider: "github",
|
|
@@ -1656,14 +1920,14 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1656
1920
|
if (!this.specialistManager) {
|
|
1657
1921
|
await this.initialize();
|
|
1658
1922
|
}
|
|
1659
|
-
const cfg = this.config.getConfig();
|
|
1923
|
+
const cfg = await this.config.getConfig();
|
|
1660
1924
|
await this.specialistManager.runSecuritySuite(cfg.saas.url);
|
|
1661
1925
|
}
|
|
1662
1926
|
async runSpecialist(type) {
|
|
1663
1927
|
if (!this.specialistManager) {
|
|
1664
1928
|
await this.initialize();
|
|
1665
1929
|
}
|
|
1666
|
-
const cfg = this.config.getConfig();
|
|
1930
|
+
const cfg = await this.config.getConfig();
|
|
1667
1931
|
const agentId = this.specialistManager.createSpecialist(type);
|
|
1668
1932
|
await this.specialistManager.runSpecialist(agentId, cfg.saas.url);
|
|
1669
1933
|
}
|
|
@@ -1686,11 +1950,11 @@ Always provide clear, actionable information with steps to reproduce. Think step
|
|
|
1686
1950
|
toggleSkill(id) {
|
|
1687
1951
|
return this.skillManager.toggleSkill(id);
|
|
1688
1952
|
}
|
|
1689
|
-
getStatus() {
|
|
1953
|
+
async getStatus() {
|
|
1690
1954
|
return {
|
|
1691
1955
|
isRunning: this.isRunning,
|
|
1692
1956
|
sessionId: this.sessionId,
|
|
1693
|
-
config: this.config.getConfig(),
|
|
1957
|
+
config: await this.config.getConfig(),
|
|
1694
1958
|
gitListenerActive: !!this.gitListener,
|
|
1695
1959
|
specialists: this.getSpecialistStatuses(),
|
|
1696
1960
|
skills: this.skillManager.getEnabledSkills().length
|