@openqa/cli 1.3.3 → 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.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/brain/diff-analyzer.js +140 -0
  3. package/dist/agent/brain/diff-analyzer.js.map +1 -0
  4. package/dist/agent/brain/llm-cache.js +47 -0
  5. package/dist/agent/brain/llm-cache.js.map +1 -0
  6. package/dist/agent/brain/llm-resilience.js +252 -0
  7. package/dist/agent/brain/llm-resilience.js.map +1 -0
  8. package/dist/agent/config/index.js +588 -0
  9. package/dist/agent/config/index.js.map +1 -0
  10. package/dist/agent/coverage/index.js +74 -0
  11. package/dist/agent/coverage/index.js.map +1 -0
  12. package/dist/agent/export/index.js +158 -0
  13. package/dist/agent/export/index.js.map +1 -0
  14. package/dist/agent/index-v2.js +2795 -0
  15. package/dist/agent/index-v2.js.map +1 -0
  16. package/dist/agent/index.js +387 -55
  17. package/dist/agent/index.js.map +1 -1
  18. package/dist/agent/logger.js +41 -0
  19. package/dist/agent/logger.js.map +1 -0
  20. package/dist/agent/metrics.js +39 -0
  21. package/dist/agent/metrics.js.map +1 -0
  22. package/dist/agent/notifications/index.js +106 -0
  23. package/dist/agent/notifications/index.js.map +1 -0
  24. package/dist/agent/openapi/spec.js +338 -0
  25. package/dist/agent/openapi/spec.js.map +1 -0
  26. package/dist/agent/tools/project-runner.js +481 -0
  27. package/dist/agent/tools/project-runner.js.map +1 -0
  28. package/dist/cli/config.html.js +454 -0
  29. package/dist/cli/daemon.js +7572 -0
  30. package/dist/cli/dashboard.html.js +1619 -0
  31. package/dist/cli/index.js +3624 -1675
  32. package/dist/cli/kanban.html.js +577 -0
  33. package/dist/cli/routes.js +895 -0
  34. package/dist/cli/routes.js.map +1 -0
  35. package/dist/cli/server.js +3564 -1646
  36. package/dist/database/index.js +503 -10
  37. package/dist/database/index.js.map +1 -1
  38. package/dist/database/sqlite.js +281 -0
  39. package/dist/database/sqlite.js.map +1 -0
  40. package/package.json +18 -5
@@ -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 __filename = fileURLToPath(import.meta.url);
16
- var __dirname = dirname(__filename);
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,17 +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
  }
221
+ // Get real data methods - connected to actual database records
222
+ async getActiveAgents() {
223
+ await this.ensureInitialized();
224
+ const sessions = await this.getRecentSessions(1);
225
+ const currentSession = sessions[0];
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
+ }
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;
273
+ }
274
+ async getCurrentTasks() {
275
+ await this.ensureInitialized();
276
+ const sessions = await this.getRecentSessions(1);
277
+ const currentSession = sessions[0];
278
+ if (!currentSession) {
279
+ return [];
280
+ }
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
+ }));
292
+ }
293
+ async getCurrentIssues() {
294
+ await this.ensureInitialized();
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();
369
+ }
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();
377
+ }
378
+ }
179
379
  async close() {
180
380
  }
181
381
  };
182
382
 
183
383
  // agent/config/index.ts
384
+ init_esm_shims();
184
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
185
499
  dotenvConfig();
