@openqa/cli 1.0.2 → 1.0.3

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.
@@ -1,35 +1,62 @@
1
1
  #!/usr/bin/env node
2
2
  #!/usr/bin/env node
3
+ "use strict";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // node_modules/tsup/assets/cjs_shims.js
28
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
29
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
3
30
 
4
31
  // cli/index.ts
5
- import { Command } from "commander";
32
+ var import_commander = require("commander");
6
33
 
7
34
  // agent/index.ts
8
- import { ReActAgent as ReActAgent2 } from "@orka-js/agent";
9
- import { OpenAIAdapter as OpenAIAdapter2 } from "@orka-js/openai";
10
- import { AnthropicAdapter as AnthropicAdapter2 } from "@orka-js/anthropic";
11
- import { SessionMemory } from "@orka-js/memory-store";
12
- import { Tracer } from "@orka-js/observability";
13
- import { EventEmitter as EventEmitter3 } from "events";
35
+ var import_agent2 = require("@orka-js/agent");
36
+ var import_openai2 = require("@orka-js/openai");
37
+ var import_anthropic2 = require("@orka-js/anthropic");
38
+ var import_memory_store = require("@orka-js/memory-store");
39
+ var import_observability = require("@orka-js/observability");
40
+ var import_events3 = require("events");
14
41
 
15
42
  // database/index.ts
