@openqa/cli 2.1.1 → 2.1.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 +1 @@
1
- {"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../database/sqlite.ts","../../agent/index.ts","../../database/index.ts","../../agent/config/index.ts","../../agent/config/schema.ts","../../agent/logger.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":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import Database from 'better-sqlite3';\nimport { mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type { TestSession, Action, Bug, KanbanTicket } from './index.js';\n\nexport class OpenQASQLiteDatabase {\n private db: Database.Database;\n\n constructor(dbPath: string = './data/openqa.db') {\n mkdirSync(dirname(dbPath), { recursive: true });\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.migrate();\n }\n\n private migrate(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS config (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS test_sessions (\n id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n status TEXT NOT NULL DEFAULT 'running',\n total_actions INTEGER NOT NULL DEFAULT 0,\n bugs_found INTEGER NOT NULL DEFAULT 0,\n metadata TEXT\n );\n\n CREATE TABLE IF NOT EXISTS actions (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n type TEXT NOT NULL,\n description TEXT NOT NULL,\n input TEXT,\n output TEXT,\n screenshot_path TEXT,\n FOREIGN KEY (session_id) REFERENCES test_sessions(id)\n );\n\n CREATE TABLE IF NOT EXISTS bugs (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n severity TEXT NOT NULL DEFAULT 'medium',\n status TEXT NOT NULL DEFAULT 'open',\n github_issue_url TEXT,\n screenshot_path TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES test_sessions(id)\n );\n\n CREATE TABLE IF NOT EXISTS kanban_tickets (\n id TEXT PRIMARY KEY,\n bug_id TEXT,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n priority TEXT NOT NULL DEFAULT 'medium',\n column TEXT NOT NULL DEFAULT 'backlog',\n tags TEXT,\n screenshot_url TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n `);\n }\n\n // ── Config ──\n\n async getConfig(key: string): Promise<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 async setConfig(key: string, value: string): Promise<void> {\n this.db.prepare('INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)').run(key, value);\n }\n\n async getAllConfig(): Promise<Record<string, string>> {\n const rows = this.db.prepare('SELECT key, value FROM config').all() as Array<{ key: string; value: string }>;\n return Object.fromEntries(rows.map(r => [r.key, r.value]));\n }\n\n async clearAllConfig(): Promise<void> {\n this.db.prepare('DELETE FROM config').run();\n }\n\n // ── Sessions ──\n\n async createSession(id: string, metadata?: Record<string, unknown>): Promise<TestSession> {\n const session: TestSession = {\n id,\n started_at: new Date().toISOString(),\n status: 'running',\n total_actions: 0,\n bugs_found: 0,\n metadata: metadata ? JSON.stringify(metadata) : undefined,\n };\n this.db.prepare(`\n INSERT INTO test_sessions (id, started_at, status, total_actions, bugs_found, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(session.id, session.started_at, session.status, session.total_actions, session.bugs_found, session.metadata ?? null);\n return session;\n }\n\n async getSession(id: string): Promise<TestSession | null> {\n return (this.db.prepare('SELECT * FROM test_sessions WHERE id = ?').get(id) as TestSession) ?? null;\n }\n\n async updateSession(id: string, updates: Partial<TestSession>): Promise<void> {\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 async getRecentSessions(limit = 10): Promise<TestSession[]> {\n return this.db.prepare('SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?').all(limit) as TestSession[];\n }\n\n // ── Actions ──\n\n async createAction(action: Omit<Action, 'id' | 'timestamp'>): Promise<Action> {\n const newAction: Action = {\n id: `action_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n timestamp: new Date().toISOString(),\n ...action,\n };\n this.db.prepare(`\n INSERT INTO actions (id, session_id, timestamp, type, description, input, output, screenshot_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newAction.id, newAction.session_id, newAction.timestamp,\n newAction.type, newAction.description,\n newAction.input ?? null, newAction.output ?? null, newAction.screenshot_path ?? null,\n );\n return newAction;\n }\n\n async getSessionActions(sessionId: string): Promise<Action[]> {\n return this.db.prepare('SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC').all(sessionId) as Action[];\n }\n\n // ── Bugs ──\n\n async createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Promise<Bug> {\n const newBug: Bug = {\n id: `bug_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...bug,\n };\n this.db.prepare(`\n INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newBug.id, newBug.session_id, newBug.title, newBug.description,\n newBug.severity, newBug.status,\n newBug.github_issue_url ?? null, newBug.screenshot_path ?? null,\n newBug.created_at, newBug.updated_at,\n );\n return newBug;\n }\n\n async updateBug(id: string, updates: Partial<Bug>): Promise<void> {\n const patch = { ...updates, updated_at: new Date().toISOString() };\n const fields = Object.keys(patch).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(patch), id];\n this.db.prepare(`UPDATE bugs SET ${fields} WHERE id = ?`).run(...values);\n }\n\n async getAllBugs(): Promise<Bug[]> {\n return this.db.prepare('SELECT * FROM bugs ORDER BY created_at DESC').all() as Bug[];\n }\n\n async getBugsByStatus(status: Bug['status']): Promise<Bug[]> {\n return this.db.prepare('SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC').all(status) as Bug[];\n }\n\n // ── Kanban ──\n\n async createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): Promise<KanbanTicket> {\n const newTicket: KanbanTicket = {\n id: `ticket_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...ticket,\n };\n this.db.prepare(`\n INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newTicket.id, newTicket.bug_id ?? null, newTicket.title, newTicket.description,\n newTicket.priority, newTicket.column,\n newTicket.tags ?? null, newTicket.screenshot_url ?? null,\n newTicket.created_at, newTicket.updated_at,\n );\n return newTicket;\n }\n\n async updateKanbanTicket(id: string, updates: Partial<KanbanTicket>): Promise<void> {\n const patch = { ...updates, updated_at: new Date().toISOString() };\n const fields = Object.keys(patch).map(k => `\"${k}\" = ?`).join(', ');\n const values = [...Object.values(patch), id];\n this.db.prepare(`UPDATE kanban_tickets SET ${fields} WHERE id = ?`).run(...values);\n }\n\n async getKanbanTickets(): Promise<KanbanTicket[]> {\n return this.db.prepare('SELECT * FROM kanban_tickets ORDER BY created_at DESC').all() as KanbanTicket[];\n }\n\n async getKanbanTicketsByColumn(column: KanbanTicket['column']): Promise<KanbanTicket[]> {\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE \"column\" = ? ORDER BY created_at DESC').all(column) as KanbanTicket[];\n }\n\n async deleteKanbanTicket(id: string): Promise<void> {\n this.db.prepare('DELETE FROM kanban_tickets WHERE id = ?').run(id);\n }\n\n // ── Storage / Cleanup ──\n\n async pruneOldSessions(maxAgeDays: number): Promise<{ sessionsRemoved: number; actionsRemoved: number }> {\n const cutoff = new Date(Date.now() - maxAgeDays * 86400000).toISOString();\n const oldSessions = this.db.prepare('SELECT id FROM test_sessions WHERE started_at < ?').all(cutoff) as Array<{ id: string }>;\n const ids = oldSessions.map(s => s.id);\n if (ids.length === 0) return { sessionsRemoved: 0, actionsRemoved: 0 };\n\n const placeholders = ids.map(() => '?').join(', ');\n const actionsResult = this.db.prepare(`DELETE FROM actions WHERE session_id IN (${placeholders})`).run(...ids);\n this.db.prepare(`DELETE FROM test_sessions WHERE id IN (${placeholders})`).run(...ids);\n\n return { sessionsRemoved: ids.length, actionsRemoved: actionsResult.changes };\n }\n\n async getStorageStats(): Promise<{ sessions: number; actions: number; bugs: number; tickets: number }> {\n const count = (table: string): number =>\n (this.db.prepare(`SELECT COUNT(*) as n FROM ${table}`).get() as { n: number }).n;\n return {\n sessions: count('test_sessions'),\n actions: count('actions'),\n bugs: count('bugs'),\n tickets: count('kanban_tickets'),\n };\n }\n\n // ── Compat helpers (used by daemon.ts) ──\n\n async getActiveAgents() {\n const sessions = await this.getRecentSessions(1);\n const current = sessions[0];\n const isRunning = current?.status === 'running';\n return [{\n name: 'Main Agent',\n status: isRunning ? 'running' : 'idle',\n purpose: 'Autonomous QA orchestration',\n performance: current ? Math.min(100, Math.round((current.total_actions / 100) * 100)) : 0,\n tasks: current?.total_actions ?? 0,\n }];\n }\n\n async getCurrentTasks() {\n const sessions = await this.getRecentSessions(1);\n if (!sessions[0]) return [];\n const actions = await this.getSessionActions(sessions[0].id);\n return actions.slice(0, 10).map((a, i) => ({\n id: a.id, name: a.type, status: i === 0 && sessions[0].status === 'running' ? 'running' : 'completed',\n progress: i === 0 && sessions[0].status === 'running' ? '65%' : '100%',\n agent: 'Main Agent', started_at: a.timestamp, result: a.output || a.description,\n }));\n }\n\n async getCurrentIssues() {\n const bugs = await this.getAllBugs();\n return bugs.slice(0, 10).map(b => ({\n id: b.id, title: b.title, description: b.description,\n severity: b.severity, status: b.status, discovered_at: b.created_at, agent: 'Main Agent',\n }));\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { ReActAgent } from '@orka-js/agent';\nimport { OpenAIAdapter } from '@orka-js/openai';\nimport { AnthropicAdapter } from '@orka-js/anthropic';\nimport { Memory } 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('./data/openqa.json');\n this.skillManager = new SkillManager(this.db);\n }\n\n private createLLMAdapter() {\n const cfg = this.config.getConfigSync();\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?: Record<string, unknown>) {\n const cfg = this.config.getConfigSync();\n this.sessionId = `session_${Date.now()}`;\n\n await this.db.createSession(this.sessionId, {\n config: cfg,\n started_at: new Date().toISOString()\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 Memory({ 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({\n goal: agentConfig.goal,\n tools: allTools,\n maxSteps: cfg.agent.maxIterations,\n systemPrompt: agentConfig.systemPrompt\n }, 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: AgentStatus & { result?: string }) => this.emit('specialist-completed', data));\n this.specialistManager.on('agent-failed', (data: AgentStatus & { error?: string }) => 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 = await 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 await 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: unknown) {\n console.error('❌ Session error:', error);\n\n await 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 = await 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 = await 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 {\n const gitlabToken = await this.config.get('gitlab.token');\n const gitlabProject = await this.config.get('gitlab.project');\n if (gitlabToken && gitlabProject) {\n const [owner, repo] = gitlabProject.split('/');\n const gitlabUrl = await this.config.get('gitlab.url');\n this.gitListener = new GitListener({\n provider: 'gitlab',\n token: gitlabToken,\n owner,\n repo,\n branch: 'main',\n pollIntervalMs: 60000,\n gitlabUrl: gitlabUrl || 'https://gitlab.com'\n });\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 = await 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 = await 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 async getStatus() {\n return {\n isRunning: this.isRunning,\n sessionId: this.sessionId,\n config: await this.config.getConfig(),\n gitListenerActive: !!this.gitListener,\n specialists: this.getSpecialistStatuses(),\n skills: this.skillManager.getEnabledSkills().length\n };\n }\n}\n","import { Low } from 'lowdb';\nimport { JSONFile } from 'lowdb/node';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync, writeFileSync, readFileSync } from 'fs';\n\nexport { OpenQASQLiteDatabase } from './sqlite.js';\n\n/**\n * Factory — chooses SQLite for .db paths, LowDB for .json paths.\n */\nexport async function createDatabase(path: string): Promise<OpenQADatabase> {\n if (path.endsWith('.db')) {\n const { OpenQASQLiteDatabase } = await import('./sqlite.js');\n return new OpenQASQLiteDatabase(path) as unknown as OpenQADatabase;\n }\n return new OpenQADatabase(path);\n}\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 interface User {\n id: string;\n username: string;\n passwordHash: string;\n role: 'admin' | 'viewer';\n createdAt: string;\n updatedAt: string;\n}\n\ninterface DatabaseSchema {\n config: Record<string, string>;\n test_sessions: TestSession[];\n actions: Action[];\n bugs: Bug[];\n kanban_tickets: KanbanTicket[];\n users: User[];\n}\n\nexport class OpenQADatabase {\n private db: Low<DatabaseSchema> | null = null;\n\n constructor(private dbPath: string = './data/openqa.json') {\n this.initialize();\n }\n\n private initialize() {\n const dir = dirname(this.dbPath);\n mkdirSync(dir, { recursive: true });\n\n const adapter = new JSONFile<DatabaseSchema>(this.dbPath);\n this.db = new Low<DatabaseSchema>(adapter, {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: [],\n users: [],\n });\n\n this.db.read();\n if (!this.db.data) {\n this.db.data = {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: [],\n users: [],\n };\n this.db.write();\n }\n }\n\n private async ensureInitialized() {\n if (!this.db) {\n this.initialize();\n }\n await this.db!.read();\n // Auto-migrate: add any missing top-level arrays added in later versions\n let migrated = false;\n if (!this.db!.data.users) { this.db!.data.users = []; migrated = true; }\n if (migrated) await this.db!.write();\n }\n\n async getConfig(key: string): Promise<string | null> {\n await this.ensureInitialized();\n return this.db!.data.config[key] || null;\n }\n\n async setConfig(key: string, value: string) {\n await this.ensureInitialized();\n this.db!.data.config[key] = value;\n await this.db!.write();\n }\n\n async getAllConfig(): Promise<Record<string, string>> {\n await this.ensureInitialized();\n return this.db!.data.config;\n }\n\n async createSession(id: string, metadata?: Record<string, unknown>): Promise<TestSession> {\n await this.ensureInitialized();\n const session: TestSession = {\n id,\n started_at: new Date().toISOString(),\n status: 'running',\n total_actions: 0,\n bugs_found: 0,\n metadata: metadata ? JSON.stringify(metadata) : undefined\n };\n this.db!.data.test_sessions.push(session);\n await this.db!.write();\n return session;\n }\n\n async getSession(id: string): Promise<TestSession | null> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions.find(s => s.id === id) || null;\n }\n\n async updateSession(id: string, updates: Partial<TestSession>) {\n await this.ensureInitialized();\n const index = this.db!.data.test_sessions.findIndex(s => s.id === id);\n if (index !== -1) {\n this.db!.data.test_sessions[index] = { ...this.db!.data.test_sessions[index], ...updates };\n await this.db!.write();\n }\n }\n\n async getRecentSessions(limit: number = 10): Promise<TestSession[]> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions\n .sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime())\n .slice(0, limit);\n }\n\n async createAction(action: Omit<Action, 'id' | 'timestamp'>): Promise<Action> {\n await this.ensureInitialized();\n const newAction: Action = {\n id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n timestamp: new Date().toISOString(),\n ...action\n };\n this.db!.data.actions.push(newAction);\n await this.db!.write();\n return newAction;\n }\n\n async getSessionActions(sessionId: string): Promise<Action[]> {\n await this.ensureInitialized();\n return this.db!.data.actions\n .filter(a => a.session_id === sessionId)\n .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n }\n\n async createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Promise<Bug> {\n await this.ensureInitialized();\n const newBug: Bug = {\n id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...bug\n };\n this.db!.data.bugs.push(newBug);\n await this.db!.write();\n return newBug;\n }\n\n async updateBug(id: string, updates: Partial<Bug>) {\n await this.ensureInitialized();\n const index = this.db!.data.bugs.findIndex(b => b.id === id);\n if (index !== -1) {\n this.db!.data.bugs[index] = { \n ...this.db!.data.bugs[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getAllBugs(): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getBugsByStatus(status: Bug['status']): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs\n .filter(b => b.status === status)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): Promise<KanbanTicket> {\n await this.ensureInitialized();\n const newTicket: KanbanTicket = {\n id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...ticket\n };\n this.db!.data.kanban_tickets.push(newTicket);\n await this.db!.write();\n return newTicket;\n }\n\n async updateKanbanTicket(id: string, updates: Partial<KanbanTicket>) {\n await this.ensureInitialized();\n const index = this.db!.data.kanban_tickets.findIndex(t => t.id === id);\n if (index !== -1) {\n this.db!.data.kanban_tickets[index] = { \n ...this.db!.data.kanban_tickets[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getKanbanTickets(): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getKanbanTicketsByColumn(column: KanbanTicket['column']): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets\n .filter(t => t.column === column)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async deleteKanbanTicket(id: string): Promise<void> {\n await this.ensureInitialized();\n const index = this.db!.data.kanban_tickets.findIndex(t => t.id === id);\n if (index !== -1) {\n this.db!.data.kanban_tickets.splice(index, 1);\n await this.db!.write();\n }\n }\n\n async clearAllConfig() {\n await this.ensureInitialized();\n this.db!.data.config = {};\n await this.db!.write();\n }\n\n // Get real data methods - connected to actual database records\n\n async getActiveAgents() {\n await this.ensureInitialized();\n const sessions = await this.getRecentSessions(1);\n const currentSession = sessions[0];\n \n // Return real agent state based on session status\n const isRunning = currentSession?.status === 'running';\n const totalActions = currentSession?.total_actions || 0;\n \n // Main agent is always present\n const agents = [\n { \n name: 'Main Agent', \n status: isRunning ? 'running' : 'idle', \n purpose: 'Autonomous QA orchestration', \n performance: totalActions > 0 ? Math.min(100, Math.round((totalActions / 100) * 100)) : 0, \n tasks: totalActions \n }\n ];\n \n // Add dynamic agents based on actual session activity\n if (currentSession && totalActions > 0) {\n const actions = await this.getSessionActions(currentSession.id);\n \n // Group actions by type to determine which specialists are active\n const actionTypes = actions.reduce((acc: Record<string, number>, action) => {\n const type = action.type || 'unknown';\n acc[type] = (acc[type] || 0) + 1;\n return acc;\n }, {});\n \n // Add specialists based on actual action types\n if (actionTypes['navigate'] || actionTypes['click'] || actionTypes['screenshot']) {\n agents.push({\n name: 'Browser Specialist',\n status: isRunning ? 'running' : 'idle',\n purpose: 'UI navigation and interaction',\n performance: Math.round(((actionTypes['navigate'] || 0) + (actionTypes['click'] || 0)) / totalActions * 100),\n tasks: (actionTypes['navigate'] || 0) + (actionTypes['click'] || 0)\n });\n }\n \n if (actionTypes['api_call'] || actionTypes['request']) {\n agents.push({\n name: 'API Tester',\n status: isRunning ? 'running' : 'idle',\n purpose: 'API endpoint testing',\n performance: Math.round((actionTypes['api_call'] || actionTypes['request'] || 0) / totalActions * 100),\n tasks: actionTypes['api_call'] || actionTypes['request'] || 0\n });\n }\n \n if (actionTypes['auth'] || actionTypes['login']) {\n agents.push({\n name: 'Auth Specialist',\n status: isRunning ? 'running' : 'idle',\n purpose: 'Authentication testing',\n performance: Math.round((actionTypes['auth'] || actionTypes['login'] || 0) / totalActions * 100),\n tasks: actionTypes['auth'] || actionTypes['login'] || 0\n });\n }\n }\n \n return agents;\n }\n\n async getCurrentTasks() {\n await this.ensureInitialized();\n const sessions = await this.getRecentSessions(1);\n const currentSession = sessions[0];\n \n if (!currentSession) {\n return [];\n }\n\n // Get real actions from the session\n const actions = await this.getSessionActions(currentSession.id);\n \n // Convert recent actions to tasks\n const recentActions = actions.slice(-10).reverse();\n \n return recentActions.map((action, index) => ({\n id: action.id,\n name: action.type || 'Unknown Action',\n status: index === 0 && currentSession.status === 'running' ? 'running' : 'completed',\n progress: index === 0 && currentSession.status === 'running' ? '65%' : '100%',\n agent: 'Main Agent',\n started_at: action.timestamp,\n result: action.output || action.description || 'Completed'\n }));\n }\n\n async getCurrentIssues() {\n await this.ensureInitialized();\n \n // Get real bugs from the database\n const bugs = await this.getAllBugs();\n \n // Return actual bugs as issues\n return bugs.slice(0, 10).map(bug => ({\n id: bug.id,\n title: bug.title,\n description: bug.description,\n severity: bug.severity || 'medium',\n status: bug.status || 'open',\n discovered_at: bug.created_at,\n agent: 'Main Agent'\n }));\n }\n\n async pruneOldSessions(maxAgeDays: number): Promise<{ sessionsRemoved: number; actionsRemoved: number }> {\n await this.ensureInitialized();\n const cutoff = new Date(Date.now() - maxAgeDays * 86400000).toISOString();\n\n const oldSessions = this.db!.data.test_sessions.filter(s => s.started_at < cutoff);\n const oldSessionIds = new Set(oldSessions.map(s => s.id));\n\n const actionsBefore = this.db!.data.actions.length;\n this.db!.data.actions = this.db!.data.actions.filter(a => !oldSessionIds.has(a.session_id));\n const actionsRemoved = actionsBefore - this.db!.data.actions.length;\n\n this.db!.data.test_sessions = this.db!.data.test_sessions.filter(s => s.started_at >= cutoff);\n await this.db!.write();\n\n return { sessionsRemoved: oldSessions.length, actionsRemoved };\n }\n\n async getStorageStats(): Promise<{ sessions: number; actions: number; bugs: number; tickets: number }> {\n await this.ensureInitialized();\n return {\n sessions: this.db!.data.test_sessions.length,\n actions: this.db!.data.actions.length,\n bugs: this.db!.data.bugs.length,\n tickets: this.db!.data.kanban_tickets.length,\n };\n }\n\n // ── User management ──────────────────────────────────────────────────────────\n\n async countUsers(): Promise<number> {\n await this.ensureInitialized();\n return this.db!.data.users.length;\n }\n\n async findUserByUsername(username: string): Promise<User | null> {\n await this.ensureInitialized();\n return this.db!.data.users.find(u => u.username === username) ?? null;\n }\n\n async getUserById(id: string): Promise<User | null> {\n await this.ensureInitialized();\n return this.db!.data.users.find(u => u.id === id) ?? null;\n }\n\n async getAllUsers(): Promise<User[]> {\n await this.ensureInitialized();\n return [...this.db!.data.users];\n }\n\n async createUser(data: { username: string; passwordHash: string; role: User['role'] }): Promise<User> {\n await this.ensureInitialized();\n const now = new Date().toISOString();\n const user: User = {\n id: `user_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,\n username: data.username,\n passwordHash: data.passwordHash,\n role: data.role,\n createdAt: now,\n updatedAt: now,\n };\n this.db!.data.users.push(user);\n await this.db!.write();\n return user;\n }\n\n async updateUser(id: string, updates: Partial<Pick<User, 'passwordHash' | 'role'>>): Promise<void> {\n await this.ensureInitialized();\n const idx = this.db!.data.users.findIndex(u => u.id === id);\n if (idx !== -1) {\n this.db!.data.users[idx] = {\n ...this.db!.data.users[idx],\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n await this.db!.write();\n }\n }\n\n async deleteUser(id: string): Promise<void> {\n await this.ensureInitialized();\n const idx = this.db!.data.users.findIndex(u => u.id === id);\n if (idx !== -1) {\n this.db!.data.users.splice(idx, 1);\n await this.db!.write();\n }\n }\n\n async close() {\n // LowDB doesn't need explicit closing\n }\n}\n","import { config as dotenvConfig } from 'dotenv';\nimport { OpenQADatabase } from '../../database/index.js';\nimport { validateConfigSafe, type ValidatedOpenQAConfig } from './schema.js';\nimport { logger } from '../logger.js';\n\ndotenvConfig();\n\nexport type OpenQAConfig = ValidatedOpenQAConfig;\n\nexport class ConfigManager {\n private db: OpenQADatabase | null = null;\n private envConfig: OpenQAConfig;\n\n constructor(dbPath?: string) {\n // Don't initialize database in constructor to avoid async issues\n this.envConfig = this.loadFromEnv();\n }\n\n private loadFromEnv(): OpenQAConfig {\n const raw = {\n llm: {\n provider: process.env.LLM_PROVIDER || '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 || '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 || '4242'),\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 const result = validateConfigSafe(raw);\n if (!result.success) {\n logger.warn('Config validation warnings', { errors: result.errors });\n // Return raw config with type assertion — Zod defaults won't apply but app can still start\n return raw as OpenQAConfig;\n }\n return result.data;\n }\n\n private getDB(): OpenQADatabase {\n if (!this.db) {\n this.db = new OpenQADatabase('./data/openqa.json');\n }\n return this.db;\n }\n\n async get(key: string): Promise<string | null> {\n const dbValue = await this.getDB().getConfig(key);\n if (dbValue) return dbValue;\n\n const keys = key.split('.');\n let value: unknown = this.envConfig;\n for (const k of keys) {\n if (value && typeof value === 'object') {\n value = (value as Record<string, unknown>)[k];\n } else {\n return null;\n }\n }\n return value != null ? String(value) : null;\n }\n\n async set(key: string, value: string) {\n await this.getDB().setConfig(key, value);\n }\n\n async getAll(): Promise<OpenQAConfig> {\n const dbConfig = await this.getDB().getAllConfig();\n const merged = { ...this.envConfig };\n\n for (const [key, value] of Object.entries(dbConfig)) {\n const keys = key.split('.');\n let obj: Record<string, unknown> = merged as unknown as Record<string, unknown>;\n for (let i = 0; i < keys.length - 1; i++) {\n if (!obj[keys[i]] || typeof obj[keys[i]] !== 'object') obj[keys[i]] = {};\n obj = obj[keys[i]] as Record<string, unknown>;\n }\n obj[keys[keys.length - 1]] = value;\n }\n\n return merged;\n }\n\n async getConfig(): Promise<OpenQAConfig> {\n return await this.getAll();\n }\n\n // Synchronous version that only uses env vars (no DB)\n getConfigSync(): OpenQAConfig {\n return this.envConfig;\n }\n}\n","import { z } from 'zod';\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai', 'anthropic', 'ollama']).default('openai'),\n apiKey: z.string().optional(),\n model: z.string().optional(),\n baseUrl: z.string().url().optional(),\n});\n\nexport const saasConfigSchema = z.object({\n url: z.string().default(''),\n authType: z.enum(['none', 'basic', 'bearer', 'session']).default('none'),\n username: z.string().optional(),\n password: z.string().optional(),\n});\n\nexport const githubConfigSchema = z.object({\n token: z.string().min(1, 'GITHUB_TOKEN is required when GitHub is configured'),\n owner: z.string().default(''),\n repo: z.string().default(''),\n});\n\nexport const agentConfigSchema = z.object({\n intervalMs: z.number().int().positive().default(3600000),\n maxIterations: z.number().int().positive().default(20),\n autoStart: z.boolean().default(false),\n});\n\nexport const webConfigSchema = z.object({\n port: z.number().int().min(1).max(65535).default(4242),\n host: z.string().default('0.0.0.0'),\n});\n\nexport const databaseConfigSchema = z.object({\n path: z.string().default('./data/openqa.db'),\n});\n\nexport const notificationsConfigSchema = z.object({\n slack: z.string().url().optional(),\n discord: z.string().url().optional(),\n});\n\nexport const openQAConfigSchema = z.object({\n llm: llmConfigSchema,\n saas: saasConfigSchema,\n github: githubConfigSchema.optional(),\n agent: agentConfigSchema,\n web: webConfigSchema,\n database: databaseConfigSchema,\n notifications: notificationsConfigSchema.optional(),\n});\n\nexport type ValidatedOpenQAConfig = z.infer<typeof openQAConfigSchema>;\n\n// SaaS application config (used by brain/SaaSConfigManager)\nexport const saasAppConfigSchema = z.object({\n name: z.string().min(1, 'SaaS application name is required'),\n description: z.string().min(1, 'SaaS application description is required'),\n url: z.string().url('SaaS application URL must be a valid URL'),\n repoUrl: z.string().url().optional(),\n localPath: z.string().optional(),\n techStack: z.array(z.string()).optional(),\n authInfo: z.object({\n type: z.enum(['none', 'basic', 'oauth', 'session']),\n testCredentials: z.object({\n username: z.string(),\n password: z.string(),\n }).optional(),\n }).optional(),\n directives: z.array(z.string()).optional(),\n});\n\nexport type ValidatedSaaSAppConfig = z.infer<typeof saasAppConfigSchema>;\n\nexport function validateSaaSAppConfig(config: unknown): ValidatedSaaSAppConfig {\n return saasAppConfigSchema.parse(config);\n}\n\nexport function validateSaaSAppConfigSafe(config: unknown): { success: true; data: ValidatedSaaSAppConfig } | { success: false; errors: string[] } {\n const result = saasAppConfigSchema.safeParse(config);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return {\n success: false,\n errors: result.error.issues.map(i => `${i.path.join('.')}: ${i.message}`),\n };\n}\n\nexport function validateConfig(config: unknown): ValidatedOpenQAConfig {\n return openQAConfigSchema.parse(config);\n}\n\nexport function validateConfigSafe(config: unknown): { success: true; data: ValidatedOpenQAConfig } | { success: false; errors: string[] } {\n const result = openQAConfigSchema.safeParse(config);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return {\n success: false,\n errors: result.error.issues.map(i => `${i.path.join('.')}: ${i.message}`),\n };\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\nconst MIN_LEVEL: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'info';\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVELS[level] >= LEVELS[MIN_LEVEL];\n}\n\nfunction format(level: LogLevel, message: string, context?: Record<string, unknown>): string {\n const entry: Record<string, unknown> = {\n ts: new Date().toISOString(),\n level,\n msg: message,\n ...context,\n };\n return JSON.stringify(entry);\n}\n\nexport const logger = {\n debug(message: string, context?: Record<string, unknown>) {\n if (shouldLog('debug')) process.stdout.write(format('debug', message, context) + '\\n');\n },\n info(message: string, context?: Record<string, unknown>) {\n if (shouldLog('info')) process.stdout.write(format('info', message, context) + '\\n');\n },\n warn(message: string, context?: Record<string, unknown>) {\n if (shouldLog('warn')) process.stderr.write(format('warn', message, context) + '\\n');\n },\n error(message: string, context?: Record<string, unknown>) {\n if (shouldLog('error')) process.stderr.write(format('error', message, context) + '\\n');\n },\n child(defaults: Record<string, unknown>) {\n return {\n debug: (msg: string, ctx?: Record<string, unknown>) => logger.debug(msg, { ...defaults, ...ctx }),\n info: (msg: string, ctx?: Record<string, unknown>) => logger.info(msg, { ...defaults, ...ctx }),\n warn: (msg: string, ctx?: Record<string, unknown>) => logger.warn(msg, { ...defaults, ...ctx }),\n error: (msg: string, ctx?: Record<string, unknown>) => logger.error(msg, { ...defaults, ...ctx }),\n };\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 { name: 'url', type: 'string' as const, description: 'The URL to navigate to', required: true }\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 { output: `Successfully navigated to ${url}. Page title: \"${title}\"` };\n } catch (error: unknown) {\n return { output: `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'click_element',\n description: 'Click on an element using a CSS selector',\n parameters: [\n { name: 'selector', type: 'string' as const, description: 'CSS selector of the element to click', required: true }\n ],\n execute: async ({ selector }: { selector: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Successfully clicked element: ${selector}` };\n } catch (error: unknown) {\n return { output: `Failed to click element: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'fill_input',\n description: 'Fill an input field with text',\n parameters: [\n { name: 'selector', type: 'string' as const, description: 'CSS selector of the input field', required: true },\n { name: 'text', type: 'string' as const, description: 'Text to fill in the input', required: true }\n ],\n execute: async ({ selector, text }: { selector: string; text: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Successfully filled input ${selector} with text` };\n } catch (error: unknown) {\n return { output: `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'take_screenshot',\n description: 'Take a screenshot of the current page for evidence',\n parameters: [\n { name: 'name', type: 'string' as const, description: 'Name for the screenshot file', required: true }\n ],\n execute: async ({ name }: { name: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Screenshot saved: ${path}` };\n } catch (error: unknown) {\n return { output: `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'get_page_content',\n description: 'Get the text content of the current page',\n parameters: [],\n execute: async () => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\n \n try {\n const content = await this.page.textContent('body');\n return { output: content?.slice(0, 1000) || 'No content found' };\n } catch (error: unknown) {\n return { output: `Failed to get content: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'check_console_errors',\n description: 'Check for JavaScript console errors on the page',\n parameters: [],\n execute: async () => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Found ${errors.length} console errors:\\n${errors.join('\\n')}` };\n }\n return { output: '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 { name: 'title', type: 'string' as const, description: 'Issue title (concise and descriptive)', required: true },\n { name: 'body', type: 'string' as const, description: 'Detailed description with steps to reproduce', required: true },\n { name: 'severity', type: 'string' as const, description: 'Bug severity (low, medium, high, critical)', required: true },\n { name: 'labels', type: 'string' as const, description: 'Comma-separated labels for the issue', required: false },\n { name: 'screenshot_path', type: 'string' as const, description: 'Path to screenshot evidence', required: false }\n ],\n execute: async ({ title, body, severity, labels = [], screenshot_path }: { title: string; body: string; severity: 'low' | 'medium' | 'high' | 'critical'; labels?: string[]; screenshot_path?: string }) => {\n if (!this.octokit || !this.config.owner || !this.config.repo) {\n return { output: 'GitHub not configured. Please set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO.', error: 'GitHub not configured' };\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,\n status: 'open',\n github_issue_url: issue.data.html_url,\n screenshot_path\n });\n\n return { output: `✅ GitHub issue created successfully!\\nURL: ${issue.data.html_url}\\nIssue #${issue.data.number}` };\n } catch (error: unknown) {\n return { output: `❌ Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n }\n ];\n }\n}\n","import { OpenQADatabase, KanbanTicket } 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 { name: 'title', type: 'string' as const, description: 'Ticket title', required: true },\n { name: 'description', type: 'string' as const, description: 'Detailed description', required: true },\n { name: 'priority', type: 'string' as const, description: 'Ticket priority (low, medium, high, critical)', required: true },\n { name: 'column', type: 'string' as const, description: 'Kanban column (backlog, to-do, in-progress, done)', required: false },\n { name: 'tags', type: 'string' as const, description: 'Comma-separated tags for categorization', required: false },\n { name: 'screenshot_path', type: 'string' as const, description: 'Path to screenshot evidence', required: false }\n ],\n execute: async ({ title, description, priority, column = 'to-do', tags = [], screenshot_path }: { title: string; description: string; priority: KanbanTicket['priority']; column?: KanbanTicket['column']; tags?: string[]; screenshot_path?: string }) => {\n try {\n const allTags = ['automated-qa', ...tags];\n\n const ticket = await this.db.createKanbanTicket({\n title,\n description,\n priority,\n column,\n tags: JSON.stringify(allTags),\n screenshot_url: screenshot_path\n });\n\n await 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 { output: `✅ Kanban ticket created successfully!\\nID: ${ticket.id}\\nColumn: ${column}\\nPriority: ${priority}` };\n } catch (error: unknown) {\n return { output: `❌ Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'update_kanban_ticket',\n description: 'Update an existing Kanban ticket (move columns, change priority, etc.)',\n parameters: [\n { name: 'ticket_id', type: 'string' as const, description: 'ID of the ticket to update', required: true },\n { name: 'column', type: 'string' as const, description: 'New column (backlog, to-do, in-progress, done)', required: false },\n { name: 'priority', type: 'string' as const, description: 'New priority (low, medium, high, critical)', required: false }\n ],\n execute: async ({ ticket_id, column, priority }: { ticket_id: string; column?: KanbanTicket['column']; priority?: KanbanTicket['priority'] }) => {\n try {\n const updates: Partial<KanbanTicket> = {};\n if (column) updates.column = column;\n if (priority) updates.priority = priority;\n\n await this.db.updateKanbanTicket(ticket_id, updates);\n\n return { output: `✅ Kanban ticket ${ticket_id} updated successfully!` };\n } catch (error: unknown) {\n return { output: `❌ Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\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 execute: async () => {\n try {\n const tickets = await 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 { output: summary };\n } catch (error: unknown) {\n return { output: `❌ Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n }\n ];\n }\n}\n","import { EventEmitter } from 'events';\nimport { Octokit } from '@octokit/rest';\nimport { logger } from '../logger.js';\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 logger.info('GitListener started', { provider: this.config.provider, owner: this.config.owner, repo: this.config.repo });\n \n await this.checkInitialState();\n \n this.pollInterval = setInterval(() => {\n this.poll().catch((e) => logger.error('Poll error', { error: e instanceof Error ? e.message : String(e) }));\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 logger.info('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 logger.error('Failed to check initial state', { error: error instanceof Error ? error.message : String(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 logger.error('Poll error', { error: error instanceof Error ? error.message : String(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 logger.info('Merge detected', { branch: this.config.branch, sha: 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 logger.info('Pipeline success', { name: run.name, id: run.id });\n } else {\n this.emit('pipeline-failure', event);\n logger.warn('Pipeline failure', { name: run.name, id: 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 logger.error('GitLab initial state error', { error: error instanceof Error ? error.message : String(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 logger.info('Merge detected', { branch: this.config.branch, id: 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 logger.info('Pipeline success', { id: pipeline.id });\n } else {\n this.emit('pipeline-failure', event);\n logger.warn('Pipeline failure', { id: pipeline.id });\n }\n }\n }\n\n if (pipelines.length > 0) {\n this.lastPipelineId = pipelines[0].id.toString();\n }\n } catch (error) {\n logger.error('GitLab poll error', { error: error instanceof Error ? error.message : String(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 llm = this.createLLMAdapter();\n const agent = new ReActAgent({\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 }, llm);\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: unknown) {\n status.status = 'failed';\n status.completedAt = new Date();\n\n this.emit('agent-failed', { ...status, error: error instanceof Error ? error.message : String(error) });\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 // Load default skills synchronously to avoid async issues\n DEFAULT_SKILLS.forEach(skill => {\n this.createSkill(skill);\n });\n }\n\n private saveSkills() {\n // Skills are stored in memory only for now\n // TODO: Implement async persistence when needed\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":";;;;;;AACA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAF9B;AAAA;AAAA;AAAA;AAAA;;;ACAA,OAAO,cAAc;AAArB;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,oBAAAC,yBAAwB;AACjC,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,gBAAAC,qBAAoB;;;ACL7B;AAMA;AANA,SAAS,WAAW;AACpB,SAAS,gBAAgB;AACzB,SAAe,eAAe;AAC9B,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,iBAA8C;AAevD,IAAMC,cAAaC,eAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQF,WAAU;AAmE7B,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YAAoB,SAAiB,sBAAsB;AAAvC;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA,EAJQ,KAAiC;AAAA,EAMjC,aAAa;AACnB,UAAM,MAAM,QAAQ,KAAK,MAAM;AAC/B,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,UAAM,UAAU,IAAI,SAAyB,KAAK,MAAM;AACxD,SAAK,KAAK,IAAI,IAAoB,SAAS;AAAA,MACzC,QAAQ,CAAC;AAAA,MACT,eAAe,CAAC;AAAA,MAChB,SAAS,CAAC;AAAA,MACV,MAAM,CAAC;AAAA,MACP,gBAAgB,CAAC;AAAA,MACjB,OAAO,CAAC;AAAA,IACV,CAAC;AAED,SAAK,GAAG,KAAK;AACb,QAAI,CAAC,KAAK,GAAG,MAAM;AACjB,WAAK,GAAG,OAAO;AAAA,QACb,QAAQ,CAAC;AAAA,QACT,eAAe,CAAC;AAAA,QAChB,SAAS,CAAC;AAAA,QACV,MAAM,CAAC;AAAA,QACP,gBAAgB,CAAC;AAAA,QACjB,OAAO,CAAC;AAAA,MACV;AACA,WAAK,GAAG,MAAM;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB;AAChC,QAAI,CAAC,KAAK,IAAI;AACZ,WAAK,WAAW;AAAA,IAClB;AACA,UAAM,KAAK,GAAI,KAAK;AAEpB,QAAI,WAAW;AACf,QAAI,CAAC,KAAK,GAAI,KAAK,OAAO;AAAE,WAAK,GAAI,KAAK,QAAQ,CAAC;AAAG,iBAAW;AAAA,IAAM;AACvE,QAAI,SAAU,OAAM,KAAK,GAAI,MAAM;AAAA,EACrC;AAAA,EAEA,MAAM,UAAU,KAAqC;AACnD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,OAAO,GAAG,KAAK;AAAA,EACtC;AAAA,EAEA,MAAM,UAAU,KAAa,OAAe;AAC1C,UAAM,KAAK,kBAAkB;AAC7B,SAAK,GAAI,KAAK,OAAO,GAAG,IAAI;AAC5B,UAAM,KAAK,GAAI,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,eAAgD;AACpD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,cAAc,IAAY,UAA0D;AACxF,UAAM,KAAK,kBAAkB;AAC7B,UAAM,UAAuB;AAAA,MAC3B;AAAA,MACA,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,UAAU,WAAW,KAAK,UAAU,QAAQ,IAAI;AAAA,IAClD;AACA,SAAK,GAAI,KAAK,cAAc,KAAK,OAAO;AACxC,UAAM,KAAK,GAAI,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,IAAyC;AACxD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,cAAc,KAAK,OAAK,EAAE,OAAO,EAAE,KAAK;AAAA,EAC/D;AAAA,EAEA,MAAM,cAAc,IAAY,SAA+B;AAC7D,UAAM,KAAK,kBAAkB;AAC7B,UAAM,QAAQ,KAAK,GAAI,KAAK,cAAc,UAAU,OAAK,EAAE,OAAO,EAAE;AACpE,QAAI,UAAU,IAAI;AAChB,WAAK,GAAI,KAAK,cAAc,KAAK,IAAI,EAAE,GAAG,KAAK,GAAI,KAAK,cAAc,KAAK,GAAG,GAAG,QAAQ;AACzF,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,QAAgB,IAA4B;AAClE,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,cAClB,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,EAClF,MAAM,GAAG,KAAK;AAAA,EACnB;AAAA,EAEA,MAAM,aAAa,QAA2D;AAC5E,UAAM,KAAK,kBAAkB;AAC7B,UAAM,YAAoB;AAAA,MACxB,IAAI,UAAU,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,MACnE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,GAAG;AAAA,IACL;AACA,SAAK,GAAI,KAAK,QAAQ,KAAK,SAAS;AACpC,UAAM,KAAK,GAAI,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBAAkB,WAAsC;AAC5D,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,QAClB,OAAO,OAAK,EAAE,eAAe,SAAS,EACtC,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,EACrF;AAAA,EAEA,MAAM,UAAU,KAAkE;AAChF,UAAM,KAAK,kBAAkB;AAC7B,UAAM,SAAc;AAAA,MAClB,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,MAChE,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,GAAG;AAAA,IACL;AACA,SAAK,GAAI,KAAK,KAAK,KAAK,MAAM;AAC9B,UAAM,KAAK,GAAI,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,IAAY,SAAuB;AACjD,UAAM,KAAK,kBAAkB;AAC7B,UAAM,QAAQ,KAAK,GAAI,KAAK,KAAK,UAAU,OAAK,EAAE,OAAO,EAAE;AAC3D,QAAI,UAAU,IAAI;AAChB,WAAK,GAAI,KAAK,KAAK,KAAK,IAAI;AAAA,QAC1B,GAAG,KAAK,GAAI,KAAK,KAAK,KAAK;AAAA,QAC3B,GAAG;AAAA,QACH,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACrC;AACA,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,aAA6B;AACjC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,KAAK,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC;AAAA,EAC9G;AAAA,EAEA,MAAM,gBAAgB,QAAuC;AAC3D,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,KAClB,OAAO,OAAK,EAAE,WAAW,MAAM,EAC/B,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC;AAAA,EACvF;AAAA,EAEA,MAAM,mBAAmB,QAAuF;AAC9G,UAAM,KAAK,kBAAkB;AAC7B,UAAM,YAA0B;AAAA,MAC9B,IAAI,UAAU,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,MACnE,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,GAAG;AAAA,IACL;AACA,SAAK,GAAI,KAAK,eAAe,KAAK,SAAS;AAC3C,UAAM,KAAK,GAAI,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,mBAAmB,IAAY,SAAgC;AACnE,UAAM,KAAK,kBAAkB;AAC7B,UAAM,QAAQ,KAAK,GAAI,KAAK,eAAe,UAAU,OAAK,EAAE,OAAO,EAAE;AACrE,QAAI,UAAU,IAAI;AAChB,WAAK,GAAI,KAAK,eAAe,KAAK,IAAI;AAAA,QACpC,GAAG,KAAK,GAAI,KAAK,eAAe,KAAK;AAAA,QACrC,GAAG;AAAA,QACH,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACrC;AACA,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,mBAA4C;AAChD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,eAAe,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC;AAAA,EACxH;AAAA,EAEA,MAAM,yBAAyB,QAAyD;AACtF,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,eAClB,OAAO,OAAK,EAAE,WAAW,MAAM,EAC/B,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC;AAAA,EACvF;AAAA,EAEA,MAAM,mBAAmB,IAA2B;AAClD,UAAM,KAAK,kBAAkB;AAC7B,UAAM,QAAQ,KAAK,GAAI,KAAK,eAAe,UAAU,OAAK,EAAE,OAAO,EAAE;AACrE,QAAI,UAAU,IAAI;AAChB,WAAK,GAAI,KAAK,eAAe,OAAO,OAAO,CAAC;AAC5C,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB;AACrB,UAAM,KAAK,kBAAkB;AAC7B,SAAK,GAAI,KAAK,SAAS,CAAC;AACxB,UAAM,KAAK,GAAI,MAAM;AAAA,EACvB;AAAA;AAAA,EAIA,MAAM,kBAAkB;AACtB,UAAM,KAAK,kBAAkB;AAC7B,UAAM,WAAW,MAAM,KAAK,kBAAkB,CAAC;AAC/C,UAAM,iBAAiB,SAAS,CAAC;AAGjC,UAAM,YAAY,gBAAgB,WAAW;AAC7C,UAAM,eAAe,gBAAgB,iBAAiB;AAGtD,UAAM,SAAS;AAAA,MACb;AAAA,QACE,MAAM;AAAA,QACN,QAAQ,YAAY,YAAY;AAAA,QAChC,SAAS;AAAA,QACT,aAAa,eAAe,IAAI,KAAK,IAAI,KAAK,KAAK,MAAO,eAAe,MAAO,GAAG,CAAC,IAAI;AAAA,QACxF,OAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,kBAAkB,eAAe,GAAG;AACtC,YAAM,UAAU,MAAM,KAAK,kBAAkB,eAAe,EAAE;AAG9D,YAAM,cAAc,QAAQ,OAAO,CAAC,KAA6B,WAAW;AAC1E,cAAM,OAAO,OAAO,QAAQ;AAC5B,YAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK;AAC/B,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AAGL,UAAI,YAAY,UAAU,KAAK,YAAY,OAAO,KAAK,YAAY,YAAY,GAAG;AAChF,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,YAAY,YAAY;AAAA,UAChC,SAAS;AAAA,UACT,aAAa,KAAK,QAAQ,YAAY,UAAU,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,eAAe,GAAG;AAAA,UAC3G,QAAQ,YAAY,UAAU,KAAK,MAAM,YAAY,OAAO,KAAK;AAAA,QACnE,CAAC;AAAA,MACH;AAEA,UAAI,YAAY,UAAU,KAAK,YAAY,SAAS,GAAG;AACrD,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,YAAY,YAAY;AAAA,UAChC,SAAS;AAAA,UACT,aAAa,KAAK,OAAO,YAAY,UAAU,KAAK,YAAY,SAAS,KAAK,KAAK,eAAe,GAAG;AAAA,UACrG,OAAO,YAAY,UAAU,KAAK,YAAY,SAAS,KAAK;AAAA,QAC9D,CAAC;AAAA,MACH;AAEA,UAAI,YAAY,MAAM,KAAK,YAAY,OAAO,GAAG;AAC/C,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,YAAY,YAAY;AAAA,UAChC,SAAS;AAAA,UACT,aAAa,KAAK,OAAO,YAAY,MAAM,KAAK,YAAY,OAAO,KAAK,KAAK,eAAe,GAAG;AAAA,UAC/F,OAAO,YAAY,MAAM,KAAK,YAAY,OAAO,KAAK;AAAA,QACxD,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBAAkB;AACtB,UAAM,KAAK,kBAAkB;AAC7B,UAAM,WAAW,MAAM,KAAK,kBAAkB,CAAC;AAC/C,UAAM,iBAAiB,SAAS,CAAC;AAEjC,QAAI,CAAC,gBAAgB;AACnB,aAAO,CAAC;AAAA,IACV;AAGA,UAAM,UAAU,MAAM,KAAK,kBAAkB,eAAe,EAAE;AAG9D,UAAM,gBAAgB,QAAQ,MAAM,GAAG,EAAE,QAAQ;AAEjD,WAAO,cAAc,IAAI,CAAC,QAAQ,WAAW;AAAA,MAC3C,IAAI,OAAO;AAAA,MACX,MAAM,OAAO,QAAQ;AAAA,MACrB,QAAQ,UAAU,KAAK,eAAe,WAAW,YAAY,YAAY;AAAA,MACzE,UAAU,UAAU,KAAK,eAAe,WAAW,YAAY,QAAQ;AAAA,MACvE,OAAO;AAAA,MACP,YAAY,OAAO;AAAA,MACnB,QAAQ,OAAO,UAAU,OAAO,eAAe;AAAA,IACjD,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB;AACvB,UAAM,KAAK,kBAAkB;AAG7B,UAAM,OAAO,MAAM,KAAK,WAAW;AAGnC,WAAO,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,UAAQ;AAAA,MACnC,IAAI,IAAI;AAAA,MACR,OAAO,IAAI;AAAA,MACX,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI,YAAY;AAAA,MAC1B,QAAQ,IAAI,UAAU;AAAA,MACtB,eAAe,IAAI;AAAA,MACnB,OAAO;AAAA,IACT,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,iBAAiB,YAAkF;AACvG,UAAM,KAAK,kBAAkB;AAC7B,UAAM,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,aAAa,KAAQ,EAAE,YAAY;AAExE,UAAM,cAAc,KAAK,GAAI,KAAK,cAAc,OAAO,OAAK,EAAE,aAAa,MAAM;AACjF,UAAM,gBAAgB,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,EAAE,CAAC;AAExD,UAAM,gBAAgB,KAAK,GAAI,KAAK,QAAQ;AAC5C,SAAK,GAAI,KAAK,UAAU,KAAK,GAAI,KAAK,QAAQ,OAAO,OAAK,CAAC,cAAc,IAAI,EAAE,UAAU,CAAC;AAC1F,UAAM,iBAAiB,gBAAgB,KAAK,GAAI,KAAK,QAAQ;AAE7D,SAAK,GAAI,KAAK,gBAAgB,KAAK,GAAI,KAAK,cAAc,OAAO,OAAK,EAAE,cAAc,MAAM;AAC5F,UAAM,KAAK,GAAI,MAAM;AAErB,WAAO,EAAE,iBAAiB,YAAY,QAAQ,eAAe;AAAA,EAC/D;AAAA,EAEA,MAAM,kBAAiG;AACrG,UAAM,KAAK,kBAAkB;AAC7B,WAAO;AAAA,MACL,UAAU,KAAK,GAAI,KAAK,cAAc;AAAA,MACtC,SAAS,KAAK,GAAI,KAAK,QAAQ;AAAA,MAC/B,MAAM,KAAK,GAAI,KAAK,KAAK;AAAA,MACzB,SAAS,KAAK,GAAI,KAAK,eAAe;AAAA,IACxC;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,aAA8B;AAClC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,MAAM;AAAA,EAC7B;AAAA,EAEA,MAAM,mBAAmB,UAAwC;AAC/D,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,MAAM,KAAK,OAAK,EAAE,aAAa,QAAQ,KAAK;AAAA,EACnE;AAAA,EAEA,MAAM,YAAY,IAAkC;AAClD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK,GAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,EAAE,KAAK;AAAA,EACvD;AAAA,EAEA,MAAM,cAA+B;AACnC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,CAAC,GAAG,KAAK,GAAI,KAAK,KAAK;AAAA,EAChC;AAAA,EAEA,MAAM,WAAW,MAAqF;AACpG,UAAM,KAAK,kBAAkB;AAC7B,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,OAAa;AAAA,MACjB,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,MAChE,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,MAAM,KAAK;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AACA,SAAK,GAAI,KAAK,MAAM,KAAK,IAAI;AAC7B,UAAM,KAAK,GAAI,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,IAAY,SAAsE;AACjG,UAAM,KAAK,kBAAkB;AAC7B,UAAM,MAAM,KAAK,GAAI,KAAK,MAAM,UAAU,OAAK,EAAE,OAAO,EAAE;AAC1D,QAAI,QAAQ,IAAI;AACd,WAAK,GAAI,KAAK,MAAM,GAAG,IAAI;AAAA,QACzB,GAAG,KAAK,GAAI,KAAK,MAAM,GAAG;AAAA,QAC1B,GAAG;AAAA,QACH,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AACA,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,IAA2B;AAC1C,UAAM,KAAK,kBAAkB;AAC7B,UAAM,MAAM,KAAK,GAAI,KAAK,MAAM,UAAU,OAAK,EAAE,OAAO,EAAE;AAC1D,QAAI,QAAQ,IAAI;AACd,WAAK,GAAI,KAAK,MAAM,OAAO,KAAK,CAAC;AACjC,YAAM,KAAK,GAAI,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ;AAAA,EAEd;AACF;;;ACjfA;AAAA,SAAS,UAAU,oBAAoB;;;ACAvC;AAAA,SAAS,SAAS;AAEX,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,UAAU,EAAE,KAAK,CAAC,UAAU,aAAa,QAAQ,CAAC,EAAE,QAAQ,QAAQ;AAAA,EACpE,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACrC,CAAC;AAEM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EAC1B,UAAU,EAAE,KAAK,CAAC,QAAQ,SAAS,UAAU,SAAS,CAAC,EAAE,QAAQ,MAAM;AAAA,EACvE,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAChC,CAAC;AAEM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,oDAAoD;AAAA,EAC7E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EAC5B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;AAC7B,CAAC;AAEM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,IAAO;AAAA,EACvD,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,EACrD,WAAW,EAAE,QAAQ,EAAE,QAAQ,KAAK;AACtC,CAAC;AAEM,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK,EAAE,QAAQ,IAAI;AAAA,EACrD,MAAM,EAAE,OAAO,EAAE,QAAQ,SAAS;AACpC,CAAC;AAEM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,MAAM,EAAE,OAAO,EAAE,QAAQ,kBAAkB;AAC7C,CAAC;AAEM,IAAM,4BAA4B,EAAE,OAAO;AAAA,EAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACjC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACrC,CAAC;AAEM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ,mBAAmB,SAAS;AAAA,EACpC,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,EACV,eAAe,0BAA0B,SAAS;AACpD,CAAC;AAKM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,mCAAmC;AAAA,EAC3D,aAAa,EAAE,OAAO,EAAE,IAAI,GAAG,0CAA0C;AAAA,EACzE,KAAK,EAAE,OAAO,EAAE,IAAI,0CAA0C;AAAA,EAC9D,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACxC,UAAU,EAAE,OAAO;AAAA,IACjB,MAAM,EAAE,KAAK,CAAC,QAAQ,SAAS,SAAS,SAAS,CAAC;AAAA,IAClD,iBAAiB,EAAE,OAAO;AAAA,MACxB,UAAU,EAAE,OAAO;AAAA,MACnB,UAAU,EAAE,OAAO;AAAA,IACrB,CAAC,EAAE,SAAS;AAAA,EACd,CAAC,EAAE,SAAS;AAAA,EACZ,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAC3C,CAAC;AAuBM,SAAS,mBAAmB,QAAwG;AACzI,QAAM,SAAS,mBAAmB,UAAU,MAAM;AAClD,MAAI,OAAO,SAAS;AAClB,WAAO,EAAE,SAAS,MAAM,MAAM,OAAO,KAAK;AAAA,EAC5C;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ,OAAO,MAAM,OAAO,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE;AAAA,EAC1E;AACF;;;ACtGA;AAEA,IAAM,SAAmC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE;AAEhF,IAAM,YAAuB,QAAQ,IAAI,aAA0B;AAEnE,SAAS,UAAU,OAA0B;AAC3C,SAAO,OAAO,KAAK,KAAK,OAAO,SAAS;AAC1C;AAEA,SAAS,OAAO,OAAiB,SAAiB,SAA2C;AAC3F,QAAM,QAAiC;AAAA,IACrC,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC3B;AAAA,IACA,KAAK;AAAA,IACL,GAAG;AAAA,EACL;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;AAEO,IAAM,SAAS;AAAA,EACpB,MAAM,SAAiB,SAAmC;AACxD,QAAI,UAAU,OAAO,EAAG,SAAQ,OAAO,MAAM,OAAO,SAAS,SAAS,OAAO,IAAI,IAAI;AAAA,EACvF;AAAA,EACA,KAAK,SAAiB,SAAmC;AACvD,QAAI,UAAU,MAAM,EAAG,SAAQ,OAAO,MAAM,OAAO,QAAQ,SAAS,OAAO,IAAI,IAAI;AAAA,EACrF;AAAA,EACA,KAAK,SAAiB,SAAmC;AACvD,QAAI,UAAU,MAAM,EAAG,SAAQ,OAAO,MAAM,OAAO,QAAQ,SAAS,OAAO,IAAI,IAAI;AAAA,EACrF;AAAA,EACA,MAAM,SAAiB,SAAmC;AACxD,QAAI,UAAU,OAAO,EAAG,SAAQ,OAAO,MAAM,OAAO,SAAS,SAAS,OAAO,IAAI,IAAI;AAAA,EACvF;AAAA,EACA,MAAM,UAAmC;AACvC,WAAO;AAAA,MACL,OAAO,CAAC,KAAa,QAAkC,OAAO,MAAM,KAAK,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAAA,MAChG,MAAO,CAAC,KAAa,QAAkC,OAAO,KAAK,KAAM,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAAA,MAChG,MAAO,CAAC,KAAa,QAAkC,OAAO,KAAK,KAAM,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAAA,MAChG,OAAO,CAAC,KAAa,QAAkC,OAAO,MAAM,KAAK,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAAA,IAClG;AAAA,EACF;AACF;;;AFpCA,aAAa;AAIN,IAAM,gBAAN,MAAoB;AAAA,EACjB,KAA4B;AAAA,EAC5B;AAAA,EAER,YAAY,QAAiB;AAE3B,SAAK,YAAY,KAAK,YAAY;AAAA,EACpC;AAAA,EAEQ,cAA4B;AAClC,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,QACH,UAAU,QAAQ,IAAI,gBAAgB;AAAA,QACtC,QAAQ,QAAQ,IAAI,kBAAkB,QAAQ,IAAI;AAAA,QAClD,OAAO,QAAQ,IAAI;AAAA,QACnB,SAAS,QAAQ,IAAI;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,QACJ,KAAK,QAAQ,IAAI,YAAY;AAAA,QAC7B,UAAU,QAAQ,IAAI,kBAAkB;AAAA,QACxC,UAAU,QAAQ,IAAI;AAAA,QACtB,UAAU,QAAQ,IAAI;AAAA,MACxB;AAAA,MACA,QAAQ,QAAQ,IAAI,eAAe;AAAA,QACjC,OAAO,QAAQ,IAAI;AAAA,QACnB,OAAO,QAAQ,IAAI,gBAAgB;AAAA,QACnC,MAAM,QAAQ,IAAI,eAAe;AAAA,MACnC,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,YAAY,SAAS,QAAQ,IAAI,qBAAqB,SAAS;AAAA,QAC/D,eAAe,SAAS,QAAQ,IAAI,wBAAwB,IAAI;AAAA,QAChE,WAAW,QAAQ,IAAI,qBAAqB;AAAA,MAC9C;AAAA,MACA,KAAK;AAAA,QACH,MAAM,SAAS,QAAQ,IAAI,YAAY,MAAM;AAAA,QAC7C,MAAM,QAAQ,IAAI,YAAY;AAAA,MAChC;AAAA,MACA,UAAU;AAAA,QACR,MAAM,QAAQ,IAAI,WAAW;AAAA,MAC/B;AAAA,MACA,eAAe;AAAA,QACb,OAAO,QAAQ,IAAI;AAAA,QACnB,SAAS,QAAQ,IAAI;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,SAAS,mBAAmB,GAAG;AACrC,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,KAAK,8BAA8B,EAAE,QAAQ,OAAO,OAAO,CAAC;AAEnE,aAAO;AAAA,IACT;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,QAAwB;AAC9B,QAAI,CAAC,KAAK,IAAI;AACZ,WAAK,KAAK,IAAI,eAAe,oBAAoB;AAAA,IACnD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,KAAqC;AAC7C,UAAM,UAAU,MAAM,KAAK,MAAM,EAAE,UAAU,GAAG;AAChD,QAAI,QAAS,QAAO;AAEpB,UAAM,OAAO,IAAI,MAAM,GAAG;AAC1B,QAAI,QAAiB,KAAK;AAC1B,eAAW,KAAK,MAAM;AACpB,UAAI,SAAS,OAAO,UAAU,UAAU;AACtC,gBAAS,MAAkC,CAAC;AAAA,MAC9C,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO,SAAS,OAAO,OAAO,KAAK,IAAI;AAAA,EACzC;AAAA,EAEA,MAAM,IAAI,KAAa,OAAe;AACpC,UAAM,KAAK,MAAM,EAAE,UAAU,KAAK,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,SAAgC;AACpC,UAAM,WAAW,MAAM,KAAK,MAAM,EAAE,aAAa;AACjD,UAAM,SAAS,EAAE,GAAG,KAAK,UAAU;AAEnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,YAAM,OAAO,IAAI,MAAM,GAAG;AAC1B,UAAI,MAA+B;AACnC,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,YAAI,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,OAAO,IAAI,KAAK,CAAC,CAAC,MAAM,SAAU,KAAI,KAAK,CAAC,CAAC,IAAI,CAAC;AACvE,cAAM,IAAI,KAAK,CAAC,CAAC;AAAA,MACnB;AACA,UAAI,KAAK,KAAK,SAAS,CAAC,CAAC,IAAI;AAAA,IAC/B;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAmC;AACvC,WAAO,MAAM,KAAK,OAAO;AAAA,EAC3B;AAAA;AAAA,EAGA,gBAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AACF;;;AGpHA;AAAA,SAAS,gBAA+B;AAExC,SAAS,aAAAG,kBAAiB;AAC1B,SAAS,QAAAC,aAAY;AAEd,IAAM,eAAN,MAAmB;AAAA,EAChB,UAA0B;AAAA,EAC1B,OAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA,gBAAwB;AAAA,EAEhC,YAAY,IAAoB,WAAmB;AACjD,SAAK,KAAK;AACV,SAAK,YAAY;AACjB,IAAAD,WAAU,KAAK,eAAe,EAAE,WAAW,KAAK,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,aAAa;AACjB,SAAK,UAAU,MAAM,SAAS,OAAO,EAAE,UAAU,KAAK,CAAC;AACvD,UAAM,UAAU,MAAM,KAAK,QAAQ,WAAW;AAAA,MAC5C,UAAU,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,MACtC,WAAW;AAAA,IACb,CAAC;AACD,SAAK,OAAO,MAAM,QAAQ,QAAQ;AAAA,EACpC;AAAA,EAEA,WAAW;AACT,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,OAAO,MAAM,UAAmB,aAAa,0BAA0B,UAAU,KAAK;AAAA,QAChG;AAAA,QACA,SAAS,OAAO,EAAE,IAAI,MAAuB;AAC3C,cAAI,CAAC,KAAK,KAAM,OAAM,KAAK,WAAW;AAEtC,cAAI;AACF,kBAAM,KAAK,KAAM,KAAK,KAAK,EAAE,WAAW,cAAc,CAAC;AACvD,kBAAM,QAAQ,MAAM,KAAK,KAAM,MAAM;AAErC,iBAAK,GAAG,aAAa;AAAA,cACnB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,gBAAgB,GAAG;AAAA,cAChC,OAAO;AAAA,cACP,QAAQ,eAAe,KAAK;AAAA,YAC9B,CAAC;AAED,mBAAO,EAAE,QAAQ,6BAA6B,GAAG,kBAAkB,KAAK,IAAI;AAAA,UAC9E,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,uBAAuB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UAClK;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,YAAY,MAAM,UAAmB,aAAa,wCAAwC,UAAU,KAAK;AAAA,QACnH;AAAA,QACA,SAAS,OAAO,EAAE,SAAS,MAA4B;AACrD,cAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,sDAAsD,OAAO,0BAA0B;AAExH,cAAI;AACF,kBAAM,KAAK,KAAK,MAAM,UAAU,EAAE,SAAS,IAAK,CAAC;AAEjD,iBAAK,GAAG,aAAa;AAAA,cACnB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,oBAAoB,QAAQ;AAAA,cACzC,OAAO;AAAA,YACT,CAAC;AAED,mBAAO,EAAE,QAAQ,iCAAiC,QAAQ,GAAG;AAAA,UAC/D,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UACvK;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,YAAY,MAAM,UAAmB,aAAa,mCAAmC,UAAU,KAAK;AAAA,UAC5G,EAAE,MAAM,QAAQ,MAAM,UAAmB,aAAa,6BAA6B,UAAU,KAAK;AAAA,QACpG;AAAA,QACA,SAAS,OAAO,EAAE,UAAU,KAAK,MAA0C;AACzE,cAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,sDAAsD,OAAO,0BAA0B;AAExH,cAAI;AACF,kBAAM,KAAK,KAAK,KAAK,UAAU,IAAI;AAEnC,iBAAK,GAAG,aAAa;AAAA,cACnB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,gBAAgB,QAAQ;AAAA,cACrC,OAAO,GAAG,QAAQ,MAAM,IAAI;AAAA,YAC9B,CAAC;AAED,mBAAO,EAAE,QAAQ,6BAA6B,QAAQ,aAAa;AAAA,UACrE,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UACpK;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,QAAQ,MAAM,UAAmB,aAAa,gCAAgC,UAAU,KAAK;AAAA,QACvG;AAAA,QACA,SAAS,OAAO,EAAE,KAAK,MAAwB;AAC7C,cAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,sDAAsD,OAAO,0BAA0B;AAExH,cAAI;AACF,kBAAM,WAAW,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI;AACtC,kBAAME,QAAOD,MAAK,KAAK,eAAe,QAAQ;AAC9C,kBAAM,KAAK,KAAK,WAAW,EAAE,MAAAC,OAAM,UAAU,KAAK,CAAC;AAEnD,iBAAK,GAAG,aAAa;AAAA,cACnB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,eAAe,IAAI;AAAA,cAChC,iBAAiBA;AAAA,YACnB,CAAC;AAED,mBAAO,EAAE,QAAQ,qBAAqBA,KAAI,GAAG;AAAA,UAC/C,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UACzK;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY,CAAC;AAAA,QACb,SAAS,YAAY;AACnB,cAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,sDAAsD,OAAO,0BAA0B;AAExH,cAAI;AACF,kBAAM,UAAU,MAAM,KAAK,KAAK,YAAY,MAAM;AAClD,mBAAO,EAAE,QAAQ,SAAS,MAAM,GAAG,GAAI,KAAK,mBAAmB;AAAA,UACjE,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UACrK;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY,CAAC;AAAA,QACb,SAAS,YAAY;AACnB,cAAI,CAAC,KAAK,KAAM,QAAO,EAAE,QAAQ,sDAAsD,OAAO,0BAA0B;AAExH,gBAAM,SAAmB,CAAC;AAC1B,eAAK,KAAK,GAAG,WAAW,SAAO;AAC7B,gBAAI,IAAI,KAAK,MAAM,SAAS;AAC1B,qBAAO,KAAK,IAAI,KAAK,CAAC;AAAA,YACxB;AAAA,UACF,CAAC;AAED,gBAAM,KAAK,KAAK,eAAe,GAAI;AAEnC,cAAI,OAAO,SAAS,GAAG;AACrB,mBAAO,EAAE,QAAQ,SAAS,OAAO,MAAM;AAAA,EAAqB,OAAO,KAAK,IAAI,CAAC,GAAG;AAAA,UAClF;AACA,iBAAO,EAAE,QAAQ,6BAA6B;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ;AACZ,QAAI,KAAK,SAAS;AAChB,YAAM,KAAK,QAAQ,MAAM;AACzB,WAAK,UAAU;AACf,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AACF;;;ACrLA;AAAA,SAAS,eAAe;AAGjB,IAAM,cAAN,MAAkB;AAAA,EACf,UAA0B;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,IAAoB,WAAmB,QAA2D;AAC5G,SAAK,KAAK;AACV,SAAK,YAAY;AACjB,SAAK,SAAS;AAEd,QAAI,OAAO,OAAO;AAChB,WAAK,UAAU,IAAI,QAAQ,EAAE,MAAM,OAAO,MAAM,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,WAAW;AACT,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,SAAS,MAAM,UAAmB,aAAa,yCAAyC,UAAU,KAAK;AAAA,UAC/G,EAAE,MAAM,QAAQ,MAAM,UAAmB,aAAa,gDAAgD,UAAU,KAAK;AAAA,UACrH,EAAE,MAAM,YAAY,MAAM,UAAmB,aAAa,8CAA8C,UAAU,KAAK;AAAA,UACvH,EAAE,MAAM,UAAU,MAAM,UAAmB,aAAa,wCAAwC,UAAU,MAAM;AAAA,UAChH,EAAE,MAAM,mBAAmB,MAAM,UAAmB,aAAa,+BAA+B,UAAU,MAAM;AAAA,QAClH;AAAA,QACA,SAAS,OAAO,EAAE,OAAO,MAAM,UAAU,SAAS,CAAC,GAAG,gBAAgB,MAAsI;AAC1M,cAAI,CAAC,KAAK,WAAW,CAAC,KAAK,OAAO,SAAS,CAAC,KAAK,OAAO,MAAM;AAC5D,mBAAO,EAAE,QAAQ,kFAAkF,OAAO,wBAAwB;AAAA,UACpI;AAEA,cAAI;AACF,kBAAM,gBAAgB,aAAa,QAAQ;AAC3C,kBAAM,YAAY,CAAC,gBAAgB,eAAe,GAAG,MAAM;AAE3D,kBAAM,YAAY;AAAA;AAAA,EAE5B,IAAI;AAAA;AAAA;AAAA;AAAA,gBAIU,SAAS,YAAY,CAAC;AAAA;AAAA,kBAEpB,KAAK,SAAS;AAAA,EAC9B,kBAAkB,mBAAmB,eAAe,KAAK,EAAE;AAAA;AAAA;AAIjD,kBAAM,QAAQ,MAAM,KAAK,QAAQ,KAAK,OAAO,OAAO;AAAA,cAClD,OAAO,KAAK,OAAO;AAAA,cACnB,MAAM,KAAK,OAAO;AAAA,cAClB,OAAO,QAAQ,KAAK;AAAA,cACpB,MAAM;AAAA,cACN,QAAQ;AAAA,YACV,CAAC;AAED,iBAAK,GAAG,aAAa;AAAA,cACnB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,yBAAyB,KAAK;AAAA,cAC3C,OAAO,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,cACzC,QAAQ,MAAM,KAAK;AAAA,YACrB,CAAC;AAED,kBAAM,MAAM,KAAK,GAAG,UAAU;AAAA,cAC5B,YAAY,KAAK;AAAA,cACjB;AAAA,cACA,aAAa;AAAA,cACb;AAAA,cACA,QAAQ;AAAA,cACR,kBAAkB,MAAM,KAAK;AAAA,cAC7B;AAAA,YACF,CAAC;AAED,mBAAO,EAAE,QAAQ;AAAA,OAA8C,MAAM,KAAK,QAAQ;AAAA,SAAY,MAAM,KAAK,MAAM,GAAG;AAAA,UACpH,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,yCAAoC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UAC/K;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACvFA;AAEO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EAER,YAAY,IAAoB,WAAmB;AACjD,SAAK,KAAK;AACV,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,WAAW;AACT,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,SAAS,MAAM,UAAmB,aAAa,gBAAgB,UAAU,KAAK;AAAA,UACtF,EAAE,MAAM,eAAe,MAAM,UAAmB,aAAa,wBAAwB,UAAU,KAAK;AAAA,UACpG,EAAE,MAAM,YAAY,MAAM,UAAmB,aAAa,iDAAiD,UAAU,KAAK;AAAA,UAC1H,EAAE,MAAM,UAAU,MAAM,UAAmB,aAAa,qDAAqD,UAAU,MAAM;AAAA,UAC7H,EAAE,MAAM,QAAQ,MAAM,UAAmB,aAAa,2CAA2C,UAAU,MAAM;AAAA,UACjH,EAAE,MAAM,mBAAmB,MAAM,UAAmB,aAAa,+BAA+B,UAAU,MAAM;AAAA,QAClH;AAAA,QACA,SAAS,OAAO,EAAE,OAAO,aAAa,UAAU,SAAS,SAAS,OAAO,CAAC,GAAG,gBAAgB,MAA8J;AACzP,cAAI;AACF,kBAAM,UAAU,CAAC,gBAAgB,GAAG,IAAI;AAExC,kBAAM,SAAS,MAAM,KAAK,GAAG,mBAAmB;AAAA,cAC9C;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,MAAM,KAAK,UAAU,OAAO;AAAA,cAC5B,gBAAgB;AAAA,YAClB,CAAC;AAED,kBAAM,KAAK,GAAG,aAAa;AAAA,cACzB,YAAY,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,aAAa,0BAA0B,KAAK;AAAA,cAC5C,OAAO,KAAK,UAAU,EAAE,OAAO,UAAU,OAAO,CAAC;AAAA,cACjD,QAAQ,OAAO;AAAA,YACjB,CAAC;AAED,mBAAO,EAAE,QAAQ;AAAA,MAA8C,OAAO,EAAE;AAAA,UAAa,MAAM;AAAA,YAAe,QAAQ,GAAG;AAAA,UACvH,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,0CAAqC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UAChL;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA,UACV,EAAE,MAAM,aAAa,MAAM,UAAmB,aAAa,8BAA8B,UAAU,KAAK;AAAA,UACxG,EAAE,MAAM,UAAU,MAAM,UAAmB,aAAa,kDAAkD,UAAU,MAAM;AAAA,UAC1H,EAAE,MAAM,YAAY,MAAM,UAAmB,aAAa,8CAA8C,UAAU,MAAM;AAAA,QAC1H;AAAA,QACA,SAAS,OAAO,EAAE,WAAW,QAAQ,SAAS,MAAmG;AAC/I,cAAI;AACF,kBAAM,UAAiC,CAAC;AACxC,gBAAI,OAAQ,SAAQ,SAAS;AAC7B,gBAAI,SAAU,SAAQ,WAAW;AAEjC,kBAAM,KAAK,GAAG,mBAAmB,WAAW,OAAO;AAEnD,mBAAO,EAAE,QAAQ,wBAAmB,SAAS,yBAAyB;AAAA,UACxE,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,0CAAqC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UAChL;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY,CAAC;AAAA,QACb,SAAS,YAAY;AACnB,cAAI;AACF,kBAAM,UAAU,MAAM,KAAK,GAAG,iBAAiB;AAE/C,kBAAM,WAAW;AAAA,cACf,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAAA,cACrD,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO;AAAA,cACnD,eAAe,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,aAAa;AAAA,cAC/D,MAAM,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM;AAAA,YACjD;AAEA,kBAAM,UAAU;AAAA;AAAA,aAEf,SAAS,QAAQ,MAAM;AAAA,WACzB,SAAS,OAAO,EAAE,MAAM;AAAA,iBAClB,SAAS,aAAa,EAAE,MAAM;AAAA,UACrC,SAAS,KAAK,MAAM;AAAA;AAAA,SAErB,QAAQ,MAAM;AAAA,cACT,KAAK;AAEP,mBAAO,EAAE,QAAQ,QAAQ;AAAA,UAC3B,SAAS,OAAgB;AACvB,mBAAO,EAAE,QAAQ,sCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,UAC5K;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC1GA;AAAA,SAAS,oBAAoB;AAC7B,SAAS,WAAAC,gBAAe;AAuDjB,IAAM,cAAN,cAA0B,aAAa;AAAA,EACpC;AAAA,EACA,UAA0B;AAAA,EAC1B,gBAA+B;AAAA,EAC/B,iBAAgC;AAAA,EAChC,eAAsC;AAAA,EACtC,YAAqB;AAAA,EAE7B,YAAY,QAA2B;AACrC,UAAM;AACN,SAAK,SAAS;AAAA,MACZ,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,GAAG;AAAA,IACL;AAEA,QAAI,OAAO,aAAa,YAAY,OAAO,OAAO;AAChD,WAAK,UAAU,IAAIC,SAAQ,EAAE,MAAM,OAAO,MAAM,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ;AACZ,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AAEjB,WAAO,KAAK,uBAAuB,EAAE,UAAU,KAAK,OAAO,UAAU,OAAO,KAAK,OAAO,OAAO,MAAM,KAAK,OAAO,KAAK,CAAC;AAEvH,UAAM,KAAK,kBAAkB;AAE7B,SAAK,eAAe,YAAY,MAAM;AACpC,WAAK,KAAK,EAAE,MAAM,CAAC,MAAM,OAAO,MAAM,cAAc,EAAE,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC,CAAC;AAAA,IAC5G,GAAG,KAAK,OAAO,cAAc;AAAA,EAC/B;AAAA,EAEA,OAAO;AACL,SAAK,YAAY;AACjB,QAAI,KAAK,cAAc;AACrB,oBAAc,KAAK,YAAY;AAC/B,WAAK,eAAe;AAAA,IACtB;AACA,WAAO,KAAK,qBAAqB;AAAA,EACnC;AAAA,EAEA,MAAc,oBAAoB;AAChC,QAAI;AACF,UAAI,KAAK,OAAO,aAAa,UAAU;AACrC,cAAM,KAAK,iBAAiB;AAAA,MAC9B,OAAO;AACL,cAAM,KAAK,iBAAiB;AAAA,MAC9B;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,iCAAiC,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IACjH;AAAA,EACF;AAAA,EAEA,MAAc,OAAO;AACnB,QAAI;AACF,UAAI,KAAK,OAAO,aAAa,UAAU;AACrC,cAAM,KAAK,WAAW;AAAA,MACxB,OAAO;AACL,cAAM,KAAK,WAAW;AAAA,MACxB;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,cAAc,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IAC9F;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB;AAC/B,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,EAAE,MAAM,QAAQ,IAAI,MAAM,KAAK,QAAQ,MAAM,YAAY;AAAA,MAC7D,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM,KAAK,OAAO;AAAA,MAClB,KAAK,KAAK,OAAO;AAAA,MACjB,UAAU;AAAA,IACZ,CAAC;AAED,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,gBAAgB,QAAQ,CAAC,EAAE;AAAA,IAClC;AAEA,QAAI;AACF,YAAM,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAQ,wBAAwB;AAAA,QACxE,OAAO,KAAK,OAAO;AAAA,QACnB,MAAM,KAAK,OAAO;AAAA,QAClB,QAAQ,KAAK,OAAO;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,UAAI,KAAK,cAAc,SAAS,GAAG;AACjC,aAAK,iBAAiB,KAAK,cAAc,CAAC,EAAE,GAAG,SAAS;AAAA,MAC1D;AAAA,IACF,QAAQ;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,aAAa;AACzB,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,EAAE,MAAM,QAAQ,IAAI,MAAM,KAAK,QAAQ,MAAM,YAAY;AAAA,MAC7D,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM,KAAK,OAAO;AAAA,MAClB,KAAK,KAAK,OAAO;AAAA,MACjB,UAAU;AAAA,IACZ,CAAC;AAED,eAAW,UAAU,SAAS;AAC5B,UAAI,KAAK,iBAAiB,OAAO,QAAQ,KAAK,cAAe;AAE7D,YAAM,UAAU,OAAO,WAAW,OAAO,QAAQ,SAAS;AAE1D,YAAM,QAAkB;AAAA,QACtB,MAAM,UAAU,UAAU;AAAA,QAC1B,UAAU;AAAA,QACV,QAAQ,KAAK,OAAO;AAAA,QACpB,QAAQ,OAAO;AAAA,QACf,QAAQ,OAAO,OAAO,QAAQ,QAAQ;AAAA,QACtC,SAAS,OAAO,OAAO;AAAA,QACvB,WAAW,IAAI,KAAK,OAAO,OAAO,QAAQ,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC9D;AAEA,WAAK,KAAK,aAAa,KAAK;AAE5B,UAAI,SAAS;AACX,aAAK,KAAK,SAAS,KAAK;AACxB,eAAO,KAAK,kBAAkB,EAAE,QAAQ,KAAK,OAAO,QAAQ,KAAK,OAAO,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,MAC3F;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,gBAAgB,QAAQ,CAAC,EAAE;AAAA,IAClC;AAEA,QAAI;AACF,YAAM,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAQ,wBAAwB;AAAA,QACxE,OAAO,KAAK,OAAO;AAAA,QACnB,MAAM,KAAK,OAAO;AAAA,QAClB,QAAQ,KAAK,OAAO;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,iBAAW,OAAO,KAAK,eAAe;AACpC,YAAI,KAAK,kBAAkB,IAAI,GAAG,SAAS,MAAM,KAAK,eAAgB;AAEtE,YAAI,IAAI,WAAW,aAAa;AAC9B,gBAAM,QAAkB;AAAA,YACtB,MAAM,IAAI,eAAe,YAAY,qBAAqB;AAAA,YAC1D,UAAU;AAAA,YACV,QAAQ,KAAK,OAAO;AAAA,YACpB,QAAQ,IAAI;AAAA,YACZ,QAAQ,IAAI,OAAO,SAAS;AAAA,YAC5B,SAAS,IAAI,QAAQ;AAAA,YACrB,WAAW,IAAI,KAAK,IAAI,cAAc,KAAK,IAAI,CAAC;AAAA,YAChD,YAAY,IAAI,GAAG,SAAS;AAAA,YAC5B,gBAAgB,IAAI,cAAc;AAAA,UACpC;AAEA,eAAK,KAAK,aAAa,KAAK;AAE5B,cAAI,IAAI,eAAe,WAAW;AAChC,iBAAK,KAAK,oBAAoB,KAAK;AACnC,mBAAO,KAAK,oBAAoB,EAAE,MAAM,IAAI,MAAM,IAAI,IAAI,GAAG,CAAC;AAAA,UAChE,OAAO;AACL,iBAAK,KAAK,oBAAoB,KAAK;AACnC,mBAAO,KAAK,oBAAoB,EAAE,MAAM,IAAI,MAAM,IAAI,IAAI,GAAG,CAAC;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,cAAc,SAAS,GAAG;AACjC,aAAK,iBAAiB,KAAK,cAAc,CAAC,EAAE,GAAG,SAAS;AAAA,MAC1D;AAAA,IACF,QAAQ;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB;AAC/B,UAAM,UAAU,EAAE,iBAAiB,KAAK,OAAO,MAAM;AACrD,UAAM,cAAc,mBAAmB,GAAG,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO,IAAI,EAAE;AACjF,UAAM,UAAU,KAAK,OAAO;AAE5B,QAAI;AACF,YAAM,aAAa,MAAM;AAAA,QACvB,GAAG,OAAO,oBAAoB,WAAW,gCAAgC,KAAK,OAAO,MAAM;AAAA,QAC3F,EAAE,QAAQ;AAAA,MACZ;AACA,YAAM,UAAU,MAAM,WAAW,KAAK;AACtC,UAAI,QAAQ,SAAS,GAAG;AACtB,aAAK,gBAAgB,QAAQ,CAAC,EAAE;AAAA,MAClC;AAEA,YAAM,eAAe,MAAM;AAAA,QACzB,GAAG,OAAO,oBAAoB,WAAW,kBAAkB,KAAK,OAAO,MAAM;AAAA,QAC7E,EAAE,QAAQ;AAAA,MACZ;AACA,YAAM,YAAY,MAAM,aAAa,KAAK;AAC1C,UAAI,UAAU,SAAS,GAAG;AACxB,aAAK,iBAAiB,UAAU,CAAC,EAAE,GAAG,SAAS;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,8BAA8B,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IAC9G;AAAA,EACF;AAAA,EAEA,MAAc,aAAa;AACzB,UAAM,UAAU,EAAE,iBAAiB,KAAK,OAAO,MAAM;AACrD,UAAM,cAAc,mBAAmB,GAAG,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO,IAAI,EAAE;AACjF,UAAM,UAAU,KAAK,OAAO;AAE5B,QAAI;AACF,YAAM,aAAa,MAAM;AAAA,QACvB,GAAG,OAAO,oBAAoB,WAAW,gCAAgC,KAAK,OAAO,MAAM;AAAA,QAC3F,EAAE,QAAQ;AAAA,MACZ;AACA,YAAM,UAAU,MAAM,WAAW,KAAK;AAEtC,iBAAW,UAAU,SAAS;AAC5B,YAAI,KAAK,iBAAiB,OAAO,OAAO,KAAK,cAAe;AAE5D,cAAM,UAAU,OAAO,cAAc,OAAO,WAAW,SAAS;AAEhE,cAAM,QAAkB;AAAA,UACtB,MAAM,UAAU,UAAU;AAAA,UAC1B,UAAU;AAAA,UACV,QAAQ,KAAK,OAAO;AAAA,UACpB,QAAQ,OAAO;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,SAAS,OAAO;AAAA,UAChB,WAAW,IAAI,KAAK,OAAO,UAAU;AAAA,QACvC;AAEA,aAAK,KAAK,aAAa,KAAK;AAE5B,YAAI,SAAS;AACX,eAAK,KAAK,SAAS,KAAK;AACxB,iBAAO,KAAK,kBAAkB,EAAE,QAAQ,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;AAAA,QACzF;AAAA,MACF;AAEA,UAAI,QAAQ,SAAS,GAAG;AACtB,aAAK,gBAAgB,QAAQ,CAAC,EAAE;AAAA,MAClC;AAEA,YAAM,eAAe,MAAM;AAAA,QACzB,GAAG,OAAO,oBAAoB,WAAW,kBAAkB,KAAK,OAAO,MAAM;AAAA,QAC7E,EAAE,QAAQ;AAAA,MACZ;AACA,YAAM,YAAY,MAAM,aAAa,KAAK;AAE1C,iBAAW,YAAY,WAAW;AAChC,YAAI,KAAK,kBAAkB,SAAS,GAAG,SAAS,MAAM,KAAK,eAAgB;AAE3E,YAAI,SAAS,WAAW,aAAa,SAAS,WAAW,UAAU;AACjE,gBAAM,QAAkB;AAAA,YACtB,MAAM,SAAS,WAAW,YAAY,qBAAqB;AAAA,YAC3D,UAAU;AAAA,YACV,QAAQ,KAAK,OAAO;AAAA,YACpB,QAAQ,SAAS;AAAA,YACjB,QAAQ,SAAS,MAAM,QAAQ;AAAA,YAC/B,SAAS,aAAa,SAAS,EAAE;AAAA,YACjC,WAAW,IAAI,KAAK,SAAS,UAAU;AAAA,YACvC,YAAY,SAAS,GAAG,SAAS;AAAA,YACjC,gBAAgB,SAAS;AAAA,UAC3B;AAEA,eAAK,KAAK,aAAa,KAAK;AAE5B,cAAI,SAAS,WAAW,WAAW;AACjC,iBAAK,KAAK,oBAAoB,KAAK;AACnC,mBAAO,KAAK,oBAAoB,EAAE,IAAI,SAAS,GAAG,CAAC;AAAA,UACrD,OAAO;AACL,iBAAK,KAAK,oBAAoB,KAAK;AACnC,mBAAO,KAAK,oBAAoB,EAAE,IAAI,SAAS,GAAG,CAAC;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAEA,UAAI,UAAU,SAAS,GAAG;AACxB,aAAK,iBAAiB,UAAU,CAAC,EAAE,GAAG,SAAS;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,qBAAqB,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IACrG;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,YAAqC;AACtD,QAAI,KAAK,OAAO,aAAa,UAAU;AACrC,aAAO,KAAK,mBAAmB,UAAU;AAAA,IAC3C,OAAO;AACL,aAAO,KAAK,mBAAmB,UAAU;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,YAAqC;AACpE,QAAI,CAAC,KAAK,QAAS,OAAM,IAAI,MAAM,uBAAuB;AAE1D,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,QAAQ,MAAM,cAAc;AAAA,MACtD,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM,KAAK,OAAO;AAAA,MAClB,QAAQ;AAAA,QACN,KAAK;AAAA,QACL,cAAc;AAAA,MAChB;AAAA,MACA,QAAQ,CAAC,QAAQ,gBAAgB,cAAc;AAAA,IACjD,CAAC;AAED,WAAO,KAAK,GAAG,SAAS;AAAA,EAC1B;AAAA,EAEA,MAAc,mBAAmB,YAAqC;AACpE,UAAM,UAAU;AAAA,MACd,iBAAiB,KAAK,OAAO;AAAA,MAC7B,gBAAgB;AAAA,IAClB;AACA,UAAM,cAAc,mBAAmB,GAAG,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO,IAAI,EAAE;AAEjF,UAAM,MAAM,MAAM;AAAA,MAChB,GAAG,KAAK,OAAO,SAAS,oBAAoB,WAAW;AAAA,MACvD;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,KAAK;AAAA,UACL,aAAa;AAAA,UACb,uBAAuB;AAAA,UACvB,iBAAiB;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,GAAG,SAAS;AAAA,EAC1B;AACF;;;ACtYA;AAAA,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,gBAAAC,qBAAoB;AAoC7B,IAAM,qBAAgD;AAAA,EACpD,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxB,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUtB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUd,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUf,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASvB;AAEO,IAAM,yBAAN,cAAqCA,cAAa;AAAA,EAC/C,SAAkC,oBAAI,IAAI;AAAA,EAC1C,gBAA0C,oBAAI,IAAI;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACE,IACA,WACA,WACA,cACA;AACA,UAAM;AACN,SAAK,KAAK;AACV,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,mBAAmB;AACzB,QAAI,KAAK,UAAU,aAAa,aAAa;AAC3C,aAAO,IAAI,iBAAiB;AAAA,QAC1B,QAAQ,KAAK,UAAU;AAAA,QACvB,OAAO,KAAK,UAAU,SAAS;AAAA,MACjC,CAAC;AAAA,IACH;AACA,WAAO,IAAI,cAAc;AAAA,MACvB,QAAQ,KAAK,UAAU;AAAA,MACvB,OAAO,KAAK,UAAU,SAAS;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,iBAAiB,MAAiB,cAA+B;AAC/D,UAAM,UAAU,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC;AAErC,UAAM,eAAe,gBAAgB,mBAAmB,IAAI;AAE5D,UAAM,MAAM,KAAK,iBAAiB;AAClC,UAAM,QAAQ,IAAI,WAAW;AAAA,MAC3B,OAAO,KAAK,aAAa,SAAS;AAAA,MAClC,eAAe;AAAA,MACf,cAAc,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ/B,GAAG,GAAG;AAEN,SAAK,OAAO,IAAI,SAAS,KAAK;AAE9B,UAAM,SAAsB;AAAA,MAC1B,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AACA,SAAK,cAAc,IAAI,SAAS,MAAM;AAEtC,SAAK,KAAK,iBAAiB,MAAM;AAEjC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,SAAiB,WAAkC;AACrE,UAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,UAAM,SAAS,KAAK,cAAc,IAAI,OAAO;AAE7C,QAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,YAAM,IAAI,MAAM,SAAS,OAAO,YAAY;AAAA,IAC9C;AAEA,WAAO,SAAS;AAChB,WAAO,YAAY,oBAAI,KAAK;AAC5B,WAAO,WAAW;AAClB,SAAK,KAAK,iBAAiB,MAAM;AAEjC,QAAI;AACF,YAAM,SAAS,MAAM,MAAM;AAAA,QACzB,2BAA2B,SAAS;AAAA,MACtC;AAEA,aAAO,SAAS;AAChB,aAAO,cAAc,oBAAI,KAAK;AAC9B,aAAO,WAAW;AAElB,WAAK,KAAK,mBAAmB,EAAE,GAAG,QAAQ,OAAO,CAAC;AAAA,IAEpD,SAAS,OAAgB;AACvB,aAAO,SAAS;AAChB,aAAO,cAAc,oBAAI,KAAK;AAE9B,WAAK,KAAK,gBAAgB,EAAE,GAAG,QAAQ,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IACxG;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,WAAmB,OAAoC;AAC7E,UAAM,aAAa,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,WAAW,WAAW,IAAI,UAAQ,KAAK,iBAAiB,IAAI,CAAC;AAEnE,eAAW,WAAW,UAAU;AAC9B,YAAM,KAAK,cAAc,SAAS,SAAS;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,WAAkC;AACvD,UAAM,gBAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,KAAK,kBAAkB,WAAW,aAAa;AAAA,EACvD;AAAA,EAEA,eAAe,SAA0C;AACvD,WAAO,KAAK,cAAc,IAAI,OAAO;AAAA,EACvC;AAAA,EAEA,iBAAgC;AAC9B,WAAO,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC;AAAA,EAC/C;AAAA,EAEA,UAAU,SAAuB;AAC/B,UAAM,SAAS,KAAK,cAAc,IAAI,OAAO;AAC7C,QAAI,UAAU,OAAO,WAAW,WAAW;AACzC,aAAO,SAAS;AAChB,aAAO,cAAc,oBAAI,KAAK;AAC9B,WAAK,KAAK,iBAAiB,MAAM;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,eAAW,CAAC,OAAO,KAAK,KAAK,QAAQ;AACnC,WAAK,UAAU,OAAO;AAAA,IACxB;AAAA,EACF;AACF;;;AC/RA;AAwBA,IAAM,iBAAkE;AAAA,EACtE;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMR,UAAU,CAAC,MAAM,QAAQ,WAAW,SAAS;AAAA,EAC/C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOR,UAAU,CAAC,UAAU,cAAc,UAAU;AAAA,EAC/C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQR,UAAU,CAAC,QAAQ,QAAQ,YAAY,WAAW,WAAW;AAAA,EAC/D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOR,UAAU,CAAC,QAAQ,SAAS,MAAM;AAAA,EACpC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQR,UAAU,CAAC,SAAS,OAAO,WAAW;AAAA,EACxC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMR,UAAU,CAAC,QAAQ,SAAS,SAAS,MAAM;AAAA,EAC7C;AACF;AAEO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA,SAA6B,oBAAI,IAAI;AAAA,EAE7C,YAAY,IAAoB;AAC9B,SAAK,KAAK;AACV,SAAK,WAAW;AAAA,EAClB;AAAA,EAEQ,aAAa;AAEnB,mBAAe,QAAQ,WAAS;AAC9B,WAAK,YAAY,KAAK;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEQ,aAAa;AAAA,EAGrB;AAAA,EAEA,YAAY,MAA4D;AACtE,UAAM,QAAe;AAAA,MACnB,GAAG;AAAA,MACH,IAAI,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,MAClE,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,IACtB;AAEA,SAAK,OAAO,IAAI,MAAM,IAAI,KAAK;AAC/B,SAAK,WAAW;AAEhB,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,IAAY,SAAiE;AACvF,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,UAAiB;AAAA,MACrB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,WAAW,oBAAI,KAAK;AAAA,IACtB;AAEA,SAAK,OAAO,IAAI,IAAI,OAAO;AAC3B,SAAK,WAAW;AAEhB,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,IAAqB;AAC/B,UAAM,UAAU,KAAK,OAAO,OAAO,EAAE;AACrC,QAAI,SAAS;AACX,WAAK,WAAW;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,IAA+B;AACtC,WAAO,KAAK,OAAO,IAAI,EAAE;AAAA,EAC3B;AAAA,EAEA,eAAwB;AACtB,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC;AAAA,EACxC;AAAA,EAEA,mBAA4B;AAC1B,WAAO,KAAK,aAAa,EACtB,OAAO,OAAK,EAAE,OAAO,EACrB,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,EAC3C;AAAA,EAEA,gBAAgB,MAA8B;AAC5C,WAAO,KAAK,aAAa,EAAE,OAAO,OAAK,EAAE,SAAS,IAAI;AAAA,EACxD;AAAA,EAEA,oBAAoB,MAAuB;AACzC,UAAM,YAAY,KAAK,YAAY;AACnC,WAAO,KAAK,iBAAiB,EAAE;AAAA,MAAO,WACpC,MAAM,UAAU,KAAK,aAAW,UAAU,SAAS,QAAQ,YAAY,CAAC,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,oBAAoB,QAAyB;AAC3C,QAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,UAAM,oBAAoB,OAAO;AAAA,MAAI,CAAC,OAAO,UAC3C,aAAa,QAAQ,CAAC,KAAK,MAAM,IAAI;AAAA,EAAK,MAAM,MAAM;AAAA,IACxD,EAAE,KAAK,MAAM;AAEb,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAIjB;AAAA,EAEA,YAAY,IAA0B;AACpC,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,QAAI,CAAC,MAAO,QAAO;AAEnB,WAAO,KAAK,YAAY,IAAI,EAAE,SAAS,CAAC,MAAM,QAAQ,CAAC;AAAA,EACzD;AAAA,EAEA,cAAc,YAA4B;AACxC,eAAW,QAAQ,CAAC,IAAI,UAAU;AAChC,YAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,UAAI,OAAO;AACT,cAAM,WAAW,QAAQ;AACzB,cAAM,YAAY,oBAAI,KAAK;AAAA,MAC7B;AAAA,IACF,CAAC;AACD,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,eAAuB;AACrB,WAAO,KAAK,UAAU,KAAK,aAAa,GAAG,MAAM,CAAC;AAAA,EACpD;AAAA,EAEA,aAAa,MAAsB;AACjC,UAAM,WAAW,KAAK,MAAM,IAAI;AAChC,QAAI,QAAQ;AAEZ,aAAS,QAAQ,WAAS;AACxB,YAAM,WAAW,KAAK,YAAY;AAAA,QAChC,MAAM,MAAM;AAAA,QACZ,aAAa,MAAM;AAAA,QACnB,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,UAAU,MAAM;AAAA,MAClB,CAAC;AACD,UAAI,SAAU;AAAA,IAChB,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AVrPO,IAAM,cAAN,cAA0BC,cAAa;AAAA,EACpC,QAA2B;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,eAAoC;AAAA,EACpC,YAAoB;AAAA,EACpB,YAAqB;AAAA,EACrB,aAAoC;AAAA;AAAA,EAGpC,cAAkC;AAAA,EAClC,oBAAmD;AAAA,EACnD;AAAA,EAER,YAAY,YAAqB;AAC/B,UAAM;AACN,SAAK,SAAS,IAAI,cAAc,UAAU;AAC1C,SAAK,KAAK,IAAI,eAAe,oBAAoB;AACjD,SAAK,eAAe,IAAI,aAAa,KAAK,EAAE;AAAA,EAC9C;AAAA,EAEQ,mBAAmB;AACzB,UAAM,MAAM,KAAK,OAAO,cAAc;AAEtC,YAAQ,IAAI,IAAI,UAAU;AAAA,MACxB,KAAK;AACH,eAAO,IAAIC,kBAAiB;AAAA,UAC1B,QAAQ,IAAI,IAAI,UAAU,QAAQ,IAAI;AAAA,UACtC,OAAO,IAAI,IAAI,SAAS;AAAA,QAC1B,CAAC;AAAA,MACH,KAAK;AAAA,MACL;AACE,eAAO,IAAIC,eAAc;AAAA,UACvB,QAAQ,IAAI,IAAI,UAAU,QAAQ,IAAI;AAAA,UACtC,OAAO,IAAI,IAAI,SAAS;AAAA,QAC1B,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,cAAyE,UAAU,aAAuC;AACzI,UAAM,MAAM,KAAK,OAAO,cAAc;AACtC,SAAK,YAAY,WAAW,KAAK,IAAI,CAAC;AAEtC,UAAM,KAAK,GAAG,cAAc,KAAK,WAAW;AAAA,MAC1C,QAAQ;AAAA,MACR,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC,CAAC;AAED,SAAK,eAAe,IAAI,aAAa,KAAK,IAAI,KAAK,SAAS;AAC5D,UAAM,cAAc,IAAI,YAAY,KAAK,IAAI,KAAK,WAAW,IAAI,UAAU,CAAC,CAAC;AAC7E,UAAM,cAAc,IAAI,YAAY,KAAK,IAAI,KAAK,SAAS;AAE3D,UAAM,WAAW;AAAA,MACf,GAAG,KAAK,aAAa,SAAS;AAAA,MAC9B,GAAG,YAAY,SAAS;AAAA,MACxB,GAAG,YAAY,SAAS;AAAA,IAC1B;AAEA,UAAM,MAAM,KAAK,iBAAiB;AAClC,UAAM,SAAS,IAAI,OAAO,EAAE,aAAa,GAAG,CAAC;AAC7C,UAAM,SAAS,IAAI,OAAO,EAAE,UAAU,OAAO,CAAC;AAG9C,UAAM,gBAAgB,KAAK,aAAa,iBAAiB;AACzD,UAAM,cAAc,KAAK,aAAa,oBAAoB,aAAa;AAEvE,UAAM,cAAc;AAAA,MAClB,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA,eAAe,IAAI,MAAM;AAAA,MACzB,cAAc;AAAA;AAAA;AAAA,qDAGiC,IAAI,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwB/D,WAAW;AAAA;AAAA;AAAA,IAGT;AAEA,SAAK,QAAQ,IAAIC,YAAW;AAAA,MAC1B,MAAM,YAAY;AAAA,MAClB,OAAO;AAAA,MACP,UAAU,IAAI,MAAM;AAAA,MACpB,cAAc,YAAY;AAAA,IAC5B,GAAG,KAAK,MAAM;AAGd,SAAK,oBAAoB,IAAI;AAAA,MAC3B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,EAAE,UAAU,IAAI,IAAI,UAAU,QAAQ,IAAI,IAAI,UAAU,GAAG;AAAA,MAC3D,KAAK;AAAA,IACP;AAGA,SAAK,kBAAkB,GAAG,iBAAiB,CAAC,WAAwB,KAAK,KAAK,sBAAsB,MAAM,CAAC;AAC3G,SAAK,kBAAkB,GAAG,iBAAiB,CAAC,WAAwB,KAAK,KAAK,sBAAsB,MAAM,CAAC;AAC3G,SAAK,kBAAkB,GAAG,mBAAmB,CAAC,SAA4C,KAAK,KAAK,wBAAwB,IAAI,CAAC;AACjI,SAAK,kBAAkB,GAAG,gBAAgB,CAAC,SAA2C,KAAK,KAAK,qBAAqB,IAAI,CAAC;AAE1H,YAAQ,IAAI,6CAAwC,KAAK,SAAS,GAAG;AAAA,EACvE;AAAA,EAEA,MAAM,aAAa;AACjB,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU;AACxC,YAAQ,IAAI,uCAAgC,IAAI,KAAK,GAAG,EAAE;AAE1D,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,MAAO;AAAA,QAC/B,uCAAuC,IAAI,KAAK,GAAG;AAAA,MACrD;AAEA,YAAM,KAAK,GAAG,cAAc,KAAK,WAAW;AAAA,QAC1C,QAAQ;AAAA,QACR,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,CAAC;AAED,cAAQ,IAAI,kCAA6B,MAAM;AAC/C,aAAO;AAAA,IACT,SAAS,OAAgB;AACvB,cAAQ,MAAM,yBAAoB,KAAK;AAEvC,YAAM,KAAK,GAAG,cAAc,KAAK,WAAW;AAAA,QAC1C,QAAQ;AAAA,QACR,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,CAAC;AAED,YAAM;AAAA,IACR,UAAE;AACA,UAAI,KAAK,cAAc;AACrB,cAAM,KAAK,aAAa,MAAM;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB;AACtB,QAAI,KAAK,WAAW;AAClB,cAAQ,IAAI,wCAA8B;AAC1C;AAAA,IACF;AAEA,SAAK,YAAY;AACjB,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU;AAExC,YAAQ,IAAI,oDAA6C;AACzD,YAAQ,IAAI,qBAAc,IAAI,KAAK,GAAG,EAAE;AACxC,YAAQ,IAAI,2BAAiB,IAAI,MAAM,UAAU,OAAO,IAAI,MAAM,aAAa,MAAO,EAAE,WAAW;AAGnG,UAAM,KAAK,iBAAiB;AAE5B,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,KAAK,UAAW;AAErB,UAAI;AACF,cAAM,KAAK,WAAW;AAAA,MACxB,SAAS,OAAO;AACd,gBAAQ,MAAM,6CAA6C;AAAA,MAC7D;AAEA,UAAI,KAAK,WAAW;AAClB,aAAK,YAAY,WAAW,KAAK,IAAI,CAAC;AACtC,aAAK,QAAQ;AACb,aAAK,eAAe;AAEpB,aAAK,aAAa,WAAW,SAAS,IAAI,MAAM,UAAU;AAAA,MAC5D;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,EAChB;AAAA,EAEA,OAAO;AACL,YAAQ,IAAI,oCAA6B;AACzC,SAAK,YAAY;AAEjB,QAAI,KAAK,YAAY;AACnB,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,KAAK;AACtB,WAAK,cAAc;AAAA,IACrB;AAEA,QAAI,KAAK,mBAAmB;AAC1B,WAAK,kBAAkB,QAAQ;AAAA,IACjC;AAEA,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,MAAM;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,mBAAmB;AAC/B,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU;AAGxC,QAAI,IAAI,QAAQ,SAAS,IAAI,QAAQ,SAAS,IAAI,QAAQ,MAAM;AAC9D,WAAK,cAAc,IAAI,YAAY;AAAA,QACjC,UAAU;AAAA,QACV,OAAO,IAAI,OAAO;AAAA,QAClB,OAAO,IAAI,OAAO;AAAA,QAClB,MAAM,IAAI,OAAO;AAAA,QACjB,QAAQ;AAAA,QACR,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAEK;AACH,YAAM,cAAc,MAAM,KAAK,OAAO,IAAI,cAAc;AACxD,YAAM,gBAAgB,MAAM,KAAK,OAAO,IAAI,gBAAgB;AAC5D,UAAI,eAAe,eAAe;AAChC,cAAM,CAAC,OAAO,IAAI,IAAI,cAAc,MAAM,GAAG;AAC7C,cAAM,YAAY,MAAM,KAAK,OAAO,IAAI,YAAY;AACpD,aAAK,cAAc,IAAI,YAAY;AAAA,UACjC,UAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,WAAW,aAAa;AAAA,QAC1B,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,KAAK,aAAa;AAEpB,WAAK,YAAY,GAAG,SAAS,OAAO,UAAoB;AACtD,gBAAQ,IAAI,oDAA6C;AACzD,aAAK,KAAK,aAAa,KAAK;AAG5B,aAAK,YAAY,WAAW,KAAK,IAAI,CAAC;AACtC,aAAK,QAAQ;AACb,aAAK,eAAe;AACpB,cAAM,KAAK,WAAW;AAAA,MACxB,CAAC;AAGD,WAAK,YAAY,GAAG,oBAAoB,OAAO,UAAoB;AACjE,gBAAQ,IAAI,mDAA8C;AAC1D,aAAK,KAAK,wBAAwB,KAAK;AAGvC,aAAK,YAAY,WAAW,KAAK,IAAI,CAAC;AACtC,aAAK,QAAQ;AACb,aAAK,eAAe;AACpB,cAAM,KAAK,WAAW;AAAA,MACxB,CAAC;AAED,YAAM,KAAK,YAAY,MAAM;AAC7B,cAAQ,IAAI,sCAA+B,KAAK,cAAc,eAAe,MAAM,EAAE;AAAA,IACvF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,kBAAiC;AACrC,QAAI,CAAC,KAAK,mBAAmB;AAC3B,YAAM,KAAK,WAAW;AAAA,IACxB;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU;AACxC,UAAM,KAAK,kBAAmB,iBAAiB,IAAI,KAAK,GAAG;AAAA,EAC7D;AAAA,EAEA,MAAM,cAAc,MAAgC;AAClD,QAAI,CAAC,KAAK,mBAAmB;AAC3B,YAAM,KAAK,WAAW;AAAA,IACxB;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU;AACxC,UAAM,UAAU,KAAK,kBAAmB,iBAAiB,IAAI;AAC7D,UAAM,KAAK,kBAAmB,cAAc,SAAS,IAAI,KAAK,GAAG;AAAA,EACnE;AAAA,EAEA,wBAAuC;AACrC,WAAO,KAAK,mBAAmB,eAAe,KAAK,CAAC;AAAA,EACtD;AAAA;AAAA,EAGA,YAAqB;AACnB,WAAO,KAAK,aAAa,aAAa;AAAA,EACxC;AAAA,EAEA,YAAY,MAA4D;AACtE,WAAO,KAAK,aAAa,YAAY,IAAI;AAAA,EAC3C;AAAA,EAEA,YAAY,IAAY,SAAuC;AAC7D,WAAO,KAAK,aAAa,YAAY,IAAI,OAAO;AAAA,EAClD;AAAA,EAEA,YAAY,IAAqB;AAC/B,WAAO,KAAK,aAAa,YAAY,EAAE;AAAA,EACzC;AAAA,EAEA,YAAY,IAA0B;AACpC,WAAO,KAAK,aAAa,YAAY,EAAE;AAAA,EACzC;AAAA,EAEA,MAAM,YAAY;AAChB,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,MAAM,KAAK,OAAO,UAAU;AAAA,MACpC,mBAAmB,CAAC,CAAC,KAAK;AAAA,MAC1B,aAAa,KAAK,sBAAsB;AAAA,MACxC,QAAQ,KAAK,aAAa,iBAAiB,EAAE;AAAA,IAC/C;AAAA,EACF;AACF;","names":["ReActAgent","OpenAIAdapter","AnthropicAdapter","EventEmitter","fileURLToPath","__filename","fileURLToPath","__dirname","mkdirSync","join","path","Octokit","Octokit","EventEmitter","EventEmitter","AnthropicAdapter","OpenAIAdapter","ReActAgent"]}
1
+ {"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../database/sqlite.ts","../../agent/index.ts","../../database/index.ts","../../agent/config/index.ts","../../agent/config/schema.ts","../../agent/logger.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":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import Database from 'better-sqlite3';\nimport { mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type { TestSession, Action, Bug, KanbanTicket } from './index.js';\n\nexport class OpenQASQLiteDatabase {\n private db: Database.Database;\n\n constructor(dbPath: string = './data/openqa.db') {\n mkdirSync(dirname(dbPath), { recursive: true });\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.migrate();\n }\n\n private migrate(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS config (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS test_sessions (\n id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n status TEXT NOT NULL DEFAULT 'running',\n total_actions INTEGER NOT NULL DEFAULT 0,\n bugs_found INTEGER NOT NULL DEFAULT 0,\n metadata TEXT\n );\n\n CREATE TABLE IF NOT EXISTS actions (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n type TEXT NOT NULL,\n description TEXT NOT NULL,\n input TEXT,\n output TEXT,\n screenshot_path TEXT,\n FOREIGN KEY (session_id) REFERENCES test_sessions(id)\n );\n\n CREATE TABLE IF NOT EXISTS bugs (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n severity TEXT NOT NULL DEFAULT 'medium',\n status TEXT NOT NULL DEFAULT 'open',\n github_issue_url TEXT,\n screenshot_path TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES test_sessions(id)\n );\n\n CREATE TABLE IF NOT EXISTS kanban_tickets (\n id TEXT PRIMARY KEY,\n bug_id TEXT,\n title TEXT NOT NULL,\n description TEXT NOT NULL,\n priority TEXT NOT NULL DEFAULT 'medium',\n column TEXT NOT NULL DEFAULT 'backlog',\n tags TEXT,\n screenshot_url TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n `);\n }\n\n // ── Config ──\n\n async getConfig(key: string): Promise<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 async setConfig(key: string, value: string): Promise<void> {\n this.db.prepare('INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)').run(key, value);\n }\n\n async getAllConfig(): Promise<Record<string, string>> {\n const rows = this.db.prepare('SELECT key, value FROM config').all() as Array<{ key: string; value: string }>;\n return Object.fromEntries(rows.map(r => [r.key, r.value]));\n }\n\n async clearAllConfig(): Promise<void> {\n this.db.prepare('DELETE FROM config').run();\n }\n\n // ── Sessions ──\n\n async createSession(id: string, metadata?: Record<string, unknown>): Promise<TestSession> {\n const session: TestSession = {\n id,\n started_at: new Date().toISOString(),\n status: 'running',\n total_actions: 0,\n bugs_found: 0,\n metadata: metadata ? JSON.stringify(metadata) : undefined,\n };\n this.db.prepare(`\n INSERT INTO test_sessions (id, started_at, status, total_actions, bugs_found, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(session.id, session.started_at, session.status, session.total_actions, session.bugs_found, session.metadata ?? null);\n return session;\n }\n\n async getSession(id: string): Promise<TestSession | null> {\n return (this.db.prepare('SELECT * FROM test_sessions WHERE id = ?').get(id) as TestSession) ?? null;\n }\n\n async updateSession(id: string, updates: Partial<TestSession>): Promise<void> {\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 async getRecentSessions(limit = 10): Promise<TestSession[]> {\n return this.db.prepare('SELECT * FROM test_sessions ORDER BY started_at DESC LIMIT ?').all(limit) as TestSession[];\n }\n\n // ── Actions ──\n\n async createAction(action: Omit<Action, 'id' | 'timestamp'>): Promise<Action> {\n const newAction: Action = {\n id: `action_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n timestamp: new Date().toISOString(),\n ...action,\n };\n this.db.prepare(`\n INSERT INTO actions (id, session_id, timestamp, type, description, input, output, screenshot_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newAction.id, newAction.session_id, newAction.timestamp,\n newAction.type, newAction.description,\n newAction.input ?? null, newAction.output ?? null, newAction.screenshot_path ?? null,\n );\n return newAction;\n }\n\n async getSessionActions(sessionId: string): Promise<Action[]> {\n return this.db.prepare('SELECT * FROM actions WHERE session_id = ? ORDER BY timestamp DESC').all(sessionId) as Action[];\n }\n\n // ── Bugs ──\n\n async createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Promise<Bug> {\n const newBug: Bug = {\n id: `bug_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...bug,\n };\n this.db.prepare(`\n INSERT INTO bugs (id, session_id, title, description, severity, status, github_issue_url, screenshot_path, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newBug.id, newBug.session_id, newBug.title, newBug.description,\n newBug.severity, newBug.status,\n newBug.github_issue_url ?? null, newBug.screenshot_path ?? null,\n newBug.created_at, newBug.updated_at,\n );\n return newBug;\n }\n\n async updateBug(id: string, updates: Partial<Bug>): Promise<void> {\n const patch = { ...updates, updated_at: new Date().toISOString() };\n const fields = Object.keys(patch).map(k => `${k} = ?`).join(', ');\n const values = [...Object.values(patch), id];\n this.db.prepare(`UPDATE bugs SET ${fields} WHERE id = ?`).run(...values);\n }\n\n async getAllBugs(): Promise<Bug[]> {\n return this.db.prepare('SELECT * FROM bugs ORDER BY created_at DESC').all() as Bug[];\n }\n\n async getBugsByStatus(status: Bug['status']): Promise<Bug[]> {\n return this.db.prepare('SELECT * FROM bugs WHERE status = ? ORDER BY created_at DESC').all(status) as Bug[];\n }\n\n // ── Kanban ──\n\n async createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): Promise<KanbanTicket> {\n const newTicket: KanbanTicket = {\n id: `ticket_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...ticket,\n };\n this.db.prepare(`\n INSERT INTO kanban_tickets (id, bug_id, title, description, priority, column, tags, screenshot_url, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n newTicket.id, newTicket.bug_id ?? null, newTicket.title, newTicket.description,\n newTicket.priority, newTicket.column,\n newTicket.tags ?? null, newTicket.screenshot_url ?? null,\n newTicket.created_at, newTicket.updated_at,\n );\n return newTicket;\n }\n\n async updateKanbanTicket(id: string, updates: Partial<KanbanTicket>): Promise<void> {\n const patch = { ...updates, updated_at: new Date().toISOString() };\n const fields = Object.keys(patch).map(k => `\"${k}\" = ?`).join(', ');\n const values = [...Object.values(patch), id];\n this.db.prepare(`UPDATE kanban_tickets SET ${fields} WHERE id = ?`).run(...values);\n }\n\n async getKanbanTickets(): Promise<KanbanTicket[]> {\n return this.db.prepare('SELECT * FROM kanban_tickets ORDER BY created_at DESC').all() as KanbanTicket[];\n }\n\n async getKanbanTicketsByColumn(column: KanbanTicket['column']): Promise<KanbanTicket[]> {\n return this.db.prepare('SELECT * FROM kanban_tickets WHERE \"column\" = ? ORDER BY created_at DESC').all(column) as KanbanTicket[];\n }\n\n async deleteKanbanTicket(id: string): Promise<void> {\n this.db.prepare('DELETE FROM kanban_tickets WHERE id = ?').run(id);\n }\n\n // ── Storage / Cleanup ──\n\n async pruneOldSessions(maxAgeDays: number): Promise<{ sessionsRemoved: number; actionsRemoved: number }> {\n const cutoff = new Date(Date.now() - maxAgeDays * 86400000).toISOString();\n const oldSessions = this.db.prepare('SELECT id FROM test_sessions WHERE started_at < ?').all(cutoff) as Array<{ id: string }>;\n const ids = oldSessions.map(s => s.id);\n if (ids.length === 0) return { sessionsRemoved: 0, actionsRemoved: 0 };\n\n const placeholders = ids.map(() => '?').join(', ');\n const actionsResult = this.db.prepare(`DELETE FROM actions WHERE session_id IN (${placeholders})`).run(...ids);\n this.db.prepare(`DELETE FROM test_sessions WHERE id IN (${placeholders})`).run(...ids);\n\n return { sessionsRemoved: ids.length, actionsRemoved: actionsResult.changes };\n }\n\n async getStorageStats(): Promise<{ sessions: number; actions: number; bugs: number; tickets: number }> {\n const count = (table: string): number =>\n (this.db.prepare(`SELECT COUNT(*) as n FROM ${table}`).get() as { n: number }).n;\n return {\n sessions: count('test_sessions'),\n actions: count('actions'),\n bugs: count('bugs'),\n tickets: count('kanban_tickets'),\n };\n }\n\n // ── Compat helpers (used by daemon.ts) ──\n\n async getActiveAgents() {\n const sessions = await this.getRecentSessions(1);\n const current = sessions[0];\n const isRunning = current?.status === 'running';\n return [{\n name: 'Main Agent',\n status: isRunning ? 'running' : 'idle',\n purpose: 'Autonomous QA orchestration',\n performance: current ? Math.min(100, Math.round((current.total_actions / 100) * 100)) : 0,\n tasks: current?.total_actions ?? 0,\n }];\n }\n\n async getCurrentTasks() {\n const sessions = await this.getRecentSessions(1);\n if (!sessions[0]) return [];\n const actions = await this.getSessionActions(sessions[0].id);\n return actions.slice(0, 10).map((a, i) => ({\n id: a.id, name: a.type, status: i === 0 && sessions[0].status === 'running' ? 'running' : 'completed',\n progress: i === 0 && sessions[0].status === 'running' ? '65%' : '100%',\n agent: 'Main Agent', started_at: a.timestamp, result: a.output || a.description,\n }));\n }\n\n async getCurrentIssues() {\n const bugs = await this.getAllBugs();\n return bugs.slice(0, 10).map(b => ({\n id: b.id, title: b.title, description: b.description,\n severity: b.severity, status: b.status, discovered_at: b.created_at, agent: 'Main Agent',\n }));\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { ReActAgent } from '@orka-js/agent';\nimport { OpenAIAdapter } from '@orka-js/openai';\nimport { AnthropicAdapter } from '@orka-js/anthropic';\nimport { Memory } 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('./data/openqa.json');\n this.skillManager = new SkillManager(this.db);\n }\n\n private createLLMAdapter() {\n const cfg = this.config.getConfigSync();\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?: Record<string, unknown>) {\n const cfg = this.config.getConfigSync();\n this.sessionId = `session_${Date.now()}`;\n\n await this.db.createSession(this.sessionId, {\n config: cfg,\n started_at: new Date().toISOString()\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 Memory({ 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({\n goal: agentConfig.goal,\n tools: allTools,\n maxSteps: cfg.agent.maxIterations,\n systemPrompt: agentConfig.systemPrompt\n }, 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: AgentStatus & { result?: string }) => this.emit('specialist-completed', data));\n this.specialistManager.on('agent-failed', (data: AgentStatus & { error?: string }) => 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 = await 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 await 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: unknown) {\n console.error('❌ Session error:', error);\n\n await 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 = await 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 = await 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 {\n const gitlabToken = await this.config.get('gitlab.token');\n const gitlabProject = await this.config.get('gitlab.project');\n if (gitlabToken && gitlabProject) {\n const [owner, repo] = gitlabProject.split('/');\n const gitlabUrl = await this.config.get('gitlab.url');\n this.gitListener = new GitListener({\n provider: 'gitlab',\n token: gitlabToken,\n owner,\n repo,\n branch: 'main',\n pollIntervalMs: 60000,\n gitlabUrl: gitlabUrl || 'https://gitlab.com'\n });\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 = await 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 = await 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 async getStatus() {\n return {\n isRunning: this.isRunning,\n sessionId: this.sessionId,\n config: await this.config.getConfig(),\n gitListenerActive: !!this.gitListener,\n specialists: this.getSpecialistStatuses(),\n skills: this.skillManager.getEnabledSkills().length\n };\n }\n}\n","import { Low } from 'lowdb';\nimport { JSONFile } from 'lowdb/node';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync, writeFileSync, readFileSync } from 'fs';\n\nexport { OpenQASQLiteDatabase } from './sqlite.js';\n\n/**\n * Factory — chooses SQLite for .db paths, LowDB for .json paths.\n */\nexport async function createDatabase(path: string): Promise<OpenQADatabase> {\n if (path.endsWith('.db')) {\n const { OpenQASQLiteDatabase } = await import('./sqlite.js');\n return new OpenQASQLiteDatabase(path) as unknown as OpenQADatabase;\n }\n return new OpenQADatabase(path);\n}\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 interface User {\n id: string;\n username: string;\n passwordHash: string;\n role: 'admin' | 'viewer';\n createdAt: string;\n updatedAt: string;\n}\n\ninterface DatabaseSchema {\n config: Record<string, string>;\n test_sessions: TestSession[];\n actions: Action[];\n bugs: Bug[];\n kanban_tickets: KanbanTicket[];\n users: User[];\n}\n\nexport class OpenQADatabase {\n private db: Low<DatabaseSchema> | null = null;\n\n constructor(private dbPath: string = './data/openqa.json') {\n this.initialize();\n }\n\n private initialize() {\n const dir = dirname(this.dbPath);\n mkdirSync(dir, { recursive: true });\n\n const adapter = new JSONFile<DatabaseSchema>(this.dbPath);\n this.db = new Low<DatabaseSchema>(adapter, {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: [],\n users: [],\n });\n\n this.db.read();\n if (!this.db.data) {\n this.db.data = {\n config: {},\n test_sessions: [],\n actions: [],\n bugs: [],\n kanban_tickets: [],\n users: [],\n };\n this.db.write();\n }\n }\n\n private async ensureInitialized() {\n if (!this.db) {\n this.initialize();\n }\n await this.db!.read();\n // Auto-migrate: add any missing top-level arrays added in later versions\n let migrated = false;\n if (!this.db!.data.users) { this.db!.data.users = []; migrated = true; }\n if (migrated) await this.db!.write();\n }\n\n async getConfig(key: string): Promise<string | null> {\n await this.ensureInitialized();\n return this.db!.data.config[key] || null;\n }\n\n async setConfig(key: string, value: string) {\n await this.ensureInitialized();\n this.db!.data.config[key] = value;\n await this.db!.write();\n }\n\n async getAllConfig(): Promise<Record<string, string>> {\n await this.ensureInitialized();\n return this.db!.data.config;\n }\n\n async createSession(id: string, metadata?: Record<string, unknown>): Promise<TestSession> {\n await this.ensureInitialized();\n const session: TestSession = {\n id,\n started_at: new Date().toISOString(),\n status: 'running',\n total_actions: 0,\n bugs_found: 0,\n metadata: metadata ? JSON.stringify(metadata) : undefined\n };\n this.db!.data.test_sessions.push(session);\n await this.db!.write();\n return session;\n }\n\n async getSession(id: string): Promise<TestSession | null> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions.find(s => s.id === id) || null;\n }\n\n async updateSession(id: string, updates: Partial<TestSession>) {\n await this.ensureInitialized();\n const index = this.db!.data.test_sessions.findIndex(s => s.id === id);\n if (index !== -1) {\n this.db!.data.test_sessions[index] = { ...this.db!.data.test_sessions[index], ...updates };\n await this.db!.write();\n }\n }\n\n async getRecentSessions(limit: number = 10): Promise<TestSession[]> {\n await this.ensureInitialized();\n return this.db!.data.test_sessions\n .sort((a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime())\n .slice(0, limit);\n }\n\n async createAction(action: Omit<Action, 'id' | 'timestamp'>): Promise<Action> {\n await this.ensureInitialized();\n const newAction: Action = {\n id: `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n timestamp: new Date().toISOString(),\n ...action\n };\n this.db!.data.actions.push(newAction);\n await this.db!.write();\n return newAction;\n }\n\n async getSessionActions(sessionId: string): Promise<Action[]> {\n await this.ensureInitialized();\n return this.db!.data.actions\n .filter(a => a.session_id === sessionId)\n .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n }\n\n async createBug(bug: Omit<Bug, 'id' | 'created_at' | 'updated_at'>): Promise<Bug> {\n await this.ensureInitialized();\n const newBug: Bug = {\n id: `bug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...bug\n };\n this.db!.data.bugs.push(newBug);\n await this.db!.write();\n return newBug;\n }\n\n async updateBug(id: string, updates: Partial<Bug>) {\n await this.ensureInitialized();\n const index = this.db!.data.bugs.findIndex(b => b.id === id);\n if (index !== -1) {\n this.db!.data.bugs[index] = { \n ...this.db!.data.bugs[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getAllBugs(): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getBugsByStatus(status: Bug['status']): Promise<Bug[]> {\n await this.ensureInitialized();\n return this.db!.data.bugs\n .filter(b => b.status === status)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async createKanbanTicket(ticket: Omit<KanbanTicket, 'id' | 'created_at' | 'updated_at'>): Promise<KanbanTicket> {\n await this.ensureInitialized();\n const newTicket: KanbanTicket = {\n id: `ticket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ...ticket\n };\n this.db!.data.kanban_tickets.push(newTicket);\n await this.db!.write();\n return newTicket;\n }\n\n async updateKanbanTicket(id: string, updates: Partial<KanbanTicket>) {\n await this.ensureInitialized();\n const index = this.db!.data.kanban_tickets.findIndex(t => t.id === id);\n if (index !== -1) {\n this.db!.data.kanban_tickets[index] = { \n ...this.db!.data.kanban_tickets[index], \n ...updates, \n updated_at: new Date().toISOString() \n };\n await this.db!.write();\n }\n }\n\n async getKanbanTickets(): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async getKanbanTicketsByColumn(column: KanbanTicket['column']): Promise<KanbanTicket[]> {\n await this.ensureInitialized();\n return this.db!.data.kanban_tickets\n .filter(t => t.column === column)\n .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n }\n\n async deleteKanbanTicket(id: string): Promise<void> {\n await this.ensureInitialized();\n const index = this.db!.data.kanban_tickets.findIndex(t => t.id === id);\n if (index !== -1) {\n this.db!.data.kanban_tickets.splice(index, 1);\n await this.db!.write();\n }\n }\n\n async clearAllConfig() {\n await this.ensureInitialized();\n this.db!.data.config = {};\n await this.db!.write();\n }\n\n // Get real data methods - connected to actual database records\n\n async getActiveAgents() {\n await this.ensureInitialized();\n const sessions = await this.getRecentSessions(1);\n const currentSession = sessions[0];\n \n // Return real agent state based on session status\n const isRunning = currentSession?.status === 'running';\n const totalActions = currentSession?.total_actions || 0;\n \n // Main agent is always present\n const agents = [\n { \n name: 'Main Agent', \n status: isRunning ? 'running' : 'idle', \n purpose: 'Autonomous QA orchestration', \n performance: totalActions > 0 ? Math.min(100, Math.round((totalActions / 100) * 100)) : 0, \n tasks: totalActions \n }\n ];\n \n // Add dynamic agents based on actual session activity\n if (currentSession && totalActions > 0) {\n const actions = await this.getSessionActions(currentSession.id);\n \n // Group actions by type to determine which specialists are active\n const actionTypes = actions.reduce((acc: Record<string, number>, action) => {\n const type = action.type || 'unknown';\n acc[type] = (acc[type] || 0) + 1;\n return acc;\n }, {});\n \n // Add specialists based on actual action types\n if (actionTypes['navigate'] || actionTypes['click'] || actionTypes['screenshot']) {\n agents.push({\n name: 'Browser Specialist',\n status: isRunning ? 'running' : 'idle',\n purpose: 'UI navigation and interaction',\n performance: Math.round(((actionTypes['navigate'] || 0) + (actionTypes['click'] || 0)) / totalActions * 100),\n tasks: (actionTypes['navigate'] || 0) + (actionTypes['click'] || 0)\n });\n }\n \n if (actionTypes['api_call'] || actionTypes['request']) {\n agents.push({\n name: 'API Tester',\n status: isRunning ? 'running' : 'idle',\n purpose: 'API endpoint testing',\n performance: Math.round((actionTypes['api_call'] || actionTypes['request'] || 0) / totalActions * 100),\n tasks: actionTypes['api_call'] || actionTypes['request'] || 0\n });\n }\n \n if (actionTypes['auth'] || actionTypes['login']) {\n agents.push({\n name: 'Auth Specialist',\n status: isRunning ? 'running' : 'idle',\n purpose: 'Authentication testing',\n performance: Math.round((actionTypes['auth'] || actionTypes['login'] || 0) / totalActions * 100),\n tasks: actionTypes['auth'] || actionTypes['login'] || 0\n });\n }\n }\n \n return agents;\n }\n\n async getCurrentTasks() {\n await this.ensureInitialized();\n const sessions = await this.getRecentSessions(1);\n const currentSession = sessions[0];\n \n if (!currentSession) {\n return [];\n }\n\n // Get real actions from the session\n const actions = await this.getSessionActions(currentSession.id);\n \n // Convert recent actions to tasks\n const recentActions = actions.slice(-10).reverse();\n \n return recentActions.map((action, index) => ({\n id: action.id,\n name: action.type || 'Unknown Action',\n status: index === 0 && currentSession.status === 'running' ? 'running' : 'completed',\n progress: index === 0 && currentSession.status === 'running' ? '65%' : '100%',\n agent: 'Main Agent',\n started_at: action.timestamp,\n result: action.output || action.description || 'Completed'\n }));\n }\n\n async getCurrentIssues() {\n await this.ensureInitialized();\n \n // Get real bugs from the database\n const bugs = await this.getAllBugs();\n \n // Return actual bugs as issues\n return bugs.slice(0, 10).map(bug => ({\n id: bug.id,\n title: bug.title,\n description: bug.description,\n severity: bug.severity || 'medium',\n status: bug.status || 'open',\n discovered_at: bug.created_at,\n agent: 'Main Agent'\n }));\n }\n\n async pruneOldSessions(maxAgeDays: number): Promise<{ sessionsRemoved: number; actionsRemoved: number }> {\n await this.ensureInitialized();\n const cutoff = new Date(Date.now() - maxAgeDays * 86400000).toISOString();\n\n const oldSessions = this.db!.data.test_sessions.filter(s => s.started_at < cutoff);\n const oldSessionIds = new Set(oldSessions.map(s => s.id));\n\n const actionsBefore = this.db!.data.actions.length;\n this.db!.data.actions = this.db!.data.actions.filter(a => !oldSessionIds.has(a.session_id));\n const actionsRemoved = actionsBefore - this.db!.data.actions.length;\n\n this.db!.data.test_sessions = this.db!.data.test_sessions.filter(s => s.started_at >= cutoff);\n await this.db!.write();\n\n return { sessionsRemoved: oldSessions.length, actionsRemoved };\n }\n\n async getStorageStats(): Promise<{ sessions: number; actions: number; bugs: number; tickets: number }> {\n await this.ensureInitialized();\n return {\n sessions: this.db!.data.test_sessions.length,\n actions: this.db!.data.actions.length,\n bugs: this.db!.data.bugs.length,\n tickets: this.db!.data.kanban_tickets.length,\n };\n }\n\n // ── User management ──────────────────────────────────────────────────────────\n\n async countUsers(): Promise<number> {\n await this.ensureInitialized();\n return this.db!.data.users.length;\n }\n\n async findUserByUsername(username: string): Promise<User | null> {\n await this.ensureInitialized();\n return this.db!.data.users.find(u => u.username === username) ?? null;\n }\n\n async getUserById(id: string): Promise<User | null> {\n await this.ensureInitialized();\n return this.db!.data.users.find(u => u.id === id) ?? null;\n }\n\n async getAllUsers(): Promise<User[]> {\n await this.ensureInitialized();\n return [...this.db!.data.users];\n }\n\n async createUser(data: { username: string; passwordHash: string; role: User['role'] }): Promise<User> {\n await this.ensureInitialized();\n const now = new Date().toISOString();\n const user: User = {\n id: `user_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,\n username: data.username,\n passwordHash: data.passwordHash,\n role: data.role,\n createdAt: now,\n updatedAt: now,\n };\n this.db!.data.users.push(user);\n await this.db!.write();\n return user;\n }\n\n async updateUser(id: string, updates: Partial<Pick<User, 'passwordHash' | 'role'>>): Promise<void> {\n await this.ensureInitialized();\n const idx = this.db!.data.users.findIndex(u => u.id === id);\n if (idx !== -1) {\n this.db!.data.users[idx] = {\n ...this.db!.data.users[idx],\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n await this.db!.write();\n }\n }\n\n async deleteUser(id: string): Promise<void> {\n await this.ensureInitialized();\n const idx = this.db!.data.users.findIndex(u => u.id === id);\n if (idx !== -1) {\n this.db!.data.users.splice(idx, 1);\n await this.db!.write();\n }\n }\n\n async close() {\n // LowDB doesn't need explicit closing\n }\n}\n","import { config as dotenvConfig } from 'dotenv';\nimport { OpenQADatabase } from '../../database/index.js';\nimport { validateConfigSafe, type ValidatedOpenQAConfig } from './schema.js';\nimport { logger } from '../logger.js';\n\ndotenvConfig();\n\nexport type OpenQAConfig = ValidatedOpenQAConfig;\n\nexport class ConfigManager {\n private db: OpenQADatabase | null = null;\n private envConfig: OpenQAConfig;\n\n constructor(dbPath?: string) {\n // Don't initialize database in constructor to avoid async issues\n this.envConfig = this.loadFromEnv();\n }\n\n private loadFromEnv(): OpenQAConfig {\n const raw = {\n llm: {\n provider: process.env.LLM_PROVIDER || '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 || '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 || '4242'),\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 const result = validateConfigSafe(raw);\n if (!result.success) {\n logger.warn('Config validation warnings', { errors: result.errors });\n // Return raw config with type assertion — Zod defaults won't apply but app can still start\n return raw as OpenQAConfig;\n }\n return result.data;\n }\n\n private getDB(): OpenQADatabase {\n if (!this.db) {\n this.db = new OpenQADatabase('./data/openqa.json');\n }\n return this.db;\n }\n\n async get(key: string): Promise<string | null> {\n const dbValue = await this.getDB().getConfig(key);\n if (dbValue) return dbValue;\n\n const keys = key.split('.');\n let value: unknown = this.envConfig;\n for (const k of keys) {\n if (value && typeof value === 'object') {\n value = (value as Record<string, unknown>)[k];\n } else {\n return null;\n }\n }\n return value != null ? String(value) : null;\n }\n\n async set(key: string, value: string) {\n await this.getDB().setConfig(key, value);\n }\n\n async getAll(): Promise<OpenQAConfig> {\n const dbConfig = await this.getDB().getAllConfig();\n const merged = { ...this.envConfig };\n\n for (const [key, value] of Object.entries(dbConfig)) {\n const keys = key.split('.');\n let obj: Record<string, unknown> = merged as unknown as Record<string, unknown>;\n for (let i = 0; i < keys.length - 1; i++) {\n if (!obj[keys[i]] || typeof obj[keys[i]] !== 'object') obj[keys[i]] = {};\n obj = obj[keys[i]] as Record<string, unknown>;\n }\n obj[keys[keys.length - 1]] = value;\n }\n\n return merged;\n }\n\n async getConfig(): Promise<OpenQAConfig> {\n return await this.getAll();\n }\n\n // Synchronous version that only uses env vars (no DB)\n getConfigSync(): OpenQAConfig {\n return this.envConfig;\n }\n}\n","import { z } from 'zod';\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai', 'anthropic', 'ollama']).default('openai'),\n apiKey: z.string().optional(),\n model: z.string().optional(),\n baseUrl: z.string().url().optional(),\n});\n\nexport const saasConfigSchema = z.object({\n url: z.string().default(''),\n authType: z.enum(['none', 'basic', 'bearer', 'session']).default('none'),\n username: z.string().optional(),\n password: z.string().optional(),\n});\n\nexport const githubConfigSchema = z.object({\n token: z.string().min(1, 'GITHUB_TOKEN is required when GitHub is configured'),\n owner: z.string().default(''),\n repo: z.string().default(''),\n});\n\nexport const agentConfigSchema = z.object({\n intervalMs: z.number().int().positive().default(3600000),\n maxIterations: z.number().int().positive().default(20),\n autoStart: z.boolean().default(false),\n});\n\nexport const webConfigSchema = z.object({\n port: z.number().int().min(1).max(65535).default(4242),\n host: z.string().default('0.0.0.0'),\n});\n\nexport const databaseConfigSchema = z.object({\n path: z.string().default('./data/openqa.db'),\n});\n\nexport const notificationsConfigSchema = z.object({\n slack: z.string().url().optional(),\n discord: z.string().url().optional(),\n});\n\nexport const openQAConfigSchema = z.object({\n llm: llmConfigSchema,\n saas: saasConfigSchema,\n github: githubConfigSchema.optional(),\n agent: agentConfigSchema,\n web: webConfigSchema,\n database: databaseConfigSchema,\n notifications: notificationsConfigSchema.optional(),\n});\n\nexport type ValidatedOpenQAConfig = z.infer<typeof openQAConfigSchema>;\n\n// SaaS application config (used by brain/SaaSConfigManager)\nexport const saasAppConfigSchema = z.object({\n name: z.string().min(1, 'SaaS application name is required'),\n description: z.string().min(1, 'SaaS application description is required'),\n url: z.string().url('SaaS application URL must be a valid URL'),\n repoUrl: z.string().url().optional(),\n localPath: z.string().optional(),\n techStack: z.array(z.string()).optional(),\n authInfo: z.object({\n type: z.enum(['none', 'basic', 'oauth', 'session']),\n testCredentials: z.object({\n username: z.string(),\n password: z.string(),\n }).optional(),\n }).optional(),\n directives: z.array(z.string()).optional(),\n});\n\nexport type ValidatedSaaSAppConfig = z.infer<typeof saasAppConfigSchema>;\n\nexport function validateSaaSAppConfig(config: unknown): ValidatedSaaSAppConfig {\n return saasAppConfigSchema.parse(config);\n}\n\nexport function validateSaaSAppConfigSafe(config: unknown): { success: true; data: ValidatedSaaSAppConfig } | { success: false; errors: string[] } {\n const result = saasAppConfigSchema.safeParse(config);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return {\n success: false,\n errors: result.error.issues.map(i => `${i.path.join('.')}: ${i.message}`),\n };\n}\n\nexport function validateConfig(config: unknown): ValidatedOpenQAConfig {\n return openQAConfigSchema.parse(config);\n}\n\nexport function validateConfigSafe(config: unknown): { success: true; data: ValidatedOpenQAConfig } | { success: false; errors: string[] } {\n const result = openQAConfigSchema.safeParse(config);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return {\n success: false,\n errors: result.error.issues.map(i => `${i.path.join('.')}: ${i.message}`),\n };\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\nconst MIN_LEVEL: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'info';\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVELS[level] >= LEVELS[MIN_LEVEL];\n}\n\nfunction format(level: LogLevel, message: string, context?: Record<string, unknown>): string {\n const entry: Record<string, unknown> = {\n ts: new Date().toISOString(),\n level,\n msg: message,\n ...context,\n };\n return JSON.stringify(entry);\n}\n\nexport const logger = {\n debug(message: string, context?: Record<string, unknown>) {\n if (shouldLog('debug')) process.stdout.write(format('debug', message, context) + '\\n');\n },\n info(message: string, context?: Record<string, unknown>) {\n if (shouldLog('info')) process.stdout.write(format('info', message, context) + '\\n');\n },\n warn(message: string, context?: Record<string, unknown>) {\n if (shouldLog('warn')) process.stderr.write(format('warn', message, context) + '\\n');\n },\n error(message: string, context?: Record<string, unknown>) {\n if (shouldLog('error')) process.stderr.write(format('error', message, context) + '\\n');\n },\n child(defaults: Record<string, unknown>) {\n return {\n debug: (msg: string, ctx?: Record<string, unknown>) => logger.debug(msg, { ...defaults, ...ctx }),\n info: (msg: string, ctx?: Record<string, unknown>) => logger.info(msg, { ...defaults, ...ctx }),\n warn: (msg: string, ctx?: Record<string, unknown>) => logger.warn(msg, { ...defaults, ...ctx }),\n error: (msg: string, ctx?: Record<string, unknown>) => logger.error(msg, { ...defaults, ...ctx }),\n };\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 { name: 'url', type: 'string' as const, description: 'The URL to navigate to', required: true }\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 { output: `Successfully navigated to ${url}. Page title: \"${title}\"` };\n } catch (error: unknown) {\n return { output: `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'click_element',\n description: 'Click on an element using a CSS selector',\n parameters: [\n { name: 'selector', type: 'string' as const, description: 'CSS selector of the element to click', required: true }\n ],\n execute: async ({ selector }: { selector: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Successfully clicked element: ${selector}` };\n } catch (error: unknown) {\n return { output: `Failed to click element: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'fill_input',\n description: 'Fill an input field with text',\n parameters: [\n { name: 'selector', type: 'string' as const, description: 'CSS selector of the input field', required: true },\n { name: 'text', type: 'string' as const, description: 'Text to fill in the input', required: true }\n ],\n execute: async ({ selector, text }: { selector: string; text: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Successfully filled input ${selector} with text` };\n } catch (error: unknown) {\n return { output: `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'take_screenshot',\n description: 'Take a screenshot of the current page for evidence',\n parameters: [\n { name: 'name', type: 'string' as const, description: 'Name for the screenshot file', required: true }\n ],\n execute: async ({ name }: { name: string }) => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Screenshot saved: ${path}` };\n } catch (error: unknown) {\n return { output: `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'get_page_content',\n description: 'Get the text content of the current page',\n parameters: [],\n execute: async () => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\n \n try {\n const content = await this.page.textContent('body');\n return { output: content?.slice(0, 1000) || 'No content found' };\n } catch (error: unknown) {\n return { output: `Failed to get content: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'check_console_errors',\n description: 'Check for JavaScript console errors on the page',\n parameters: [],\n execute: async () => {\n if (!this.page) return { output: 'Browser not initialized. Navigate to a page first.', error: 'Browser not initialized' };\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 { output: `Found ${errors.length} console errors:\\n${errors.join('\\n')}` };\n }\n return { output: '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 { name: 'title', type: 'string' as const, description: 'Issue title (concise and descriptive)', required: true },\n { name: 'body', type: 'string' as const, description: 'Detailed description with steps to reproduce', required: true },\n { name: 'severity', type: 'string' as const, description: 'Bug severity (low, medium, high, critical)', required: true },\n { name: 'labels', type: 'string' as const, description: 'Comma-separated labels for the issue', required: false },\n { name: 'screenshot_path', type: 'string' as const, description: 'Path to screenshot evidence', required: false }\n ],\n execute: async ({ title, body, severity, labels = [], screenshot_path }: { title: string; body: string; severity: 'low' | 'medium' | 'high' | 'critical'; labels?: string[]; screenshot_path?: string }) => {\n if (!this.octokit || !this.config.owner || !this.config.repo) {\n return { output: 'GitHub not configured. Please set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO.', error: 'GitHub not configured' };\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,\n status: 'open',\n github_issue_url: issue.data.html_url,\n screenshot_path\n });\n\n return { output: `✅ GitHub issue created successfully!\\nURL: ${issue.data.html_url}\\nIssue #${issue.data.number}` };\n } catch (error: unknown) {\n return { output: `❌ Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n }\n ];\n }\n}\n","import { OpenQADatabase, KanbanTicket } 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 { name: 'title', type: 'string' as const, description: 'Ticket title', required: true },\n { name: 'description', type: 'string' as const, description: 'Detailed description', required: true },\n { name: 'priority', type: 'string' as const, description: 'Ticket priority (low, medium, high, critical)', required: true },\n { name: 'column', type: 'string' as const, description: 'Kanban column (backlog, to-do, in-progress, done)', required: false },\n { name: 'tags', type: 'string' as const, description: 'Comma-separated tags for categorization', required: false },\n { name: 'screenshot_path', type: 'string' as const, description: 'Path to screenshot evidence', required: false }\n ],\n execute: async ({ title, description, priority, column = 'to-do', tags = [], screenshot_path }: { title: string; description: string; priority: KanbanTicket['priority']; column?: KanbanTicket['column']; tags?: string[]; screenshot_path?: string }) => {\n try {\n const allTags = ['automated-qa', ...tags];\n\n const ticket = await this.db.createKanbanTicket({\n title,\n description,\n priority,\n column,\n tags: JSON.stringify(allTags),\n screenshot_url: screenshot_path\n });\n\n await 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 { output: `✅ Kanban ticket created successfully!\\nID: ${ticket.id}\\nColumn: ${column}\\nPriority: ${priority}` };\n } catch (error: unknown) {\n return { output: `❌ Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n },\n {\n name: 'update_kanban_ticket',\n description: 'Update an existing Kanban ticket (move columns, change priority, etc.)',\n parameters: [\n { name: 'ticket_id', type: 'string' as const, description: 'ID of the ticket to update', required: true },\n { name: 'column', type: 'string' as const, description: 'New column (backlog, to-do, in-progress, done)', required: false },\n { name: 'priority', type: 'string' as const, description: 'New priority (low, medium, high, critical)', required: false }\n ],\n execute: async ({ ticket_id, column, priority }: { ticket_id: string; column?: KanbanTicket['column']; priority?: KanbanTicket['priority'] }) => {\n try {\n const updates: Partial<KanbanTicket> = {};\n if (column) updates.column = column;\n if (priority) updates.priority = priority;\n\n await this.db.updateKanbanTicket(ticket_id, updates);\n\n return { output: `✅ Kanban ticket ${ticket_id} updated successfully!` };\n } catch (error: unknown) {\n return { output: `❌ Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\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 execute: async () => {\n try {\n const tickets = await 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 { output: summary };\n } catch (error: unknown) {\n return { output: `❌ Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };\n }\n }\n }\n ];\n }\n}\n","import { EventEmitter } from 'events';\nimport { Octokit } from '@octokit/rest';\nimport { logger } from '../logger.js';\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 logger.info('GitListener started', { provider: this.config.provider, owner: this.config.owner, repo: this.config.repo });\n \n await this.checkInitialState();\n \n this.pollInterval = setInterval(() => {\n this.poll().catch((e) => logger.error('Poll error', { error: e instanceof Error ? e.message : String(e) }));\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 logger.info('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 logger.error('Failed to check initial state', { error: error instanceof Error ? error.message : String(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 logger.error('Poll error', { error: error instanceof Error ? error.message : String(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 let changedFiles: string[] | undefined;\n try {\n const { data: detail } = await this.octokit!.repos.getCommit({\n owner: this.config.owner,\n repo: this.config.repo,\n ref: commit.sha,\n });\n changedFiles = (detail.files ?? []).map(f => f.filename);\n } catch { /* non-fatal — changedFiles stays undefined */ }\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 changedFiles,\n };\n\n this.emit('git-event', event);\n \n if (isMerge) {\n this.emit('merge', event);\n logger.info('Merge detected', { branch: this.config.branch, sha: 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 logger.info('Pipeline success', { name: run.name, id: run.id });\n } else {\n this.emit('pipeline-failure', event);\n logger.warn('Pipeline failure', { name: run.name, id: 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 logger.error('GitLab initial state error', { error: error instanceof Error ? error.message : String(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 let changedFiles: string[] | undefined;\n try {\n const diffRes = await fetch(\n `${baseUrl}/api/v4/projects/${projectPath}/repository/commits/${commit.id}/diff`,\n { headers }\n );\n const diffs = await diffRes.json() as Array<{ new_path: string }>;\n changedFiles = diffs.map(d => d.new_path);\n } catch { /* non-fatal */ }\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 changedFiles,\n };\n\n this.emit('git-event', event);\n \n if (isMerge) {\n this.emit('merge', event);\n logger.info('Merge detected', { branch: this.config.branch, id: 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 logger.info('Pipeline success', { id: pipeline.id });\n } else {\n this.emit('pipeline-failure', event);\n logger.warn('Pipeline failure', { id: pipeline.id });\n }\n }\n }\n\n if (pipelines.length > 0) {\n this.lastPipelineId = pipelines[0].id.toString();\n }\n } catch (error) {\n logger.error('GitLab poll error', { error: error instanceof Error ? error.message : String(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 llm = this.createLLMAdapter();\n const agent = new ReActAgent({\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 }, llm);\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: unknown) {\n status.status = 'failed';\n status.completedAt = new Date();\n\n this.emit('agent-failed', { ...status, error: error instanceof Error ? error.message : String(error) });\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 // Load default skills synchronously to avoid async issues\n DEFAULT_SKILLS.forEach(skill => {\n this.createSkill(skill);\n });\n }\n\n private saveSkills() {\n // Skills are stored in memory only for now\n // TODO: Implement async persistence when needed\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","fileURLToPath","__filename","fileURLToPath","__dirname","mkdirSync","join","path","Octokit","Octokit","EventEmitter","EventEmitter","AnthropicAdapter","OpenAIAdapter","ReActAgent"]}