186
500
  var ConfigManager = class {
187
501
  db = null;
@@ -190,7 +504,7 @@ var ConfigManager = class {
190
504
  this.envConfig = this.loadFromEnv();
191
505
  }
192
506
  loadFromEnv() {
193
- return {
507
+ const raw = {
194
508
  llm: {
195
509
  provider: process.env.LLM_PROVIDER || "openai",
196
510
  apiKey: process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY,
@@ -225,6 +539,12 @@ var ConfigManager = class {
225
539
  discord: process.env.DISCORD_WEBHOOK_URL
226
540
  }
227
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;
228
548
  }
229
549
  getDB() {
230
550
  if (!this.db) {
@@ -238,9 +558,13 @@ var ConfigManager = class {
238
558
  const keys = key.split(".");
239
559
  let value = this.envConfig;
240
560
  for (const k of keys) {
241
- value = value?.[k];
561
+ if (value && typeof value === "object") {
562
+ value = value[k];
563
+ } else {
564
+ return null;
565
+ }
242
566
  }
243
- return value?.toString() || null;
567
+ return value != null ? String(value) : null;
244
568
  }
245
569
  async set(key, value) {
246
570
  await this.getDB().setConfig(key, value);
@@ -252,7 +576,7 @@ var ConfigManager = class {
252
576
  const keys = key.split(".");
253
577
  let obj = merged;
254
578
  for (let i = 0; i < keys.length - 1; i++) {
255
- if (!obj[keys[i]]) obj[keys[i]] = {};
579
+ if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") obj[keys[i]] = {};
256
580
  obj = obj[keys[i]];
257
581
  }
258
582
  obj[keys[keys.length - 1]] = value;
@@ -269,6 +593,7 @@ var ConfigManager = class {
269
593
  };
270
594
 
271
595
  // agent/tools/browser.ts
596
+ init_esm_shims();
272
597
  import { chromium } from "playwright";
273
598
  import { mkdirSync as mkdirSync2 } from "fs";
274
599
  import { join as join2 } from "path";
@@ -317,7 +642,7 @@ var BrowserTools = class {
317
642
  });
318
643
  return `Successfully navigated to ${url}. Page title: "${title}"`;
319
644
  } catch (error) {
320
- return `Failed to navigate: ${error.message}`;
645
+ return `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`;
321
646
  }
322
647
  }
323
648
  },
@@ -343,7 +668,7 @@ var BrowserTools = class {
343
668
  });
344
669
  return `Successfully clicked element: ${selector}`;
345
670
  } catch (error) {
346
- return `Failed to click element: ${error.message}`;
671
+ return `Failed to click element: ${error instanceof Error ? error.message : String(error)}`;
347
672
  }
348
673
  }
349
674
  },
@@ -370,7 +695,7 @@ var BrowserTools = class {
370
695
  });
371
696
  return `Successfully filled input ${selector} with text`;
372
697
  } catch (error) {
373
- return `Failed to fill input: ${error.message}`;
698
+ return `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`;
374
699
  }
375
700
  }
376
701
  },
@@ -388,17 +713,17 @@ var BrowserTools = class {
388
713
  if (!this.page) return "Browser not initialized. Navigate to a page first.";
389
714
  try {
390
715
  const filename = `${Date.now()}_${name}.png`;
391
- const path = join2(this.screenshotDir, filename);
392
- await this.page.screenshot({ path, fullPage: true });
716
+ const path2 = join2(this.screenshotDir, filename);
717
+ await this.page.screenshot({ path: path2, fullPage: true });
393
718
  this.db.createAction({
394
719
  session_id: this.sessionId,
395
720
  type: "screenshot",
396
721
  description: `Screenshot: ${name}`,
397
- screenshot_path: path
722
+ screenshot_path: path2
398
723
  });
399
- return `Screenshot saved: ${path}`;
724
+ return `Screenshot saved: ${path2}`;
400
725
  } catch (error) {
401
- return `Failed to take screenshot: ${error.message}`;
726
+ return `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`;
402
727
  }
403
728
  }
404
729
  },
@@ -415,7 +740,7 @@ var BrowserTools = class {
415
740
  const content = await this.page.textContent("body");
416
741
  return content?.slice(0, 1e3) || "No content found";
417
742
  } catch (error) {
418
- return `Failed to get content: ${error.message}`;
743
+ return `Failed to get content: ${error instanceof Error ? error.message : String(error)}`;
419
744
  }
420
745
  }
421
746
  },
@@ -454,6 +779,7 @@ ${errors.join("\n")}`;
454
779
  };
455
780
 
456
781
  // agent/tools/github.ts
782
+ init_esm_shims();
457
783
  import { Octokit } from "@octokit/rest";
458
784
  var GitHubTools = class {
459
785
  octokit = null;
@@ -530,7 +856,7 @@ ${screenshot_path ? `**Screenshot:** ${screenshot_path}` : ""}
530
856
  URL: ${issue.data.html_url}
531
857
  Issue #${issue.data.number}`;