16
- import Database from "better-sqlite3";
17
- import { readFileSync } from "fs";
18
- import { join, dirname } from "path";
19
- import { fileURLToPath } from "url";
20
- import { mkdirSync } from "fs";
21
- var __filename = fileURLToPath(import.meta.url);
22
- var __dirname = dirname(__filename);
43
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
44
+ var import_fs = require("fs");
45
+ var import_path = require("path");
46
+ var import_url = require("url");
47
+ var import_fs2 = require("fs");
48
+ var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
49
+ var __dirname = (0, import_path.dirname)(__filename2);
23
50
  var OpenQADatabase = class {
24
51
  db;
25
52
  constructor(dbPath = "./data/openqa.db") {
26
- const dir = dirname(dbPath);
27
- mkdirSync(dir, { recursive: true });
28
- this.db = new Database(dbPath);
53
+ const dir = (0, import_path.dirname)(dbPath);
54
+ (0, import_fs2.mkdirSync)(dir, { recursive: true });
55
+ this.db = new import_better_sqlite3.default(dbPath);
29
56
  this.initialize();
30
57
  }
31
58
  initialize() {
32
- const schema = readFileSync(join(__dirname, "schema.sql"), "utf-8");
59
+ const schema = (0, import_fs.readFileSync)((0, import_path.join)(__dirname, "schema.sql"), "utf-8");
33
60
  this.db.exec(schema);
34
61
  }
35
62
  getConfig(key) {
@@ -134,8 +161,8 @@ var OpenQADatabase = class {
134
161
  };
135
162
 
136
163
  // agent/config/index.ts
137
- import { config as dotenvConfig } from "dotenv";
138
- dotenvConfig();
164
+ var import_dotenv = require("dotenv");
165
+ (0, import_dotenv.config)();
139
166
  var ConfigManager = class {
140
167
  db;
141
168
  envConfig;
@@ -213,9 +240,9 @@ var ConfigManager = class {
213
240
  };
214
241
 
215
242
  // agent/tools/browser.ts
216
- import { chromium } from "playwright";
217
- import { mkdirSync as mkdirSync2 } from "fs";
218
- import { join as join2 } from "path";
243
+ var import_playwright = require("playwright");
244
+ var import_fs3 = require("fs");
245
+ var import_path2 = require("path");
219
246
  var BrowserTools = class {
220
247
  browser = null;
221
248
  page = null;
@@ -225,10 +252,10 @@ var BrowserTools = class {
225
252
  constructor(db, sessionId) {
226
253
  this.db = db;
227
254
  this.sessionId = sessionId;
228
- mkdirSync2(this.screenshotDir, { recursive: true });
255
+ (0, import_fs3.mkdirSync)(this.screenshotDir, { recursive: true });
229
256
  }
230
257
  async initialize() {
231
- this.browser = await chromium.launch({ headless: true });
258
+ this.browser = await import_playwright.chromium.launch({ headless: true });
232
259
  const context = await this.browser.newContext({
233
260
  viewport: { width: 1920, height: 1080 },
234
261
  userAgent: "OpenQA/1.0 (Automated Testing Agent)"
@@ -332,7 +359,7 @@ var BrowserTools = class {
332
359
  if (!this.page) return "Browser not initialized. Navigate to a page first.";
333
360
  try {
334
361
  const filename = `${Date.now()}_${name}.png`;
335
- const path = join2(this.screenshotDir, filename);
362
+ const path = (0, import_path2.join)(this.screenshotDir, filename);
336
363
  await this.page.screenshot({ path, fullPage: true });
337
364
  this.db.createAction({
338
365
  session_id: this.sessionId,
@@ -398,7 +425,7 @@ ${errors.join("\n")}`;
398
425
  };
399
426
 
400
427
  // agent/tools/github.ts
401
- import { Octokit } from "@octokit/rest";
428
+ var import_rest = require("@octokit/rest");
402
429
  var GitHubTools = class {
403
430
  octokit = null;
404
431
  db;
@@ -409,7 +436,7 @@ var GitHubTools = class {
409
436
  this.sessionId = sessionId;
410
437
  this.config = config;
411
438
  if (config.token) {
412
- this.octokit = new Octokit({ auth: config.token });
439
+ this.octokit = new import_rest.Octokit({ auth: config.token });
413
440
  }
414
441
  }
415
442
  getTools() {
@@ -594,9 +621,9 @@ Total: ${tickets.length} tickets
594
621
  };
595
622
 
596
623
  // agent/webhooks/git-listener.ts
597
- import { EventEmitter } from "events";
598
- import { Octokit as Octokit2 } from "@octokit/rest";
599
- var GitListener = class extends EventEmitter {
624
+ var import_events = require("events");
625
+ var import_rest2 = require("@octokit/rest");
626
+ var GitListener = class extends import_events.EventEmitter {
600
627
  config;
601
628
  octokit = null;
602
629
  lastCommitSha = null;
@@ -612,7 +639,7 @@ var GitListener = class extends EventEmitter {
612
639
  ...config
613
640
  };
614
641
  if (config.provider === "github" && config.token) {
615
- this.octokit = new Octokit2({ auth: config.token });
642
+ this.octokit = new import_rest2.Octokit({ auth: config.token });
616
643
  }
617
644
  }
618
645
  async start() {
@@ -881,10 +908,10 @@ var GitListener = class extends EventEmitter {
881
908
  };
882
909
 
883
910
  // agent/specialists/index.ts
884
- import { ReActAgent } from "@orka-js/agent";
885
- import { OpenAIAdapter } from "@orka-js/openai";
886
- import { AnthropicAdapter } from "@orka-js/anthropic";
887
- import { EventEmitter as EventEmitter2 } from "events";
911
+ var import_agent = require("@orka-js/agent");
912
+ var import_openai = require("@orka-js/openai");
913
+ var import_anthropic = require("@orka-js/anthropic");
914
+ var import_events2 = require("events");
888
915
  var SPECIALIST_PROMPTS = {
889
916
  "form-tester": `You are a Form Testing Specialist. Your mission:
890
917
  - Find all forms on the page (login, signup, contact, search, etc.)
@@ -973,7 +1000,7 @@ var SPECIALIST_PROMPTS = {
973
1000
  - Test pagination and infinite scroll
974
1001
  - Report navigation issues with affected URLs`
975
1002
  };
976
- var SpecialistAgentManager = class extends EventEmitter2 {
1003
+ var SpecialistAgentManager = class extends import_events2.EventEmitter {
977
1004
  agents = /* @__PURE__ */ new Map();
978
1005
  agentStatuses = /* @__PURE__ */ new Map();
979
1006
  db;
@@ -989,12 +1016,12 @@ var SpecialistAgentManager = class extends EventEmitter2 {
989
1016
  }
990
1017
  createLLMAdapter() {
991
1018
  if (this.llmConfig.provider === "anthropic") {
992
- return new AnthropicAdapter({
1019
+ return new import_anthropic.AnthropicAdapter({
993
1020
  apiKey: this.llmConfig.apiKey,
994
1021
  model: this.llmConfig.model || "claude-3-5-sonnet-20241022"
995
1022
  });
996
1023
  }
997
- return new OpenAIAdapter({
1024
+ return new import_openai.OpenAIAdapter({
998
1025
  apiKey: this.llmConfig.apiKey,
999
1026
  model: this.llmConfig.model || "gpt-4"
1000
1027
  });
@@ -1002,7 +1029,7 @@ var SpecialistAgentManager = class extends EventEmitter2 {
1002
1029
  createSpecialist(type, customPrompt) {
1003
1030
  const agentId = `${type}_${Date.now()}`;
1004
1031
  const systemPrompt = customPrompt || SPECIALIST_PROMPTS[type];
1005
- const agent = new ReActAgent({
1032
+ const agent = new import_agent.ReActAgent({
1006
1033
  llm: this.createLLMAdapter(),
1007
1034
  tools: this.browserTools.getTools(),
1008
1035
  maxIterations: 15,
@@ -1311,7 +1338,7 @@ Remember to report findings from each skill separately.
1311
1338
  };
1312
1339
 
1313
1340
  // agent/index.ts
1314
- var OpenQAAgent = class extends EventEmitter3 {
1341
+ var OpenQAAgent = class extends import_events3.EventEmitter {
1315
1342
  agent = null;
1316
1343
  db;
1317
1344
  config;
@@ -1333,13 +1360,13 @@ var OpenQAAgent = class extends EventEmitter3 {
1333
1360
  const cfg = this.config.getConfig();
1334
1361
  switch (cfg.llm.provider) {
1335
1362
  case "anthropic":
1336
- return new AnthropicAdapter2({
1363
+ return new import_anthropic2.AnthropicAdapter({
1337
1364
  apiKey: cfg.llm.apiKey || process.env.ANTHROPIC_API_KEY,
1338
1365
  model: cfg.llm.model || "claude-3-5-sonnet-20241022"
1339
1366
  });
1340
1367
  case "openai":
1341
1368
  default:
1342
- return new OpenAIAdapter2({
1369
+ return new import_openai2.OpenAIAdapter({
1343
1370
  apiKey: cfg.llm.apiKey || process.env.OPENAI_API_KEY,
1344
1371
  model: cfg.llm.model || "gpt-4"
1345
1372
  });
@@ -1363,8 +1390,8 @@ var OpenQAAgent = class extends EventEmitter3 {
1363
1390
  ...kanbanTools.getTools()
1364
1391
  ];
1365
1392
  const llm = this.createLLMAdapter();
1366
- const memory = new SessionMemory({ maxMessages: 50 });
1367
- const tracer = new Tracer({ logLevel: "info" });
1393
+ const memory = new import_memory_store.SessionMemory({ maxMessages: 50 });
1394
+ const tracer = new import_observability.Tracer({ logLevel: "info" });
1368
1395
  const enabledSkills = this.skillManager.getEnabledSkills();
1369
1396
  const skillPrompt = this.skillManager.generateSkillPrompt(enabledSkills);
1370
1397
  const agentConfig = {
@@ -1403,7 +1430,7 @@ ${skillPrompt}
1403
1430
 
1404
1431
  Always provide clear, actionable information with steps to reproduce. Think step by step like a human QA expert.`
1405
1432
  };
1406
- this.agent = new ReActAgent2(agentConfig, llm, memory);
1433
+ this.agent = new import_agent2.ReActAgent(agentConfig, llm, memory);
1407
1434
  this.specialistManager = new SpecialistAgentManager(
1408
1435
  this.db,
1409
1436
  this.sessionId,
@@ -1583,84 +1610,84 @@ Always provide clear, actionable information with steps to reproduce. Think step
1583
1610
  };
1584
1611
 
1585
1612
  // cli/index.ts
1586
- import { spawn } from "child_process";
1587
- import { writeFileSync, readFileSync as readFileSync2, existsSync, unlinkSync } from "fs";
1588
- import { join as join3 } from "path";
1589
- import chalk from "chalk";
1590
- import ora from "ora";
1591
- var program = new Command();
1613
+ var import_child_process = require("child_process");
1614
+ var import_fs4 = require("fs");
1615
+ var import_path3 = require("path");
1616
+ var import_chalk = __toESM(require("chalk"), 1);
1617
+ var import_ora = __toESM(require("ora"), 1);
1618
+ var program = new import_commander.Command();
1592
1619
  var PID_FILE = "./data/openqa.pid";
1593
1620
  program.name("openqa").description("OpenQA - Autonomous QA Testing Agent powered by Orka.js").version("1.0.0");
1594
1621
  program.command("start").description("Start the OpenQA agent and web UI").option("-d, --daemon", "Run in daemon mode").action(async (options) => {
1595
- const spinner = ora("Starting OpenQA...").start();
1622
+ const spinner = (0, import_ora.default)("Starting OpenQA...").start();
1596
1623
  try {
1597
- if (existsSync(PID_FILE)) {
1598
- const pid = readFileSync2(PID_FILE, "utf-8").trim();
1624
+ if ((0, import_fs4.existsSync)(PID_FILE)) {
1625
+ const pid = (0, import_fs4.readFileSync)(PID_FILE, "utf-8").trim();
1599
1626
  try {
1600
1627
  process.kill(parseInt(pid), 0);
1601
- spinner.fail(chalk.red("OpenQA is already running"));
1602
- console.log(chalk.yellow(`PID: ${pid}`));
1603
- console.log(chalk.cyan('Run "openqa stop" to stop it first'));
1628
+ spinner.fail(import_chalk.default.red("OpenQA is already running"));
1629
+ console.log(import_chalk.default.yellow(`PID: ${pid}`));
1630
+ console.log(import_chalk.default.cyan('Run "openqa stop" to stop it first'));
1604
1631
  process.exit(1);
1605
1632
  } catch {
1606
- unlinkSync(PID_FILE);
1633
+ (0, import_fs4.unlinkSync)(PID_FILE);
1607
1634
  }
1608
1635
  }
1609
1636
  if (options.daemon) {
1610
- const child = spawn("node", [join3(process.cwd(), "dist/cli/daemon.js")], {
1637
+ const child = (0, import_child_process.spawn)("node", [(0, import_path3.join)(process.cwd(), "dist/cli/daemon.js")], {
1611
1638
  detached: true,
1612
1639
  stdio: "ignore"
1613
1640
  });
1614
1641
  child.unref();
1615
- writeFileSync(PID_FILE, child.pid.toString());
1616
- spinner.succeed(chalk.green("OpenQA started in daemon mode"));
1617
- console.log(chalk.cyan(`PID: ${child.pid}`));
1642
+ (0, import_fs4.writeFileSync)(PID_FILE, child.pid.toString());
1643
+ spinner.succeed(import_chalk.default.green("OpenQA started in daemon mode"));
1644
+ console.log(import_chalk.default.cyan(`PID: ${child.pid}`));
1618
1645
  } else {
1619
- spinner.succeed(chalk.green("OpenQA started"));
1646
+ spinner.succeed(import_chalk.default.green("OpenQA started"));
1620
1647
  const agent = new OpenQAAgent();
1621
1648
  const config = new ConfigManager();
1622
1649
  const cfg = config.getConfig();
1623
- console.log(chalk.cyan("\n\u{1F4CA} OpenQA Status:"));
1624
- console.log(chalk.white(` Agent: Running`));
1625
- console.log(chalk.white(` Target: ${cfg.saas.url || "Not configured"}`));
1626
- console.log(chalk.white(` Web UI: http://localhost:${cfg.web.port}`));
1627
- console.log(chalk.white(` DevTools: http://localhost:${cfg.web.port}`));
1628
- console.log(chalk.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));
1629
- console.log(chalk.white(` Config: http://localhost:${cfg.web.port}/config`));
1630
- console.log(chalk.gray("\nPress Ctrl+C to stop\n"));
1650
+ console.log(import_chalk.default.cyan("\n\u{1F4CA} OpenQA Status:"));
1651
+ console.log(import_chalk.default.white(` Agent: Running`));
1652
+ console.log(import_chalk.default.white(` Target: ${cfg.saas.url || "Not configured"}`));
1653
+ console.log(import_chalk.default.white(` Web UI: http://localhost:${cfg.web.port}`));
1654
+ console.log(import_chalk.default.white(` DevTools: http://localhost:${cfg.web.port}`));
1655
+ console.log(import_chalk.default.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));
1656
+ console.log(import_chalk.default.white(` Config: http://localhost:${cfg.web.port}/config`));
1657
+ console.log(import_chalk.default.gray("\nPress Ctrl+C to stop\n"));
1631
1658
  if (cfg.agent.autoStart) {
1632
1659
  await agent.startAutonomous();
1633
1660
  } else {
1634
- console.log(chalk.yellow("Auto-start disabled. Agent is idle."));
1635
- console.log(chalk.cyan("Set AGENT_AUTO_START=true to enable autonomous mode"));
1661
+ console.log(import_chalk.default.yellow("Auto-start disabled. Agent is idle."));
1662
+ console.log(import_chalk.default.cyan("Set AGENT_AUTO_START=true to enable autonomous mode"));
1636
1663
  }
1637
1664
  }
1638
1665
  } catch (error) {
1639
- spinner.fail(chalk.red("Failed to start OpenQA"));
1640
- console.error(chalk.red(error.message));
1666
+ spinner.fail(import_chalk.default.red("Failed to start OpenQA"));
1667
+ console.error(import_chalk.default.red(error.message));
1641
1668
  process.exit(1);
1642
1669
  }
1643
1670
  });
1644
1671
  program.command("stop").description("Stop the OpenQA agent").action(() => {
1645
- const spinner = ora("Stopping OpenQA...").start();
1672
+ const spinner = (0, import_ora.default)("Stopping OpenQA...").start();
1646
1673
  try {
1647
- if (!existsSync(PID_FILE)) {
1648
- spinner.fail(chalk.red("OpenQA is not running"));
1674
+ if (!(0, import_fs4.existsSync)(PID_FILE)) {
1675
+ spinner.fail(import_chalk.default.red("OpenQA is not running"));
1649
1676
  process.exit(1);
1650
1677
  }
1651
- const pid = readFileSync2(PID_FILE, "utf-8").trim();
1678
+ const pid = (0, import_fs4.readFileSync)(PID_FILE, "utf-8").trim();
1652
1679
  try {
1653
1680
  process.kill(parseInt(pid), "SIGTERM");
1654
- unlinkSync(PID_FILE);
1655
- spinner.succeed(chalk.green("OpenQA stopped"));
1681
+ (0, import_fs4.unlinkSync)(PID_FILE);
1682
+ spinner.succeed(import_chalk.default.green("OpenQA stopped"));
1656
1683
  } catch (error) {
1657
- spinner.fail(chalk.red("Failed to stop OpenQA"));
1658
- console.error(chalk.red("Process not found. Cleaning up PID file..."));
1659
- unlinkSync(PID_FILE);
1684
+ spinner.fail(import_chalk.default.red("Failed to stop OpenQA"));
1685
+ console.error(import_chalk.default.red("Process not found. Cleaning up PID file..."));
1686
+ (0, import_fs4.unlinkSync)(PID_FILE);
1660
1687
  }
1661
1688
  } catch (error) {
1662
- spinner.fail(chalk.red("Failed to stop OpenQA"));
1663
- console.error(chalk.red(error.message));
1689
+ spinner.fail(import_chalk.default.red("Failed to stop OpenQA"));
1690
+ console.error(import_chalk.default.red(error.message));
1664
1691
  process.exit(1);
1665
1692
  }
1666
1693
  });
@@ -1668,38 +1695,38 @@ program.command("status").description("Show OpenQA status").action(() => {
1668
1695
  const config = new ConfigManager();
1669
1696
  const cfg = config.getConfig();
1670
1697
  const db = new OpenQADatabase(cfg.database.path);
1671
- console.log(chalk.cyan.bold("\n\u{1F4CA} OpenQA Status\n"));
1672
- if (existsSync(PID_FILE)) {
1673
- const pid = readFileSync2(PID_FILE, "utf-8").trim();
1698
+ console.log(import_chalk.default.cyan.bold("\n\u{1F4CA} OpenQA Status\n"));
1699
+ if ((0, import_fs4.existsSync)(PID_FILE)) {
1700
+ const pid = (0, import_fs4.readFileSync)(PID_FILE, "utf-8").trim();
1674
1701
  try {
1675
1702
  process.kill(parseInt(pid), 0);
1676
- console.log(chalk.green("\u2713 Agent: Running"));
1677
- console.log(chalk.white(` PID: ${pid}`));
1703
+ console.log(import_chalk.default.green("\u2713 Agent: Running"));
1704
+ console.log(import_chalk.default.white(` PID: ${pid}`));
1678
1705
  } catch {
1679
- console.log(chalk.red("\u2717 Agent: Stopped (stale PID file)"));
1680
- unlinkSync(PID_FILE);
1706
+ console.log(import_chalk.default.red("\u2717 Agent: Stopped (stale PID file)"));
1707
+ (0, import_fs4.unlinkSync)(PID_FILE);
1681
1708
  }
1682
1709
  } else {
1683
- console.log(chalk.red("\u2717 Agent: Stopped"));
1684
- }
1685
- console.log(chalk.cyan("\n\u{1F310} Web Interfaces:"));
1686
- console.log(chalk.white(` DevTools: http://localhost:${cfg.web.port}`));
1687
- console.log(chalk.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));
1688
- console.log(chalk.white(` Config: http://localhost:${cfg.web.port}/config`));
1689
- console.log(chalk.cyan("\n\u2699\uFE0F Configuration:"));
1690
- console.log(chalk.white(` LLM Provider: ${cfg.llm.provider}`));
1691
- console.log(chalk.white(` Target SaaS: ${cfg.saas.url || "Not configured"}`));
1692
- console.log(chalk.white(` GitHub: ${cfg.github?.token ? "Configured" : "Not configured"}`));
1693
- console.log(chalk.white(` Test Interval: ${cfg.agent.intervalMs / 1e3 / 60} minutes`));
1710
+ console.log(import_chalk.default.red("\u2717 Agent: Stopped"));
1711
+ }
1712
+ console.log(import_chalk.default.cyan("\n\u{1F310} Web Interfaces:"));
1713
+ console.log(import_chalk.default.white(` DevTools: http://localhost:${cfg.web.port}`));
1714
+ console.log(import_chalk.default.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));
1715
+ console.log(import_chalk.default.white(` Config: http://localhost:${cfg.web.port}/config`));
1716
+ console.log(import_chalk.default.cyan("\n\u2699\uFE0F Configuration:"));
1717
+ console.log(import_chalk.default.white(` LLM Provider: ${cfg.llm.provider}`));
1718
+ console.log(import_chalk.default.white(` Target SaaS: ${cfg.saas.url || "Not configured"}`));
1719
+ console.log(import_chalk.default.white(` GitHub: ${cfg.github?.token ? "Configured" : "Not configured"}`));
1720
+ console.log(import_chalk.default.white(` Test Interval: ${cfg.agent.intervalMs / 1e3 / 60} minutes`));
1694
1721
  const sessions = db.getRecentSessions(5);
1695
- console.log(chalk.cyan(`
1722
+ console.log(import_chalk.default.cyan(`
1696
1723
  \u{1F4CB} Recent Sessions (${sessions.length}):`));
1697
1724
  sessions.forEach((s) => {
1698
- const status = s.status === "completed" ? chalk.green("\u2713") : s.status === "failed" ? chalk.red("\u2717") : chalk.yellow("\u27F3");
1699
- console.log(chalk.white(` ${status} ${s.id} - ${s.bugs_found} bugs found`));
1725
+ const status = s.status === "completed" ? import_chalk.default.green("\u2713") : s.status === "failed" ? import_chalk.default.red("\u2717") : import_chalk.default.yellow("\u27F3");
1726
+ console.log(import_chalk.default.white(` ${status} ${s.id} - ${s.bugs_found} bugs found`));
1700
1727
  });
1701
1728
  const bugs = db.getBugsByStatus("open");
1702
- console.log(chalk.cyan(`
1729
+ console.log(import_chalk.default.cyan(`
1703
1730
  \u{1F41B} Open Bugs: ${bugs.length}`));
1704
1731
  const tickets = db.getKanbanTickets();
1705
1732
  const byColumn = {
@@ -1708,42 +1735,42 @@ program.command("status").description("Show OpenQA status").action(() => {
1708
1735
  "in-progress": tickets.filter((t) => t.column === "in-progress").length,
1709
1736
  done: tickets.filter((t) => t.column === "done").length
1710
1737
  };
1711
- console.log(chalk.cyan("\n\u{1F4CA} Kanban Board:"));
1712
- console.log(chalk.white(` Backlog: ${byColumn.backlog}`));
1713
- console.log(chalk.white(` To Do: ${byColumn["to-do"]}`));
1714
- console.log(chalk.white(` In Progress: ${byColumn["in-progress"]}`));
1715
- console.log(chalk.white(` Done: ${byColumn.done}`));
1738
+ console.log(import_chalk.default.cyan("\n\u{1F4CA} Kanban Board:"));
1739
+ console.log(import_chalk.default.white(` Backlog: ${byColumn.backlog}`));
1740
+ console.log(import_chalk.default.white(` To Do: ${byColumn["to-do"]}`));
1741
+ console.log(import_chalk.default.white(` In Progress: ${byColumn["in-progress"]}`));
1742
+ console.log(import_chalk.default.white(` Done: ${byColumn.done}`));
1716
1743
  console.log("");
1717
1744
  });
1718
1745
  program.command("config").description("Manage configuration").argument("[action]", "Action: get, set, list").argument("[key]", "Configuration key (e.g., llm.provider)").argument("[value]", "Configuration value").action((action, key, value) => {
1719
1746
  const config = new ConfigManager();
1720
1747
  if (!action || action === "list") {
1721
1748
  const cfg = config.getConfig();
1722
- console.log(chalk.cyan.bold("\n\u2699\uFE0F OpenQA Configuration\n"));
1749
+ console.log(import_chalk.default.cyan.bold("\n\u2699\uFE0F OpenQA Configuration\n"));
1723
1750
  console.log(JSON.stringify(cfg, null, 2));
1724
1751
  console.log("");
1725
1752
  return;
1726
1753
  }
1727
1754
  if (action === "get") {
1728
1755
  if (!key) {
1729
- console.error(chalk.red('Error: key is required for "get" action'));
1756
+ console.error(import_chalk.default.red('Error: key is required for "get" action'));
1730
1757
  process.exit(1);
1731
1758
  }
1732
1759
  const val = config.get(key);
1733
- console.log(chalk.cyan(`${key}:`), chalk.white(val || "Not set"));
1760
+ console.log(import_chalk.default.cyan(`${key}:`), import_chalk.default.white(val || "Not set"));
1734
1761
  return;
1735
1762
  }
1736
1763
  if (action === "set") {
1737
1764
  if (!key || !value) {
1738
- console.error(chalk.red('Error: key and value are required for "set" action'));
1765
+ console.error(import_chalk.default.red('Error: key and value are required for "set" action'));
1739
1766
  process.exit(1);
1740
1767
  }
1741
1768
  config.set(key, value);
1742
- console.log(chalk.green(`\u2713 Set ${key} = ${value}`));
1769
+ console.log(import_chalk.default.green(`\u2713 Set ${key} = ${value}`));
1743
1770
  return;
1744
1771
  }
1745
- console.error(chalk.red(`Unknown action: ${action}`));
1746
- console.log(chalk.cyan("Available actions: get, set, list"));
1772
+ console.error(import_chalk.default.red(`Unknown action: ${action}`));
1773
+ console.log(import_chalk.default.cyan("Available actions: get, set, list"));
1747
1774
  process.exit(1);
1748
1775
  });
1749
1776
  program.command("logs").description("Show agent logs").option("-f, --follow", "Follow log output").option("-n, --lines <number>", "Number of lines to show", "50").action((options) => {
@@ -1752,28 +1779,27 @@ program.command("logs").description("Show agent logs").option("-f, --follow", "F
1752
1779
  const db = new OpenQADatabase(cfg.database.path);
1753
1780
  const sessions = db.getRecentSessions(1);
1754
1781
  if (sessions.length === 0) {
1755
- console.log(chalk.yellow("No sessions found"));
1782
+ console.log(import_chalk.default.yellow("No sessions found"));
1756
1783
  return;
1757
1784
  }
1758
1785
  const session = sessions[0];
1759
1786
  const actions = db.getSessionActions(session.id);
1760
- console.log(chalk.cyan.bold(`
1787
+ console.log(import_chalk.default.cyan.bold(`
1761
1788
  \u{1F4CB} Session Logs: ${session.id}
1762
1789
  `));
1763
- console.log(chalk.white(`Status: ${session.status}`));
1764
- console.log(chalk.white(`Started: ${session.started_at}`));
1765
- console.log(chalk.white(`Actions: ${actions.length}
1790
+ console.log(import_chalk.default.white(`Status: ${session.status}`));
1791
+ console.log(import_chalk.default.white(`Started: ${session.started_at}`));
1792
+ console.log(import_chalk.default.white(`Actions: ${actions.length}
1766
1793
  `));
1767
1794
  const limit = parseInt(options.lines);
1768
1795
  const displayActions = actions.slice(0, limit);
1769
1796
  displayActions.forEach((action) => {
1770
1797
  const icon = action.type === "navigate" ? "\u{1F310}" : action.type === "click" ? "\u{1F446}" : action.type === "fill" ? "\u2328\uFE0F" : action.type === "screenshot" ? "\u{1F4F8}" : action.type === "github_issue" ? "\u{1F41B}" : action.type === "kanban_ticket" ? "\u{1F4CB}" : "\u2022";
1771
- console.log(chalk.gray(`[${action.timestamp}]`), icon, chalk.white(action.description));
1798
+ console.log(import_chalk.default.gray(`[${action.timestamp}]`), icon, import_chalk.default.white(action.description));
1772
1799
  if (action.output) {
1773
- console.log(chalk.gray(` \u2192 ${action.output}`));
1800
+ console.log(import_chalk.default.gray(` \u2192 ${action.output}`));
1774
1801
  }
1775
1802
  });
1776
1803
  console.log("");
1777
1804
  });
1778
1805
  program.parse();
1779
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@openqa/cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Autonomous QA testing agent powered by Orka.js",
5
5
  "type": "module",
6
- "main": "./dist/cli/index.js",
6
+ "main": "./dist/cli/index.cjs",
7
7
  "bin": {
8
- "openqa": "./dist/cli/index.js"
8
+ "openqa": "./dist/cli/index.cjs"
9
9
  },
10
10
  "files": [
11
11
  "dist",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../cli/index.ts","../../agent/index.ts","../../database/index.ts","../../agent/config/index.ts","../../agent/tools/browser.ts","../../agent/tools/github.ts","../../agent/tools/kanban.ts","../../agent/webhooks/git-listener.ts","../../agent/specialists/index.ts","../../agent/skills/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { OpenQAAgent } from '../agent/index.js';\nimport { ConfigManager } from '../agent/config/index.js';\nimport { OpenQADatabase } from '../database/index.js';\nimport { spawn } from 'child_process';\nimport { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\n\nconst program = new Command();\nconst PID_FILE = './data/openqa.pid';\n\nprogram\n .name('openqa')\n .description('OpenQA - Autonomous QA Testing Agent powered by Orka.js')\n .version('1.0.0');\n\nprogram\n .command('start')\n .description('Start the OpenQA agent and web UI')\n .option('-d, --daemon', 'Run in daemon mode')\n .action(async (options) => {\n const spinner = ora('Starting OpenQA...').start();\n\n try {\n if (existsSync(PID_FILE)) {\n const pid = readFileSync(PID_FILE, 'utf-8').trim();\n try {\n process.kill(parseInt(pid), 0);\n spinner.fail(chalk.red('OpenQA is already running'));\n console.log(chalk.yellow(`PID: ${pid}`));\n console.log(chalk.cyan('Run \"openqa stop\" to stop it first'));\n process.exit(1);\n } catch {\n unlinkSync(PID_FILE);\n }\n }\n\n if (options.daemon) {\n const child = spawn('node', [join(process.cwd(), 'dist/cli/daemon.js')], {\n detached: true,\n stdio: 'ignore'\n });\n child.unref();\n \n writeFileSync(PID_FILE, child.pid!.toString());\n \n spinner.succeed(chalk.green('OpenQA started in daemon mode'));\n console.log(chalk.cyan(`PID: ${child.pid}`));\n } else {\n spinner.succeed(chalk.green('OpenQA started'));\n \n const agent = new OpenQAAgent();\n const config = new ConfigManager();\n const cfg = config.getConfig();\n\n console.log(chalk.cyan('\\n📊 OpenQA Status:'));\n console.log(chalk.white(` Agent: Running`));\n console.log(chalk.white(` Target: ${cfg.saas.url || 'Not configured'}`));\n console.log(chalk.white(` Web UI: http://localhost:${cfg.web.port}`));\n console.log(chalk.white(` DevTools: http://localhost:${cfg.web.port}`));\n console.log(chalk.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));\n console.log(chalk.white(` Config: http://localhost:${cfg.web.port}/config`));\n console.log(chalk.gray('\\nPress Ctrl+C to stop\\n'));\n\n if (cfg.agent.autoStart) {\n await agent.startAutonomous();\n } else {\n console.log(chalk.yellow('Auto-start disabled. Agent is idle.'));\n console.log(chalk.cyan('Set AGENT_AUTO_START=true to enable autonomous mode'));\n }\n }\n } catch (error: any) {\n spinner.fail(chalk.red('Failed to start OpenQA'));\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\nprogram\n .command('stop')\n .description('Stop the OpenQA agent')\n .action(() => {\n const spinner = ora('Stopping OpenQA...').start();\n\n try {\n if (!existsSync(PID_FILE)) {\n spinner.fail(chalk.red('OpenQA is not running'));\n process.exit(1);\n }\n\n const pid = readFileSync(PID_FILE, 'utf-8').trim();\n \n try {\n process.kill(parseInt(pid), 'SIGTERM');\n unlinkSync(PID_FILE);\n spinner.succeed(chalk.green('OpenQA stopped'));\n } catch (error) {\n spinner.fail(chalk.red('Failed to stop OpenQA'));\n console.error(chalk.red('Process not found. Cleaning up PID file...'));\n unlinkSync(PID_FILE);\n }\n } catch (error: any) {\n spinner.fail(chalk.red('Failed to stop OpenQA'));\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\nprogram\n .command('status')\n .description('Show OpenQA status')\n .action(() => {\n const config = new ConfigManager();\n const cfg = config.getConfig();\n const db = new OpenQADatabase(cfg.database.path);\n\n console.log(chalk.cyan.bold('\\n📊 OpenQA Status\\n'));\n\n if (existsSync(PID_FILE)) {\n const pid = readFileSync(PID_FILE, 'utf-8').trim();\n try {\n process.kill(parseInt(pid), 0);\n console.log(chalk.green('✓ Agent: Running'));\n console.log(chalk.white(` PID: ${pid}`));\n } catch {\n console.log(chalk.red('✗ Agent: Stopped (stale PID file)'));\n unlinkSync(PID_FILE);\n }\n } else {\n console.log(chalk.red('✗ Agent: Stopped'));\n }\n\n console.log(chalk.cyan('\\n🌐 Web Interfaces:'));\n console.log(chalk.white(` DevTools: http://localhost:${cfg.web.port}`));\n console.log(chalk.white(` Kanban: http://localhost:${cfg.web.port}/kanban`));\n console.log(chalk.white(` Config: http://localhost:${cfg.web.port}/config`));\n\n console.log(chalk.cyan('\\n⚙️ Configuration:'));\n console.log(chalk.white(` LLM Provider: ${cfg.llm.provider}`));\n console.log(chalk.white(` Target SaaS: ${cfg.saas.url || 'Not configured'}`));\n console.log(chalk.white(` GitHub: ${cfg.github?.token ? 'Configured' : 'Not configured'}`));\n console.log(chalk.white(` Test Interval: ${cfg.agent.intervalMs / 1000 / 60} minutes`));\n\n const sessions = db.getRecentSessions(5);\n console.log(chalk.cyan(`\\n📋 Recent Sessions (${sessions.length}):`));\n sessions.forEach(s => {\n const status = s.status === 'completed' ? chalk.green('✓') : s.status === 'failed' ? chalk.red('✗') : chalk.yellow('⟳');\n console.log(chalk.white(` ${status} ${s.id} - ${s.bugs_found} bugs found`));\n });\n\n const bugs = db.getBugsByStatus('open');\n console.log(chalk.cyan(`\\n🐛 Open Bugs: ${bugs.length}`));\n\n const tickets = db.getKanbanTickets();\n const byColumn = {\n backlog: tickets.filter(t => t.column === 'backlog').length,\n 'to-do': tickets.filter(t => t.column === 'to-do').length,\n 'in-progress': tickets.filter(t => t.column === 'in-progress').length,\n done: tickets.filter(t => t.column === 'done').length\n };\n console.log(chalk.cyan('\\n📊 Kanban Board:'));\n console.log(chalk.white(` Backlog: ${byColumn.backlog}`));\n console.log(chalk.white(` To Do: ${byColumn['to-do']}`));\n console.log(chalk.white(` In Progress: ${byColumn['in-progress']}`));\n console.log(chalk.white(` Done: ${byColumn.done}`));\n console.log('');\n });\n\nprogram\n .command('config')\n .description('Manage configuration')\n .argument('[action]', 'Action: get, set, list')\n .argument('[key]', 'Configuration key (e.g., llm.provider)')\n .argument('[value]', 'Configuration value')\n .action((action, key, value) => {\n const config = new ConfigManager();\n\n if (!action || action === 'list') {\n const cfg = config.getConfig();\n console.log(chalk.cyan.bold('\\n⚙️ OpenQA Configuration\\n'));\n console.log(JSON.stringify(cfg, null, 2));\n console.log('');\n return;\n }\n\n if (action === 'get') {\n if (!key) {\n console.error(chalk.red('Error: key is required for \"get\" action'));\n process.exit(1);\n }\n const val = config.get(key);\n console.log(chalk.cyan(`${key}:`), chalk.white(val || 'Not set'));\n return;\n }\n\n if (action === 'set') {\n if (!key || !value) {\n console.error(chalk.red('Error: key and value are required for \"set\" action'));\n process.exit(1);\n }\n config.set(key, value);\n console.log(chalk.green(`✓ Set ${key} = ${value}`));\n return;\n }\n\n console.error(chalk.red(`Unknown action: ${action}`));\n console.log(chalk.cyan('Available actions: get, set, list'));\n process.exit(1);\n });\n\nprogram\n .command('logs')\n .description('Show agent logs')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --lines <number>', 'Number of lines to show', '50')\n .action((options) => {\n const config = new ConfigManager();\n const cfg = config.getConfig();\n const db = new OpenQADatabase(cfg.database.path);\n\n const sessions = db.getRecentSessions(1);\n if (sessions.length === 0) {\n console.log(chalk.yellow('No sessions found'));\n return;\n }\n\n const session = sessions[0];\n const actions = db.getSessionActions(session.id);\n\n console.log(chalk.cyan.bold(`\\n📋 Session Logs: ${session.id}\\n`));\n console.log(chalk.white(`Status: ${session.status}`));\n console.log(chalk.white(`Started: ${session.started_at}`));\n console.log(chalk.white(`Actions: ${actions.length}\\n`));\n\n const limit = parseInt(options.lines);\n const displayActions = actions.slice(0, limit);\n\n displayActions.forEach(action => {\n const icon = action.type === 'navigate' ? '🌐' : \n action.type === 'click' ? '👆' :\n action.type === 'fill' ? '⌨️' :\n action.type === 'screenshot' ? '📸' :\n action.type === 'github_issue' ? '🐛' :\n action.type === 'kanban_ticket' ? '📋' : '•';\n \n console.log(chalk.gray(`[${action.timestamp}]`), icon, chalk.white(action.description));\n if (action.output) {\n console.log(chalk.gray(` → ${action.output}`));\n }\n });\n\n console.log('');\n });\n\nprogram.parse();\n","import { ReActAgent } from '@orka-js/agent';\nimport { OpenAIAdapter } from '@orka-js/openai';\nimport { AnthropicAdapter } from '@orka-js/anthropic';\nimport { SessionMemory } from '@orka-js/memory-store';\nimport { Tracer } from '@orka-js/observability';\nimport { EventEmitter } from 'events';\nimport { OpenQADatabase } from '../database/index.js';\nimport { ConfigManager } from './config/index.js';\nimport { BrowserTools } from './tools/browser.js';\nimport { GitHubTools } from './tools/github.js';\nimport { KanbanTools } from './tools/kanban.js';\nimport { GitListener, GitEvent } from './webhooks/git-listener.js';\nimport { SpecialistAgentManager, AgentType, AgentStatus } from './specialists/index.js';\nimport { SkillManager, Skill } from './skills/index.js';\n\nexport class OpenQAAgent extends EventEmitter {\n private agent: ReActAgent | null = null;\n private db: OpenQADatabase;\n private config: ConfigManager;\n private browserTools: BrowserTools | null = null;\n private sessionId: string = '';\n private isRunning: boolean = false;\n private intervalId: NodeJS.Timeout | null = null;\n \n // New v2 features\n private gitListener: GitListener | null = null;\n private specialistManager: SpecialistAgentManager | null = null;\n private skillManager: SkillManager;\n\n constructor(configPath?: string) {\n super();\n this.config = new ConfigManager(configPath);\n this.db = new OpenQADatabase(this.config.get('database.path') || undefined);\n this.skillManager = new SkillManager(this.db);\n }\n\n private createLLMAdapter() {\n const cfg = this.config.getConfig();\n \n switch (cfg.llm.provider) {\n case 'anthropic':\n return new AnthropicAdapter({\n apiKey: cfg.llm.apiKey || process.env.ANTHROPIC_API_KEY!,\n model: cfg.llm.model || 'claude-3-5-sonnet-20241022'\n });\n case 'openai':\n default:\n return new OpenAIAdapter({\n apiKey: cfg.llm.apiKey || process.env.OPENAI_API_KEY!,\n model: cfg.llm.model || 'gpt-4'\n });\n }\n }\n\n async initialize(triggerType: 'manual' | 'scheduled' | 'merge' | 'pipeline' | 'webhook' = 'manual', triggerData?: any) {\n const cfg = this.config.getConfig();\n this.sessionId = `session_${Date.now()}`;\n\n this.db.createSession(this.sessionId, {\n config: cfg,\n started_at: new Date().toISOString(),\n trigger_type: triggerType,\n trigger_data: triggerData ? JSON.stringify(triggerData) : null\n });\n\n this.browserTools = new BrowserTools(this.db, this.sessionId);\n const githubTools = new GitHubTools(this.db, this.sessionId, cfg.github || {});\n const kanbanTools = new KanbanTools(this.db, this.sessionId);\n\n const allTools = [\n ...this.browserTools.getTools(),\n ...githubTools.getTools(),\n ...kanbanTools.getTools()\n ];\n\n const llm = this.createLLMAdapter();\n const memory = new SessionMemory({ maxMessages: 50 });\n const tracer = new Tracer({ logLevel: 'info' });\n\n // Get enabled skills and generate skill prompt\n const enabledSkills = this.skillManager.getEnabledSkills();\n const skillPrompt = this.skillManager.generateSkillPrompt(enabledSkills);\n\n const agentConfig = {\n goal: \"Test the SaaS application comprehensively and identify bugs\",\n tools: allTools,\n tracer,\n maxIterations: cfg.agent.maxIterations,\n systemPrompt: `You are OpenQA, an autonomous QA testing agent - intelligent and thorough like a senior QA engineer.\n\nYour mission:\n1. **Systematically test the SaaS application** at ${cfg.saas.url}\n2. **Create comprehensive test flows** - think like a real user AND a security expert\n3. **Identify bugs and issues** - UI bugs, console errors, broken flows, UX issues, security vulnerabilities\n4. **Report findings appropriately**:\n - Use create_github_issue for critical bugs requiring developer attention\n - Use create_kanban_ticket for QA tracking, minor issues, or improvements\n - You can create BOTH for critical bugs\n5. **Learn from previous sessions** - avoid repeating the same tests\n6. **Spawn specialist agents** when needed for deep testing (security, forms, etc.)\n\nTesting strategy:\n- Start with core user flows (signup, login, main features)\n- Test edge cases and error handling\n- Check for console errors and network issues\n- Test security (SQL injection, XSS, auth bypass)\n- Test forms thoroughly (validation, edge cases)\n- Take screenshots as evidence\n- Document steps to reproduce clearly\n\nReporting guidelines:\n- **Critical/High severity** → GitHub issue + Kanban ticket\n- **Medium severity** → Kanban ticket (optionally GitHub if it blocks users)\n- **Low severity/Improvements** → Kanban ticket only\n\n${skillPrompt}\n\nAlways provide clear, actionable information with steps to reproduce. Think step by step like a human QA expert.`\n };\n\n this.agent = new ReActAgent(agentConfig, llm, memory);\n\n // Initialize specialist manager\n this.specialistManager = new SpecialistAgentManager(\n this.db,\n this.sessionId,\n { provider: cfg.llm.provider, apiKey: cfg.llm.apiKey || '' },\n this.browserTools\n );\n\n // Forward specialist events\n this.specialistManager.on('agent-created', (status: AgentStatus) => this.emit('specialist-created', status));\n this.specialistManager.on('agent-started', (status: AgentStatus) => this.emit('specialist-started', status));\n this.specialistManager.on('agent-completed', (data: any) => this.emit('specialist-completed', data));\n this.specialistManager.on('agent-failed', (data: any) => this.emit('specialist-failed', data));\n\n console.log(`✅ OpenQA Agent initialized (Session: ${this.sessionId})`);\n }\n\n async runSession() {\n if (!this.agent) {\n await this.initialize();\n }\n\n const cfg = this.config.getConfig();\n console.log(`🚀 Starting test session for ${cfg.saas.url}`);\n\n try {\n const result = await this.agent!.run(\n `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.`\n );\n\n this.db.updateSession(this.sessionId, {\n status: 'completed',\n ended_at: new Date().toISOString()\n });\n\n console.log('✅ Test session completed:', result);\n return result;\n } catch (error: any) {\n console.error('❌ Session error:', error);\n \n this.db.updateSession(this.sessionId, {\n status: 'failed',\n ended_at: new Date().toISOString()\n });\n\n throw error;\n } finally {\n if (this.browserTools) {\n await this.browserTools.close();\n }\n }\n }\n\n async startAutonomous() {\n if (this.isRunning) {\n console.log('⚠️ Agent is already running');\n return;\n }\n\n this.isRunning = true;\n const cfg = this.config.getConfig();\n \n console.log(`🤖 OpenQA Agent starting in autonomous mode`);\n console.log(`📍 Target: ${cfg.saas.url}`);\n console.log(`⏱️ Interval: ${cfg.agent.intervalMs}ms (${cfg.agent.intervalMs / 1000 / 60} minutes)`);\n\n // Start Git listener if configured\n await this.startGitListener();\n\n const runLoop = async () => {\n if (!this.isRunning) return;\n\n try {\n await this.runSession();\n } catch (error) {\n console.error('Session failed, will retry on next interval');\n }\n\n if (this.isRunning) {\n this.sessionId = `session_${Date.now()}`;\n this.agent = null;\n this.browserTools = null;\n \n this.intervalId = setTimeout(runLoop, cfg.agent.intervalMs);\n }\n };\n\n await runLoop();\n }\n\n stop() {\n console.log('🛑 Stopping OpenQA Agent...');\n this.isRunning = false;\n \n if (this.intervalId) {\n clearTimeout(this.intervalId);\n this.intervalId = null;\n }\n\n if (this.gitListener) {\n this.gitListener.stop();\n this.gitListener = null;\n }\n\n if (this.specialistManager) {\n this.specialistManager.stopAll();\n }\n\n if (this.browserTools) {\n this.browserTools.close();\n }\n }\n\n // Git integration\n private async startGitListener() {\n const cfg = this.config.getConfig();\n \n // Try GitHub first\n if (cfg.github?.token && cfg.github?.owner && cfg.github?.repo) {\n this.gitListener = new GitListener({\n provider: 'github',\n token: cfg.github.token,\n owner: cfg.github.owner,\n repo: cfg.github.repo,\n branch: 'main',\n pollIntervalMs: 60000\n });\n }\n // Try GitLab\n else if (this.config.get('gitlab.token') && this.config.get('gitlab.project')) {\n const [owner, repo] = (this.config.get('gitlab.project') || '').split('/');\n this.gitListener = new GitListener({\n provider: 'gitlab',\n token: this.config.get('gitlab.token') || '',\n owner,\n repo,\n branch: 'main',\n pollIntervalMs: 60000,\n gitlabUrl: this.config.get('gitlab.url') || 'https://gitlab.com'\n });\n }\n\n if (this.gitListener) {\n // Listen for merges to trigger tests\n this.gitListener.on('merge', async (event: GitEvent) => {\n console.log(`🔀 Merge detected! Starting test session...`);\n this.emit('git-merge', event);\n \n // Reset and run new session\n this.sessionId = `session_${Date.now()}`;\n this.agent = null;\n this.browserTools = null;\n await this.runSession();\n });\n\n // Listen for successful pipelines\n this.gitListener.on('pipeline-success', async (event: GitEvent) => {\n console.log(`✅ Pipeline success! Starting test session...`);\n this.emit('git-pipeline-success', event);\n \n // Reset and run new session\n this.sessionId = `session_${Date.now()}`;\n this.agent = null;\n this.browserTools = null;\n await this.runSession();\n });\n\n await this.gitListener.start();\n console.log(`🔗 Git listener started for ${this.gitListener ? 'repository' : 'none'}`);\n }\n }\n\n // Specialist agents management\n async runSecurityScan(): Promise<void> {\n if (!this.specialistManager) {\n await this.initialize();\n }\n const cfg = this.config.getConfig();\n await this.specialistManager!.runSecuritySuite(cfg.saas.url);\n }\n\n async runSpecialist(type: AgentType): Promise<void> {\n if (!this.specialistManager) {\n await this.initialize();\n }\n const cfg = this.config.getConfig();\n const agentId = this.specialistManager!.createSpecialist(type);\n await this.specialistManager!.runSpecialist(agentId, cfg.saas.url);\n }\n\n getSpecialistStatuses(): AgentStatus[] {\n return this.specialistManager?.getAllStatuses() || [];\n }\n\n // Skills management\n getSkills(): Skill[] {\n return this.skillManager.getAllSkills();\n }\n\n createSkill(data: Omit<Skill, 'id' | 'createdAt' | 'updatedAt'>): Skill {\n return this.skillManager.createSkill(data);\n }\n\n updateSkill(id: string, updates: Partial<Skill>): Skill | null {\n return this.skillManager.updateSkill(id, updates);\n }\n\n deleteSkill(id: string): boolean {\n return this.skillManager.deleteSkill(id);\n }\n\n toggleSkill(id: string): Skill | null {\n return this.skillManager.toggleSkill(id);\n }\n\n getStatus() {\n return {\n isRunning: this.isRunning,\n sessionId: this.sessionId,\n config: this.config.getConfig(),\n gitListenerActive: !!this.gitListener,\n specialists: this.getSpecialistStatuses(),\n skills: this.skillManager.getEnabledSkills().length\n };\n }\n}\n","import Database from 'better-sqlite3';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync } from 'fs';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface TestSession {\n id: string;\n started_at: string;\n ended_at?: string;\n status: 'running' | 'completed' | 'failed';\n total_actions: number;\n bugs_found: number;\n metadata?: string;\n}\n\nexport interface Action {\n id: string;\n session_id: string;\n timestamp: string;\n type: string;\n description: string;\n input?: string;\n output?: string;\n screenshot_path?: string;\n}\n\nexport interface Bug {\n id: string;\n session_id: string;\n title: string;\n description: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n status: 'open' | 'in-progress' | 'resolved' | 'closed';\n github_issue_url?: string;\n screenshot_path?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface KanbanTicket {\n id: string;\n bug_id?: string;\n title: string;\n description: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n column: 'backlog' | 'to-do' | 'in-progress' | 'done';\n tags?: string;\n screenshot_url?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport class OpenQADatabase {\n private db: Database.Database;\n\n constructor(dbPath: string = './data/openqa.db') {\n const dir = dirname(dbPath);\n mkdirSync(dir, { recursive: true });\n\n this.db = new Database(dbPath);\n this.initialize();\n }\n\n private initialize() {\n const schema = readFileSync(join(__dirname, 'schema.sql'), 'utf-8');\n this.db.exec(schema);\n }\n\n getConfig(key: string): string | null {\n const row = this.db.prepare('SELECT value FROM config WHERE key = ?').get(key) as { value: string } | undefined;\n return row?.value || null;\n }\n\n setConfig(key: string, value: string) {\n this.db.prepare('INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)').run(key, value);\n }\n\n getAllConfig(): Record<string, string> {\n const rows = this.db.prepare('SELECT key, value FROM config').all() as { key: string; value: string }[];\n return Object.fromEntries(rows.map(r => [r.key, r.value]));\n }\n\n createSession(id: string, metadata?: any): TestSession {\n this.db.prepare('INSERT INTO test_sessions (id, status, metadata) VALUES (?, ?, ?)').run(\n id,\n 'running',\n metadata ? JSON.stringify(metadata) : null\n );\n return this.getSession(id)!;\n }\n\n getSession(id: string): TestSession | null {\n return this.db.prepare('SELECT * FROM test_sessions WHERE id = ?').get(id) as TestSession | null;\n }\n\n updateSession(id: string, updates: Partial<TestSession>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE test_sessions SET ${fields} WHERE id = ?`).run(...values);\n }\n\n getRecentSessions(limit: number = 10): TestSession[] {\n return this.db.prepare('SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?').all(limit) as TestSession[];\n }\n\n createAction(action: Omit<Action, 'id' | 'timestamp'>): Action {\n const id = `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO actions (id, session_id, type, description, input, output, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?)').run(\n id,\n action.session_id,\n action.type,\n action.description,\n action.input || null,\n action.output || null,\n action.screenshot_path || null\n );\n return this.db.prepare('SELECT * FROM actions WHERE id = ?').get(id) as Action;\n }\n\n getSessionActions(sessionId: string): Action[] {\n return this.db.prepare('SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC').all(sessionId) as Action[];\n }\n\n createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Bug {\n const id = `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(\n id,\n bug.session_id,\n bug.title,\n bug.description,\n bug.severity,\n bug.status,\n bug.github_issue_url || null,\n bug.screenshot_path || null\n );\n return this.db.prepare('SELECT * FROM bugs WHERE id = ?').get(id) as Bug;\n }\n\n updateBug(id: string, updates: Partial<Bug>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE bugs SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);\n }\n\n getAllBugs(): Bug[] {\n return this.db.prepare('SELECT * FROM bugs ORDER BY created_at DESC').all() as Bug[];\n }\n\n getBugsByStatus(status: Bug['status']): Bug[] {\n return this.db.prepare('SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC').all(status) as Bug[];\n }\n\n createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): KanbanTicket {\n const id = `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.db.prepare('INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(\n id,\n ticket.bug_id || null,\n ticket.title,\n ticket.description,\n ticket.priority,\n ticket.column,\n ticket.tags || null,\n ticket.screenshot_url || null\n );\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE id = ?').get(id) as KanbanTicket;\n }\n\n updateKanbanTicket(id: string, updates: Partial<KanbanTicket>) {\n const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(updates), id];\n this.db.prepare(`UPDATE kanban_tickets SET ${fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);\n }\n\n getKanbanTickets(): KanbanTicket[] {\n return this.db.prepare('SELECT * FROM kanban_tickets ORDER BY created_at DESC').all() as KanbanTicket[];\n }\n\n getKanbanTicketsByColumn(column: KanbanTicket['column']): KanbanTicket[] {\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE column = ? ORDER BY created_at DESC').all(column) as KanbanTicket[];\n }\n\n close() {\n this.db.close();\n }\n}\n","import { config as dotenvConfig } from 'dotenv';\nimport { OpenQADatabase } from '../../database/index.js';\n\ndotenvConfig();\n\nexport interface OpenQAConfig {\n llm: {\n provider: 'openai' | 'anthropic' | 'ollama';\n apiKey?: string;\n model?: string;\n baseUrl?: string;\n };\n saas: {\n url: string;\n authType: 'none' | 'basic' | 'session';\n username?: string;\n password?: string;\n };\n github?: {\n token: string;\n owner: string;\n repo: string;\n };\n agent: {\n intervalMs: number;\n maxIterations: number;\n autoStart: boolean;\n };\n web: {\n port: number;\n host: string;\n };\n database: {\n path: string;\n };\n notifications?: {\n slack?: string;\n discord?: string;\n };\n}\n\nexport class ConfigManager {\n private db: OpenQADatabase;\n private envConfig: OpenQAConfig;\n\n constructor(dbPath?: string) {\n this.db = new OpenQADatabase(dbPath || process.env.DB_PATH || './data/openqa.db');\n this.envConfig = this.loadFromEnv();\n }\n\n private loadFromEnv(): OpenQAConfig {\n return {\n llm: {\n provider: (process.env.LLM_PROVIDER as any) || 'openai',\n apiKey: process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY,\n model: process.env.LLM_MODEL,\n baseUrl: process.env.OLLAMA_BASE_URL\n },\n saas: {\n url: process.env.SAAS_URL || '',\n authType: (process.env.SAAS_AUTH_TYPE as any) || 'none',\n username: process.env.SAAS_USERNAME,\n password: process.env.SAAS_PASSWORD\n },\n github: process.env.GITHUB_TOKEN ? {\n token: process.env.GITHUB_TOKEN,\n owner: process.env.GITHUB_OWNER || '',\n repo: process.env.GITHUB_REPO || ''\n } : undefined,\n agent: {\n intervalMs: parseInt(process.env.AGENT_INTERVAL_MS || '3600000'),\n maxIterations: parseInt(process.env.AGENT_MAX_ITERATIONS || '20'),\n autoStart: process.env.AGENT_AUTO_START === 'true'\n },\n web: {\n port: parseInt(process.env.WEB_PORT || '3000'),\n host: process.env.WEB_HOST || '0.0.0.0'\n },\n database: {\n path: process.env.DB_PATH || './data/openqa.db'\n },\n notifications: {\n slack: process.env.SLACK_WEBHOOK_URL,\n discord: process.env.DISCORD_WEBHOOK_URL\n }\n };\n }\n\n get(key: string): string | null {\n const dbValue = this.db.getConfig(key);\n if (dbValue) return dbValue;\n\n const keys = key.split('.');\n let value: any = this.envConfig;\n for (const k of keys) {\n value = value?.[k];\n }\n return value?.toString() || null;\n }\n\n set(key: string, value: string) {\n this.db.setConfig(key, value);\n }\n\n getAll(): OpenQAConfig {\n const dbConfig = this.db.getAllConfig();\n const merged = { ...this.envConfig };\n\n for (const [key, value] of Object.entries(dbConfig)) {\n const keys = key.split('.');\n let obj: any = merged;\n for (let i = 0; i < keys.length - 1; i++) {\n if (!obj[keys[i]]) obj[keys[i]] = {};\n obj = obj[keys[i]];\n }\n obj[keys[keys.length - 1]] = value;\n }\n\n return merged;\n }\n\n getConfig(): OpenQAConfig {\n return this.getAll();\n }\n}\n","import { chromium, Browser, Page } from 'playwright';\nimport { OpenQADatabase } from '../../database/index.js';\nimport { mkdirSync } from 'fs';\nimport { join } from 'path';\n\nexport class BrowserTools {\n private browser: Browser | null = null;\n private page: Page | null = null;\n private db: OpenQADatabase;\n private sessionId: string;\n private screenshotDir: string = './data/screenshots';\n\n constructor(db: OpenQADatabase, sessionId: string) {\n this.db = db;\n this.sessionId = sessionId;\n mkdirSync(this.screenshotDir, { recursive: true });\n }\n\n async initialize() {\n this.browser = await chromium.launch({ headless: true });\n const context = await this.browser.newContext({\n viewport: { width: 1920, height: 1080 },\n userAgent: 'OpenQA/1.0 (Automated Testing Agent)'\n });\n this.page = await context.newPage();\n }\n\n getTools() {\n return [\n {\n name: 'navigate_to_page',\n description: 'Navigate to a specific URL in the application',\n parameters: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'The URL to navigate to' }\n },\n required: ['url']\n },\n execute: async ({ url }: { url: string }) => {\n if (!this.page) await this.initialize();\n \n try {\n await this.page!.goto(url, { waitUntil: 'networkidle' });\n const title = await this.page!.title();\n \n this.db.createAction({\n session_id: this.sessionId,\n type: 'navigate',\n description: `Navigated to ${url}`,\n input: url,\n output: `Page title: ${title}`\n });\n \n return `Successfully navigated to ${url}. Page title: \"${title}\"`;\n } catch (error: any) {\n return `Failed to navigate: ${error.message}`;\n }\n }\n },\n {\n name: 'click_element',\n description: 'Click on an element using a CSS selector',\n parameters: {\n type: 'object',\n properties: {\n selector: { type: 'string', description: 'CSS selector of the element to click' }\n },\n required: ['selector']\n },\n execute: async ({ selector }: { selector: string }) => {\n if (!this.page) return 'Browser not initialized. Navigate to a page first.';\n \n try {\n await this.page.click(selector, { timeout: 5000 });\n \n this.db.createAction({\n session_id: this.sessionId,\n type: 'click',\n description: `Clicked element: ${selector}`,\n input: selector\n });\n \n return `Successfully clicked element: ${selector}`;\n } catch (error: any) {\n return `Failed to click element: ${error.message}`;\n }\n }\n },\n {\n name: 'fill_input',\n description: 'Fill an input field with text',\n parameters: {\n type: 'object',\n properties: {\n selector: { type: 'string', description: 'CSS selector of the input field' },\n text: { type: 'string', description: 'Text to fill in the input' }\n },\n required: ['selector', 'text']\n },\n execute: async ({ selector, text }: { selector: string; text: string }) => {\n if (!this.page) return 'Browser not initialized. Navigate to a page first.';\n \n try {\n await this.page.fill(selector, text);\n \n this.db.createAction({\n session_id: this.sessionId,\n type: 'fill',\n description: `Filled input ${selector}`,\n input: `${selector} = ${text}`\n });\n \n return `Successfully filled input ${selector} with text`;\n } catch (error: any) {\n return `Failed to fill input: ${error.message}`;\n }\n }\n },\n {\n name: 'take_screenshot',\n description: 'Take a screenshot of the current page for evidence',\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Name for the screenshot file' }\n },\n required: ['name']\n },\n execute: async ({ name }: { name: string }) => {\n if (!this.page) return 'Browser not initialized. Navigate to a page first.';\n \n try {\n const filename = `${Date.now()}_${name}.png`;\n const path = join(this.screenshotDir, filename);\n await this.page.screenshot({ path, fullPage: true });\n \n this.db.createAction({\n session_id: this.sessionId,\n type: 'screenshot',\n description: `Screenshot: ${name}`,\n screenshot_path: path\n });\n \n return `Screenshot saved: ${path}`;\n } catch (error: any) {\n return `Failed to take screenshot: ${error.message}`;\n }\n }\n },\n {\n name: 'get_page_content',\n description: 'Get the text content of the current page',\n parameters: {\n type: 'object',\n properties: {}\n },\n execute: async () => {\n if (!this.page) return 'Browser not initialized. Navigate to a page first.';\n \n try {\n const content = await this.page.textContent('body');\n return content?.slice(0, 1000) || 'No content found';\n } catch (error: any) {\n return `Failed to get content: ${error.message}`;\n }\n }\n },\n {\n name: 'check_console_errors',\n description: 'Check for JavaScript console errors on the page',\n parameters: {\n type: 'object',\n properties: {}\n },\n execute: async () => {\n if (!this.page) return 'Browser not initialized. Navigate to a page first.';\n \n const errors: string[] = [];\n this.page.on('console', msg => {\n if (msg.type() === 'error') {\n errors.push(msg.text());\n }\n });\n \n await this.page.waitForTimeout(2000);\n \n if (errors.length > 0) {\n return `Found ${errors.length} console errors:\\n${errors.join('\\n')}`;\n }\n return 'No console errors detected';\n }\n }\n ];\n }\n\n async close() {\n if (this.browser) {\n await this.browser.close();\n this.browser = null;\n this.page = null;\n }\n }\n}\n","import { Octokit } from '@octokit/rest';\nimport { OpenQADatabase } from '../../database/index.js';\n\nexport class GitHubTools {\n private octokit: Octokit | null = null;\n private db: OpenQADatabase;\n private sessionId: string;\n private config: { token?: string; owner?: string; repo?: string };\n\n constructor(db: OpenQADatabase, sessionId: string, config: { token?: string; owner?: string; repo?: string }) {\n this.db = db;\n this.sessionId = sessionId;\n this.config = config;\n \n if (config.token) {\n this.octokit = new Octokit({ auth: config.token });\n }\n }\n\n getTools() {\n return [\n {\n name: 'create_github_issue',\n description: 'Create a GitHub issue when a critical bug is found. Use this for bugs that require developer attention.',\n parameters: {\n type: 'object',\n properties: {\n title: { type: 'string', description: 'Issue title (concise and descriptive)' },\n body: { type: 'string', description: 'Detailed description with steps to reproduce' },\n severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], description: 'Bug severity' },\n labels: { type: 'array', items: { type: 'string' }, description: 'Labels for the issue' },\n screenshot_path: { type: 'string', description: 'Path to screenshot evidence' }\n },\n required: ['title', 'body', 'severity']\n },\n execute: async ({ title, body, severity, labels = [], screenshot_path }: any) => {\n if (!this.octokit || !this.config.owner || !this.config.repo) {\n return 'GitHub not configured. Please set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO.';\n }\n\n try {\n const severityLabel = `severity: ${severity}`;\n const allLabels = ['automated-qa', severityLabel, ...labels];\n\n const issueBody = `## 🤖 Automated QA Report\n\n${body}\n\n---\n\n**Severity:** ${severity.toUpperCase()}\n**Detected by:** OpenQA Agent\n**Session ID:** ${this.sessionId}\n${screenshot_path ? `**Screenshot:** ${screenshot_path}` : ''}\n\n*This issue was automatically created by OpenQA during automated testing.*`;\n\n const issue = await this.octokit.rest.issues.create({\n owner: this.config.owner,\n repo: this.config.repo,\n title: `[QA] ${title}`,\n body: issueBody,\n labels: allLabels\n });\n\n this.db.createAction({\n session_id: this.sessionId,\n type: 'github_issue',\n description: `Created GitHub issue: ${title}`,\n input: JSON.stringify({ title, severity }),\n output: issue.data.html_url\n });\n\n const bug = this.db.createBug({\n session_id: this.sessionId,\n title,\n description: body,\n severity: severity as any,\n status: 'open',\n github_issue_url: issue.data.html_url,\n screenshot_path\n });\n\n return `✅ GitHub issue created successfully!\\nURL: ${issue.data.html_url}\\nIssue #${issue.data.number}`;\n } catch (error: any) {\n return `❌ Failed to create GitHub issue: ${error.message}`;\n }\n }\n }\n ];\n }\n}\n","import { OpenQADatabase } from '../../database/index.js';\n\nexport class KanbanTools {\n private db: OpenQADatabase;\n private sessionId: string;\n\n constructor(db: OpenQADatabase, sessionId: string) {\n this.db = db;\n this.sessionId = sessionId;\n }\n\n getTools() {\n return [\n {\n name: 'create_kanban_ticket',\n description: 'Create a ticket on the internal Kanban board for QA tracking. Use this for bugs, improvements, or test findings.',\n parameters: {\n type: 'object',\n properties: {\n title: { type: 'string', description: 'Ticket title' },\n description: { type: 'string', description: 'Detailed description' },\n priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], description: 'Ticket priority' },\n column: { type: 'string', enum: ['backlog', 'to-do', 'in-progress', 'done'], description: 'Kanban column' },\n tags: { type: 'array', items: { type: 'string' }, description: 'Tags for categorization' },\n screenshot_path: { type: 'string', description: 'Path to screenshot evidence' }\n },\n required: ['title', 'description', 'priority']\n },\n execute: async ({ title, description, priority, column = 'to-do', tags = [], screenshot_path }: any) => {\n try {\n const allTags = ['automated-qa', ...tags];\n \n const ticket = this.db.createKanbanTicket({\n title,\n description,\n priority: priority as any,\n column: column as any,\n tags: JSON.stringify(allTags),\n screenshot_url: screenshot_path\n });\n\n this.db.createAction({\n session_id: this.sessionId,\n type: 'kanban_ticket',\n description: `Created Kanban ticket: ${title}`,\n input: JSON.stringify({ title, priority, column }),\n output: ticket.id\n });\n\n return `✅ Kanban ticket created successfully!\\nID: ${ticket.id}\\nColumn: ${column}\\nPriority: ${priority}`;\n } catch (error: any) {\n return `❌ Failed to create Kanban ticket: ${error.message}`;\n }\n }\n },\n {\n name: 'update_kanban_ticket',\n description: 'Update an existing Kanban ticket (move columns, change priority, etc.)',\n parameters: {\n type: 'object',\n properties: {\n ticket_id: { type: 'string', description: 'ID of the ticket to update' },\n column: { type: 'string', enum: ['backlog', 'to-do', 'in-progress', 'done'], description: 'New column' },\n priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], description: 'New priority' }\n },\n required: ['ticket_id']\n },\n execute: async ({ ticket_id, column, priority }: any) => {\n try {\n const updates: any = {};\n if (column) updates.column = column;\n if (priority) updates.priority = priority;\n\n this.db.updateKanbanTicket(ticket_id, updates);\n\n return `✅ Kanban ticket ${ticket_id} updated successfully!`;\n } catch (error: any) {\n return `❌ Failed to update Kanban ticket: ${error.message}`;\n }\n }\n },\n {\n name: 'get_kanban_board',\n description: 'Get all tickets from the Kanban board to see current status',\n parameters: {\n type: 'object',\n properties: {}\n },\n execute: async () => {\n try {\n const tickets = this.db.getKanbanTickets();\n \n const byColumn = {\n backlog: tickets.filter(t => t.column === 'backlog'),\n 'to-do': tickets.filter(t => t.column === 'to-do'),\n 'in-progress': tickets.filter(t => t.column === 'in-progress'),\n done: tickets.filter(t => t.column === 'done')\n };\n\n const summary = `\n📊 Kanban Board Status:\n- Backlog: ${byColumn.backlog.length} tickets\n- To Do: ${byColumn['to-do'].length} tickets\n- In Progress: ${byColumn['in-progress'].length} tickets\n- Done: ${byColumn.done.length} tickets\n\nTotal: ${tickets.length} tickets\n `.trim();\n\n return summary;\n } catch (error: any) {\n return `❌ Failed to get Kanban board: ${error.message}`;\n }\n }\n }\n ];\n }\n}\n","import { EventEmitter } from 'events';\nimport { Octokit } from '@octokit/rest';\n\nexport interface GitEvent {\n type: 'merge' | 'push' | 'pipeline_success' | 'pipeline_failure' | 'tag';\n provider: 'github' | 'gitlab';\n branch: string;\n commit: string;\n author: string;\n message: string;\n timestamp: Date;\n pipelineId?: string;\n pipelineStatus?: string;\n changedFiles?: string[];\n}\n\nexport interface GitListenerConfig {\n provider: 'github' | 'gitlab';\n token: string;\n owner: string;\n repo: string;\n branch?: string;\n pollIntervalMs?: number;\n gitlabUrl?: string;\n}\n\ninterface GitLabCommit {\n id: string;\n author_name: string;\n message: string;\n created_at: string;\n parent_ids?: string[];\n}\n\ninterface GitLabPipeline {\n id: number;\n status: string;\n ref: string;\n sha: string;\n created_at: string;\n updated_at: string;\n user?: {\n name: string;\n username: string;\n };\n}\n\ninterface GitLabWebhook {\n id: number;\n url: string;\n push_events: boolean;\n merge_requests_events: boolean;\n pipeline_events: boolean;\n}\n\nexport class GitListener extends EventEmitter {\n private config: GitListenerConfig;\n private octokit: Octokit | null = null;\n private lastCommitSha: string | null = null;\n private lastPipelineId: string | null = null;\n private pollInterval: NodeJS.Timeout | null = null;\n private isRunning: boolean = false;\n\n constructor(config: GitListenerConfig) {\n super();\n this.config = {\n branch: 'main',\n pollIntervalMs: 60000,\n gitlabUrl: 'https://gitlab.com',\n ...config\n };\n\n if (config.provider === 'github' && config.token) {\n this.octokit = new Octokit({ auth: config.token });\n }\n }\n\n async start() {\n if (this.isRunning) return;\n this.isRunning = true;\n\n console.log(`🔗 GitListener started for ${this.config.provider}/${this.config.owner}/${this.config.repo}`);\n \n await this.checkInitialState();\n \n this.pollInterval = setInterval(() => {\n this.poll().catch(console.error);\n }, this.config.pollIntervalMs);\n }\n\n stop() {\n this.isRunning = false;\n if (this.pollInterval) {\n clearInterval(this.pollInterval);\n this.pollInterval = null;\n }\n console.log('🔗 GitListener stopped');\n }\n\n private async checkInitialState() {\n try {\n if (this.config.provider === 'github') {\n await this.checkGitHubState();\n } else {\n await this.checkGitLabState();\n }\n } catch (error) {\n console.error('Failed to check initial state:', error);\n }\n }\n\n private async poll() {\n try {\n if (this.config.provider === 'github') {\n await this.pollGitHub();\n } else {\n await this.pollGitLab();\n }\n } catch (error) {\n console.error('Poll error:', error);\n }\n }\n\n private async checkGitHubState() {\n if (!this.octokit) return;\n\n const { data: commits } = await this.octokit.repos.listCommits({\n owner: this.config.owner,\n repo: this.config.repo,\n sha: this.config.branch,\n per_page: 1\n });\n\n if (commits.length > 0) {\n this.lastCommitSha = commits[0].sha;\n }\n\n try {\n const { data: runs } = await this.octokit.actions.listWorkflowRunsForRepo({\n owner: this.config.owner,\n repo: this.config.repo,\n branch: this.config.branch,\n per_page: 1\n });\n\n if (runs.workflow_runs.length > 0) {\n this.lastPipelineId = runs.workflow_runs[0].id.toString();\n }\n } catch {\n }\n }\n\n private async pollGitHub() {\n if (!this.octokit) return;\n\n const { data: commits } = await this.octokit.repos.listCommits({\n owner: this.config.owner,\n repo: this.config.repo,\n sha: this.config.branch,\n per_page: 5\n });\n\n for (const commit of commits) {\n if (this.lastCommitSha && commit.sha === this.lastCommitSha) break;\n\n const isMerge = commit.parents && commit.parents.length > 1;\n \n const event: GitEvent = {\n type: isMerge ? 'merge' : 'push',\n provider: 'github',\n branch: this.config.branch!,\n commit: commit.sha,\n author: commit.commit.author?.name || 'unknown',\n message: commit.commit.message,\n timestamp: new Date(commit.commit.author?.date || Date.now())\n };\n\n this.emit('git-event', event);\n \n if (isMerge) {\n this.emit('merge', event);\n console.log(`🔀 Merge detected on ${this.config.branch}: ${commit.sha.slice(0, 7)}`);\n }\n }\n\n if (commits.length > 0) {\n this.lastCommitSha = commits[0].sha;\n }\n\n try {\n const { data: runs } = await this.octokit.actions.listWorkflowRunsForRepo({\n owner: this.config.owner,\n repo: this.config.repo,\n branch: this.config.branch,\n per_page: 5\n });\n\n for (const run of runs.workflow_runs) {\n if (this.lastPipelineId && run.id.toString() === this.lastPipelineId) break;\n\n if (run.status === 'completed') {\n const event: GitEvent = {\n type: run.conclusion === 'success' ? 'pipeline_success' : 'pipeline_failure',\n provider: 'github',\n branch: this.config.branch!,\n commit: run.head_sha,\n author: run.actor?.login || 'unknown',\n message: run.name || '',\n timestamp: new Date(run.updated_at || Date.now()),\n pipelineId: run.id.toString(),\n pipelineStatus: run.conclusion || undefined\n };\n\n this.emit('git-event', event);\n \n if (run.conclusion === 'success') {\n this.emit('pipeline-success', event);\n console.log(`✅ Pipeline success: ${run.name} (${run.id})`);\n } else {\n this.emit('pipeline-failure', event);\n console.log(`❌ Pipeline failure: ${run.name} (${run.id})`);\n }\n }\n }\n\n if (runs.workflow_runs.length > 0) {\n this.lastPipelineId = runs.workflow_runs[0].id.toString();\n }\n } catch {\n }\n }\n\n private async checkGitLabState() {\n const headers = { 'PRIVATE-TOKEN': this.config.token };\n const projectPath = encodeURIComponent(`${this.config.owner}/${this.config.repo}`);\n const baseUrl = this.config.gitlabUrl;\n\n try {\n const commitsRes = await fetch(\n `${baseUrl}/api/v4/projects/${projectPath}/repository/commits?ref_name=${this.config.branch}&per_page=1`,\n { headers }\n );\n const commits = await commitsRes.json() as GitLabCommit[];\n if (commits.length > 0) {\n this.lastCommitSha = commits[0].id;\n }\n\n const pipelinesRes = await fetch(\n `${baseUrl}/api/v4/projects/${projectPath}/pipelines?ref=${this.config.branch}&per_page=1`,\n { headers }\n );\n const pipelines = await pipelinesRes.json() as GitLabPipeline[];\n if (pipelines.length > 0) {\n this.lastPipelineId = pipelines[0].id.toString();\n }\n } catch (error) {\n console.error('GitLab initial state error:', error);\n }\n }\n\n private async pollGitLab() {\n const headers = { 'PRIVATE-TOKEN': this.config.token };\n const projectPath = encodeURIComponent(`${this.config.owner}/${this.config.repo}`);\n const baseUrl = this.config.gitlabUrl;\n\n try {\n const commitsRes = await fetch(\n `${baseUrl}/api/v4/projects/${projectPath}/repository/commits?ref_name=${this.config.branch}&per_page=5`,\n { headers }\n );\n const commits = await commitsRes.json() as GitLabCommit[];\n\n for (const commit of commits) {\n if (this.lastCommitSha && commit.id === this.lastCommitSha) break;\n\n const isMerge = commit.parent_ids && commit.parent_ids.length > 1;\n\n const event: GitEvent = {\n type: isMerge ? 'merge' : 'push',\n provider: 'gitlab',\n branch: this.config.branch!,\n commit: commit.id,\n author: commit.author_name,\n message: commit.message,\n timestamp: new Date(commit.created_at)\n };\n\n this.emit('git-event', event);\n \n if (isMerge) {\n this.emit('merge', event);\n console.log(`🔀 Merge detected on ${this.config.branch}: ${commit.id.slice(0, 7)}`);\n }\n }\n\n if (commits.length > 0) {\n this.lastCommitSha = commits[0].id;\n }\n\n const pipelinesRes = await fetch(\n `${baseUrl}/api/v4/projects/${projectPath}/pipelines?ref=${this.config.branch}&per_page=5`,\n { headers }\n );\n const pipelines = await pipelinesRes.json() as GitLabPipeline[];\n\n for (const pipeline of pipelines) {\n if (this.lastPipelineId && pipeline.id.toString() === this.lastPipelineId) break;\n\n if (pipeline.status === 'success' || pipeline.status === 'failed') {\n const event: GitEvent = {\n type: pipeline.status === 'success' ? 'pipeline_success' : 'pipeline_failure',\n provider: 'gitlab',\n branch: this.config.branch!,\n commit: pipeline.sha,\n author: pipeline.user?.name || 'unknown',\n message: `Pipeline #${pipeline.id}`,\n timestamp: new Date(pipeline.updated_at),\n pipelineId: pipeline.id.toString(),\n pipelineStatus: pipeline.status\n };\n\n this.emit('git-event', event);\n \n if (pipeline.status === 'success') {\n this.emit('pipeline-success', event);\n console.log(`✅ Pipeline success: #${pipeline.id}`);\n } else {\n this.emit('pipeline-failure', event);\n console.log(`❌ Pipeline failure: #${pipeline.id}`);\n }\n }\n }\n\n if (pipelines.length > 0) {\n this.lastPipelineId = pipelines[0].id.toString();\n }\n } catch (error) {\n console.error('GitLab poll error:', error);\n }\n }\n\n async setupWebhook(webhookUrl: string): Promise<string> {\n if (this.config.provider === 'github') {\n return this.setupGitHubWebhook(webhookUrl);\n } else {\n return this.setupGitLabWebhook(webhookUrl);\n }\n }\n\n private async setupGitHubWebhook(webhookUrl: string): Promise<string> {\n if (!this.octokit) throw new Error('GitHub not configured');\n\n const { data } = await this.octokit.repos.createWebhook({\n owner: this.config.owner,\n repo: this.config.repo,\n config: {\n url: webhookUrl,\n content_type: 'json'\n },\n events: ['push', 'pull_request', 'workflow_run']\n });\n\n return data.id.toString();\n }\n\n private async setupGitLabWebhook(webhookUrl: string): Promise<string> {\n const headers = { \n 'PRIVATE-TOKEN': this.config.token,\n 'Content-Type': 'application/json'\n };\n const projectPath = encodeURIComponent(`${this.config.owner}/${this.config.repo}`);\n\n const res = await fetch(\n `${this.config.gitlabUrl}/api/v4/projects/${projectPath}/hooks`,\n {\n method: 'POST',\n headers,\n body: JSON.stringify({\n url: webhookUrl,\n push_events: true,\n merge_requests_events: true,\n pipeline_events: true\n })\n }\n );\n\n const data = await res.json() as GitLabWebhook;\n return data.id.toString();\n }\n}\n","import { ReActAgent } from '@orka-js/agent';\nimport { OpenAIAdapter } from '@orka-js/openai';\nimport { AnthropicAdapter } from '@orka-js/anthropic';\nimport { EventEmitter } from 'events';\nimport { OpenQADatabase } from '../../database/index.js';\nimport { BrowserTools } from '../tools/browser.js';\n\nexport type AgentType = \n | 'form-tester'\n | 'security-scanner'\n | 'sql-injection'\n | 'xss-tester'\n | 'component-tester'\n | 'accessibility-tester'\n | 'performance-tester'\n | 'api-tester'\n | 'auth-tester'\n | 'navigation-tester';\n\nexport interface AgentStatus {\n id: string;\n type: AgentType;\n status: 'idle' | 'running' | 'completed' | 'failed';\n currentTask?: string;\n progress: number;\n startedAt?: Date;\n completedAt?: Date;\n findings: number;\n actions: number;\n}\n\nexport interface SpecialistConfig {\n type: AgentType;\n enabled: boolean;\n priority: number;\n maxIterations: number;\n customPrompt?: string;\n}\n\nconst SPECIALIST_PROMPTS: Record<AgentType, string> = {\n 'form-tester': `You are a Form Testing Specialist. Your mission:\n- Find all forms on the page (login, signup, contact, search, etc.)\n- Test form validation (empty fields, invalid formats, boundary values)\n- Test error messages and user feedback\n- Test form submission success/failure scenarios\n- Check for proper field types (email, password, phone)\n- Test autofill behavior\n- Report any form-related bugs with clear reproduction steps`,\n\n 'security-scanner': `You are a Security Scanner Specialist. Your mission:\n- Identify potential security vulnerabilities\n- Check for exposed sensitive data in page source\n- Look for insecure HTTP resources on HTTPS pages\n- Check for missing security headers\n- Identify potential CSRF vulnerabilities\n- Check for information disclosure in error messages\n- Look for hardcoded credentials or API keys\n- Report security issues with severity ratings`,\n\n 'sql-injection': `You are a SQL Injection Testing Specialist. Your mission:\n- Identify input fields that might interact with databases\n- Test common SQL injection payloads (', \", --, ;, OR 1=1, etc.)\n- Test for blind SQL injection (time-based, boolean-based)\n- Check URL parameters for injection vulnerabilities\n- Test search fields, login forms, and filters\n- Document any successful injections with exact payloads\n- Rate severity based on data exposure risk`,\n\n 'xss-tester': `You are an XSS (Cross-Site Scripting) Testing Specialist. Your mission:\n- Find all user input fields that reflect content\n- Test for reflected XSS (<script>, onerror, onload, etc.)\n- Test for stored XSS in comments, profiles, messages\n- Check for DOM-based XSS vulnerabilities\n- Test various encoding bypasses\n- Check if Content-Security-Policy is properly configured\n- Document successful XSS with exact payloads`,\n\n 'component-tester': `You are a UI Component Testing Specialist. Your mission:\n- Test all interactive components (buttons, dropdowns, modals, tabs)\n- Verify component states (hover, active, disabled, loading)\n- Test responsive behavior at different viewport sizes\n- Check for broken layouts or overlapping elements\n- Test keyboard navigation and focus management\n- Verify animations and transitions work correctly\n- Report visual bugs with screenshots`,\n\n 'accessibility-tester': `You are an Accessibility Testing Specialist. Your mission:\n- Check for proper ARIA labels and roles\n- Verify keyboard navigation works for all interactive elements\n- Check color contrast ratios\n- Verify images have alt text\n- Test screen reader compatibility\n- Check for proper heading hierarchy\n- Verify focus indicators are visible\n- Report WCAG violations with severity`,\n\n 'performance-tester': `You are a Performance Testing Specialist. Your mission:\n- Measure page load times\n- Identify slow-loading resources\n- Check for render-blocking resources\n- Monitor network requests and response times\n- Identify memory leaks or excessive DOM nodes\n- Check for unnecessary re-renders\n- Test under simulated slow network conditions\n- Report performance issues with metrics`,\n\n 'api-tester': `You are an API Testing Specialist. Your mission:\n- Monitor network requests made by the application\n- Test API error handling\n- Check for proper authentication on API calls\n- Verify API response formats\n- Test rate limiting behavior\n- Check for exposed internal APIs\n- Verify proper HTTP methods are used\n- Report API issues with request/response details`,\n\n 'auth-tester': `You are an Authentication Testing Specialist. Your mission:\n- Test login with valid/invalid credentials\n- Test password reset flow\n- Check session management (timeout, persistence)\n- Test logout functionality\n- Check for session fixation vulnerabilities\n- Test remember me functionality\n- Verify proper access control on protected pages\n- Test multi-factor authentication if present`,\n\n 'navigation-tester': `You are a Navigation Testing Specialist. Your mission:\n- Test all navigation links and menus\n- Verify breadcrumbs work correctly\n- Test browser back/forward behavior\n- Check for broken links (404s)\n- Test deep linking and URL sharing\n- Verify redirects work properly\n- Test pagination and infinite scroll\n- Report navigation issues with affected URLs`\n};\n\nexport class SpecialistAgentManager extends EventEmitter {\n private agents: Map<string, ReActAgent> = new Map();\n private agentStatuses: Map<string, AgentStatus> = new Map();\n private db: OpenQADatabase;\n private sessionId: string;\n private llmConfig: { provider: string; apiKey: string; model?: string };\n private browserTools: BrowserTools;\n\n constructor(\n db: OpenQADatabase,\n sessionId: string,\n llmConfig: { provider: string; apiKey: string; model?: string },\n browserTools: BrowserTools\n ) {\n super();\n this.db = db;\n this.sessionId = sessionId;\n this.llmConfig = llmConfig;\n this.browserTools = browserTools;\n }\n\n private createLLMAdapter() {\n if (this.llmConfig.provider === 'anthropic') {\n return new AnthropicAdapter({\n apiKey: this.llmConfig.apiKey,\n model: this.llmConfig.model || 'claude-3-5-sonnet-20241022'\n });\n }\n return new OpenAIAdapter({\n apiKey: this.llmConfig.apiKey,\n model: this.llmConfig.model || 'gpt-4'\n });\n }\n\n createSpecialist(type: AgentType, customPrompt?: string): string {\n const agentId = `${type}_${Date.now()}`;\n \n const systemPrompt = customPrompt || SPECIALIST_PROMPTS[type];\n \n const agent = new ReActAgent({\n llm: this.createLLMAdapter(),\n tools: this.browserTools.getTools(),\n maxIterations: 15,\n systemPrompt: `${systemPrompt}\n\nIMPORTANT RULES:\n- Take screenshots as evidence for any bug found\n- Create Kanban tickets for all findings\n- Create GitHub issues for critical/high severity bugs\n- Be thorough but efficient\n- Stop when you've tested the main scenarios for your specialty`\n });\n\n this.agents.set(agentId, agent);\n \n const status: AgentStatus = {\n id: agentId,\n type,\n status: 'idle',\n progress: 0,\n findings: 0,\n actions: 0\n };\n this.agentStatuses.set(agentId, status);\n\n this.emit('agent-created', status);\n \n return agentId;\n }\n\n async runSpecialist(agentId: string, targetUrl: string): Promise<void> {\n const agent = this.agents.get(agentId);\n const status = this.agentStatuses.get(agentId);\n \n if (!agent || !status) {\n throw new Error(`Agent ${agentId} not found`);\n }\n\n status.status = 'running';\n status.startedAt = new Date();\n status.progress = 0;\n this.emit('agent-started', status);\n\n try {\n const result = await agent.run(\n `Test the application at ${targetUrl}. Focus on your specialty area. Report all findings.`\n );\n\n status.status = 'completed';\n status.completedAt = new Date();\n status.progress = 100;\n \n this.emit('agent-completed', { ...status, result });\n \n } catch (error: any) {\n status.status = 'failed';\n status.completedAt = new Date();\n \n this.emit('agent-failed', { ...status, error: error.message });\n }\n }\n\n async runAllSpecialists(targetUrl: string, types?: AgentType[]): Promise<void> {\n const agentTypes = types || [\n 'form-tester',\n 'security-scanner',\n 'component-tester',\n 'navigation-tester'\n ];\n\n const agentIds = agentTypes.map(type => this.createSpecialist(type));\n\n for (const agentId of agentIds) {\n await this.runSpecialist(agentId, targetUrl);\n }\n }\n\n async runSecuritySuite(targetUrl: string): Promise<void> {\n const securityTypes: AgentType[] = [\n 'security-scanner',\n 'sql-injection',\n 'xss-tester',\n 'auth-tester'\n ];\n\n await this.runAllSpecialists(targetUrl, securityTypes);\n }\n\n getAgentStatus(agentId: string): AgentStatus | undefined {\n return this.agentStatuses.get(agentId);\n }\n\n getAllStatuses(): AgentStatus[] {\n return Array.from(this.agentStatuses.values());\n }\n\n stopAgent(agentId: string): void {\n const status = this.agentStatuses.get(agentId);\n if (status && status.status === 'running') {\n status.status = 'failed';\n status.completedAt = new Date();\n this.emit('agent-stopped', status);\n }\n }\n\n stopAll(): void {\n for (const [agentId] of this.agents) {\n this.stopAgent(agentId);\n }\n }\n}\n","import { OpenQADatabase } from '../../database/index.js';\n\nexport interface Skill {\n id: string;\n name: string;\n description: string;\n type: 'directive' | 'test-scenario' | 'custom-check' | 'workflow';\n enabled: boolean;\n priority: number;\n prompt: string;\n triggers?: string[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface SkillExecution {\n skillId: string;\n sessionId: string;\n startedAt: Date;\n completedAt?: Date;\n status: 'running' | 'completed' | 'failed';\n result?: string;\n}\n\nconst DEFAULT_SKILLS: Omit<Skill, 'id' | 'createdAt' | 'updatedAt'>[] = [\n {\n name: 'GDPR Compliance Check',\n description: 'Check for GDPR compliance (cookie consent, privacy policy, data handling)',\n type: 'custom-check',\n enabled: true,\n priority: 1,\n prompt: `Check GDPR compliance:\n- Verify cookie consent banner exists and works\n- Check for privacy policy link\n- Verify data deletion/export options if user accounts exist\n- Check for proper consent checkboxes on forms\n- Report any GDPR violations`,\n triggers: ['eu', 'gdpr', 'privacy', 'cookies']\n },\n {\n name: 'Mobile Responsiveness',\n description: 'Test application on mobile viewport sizes',\n type: 'test-scenario',\n enabled: true,\n priority: 2,\n prompt: `Test mobile responsiveness:\n- Test at 375px width (iPhone)\n- Test at 768px width (tablet)\n- Check for horizontal scrolling issues\n- Verify touch targets are large enough\n- Check navigation menu behavior on mobile\n- Report any responsive design issues`,\n triggers: ['mobile', 'responsive', 'viewport']\n },\n {\n name: 'E-commerce Flow',\n description: 'Test complete e-commerce purchase flow',\n type: 'workflow',\n enabled: false,\n priority: 3,\n prompt: `Test e-commerce flow:\n- Browse products\n- Add items to cart\n- Verify cart updates correctly\n- Test checkout process\n- Test payment form validation\n- Verify order confirmation\n- Report any issues in the purchase flow`,\n triggers: ['shop', 'cart', 'checkout', 'payment', 'ecommerce']\n },\n {\n name: 'Dark Mode Testing',\n description: 'Test dark mode if available',\n type: 'custom-check',\n enabled: true,\n priority: 4,\n prompt: `Test dark mode:\n- Look for dark mode toggle\n- Switch between light and dark modes\n- Check for contrast issues in dark mode\n- Verify all text is readable\n- Check images and icons visibility\n- Report any dark mode specific bugs`,\n triggers: ['dark', 'theme', 'mode']\n },\n {\n name: 'Error Handling',\n description: 'Test application error handling',\n type: 'test-scenario',\n enabled: true,\n priority: 1,\n prompt: `Test error handling:\n- Try accessing non-existent pages (404)\n- Submit forms with invalid data\n- Test with network errors (if possible)\n- Check error message clarity\n- Verify errors don't expose sensitive info\n- Test recovery from error states\n- Report poor error handling`,\n triggers: ['error', '404', 'exception']\n },\n {\n name: 'Rate Limiting Check',\n description: 'Test for rate limiting on sensitive endpoints',\n type: 'custom-check',\n enabled: true,\n priority: 2,\n prompt: `Test rate limiting:\n- Attempt multiple rapid login attempts\n- Test API endpoints for rate limiting\n- Check for CAPTCHA on repeated failures\n- Verify account lockout mechanisms\n- Report missing rate limiting as security issue`,\n triggers: ['rate', 'limit', 'brute', 'ddos']\n }\n];\n\nexport class SkillManager {\n private db: OpenQADatabase;\n private skills: Map<string, Skill> = new Map();\n\n constructor(db: OpenQADatabase) {\n this.db = db;\n this.loadSkills();\n }\n\n private loadSkills() {\n const savedSkills = this.db.getConfig('skills');\n \n if (savedSkills) {\n const parsed = JSON.parse(savedSkills) as Skill[];\n parsed.forEach(skill => this.skills.set(skill.id, skill));\n } else {\n DEFAULT_SKILLS.forEach(skill => {\n this.createSkill(skill);\n });\n }\n }\n\n private saveSkills() {\n const skillsArray = Array.from(this.skills.values());\n this.db.setConfig('skills', JSON.stringify(skillsArray));\n }\n\n createSkill(data: Omit<Skill, 'id' | 'createdAt' | 'updatedAt'>): Skill {\n const skill: Skill = {\n ...data,\n id: `skill_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n createdAt: new Date(),\n updatedAt: new Date()\n };\n\n this.skills.set(skill.id, skill);\n this.saveSkills();\n \n return skill;\n }\n\n updateSkill(id: string, updates: Partial<Omit<Skill, 'id' | 'createdAt'>>): Skill | null {\n const skill = this.skills.get(id);\n if (!skill) return null;\n\n const updated: Skill = {\n ...skill,\n ...updates,\n updatedAt: new Date()\n };\n\n this.skills.set(id, updated);\n this.saveSkills();\n \n return updated;\n }\n\n deleteSkill(id: string): boolean {\n const deleted = this.skills.delete(id);\n if (deleted) {\n this.saveSkills();\n }\n return deleted;\n }\n\n getSkill(id: string): Skill | undefined {\n return this.skills.get(id);\n }\n\n getAllSkills(): Skill[] {\n return Array.from(this.skills.values());\n }\n\n getEnabledSkills(): Skill[] {\n return this.getAllSkills()\n .filter(s => s.enabled)\n .sort((a, b) => a.priority - b.priority);\n }\n\n getSkillsByType(type: Skill['type']): Skill[] {\n return this.getAllSkills().filter(s => s.type === type);\n }\n\n findSkillsByTrigger(text: string): Skill[] {\n const lowerText = text.toLowerCase();\n return this.getEnabledSkills().filter(skill => \n skill.triggers?.some(trigger => lowerText.includes(trigger.toLowerCase()))\n );\n }\n\n generateSkillPrompt(skills: Skill[]): string {\n if (skills.length === 0) return '';\n\n const skillInstructions = skills.map((skill, index) => \n `### Skill ${index + 1}: ${skill.name}\\n${skill.prompt}`\n ).join('\\n\\n');\n\n return `\n## Additional Skills/Directives to Follow\n\nThe following skills have been configured. Execute them as part of your testing:\n\n${skillInstructions}\n\nRemember to report findings from each skill separately.\n`;\n }\n\n toggleSkill(id: string): Skill | null {\n const skill = this.skills.get(id);\n if (!skill) return null;\n\n return this.updateSkill(id, { enabled: !skill.enabled });\n }\n\n reorderSkills(orderedIds: string[]): void {\n orderedIds.forEach((id, index) => {\n const skill = this.skills.get(id);\n if (skill) {\n skill.priority = index + 1;\n skill.updatedAt = new Date();\n }\n });\n this.saveSkills();\n }\n\n exportSkills(): string {\n return JSON.stringify(this.getAllSkills(), null, 2);\n }\n\n importSkills(json: string): number {\n const imported = JSON.parse(json) as Skill[];\n let count = 0;\n\n imported.forEach(skill => {\n const newSkill = this.createSkill({\n name: skill.name,\n description: skill.description,\n type: skill.type,\n enabled: skill.enabled,\n priority: skill.priority,\n prompt: skill.prompt,\n triggers: skill.triggers\n });\n if (newSkill) count++;\n });\n\n return count;\n }\n}\n"],"mappings":"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","names":["ReActAgent","OpenAIAdapter","AnthropicAdapter","EventEmitter","mkdirSync","join","Octokit","EventEmitter","EventEmitter","AnthropicAdapter","OpenAIAdapter","ReActAgent","readFileSync","join"]}