532
858
  } catch (error) {
533
- return `\u274C Failed to create GitHub issue: ${error.message}`;
859
+ return `\u274C Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`;
534
860
  }
535
861
  }
536
862
  }
@@ -539,6 +865,7 @@ Issue #${issue.data.number}`;
539
865
  };
540
866
 
541
867
  // agent/tools/kanban.ts
868
+ init_esm_shims();
542
869
  var KanbanTools = class {
543
870
  db;
544
871
  sessionId;
@@ -566,7 +893,7 @@ var KanbanTools = class {
566
893
  execute: async ({ title, description, priority, column = "to-do", tags = [], screenshot_path }) => {
567
894
  try {
568
895
  const allTags = ["automated-qa", ...tags];
569
- const ticket = this.db.createKanbanTicket({
896
+ const ticket = await this.db.createKanbanTicket({
570
897
  title,
571
898
  description,
572
899
  priority,
@@ -574,7 +901,7 @@ var KanbanTools = class {
574
901
  tags: JSON.stringify(allTags),
575
902
  screenshot_url: screenshot_path
576
903
  });
577
- this.db.createAction({
904
+ await this.db.createAction({
578
905
  session_id: this.sessionId,
579
906
  type: "kanban_ticket",
580
907
  description: `Created Kanban ticket: ${title}`,
@@ -586,7 +913,7 @@ ID: ${ticket.id}
586
913
  Column: ${column}
587
914
  Priority: ${priority}`;
588
915
  } catch (error) {
589
- return `\u274C Failed to create Kanban ticket: ${error.message}`;
916
+ return `\u274C Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
590
917
  }
591
918
  }
592
919
  },
@@ -607,10 +934,10 @@ Priority: ${priority}`;
607
934
  const updates = {};
608
935
  if (column) updates.column = column;
609
936
  if (priority) updates.priority = priority;
610
- this.db.updateKanbanTicket(ticket_id, updates);
937
+ await this.db.updateKanbanTicket(ticket_id, updates);
611
938
  return `\u2705 Kanban ticket ${ticket_id} updated successfully!`;
612
939
  } catch (error) {
613
- return `\u274C Failed to update Kanban ticket: ${error.message}`;
940
+ return `\u274C Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
614
941
  }
615
942
  }
616
943
  },
@@ -623,7 +950,7 @@ Priority: ${priority}`;
623
950
  },
624
951
  execute: async () => {
625
952
  try {
626
- const tickets = this.db.getKanbanTickets();
953
+ const tickets = await this.db.getKanbanTickets();
627
954
  const byColumn = {
628
955
  backlog: tickets.filter((t) => t.column === "backlog"),
629
956
  "to-do": tickets.filter((t) => t.column === "to-do"),
@@ -641,7 +968,7 @@ Total: ${tickets.length} tickets
641
968
  `.trim();
642
969
  return summary;
643
970
  } catch (error) {
644
- return `\u274C Failed to get Kanban board: ${error.message}`;
971
+ return `\u274C Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`;
645
972
  }
646
973
  }
647
974
  }
@@ -650,6 +977,7 @@ Total: ${tickets.length} tickets
650
977
  };
651
978
 
652
979
  // agent/webhooks/git-listener.ts
980
+ init_esm_shims();
653
981
  import { EventEmitter } from "events";
654
982
  import { Octokit as Octokit2 } from "@octokit/rest";
655
983
  var GitListener = class extends EventEmitter {
@@ -674,10 +1002,10 @@ var GitListener = class extends EventEmitter {
674
1002
  async start() {
675
1003
  if (this.isRunning) return;
676
1004
  this.isRunning = true;
677
- console.log(`\u{1F517} GitListener started for ${this.config.provider}/${this.config.owner}/${this.config.repo}`);
1005
+ logger.info("GitListener started", { provider: this.config.provider, owner: this.config.owner, repo: this.config.repo });
678
1006
  await this.checkInitialState();
679
1007
  this.pollInterval = setInterval(() => {
680
- this.poll().catch(console.error);
1008
+ this.poll().catch((e) => logger.error("Poll error", { error: e instanceof Error ? e.message : String(e) }));
681
1009
  }, this.config.pollIntervalMs);
682
1010
  }
683
1011
  stop() {
@@ -686,7 +1014,7 @@ var GitListener = class extends EventEmitter {
686
1014
  clearInterval(this.pollInterval);
687
1015
  this.pollInterval = null;
688
1016
  }
689
- console.log("\u{1F517} GitListener stopped");
1017
+ logger.info("GitListener stopped");
690
1018
  }
691
1019
  async checkInitialState() {
692
1020
  try {
@@ -696,7 +1024,7 @@ var GitListener = class extends EventEmitter {
696
1024
  await this.checkGitLabState();
697
1025
  }
698
1026
  } catch (error) {
699
- console.error("Failed to check initial state:", error);
1027
+ logger.error("Failed to check initial state", { error: error instanceof Error ? error.message : String(error) });
700
1028
  }
701
1029
  }
702
1030
  async poll() {
@@ -707,7 +1035,7 @@ var GitListener = class extends EventEmitter {
707
1035
  await this.pollGitLab();
708
1036
  }
709
1037
  } catch (error) {
710
- console.error("Poll error:", error);
1038
+ logger.error("Poll error", { error: error instanceof Error ? error.message : String(error) });
711
1039
  }
712
1040
  }
713
1041
  async checkGitHubState() {
@@ -757,7 +1085,7 @@ var GitListener = class extends EventEmitter {
757
1085
  this.emit("git-event", event);
758
1086
  if (isMerge) {
759
1087
  this.emit("merge", event);
760
- console.log(`\u{1F500} Merge detected on ${this.config.branch}: ${commit.sha.slice(0, 7)}`);
1088
+ logger.info("Merge detected", { branch: this.config.branch, sha: commit.sha.slice(0, 7) });
761
1089
  }
762
1090
  }
763
1091
  if (commits.length > 0) {
@@ -787,10 +1115,10 @@ var GitListener = class extends EventEmitter {
787
1115
  this.emit("git-event", event);
788
1116
  if (run.conclusion === "success") {
789
1117
  this.emit("pipeline-success", event);
790
- console.log(`\u2705 Pipeline success: ${run.name} (${run.id})`);
1118
+ logger.info("Pipeline success", { name: run.name, id: run.id });
791
1119
  } else {
792
1120
  this.emit("pipeline-failure", event);
793
- console.log(`\u274C Pipeline failure: ${run.name} (${run.id})`);
1121
+ logger.warn("Pipeline failure", { name: run.name, id: run.id });
794
1122
  }
795
1123
  }
796
1124
  }
@@ -822,7 +1150,7 @@ var GitListener = class extends EventEmitter {
822
1150
  this.lastPipelineId = pipelines[0].id.toString();
823
1151
  }
824
1152
  } catch (error) {
825
- console.error("GitLab initial state error:", error);
1153
+ logger.error("GitLab initial state error", { error: error instanceof Error ? error.message : String(error) });
826
1154
  }
827
1155
  }
828
1156
  async pollGitLab() {
@@ -850,7 +1178,7 @@ var GitListener = class extends EventEmitter {
850
1178
  this.emit("git-event", event);
851
1179
  if (isMerge) {
852
1180
  this.emit("merge", event);
853
- console.log(`\u{1F500} Merge detected on ${this.config.branch}: ${commit.id.slice(0, 7)}`);
1181
+ logger.info("Merge detected", { branch: this.config.branch, id: commit.id.slice(0, 7) });
854
1182
  }
855
1183
  }
856
1184
  if (commits.length > 0) {
@@ -878,10 +1206,10 @@ var GitListener = class extends EventEmitter {
878
1206
  this.emit("git-event", event);
879
1207
  if (pipeline.status === "success") {
880
1208
  this.emit("pipeline-success", event);
881
- console.log(`\u2705 Pipeline success: #${pipeline.id}`);
1209
+ logger.info("Pipeline success", { id: pipeline.id });
882
1210
  } else {
883
1211
  this.emit("pipeline-failure", event);
884
- console.log(`\u274C Pipeline failure: #${pipeline.id}`);
1212
+ logger.warn("Pipeline failure", { id: pipeline.id });
885
1213
  }
886
1214
  }
887
1215
  }
@@ -889,7 +1217,7 @@ var GitListener = class extends EventEmitter {
889
1217
  this.lastPipelineId = pipelines[0].id.toString();
890
1218
  }
891
1219
  } catch (error) {
892
- console.error("GitLab poll error:", error);
1220
+ logger.error("GitLab poll error", { error: error instanceof Error ? error.message : String(error) });
893
1221
  }
894
1222
  }
895
1223
  async setupWebhook(webhookUrl) {
@@ -937,6 +1265,7 @@ var GitListener = class extends EventEmitter {
937
1265
  };
938
1266
 
939
1267
  // agent/specialists/index.ts
1268
+ init_esm_shims();
940
1269
  import { ReActAgent } from "@orka-js/agent";
941
1270
  import { OpenAIAdapter } from "@orka-js/openai";
942
1271
  import { AnthropicAdapter } from "@orka-js/anthropic";
@@ -1058,8 +1387,8 @@ var SpecialistAgentManager = class extends EventEmitter2 {
1058
1387
  createSpecialist(type, customPrompt) {
1059
1388
  const agentId = `${type}_${Date.now()}`;
1060
1389
  const systemPrompt = customPrompt || SPECIALIST_PROMPTS[type];
1390
+ const llm = this.createLLMAdapter();
1061
1391
  const agent = new ReActAgent({
1062
- llm: this.createLLMAdapter(),
1063
1392
  tools: this.browserTools.getTools(),
1064
1393
  maxIterations: 15,
1065
1394
  systemPrompt: `${systemPrompt}
@@ -1070,7 +1399,7 @@ IMPORTANT RULES:
1070
1399
  - Create GitHub issues for critical/high severity bugs
1071
1400
  - Be thorough but efficient
1072
1401
  - Stop when you've tested the main scenarios for your specialty`
1073
- });
1402
+ }, llm);
1074
1403
  this.agents.set(agentId, agent);
1075
1404
  const status = {
1076
1405
  id: agentId,
@@ -1105,7 +1434,7 @@ IMPORTANT RULES:
1105
1434
  } catch (error) {
1106
1435
  status.status = "failed";
1107
1436
  status.completedAt = /* @__PURE__ */ new Date();
1108
- this.emit("agent-failed", { ...status, error: error.message });
1437
+ this.emit("agent-failed", { ...status, error: error instanceof Error ? error.message : String(error) });
1109
1438
  }
1110
1439
  }
1111
1440
  async runAllSpecialists(targetUrl, types) {
@@ -1151,6 +1480,7 @@ IMPORTANT RULES:
1151
1480
  };
1152
1481
 
1153
1482
  // agent/skills/index.ts
1483
+ init_esm_shims();
1154
1484
  var DEFAULT_SKILLS = [
1155
1485
  {
1156
1486
  name: "GDPR Compliance Check",
@@ -1398,9 +1728,7 @@ var OpenQAAgent = class extends EventEmitter3 {
1398
1728
  this.sessionId = `session_${Date.now()}`;
1399
1729
  await this.db.createSession(this.sessionId, {
1400
1730
  config: cfg,
1401
- started_at: (/* @__PURE__ */ new Date()).toISOString(),
1402
- trigger_type: triggerType,
1403
- trigger_data: triggerData ? JSON.stringify(triggerData) : null
1731
+ started_at: (/* @__PURE__ */ new Date()).toISOString()
1404
1732
  });
1405
1733
  this.browserTools = new BrowserTools(this.db, this.sessionId);
1406
1734
  const githubTools = new GitHubTools(this.db, this.sessionId, cfg.github || {});
@@ -1451,7 +1779,11 @@ ${skillPrompt}
1451
1779
 
1452
1780
  Always provide clear, actionable information with steps to reproduce. Think step by step like a human QA expert.`
1453
1781
  };
1454
- this.agent = new ReActAgent2(agentConfig, llm, memory);
1782
+ this.agent = new ReActAgent2({
1783
+ tools: allTools,
1784
+ maxIterations: cfg.agent.maxIterations,
1785
+ systemPrompt: agentConfig.systemPrompt
1786
+ }, llm, memory);
1455
1787
  this.specialistManager = new SpecialistAgentManager(
1456
1788
  this.db,
1457
1789
  this.sessionId,
@@ -1468,13 +1800,13 @@ Always provide clear, actionable information with steps to reproduce. Think step
1468
1800
  if (!this.agent) {
1469
1801
  await this.initialize();
1470
1802
  }
1471
- const cfg = this.config.getConfig();
1803
+ const cfg = await this.config.getConfig();
1472
1804
  console.log(`\u{1F680} Starting test session for ${cfg.saas.url}`);
1473
1805
  try {
1474
1806
  const result = await this.agent.run(
1475
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.`
1476
1808
  );
1477
- this.db.updateSession(this.sessionId, {
1809
+ await this.db.updateSession(this.sessionId, {
1478
1810
  status: "completed",
1479
1811
  ended_at: (/* @__PURE__ */ new Date()).toISOString()
1480
1812
  });
@@ -1482,7 +1814,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
1482
1814
  return result;
1483
1815
  } catch (error) {
1484
1816
  console.error("\u274C Session error:", error);
1485
- this.db.updateSession(this.sessionId, {
1817
+ await this.db.updateSession(this.sessionId, {
1486
1818
  status: "failed",
1487
1819
  ended_at: (/* @__PURE__ */ new Date()).toISOString()
1488
1820
  });
@@ -1499,7 +1831,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
1499
1831
  return;
1500
1832
  }
1501
1833
  this.isRunning = true;
1502
- const cfg = this.config.getConfig();
1834
+ const cfg = await this.config.getConfig();
1503
1835
  console.log(`\u{1F916} OpenQA Agent starting in autonomous mode`);
1504
1836
  console.log(`\u{1F4CD} Target: ${cfg.saas.url}`);
1505
1837
  console.log(`\u23F1\uFE0F Interval: ${cfg.agent.intervalMs}ms (${cfg.agent.intervalMs / 1e3 / 60} minutes)`);
@@ -1540,7 +1872,7 @@ Always provide clear, actionable information with steps to reproduce. Think step
1540
1872
  }
1541
1873
  // Git integration
1542
1874
  async startGitListener() {
1543
- const cfg = this.config.getConfig();
1875
+ const cfg = await this.config.getConfig();
1544
1876
  if (cfg.github?.token && cfg.github?.owner && cfg.github?.repo) {
1545
1877
  this.gitListener = new GitListener({
1546
1878
  provider: "github",
@@ -1588,14 +1920,14 @@ Always provide clear, actionable information with steps to reproduce. Think step
1588
1920
  if (!this.specialistManager) {
1589
1921
  await this.initialize();
1590
1922
  }
1591
- const cfg = this.config.getConfig();
1923
+ const cfg = await this.config.getConfig();
1592
1924
  await this.specialistManager.runSecuritySuite(cfg.saas.url);
1593
1925
  }
1594
1926
  async runSpecialist(type) {
1595
1927
  if (!this.specialistManager) {
1596
1928
  await this.initialize();
1597
1929
  }
1598
- const cfg = this.config.getConfig();
1930
+ const cfg = await this.config.getConfig();
1599
1931
  const agentId = this.specialistManager.createSpecialist(type);
1600
1932
  await this.specialistManager.runSpecialist(agentId, cfg.saas.url);
1601
1933
  }
@@ -1618,11 +1950,11 @@ Always provide clear, actionable information with steps to reproduce. Think step
1618
1950
  toggleSkill(id) {
1619
1951
  return this.skillManager.toggleSkill(id);
1620
1952
  }
1621
- getStatus() {
1953
+ async getStatus() {
1622
1954
  return {
1623
1955
  isRunning: this.isRunning,
1624
1956
  sessionId: this.sessionId,
1625
- config: this.config.getConfig(),
1957
+ config: await this.config.getConfig(),
1626
1958
  gitListenerActive: !!this.gitListener,
1627
1959
  specialists: this.getSpecialistStatuses(),
1628
1960
  skills: this.skillManager.getEnabledSkills().length