bashbros 0.1.2 → 0.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.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/onboarding.ts","../src/doctor.ts","../src/transparency/agent-config.ts","../src/policy/ward/exposure.ts","../src/policy/ward/patterns.ts","../src/policy/ward/egress.ts","../src/watch.ts","../src/dashboard/writer.ts","../src/allow.ts","../src/dashboard/server.ts"],"sourcesContent":["import { Command } from 'commander'\r\nimport chalk from 'chalk'\r\nimport { runOnboarding } from './onboarding.js'\r\nimport { runDoctor } from './doctor.js'\r\nimport { startWatch } from './watch.js'\r\nimport { handleAllow } from './allow.js'\r\nimport { BashBro } from './bro/bro.js'\r\nimport { ClaudeCodeHooks, gateCommand } from './hooks/claude-code.js'\r\nimport { MoltbotHooks } from './hooks/moltbot.js'\r\nimport { RiskScorer } from './policy/risk-scorer.js'\r\nimport { MetricsCollector } from './observability/metrics.js'\r\nimport {\r\n getAllAgentConfigs,\r\n getAgentConfigInfo,\r\n formatRedactedConfig\r\n} from './transparency/index.js'\r\nimport {\r\n formatAllAgentsInfo,\r\n formatPermissionsTable,\r\n getEffectivePermissions\r\n} from './transparency/display.js'\r\nimport { CostEstimator } from './observability/cost.js'\r\nimport { ReportGenerator } from './observability/report.js'\r\nimport { UndoStack } from './safety/undo-stack.js'\r\nimport { LoopDetector } from './policy/loop-detector.js'\r\nimport { DashboardServer } from './dashboard/index.js'\r\nimport { ExposureScanner, EgressMonitor, EgressPatternMatcher } from './policy/ward/index.js'\r\n\r\n// Shared state for session tracking\r\nlet metricsCollector: MetricsCollector | null = null\r\nlet costEstimator: CostEstimator | null = null\r\nlet loopDetector: LoopDetector | null = null\r\nlet undoStack: UndoStack | null = null\r\n\r\nconst logo = `\r\n ╱BashBros ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n 🤝 Your Friendly Bash Agent Helper\r\n`\r\n\r\nconst program = new Command()\r\n\r\nprogram\r\n .name('bashbros')\r\n .description('The Bash Agent Helper')\r\n .version('0.1.0')\r\n\r\nprogram\r\n .command('init')\r\n .description('Set up BashBros for your project')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n await runOnboarding()\r\n })\r\n\r\nprogram\r\n .command('watch')\r\n .description('Start protecting your agent')\r\n .option('-v, --verbose', 'Show all commands as they run')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n await startWatch(options)\r\n })\r\n\r\nprogram\r\n .command('doctor')\r\n .description('Check your BashBros configuration')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n await runDoctor()\r\n })\r\n\r\nprogram\r\n .command('allow <command>')\r\n .description('Allow a specific command')\r\n .option('--once', 'Allow only for current session')\r\n .option('--persist', 'Add to config permanently')\r\n .action(async (command, options) => {\r\n await handleAllow(command, options)\r\n })\r\n\r\nprogram\r\n .command('audit')\r\n .description('View recent command history')\r\n .option('-n, --lines <number>', 'Number of lines to show', '50')\r\n .option('--violations', 'Show only blocked commands')\r\n .action(async (options) => {\r\n const { viewAudit } = await import('./audit.js')\r\n await viewAudit(options)\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Bash Bro Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('scan')\r\n .description('Scan your system and project environment')\r\n .option('-p, --project <path>', 'Project path to scan', '.')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Scanning your environment...\\n'))\r\n\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (options.project) {\r\n bro.scanProject(options.project)\r\n }\r\n\r\n console.log(bro.getSystemContext())\r\n console.log()\r\n\r\n // Add Agent Configurations section\r\n console.log(chalk.bold('\\n## Agent Configurations\\n'))\r\n const { formatAgentSummary } = await import('./transparency/display.js')\r\n const agents = await getAllAgentConfigs()\r\n console.log(formatAgentSummary(agents))\r\n console.log()\r\n\r\n console.log(chalk.green('✓'), 'System profile saved to ~/.bashbros/system-profile.json')\r\n })\r\n\r\nprogram\r\n .command('status')\r\n .alias('bro')\r\n .description('Show Bash Bro status and system info')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n console.log(bro.status())\r\n })\r\n\r\nprogram\r\n .command('suggest')\r\n .description('Get command suggestions based on context')\r\n .option('-c, --command <cmd>', 'Last command for context')\r\n .option('-e, --error <msg>', 'Last error message')\r\n .action(async (options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n const suggestions = bro.suggest({\r\n lastCommand: options.command,\r\n lastError: options.error,\r\n cwd: process.cwd()\r\n })\r\n\r\n if (suggestions.length === 0) {\r\n console.log(chalk.dim('No suggestions available.'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Bash Bro suggests:\\n'))\r\n for (const s of suggestions) {\r\n const confidence = Math.round(s.confidence * 100)\r\n console.log(` ${chalk.cyan(s.command)}`)\r\n console.log(chalk.dim(` ${s.description} (${confidence}% confidence)`))\r\n console.log()\r\n }\r\n })\r\n\r\nprogram\r\n .command('route <command>')\r\n .description('Check how a command would be routed')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n const result = bro.route(command)\r\n const icon = result.decision === 'bro' ? '🤝' : result.decision === 'main' ? '🤖' : '⚡'\r\n const label = result.decision === 'bro' ? 'Bash Bro' : result.decision === 'main' ? 'Main Agent' : 'Both (parallel)'\r\n\r\n console.log()\r\n console.log(`${icon} Route: ${chalk.bold(label)}`)\r\n console.log(chalk.dim(` Reason: ${result.reason}`))\r\n console.log(chalk.dim(` Confidence: ${Math.round(result.confidence * 100)}%`))\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('run <command>')\r\n .description('Run a command through Bash Bro')\r\n .option('-b, --background', 'Run in background')\r\n .action(async (command, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (options.background) {\r\n const task = bro.runBackground(command)\r\n console.log(chalk.green('✓'), `Started background task: ${task.id}`)\r\n console.log(chalk.dim(` Command: ${command}`))\r\n console.log(chalk.dim(` Run 'bashbros tasks' to check status`))\r\n } else {\r\n console.log(chalk.dim(`🤝 Bash Bro executing: ${command}\\n`))\r\n const output = await bro.execute(command)\r\n console.log(output)\r\n }\r\n })\r\n\r\nprogram\r\n .command('tasks')\r\n .description('List background tasks')\r\n .option('-a, --all', 'Show all tasks (not just running)')\r\n .action(async (options) => {\r\n const bro = new BashBro()\r\n\r\n const tasks = options.all\r\n ? bro.getBackgroundTasks()\r\n : bro.getBackgroundTasks().filter(t => t.status === 'running')\r\n\r\n if (tasks.length === 0) {\r\n console.log(chalk.dim('No background tasks.'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Background Tasks:\\n'))\r\n for (const task of tasks) {\r\n const elapsed = Math.round((Date.now() - task.startTime.getTime()) / 1000)\r\n const statusIcon = task.status === 'running' ? '⏳' :\r\n task.status === 'completed' ? '✓' :\r\n task.status === 'failed' ? '✗' : '○'\r\n\r\n console.log(` ${statusIcon} [${task.id}] ${task.command}`)\r\n console.log(chalk.dim(` Status: ${task.status}, Elapsed: ${elapsed}s`))\r\n console.log()\r\n }\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// AI Commands (requires Ollama)\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('explain <command>')\r\n .description('Ask Bash Bro to explain a command')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is thinking...\\n'))\r\n const explanation = await bro.aiExplain(command)\r\n console.log(explanation)\r\n })\r\n\r\nprogram\r\n .command('fix <command>')\r\n .description('Ask Bash Bro to fix a failed command')\r\n .option('-e, --error <message>', 'Error message from the failed command')\r\n .action(async (command, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n const error = options.error || 'Command failed'\r\n console.log(chalk.dim('🤝 Bash Bro is analyzing...\\n'))\r\n\r\n const fixed = await bro.aiFix(command, error)\r\n\r\n if (fixed) {\r\n console.log(chalk.green('Suggested fix:'))\r\n console.log(chalk.cyan(` ${fixed}`))\r\n } else {\r\n console.log(chalk.yellow('Could not suggest a fix.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('ai <prompt>')\r\n .description('Ask Bash Bro anything')\r\n .action(async (prompt) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is thinking...\\n'))\r\n const suggestion = await bro.aiSuggest(prompt)\r\n\r\n if (suggestion) {\r\n console.log(chalk.cyan(suggestion))\r\n } else {\r\n console.log(chalk.dim('No suggestion available.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('script <description>')\r\n .description('Generate a shell script from description')\r\n .option('-o, --output <file>', 'Save script to file')\r\n .action(async (description, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is generating script...\\n'))\r\n const script = await bro.aiGenerateScript(description)\r\n\r\n if (script) {\r\n console.log(chalk.cyan(script))\r\n\r\n if (options.output) {\r\n const { writeFileSync } = await import('fs')\r\n writeFileSync(options.output, script, { mode: 0o755 })\r\n console.log(chalk.green(`\\n✓ Saved to ${options.output}`))\r\n }\r\n } else {\r\n console.log(chalk.yellow('Could not generate script.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('safety <command>')\r\n .description('Analyze a command for security risks')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is analyzing...\\n'))\r\n const analysis = await bro.aiAnalyzeSafety(command)\r\n\r\n const riskColors = {\r\n low: chalk.green,\r\n medium: chalk.yellow,\r\n high: chalk.red,\r\n critical: chalk.bgRed.white\r\n }\r\n\r\n const icon = analysis.safe ? '✓' : '⚠'\r\n const color = riskColors[analysis.risk]\r\n\r\n console.log(`${icon} Risk Level: ${color(analysis.risk.toUpperCase())}`)\r\n console.log()\r\n console.log(chalk.bold('Explanation:'))\r\n console.log(` ${analysis.explanation}`)\r\n\r\n if (analysis.suggestions.length > 0) {\r\n console.log()\r\n console.log(chalk.bold('Suggestions:'))\r\n for (const suggestion of analysis.suggestions) {\r\n console.log(` • ${suggestion}`)\r\n }\r\n }\r\n })\r\n\r\nprogram\r\n .command('help-ai <topic>')\r\n .alias('h')\r\n .description('Get AI help for a command or topic')\r\n .action(async (topic) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is looking that up...\\n'))\r\n const help = await bro.aiHelp(topic)\r\n console.log(help)\r\n })\r\n\r\nprogram\r\n .command('do <description>')\r\n .description('Convert natural language to a command')\r\n .option('-x, --execute', 'Execute the command after showing it')\r\n .action(async (description, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is translating...\\n'))\r\n const command = await bro.aiToCommand(description)\r\n\r\n if (command) {\r\n console.log(chalk.bold('Command:'))\r\n console.log(chalk.cyan(` $ ${command}`))\r\n\r\n if (options.execute) {\r\n console.log()\r\n console.log(chalk.dim('Executing...'))\r\n const output = await bro.execute(command)\r\n console.log(output)\r\n }\r\n } else {\r\n console.log(chalk.yellow('Could not translate to a command.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('models')\r\n .description('List available Ollama models')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const { OllamaClient } = await import('./bro/ollama.js')\r\n const ollama = new OllamaClient()\r\n\r\n const available = await ollama.isAvailable()\r\n if (!available) {\r\n console.log(chalk.yellow('Ollama not running. Start Ollama to see available models.'))\r\n return\r\n }\r\n\r\n const models = await ollama.listModels()\r\n\r\n if (models.length === 0) {\r\n console.log(chalk.dim('No models installed. Run: ollama pull qwen2.5-coder:7b'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Available Models:\\n'))\r\n for (const model of models) {\r\n const current = model === ollama.getModel() ? chalk.green(' (current)') : ''\r\n console.log(` • ${model}${current}`)\r\n }\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Hook & Observability Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst hookCmd = program\r\n .command('hook')\r\n .description('Manage Claude Code hook integration')\r\n\r\nhookCmd\r\n .command('install')\r\n .description('Install BashBros hooks into Claude Code')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.install()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nhookCmd\r\n .command('uninstall')\r\n .description('Remove BashBros hooks from Claude Code')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.uninstall()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nhookCmd\r\n .command('status')\r\n .description('Check Claude Code hook status')\r\n .action(() => {\r\n const status = ClaudeCodeHooks.getStatus()\r\n console.log()\r\n console.log(chalk.bold('Claude Code Integration Status'))\r\n console.log()\r\n console.log(` Claude Code: ${status.claudeInstalled ? chalk.green('installed') : chalk.yellow('not found')}`)\r\n console.log(` BashBros hooks: ${status.hooksInstalled ? chalk.green('active') : chalk.dim('not installed')}`)\r\n if (status.hooks.length > 0) {\r\n console.log(` Active hooks: ${status.hooks.join(', ')}`)\r\n }\r\n console.log()\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Moltbot Integration Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst moltbotCmd = program\r\n .command('moltbot')\r\n .alias('clawdbot')\r\n .description('Manage Moltbot/Clawdbot integration')\r\n\r\nmoltbotCmd\r\n .command('install')\r\n .description('Install BashBros hooks into Moltbot')\r\n .action(() => {\r\n const result = MoltbotHooks.install()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nmoltbotCmd\r\n .command('uninstall')\r\n .description('Remove BashBros hooks from Moltbot')\r\n .action(() => {\r\n const result = MoltbotHooks.uninstall()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nmoltbotCmd\r\n .command('status')\r\n .description('Check Moltbot integration status')\r\n .action(async () => {\r\n const status = MoltbotHooks.getStatus()\r\n console.log()\r\n console.log(chalk.bold('Moltbot Integration Status'))\r\n console.log()\r\n\r\n // Installation status\r\n if (status.moltbotInstalled) {\r\n console.log(` Moltbot: ${chalk.green('installed')}`)\r\n } else if (status.clawdbotInstalled) {\r\n console.log(` Clawdbot: ${chalk.green('installed')} ${chalk.dim('(legacy)')}`)\r\n } else {\r\n console.log(` Moltbot: ${chalk.yellow('not found')}`)\r\n }\r\n\r\n // Config status\r\n if (status.configPath) {\r\n console.log(` Config: ${chalk.green(status.configPath)}`)\r\n } else {\r\n console.log(` Config: ${chalk.dim('not found')}`)\r\n }\r\n\r\n // Hooks status\r\n console.log(` BashBros hooks: ${status.hooksInstalled ? chalk.green('active') : chalk.dim('not installed')}`)\r\n if (status.hooks.length > 0) {\r\n console.log(` Active hooks: ${status.hooks.join(', ')}`)\r\n }\r\n\r\n // Sandbox mode\r\n if (status.sandboxMode) {\r\n const sandboxColor = status.sandboxMode === 'strict' ? chalk.green : chalk.yellow\r\n console.log(` Sandbox mode: ${sandboxColor(status.sandboxMode)}`)\r\n }\r\n\r\n console.log()\r\n })\r\n\r\nmoltbotCmd\r\n .command('gateway')\r\n .description('Check Moltbot gateway status')\r\n .action(async () => {\r\n console.log()\r\n console.log(chalk.bold('Moltbot Gateway Status'))\r\n console.log()\r\n\r\n const gatewayStatus = await MoltbotHooks.getGatewayStatus()\r\n\r\n if (gatewayStatus.running) {\r\n console.log(` Status: ${chalk.green('running')}`)\r\n console.log(` Host: ${gatewayStatus.host}`)\r\n console.log(` Port: ${gatewayStatus.port}`)\r\n console.log(` Sandbox: ${gatewayStatus.sandboxMode ? chalk.green('enabled') : chalk.yellow('disabled')}`)\r\n } else {\r\n console.log(` Status: ${chalk.yellow('not running')}`)\r\n console.log(` Expected: ${gatewayStatus.host}:${gatewayStatus.port}`)\r\n if (gatewayStatus.error) {\r\n console.log(` Error: ${chalk.dim(gatewayStatus.error)}`)\r\n }\r\n }\r\n\r\n console.log()\r\n })\r\n\r\nmoltbotCmd\r\n .command('audit')\r\n .description('Run Moltbot security audit')\r\n .option('--json', 'Output as JSON')\r\n .action(async (options) => {\r\n console.log(chalk.dim('Running security audit...\\n'))\r\n\r\n const result = await MoltbotHooks.runSecurityAudit()\r\n\r\n if (options.json) {\r\n console.log(JSON.stringify(result, null, 2))\r\n return\r\n }\r\n\r\n // Display results\r\n const statusIcon = result.passed ? chalk.green('✓') : chalk.red('✗')\r\n const statusText = result.passed ? chalk.green('PASSED') : chalk.red('FAILED')\r\n\r\n console.log(`${statusIcon} Security Audit: ${statusText}`)\r\n console.log()\r\n\r\n if (result.findings.length === 0) {\r\n console.log(chalk.dim(' No findings.'))\r\n } else {\r\n const severityColors: Record<string, (s: string) => string> = {\r\n critical: chalk.bgRed.white,\r\n warning: chalk.yellow,\r\n info: chalk.dim\r\n }\r\n\r\n for (const finding of result.findings) {\r\n const color = severityColors[finding.severity] || chalk.white\r\n console.log(` ${color(`[${finding.severity.toUpperCase()}]`)} ${finding.message}`)\r\n console.log(chalk.dim(` Category: ${finding.category}`))\r\n if (finding.recommendation) {\r\n console.log(chalk.dim(` Fix: ${finding.recommendation}`))\r\n }\r\n console.log()\r\n }\r\n }\r\n\r\n console.log(chalk.dim(`Audit completed at ${result.timestamp.toLocaleString()}`))\r\n console.log()\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Agent Transparency Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('agent-info [agent]')\r\n .description('Show detailed info about installed agents and their configurations')\r\n .option('-r, --raw', 'Show raw (redacted) config contents')\r\n .action(async (agent, options) => {\r\n console.log(chalk.cyan(logo))\r\n\r\n if (agent) {\r\n // Show specific agent\r\n const validAgents = ['claude-code', 'moltbot', 'clawdbot', 'aider', 'gemini-cli', 'opencode']\r\n if (!validAgents.includes(agent)) {\r\n console.log(chalk.red(`Unknown agent: ${agent}`))\r\n console.log(chalk.dim(`Valid agents: ${validAgents.join(', ')}`))\r\n return\r\n }\r\n\r\n const info = await getAgentConfigInfo(agent as any)\r\n const { formatAgentInfo } = await import('./transparency/display.js')\r\n console.log()\r\n console.log(formatAgentInfo(info))\r\n\r\n // Show raw config if requested\r\n if (options.raw && info.configExists && info.configPath) {\r\n const { parseAgentConfig } = await import('./transparency/config-parser.js')\r\n const parsed = await parseAgentConfig(agent as any, info.configPath)\r\n if (parsed?.rawRedacted) {\r\n console.log()\r\n console.log(chalk.bold('Configuration (sensitive data redacted):'))\r\n console.log(formatRedactedConfig(parsed.rawRedacted))\r\n }\r\n }\r\n } else {\r\n // Show all agents\r\n const agents = await getAllAgentConfigs()\r\n console.log()\r\n console.log(formatAllAgentsInfo(agents))\r\n }\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('permissions')\r\n .description('Show combined permissions view across bashbros and agents')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const agents = await getAllAgentConfigs()\r\n const installed = agents.filter(a => a.installed)\r\n\r\n if (installed.length === 0) {\r\n console.log(chalk.yellow('No agents installed to compare permissions with.'))\r\n console.log(chalk.dim('Install an agent (claude, aider, etc.) to see combined permissions.'))\r\n return\r\n }\r\n\r\n console.log()\r\n console.log(formatPermissionsTable(agents))\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('gate <command>')\r\n .description('Check if a command should be allowed (used by hooks)')\r\n .option('-y, --yes', 'Skip interactive prompt and block')\r\n .action(async (command, options) => {\r\n const result = await gateCommand(command)\r\n\r\n if (!result.allowed) {\r\n // If stdin is a TTY and not skipping prompt, ask user\r\n if (process.stdin.isTTY && !options.yes) {\r\n const { allowForSession } = await import('./session.js')\r\n const { readFileSync, writeFileSync } = await import('fs')\r\n const { parse, stringify } = await import('yaml')\r\n const { findConfig } = await import('./config.js')\r\n\r\n console.error()\r\n console.error(chalk.red('🛡️ BashBros blocked a command'))\r\n console.error()\r\n console.error(chalk.dim(' Command:'), command)\r\n console.error(chalk.dim(' Reason:'), result.reason)\r\n console.error()\r\n console.error(chalk.yellow(' Allow this command?'))\r\n console.error(chalk.cyan(' [y]'), 'Allow once')\r\n console.error(chalk.cyan(' [s]'), 'Allow for session')\r\n console.error(chalk.cyan(' [p]'), 'Allow permanently')\r\n console.error(chalk.cyan(' [n]'), 'Block (default)')\r\n process.stderr.write(chalk.dim('\\n Choice: '))\r\n\r\n // Read single character from stdin\r\n const choice = await new Promise<string>((resolve) => {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(true)\r\n }\r\n process.stdin.resume()\r\n process.stdin.once('data', (data) => {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(false)\r\n }\r\n const char = data.toString().toLowerCase()\r\n console.error(char)\r\n resolve(char)\r\n })\r\n })\r\n\r\n switch (choice) {\r\n case 'y':\r\n console.error(chalk.green(' ✓ Allowed once'))\r\n process.exit(0)\r\n break\r\n\r\n case 's':\r\n allowForSession(command)\r\n console.error(chalk.green(' ✓ Allowed for session'))\r\n process.exit(0)\r\n break\r\n\r\n case 'p':\r\n try {\r\n const configPath = findConfig()\r\n if (configPath) {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n if (!config.commands) config.commands = { allow: [], block: [] }\r\n if (!config.commands.allow) config.commands.allow = []\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n }\r\n console.error(chalk.green(' ✓ Added to allowlist permanently'))\r\n process.exit(0)\r\n }\r\n } catch {\r\n console.error(chalk.red(' ✗ Failed to update config'))\r\n }\r\n process.exit(2)\r\n break\r\n\r\n default:\r\n console.error(chalk.yellow(' ✗ Blocked'))\r\n process.exit(2)\r\n }\r\n } else {\r\n // Clean, minimal output for non-interactive use (hooks)\r\n console.error(`Blocked: ${result.reason}`)\r\n process.exit(2)\r\n }\r\n }\r\n\r\n // Silently allow\r\n process.exit(0)\r\n })\r\n\r\nprogram\r\n .command('record <command>')\r\n .description('Record a command execution (used by hooks)')\r\n .option('-o, --output <output>', 'Command output')\r\n .option('-e, --exit-code <code>', 'Exit code', '0')\r\n .action(async (command, options) => {\r\n // Initialize collectors if needed\r\n if (!metricsCollector) metricsCollector = new MetricsCollector()\r\n if (!costEstimator) costEstimator = new CostEstimator()\r\n if (!loopDetector) loopDetector = new LoopDetector()\r\n if (!undoStack) undoStack = new UndoStack()\r\n\r\n const scorer = new RiskScorer()\r\n const risk = scorer.score(command)\r\n\r\n // Record metrics\r\n metricsCollector.record({\r\n command,\r\n timestamp: new Date(),\r\n duration: 0, // Not available in hook\r\n allowed: true,\r\n riskScore: risk,\r\n violations: [],\r\n exitCode: parseInt(options.exitCode) || 0\r\n })\r\n\r\n // Record for cost estimation\r\n costEstimator.recordToolCall(command, options.output || '')\r\n\r\n // Check for loops\r\n const loopAlert = loopDetector.check(command)\r\n if (loopAlert) {\r\n console.error(chalk.yellow(`⚠ Loop detected: ${loopAlert.message}`))\r\n }\r\n\r\n // Track file changes for undo\r\n const paths = command.match(/(?:^|\\s)(\\.\\/|\\.\\.\\/|\\/|~\\/)[^\\s]+/g) || []\r\n const cleanPaths = paths.map((p: string) => p.trim())\r\n if (cleanPaths.length > 0) {\r\n undoStack.recordFromCommand(command, cleanPaths)\r\n }\r\n })\r\n\r\nprogram\r\n .command('session-end')\r\n .description('Generate session report (used by hooks)')\r\n .option('-f, --format <format>', 'Output format (text, markdown, json)', 'text')\r\n .action((options) => {\r\n if (!metricsCollector) {\r\n console.log(chalk.dim('No session data to report.'))\r\n return\r\n }\r\n\r\n const metrics = metricsCollector.getMetrics()\r\n const cost = costEstimator?.getEstimate()\r\n const report = ReportGenerator.generate(metrics, cost, { format: options.format })\r\n\r\n console.log()\r\n console.log(report)\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('report')\r\n .description('Generate a session report')\r\n .option('-f, --format <format>', 'Output format (text, markdown, json)', 'text')\r\n .option('--no-cost', 'Hide cost estimate')\r\n .option('--no-risk', 'Hide risk distribution')\r\n .action((options) => {\r\n if (!metricsCollector) {\r\n console.log(chalk.dim('No session data. Run some commands first.'))\r\n return\r\n }\r\n\r\n const metrics = metricsCollector.getMetrics()\r\n const cost = options.cost ? costEstimator?.getEstimate() : undefined\r\n const report = ReportGenerator.generate(metrics, cost, {\r\n format: options.format,\r\n showCost: options.cost,\r\n showRisk: options.risk\r\n })\r\n\r\n console.log()\r\n console.log(report)\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('risk <command>')\r\n .description('Score a command for security risk')\r\n .action((command) => {\r\n const scorer = new RiskScorer()\r\n const result = scorer.score(command)\r\n\r\n const colors: Record<string, (s: string) => string> = {\r\n safe: chalk.green,\r\n caution: chalk.yellow,\r\n dangerous: chalk.red,\r\n critical: chalk.bgRed.white\r\n }\r\n\r\n const color = colors[result.level]\r\n\r\n console.log()\r\n console.log(` Risk Score: ${color(`${result.score}/10`)} (${color(result.level.toUpperCase())})`)\r\n console.log()\r\n console.log(chalk.bold(' Factors:'))\r\n for (const factor of result.factors) {\r\n console.log(` • ${factor}`)\r\n }\r\n console.log()\r\n })\r\n\r\nconst undoCmd = program\r\n .command('undo')\r\n .description('Undo file operations')\r\n\r\nundoCmd\r\n .command('last')\r\n .alias('pop')\r\n .description('Undo the last file operation')\r\n .action(() => {\r\n if (!undoStack) {\r\n console.log(chalk.dim('No operations to undo.'))\r\n return\r\n }\r\n\r\n const result = undoStack.undo()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n }\r\n })\r\n\r\nundoCmd\r\n .command('all')\r\n .description('Undo all file operations in session')\r\n .action(() => {\r\n if (!undoStack || undoStack.size() === 0) {\r\n console.log(chalk.dim('No operations to undo.'))\r\n return\r\n }\r\n\r\n const results = undoStack.undoAll()\r\n let success = 0, failed = 0\r\n\r\n for (const result of results) {\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n success++\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n failed++\r\n }\r\n }\r\n\r\n console.log()\r\n console.log(`Undone: ${success} successful, ${failed} failed`)\r\n })\r\n\r\nundoCmd\r\n .command('list')\r\n .description('Show undo stack')\r\n .action(() => {\r\n if (!undoStack) {\r\n undoStack = new UndoStack()\r\n }\r\n\r\n console.log()\r\n console.log(undoStack.formatStack())\r\n console.log()\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Dashboard Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nlet dashboardServer: DashboardServer | null = null\r\n\r\nprogram\r\n .command('dashboard')\r\n .description('Start the BashBros dashboard')\r\n .option('-p, --port <port>', 'Port to run on', '7890')\r\n .option('-b, --bind <address>', 'Address to bind to', '127.0.0.1')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Starting dashboard...\\n'))\r\n\r\n dashboardServer = new DashboardServer({\r\n port: parseInt(options.port),\r\n bind: options.bind\r\n })\r\n\r\n await dashboardServer.start()\r\n console.log(chalk.green('✓'), `Dashboard running at http://${options.bind}:${options.port}`)\r\n console.log(chalk.dim(' Press Ctrl+C to stop'))\r\n\r\n // Keep process alive\r\n process.on('SIGINT', async () => {\r\n console.log(chalk.dim('\\n Stopping dashboard...'))\r\n await dashboardServer?.stop()\r\n process.exit(0)\r\n })\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Ward Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst wardCmd = program\r\n .command('ward')\r\n .description('Network and connector security')\r\n\r\nwardCmd\r\n .command('status')\r\n .description('Show ward security status')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.bold('Ward Security Status\\n'))\r\n\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green('✓'), 'No exposed agent servers detected')\r\n } else {\r\n console.log(chalk.yellow('⚠'), `Found ${results.length} exposure(s):\\n`)\r\n for (const r of results) {\r\n const color = r.severity === 'critical' ? chalk.bgRed.white :\r\n r.severity === 'high' ? chalk.red :\r\n r.severity === 'medium' ? chalk.yellow :\r\n chalk.dim\r\n console.log(` ${color(r.severity.toUpperCase().padEnd(8))} ${r.message}`)\r\n }\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('scan')\r\n .description('Run exposure scan')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Scanning for exposed agent servers...\\n'))\r\n\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green('✓'), 'No exposed agent servers detected')\r\n } else {\r\n for (const r of results) {\r\n const icon = r.severity === 'critical' ? '🚨' :\r\n r.severity === 'high' ? '⚠️' :\r\n r.severity === 'medium' ? '⚡' : 'ℹ️'\r\n\r\n console.log(`${icon} ${r.agent}`)\r\n console.log(chalk.dim(` Port: ${r.port}`))\r\n console.log(chalk.dim(` Bind: ${r.bindAddress}`))\r\n console.log(chalk.dim(` Auth: ${r.hasAuth}`))\r\n console.log(chalk.dim(` Severity: ${r.severity}`))\r\n console.log(chalk.dim(` Action: ${r.action}`))\r\n console.log()\r\n }\r\n }\r\n })\r\n\r\nconst exposureCmd = wardCmd\r\n .command('exposure')\r\n .description('Exposure scanner commands')\r\n\r\nexposureCmd\r\n .command('list')\r\n .description('List monitored agents')\r\n .action(() => {\r\n const scanner = new ExposureScanner()\r\n const agents = scanner.getAgents()\r\n\r\n console.log(chalk.bold('\\nMonitored Agent Signatures:\\n'))\r\n for (const agent of agents) {\r\n console.log(` ${chalk.cyan(agent.name)}`)\r\n console.log(chalk.dim(` Processes: ${agent.processNames.join(', ')}`))\r\n console.log(chalk.dim(` Ports: ${agent.defaultPorts.join(', ')}`))\r\n console.log()\r\n }\r\n })\r\n\r\nexposureCmd\r\n .command('scan')\r\n .description('Run immediate exposure scan')\r\n .action(async () => {\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n console.log(chalk.bold('\\nExposure Scan Results:\\n'))\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green(' ✓ No exposures detected'))\r\n } else {\r\n for (const r of results) {\r\n const color = r.severity === 'critical' ? chalk.bgRed.white :\r\n r.severity === 'high' ? chalk.red :\r\n r.severity === 'medium' ? chalk.yellow : chalk.green\r\n console.log(` ${color(r.severity.toUpperCase().padEnd(10))} ${r.message}`)\r\n }\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('blocked')\r\n .description('Show pending blocked egress items')\r\n .action(() => {\r\n const monitor = new EgressMonitor()\r\n const pending = monitor.getPendingBlocks()\r\n\r\n console.log(chalk.bold('\\nPending Egress Blocks:\\n'))\r\n\r\n if (pending.length === 0) {\r\n console.log(chalk.dim(' No pending blocks'))\r\n } else {\r\n for (const block of pending) {\r\n const severityColor = block.pattern.severity === 'critical' ? chalk.bgRed.white :\r\n block.pattern.severity === 'high' ? chalk.red :\r\n block.pattern.severity === 'medium' ? chalk.yellow : chalk.dim\r\n console.log(` ${chalk.cyan(block.id)} ${severityColor(block.pattern.severity.toUpperCase())}`)\r\n console.log(chalk.dim(` Pattern: ${block.pattern.name} (${block.pattern.category})`))\r\n console.log(chalk.dim(` Matched: ${block.matchedText.substring(0, 50)}${block.matchedText.length > 50 ? '...' : ''}`))\r\n if (block.connector) console.log(chalk.dim(` Connector: ${block.connector}`))\r\n if (block.destination) console.log(chalk.dim(` Destination: ${block.destination}`))\r\n console.log()\r\n }\r\n console.log(chalk.dim(` Use 'bashbros ward approve <id>' or 'bashbros ward deny <id>' to resolve`))\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('approve <id>')\r\n .description('Approve a blocked egress item')\r\n .option('--by <name>', 'Name of approver', 'user')\r\n .action((id, options) => {\r\n const monitor = new EgressMonitor()\r\n monitor.approveBlock(id, options.by)\r\n console.log(chalk.green('✓'), `Approved block ${id}`)\r\n })\r\n\r\nwardCmd\r\n .command('deny <id>')\r\n .description('Deny a blocked egress item')\r\n .action((id) => {\r\n const monitor = new EgressMonitor()\r\n monitor.denyBlock(id)\r\n console.log(chalk.green('✓'), `Denied block ${id}`)\r\n })\r\n\r\nconst patternsCmd = wardCmd\r\n .command('patterns')\r\n .description('Egress pattern detection commands')\r\n\r\npatternsCmd\r\n .command('list')\r\n .description('List active detection patterns')\r\n .option('--category <cat>', 'Filter by category (credentials, pii)')\r\n .action((options) => {\r\n const matcher = new EgressPatternMatcher()\r\n let patterns = matcher.getPatterns()\r\n\r\n if (options.category) {\r\n patterns = patterns.filter(p => p.category === options.category)\r\n }\r\n\r\n console.log(chalk.bold('\\nActive Egress Patterns:\\n'))\r\n\r\n const byCategory: Record<string, typeof patterns> = {}\r\n for (const p of patterns) {\r\n const cat = p.category\r\n if (!byCategory[cat]) byCategory[cat] = []\r\n byCategory[cat].push(p)\r\n }\r\n\r\n for (const [category, categoryPatterns] of Object.entries(byCategory)) {\r\n console.log(chalk.cyan(` ${category.toUpperCase()}`))\r\n for (const p of categoryPatterns) {\r\n const severityColor = p.severity === 'critical' ? chalk.red :\r\n p.severity === 'high' ? chalk.yellow :\r\n p.severity === 'medium' ? chalk.blue : chalk.dim\r\n const actionColor = p.action === 'block' ? chalk.red :\r\n p.action === 'alert' ? chalk.yellow : chalk.dim\r\n console.log(` ${chalk.bold(p.name.padEnd(16))} ${severityColor(p.severity.padEnd(10))} ${actionColor(p.action.padEnd(6))} ${p.description}`)\r\n }\r\n console.log()\r\n }\r\n })\r\n\r\npatternsCmd\r\n .command('test <text>')\r\n .description('Test if text matches any detection pattern')\r\n .action((text) => {\r\n const monitor = new EgressMonitor()\r\n const result = monitor.test(text)\r\n\r\n console.log(chalk.bold('\\nPattern Test Results:\\n'))\r\n\r\n if (result.matches.length === 0) {\r\n console.log(chalk.green(' ✓ No patterns matched'))\r\n } else {\r\n console.log(` ${result.blocked ? chalk.red('WOULD BLOCK') : chalk.yellow('WOULD ALERT')}`)\r\n console.log()\r\n console.log(chalk.bold(' Matches:'))\r\n for (const m of result.matches) {\r\n const severityColor = m.pattern.severity === 'critical' ? chalk.red :\r\n m.pattern.severity === 'high' ? chalk.yellow :\r\n m.pattern.severity === 'medium' ? chalk.blue : chalk.dim\r\n console.log(` ${chalk.cyan(m.pattern.name)} ${severityColor(`[${m.pattern.severity}]`)} - \"${m.matchedText.substring(0, 30)}${m.matchedText.length > 30 ? '...' : ''}\"`)\r\n }\r\n console.log()\r\n console.log(chalk.bold(' Redacted output:'))\r\n console.log(chalk.dim(` ${result.redacted.substring(0, 100)}${result.redacted.length > 100 ? '...' : ''}`))\r\n }\r\n console.log()\r\n })\r\n\r\nprogram.parse()\r\n","import inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { writeFileSync, existsSync, mkdirSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { stringify } from 'yaml'\r\nimport type { BashBrosConfig, AgentType, SecurityProfile } from './types.js'\r\nimport { getDefaultConfig } from './config.js'\r\nimport { getBashgymIntegration } from './integration/bashgym.js'\r\n\r\nexport async function runOnboarding(): Promise<void> {\r\n console.log(chalk.dim(' \"I watch your agent\\'s back so you don\\'t have to.\"\\n'))\r\n\r\n // Check if bashgym integration is available\r\n const bashgymAvailable = existsSync(join(homedir(), '.bashgym', 'integration'))\r\n\r\n const questions: any[] = [\r\n {\r\n type: 'list',\r\n name: 'agent',\r\n message: 'What agent are you protecting?',\r\n choices: [\r\n { name: 'Claude Code', value: 'claude-code' },\r\n { name: 'Moltbot (clawd.bot)', value: 'moltbot' },\r\n { name: 'Clawdbot (legacy)', value: 'clawdbot' },\r\n { name: 'Gemini CLI', value: 'gemini-cli' },\r\n { name: 'Aider', value: 'aider' },\r\n { name: 'OpenCode', value: 'opencode' },\r\n { name: 'Other (custom)', value: 'custom' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'projectType',\r\n message: \"What's this project about? (helps tune defaults)\",\r\n choices: [\r\n { name: 'Web development', value: 'web' },\r\n { name: 'DevOps / Infrastructure', value: 'devops' },\r\n { name: 'Data engineering', value: 'data' },\r\n { name: 'General coding', value: 'general' },\r\n { name: 'Sensitive/regulated work', value: 'sensitive' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'profile',\r\n message: 'Security posture:',\r\n choices: [\r\n {\r\n name: 'Balanced (recommended) - Block dangerous, allow common dev tools',\r\n value: 'balanced'\r\n },\r\n {\r\n name: 'Strict - Allowlist only, explicit approval for new commands',\r\n value: 'strict'\r\n },\r\n {\r\n name: 'Permissive - Log everything, block only critical threats',\r\n value: 'permissive'\r\n },\r\n {\r\n name: \"Custom - I'll configure manually\",\r\n value: 'custom'\r\n }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'secrets',\r\n message: 'Protect secrets? (scans for .env, credentials, SSH keys)',\r\n choices: [\r\n { name: 'Yes, block access and warn (recommended)', value: 'block' },\r\n { name: 'Yes, but allow read with audit log', value: 'audit' },\r\n { name: 'No', value: 'disabled' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'audit',\r\n message: 'Enable audit logging?',\r\n choices: [\r\n { name: 'Local file (~/.bashbros/audit.log)', value: 'local' },\r\n { name: 'Send to remote (Datadog, Splunk, webhook)', value: 'remote' },\r\n { name: 'Both', value: 'both' },\r\n { name: 'None', value: 'disabled' }\r\n ]\r\n }\r\n ]\r\n\r\n // Add bashgym integration question if available\r\n if (bashgymAvailable) {\r\n questions.push({\r\n type: 'list',\r\n name: 'bashgym',\r\n message: 'Link to BashGym? (enables self-improving AI sidekick)',\r\n choices: [\r\n {\r\n name: 'Yes (recommended) - Export traces for training, get smarter sidekick',\r\n value: 'link'\r\n },\r\n {\r\n name: 'No - Use bashbros standalone',\r\n value: 'skip'\r\n }\r\n ]\r\n })\r\n }\r\n\r\n const answers = await inquirer.prompt(questions)\r\n\r\n // Build config\r\n const config = buildConfig(answers)\r\n\r\n // Write config file\r\n const configYaml = stringify(config)\r\n writeFileSync('.bashbros.yml', configYaml)\r\n\r\n console.log()\r\n console.log(chalk.green('✓'), 'Config written to', chalk.cyan('.bashbros.yml'))\r\n console.log(chalk.green('✓'), 'PTY wrapper ready')\r\n console.log(chalk.green('✓'), 'Audit logging', answers.audit !== 'disabled' ? 'enabled' : 'disabled')\r\n\r\n // Handle bashgym integration\r\n if (answers.bashgym === 'link') {\r\n const linked = await linkBashgym()\r\n if (linked) {\r\n console.log(chalk.green('✓'), 'BashGym integration', chalk.cyan('linked'))\r\n console.log(chalk.dim(' Traces will be exported for training'))\r\n console.log(chalk.dim(' AI sidekick will improve over time'))\r\n } else {\r\n console.log(chalk.yellow('⚠'), 'BashGym integration', chalk.dim('not linked (bashgym not running?)'))\r\n }\r\n } else if (bashgymAvailable) {\r\n console.log(chalk.dim('○'), 'BashGym integration', chalk.dim('skipped'))\r\n }\r\n\r\n console.log()\r\n console.log(chalk.dim(\"Run\"), chalk.cyan(\"'bashbros doctor'\"), chalk.dim(\"to verify setup\"))\r\n console.log(chalk.dim(\"Run\"), chalk.cyan(\"'bashbros watch'\"), chalk.dim(\"to start protection\"))\r\n console.log()\r\n}\r\n\r\n/**\r\n * Link bashbros to bashgym integration\r\n */\r\nasync function linkBashgym(): Promise<boolean> {\r\n try {\r\n const integration = getBashgymIntegration()\r\n\r\n // Check if bashgym directory exists\r\n if (!integration.isAvailable()) {\r\n // Create the integration directory structure\r\n const integrationDir = join(homedir(), '.bashgym', 'integration')\r\n const dirs = [\r\n join(integrationDir, 'traces', 'pending'),\r\n join(integrationDir, 'traces', 'processed'),\r\n join(integrationDir, 'traces', 'failed'),\r\n join(integrationDir, 'models', 'latest'),\r\n join(integrationDir, 'config'),\r\n join(integrationDir, 'status'),\r\n ]\r\n\r\n for (const dir of dirs) {\r\n mkdirSync(dir, { recursive: true })\r\n }\r\n\r\n // Create initial settings file\r\n const settingsPath = join(integrationDir, 'config', 'settings.json')\r\n const settings = {\r\n version: '1.0',\r\n updated_at: new Date().toISOString(),\r\n updated_by: 'bashbros',\r\n integration: {\r\n enabled: true,\r\n linked_at: new Date().toISOString(),\r\n },\r\n capture: {\r\n mode: 'successful_only',\r\n auto_stream: true,\r\n },\r\n training: {\r\n auto_enabled: false,\r\n quality_threshold: 50,\r\n trigger: 'quality_based',\r\n },\r\n security: {\r\n bashbros_primary: true,\r\n policy_path: null,\r\n },\r\n model_sync: {\r\n auto_export_ollama: true,\r\n ollama_model_name: 'bashgym-sidekick',\r\n notify_on_update: true,\r\n },\r\n }\r\n\r\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2))\r\n } else {\r\n // Update existing settings to enable integration\r\n integration.updateSettings({\r\n integration: {\r\n enabled: true,\r\n linked_at: new Date().toISOString(),\r\n },\r\n } as any)\r\n }\r\n\r\n return true\r\n } catch (error) {\r\n console.error('Failed to link bashgym:', error)\r\n return false\r\n }\r\n}\r\n\r\nfunction buildConfig(answers: Record<string, string>): BashBrosConfig {\r\n const defaults = getDefaultConfig()\r\n\r\n const config: BashBrosConfig = {\r\n ...defaults,\r\n agent: answers.agent as AgentType,\r\n profile: answers.profile as SecurityProfile,\r\n secrets: {\r\n ...defaults.secrets,\r\n enabled: answers.secrets !== 'disabled',\r\n mode: answers.secrets === 'audit' ? 'audit' : 'block'\r\n },\r\n audit: {\r\n ...defaults.audit,\r\n enabled: answers.audit !== 'disabled',\r\n destination: answers.audit === 'disabled' ? 'local' : answers.audit as 'local' | 'remote' | 'both'\r\n }\r\n }\r\n\r\n // Adjust for project type\r\n if (answers.projectType === 'sensitive') {\r\n config.profile = 'strict'\r\n config.rateLimit.maxPerMinute = 50\r\n }\r\n\r\n if (answers.projectType === 'devops') {\r\n config.commands.allow.push('docker *', 'kubectl *', 'terraform *', 'aws *')\r\n }\r\n\r\n if (answers.projectType === 'data') {\r\n config.commands.allow.push('python *', 'jupyter *', 'pandas *', 'psql *')\r\n }\r\n\r\n return config\r\n}\r\n","import chalk from 'chalk'\r\nimport { existsSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { findConfig, loadConfig } from './config.js'\r\nimport { getAllAgentConfigs, getAgentConfigInfo } from './transparency/agent-config.js'\r\nimport { ExposureScanner, EgressPatternMatcher } from './policy/ward/index.js'\r\nimport type { AgentConfigInfo } from './types.js'\r\n\r\ninterface CheckResult {\r\n name: string\r\n passed: boolean\r\n message: string\r\n}\r\n\r\n/**\r\n * Check agent configurations for health issues\r\n */\r\nasync function checkAgentConfigs(agents: AgentConfigInfo[]): Promise<CheckResult[]> {\r\n const checks: CheckResult[] = []\r\n\r\n for (const agent of agents) {\r\n const agentName = agent.agent.charAt(0).toUpperCase() + agent.agent.slice(1).replace('-', ' ')\r\n\r\n // Check if config exists\r\n if (agent.configPath && !agent.configExists) {\r\n checks.push({\r\n name: `${agentName} config`,\r\n passed: false,\r\n message: `Config path known (${agent.configPath}) but file not found`\r\n })\r\n } else if (agent.configExists) {\r\n checks.push({\r\n name: `${agentName} config`,\r\n passed: true,\r\n message: `Found at ${agent.configPath}`\r\n })\r\n }\r\n\r\n // Check bashbros integration\r\n if (agent.agent === 'claude-code') {\r\n checks.push({\r\n name: `${agentName} integration`,\r\n passed: agent.bashbrosIntegrated,\r\n message: agent.bashbrosIntegrated\r\n ? 'BashBros hooks installed'\r\n : 'Hooks not installed. Run \"bashbros hook install\" to protect Claude Code'\r\n })\r\n }\r\n\r\n // Check moltbot/clawdbot specific integration\r\n if (agent.agent === 'moltbot' || agent.agent === 'clawdbot') {\r\n checks.push({\r\n name: `${agentName} integration`,\r\n passed: agent.bashbrosIntegrated,\r\n message: agent.bashbrosIntegrated\r\n ? 'BashBros hooks installed'\r\n : 'Hooks not installed. Run \"bashbros moltbot install\" to protect moltbot'\r\n })\r\n\r\n // Check for moltbot-specific settings via dynamic import\r\n try {\r\n const { MoltbotHooks } = await import('./hooks/moltbot.js')\r\n const status = MoltbotHooks.getStatus()\r\n\r\n // Check sandbox mode\r\n if (status.sandboxMode) {\r\n checks.push({\r\n name: `${agentName} sandbox`,\r\n passed: status.sandboxMode === 'strict',\r\n message: status.sandboxMode === 'strict'\r\n ? 'Sandbox mode enabled (strict)'\r\n : `Sandbox mode: ${status.sandboxMode} (consider \"strict\" for better security)`\r\n })\r\n }\r\n\r\n // Check gateway configuration\r\n if (status.gatewayRunning) {\r\n const gatewayStatus = await MoltbotHooks.getGatewayStatus()\r\n checks.push({\r\n name: `${agentName} gateway`,\r\n passed: gatewayStatus.running,\r\n message: gatewayStatus.running\r\n ? `Gateway running on port ${gatewayStatus.port}`\r\n : 'Gateway configured but not running'\r\n })\r\n }\r\n } catch {\r\n // Moltbot hooks module not available, skip additional checks\r\n }\r\n }\r\n\r\n // Check for potential permission conflicts\r\n if (agent.permissions) {\r\n const config = loadConfig()\r\n\r\n // Warn if agent has no path restrictions but bashbros does\r\n if ((!agent.permissions.allowedPaths || agent.permissions.allowedPaths.length === 0) &&\r\n config.paths.allow.length > 0 && !config.paths.allow.includes('*')) {\r\n checks.push({\r\n name: `${agentName} path policy`,\r\n passed: true, // Not a failure, just a note\r\n message: `Agent has no path restrictions; bashbros will enforce: ${config.paths.allow.slice(0, 3).join(', ')}`\r\n })\r\n }\r\n }\r\n }\r\n\r\n return checks\r\n}\r\n\r\nexport async function runDoctor(): Promise<void> {\r\n console.log(chalk.bold('\\nRunning diagnostics...\\n'))\r\n\r\n const checks: CheckResult[] = []\r\n\r\n // Check 1: Config file exists\r\n const configPath = findConfig()\r\n checks.push({\r\n name: 'Config file',\r\n passed: configPath !== null,\r\n message: configPath\r\n ? `Found at ${configPath}`\r\n : 'Not found. Run \"bashbros init\" to create one.'\r\n })\r\n\r\n // Check 2: Config is valid\r\n if (configPath) {\r\n try {\r\n const config = loadConfig(configPath)\r\n checks.push({\r\n name: 'Config valid',\r\n passed: true,\r\n message: `Profile: ${config.profile}, Agent: ${config.agent}`\r\n })\r\n } catch (error) {\r\n checks.push({\r\n name: 'Config valid',\r\n passed: false,\r\n message: `Parse error: ${error}`\r\n })\r\n }\r\n }\r\n\r\n // Check 3: Audit directory exists\r\n const auditDir = join(homedir(), '.bashbros')\r\n checks.push({\r\n name: 'Audit directory',\r\n passed: existsSync(auditDir),\r\n message: existsSync(auditDir)\r\n ? `Found at ${auditDir}`\r\n : 'Will be created on first run'\r\n })\r\n\r\n // Check 4: node-pty available\r\n try {\r\n await import('node-pty')\r\n checks.push({\r\n name: 'PTY support',\r\n passed: true,\r\n message: 'node-pty loaded successfully'\r\n })\r\n } catch (error) {\r\n checks.push({\r\n name: 'PTY support',\r\n passed: false,\r\n message: 'node-pty not available. Run \"npm install\" to install dependencies.'\r\n })\r\n }\r\n\r\n // Check 5: Secrets protection patterns\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const secretsEnabled = config.secrets.enabled\r\n checks.push({\r\n name: 'Secrets protection',\r\n passed: secretsEnabled,\r\n message: secretsEnabled\r\n ? `Enabled with ${config.secrets.patterns.length} patterns`\r\n : 'Disabled - credentials may be exposed'\r\n })\r\n }\r\n\r\n // Check 6: Rate limiting\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n checks.push({\r\n name: 'Rate limiting',\r\n passed: config.rateLimit.enabled,\r\n message: config.rateLimit.enabled\r\n ? `${config.rateLimit.maxPerMinute}/min, ${config.rateLimit.maxPerHour}/hr`\r\n : 'Disabled - runaway agents possible'\r\n })\r\n }\r\n\r\n // Check 7: Agent configurations\r\n const agents = await getAllAgentConfigs()\r\n const installedAgents = agents.filter(a => a.installed)\r\n\r\n if (installedAgents.length > 0) {\r\n // Check agent config health\r\n const agentChecks = await checkAgentConfigs(installedAgents)\r\n checks.push(...agentChecks)\r\n } else {\r\n checks.push({\r\n name: 'Agent detection',\r\n passed: true,\r\n message: 'No agents detected (install claude, aider, etc. to use bashbros protection)'\r\n })\r\n }\r\n\r\n // Check 8: Ward security\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const wardEnabled = config.ward?.enabled ?? false\r\n checks.push({\r\n name: 'Ward security',\r\n passed: wardEnabled,\r\n message: wardEnabled\r\n ? `Enabled (exposure scan: ${config.ward.exposure.scanInterval}ms)`\r\n : 'Disabled - network exposure monitoring off'\r\n })\r\n }\r\n\r\n // Check 9: Dashboard\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const dashEnabled = config.dashboard?.enabled ?? false\r\n checks.push({\r\n name: 'Dashboard',\r\n passed: dashEnabled,\r\n message: dashEnabled\r\n ? `Enabled on ${config.dashboard.bind}:${config.dashboard.port}`\r\n : 'Disabled - run \"bashbros dashboard\" to start'\r\n })\r\n }\r\n\r\n // Check 10: Exposure scanner\r\n try {\r\n const scanner = new ExposureScanner()\r\n const agentSignatures = scanner.getAgents()\r\n checks.push({\r\n name: 'Exposure scanner',\r\n passed: true,\r\n message: `Ready, monitoring ${agentSignatures.length} agent signatures`\r\n })\r\n } catch {\r\n checks.push({\r\n name: 'Exposure scanner',\r\n passed: false,\r\n message: 'Failed to initialize exposure scanner'\r\n })\r\n }\r\n\r\n // Check 11: Egress patterns\r\n try {\r\n const matcher = new EgressPatternMatcher()\r\n const patterns = matcher.getPatterns()\r\n const credPatterns = patterns.filter(p => p.category === 'credentials').length\r\n const piiPatterns = patterns.filter(p => p.category === 'pii').length\r\n checks.push({\r\n name: 'Egress patterns',\r\n passed: true,\r\n message: `Loaded ${patterns.length} patterns (${credPatterns} credential, ${piiPatterns} PII)`\r\n })\r\n } catch {\r\n checks.push({\r\n name: 'Egress patterns',\r\n passed: false,\r\n message: 'Failed to initialize egress patterns'\r\n })\r\n }\r\n\r\n // Print results\r\n let passed = 0\r\n let failed = 0\r\n\r\n for (const check of checks) {\r\n const icon = check.passed ? chalk.green('✓') : chalk.red('✗')\r\n const status = check.passed ? chalk.green('OK') : chalk.red('FAIL')\r\n\r\n console.log(` ${icon} ${chalk.bold(check.name)}: ${status}`)\r\n console.log(chalk.dim(` ${check.message}`))\r\n console.log()\r\n\r\n if (check.passed) passed++\r\n else failed++\r\n }\r\n\r\n // Summary\r\n console.log(chalk.bold('─'.repeat(40)))\r\n if (failed === 0) {\r\n console.log(chalk.green(`\\n✓ All ${passed} checks passed. BashBros is ready.\\n`))\r\n } else {\r\n console.log(chalk.yellow(`\\n${passed} passed, ${failed} failed. Fix issues above.\\n`))\r\n }\r\n}\r\n","/**\r\n * Agent Configuration Discovery\r\n * Discovers and reports on agent configurations for transparency\r\n */\r\n\r\nimport { existsSync, statSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir, platform } from 'os'\r\nimport { execFileSync } from 'child_process'\r\nimport type { AgentType, AgentConfigInfo } from '../types.js'\r\nimport { ClaudeCodeHooks } from '../hooks/claude-code.js'\r\nimport { parseAgentConfig } from './config-parser.js'\r\n\r\n// Known agent config paths\r\n// Primary path is checked first, then fallbacks\r\nexport const AGENT_CONFIG_PATHS: Record<AgentType, string[]> = {\r\n 'claude-code': [\r\n join(homedir(), '.claude', 'settings.json')\r\n ],\r\n 'clawdbot': [\r\n join(homedir(), '.clawdbot', 'moltbot.json'), // New primary (moltbot format)\r\n join(homedir(), '.clawdbot', 'config.yml'), // Legacy\r\n join(homedir(), '.config', 'clawdbot', 'config.yml')\r\n ],\r\n 'moltbot': [\r\n join(homedir(), '.moltbot', 'config.json'),\r\n join(homedir(), '.clawdbot', 'moltbot.json'), // Common location\r\n join(homedir(), '.config', 'moltbot', 'config.json')\r\n ],\r\n 'aider': [\r\n join(homedir(), '.aider.conf.yml'),\r\n join(homedir(), '.config', 'aider', 'aider.conf.yml')\r\n ],\r\n 'gemini-cli': [\r\n join(homedir(), '.config', 'gemini-cli', 'config.json')\r\n ],\r\n 'opencode': [\r\n join(homedir(), '.opencode', 'config.yml'),\r\n join(homedir(), '.config', 'opencode', 'config.yml')\r\n ],\r\n 'custom': []\r\n}\r\n\r\n// Command names for each agent (used to check if installed)\r\nconst AGENT_COMMANDS: Record<AgentType, string> = {\r\n 'claude-code': 'claude',\r\n 'clawdbot': 'clawdbot',\r\n 'moltbot': 'moltbot',\r\n 'aider': 'aider',\r\n 'gemini-cli': 'gemini',\r\n 'opencode': 'opencode',\r\n 'custom': ''\r\n}\r\n\r\n/**\r\n * Detect which naming convention is being used (moltbot vs clawdbot)\r\n * Returns the detected naming or null if neither is found\r\n */\r\nexport function detectMoltbotNaming(): 'moltbot' | 'clawdbot' | null {\r\n // Check environment variables first (runtime indicator)\r\n if (process.env.MOLTBOT_SESSION_ID || process.env.MOLTBOT_AGENT) {\r\n return 'moltbot'\r\n }\r\n if (process.env.CLAWDBOT_SESSION_ID || process.env.CLAWDBOT_AGENT) {\r\n return 'clawdbot'\r\n }\r\n\r\n // Check for moltbot command\r\n if (commandExists('moltbot')) {\r\n return 'moltbot'\r\n }\r\n\r\n // Check for clawdbot command\r\n if (commandExists('clawdbot')) {\r\n return 'clawdbot'\r\n }\r\n\r\n // Check for config files\r\n const moltbotPaths = AGENT_CONFIG_PATHS['moltbot']\r\n for (const p of moltbotPaths) {\r\n if (existsSync(p)) {\r\n return 'moltbot'\r\n }\r\n }\r\n\r\n const clawdbotPaths = AGENT_CONFIG_PATHS['clawdbot']\r\n for (const p of clawdbotPaths) {\r\n if (existsSync(p)) {\r\n return 'clawdbot'\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * Check if a command exists in PATH\r\n */\r\nfunction commandExists(cmd: string): boolean {\r\n if (!cmd) return false\r\n\r\n try {\r\n const whichCmd = platform() === 'win32' ? 'where' : 'which'\r\n execFileSync(whichCmd, [cmd], {\r\n stdio: 'pipe',\r\n timeout: 3000,\r\n windowsHide: true\r\n })\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Get version of an agent command\r\n */\r\nfunction getAgentVersion(agent: AgentType): string | undefined {\r\n const cmd = AGENT_COMMANDS[agent]\r\n if (!cmd) return undefined\r\n\r\n try {\r\n const output = execFileSync(cmd, ['--version'], {\r\n encoding: 'utf-8',\r\n timeout: 5000,\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n windowsHide: true\r\n }).trim()\r\n\r\n // Extract version number\r\n const match = output.match(/(\\d+\\.\\d+(?:\\.\\d+)?(?:-[\\w.]+)?)/i)\r\n return match ? match[1] : output.split('\\n')[0].slice(0, 50)\r\n } catch {\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Find the config path for an agent\r\n */\r\nfunction findAgentConfigPath(agent: AgentType): string | undefined {\r\n const paths = AGENT_CONFIG_PATHS[agent]\r\n\r\n for (const configPath of paths) {\r\n if (existsSync(configPath)) {\r\n return configPath\r\n }\r\n }\r\n\r\n return undefined\r\n}\r\n\r\n/**\r\n * Get last modified date of a file\r\n */\r\nfunction getLastModified(filePath: string): Date | undefined {\r\n try {\r\n const stats = statSync(filePath)\r\n return stats.mtime\r\n } catch {\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Check if BashBros is integrated with an agent\r\n */\r\nasync function isBashbrosIntegrated(agent: AgentType): Promise<boolean> {\r\n if (agent === 'claude-code') {\r\n const status = ClaudeCodeHooks.getStatus()\r\n return status.hooksInstalled\r\n }\r\n\r\n if (agent === 'moltbot' || agent === 'clawdbot') {\r\n try {\r\n const { MoltbotHooks } = await import('../hooks/moltbot.js')\r\n return MoltbotHooks.isInstalled()\r\n } catch {\r\n return false\r\n }\r\n }\r\n\r\n // For other agents, check if they have bashbros hooks configured\r\n // This would need to be extended as more integrations are built\r\n return false\r\n}\r\n\r\n/**\r\n * Get configuration info for a specific agent\r\n */\r\nexport async function getAgentConfigInfo(agent: AgentType): Promise<AgentConfigInfo> {\r\n const cmd = AGENT_COMMANDS[agent]\r\n const installed = cmd ? commandExists(cmd) : false\r\n const configPath = findAgentConfigPath(agent)\r\n const configExists = configPath ? existsSync(configPath) : false\r\n\r\n const info: AgentConfigInfo = {\r\n agent,\r\n installed,\r\n configPath,\r\n configExists,\r\n bashbrosIntegrated: await isBashbrosIntegrated(agent)\r\n }\r\n\r\n if (installed) {\r\n info.version = getAgentVersion(agent)\r\n }\r\n\r\n if (configExists && configPath) {\r\n info.lastModified = getLastModified(configPath)\r\n\r\n // Parse config for permissions and hooks\r\n const parsed = await parseAgentConfig(agent, configPath)\r\n if (parsed) {\r\n info.permissions = parsed.permissions\r\n info.hooks = parsed.hooks\r\n }\r\n }\r\n\r\n return info\r\n}\r\n\r\n/**\r\n * Get configuration info for all known agents\r\n */\r\nexport async function getAllAgentConfigs(): Promise<AgentConfigInfo[]> {\r\n const agents: AgentType[] = ['claude-code', 'moltbot', 'clawdbot', 'aider', 'gemini-cli', 'opencode']\r\n const results: AgentConfigInfo[] = []\r\n\r\n for (const agent of agents) {\r\n const info = await getAgentConfigInfo(agent)\r\n results.push(info)\r\n }\r\n\r\n return results\r\n}\r\n\r\n/**\r\n * Get only installed agents\r\n */\r\nexport async function getInstalledAgents(): Promise<AgentConfigInfo[]> {\r\n const all = await getAllAgentConfigs()\r\n return all.filter(info => info.installed)\r\n}\r\n\r\n/**\r\n * Get agents with configurations\r\n */\r\nexport async function getConfiguredAgents(): Promise<AgentConfigInfo[]> {\r\n const all = await getAllAgentConfigs()\r\n return all.filter(info => info.configExists)\r\n}\r\n","/**\r\n * Exposure Scanner - Detects exposed AI agent servers\r\n *\r\n * Scans for listening ports that match known AI agent signatures\r\n * and assesses their security risk based on binding, authentication,\r\n * and external reachability.\r\n */\r\n\r\nimport { exec } from 'node:child_process'\r\nimport { promisify } from 'node:util'\r\nimport { existsSync, readFileSync } from 'node:fs'\r\nimport { platform } from 'node:os'\r\nimport type {\r\n AgentSignature,\r\n ExposureResult,\r\n ExposureSeverity,\r\n ExposureAction,\r\n ExposureConfig,\r\n} from './types.js'\r\n\r\nconst execAsync = promisify(exec)\r\n\r\n/**\r\n * Default agent signatures for common AI coding assistants\r\n */\r\nexport const DEFAULT_AGENT_SIGNATURES: AgentSignature[] = [\r\n {\r\n name: 'claude-code',\r\n processNames: ['claude', 'claude-code', 'claude_code'],\r\n defaultPorts: [3000, 3001, 8080],\r\n configPaths: [\r\n '~/.claude/config.json',\r\n '~/.config/claude/config.json',\r\n ],\r\n authIndicators: ['api_key', 'auth_token', 'authorization'],\r\n },\r\n {\r\n name: 'aider',\r\n processNames: ['aider', 'aider-chat'],\r\n defaultPorts: [8501, 8000],\r\n configPaths: [\r\n '~/.aider.conf.yml',\r\n '.aider.conf.yml',\r\n ],\r\n authIndicators: ['api_key', 'openai_api_key'],\r\n },\r\n {\r\n name: 'continue',\r\n processNames: ['continue', 'continue-server'],\r\n defaultPorts: [65432, 65433],\r\n configPaths: [\r\n '~/.continue/config.json',\r\n '.continue/config.json',\r\n ],\r\n authIndicators: ['apiKey', 'auth'],\r\n },\r\n {\r\n name: 'cursor',\r\n processNames: ['cursor', 'Cursor', 'cursor-server'],\r\n defaultPorts: [3000, 8080, 9000],\r\n configPaths: [\r\n '~/.cursor/config.json',\r\n '%APPDATA%/Cursor/config.json',\r\n ],\r\n authIndicators: ['apiKey', 'token', 'auth'],\r\n },\r\n]\r\n\r\n/**\r\n * Default mapping from severity to action\r\n */\r\nexport const DEFAULT_SEVERITY_ACTIONS: Record<ExposureSeverity, ExposureAction> = {\r\n low: 'alert',\r\n medium: 'alert',\r\n high: 'block',\r\n critical: 'block_and_kill',\r\n}\r\n\r\n/**\r\n * Input for severity assessment\r\n */\r\nexport interface SeverityInput {\r\n bindAddress: string\r\n hasAuth: boolean | 'unknown'\r\n externallyReachable: boolean\r\n hasActiveSessions: boolean\r\n}\r\n\r\n/**\r\n * Parsed netstat line result\r\n */\r\nexport interface NetstatResult {\r\n protocol: string\r\n localAddress: string\r\n localPort: number\r\n state: string\r\n pid: number\r\n}\r\n\r\n/**\r\n * ExposureScanner - Scans for exposed AI agent servers\r\n */\r\nexport class ExposureScanner {\r\n private config: ExposureConfig\r\n private agents: AgentSignature[]\r\n\r\n constructor(config?: Partial<ExposureConfig>) {\r\n this.agents = [...DEFAULT_AGENT_SIGNATURES]\r\n this.config = {\r\n enabled: true,\r\n scanInterval: 60000,\r\n externalProbe: false,\r\n severityActions: { ...DEFAULT_SEVERITY_ACTIONS },\r\n agents: this.agents,\r\n ...config,\r\n }\r\n\r\n // Merge any custom agents from config\r\n if (config?.agents) {\r\n for (const agent of config.agents) {\r\n if (!this.agents.find(a => a.name === agent.name)) {\r\n this.agents.push(agent)\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Scan for exposed agent servers\r\n */\r\n async scan(): Promise<ExposureResult[]> {\r\n const results: ExposureResult[] = []\r\n const listeningPorts = await this.getListeningPorts()\r\n\r\n for (const port of listeningPorts) {\r\n for (const agent of this.agents) {\r\n if (agent.defaultPorts.includes(port.localPort)) {\r\n const hasAuth = await this.checkAuthConfig(agent)\r\n const externallyReachable = this.isExternallyReachable(port.localAddress)\r\n\r\n const severity = this.assessSeverity({\r\n bindAddress: port.localAddress,\r\n hasAuth,\r\n externallyReachable,\r\n hasActiveSessions: false,\r\n })\r\n\r\n const action = this.getActionForSeverity(severity)\r\n\r\n results.push({\r\n agent: agent.name,\r\n pid: port.pid,\r\n port: port.localPort,\r\n bindAddress: port.localAddress,\r\n hasAuth,\r\n severity,\r\n action,\r\n message: this.generateMessage(agent.name, port, severity, hasAuth),\r\n timestamp: new Date(),\r\n })\r\n }\r\n }\r\n }\r\n\r\n return results\r\n }\r\n\r\n /**\r\n * Assess severity based on exposure factors\r\n */\r\n assessSeverity(input: SeverityInput): ExposureSeverity {\r\n const { bindAddress, hasAuth, externallyReachable, hasActiveSessions } = input\r\n\r\n // Critical: Externally reachable without auth\r\n if (externallyReachable && hasAuth !== true) {\r\n return 'critical'\r\n }\r\n\r\n // Critical: Active sessions on externally reachable\r\n if (externallyReachable && hasActiveSessions) {\r\n return 'critical'\r\n }\r\n\r\n // High: Bound to all interfaces (0.0.0.0 or ::) without auth\r\n const isWildcardBind = bindAddress === '0.0.0.0' || bindAddress === '::' || bindAddress === '*'\r\n if (isWildcardBind && hasAuth !== true) {\r\n return 'high'\r\n }\r\n\r\n // Medium: Bound to all interfaces with auth, or localhost without auth\r\n if (isWildcardBind && hasAuth === true) {\r\n return 'medium'\r\n }\r\n\r\n // Check if localhost\r\n const isLocalhost =\r\n bindAddress === '127.0.0.1' ||\r\n bindAddress === '::1' ||\r\n bindAddress === 'localhost'\r\n\r\n if (isLocalhost && hasAuth !== true) {\r\n return 'medium'\r\n }\r\n\r\n // Low: Localhost with auth\r\n return 'low'\r\n }\r\n\r\n /**\r\n * Get action for a given severity level\r\n */\r\n getActionForSeverity(severity: ExposureSeverity): ExposureAction {\r\n return this.config.severityActions[severity]\r\n }\r\n\r\n /**\r\n * Parse a Windows netstat output line\r\n */\r\n parseNetstatLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || !trimmed.includes('LISTENING')) {\r\n return null\r\n }\r\n\r\n // Windows netstat -ano format:\r\n // TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12345\r\n // TCP [::]:8000 [::]:0 LISTENING 1111\r\n\r\n const parts = trimmed.split(/\\s+/)\r\n if (parts.length < 5) {\r\n return null\r\n }\r\n\r\n const protocol = parts[0]\r\n if (protocol !== 'TCP' && protocol !== 'UDP') {\r\n return null\r\n }\r\n\r\n const localAddressPart = parts[1]\r\n const state = parts[3]\r\n const pid = parseInt(parts[4], 10)\r\n\r\n if (state !== 'LISTENING' || isNaN(pid)) {\r\n return null\r\n }\r\n\r\n // Parse address:port - handle IPv6 [addr]:port format\r\n let localAddress: string\r\n let localPort: number\r\n\r\n if (localAddressPart.startsWith('[')) {\r\n // IPv6 format: [::1]:3000 or [::]:8000\r\n const match = localAddressPart.match(/^\\[([^\\]]+)\\]:(\\d+)$/)\r\n if (!match) {\r\n return null\r\n }\r\n localAddress = match[1]\r\n localPort = parseInt(match[2], 10)\r\n } else {\r\n // IPv4 format: 0.0.0.0:3000\r\n const lastColonIndex = localAddressPart.lastIndexOf(':')\r\n if (lastColonIndex === -1) {\r\n return null\r\n }\r\n localAddress = localAddressPart.substring(0, lastColonIndex)\r\n localPort = parseInt(localAddressPart.substring(lastColonIndex + 1), 10)\r\n }\r\n\r\n if (isNaN(localPort)) {\r\n return null\r\n }\r\n\r\n return {\r\n protocol,\r\n localAddress,\r\n localPort,\r\n state,\r\n pid,\r\n }\r\n }\r\n\r\n /**\r\n * Get all listening TCP ports (cross-platform)\r\n */\r\n async getListeningPorts(): Promise<NetstatResult[]> {\r\n const results: NetstatResult[] = []\r\n\r\n try {\r\n if (platform() === 'win32') {\r\n const { stdout } = await execAsync('netstat -ano -p TCP')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseNetstatLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n } else {\r\n // Unix-like systems: use ss or netstat\r\n try {\r\n const { stdout } = await execAsync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseUnixListeningLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n } catch {\r\n // Fallback to lsof on macOS\r\n const { stdout } = await execAsync('lsof -iTCP -sTCP:LISTEN -n -P 2>/dev/null || true')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseLsofLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n }\r\n }\r\n } catch {\r\n // Return empty array if we can't get port info\r\n }\r\n\r\n return results\r\n }\r\n\r\n /**\r\n * Parse Unix ss/netstat output line\r\n */\r\n private parseUnixListeningLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || trimmed.startsWith('State') || trimmed.startsWith('Proto')) {\r\n return null\r\n }\r\n\r\n // ss format: LISTEN 0 128 0.0.0.0:3000 0.0.0.0:* users:((\"node\",pid=1234,fd=3))\r\n // netstat format: tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 1234/node\r\n\r\n // Try ss format first\r\n const ssMatch = trimmed.match(/LISTEN\\s+\\d+\\s+\\d+\\s+([^\\s]+):(\\d+)\\s+.*?pid=(\\d+)/)\r\n if (ssMatch) {\r\n return {\r\n protocol: 'TCP',\r\n localAddress: ssMatch[1] === '*' ? '0.0.0.0' : ssMatch[1],\r\n localPort: parseInt(ssMatch[2], 10),\r\n state: 'LISTENING',\r\n pid: parseInt(ssMatch[3], 10),\r\n }\r\n }\r\n\r\n // Try netstat format\r\n const netstatMatch = trimmed.match(/tcp\\s+\\d+\\s+\\d+\\s+([^\\s]+):(\\d+)\\s+.*?LISTEN\\s+(\\d+)/)\r\n if (netstatMatch) {\r\n return {\r\n protocol: 'TCP',\r\n localAddress: netstatMatch[1] === '*' ? '0.0.0.0' : netstatMatch[1],\r\n localPort: parseInt(netstatMatch[2], 10),\r\n state: 'LISTENING',\r\n pid: parseInt(netstatMatch[3], 10),\r\n }\r\n }\r\n\r\n return null\r\n }\r\n\r\n /**\r\n * Parse lsof output line (macOS fallback)\r\n */\r\n private parseLsofLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || trimmed.startsWith('COMMAND')) {\r\n return null\r\n }\r\n\r\n // lsof format: node 1234 user 3u IPv4 0x123 0t0 TCP *:3000 (LISTEN)\r\n const parts = trimmed.split(/\\s+/)\r\n if (parts.length < 9) {\r\n return null\r\n }\r\n\r\n const pid = parseInt(parts[1], 10)\r\n if (isNaN(pid)) {\r\n return null\r\n }\r\n\r\n // Find TCP and port info\r\n const tcpIndex = parts.findIndex(p => p === 'TCP' || p === 'TCP6')\r\n if (tcpIndex === -1) {\r\n return null\r\n }\r\n\r\n const addressPart = parts[tcpIndex + 1]\r\n if (!addressPart) {\r\n return null\r\n }\r\n\r\n // Parse *:3000 or 127.0.0.1:3000\r\n const match = addressPart.match(/^([^:]+):(\\d+)$/)\r\n if (!match) {\r\n return null\r\n }\r\n\r\n return {\r\n protocol: 'TCP',\r\n localAddress: match[1] === '*' ? '0.0.0.0' : match[1],\r\n localPort: parseInt(match[2], 10),\r\n state: 'LISTENING',\r\n pid,\r\n }\r\n }\r\n\r\n /**\r\n * Check if an agent has auth configured\r\n */\r\n async checkAuthConfig(agent: AgentSignature): Promise<boolean | 'unknown'> {\r\n for (const configPath of agent.configPaths) {\r\n const expandedPath = this.expandPath(configPath)\r\n\r\n if (existsSync(expandedPath)) {\r\n try {\r\n const content = readFileSync(expandedPath, 'utf-8')\r\n\r\n for (const indicator of agent.authIndicators) {\r\n if (content.includes(indicator)) {\r\n return true\r\n }\r\n }\r\n return false\r\n } catch {\r\n // Can't read config, unknown\r\n }\r\n }\r\n }\r\n\r\n return 'unknown'\r\n }\r\n\r\n /**\r\n * Check if an address is externally reachable\r\n */\r\n private isExternallyReachable(bindAddress: string): boolean {\r\n // 0.0.0.0 or :: binds to all interfaces\r\n if (bindAddress === '0.0.0.0' || bindAddress === '::' || bindAddress === '*') {\r\n // Could be externally reachable if there's a non-loopback interface\r\n // For now, we assume it could be reachable\r\n // In a real implementation, we'd check network interfaces\r\n return this.config.externalProbe\r\n }\r\n\r\n // Localhost addresses are not externally reachable\r\n if (\r\n bindAddress === '127.0.0.1' ||\r\n bindAddress === '::1' ||\r\n bindAddress === 'localhost'\r\n ) {\r\n return false\r\n }\r\n\r\n // Private IP ranges - potentially reachable on LAN\r\n if (this.isPrivateIP(bindAddress)) {\r\n return this.config.externalProbe\r\n }\r\n\r\n // Public IP - externally reachable\r\n return true\r\n }\r\n\r\n /**\r\n * Check if an IP is in a private range\r\n */\r\n private isPrivateIP(ip: string): boolean {\r\n // IPv4 private ranges\r\n if (ip.startsWith('10.')) return true\r\n if (ip.startsWith('172.')) {\r\n const second = parseInt(ip.split('.')[1], 10)\r\n if (second >= 16 && second <= 31) return true\r\n }\r\n if (ip.startsWith('192.168.')) return true\r\n\r\n // IPv6 private ranges\r\n if (ip.toLowerCase().startsWith('fc') || ip.toLowerCase().startsWith('fd')) {\r\n return true\r\n }\r\n\r\n return false\r\n }\r\n\r\n /**\r\n * Expand path with home directory and environment variables\r\n */\r\n private expandPath(path: string): string {\r\n let expanded = path\r\n\r\n // Expand ~ to home directory\r\n if (expanded.startsWith('~')) {\r\n const home = process.env.HOME || process.env.USERPROFILE || ''\r\n expanded = expanded.replace('~', home)\r\n }\r\n\r\n // Expand %VAR% style env vars (Windows)\r\n expanded = expanded.replace(/%([^%]+)%/g, (_, name) => process.env[name] || '')\r\n\r\n // Expand $VAR style env vars (Unix)\r\n expanded = expanded.replace(/\\$([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => process.env[name] || '')\r\n\r\n return expanded\r\n }\r\n\r\n /**\r\n * Generate human-readable message for an exposure\r\n */\r\n private generateMessage(\r\n agentName: string,\r\n port: NetstatResult,\r\n severity: ExposureSeverity,\r\n hasAuth: boolean | 'unknown'\r\n ): string {\r\n const authStatus = hasAuth === true\r\n ? 'with authentication'\r\n : hasAuth === false\r\n ? 'without authentication'\r\n : 'authentication status unknown'\r\n\r\n const bindDesc = port.localAddress === '0.0.0.0' || port.localAddress === '::'\r\n ? 'all interfaces'\r\n : port.localAddress\r\n\r\n return `${agentName} server detected on port ${port.localPort} (${bindDesc}) ${authStatus}. Severity: ${severity}`\r\n }\r\n\r\n /**\r\n * Add a custom agent signature\r\n */\r\n addAgent(agent: AgentSignature): void {\r\n this.agents.push(agent)\r\n }\r\n\r\n /**\r\n * Get all configured agent signatures\r\n */\r\n getAgents(): AgentSignature[] {\r\n return [...this.agents]\r\n }\r\n}\r\n","/**\r\n * Egress Patterns - Pattern matching for sensitive data detection\r\n *\r\n * Provides pattern definitions and matching utilities for detecting\r\n * credentials, PII, and other sensitive data in egress traffic.\r\n */\r\n\r\nimport type {\r\n EgressPattern,\r\n PatternSeverity,\r\n RedactedPayload,\r\n RedactionInfo,\r\n} from './types.js'\r\n\r\n/**\r\n * Default patterns for detecting sensitive data\r\n */\r\nexport const DEFAULT_PATTERNS: EgressPattern[] = [\r\n // Credential patterns\r\n {\r\n name: 'api_key',\r\n regex: '(?:api[_-]?key|apikey)[\\\\s]*[=:][\\\\s]*[\"\\']?([a-zA-Z0-9_\\\\-]{20,})[\"\\']?',\r\n severity: 'high',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'Generic API key pattern',\r\n },\r\n {\r\n name: 'aws_secret',\r\n regex: '(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key)[\\\\s]*[=:][\\\\s]*[\"\\']?([a-zA-Z0-9/+=]{40})[\"\\']?',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'AWS Secret Access Key',\r\n },\r\n {\r\n name: 'private_key',\r\n regex: '-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'Private key header',\r\n },\r\n {\r\n name: 'github_token',\r\n regex: '(?:gh[pousr]_[a-zA-Z0-9]{36,}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'GitHub personal access token',\r\n },\r\n {\r\n name: 'openai_key',\r\n regex: 'sk-[a-zA-Z0-9]{20,}T3BlbkFJ[a-zA-Z0-9]{20,}',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'OpenAI API key',\r\n },\r\n {\r\n name: 'jwt_token',\r\n regex: 'eyJ[a-zA-Z0-9_-]*\\\\.eyJ[a-zA-Z0-9_-]*\\\\.[a-zA-Z0-9_-]*',\r\n severity: 'high',\r\n action: 'alert',\r\n category: 'credentials',\r\n description: 'JSON Web Token',\r\n },\r\n\r\n // PII patterns\r\n {\r\n name: 'ssn',\r\n regex: '\\\\b\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}\\\\b',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'pii',\r\n description: 'US Social Security Number',\r\n },\r\n {\r\n name: 'credit_card',\r\n regex: '\\\\b(?:4[0-9]{3}|5[1-5][0-9]{2}|6(?:011|5[0-9]{2})|3[47][0-9]{2})[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}\\\\b',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'pii',\r\n description: 'Credit card number (Visa, MasterCard, Amex, Discover)',\r\n },\r\n {\r\n name: 'email',\r\n regex: '\\\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}\\\\b',\r\n severity: 'low',\r\n action: 'log',\r\n category: 'pii',\r\n description: 'Email address',\r\n },\r\n {\r\n name: 'phone_us',\r\n regex: '\\\\b(?:\\\\+1[- ]?)?(?:\\\\([0-9]{3}\\\\)|[0-9]{3})[- ]?[0-9]{3}[- ]?[0-9]{4}\\\\b',\r\n severity: 'medium',\r\n action: 'alert',\r\n category: 'pii',\r\n description: 'US phone number',\r\n },\r\n]\r\n\r\n/**\r\n * Pattern match result\r\n */\r\nexport interface PatternMatch {\r\n pattern: EgressPattern\r\n matchedText: string\r\n index: number\r\n}\r\n\r\n/**\r\n * Severity ordering for comparison\r\n */\r\nconst SEVERITY_ORDER: Record<PatternSeverity, number> = {\r\n low: 1,\r\n medium: 2,\r\n high: 3,\r\n critical: 4,\r\n}\r\n\r\n/**\r\n * EgressPatternMatcher - Matches and redacts sensitive data in text\r\n */\r\nexport class EgressPatternMatcher {\r\n private patterns: EgressPattern[]\r\n private compiledPatterns: Map<string, RegExp>\r\n\r\n constructor(customPatterns?: EgressPattern[]) {\r\n this.patterns = [...DEFAULT_PATTERNS]\r\n this.compiledPatterns = new Map()\r\n\r\n if (customPatterns) {\r\n for (const pattern of customPatterns) {\r\n this.patterns.push(pattern)\r\n }\r\n }\r\n\r\n // Pre-compile all patterns\r\n this.compilePatterns()\r\n }\r\n\r\n /**\r\n * Compile regex patterns for efficient matching\r\n */\r\n private compilePatterns(): void {\r\n for (const pattern of this.patterns) {\r\n if (!this.compiledPatterns.has(pattern.name)) {\r\n try {\r\n this.compiledPatterns.set(pattern.name, new RegExp(pattern.regex, 'gi'))\r\n } catch {\r\n // Invalid regex - skip pattern\r\n console.warn(`Invalid regex for pattern ${pattern.name}: ${pattern.regex}`)\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Find all pattern matches in text\r\n */\r\n match(text: string): PatternMatch[] {\r\n const matches: PatternMatch[] = []\r\n\r\n for (const pattern of this.patterns) {\r\n const regex = this.compiledPatterns.get(pattern.name)\r\n if (!regex) continue\r\n\r\n // Reset regex state\r\n regex.lastIndex = 0\r\n\r\n let match: RegExpExecArray | null\r\n while ((match = regex.exec(text)) !== null) {\r\n matches.push({\r\n pattern,\r\n matchedText: match[0],\r\n index: match.index,\r\n })\r\n }\r\n }\r\n\r\n return matches\r\n }\r\n\r\n /**\r\n * Check if any blocking patterns match the text\r\n */\r\n shouldBlock(text: string): boolean {\r\n const matches = this.match(text)\r\n return matches.some(m => m.pattern.action === 'block')\r\n }\r\n\r\n /**\r\n * Get the highest severity level from all matches\r\n */\r\n getHighestSeverity(text: string): PatternSeverity | null {\r\n const matches = this.match(text)\r\n if (matches.length === 0) return null\r\n\r\n let highest: PatternSeverity = 'low'\r\n for (const m of matches) {\r\n if (SEVERITY_ORDER[m.pattern.severity] > SEVERITY_ORDER[highest]) {\r\n highest = m.pattern.severity\r\n }\r\n }\r\n\r\n return highest\r\n }\r\n\r\n /**\r\n * Redact sensitive data from text\r\n */\r\n redact(text: string): RedactedPayload {\r\n const matches = this.match(text)\r\n const redactions: RedactionInfo[] = []\r\n let redacted = text\r\n\r\n // Sort matches by index in reverse order to preserve positions during replacement\r\n const sortedMatches = [...matches].sort((a, b) => b.index - a.index)\r\n\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n\r\n // Map pattern category to RedactionInfo type\r\n let redactionType: RedactionInfo['type']\r\n if (m.pattern.name === 'api_key' || m.pattern.name === 'aws_secret' ||\r\n m.pattern.name === 'private_key' || m.pattern.name === 'github_token' ||\r\n m.pattern.name === 'openai_key' || m.pattern.name === 'jwt_token') {\r\n redactionType = 'api_key'\r\n } else if (m.pattern.name === 'email') {\r\n redactionType = 'email'\r\n } else if (m.pattern.name === 'phone_us') {\r\n redactionType = 'phone'\r\n } else if (m.pattern.name === 'ssn') {\r\n redactionType = 'ssn'\r\n } else if (m.pattern.name === 'credit_card') {\r\n redactionType = 'credit_card'\r\n } else {\r\n redactionType = 'custom'\r\n }\r\n\r\n redactions.push({\r\n type: redactionType,\r\n replacement,\r\n })\r\n\r\n // Replace the matched text\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n\r\n return {\r\n original: text,\r\n redacted,\r\n redactions: redactions.reverse(), // Return in original order\r\n }\r\n }\r\n\r\n /**\r\n * Add a custom pattern\r\n */\r\n addPattern(pattern: EgressPattern): void {\r\n this.patterns.push(pattern)\r\n try {\r\n this.compiledPatterns.set(pattern.name, new RegExp(pattern.regex, 'gi'))\r\n } catch {\r\n console.warn(`Invalid regex for pattern ${pattern.name}: ${pattern.regex}`)\r\n }\r\n }\r\n\r\n /**\r\n * Get all configured patterns\r\n */\r\n getPatterns(): EgressPattern[] {\r\n return [...this.patterns]\r\n }\r\n\r\n /**\r\n * Test helper - returns matches, shouldBlock, and redacted result\r\n */\r\n test(text: string): {\r\n matches: PatternMatch[]\r\n shouldBlock: boolean\r\n redacted: RedactedPayload\r\n } {\r\n return {\r\n matches: this.match(text),\r\n shouldBlock: this.shouldBlock(text),\r\n redacted: this.redact(text),\r\n }\r\n }\r\n}\r\n","/**\r\n * Egress Monitor - Monitors and blocks sensitive data in outbound traffic\r\n *\r\n * Provides inspection of content for sensitive patterns (API keys, PII, etc.)\r\n * with support for connector-based allowlisting and pattern-specific exceptions.\r\n */\r\n\r\nimport { EgressPatternMatcher, type PatternMatch } from './patterns.js'\r\nimport type {\r\n EgressPattern,\r\n EgressConfig,\r\n EgressAllowlistEntry,\r\n EgressMatch,\r\n} from './types.js'\r\n\r\n// Optional database import - gracefully handle if unavailable\r\nlet DashboardDB: typeof import('../../dashboard/db.js').DashboardDB | null = null\r\ntry {\r\n const dbModule = await import('../../dashboard/db.js')\r\n DashboardDB = dbModule.DashboardDB\r\n} catch {\r\n // Database unavailable - operate without persistence\r\n}\r\n\r\n/**\r\n * Result of content inspection\r\n */\r\nexport interface InspectionResult {\r\n /** Whether the content was blocked */\r\n blocked: boolean\r\n /** Whether the content was allowlisted (skipped inspection) */\r\n allowlisted: boolean\r\n /** Patterns that matched */\r\n matches: PatternMatch[]\r\n /** Content with sensitive data redacted */\r\n redacted: string\r\n /** Block ID if content was recorded to database */\r\n blockId?: string\r\n}\r\n\r\n/**\r\n * Default egress configuration\r\n */\r\nconst DEFAULT_EGRESS_CONFIG: EgressConfig = {\r\n enabled: true,\r\n defaultAction: 'block',\r\n allowlist: [],\r\n}\r\n\r\n/**\r\n * EgressMonitor - Monitors outbound content for sensitive data\r\n */\r\nexport class EgressMonitor {\r\n private config: EgressConfig\r\n private matcher: EgressPatternMatcher\r\n private db: InstanceType<typeof import('../../dashboard/db.js').DashboardDB> | null = null\r\n private allowlist: EgressAllowlistEntry[]\r\n\r\n constructor(config?: Partial<EgressConfig>) {\r\n this.config = { ...DEFAULT_EGRESS_CONFIG, ...config }\r\n this.matcher = new EgressPatternMatcher()\r\n this.allowlist = [...this.config.allowlist]\r\n\r\n // Try to initialize database\r\n if (DashboardDB) {\r\n try {\r\n this.db = new DashboardDB()\r\n } catch {\r\n // Database initialization failed - operate without persistence\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Inspect content for sensitive data\r\n *\r\n * @param content - The content to inspect\r\n * @param connector - Optional connector name for allowlist checking\r\n * @param destination - Optional destination for allowlist checking\r\n * @returns Inspection result with blocking decision and matches\r\n */\r\n inspect(content: string, connector?: string, destination?: string): InspectionResult {\r\n // Check if fully allowlisted (skip all inspection)\r\n if (this.isAllowlisted(connector, destination)) {\r\n return {\r\n blocked: false,\r\n allowlisted: true,\r\n matches: [],\r\n redacted: content,\r\n }\r\n }\r\n\r\n // Get all matches\r\n const allMatches = this.matcher.match(content)\r\n\r\n // Filter out pattern-specific allowlisted matches\r\n const effectiveMatches = allMatches.filter(match => {\r\n return !this.isPatternAllowlisted(match.pattern.name, connector, destination)\r\n })\r\n\r\n // Check if any remaining matches should block\r\n const shouldBlock = effectiveMatches.some(m => m.pattern.action === 'block')\r\n\r\n // Redact content based on effective matches\r\n let redacted = content\r\n if (effectiveMatches.length > 0) {\r\n // Sort by index descending to preserve positions during replacement\r\n const sortedMatches = [...effectiveMatches].sort((a, b) => b.index - a.index)\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n }\r\n\r\n // Check if all matched patterns were allowlisted\r\n const wasAllowlisted = allMatches.length > 0 && effectiveMatches.length === 0\r\n\r\n const result: InspectionResult = {\r\n blocked: shouldBlock,\r\n allowlisted: wasAllowlisted,\r\n matches: effectiveMatches,\r\n redacted,\r\n }\r\n\r\n // Record to database if blocking\r\n if (shouldBlock && this.db) {\r\n try {\r\n // Record each blocking match\r\n for (const match of effectiveMatches.filter(m => m.pattern.action === 'block')) {\r\n const blockId = this.db.insertEgressBlock({\r\n pattern: match.pattern,\r\n matchedText: match.matchedText.substring(0, 100), // Truncate for safety\r\n redactedText: redacted,\r\n connector,\r\n destination,\r\n })\r\n result.blockId = blockId\r\n }\r\n\r\n // Log the event\r\n this.db.insertEvent({\r\n source: 'ward',\r\n level: 'warn',\r\n category: 'egress',\r\n message: `Blocked egress: ${effectiveMatches.map(m => m.pattern.name).join(', ')}`,\r\n data: {\r\n connector,\r\n destination,\r\n patternNames: effectiveMatches.map(m => m.pattern.name),\r\n },\r\n })\r\n } catch {\r\n // Database operation failed - continue without persistence\r\n }\r\n }\r\n\r\n return result\r\n }\r\n\r\n /**\r\n * Check if connector/destination combination is fully allowlisted\r\n */\r\n private isAllowlisted(connector?: string, destination?: string): boolean {\r\n return this.allowlist.some(entry => {\r\n // Skip pattern-specific entries (they don't allowlist all inspection)\r\n if (entry.pattern) return false\r\n\r\n // Check connector match\r\n if (entry.connector && entry.destination) {\r\n // Both specified - must match both\r\n return entry.connector === connector && entry.destination === destination\r\n }\r\n\r\n if (entry.connector) {\r\n return entry.connector === connector\r\n }\r\n\r\n if (entry.destination) {\r\n return entry.destination === destination\r\n }\r\n\r\n return false\r\n })\r\n }\r\n\r\n /**\r\n * Check if a specific pattern is allowlisted for the connector/destination\r\n */\r\n private isPatternAllowlisted(\r\n patternName: string,\r\n connector?: string,\r\n destination?: string\r\n ): boolean {\r\n return this.allowlist.some(entry => {\r\n // Only check pattern-specific entries\r\n if (!entry.pattern || entry.pattern !== patternName) return false\r\n\r\n // Check connector/destination match\r\n if (entry.connector && entry.destination) {\r\n return entry.connector === connector && entry.destination === destination\r\n }\r\n\r\n if (entry.connector) {\r\n return entry.connector === connector\r\n }\r\n\r\n if (entry.destination) {\r\n return entry.destination === destination\r\n }\r\n\r\n // Pattern allowlist with no connector/destination matches all\r\n return true\r\n })\r\n }\r\n\r\n /**\r\n * Add an allowlist entry\r\n */\r\n addAllowlistEntry(entry: EgressAllowlistEntry): void {\r\n this.allowlist.push(entry)\r\n }\r\n\r\n /**\r\n * Add a custom pattern\r\n */\r\n addPattern(pattern: EgressPattern): void {\r\n this.matcher.addPattern(pattern)\r\n }\r\n\r\n /**\r\n * Get pending blocks from database\r\n */\r\n getPendingBlocks(): EgressMatch[] {\r\n if (!this.db) return []\r\n try {\r\n return this.db.getPendingBlocks()\r\n } catch {\r\n return []\r\n }\r\n }\r\n\r\n /**\r\n * Approve a pending block\r\n */\r\n approveBlock(id: string, approvedBy?: string): void {\r\n if (!this.db) return\r\n try {\r\n this.db.approveBlock(id, approvedBy ?? 'system')\r\n } catch {\r\n // Database operation failed\r\n }\r\n }\r\n\r\n /**\r\n * Deny a pending block\r\n */\r\n denyBlock(id: string): void {\r\n if (!this.db) return\r\n try {\r\n this.db.denyBlock(id, 'system')\r\n } catch {\r\n // Database operation failed\r\n }\r\n }\r\n\r\n /**\r\n * Test content without recording to database\r\n * Useful for CLI testing of patterns\r\n */\r\n test(content: string): {\r\n blocked: boolean\r\n matches: PatternMatch[]\r\n redacted: string\r\n } {\r\n const matches = this.matcher.match(content)\r\n const shouldBlock = matches.some(m => m.pattern.action === 'block')\r\n\r\n // Redact content\r\n let redacted = content\r\n if (matches.length > 0) {\r\n const sortedMatches = [...matches].sort((a, b) => b.index - a.index)\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n }\r\n\r\n return {\r\n blocked: shouldBlock,\r\n matches,\r\n redacted,\r\n }\r\n }\r\n}\r\n","import chalk from 'chalk'\r\nimport { readFileSync, writeFileSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { BashBros } from './core.js'\r\nimport { findConfig } from './config.js'\r\nimport { allowForSession } from './session.js'\r\nimport { DashboardWriter } from './dashboard/writer.js'\r\nimport { RiskScorer, type RiskScore } from './policy/risk-scorer.js'\r\n\r\n// Dashboard writer and risk scorer for monitoring\r\nlet dashboardWriter: DashboardWriter | null = null\r\nlet riskScorer: RiskScorer | null = null\r\n\r\nfunction cleanup(): void {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(false)\r\n }\r\n}\r\n\r\nexport async function startWatch(options: { verbose?: boolean }): Promise<void> {\r\n const configPath = findConfig()\r\n\r\n if (!configPath) {\r\n console.log(chalk.red('No config found. Run \"bashbros init\" first.'))\r\n process.exit(1)\r\n }\r\n\r\n console.log(chalk.dim(' \"I watch your agent\\'s back so you don\\'t have to.\"'))\r\n console.log()\r\n console.log(chalk.green('✓'), 'Protection active')\r\n console.log(chalk.dim(` Config: ${configPath}`))\r\n console.log(chalk.dim(' Press Ctrl+C to stop'))\r\n console.log()\r\n\r\n const bashbros = new BashBros(configPath)\r\n const config = bashbros.getConfig()\r\n\r\n // Initialize dashboard writer and risk scorer\r\n try {\r\n dashboardWriter = new DashboardWriter()\r\n riskScorer = new RiskScorer()\r\n\r\n // Start a new session\r\n const sessionId = dashboardWriter.startSession(config.agent, process.cwd())\r\n if (options.verbose) {\r\n console.log(chalk.dim(` Session: ${sessionId}`))\r\n }\r\n } catch (error) {\r\n // Dashboard writing is non-critical, continue without it\r\n if (options.verbose) {\r\n console.log(chalk.yellow(' Dashboard recording disabled'))\r\n }\r\n }\r\n\r\n // State for interactive prompt when command is blocked\r\n let pendingCommand: string | null = null\r\n let awaitingPromptResponse = false\r\n\r\n function showBlockedPrompt(command: string, violations: { message: string; rule: string }[]): void {\r\n pendingCommand = command\r\n awaitingPromptResponse = true\r\n\r\n console.log()\r\n console.log(chalk.red('🛡️ BashBros blocked a command'))\r\n console.log()\r\n console.log(chalk.dim(' Command:'), command)\r\n console.log(chalk.dim(' Reason:'), violations[0].message)\r\n console.log(chalk.dim(' Policy:'), violations[0].rule)\r\n console.log()\r\n console.log(chalk.yellow(' Allow this command?'))\r\n console.log(chalk.cyan(' [y]'), 'Allow once')\r\n console.log(chalk.cyan(' [s]'), 'Allow for session')\r\n console.log(chalk.cyan(' [p]'), 'Allow permanently')\r\n console.log(chalk.cyan(' [n]'), 'Block (default)')\r\n process.stdout.write(chalk.dim('\\n Choice: '))\r\n }\r\n\r\n function handlePromptResponse(choice: string): void {\r\n if (!pendingCommand) return\r\n\r\n const command = pendingCommand\r\n pendingCommand = null\r\n awaitingPromptResponse = false\r\n\r\n console.log(choice) // Echo the choice\r\n\r\n switch (choice.toLowerCase()) {\r\n case 'y':\r\n // Allow once - just execute, no persistence\r\n console.log(chalk.green(' ✓ Allowed once'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n break\r\n\r\n case 's':\r\n // Allow for session\r\n allowForSession(command)\r\n console.log(chalk.green(' ✓ Allowed for session'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n break\r\n\r\n case 'p':\r\n // Allow permanently - update config file\r\n try {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n\r\n if (!config.commands) {\r\n config.commands = { allow: [], block: [] }\r\n }\r\n if (!config.commands.allow) {\r\n config.commands.allow = []\r\n }\r\n\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n }\r\n\r\n console.log(chalk.green(' ✓ Added to allowlist permanently'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n } catch (error) {\r\n console.log(chalk.red(' ✗ Failed to update config'))\r\n console.log()\r\n }\r\n break\r\n\r\n case 'n':\r\n default:\r\n // Keep blocked\r\n console.log(chalk.yellow(' ✗ Blocked'))\r\n console.log()\r\n break\r\n }\r\n }\r\n\r\n bashbros.on('blocked', (command, violations) => {\r\n // Record blocked command to dashboard\r\n if (dashboardWriter && riskScorer) {\r\n const risk = riskScorer.score(command)\r\n dashboardWriter.recordCommand(command, false, risk, violations, 0)\r\n }\r\n showBlockedPrompt(command, violations)\r\n })\r\n\r\n bashbros.on('allowed', (result) => {\r\n // Record allowed command to dashboard\r\n if (dashboardWriter && riskScorer) {\r\n const risk = riskScorer.score(result.command)\r\n dashboardWriter.recordCommand(result.command, true, risk, [], result.duration)\r\n }\r\n if (options.verbose) {\r\n console.log(chalk.green('✓'), chalk.dim(result.command))\r\n }\r\n })\r\n\r\n bashbros.on('output', (data) => {\r\n process.stdout.write(data)\r\n })\r\n\r\n bashbros.on('error', (error) => {\r\n console.error(chalk.red('Error:'), error.message)\r\n })\r\n\r\n // Handle PTY exit\r\n bashbros.on('exit', (exitCode) => {\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n cleanup()\r\n process.exit(exitCode ?? 0)\r\n })\r\n\r\n // Handle graceful shutdown\r\n process.on('SIGINT', () => {\r\n cleanup()\r\n console.log()\r\n console.log(chalk.yellow('Stopping BashBros...'))\r\n\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n bashbros.stop()\r\n process.exit(0)\r\n })\r\n\r\n process.on('SIGTERM', () => {\r\n cleanup()\r\n\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n bashbros.stop()\r\n process.exit(0)\r\n })\r\n\r\n // Handle unexpected crashes\r\n process.on('uncaughtException', (error) => {\r\n console.error(chalk.red('Unexpected error:'), error.message)\r\n\r\n // Mark session as crashed\r\n if (dashboardWriter) {\r\n dashboardWriter.crashSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n cleanup()\r\n bashbros.stop()\r\n process.exit(1)\r\n })\r\n\r\n bashbros.start()\r\n\r\n // Command buffer for validation\r\n let commandBuffer = ''\r\n\r\n // Set initial PTY size to match terminal\r\n if (process.stdout.isTTY) {\r\n bashbros.resize(process.stdout.columns, process.stdout.rows)\r\n }\r\n\r\n // Handle terminal resize\r\n process.stdout.on('resize', () => {\r\n if (process.stdout.isTTY) {\r\n bashbros.resize(process.stdout.columns, process.stdout.rows)\r\n }\r\n })\r\n\r\n // Enable raw mode for character-by-character input\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(true)\r\n }\r\n process.stdin.resume()\r\n\r\n // Handle stdin with command interception\r\n process.stdin.on('data', (data) => {\r\n const str = data.toString()\r\n\r\n for (const char of str) {\r\n const code = char.charCodeAt(0)\r\n\r\n // If awaiting prompt response, handle it separately\r\n if (awaitingPromptResponse) {\r\n if (code === 3) {\r\n // Ctrl+C cancels the prompt\r\n pendingCommand = null\r\n awaitingPromptResponse = false\r\n console.log(chalk.yellow('Cancelled'))\r\n console.log()\r\n } else if (char === '\\r' || char === '\\n') {\r\n // Enter with no choice = block (default)\r\n handlePromptResponse('n')\r\n } else if (code >= 32) {\r\n // Letter response\r\n handlePromptResponse(char)\r\n }\r\n continue\r\n }\r\n\r\n // Enter key - validate command before allowing execution\r\n if (char === '\\r' || char === '\\n') {\r\n const command = commandBuffer.trim()\r\n commandBuffer = ''\r\n\r\n if (command) {\r\n // Validate the command (don't use execute() - command is already in PTY buffer)\r\n const violations = bashbros.validateOnly(command)\r\n\r\n if (violations.length > 0) {\r\n // Blocked - clear the line and emit blocked event\r\n bashbros.write('\\x15') // Ctrl+U to clear line\r\n bashbros.write('\\r') // New line\r\n bashbros.emit('blocked', command, violations)\r\n } else {\r\n // Allowed - just send Enter to execute the already-typed command\r\n bashbros.write('\\r')\r\n }\r\n } else {\r\n // Empty command (just Enter) - pass through\r\n bashbros.write('\\r')\r\n }\r\n }\r\n // Backspace/Delete - remove from buffer\r\n else if (code === 127 || code === 8) {\r\n if (commandBuffer.length > 0) {\r\n commandBuffer = commandBuffer.slice(0, -1)\r\n }\r\n bashbros.write(char)\r\n }\r\n // Escape sequence start\r\n else if (code === 27) {\r\n // Pass through escape sequences\r\n bashbros.write(char)\r\n }\r\n // Ctrl+C - clear buffer\r\n else if (code === 3) {\r\n commandBuffer = ''\r\n bashbros.write(char)\r\n }\r\n // Ctrl+U (clear line)\r\n else if (code === 21) {\r\n commandBuffer = ''\r\n bashbros.write(char)\r\n }\r\n // Regular character - add to buffer and forward\r\n else if (code >= 32 || char === '\\t') {\r\n commandBuffer += char\r\n bashbros.write(char)\r\n }\r\n // Other control characters - pass through\r\n else {\r\n bashbros.write(char)\r\n }\r\n }\r\n })\r\n\r\n // Keep process alive\r\n await new Promise(() => {})\r\n}\r\n","/**\r\n * Dashboard Writer Module\r\n * Bridge for watch mode to write monitoring data to the dashboard database\r\n */\r\n\r\nimport { homedir } from 'os'\r\nimport { join } from 'path'\r\nimport { mkdirSync, existsSync } from 'fs'\r\nimport { DashboardDB, type InsertCommandInput, type InsertBroEventInput, type InsertBroStatusInput } from './db.js'\r\nimport type { RiskScore } from '../policy/risk-scorer.js'\r\nimport type { PolicyViolation } from '../types.js'\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Types\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport interface BroEventInput {\r\n eventType: string\r\n inputContext: string\r\n outputSummary: string\r\n modelUsed: string\r\n latencyMs: number\r\n success: boolean\r\n}\r\n\r\nexport interface BroStatusInput {\r\n ollamaAvailable: boolean\r\n ollamaModel: string\r\n platform: string\r\n shell: string\r\n projectType?: string\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Default Database Path\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nfunction getDefaultDbPath(): string {\r\n const bashbrosDir = join(homedir(), '.bashbros')\r\n\r\n // Ensure directory exists\r\n if (!existsSync(bashbrosDir)) {\r\n mkdirSync(bashbrosDir, { recursive: true })\r\n }\r\n\r\n return join(bashbrosDir, 'dashboard.db')\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Dashboard Writer Class\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport class DashboardWriter {\r\n private db: DashboardDB\r\n private sessionId: string | null = null\r\n private commandCount: number = 0\r\n private blockedCount: number = 0\r\n private totalRiskScore: number = 0\r\n\r\n constructor(dbPath?: string) {\r\n const path = dbPath ?? getDefaultDbPath()\r\n this.db = new DashboardDB(path)\r\n }\r\n\r\n /**\r\n * Start a new watch session\r\n */\r\n startSession(agent: string, workingDir: string): string {\r\n this.sessionId = this.db.insertSession({\r\n agent,\r\n pid: process.pid,\r\n workingDir\r\n })\r\n\r\n this.commandCount = 0\r\n this.blockedCount = 0\r\n this.totalRiskScore = 0\r\n\r\n return this.sessionId\r\n }\r\n\r\n /**\r\n * End the current session\r\n */\r\n endSession(): void {\r\n if (!this.sessionId) return\r\n\r\n const avgRiskScore = this.commandCount > 0\r\n ? this.totalRiskScore / this.commandCount\r\n : 0\r\n\r\n this.db.updateSession(this.sessionId, {\r\n endTime: new Date(),\r\n status: 'completed',\r\n commandCount: this.commandCount,\r\n blockedCount: this.blockedCount,\r\n avgRiskScore\r\n })\r\n\r\n this.sessionId = null\r\n }\r\n\r\n /**\r\n * Mark session as crashed (for unexpected exits)\r\n */\r\n crashSession(): void {\r\n if (!this.sessionId) return\r\n\r\n const avgRiskScore = this.commandCount > 0\r\n ? this.totalRiskScore / this.commandCount\r\n : 0\r\n\r\n this.db.updateSession(this.sessionId, {\r\n endTime: new Date(),\r\n status: 'crashed',\r\n commandCount: this.commandCount,\r\n blockedCount: this.blockedCount,\r\n avgRiskScore\r\n })\r\n\r\n this.sessionId = null\r\n }\r\n\r\n /**\r\n * Record a command execution\r\n */\r\n recordCommand(\r\n command: string,\r\n allowed: boolean,\r\n riskScore: RiskScore,\r\n violations: PolicyViolation[],\r\n durationMs: number\r\n ): string | null {\r\n if (!this.sessionId) return null\r\n\r\n const input: InsertCommandInput = {\r\n sessionId: this.sessionId,\r\n command,\r\n allowed,\r\n riskScore: riskScore.score,\r\n riskLevel: riskScore.level,\r\n riskFactors: riskScore.factors,\r\n durationMs,\r\n violations: violations.map(v => v.message)\r\n }\r\n\r\n const id = this.db.insertCommand(input)\r\n\r\n // Update session stats\r\n this.commandCount++\r\n this.totalRiskScore += riskScore.score\r\n if (!allowed) {\r\n this.blockedCount++\r\n }\r\n\r\n // Update session in DB periodically (every 10 commands)\r\n if (this.commandCount % 10 === 0) {\r\n const avgRiskScore = this.totalRiskScore / this.commandCount\r\n this.db.updateSession(this.sessionId, {\r\n commandCount: this.commandCount,\r\n blockedCount: this.blockedCount,\r\n avgRiskScore\r\n })\r\n }\r\n\r\n return id\r\n }\r\n\r\n /**\r\n * Record a Bash Bro AI event\r\n */\r\n recordBroEvent(input: BroEventInput): string {\r\n const dbInput: InsertBroEventInput = {\r\n sessionId: this.sessionId ?? undefined,\r\n eventType: input.eventType,\r\n inputContext: input.inputContext,\r\n outputSummary: input.outputSummary,\r\n modelUsed: input.modelUsed,\r\n latencyMs: input.latencyMs,\r\n success: input.success\r\n }\r\n\r\n return this.db.insertBroEvent(dbInput)\r\n }\r\n\r\n /**\r\n * Update Bash Bro status\r\n */\r\n updateBroStatus(status: BroStatusInput): string {\r\n const dbInput: InsertBroStatusInput = {\r\n ollamaAvailable: status.ollamaAvailable,\r\n ollamaModel: status.ollamaModel,\r\n platform: status.platform,\r\n shell: status.shell,\r\n projectType: status.projectType\r\n }\r\n\r\n return this.db.updateBroStatus(dbInput)\r\n }\r\n\r\n /**\r\n * Get current session ID\r\n */\r\n getSessionId(): string | null {\r\n return this.sessionId\r\n }\r\n\r\n /**\r\n * Get current session stats\r\n */\r\n getSessionStats(): {\r\n commandCount: number\r\n blockedCount: number\r\n avgRiskScore: number\r\n } {\r\n return {\r\n commandCount: this.commandCount,\r\n blockedCount: this.blockedCount,\r\n avgRiskScore: this.commandCount > 0 ? this.totalRiskScore / this.commandCount : 0\r\n }\r\n }\r\n\r\n /**\r\n * Close database connection\r\n */\r\n close(): void {\r\n this.db.close()\r\n }\r\n\r\n /**\r\n * Get the underlying database instance (for advanced use)\r\n */\r\n getDB(): DashboardDB {\r\n return this.db\r\n }\r\n}\r\n\r\nexport default DashboardWriter\r\n","import chalk from 'chalk'\r\nimport { readFileSync, writeFileSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { findConfig } from './config.js'\r\nimport { allowForSession, getSessionAllowlist, clearSessionAllowlist } from './session.js'\r\n\r\nexport async function handleAllow(\r\n command: string,\r\n options: { once?: boolean; persist?: boolean }\r\n): Promise<void> {\r\n if (options.once) {\r\n // Add to session allowlist\r\n allowForSession(command)\r\n console.log(chalk.green('✓'), `Allowed for this session: ${command}`)\r\n console.log(chalk.dim(' This will reset when BashBros restarts.'))\r\n return\r\n }\r\n\r\n if (options.persist) {\r\n const configPath = findConfig()\r\n\r\n if (!configPath) {\r\n console.log(chalk.red('No config found. Run \"bashbros init\" first.'))\r\n process.exit(1)\r\n }\r\n\r\n try {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n\r\n // Initialize commands.allow if it doesn't exist\r\n if (!config.commands) {\r\n config.commands = { allow: [], block: [] }\r\n }\r\n if (!config.commands.allow) {\r\n config.commands.allow = []\r\n }\r\n\r\n // Add command pattern if not already present\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n\r\n console.log(chalk.green('✓'), `Added to allowlist: ${command}`)\r\n console.log(chalk.dim(` Updated ${configPath}`))\r\n } else {\r\n console.log(chalk.yellow('Already in allowlist:'), command)\r\n }\r\n } catch (error) {\r\n console.error(chalk.red('Failed to update config:'), error)\r\n process.exit(1)\r\n }\r\n\r\n return\r\n }\r\n\r\n // No flag specified - show help\r\n console.log(chalk.yellow('Specify how to allow this command:'))\r\n console.log()\r\n console.log(chalk.cyan(` bashbros allow \"${command}\" --once`))\r\n console.log(chalk.dim(' Allow for current session only'))\r\n console.log()\r\n console.log(chalk.cyan(` bashbros allow \"${command}\" --persist`))\r\n console.log(chalk.dim(' Add to config file permanently'))\r\n}\r\n","/**\r\n * Dashboard Server Module\r\n * Express HTTP server with WebSocket support for real-time dashboard updates\r\n */\r\n\r\nimport express, { type Express, type Request, type Response } from 'express'\r\nimport { WebSocketServer, type WebSocket } from 'ws'\r\nimport { createServer, type Server } from 'http'\r\nimport { fileURLToPath } from 'url'\r\nimport { dirname, join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { DashboardDB } from './db.js'\r\nimport { findConfig } from '../config.js'\r\n\r\n// Default dashboard database path\r\nfunction getDefaultDbPath(): string {\r\n const bashbrosDir = join(homedir(), '.bashbros')\r\n if (!existsSync(bashbrosDir)) {\r\n mkdirSync(bashbrosDir, { recursive: true })\r\n }\r\n return join(bashbrosDir, 'dashboard.db')\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Types\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport interface ServerConfig {\r\n port?: number\r\n bind?: string\r\n dbPath?: string\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Dashboard Server Class\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport class DashboardServer {\r\n private app: Express\r\n private server: Server | null = null\r\n private wss: WebSocketServer | null = null\r\n private db: DashboardDB\r\n private port: number\r\n private bind: string\r\n private clients: Set<WebSocket> = new Set()\r\n\r\n constructor(config: ServerConfig = {}) {\r\n this.port = config.port ?? 17800\r\n this.bind = config.bind ?? '127.0.0.1'\r\n // Use persistent database path by default for shared access with watch mode\r\n this.db = new DashboardDB(config.dbPath ?? getDefaultDbPath())\r\n this.app = express()\r\n\r\n this.setupMiddleware()\r\n this.setupRoutes()\r\n }\r\n\r\n private setupMiddleware(): void {\r\n this.app.use(express.json())\r\n\r\n // CORS headers for local development\r\n this.app.use((_req: Request, res: Response, next) => {\r\n res.header('Access-Control-Allow-Origin', '*')\r\n res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\r\n res.header('Access-Control-Allow-Headers', 'Content-Type')\r\n next()\r\n })\r\n }\r\n\r\n private setupRoutes(): void {\r\n // Health check endpoint\r\n this.app.get('/api/health', (_req: Request, res: Response) => {\r\n res.json({ status: 'ok', timestamp: new Date().toISOString() })\r\n })\r\n\r\n // Get dashboard stats\r\n this.app.get('/api/stats', (_req: Request, res: Response) => {\r\n try {\r\n const stats = this.db.getStats()\r\n res.json(stats)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch stats' })\r\n }\r\n })\r\n\r\n // Get events with optional filtering\r\n this.app.get('/api/events', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.source) filter.source = req.query.source\r\n if (req.query.level) filter.level = req.query.level\r\n if (req.query.category) filter.category = req.query.category\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n\r\n const events = this.db.getEvents(filter)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch events' })\r\n }\r\n })\r\n\r\n // Get unique connectors\r\n this.app.get('/api/connectors', (_req: Request, res: Response) => {\r\n try {\r\n // Get all connector events and extract unique connector names\r\n const events = this.db.getAllConnectorEvents(1000)\r\n const connectors = [...new Set(events.map(e => e.connector))]\r\n res.json(connectors)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch connectors' })\r\n }\r\n })\r\n\r\n // Get events for a specific connector\r\n this.app.get('/api/connectors/:name/events', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const events = this.db.getConnectorEvents(req.params.name, limit)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch connector events' })\r\n }\r\n })\r\n\r\n // Get pending egress blocks\r\n this.app.get('/api/blocked', (_req: Request, res: Response) => {\r\n try {\r\n const blocks = this.db.getPendingBlocks()\r\n res.json(blocks)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch blocked items' })\r\n }\r\n })\r\n\r\n // Approve a blocked egress\r\n this.app.post('/api/blocked/:id/approve', (req: Request, res: Response) => {\r\n try {\r\n const { id } = req.params\r\n const approvedBy = req.body?.approvedBy ?? 'dashboard-user'\r\n\r\n const block = this.db.getBlock(id)\r\n if (!block) {\r\n res.status(404).json({ error: 'Block not found' })\r\n return\r\n }\r\n\r\n this.db.approveBlock(id, approvedBy)\r\n this.broadcast({ type: 'block-approved', id })\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to approve block' })\r\n }\r\n })\r\n\r\n // Deny a blocked egress\r\n this.app.post('/api/blocked/:id/deny', (req: Request, res: Response) => {\r\n try {\r\n const { id } = req.params\r\n const deniedBy = req.body?.deniedBy ?? 'dashboard-user'\r\n\r\n const block = this.db.getBlock(id)\r\n if (!block) {\r\n res.status(404).json({ error: 'Block not found' })\r\n return\r\n }\r\n\r\n this.db.denyBlock(id, deniedBy)\r\n this.broadcast({ type: 'block-denied', id })\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to deny block' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Session Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // List sessions with pagination and filters\r\n this.app.get('/api/sessions', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.status) filter.status = req.query.status\r\n if (req.query.agent) filter.agent = req.query.agent\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n if (req.query.until) filter.until = new Date(req.query.until as string)\r\n\r\n const sessions = this.db.getSessions(filter)\r\n res.json(sessions)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch sessions' })\r\n }\r\n })\r\n\r\n // Get active session\r\n this.app.get('/api/sessions/active', (_req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getActiveSession()\r\n if (!session) {\r\n res.json(null)\r\n return\r\n }\r\n res.json(session)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch active session' })\r\n }\r\n })\r\n\r\n // Get session details\r\n this.app.get('/api/sessions/:id', (req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getSession(req.params.id)\r\n if (!session) {\r\n res.status(404).json({ error: 'Session not found' })\r\n return\r\n }\r\n res.json(session)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session' })\r\n }\r\n })\r\n\r\n // Get commands for a session\r\n this.app.get('/api/sessions/:id/commands', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const commands = this.db.getCommandsBySession(req.params.id, limit)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session commands' })\r\n }\r\n })\r\n\r\n // Get session metrics\r\n this.app.get('/api/sessions/:id/metrics', (req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getSession(req.params.id)\r\n if (!session) {\r\n res.status(404).json({ error: 'Session not found' })\r\n return\r\n }\r\n const metrics = this.db.getSessionMetrics(req.params.id)\r\n res.json(metrics)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session metrics' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Command Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get live commands (most recent)\r\n this.app.get('/api/commands/live', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 20\r\n const commands = this.db.getLiveCommands(limit)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch live commands' })\r\n }\r\n })\r\n\r\n // Get commands with incremental fetch support\r\n this.app.get('/api/commands', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.sessionId) filter.sessionId = req.query.sessionId\r\n if (req.query.allowed !== undefined) filter.allowed = req.query.allowed === 'true'\r\n if (req.query.riskLevel) filter.riskLevel = req.query.riskLevel\r\n if (req.query.afterId) filter.afterId = req.query.afterId\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n\r\n const commands = this.db.getCommands(filter)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch commands' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Bash Bro Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get Bash Bro status\r\n this.app.get('/api/bro/status', (_req: Request, res: Response) => {\r\n try {\r\n const status = this.db.getLatestBroStatus()\r\n res.json(status)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch Bro status' })\r\n }\r\n })\r\n\r\n // Get Bash Bro events\r\n this.app.get('/api/bro/events', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const sessionId = req.query.sessionId as string | undefined\r\n const events = this.db.getBroEvents(limit, sessionId)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch Bro events' })\r\n }\r\n })\r\n\r\n // Get available Ollama models\r\n this.app.get('/api/bro/models', async (_req: Request, res: Response) => {\r\n try {\r\n // Try to fetch models from Ollama\r\n const controller = new AbortController()\r\n const timeout = setTimeout(() => controller.abort(), 5000)\r\n\r\n const response = await fetch('http://localhost:11434/api/tags', {\r\n signal: controller.signal\r\n })\r\n\r\n clearTimeout(timeout)\r\n\r\n if (!response.ok) {\r\n res.json({ available: false, models: [] })\r\n return\r\n }\r\n\r\n const data = await response.json() as { models?: { name: string }[] }\r\n const models = data.models?.map((m) => m.name) || []\r\n res.json({ available: true, models })\r\n } catch (error) {\r\n res.json({ available: false, models: [] })\r\n }\r\n })\r\n\r\n // Change Ollama model (writes to a control file that watch mode can pick up)\r\n this.app.post('/api/bro/model', (req: Request, res: Response) => {\r\n try {\r\n const { model } = req.body\r\n if (!model) {\r\n res.status(400).json({ error: 'Model name required' })\r\n return\r\n }\r\n\r\n // Write to control file in .bashbros directory\r\n const controlPath = join(homedir(), '.bashbros', 'model-control.json')\r\n writeFileSync(controlPath, JSON.stringify({\r\n model,\r\n timestamp: new Date().toISOString()\r\n }), 'utf-8')\r\n\r\n res.json({ success: true, model })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to change model' })\r\n }\r\n })\r\n\r\n // Trigger system scan (writes control file)\r\n this.app.post('/api/bro/scan', (_req: Request, res: Response) => {\r\n try {\r\n const controlPath = join(homedir(), '.bashbros', 'scan-control.json')\r\n writeFileSync(controlPath, JSON.stringify({\r\n action: 'scan',\r\n timestamp: new Date().toISOString()\r\n }), 'utf-8')\r\n\r\n res.json({ success: true, message: 'Scan requested' })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to trigger scan' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Exposure Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get recent exposures\r\n this.app.get('/api/exposures', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const exposures = this.db.getRecentExposures(limit)\r\n res.json(exposures)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch exposures' })\r\n }\r\n })\r\n\r\n // Get config\r\n this.app.get('/api/config', (_req: Request, res: Response) => {\r\n try {\r\n const configPath = findConfig()\r\n if (!configPath) {\r\n res.status(404).json({ error: 'No config file found' })\r\n return\r\n }\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n res.json(config)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to load config' })\r\n }\r\n })\r\n\r\n // Save config\r\n this.app.post('/api/config', (req: Request, res: Response) => {\r\n try {\r\n const configPath = findConfig()\r\n if (!configPath) {\r\n res.status(404).json({ error: 'No config file found' })\r\n return\r\n }\r\n const config = req.body\r\n const content = stringify(config)\r\n writeFileSync(configPath, content, 'utf-8')\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to save config' })\r\n }\r\n })\r\n\r\n // Static file serving - resolve relative to this file\r\n const __filename = fileURLToPath(import.meta.url)\r\n const __dirname = dirname(__filename)\r\n const staticPath = join(__dirname, 'static')\r\n this.app.use(express.static(staticPath))\r\n\r\n // Fallback to index.html for SPA routing (Express 5 path-to-regexp syntax)\r\n this.app.get('/{*path}', (_req: Request, res: Response) => {\r\n res.sendFile(join(staticPath, 'index.html'))\r\n })\r\n }\r\n\r\n private setupWebSocket(): void {\r\n if (!this.server) return\r\n\r\n this.wss = new WebSocketServer({ server: this.server })\r\n\r\n this.wss.on('connection', (ws: WebSocket) => {\r\n this.clients.add(ws)\r\n\r\n ws.on('close', () => {\r\n this.clients.delete(ws)\r\n })\r\n\r\n ws.on('error', () => {\r\n this.clients.delete(ws)\r\n })\r\n\r\n // Send initial stats on connection\r\n try {\r\n const stats = this.db.getStats()\r\n ws.send(JSON.stringify({ type: 'stats', data: stats }))\r\n } catch {\r\n // Ignore errors on initial send\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * Start the dashboard server\r\n */\r\n async start(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n this.server = createServer(this.app)\r\n this.setupWebSocket()\r\n\r\n this.server.on('error', (error: NodeJS.ErrnoException) => {\r\n if (error.code === 'EADDRINUSE') {\r\n reject(new Error(`Port ${this.port} is already in use`))\r\n } else {\r\n reject(error)\r\n }\r\n })\r\n\r\n this.server.listen(this.port, this.bind, () => {\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Stop the dashboard server\r\n */\r\n async stop(): Promise<void> {\r\n return new Promise((resolve) => {\r\n // Close all WebSocket connections\r\n for (const client of this.clients) {\r\n client.close()\r\n }\r\n this.clients.clear()\r\n\r\n if (this.wss) {\r\n this.wss.close()\r\n this.wss = null\r\n }\r\n\r\n if (this.server) {\r\n this.server.close(() => {\r\n this.server = null\r\n this.db.close()\r\n resolve()\r\n })\r\n } else {\r\n this.db.close()\r\n resolve()\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * Broadcast a message to all connected WebSocket clients\r\n */\r\n broadcast(message: unknown): void {\r\n const data = JSON.stringify(message)\r\n for (const client of this.clients) {\r\n if (client.readyState === 1) { // WebSocket.OPEN\r\n client.send(data)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the database instance for external use\r\n */\r\n getDB(): DashboardDB {\r\n return this.db\r\n }\r\n\r\n /**\r\n * Get the port the server is running on\r\n */\r\n getPort(): number {\r\n return this.port\r\n }\r\n}\r\n\r\nexport default DashboardServer\r\n"],"mappings":"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","names":["chalk","chalk","existsSync","join","homedir","existsSync","join","homedir","join","homedir","existsSync","MoltbotHooks","existsSync","platform","DashboardDB","MoltbotHooks","chalk","join","homedir","existsSync","chalk","readFileSync","writeFileSync","stringify","homedir","join","mkdirSync","existsSync","join","homedir","existsSync","mkdirSync","chalk","readFileSync","config","writeFileSync","stringify","chalk","readFileSync","writeFileSync","parse","stringify","chalk","readFileSync","parse","writeFileSync","stringify","join","homedir","readFileSync","writeFileSync","existsSync","mkdirSync","parse","stringify","getDefaultDbPath","join","homedir","existsSync","mkdirSync","writeFileSync","readFileSync","parse","stringify","chalk","writeFileSync","formatAgentInfo","parseAgentConfig","allowForSession","readFileSync","parse","stringify","findConfig"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/onboarding.ts","../src/doctor.ts","../src/transparency/agent-config.ts","../src/policy/ward/exposure.ts","../src/policy/ward/patterns.ts","../src/policy/ward/egress.ts","../src/watch.ts","../src/allow.ts","../src/dashboard/server.ts"],"sourcesContent":["import { Command } from 'commander'\r\nimport chalk from 'chalk'\r\nimport { runOnboarding } from './onboarding.js'\r\nimport { runDoctor } from './doctor.js'\r\nimport { startWatch } from './watch.js'\r\nimport { handleAllow } from './allow.js'\r\nimport { BashBro } from './bro/bro.js'\r\nimport { ClaudeCodeHooks, gateCommand } from './hooks/claude-code.js'\r\nimport { MoltbotHooks } from './hooks/moltbot.js'\r\nimport { RiskScorer } from './policy/risk-scorer.js'\r\nimport { MetricsCollector } from './observability/metrics.js'\r\nimport {\r\n getAllAgentConfigs,\r\n getAgentConfigInfo,\r\n formatRedactedConfig\r\n} from './transparency/index.js'\r\nimport {\r\n formatAllAgentsInfo,\r\n formatPermissionsTable,\r\n getEffectivePermissions\r\n} from './transparency/display.js'\r\nimport { CostEstimator } from './observability/cost.js'\r\nimport { ReportGenerator } from './observability/report.js'\r\nimport { UndoStack } from './safety/undo-stack.js'\r\nimport { LoopDetector } from './policy/loop-detector.js'\r\nimport { DashboardServer } from './dashboard/index.js'\r\nimport { ExposureScanner, EgressMonitor, EgressPatternMatcher } from './policy/ward/index.js'\r\n\r\n// Shared state for session tracking\r\nlet metricsCollector: MetricsCollector | null = null\r\nlet costEstimator: CostEstimator | null = null\r\nlet loopDetector: LoopDetector | null = null\r\nlet undoStack: UndoStack | null = null\r\n\r\nconst logo = `\r\n ╱BashBros ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n 🤝 Your Friendly Bash Agent Helper\r\n`\r\n\r\nconst program = new Command()\r\n\r\nprogram\r\n .name('bashbros')\r\n .description('The Bash Agent Helper')\r\n .version('0.1.0')\r\n\r\nprogram\r\n .command('init')\r\n .description('Set up BashBros for your project')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n await runOnboarding()\r\n })\r\n\r\nprogram\r\n .command('watch')\r\n .description('Start protecting your agent')\r\n .option('-v, --verbose', 'Show all commands as they run')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n await startWatch(options)\r\n })\r\n\r\nprogram\r\n .command('doctor')\r\n .description('Check your BashBros configuration')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n await runDoctor()\r\n })\r\n\r\nprogram\r\n .command('allow <command>')\r\n .description('Allow a specific command')\r\n .option('--once', 'Allow only for current session')\r\n .option('--persist', 'Add to config permanently')\r\n .action(async (command, options) => {\r\n await handleAllow(command, options)\r\n })\r\n\r\nprogram\r\n .command('audit')\r\n .description('View recent command history')\r\n .option('-n, --lines <number>', 'Number of lines to show', '50')\r\n .option('--violations', 'Show only blocked commands')\r\n .action(async (options) => {\r\n const { viewAudit } = await import('./audit.js')\r\n await viewAudit(options)\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Bash Bro Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('scan')\r\n .description('Scan your system and project environment')\r\n .option('-p, --project <path>', 'Project path to scan', '.')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Scanning your environment...\\n'))\r\n\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (options.project) {\r\n bro.scanProject(options.project)\r\n }\r\n\r\n console.log(bro.getSystemContext())\r\n console.log()\r\n\r\n // Add Agent Configurations section\r\n console.log(chalk.bold('\\n## Agent Configurations\\n'))\r\n const { formatAgentSummary } = await import('./transparency/display.js')\r\n const agents = await getAllAgentConfigs()\r\n console.log(formatAgentSummary(agents))\r\n console.log()\r\n\r\n console.log(chalk.green('✓'), 'System profile saved to ~/.bashbros/system-profile.json')\r\n })\r\n\r\nprogram\r\n .command('status')\r\n .alias('bro')\r\n .description('Show Bash Bro status and system info')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n console.log(bro.status())\r\n })\r\n\r\nprogram\r\n .command('suggest')\r\n .description('Get command suggestions based on context')\r\n .option('-c, --command <cmd>', 'Last command for context')\r\n .option('-e, --error <msg>', 'Last error message')\r\n .action(async (options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n const suggestions = bro.suggest({\r\n lastCommand: options.command,\r\n lastError: options.error,\r\n cwd: process.cwd()\r\n })\r\n\r\n if (suggestions.length === 0) {\r\n console.log(chalk.dim('No suggestions available.'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Bash Bro suggests:\\n'))\r\n for (const s of suggestions) {\r\n const confidence = Math.round(s.confidence * 100)\r\n console.log(` ${chalk.cyan(s.command)}`)\r\n console.log(chalk.dim(` ${s.description} (${confidence}% confidence)`))\r\n console.log()\r\n }\r\n })\r\n\r\nprogram\r\n .command('route <command>')\r\n .description('Check how a command would be routed')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n const result = bro.route(command)\r\n const icon = result.decision === 'bro' ? '🤝' : result.decision === 'main' ? '🤖' : '⚡'\r\n const label = result.decision === 'bro' ? 'Bash Bro' : result.decision === 'main' ? 'Main Agent' : 'Both (parallel)'\r\n\r\n console.log()\r\n console.log(`${icon} Route: ${chalk.bold(label)}`)\r\n console.log(chalk.dim(` Reason: ${result.reason}`))\r\n console.log(chalk.dim(` Confidence: ${Math.round(result.confidence * 100)}%`))\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('run <command>')\r\n .description('Run a command through Bash Bro')\r\n .option('-b, --background', 'Run in background')\r\n .action(async (command, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (options.background) {\r\n const task = bro.runBackground(command)\r\n console.log(chalk.green('✓'), `Started background task: ${task.id}`)\r\n console.log(chalk.dim(` Command: ${command}`))\r\n console.log(chalk.dim(` Run 'bashbros tasks' to check status`))\r\n } else {\r\n console.log(chalk.dim(`🤝 Bash Bro executing: ${command}\\n`))\r\n const output = await bro.execute(command)\r\n console.log(output)\r\n }\r\n })\r\n\r\nprogram\r\n .command('tasks')\r\n .description('List background tasks')\r\n .option('-a, --all', 'Show all tasks (not just running)')\r\n .action(async (options) => {\r\n const bro = new BashBro()\r\n\r\n const tasks = options.all\r\n ? bro.getBackgroundTasks()\r\n : bro.getBackgroundTasks().filter(t => t.status === 'running')\r\n\r\n if (tasks.length === 0) {\r\n console.log(chalk.dim('No background tasks.'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Background Tasks:\\n'))\r\n for (const task of tasks) {\r\n const elapsed = Math.round((Date.now() - task.startTime.getTime()) / 1000)\r\n const statusIcon = task.status === 'running' ? '⏳' :\r\n task.status === 'completed' ? '✓' :\r\n task.status === 'failed' ? '✗' : '○'\r\n\r\n console.log(` ${statusIcon} [${task.id}] ${task.command}`)\r\n console.log(chalk.dim(` Status: ${task.status}, Elapsed: ${elapsed}s`))\r\n console.log()\r\n }\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// AI Commands (requires Ollama)\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('explain <command>')\r\n .description('Ask Bash Bro to explain a command')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is thinking...\\n'))\r\n const explanation = await bro.aiExplain(command)\r\n console.log(explanation)\r\n })\r\n\r\nprogram\r\n .command('fix <command>')\r\n .description('Ask Bash Bro to fix a failed command')\r\n .option('-e, --error <message>', 'Error message from the failed command')\r\n .action(async (command, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n const error = options.error || 'Command failed'\r\n console.log(chalk.dim('🤝 Bash Bro is analyzing...\\n'))\r\n\r\n const fixed = await bro.aiFix(command, error)\r\n\r\n if (fixed) {\r\n console.log(chalk.green('Suggested fix:'))\r\n console.log(chalk.cyan(` ${fixed}`))\r\n } else {\r\n console.log(chalk.yellow('Could not suggest a fix.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('ai <prompt>')\r\n .description('Ask Bash Bro anything')\r\n .action(async (prompt) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is thinking...\\n'))\r\n const suggestion = await bro.aiSuggest(prompt)\r\n\r\n if (suggestion) {\r\n console.log(chalk.cyan(suggestion))\r\n } else {\r\n console.log(chalk.dim('No suggestion available.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('script <description>')\r\n .description('Generate a shell script from description')\r\n .option('-o, --output <file>', 'Save script to file')\r\n .action(async (description, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is generating script...\\n'))\r\n const script = await bro.aiGenerateScript(description)\r\n\r\n if (script) {\r\n console.log(chalk.cyan(script))\r\n\r\n if (options.output) {\r\n const { writeFileSync } = await import('fs')\r\n writeFileSync(options.output, script, { mode: 0o755 })\r\n console.log(chalk.green(`\\n✓ Saved to ${options.output}`))\r\n }\r\n } else {\r\n console.log(chalk.yellow('Could not generate script.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('safety <command>')\r\n .description('Analyze a command for security risks')\r\n .action(async (command) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is analyzing...\\n'))\r\n const analysis = await bro.aiAnalyzeSafety(command)\r\n\r\n const riskColors = {\r\n low: chalk.green,\r\n medium: chalk.yellow,\r\n high: chalk.red,\r\n critical: chalk.bgRed.white\r\n }\r\n\r\n const icon = analysis.safe ? '✓' : '⚠'\r\n const color = riskColors[analysis.risk]\r\n\r\n console.log(`${icon} Risk Level: ${color(analysis.risk.toUpperCase())}`)\r\n console.log()\r\n console.log(chalk.bold('Explanation:'))\r\n console.log(` ${analysis.explanation}`)\r\n\r\n if (analysis.suggestions.length > 0) {\r\n console.log()\r\n console.log(chalk.bold('Suggestions:'))\r\n for (const suggestion of analysis.suggestions) {\r\n console.log(` • ${suggestion}`)\r\n }\r\n }\r\n })\r\n\r\nprogram\r\n .command('help-ai <topic>')\r\n .alias('h')\r\n .description('Get AI help for a command or topic')\r\n .action(async (topic) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is looking that up...\\n'))\r\n const help = await bro.aiHelp(topic)\r\n console.log(help)\r\n })\r\n\r\nprogram\r\n .command('do <description>')\r\n .description('Convert natural language to a command')\r\n .option('-x, --execute', 'Execute the command after showing it')\r\n .action(async (description, options) => {\r\n const bro = new BashBro()\r\n await bro.initialize()\r\n\r\n if (!bro.isOllamaAvailable()) {\r\n console.log(chalk.yellow('Ollama not available. Start Ollama to use AI features.'))\r\n return\r\n }\r\n\r\n console.log(chalk.dim('🤝 Bash Bro is translating...\\n'))\r\n const command = await bro.aiToCommand(description)\r\n\r\n if (command) {\r\n console.log(chalk.bold('Command:'))\r\n console.log(chalk.cyan(` $ ${command}`))\r\n\r\n if (options.execute) {\r\n console.log()\r\n console.log(chalk.dim('Executing...'))\r\n const output = await bro.execute(command)\r\n console.log(output)\r\n }\r\n } else {\r\n console.log(chalk.yellow('Could not translate to a command.'))\r\n }\r\n })\r\n\r\nprogram\r\n .command('models')\r\n .description('List available Ollama models')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const { OllamaClient } = await import('./bro/ollama.js')\r\n const ollama = new OllamaClient()\r\n\r\n const available = await ollama.isAvailable()\r\n if (!available) {\r\n console.log(chalk.yellow('Ollama not running. Start Ollama to see available models.'))\r\n return\r\n }\r\n\r\n const models = await ollama.listModels()\r\n\r\n if (models.length === 0) {\r\n console.log(chalk.dim('No models installed. Run: ollama pull qwen2.5-coder:7b'))\r\n return\r\n }\r\n\r\n console.log(chalk.bold('🤝 Available Models:\\n'))\r\n for (const model of models) {\r\n const current = model === ollama.getModel() ? chalk.green(' (current)') : ''\r\n console.log(` • ${model}${current}`)\r\n }\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Hook & Observability Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst hookCmd = program\r\n .command('hook')\r\n .description('Manage Claude Code hook integration')\r\n\r\nhookCmd\r\n .command('install')\r\n .description('Install BashBros hooks into Claude Code')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.install()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nhookCmd\r\n .command('uninstall')\r\n .description('Remove BashBros hooks from Claude Code')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.uninstall()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nhookCmd\r\n .command('status')\r\n .description('Check Claude Code hook status')\r\n .action(() => {\r\n const status = ClaudeCodeHooks.getStatus()\r\n console.log()\r\n console.log(chalk.bold('Claude Code Integration Status'))\r\n console.log()\r\n console.log(` Claude Code: ${status.claudeInstalled ? chalk.green('installed') : chalk.yellow('not found')}`)\r\n console.log(` BashBros hooks: ${status.hooksInstalled ? chalk.green('active') : chalk.dim('not installed')}`)\r\n console.log(` All-tools recording: ${status.allToolsInstalled ? chalk.green('active') : chalk.dim('not installed')}`)\r\n if (status.hooks.length > 0) {\r\n console.log(` Active hooks: ${status.hooks.join(', ')}`)\r\n }\r\n console.log()\r\n })\r\n\r\nhookCmd\r\n .command('install-all-tools')\r\n .description('Install hook to record ALL Claude Code tool uses (not just Bash)')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.installAllTools()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nhookCmd\r\n .command('uninstall-all-tools')\r\n .description('Remove all-tools recording hook')\r\n .action(() => {\r\n const result = ClaudeCodeHooks.uninstallAllTools()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Moltbot Integration Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst moltbotCmd = program\r\n .command('moltbot')\r\n .alias('clawdbot')\r\n .description('Manage Moltbot/Clawdbot integration')\r\n\r\nmoltbotCmd\r\n .command('install')\r\n .description('Install BashBros hooks into Moltbot')\r\n .action(() => {\r\n const result = MoltbotHooks.install()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nmoltbotCmd\r\n .command('uninstall')\r\n .description('Remove BashBros hooks from Moltbot')\r\n .action(() => {\r\n const result = MoltbotHooks.uninstall()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nmoltbotCmd\r\n .command('status')\r\n .description('Check Moltbot integration status')\r\n .action(async () => {\r\n const status = MoltbotHooks.getStatus()\r\n console.log()\r\n console.log(chalk.bold('Moltbot Integration Status'))\r\n console.log()\r\n\r\n // Installation status\r\n if (status.moltbotInstalled) {\r\n console.log(` Moltbot: ${chalk.green('installed')}`)\r\n } else if (status.clawdbotInstalled) {\r\n console.log(` Clawdbot: ${chalk.green('installed')} ${chalk.dim('(legacy)')}`)\r\n } else {\r\n console.log(` Moltbot: ${chalk.yellow('not found')}`)\r\n }\r\n\r\n // Config status\r\n if (status.configPath) {\r\n console.log(` Config: ${chalk.green(status.configPath)}`)\r\n } else {\r\n console.log(` Config: ${chalk.dim('not found')}`)\r\n }\r\n\r\n // Hooks status\r\n console.log(` BashBros hooks: ${status.hooksInstalled ? chalk.green('active') : chalk.dim('not installed')}`)\r\n if (status.hooks.length > 0) {\r\n console.log(` Active hooks: ${status.hooks.join(', ')}`)\r\n }\r\n\r\n // Sandbox mode\r\n if (status.sandboxMode) {\r\n const sandboxColor = status.sandboxMode === 'strict' ? chalk.green : chalk.yellow\r\n console.log(` Sandbox mode: ${sandboxColor(status.sandboxMode)}`)\r\n }\r\n\r\n console.log()\r\n })\r\n\r\nmoltbotCmd\r\n .command('gateway')\r\n .description('Check Moltbot gateway status')\r\n .action(async () => {\r\n console.log()\r\n console.log(chalk.bold('Moltbot Gateway Status'))\r\n console.log()\r\n\r\n const gatewayStatus = await MoltbotHooks.getGatewayStatus()\r\n\r\n if (gatewayStatus.running) {\r\n console.log(` Status: ${chalk.green('running')}`)\r\n console.log(` Host: ${gatewayStatus.host}`)\r\n console.log(` Port: ${gatewayStatus.port}`)\r\n console.log(` Sandbox: ${gatewayStatus.sandboxMode ? chalk.green('enabled') : chalk.yellow('disabled')}`)\r\n } else {\r\n console.log(` Status: ${chalk.yellow('not running')}`)\r\n console.log(` Expected: ${gatewayStatus.host}:${gatewayStatus.port}`)\r\n if (gatewayStatus.error) {\r\n console.log(` Error: ${chalk.dim(gatewayStatus.error)}`)\r\n }\r\n }\r\n\r\n console.log()\r\n })\r\n\r\nmoltbotCmd\r\n .command('audit')\r\n .description('Run Moltbot security audit')\r\n .option('--json', 'Output as JSON')\r\n .action(async (options) => {\r\n console.log(chalk.dim('Running security audit...\\n'))\r\n\r\n const result = await MoltbotHooks.runSecurityAudit()\r\n\r\n if (options.json) {\r\n console.log(JSON.stringify(result, null, 2))\r\n return\r\n }\r\n\r\n // Display results\r\n const statusIcon = result.passed ? chalk.green('✓') : chalk.red('✗')\r\n const statusText = result.passed ? chalk.green('PASSED') : chalk.red('FAILED')\r\n\r\n console.log(`${statusIcon} Security Audit: ${statusText}`)\r\n console.log()\r\n\r\n if (result.findings.length === 0) {\r\n console.log(chalk.dim(' No findings.'))\r\n } else {\r\n const severityColors: Record<string, (s: string) => string> = {\r\n critical: chalk.bgRed.white,\r\n warning: chalk.yellow,\r\n info: chalk.dim\r\n }\r\n\r\n for (const finding of result.findings) {\r\n const color = severityColors[finding.severity] || chalk.white\r\n console.log(` ${color(`[${finding.severity.toUpperCase()}]`)} ${finding.message}`)\r\n console.log(chalk.dim(` Category: ${finding.category}`))\r\n if (finding.recommendation) {\r\n console.log(chalk.dim(` Fix: ${finding.recommendation}`))\r\n }\r\n console.log()\r\n }\r\n }\r\n\r\n console.log(chalk.dim(`Audit completed at ${result.timestamp.toLocaleString()}`))\r\n console.log()\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Agent Transparency Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nprogram\r\n .command('agent-info [agent]')\r\n .description('Show detailed info about installed agents and their configurations')\r\n .option('-r, --raw', 'Show raw (redacted) config contents')\r\n .action(async (agent, options) => {\r\n console.log(chalk.cyan(logo))\r\n\r\n if (agent) {\r\n // Show specific agent\r\n const validAgents = ['claude-code', 'moltbot', 'clawdbot', 'aider', 'gemini-cli', 'opencode']\r\n if (!validAgents.includes(agent)) {\r\n console.log(chalk.red(`Unknown agent: ${agent}`))\r\n console.log(chalk.dim(`Valid agents: ${validAgents.join(', ')}`))\r\n return\r\n }\r\n\r\n const info = await getAgentConfigInfo(agent as any)\r\n const { formatAgentInfo } = await import('./transparency/display.js')\r\n console.log()\r\n console.log(formatAgentInfo(info))\r\n\r\n // Show raw config if requested\r\n if (options.raw && info.configExists && info.configPath) {\r\n const { parseAgentConfig } = await import('./transparency/config-parser.js')\r\n const parsed = await parseAgentConfig(agent as any, info.configPath)\r\n if (parsed?.rawRedacted) {\r\n console.log()\r\n console.log(chalk.bold('Configuration (sensitive data redacted):'))\r\n console.log(formatRedactedConfig(parsed.rawRedacted))\r\n }\r\n }\r\n } else {\r\n // Show all agents\r\n const agents = await getAllAgentConfigs()\r\n console.log()\r\n console.log(formatAllAgentsInfo(agents))\r\n }\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('permissions')\r\n .description('Show combined permissions view across bashbros and agents')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n\r\n const agents = await getAllAgentConfigs()\r\n const installed = agents.filter(a => a.installed)\r\n\r\n if (installed.length === 0) {\r\n console.log(chalk.yellow('No agents installed to compare permissions with.'))\r\n console.log(chalk.dim('Install an agent (claude, aider, etc.) to see combined permissions.'))\r\n return\r\n }\r\n\r\n console.log()\r\n console.log(formatPermissionsTable(agents))\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('gate <command>')\r\n .description('Check if a command should be allowed (used by hooks)')\r\n .option('-y, --yes', 'Skip interactive prompt and block')\r\n .action(async (command, options) => {\r\n const result = await gateCommand(command)\r\n\r\n if (!result.allowed) {\r\n // If stdin is a TTY and not skipping prompt, ask user\r\n if (process.stdin.isTTY && !options.yes) {\r\n const { allowForSession } = await import('./session.js')\r\n const { readFileSync, writeFileSync } = await import('fs')\r\n const { parse, stringify } = await import('yaml')\r\n const { findConfig } = await import('./config.js')\r\n\r\n console.error()\r\n console.error(chalk.red('🛡️ BashBros blocked a command'))\r\n console.error()\r\n console.error(chalk.dim(' Command:'), command)\r\n console.error(chalk.dim(' Reason:'), result.reason)\r\n console.error()\r\n console.error(chalk.yellow(' Allow this command?'))\r\n console.error(chalk.cyan(' [y]'), 'Allow once')\r\n console.error(chalk.cyan(' [s]'), 'Allow for session')\r\n console.error(chalk.cyan(' [p]'), 'Allow permanently')\r\n console.error(chalk.cyan(' [n]'), 'Block (default)')\r\n process.stderr.write(chalk.dim('\\n Choice: '))\r\n\r\n // Read single character from stdin\r\n const choice = await new Promise<string>((resolve) => {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(true)\r\n }\r\n process.stdin.resume()\r\n process.stdin.once('data', (data) => {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(false)\r\n }\r\n const char = data.toString().toLowerCase()\r\n console.error(char)\r\n resolve(char)\r\n })\r\n })\r\n\r\n switch (choice) {\r\n case 'y':\r\n console.error(chalk.green(' ✓ Allowed once'))\r\n process.exit(0)\r\n break\r\n\r\n case 's':\r\n allowForSession(command)\r\n console.error(chalk.green(' ✓ Allowed for session'))\r\n process.exit(0)\r\n break\r\n\r\n case 'p':\r\n try {\r\n const configPath = findConfig()\r\n if (configPath) {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n if (!config.commands) config.commands = { allow: [], block: [] }\r\n if (!config.commands.allow) config.commands.allow = []\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n }\r\n console.error(chalk.green(' ✓ Added to allowlist permanently'))\r\n process.exit(0)\r\n }\r\n } catch {\r\n console.error(chalk.red(' ✗ Failed to update config'))\r\n }\r\n process.exit(2)\r\n break\r\n\r\n default:\r\n console.error(chalk.yellow(' ✗ Blocked'))\r\n process.exit(2)\r\n }\r\n } else {\r\n // Clean, minimal output for non-interactive use (hooks)\r\n console.error(`Blocked: ${result.reason}`)\r\n process.exit(2)\r\n }\r\n }\r\n\r\n // Silently allow\r\n process.exit(0)\r\n })\r\n\r\nprogram\r\n .command('record-tool')\r\n .description('Record a Claude Code tool execution (used by hooks)')\r\n .option('--marker <marker>', 'Hook marker (ignored, used for identification)')\r\n .action(async () => {\r\n // Read JSON from CLAUDE_HOOK_EVENT environment variable\r\n const eventJson = process.env.CLAUDE_HOOK_EVENT || ''\r\n\r\n if (!eventJson) {\r\n // Silent exit - no event data\r\n return\r\n }\r\n\r\n try {\r\n const event = JSON.parse(eventJson)\r\n const events = Array.isArray(event) ? event : [event]\r\n\r\n const { DashboardWriter } = await import('./dashboard/writer.js')\r\n const writer = new DashboardWriter()\r\n\r\n for (const evt of events) {\r\n const toolName = evt.tool_name || evt.tool || 'unknown'\r\n const toolInput = evt.tool_input || evt.input || {}\r\n const toolOutput = evt.tool_output || evt.output || ''\r\n\r\n // Extract command/input based on tool type\r\n let inputStr: string\r\n if (typeof toolInput === 'string') {\r\n inputStr = toolInput\r\n } else if (typeof toolInput === 'object') {\r\n inputStr = JSON.stringify(toolInput, null, 2)\r\n } else {\r\n inputStr = String(toolInput)\r\n }\r\n\r\n // Extract output\r\n let outputStr: string\r\n let exitCode: number | null = null\r\n let success: boolean | null = null\r\n\r\n if (typeof toolOutput === 'object' && toolOutput !== null) {\r\n outputStr = (toolOutput.stdout || '') + (toolOutput.stderr || '')\r\n exitCode = toolOutput.exit_code ?? toolOutput.exitCode ?? null\r\n if (exitCode !== null) {\r\n success = exitCode === 0\r\n }\r\n } else {\r\n outputStr = String(toolOutput || '')\r\n }\r\n\r\n // Get repo info if available\r\n const repoName = evt.repo?.name ?? null\r\n const repoPath = evt.repo?.path ?? null\r\n\r\n writer.recordToolUse({\r\n toolName,\r\n toolInput: inputStr,\r\n toolOutput: outputStr,\r\n exitCode,\r\n success,\r\n cwd: evt.cwd || process.cwd(),\r\n repoName,\r\n repoPath\r\n })\r\n\r\n // Minimal output for hook\r\n const preview = inputStr.substring(0, 40).replace(/\\n/g, ' ')\r\n console.log(`[BashBros] ${toolName}: ${preview}${inputStr.length > 40 ? '...' : ''}`)\r\n }\r\n\r\n writer.close()\r\n } catch (e) {\r\n // Silent fail for hooks\r\n console.error(`[BashBros] Error recording tool: ${e instanceof Error ? e.message : e}`)\r\n }\r\n })\r\n\r\nprogram\r\n .command('record <command>')\r\n .description('Record a command execution (used by hooks)')\r\n .option('-o, --output <output>', 'Command output')\r\n .option('-e, --exit-code <code>', 'Exit code', '0')\r\n .action(async (command, options) => {\r\n // Initialize collectors if needed\r\n if (!metricsCollector) metricsCollector = new MetricsCollector()\r\n if (!costEstimator) costEstimator = new CostEstimator()\r\n if (!loopDetector) loopDetector = new LoopDetector()\r\n if (!undoStack) undoStack = new UndoStack()\r\n\r\n const scorer = new RiskScorer()\r\n const risk = scorer.score(command)\r\n\r\n // Record metrics\r\n metricsCollector.record({\r\n command,\r\n timestamp: new Date(),\r\n duration: 0, // Not available in hook\r\n allowed: true,\r\n riskScore: risk,\r\n violations: [],\r\n exitCode: parseInt(options.exitCode) || 0\r\n })\r\n\r\n // Record for cost estimation\r\n costEstimator.recordToolCall(command, options.output || '')\r\n\r\n // Check for loops\r\n const loopAlert = loopDetector.check(command)\r\n if (loopAlert) {\r\n console.error(chalk.yellow(`⚠ Loop detected: ${loopAlert.message}`))\r\n }\r\n\r\n // Track file changes for undo\r\n const paths = command.match(/(?:^|\\s)(\\.\\/|\\.\\.\\/|\\/|~\\/)[^\\s]+/g) || []\r\n const cleanPaths = paths.map((p: string) => p.trim())\r\n if (cleanPaths.length > 0) {\r\n undoStack.recordFromCommand(command, cleanPaths)\r\n }\r\n })\r\n\r\nprogram\r\n .command('session-end')\r\n .description('Generate session report (used by hooks)')\r\n .option('-f, --format <format>', 'Output format (text, markdown, json)', 'text')\r\n .action((options) => {\r\n if (!metricsCollector) {\r\n console.log(chalk.dim('No session data to report.'))\r\n return\r\n }\r\n\r\n const metrics = metricsCollector.getMetrics()\r\n const cost = costEstimator?.getEstimate()\r\n const report = ReportGenerator.generate(metrics, cost, { format: options.format })\r\n\r\n console.log()\r\n console.log(report)\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('report')\r\n .description('Generate a session report')\r\n .option('-f, --format <format>', 'Output format (text, markdown, json)', 'text')\r\n .option('--no-cost', 'Hide cost estimate')\r\n .option('--no-risk', 'Hide risk distribution')\r\n .action((options) => {\r\n if (!metricsCollector) {\r\n console.log(chalk.dim('No session data. Run some commands first.'))\r\n return\r\n }\r\n\r\n const metrics = metricsCollector.getMetrics()\r\n const cost = options.cost ? costEstimator?.getEstimate() : undefined\r\n const report = ReportGenerator.generate(metrics, cost, {\r\n format: options.format,\r\n showCost: options.cost,\r\n showRisk: options.risk\r\n })\r\n\r\n console.log()\r\n console.log(report)\r\n console.log()\r\n })\r\n\r\nprogram\r\n .command('risk <command>')\r\n .description('Score a command for security risk')\r\n .action((command) => {\r\n const scorer = new RiskScorer()\r\n const result = scorer.score(command)\r\n\r\n const colors: Record<string, (s: string) => string> = {\r\n safe: chalk.green,\r\n caution: chalk.yellow,\r\n dangerous: chalk.red,\r\n critical: chalk.bgRed.white\r\n }\r\n\r\n const color = colors[result.level]\r\n\r\n console.log()\r\n console.log(` Risk Score: ${color(`${result.score}/10`)} (${color(result.level.toUpperCase())})`)\r\n console.log()\r\n console.log(chalk.bold(' Factors:'))\r\n for (const factor of result.factors) {\r\n console.log(` • ${factor}`)\r\n }\r\n console.log()\r\n })\r\n\r\nconst undoCmd = program\r\n .command('undo')\r\n .description('Undo file operations')\r\n\r\nundoCmd\r\n .command('last')\r\n .alias('pop')\r\n .description('Undo the last file operation')\r\n .action(() => {\r\n if (!undoStack) {\r\n console.log(chalk.dim('No operations to undo.'))\r\n return\r\n }\r\n\r\n const result = undoStack.undo()\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n }\r\n })\r\n\r\nundoCmd\r\n .command('all')\r\n .description('Undo all file operations in session')\r\n .action(() => {\r\n if (!undoStack || undoStack.size() === 0) {\r\n console.log(chalk.dim('No operations to undo.'))\r\n return\r\n }\r\n\r\n const results = undoStack.undoAll()\r\n let success = 0, failed = 0\r\n\r\n for (const result of results) {\r\n if (result.success) {\r\n console.log(chalk.green('✓'), result.message)\r\n success++\r\n } else {\r\n console.log(chalk.red('✗'), result.message)\r\n failed++\r\n }\r\n }\r\n\r\n console.log()\r\n console.log(`Undone: ${success} successful, ${failed} failed`)\r\n })\r\n\r\nundoCmd\r\n .command('list')\r\n .description('Show undo stack')\r\n .action(() => {\r\n if (!undoStack) {\r\n undoStack = new UndoStack()\r\n }\r\n\r\n console.log()\r\n console.log(undoStack.formatStack())\r\n console.log()\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Dashboard Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nlet dashboardServer: DashboardServer | null = null\r\n\r\nprogram\r\n .command('dashboard')\r\n .description('Start the BashBros dashboard')\r\n .option('-p, --port <port>', 'Port to run on', '7890')\r\n .option('-b, --bind <address>', 'Address to bind to', '127.0.0.1')\r\n .action(async (options) => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Starting dashboard...\\n'))\r\n\r\n dashboardServer = new DashboardServer({\r\n port: parseInt(options.port),\r\n bind: options.bind\r\n })\r\n\r\n await dashboardServer.start()\r\n console.log(chalk.green('✓'), `Dashboard running at http://${options.bind}:${options.port}`)\r\n console.log(chalk.dim(' Press Ctrl+C to stop'))\r\n\r\n // Keep process alive\r\n process.on('SIGINT', async () => {\r\n console.log(chalk.dim('\\n Stopping dashboard...'))\r\n await dashboardServer?.stop()\r\n process.exit(0)\r\n })\r\n })\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Ward Commands\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nconst wardCmd = program\r\n .command('ward')\r\n .description('Network and connector security')\r\n\r\nwardCmd\r\n .command('status')\r\n .description('Show ward security status')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.bold('Ward Security Status\\n'))\r\n\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green('✓'), 'No exposed agent servers detected')\r\n } else {\r\n console.log(chalk.yellow('⚠'), `Found ${results.length} exposure(s):\\n`)\r\n for (const r of results) {\r\n const color = r.severity === 'critical' ? chalk.bgRed.white :\r\n r.severity === 'high' ? chalk.red :\r\n r.severity === 'medium' ? chalk.yellow :\r\n chalk.dim\r\n console.log(` ${color(r.severity.toUpperCase().padEnd(8))} ${r.message}`)\r\n }\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('scan')\r\n .description('Run exposure scan')\r\n .action(async () => {\r\n console.log(chalk.cyan(logo))\r\n console.log(chalk.dim(' Scanning for exposed agent servers...\\n'))\r\n\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green('✓'), 'No exposed agent servers detected')\r\n } else {\r\n for (const r of results) {\r\n const icon = r.severity === 'critical' ? '🚨' :\r\n r.severity === 'high' ? '⚠️' :\r\n r.severity === 'medium' ? '⚡' : 'ℹ️'\r\n\r\n console.log(`${icon} ${r.agent}`)\r\n console.log(chalk.dim(` Port: ${r.port}`))\r\n console.log(chalk.dim(` Bind: ${r.bindAddress}`))\r\n console.log(chalk.dim(` Auth: ${r.hasAuth}`))\r\n console.log(chalk.dim(` Severity: ${r.severity}`))\r\n console.log(chalk.dim(` Action: ${r.action}`))\r\n console.log()\r\n }\r\n }\r\n })\r\n\r\nconst exposureCmd = wardCmd\r\n .command('exposure')\r\n .description('Exposure scanner commands')\r\n\r\nexposureCmd\r\n .command('list')\r\n .description('List monitored agents')\r\n .action(() => {\r\n const scanner = new ExposureScanner()\r\n const agents = scanner.getAgents()\r\n\r\n console.log(chalk.bold('\\nMonitored Agent Signatures:\\n'))\r\n for (const agent of agents) {\r\n console.log(` ${chalk.cyan(agent.name)}`)\r\n console.log(chalk.dim(` Processes: ${agent.processNames.join(', ')}`))\r\n console.log(chalk.dim(` Ports: ${agent.defaultPorts.join(', ')}`))\r\n console.log()\r\n }\r\n })\r\n\r\nexposureCmd\r\n .command('scan')\r\n .description('Run immediate exposure scan')\r\n .action(async () => {\r\n const scanner = new ExposureScanner()\r\n const results = await scanner.scan()\r\n\r\n console.log(chalk.bold('\\nExposure Scan Results:\\n'))\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.green(' ✓ No exposures detected'))\r\n } else {\r\n for (const r of results) {\r\n const color = r.severity === 'critical' ? chalk.bgRed.white :\r\n r.severity === 'high' ? chalk.red :\r\n r.severity === 'medium' ? chalk.yellow : chalk.green\r\n console.log(` ${color(r.severity.toUpperCase().padEnd(10))} ${r.message}`)\r\n }\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('blocked')\r\n .description('Show pending blocked egress items')\r\n .action(() => {\r\n const monitor = new EgressMonitor()\r\n const pending = monitor.getPendingBlocks()\r\n\r\n console.log(chalk.bold('\\nPending Egress Blocks:\\n'))\r\n\r\n if (pending.length === 0) {\r\n console.log(chalk.dim(' No pending blocks'))\r\n } else {\r\n for (const block of pending) {\r\n const severityColor = block.pattern.severity === 'critical' ? chalk.bgRed.white :\r\n block.pattern.severity === 'high' ? chalk.red :\r\n block.pattern.severity === 'medium' ? chalk.yellow : chalk.dim\r\n console.log(` ${chalk.cyan(block.id)} ${severityColor(block.pattern.severity.toUpperCase())}`)\r\n console.log(chalk.dim(` Pattern: ${block.pattern.name} (${block.pattern.category})`))\r\n console.log(chalk.dim(` Matched: ${block.matchedText.substring(0, 50)}${block.matchedText.length > 50 ? '...' : ''}`))\r\n if (block.connector) console.log(chalk.dim(` Connector: ${block.connector}`))\r\n if (block.destination) console.log(chalk.dim(` Destination: ${block.destination}`))\r\n console.log()\r\n }\r\n console.log(chalk.dim(` Use 'bashbros ward approve <id>' or 'bashbros ward deny <id>' to resolve`))\r\n }\r\n console.log()\r\n })\r\n\r\nwardCmd\r\n .command('approve <id>')\r\n .description('Approve a blocked egress item')\r\n .option('--by <name>', 'Name of approver', 'user')\r\n .action((id, options) => {\r\n const monitor = new EgressMonitor()\r\n monitor.approveBlock(id, options.by)\r\n console.log(chalk.green('✓'), `Approved block ${id}`)\r\n })\r\n\r\nwardCmd\r\n .command('deny <id>')\r\n .description('Deny a blocked egress item')\r\n .action((id) => {\r\n const monitor = new EgressMonitor()\r\n monitor.denyBlock(id)\r\n console.log(chalk.green('✓'), `Denied block ${id}`)\r\n })\r\n\r\nconst patternsCmd = wardCmd\r\n .command('patterns')\r\n .description('Egress pattern detection commands')\r\n\r\npatternsCmd\r\n .command('list')\r\n .description('List active detection patterns')\r\n .option('--category <cat>', 'Filter by category (credentials, pii)')\r\n .action((options) => {\r\n const matcher = new EgressPatternMatcher()\r\n let patterns = matcher.getPatterns()\r\n\r\n if (options.category) {\r\n patterns = patterns.filter(p => p.category === options.category)\r\n }\r\n\r\n console.log(chalk.bold('\\nActive Egress Patterns:\\n'))\r\n\r\n const byCategory: Record<string, typeof patterns> = {}\r\n for (const p of patterns) {\r\n const cat = p.category\r\n if (!byCategory[cat]) byCategory[cat] = []\r\n byCategory[cat].push(p)\r\n }\r\n\r\n for (const [category, categoryPatterns] of Object.entries(byCategory)) {\r\n console.log(chalk.cyan(` ${category.toUpperCase()}`))\r\n for (const p of categoryPatterns) {\r\n const severityColor = p.severity === 'critical' ? chalk.red :\r\n p.severity === 'high' ? chalk.yellow :\r\n p.severity === 'medium' ? chalk.blue : chalk.dim\r\n const actionColor = p.action === 'block' ? chalk.red :\r\n p.action === 'alert' ? chalk.yellow : chalk.dim\r\n console.log(` ${chalk.bold(p.name.padEnd(16))} ${severityColor(p.severity.padEnd(10))} ${actionColor(p.action.padEnd(6))} ${p.description}`)\r\n }\r\n console.log()\r\n }\r\n })\r\n\r\npatternsCmd\r\n .command('test <text>')\r\n .description('Test if text matches any detection pattern')\r\n .action((text) => {\r\n const monitor = new EgressMonitor()\r\n const result = monitor.test(text)\r\n\r\n console.log(chalk.bold('\\nPattern Test Results:\\n'))\r\n\r\n if (result.matches.length === 0) {\r\n console.log(chalk.green(' ✓ No patterns matched'))\r\n } else {\r\n console.log(` ${result.blocked ? chalk.red('WOULD BLOCK') : chalk.yellow('WOULD ALERT')}`)\r\n console.log()\r\n console.log(chalk.bold(' Matches:'))\r\n for (const m of result.matches) {\r\n const severityColor = m.pattern.severity === 'critical' ? chalk.red :\r\n m.pattern.severity === 'high' ? chalk.yellow :\r\n m.pattern.severity === 'medium' ? chalk.blue : chalk.dim\r\n console.log(` ${chalk.cyan(m.pattern.name)} ${severityColor(`[${m.pattern.severity}]`)} - \"${m.matchedText.substring(0, 30)}${m.matchedText.length > 30 ? '...' : ''}\"`)\r\n }\r\n console.log()\r\n console.log(chalk.bold(' Redacted output:'))\r\n console.log(chalk.dim(` ${result.redacted.substring(0, 100)}${result.redacted.length > 100 ? '...' : ''}`))\r\n }\r\n console.log()\r\n })\r\n\r\nprogram.parse()\r\n","import inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { writeFileSync, existsSync, mkdirSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { stringify } from 'yaml'\r\nimport type { BashBrosConfig, AgentType, SecurityProfile } from './types.js'\r\nimport { getDefaultConfig } from './config.js'\r\nimport { getBashgymIntegration } from './integration/bashgym.js'\r\n\r\nexport async function runOnboarding(): Promise<void> {\r\n console.log(chalk.dim(' \"I watch your agent\\'s back so you don\\'t have to.\"\\n'))\r\n\r\n // Check if bashgym integration is available\r\n const bashgymAvailable = existsSync(join(homedir(), '.bashgym', 'integration'))\r\n\r\n const questions: any[] = [\r\n {\r\n type: 'list',\r\n name: 'agent',\r\n message: 'What agent are you protecting?',\r\n choices: [\r\n { name: 'Claude Code', value: 'claude-code' },\r\n { name: 'Moltbot (clawd.bot)', value: 'moltbot' },\r\n { name: 'Clawdbot (legacy)', value: 'clawdbot' },\r\n { name: 'Gemini CLI', value: 'gemini-cli' },\r\n { name: 'Aider', value: 'aider' },\r\n { name: 'OpenCode', value: 'opencode' },\r\n { name: 'Other (custom)', value: 'custom' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'projectType',\r\n message: \"What's this project about? (helps tune defaults)\",\r\n choices: [\r\n { name: 'Web development', value: 'web' },\r\n { name: 'DevOps / Infrastructure', value: 'devops' },\r\n { name: 'Data engineering', value: 'data' },\r\n { name: 'General coding', value: 'general' },\r\n { name: 'Sensitive/regulated work', value: 'sensitive' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'profile',\r\n message: 'Security posture:',\r\n choices: [\r\n {\r\n name: 'Balanced (recommended) - Block dangerous, allow common dev tools',\r\n value: 'balanced'\r\n },\r\n {\r\n name: 'Strict - Allowlist only, explicit approval for new commands',\r\n value: 'strict'\r\n },\r\n {\r\n name: 'Permissive - Log everything, block only critical threats',\r\n value: 'permissive'\r\n },\r\n {\r\n name: \"Custom - I'll configure manually\",\r\n value: 'custom'\r\n }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'secrets',\r\n message: 'Protect secrets? (scans for .env, credentials, SSH keys)',\r\n choices: [\r\n { name: 'Yes, block access and warn (recommended)', value: 'block' },\r\n { name: 'Yes, but allow read with audit log', value: 'audit' },\r\n { name: 'No', value: 'disabled' }\r\n ]\r\n },\r\n {\r\n type: 'list',\r\n name: 'audit',\r\n message: 'Enable audit logging?',\r\n choices: [\r\n { name: 'Local file (~/.bashbros/audit.log)', value: 'local' },\r\n { name: 'Send to remote (Datadog, Splunk, webhook)', value: 'remote' },\r\n { name: 'Both', value: 'both' },\r\n { name: 'None', value: 'disabled' }\r\n ]\r\n }\r\n ]\r\n\r\n // Add bashgym integration question if available\r\n if (bashgymAvailable) {\r\n questions.push({\r\n type: 'list',\r\n name: 'bashgym',\r\n message: 'Link to BashGym? (enables self-improving AI sidekick)',\r\n choices: [\r\n {\r\n name: 'Yes (recommended) - Export traces for training, get smarter sidekick',\r\n value: 'link'\r\n },\r\n {\r\n name: 'No - Use bashbros standalone',\r\n value: 'skip'\r\n }\r\n ]\r\n })\r\n }\r\n\r\n const answers = await inquirer.prompt(questions)\r\n\r\n // Build config\r\n const config = buildConfig(answers)\r\n\r\n // Write config file\r\n const configYaml = stringify(config)\r\n writeFileSync('.bashbros.yml', configYaml)\r\n\r\n console.log()\r\n console.log(chalk.green('✓'), 'Config written to', chalk.cyan('.bashbros.yml'))\r\n console.log(chalk.green('✓'), 'PTY wrapper ready')\r\n console.log(chalk.green('✓'), 'Audit logging', answers.audit !== 'disabled' ? 'enabled' : 'disabled')\r\n\r\n // Handle bashgym integration\r\n if (answers.bashgym === 'link') {\r\n const linked = await linkBashgym()\r\n if (linked) {\r\n console.log(chalk.green('✓'), 'BashGym integration', chalk.cyan('linked'))\r\n console.log(chalk.dim(' Traces will be exported for training'))\r\n console.log(chalk.dim(' AI sidekick will improve over time'))\r\n } else {\r\n console.log(chalk.yellow('⚠'), 'BashGym integration', chalk.dim('not linked (bashgym not running?)'))\r\n }\r\n } else if (bashgymAvailable) {\r\n console.log(chalk.dim('○'), 'BashGym integration', chalk.dim('skipped'))\r\n }\r\n\r\n console.log()\r\n console.log(chalk.dim(\"Run\"), chalk.cyan(\"'bashbros doctor'\"), chalk.dim(\"to verify setup\"))\r\n console.log(chalk.dim(\"Run\"), chalk.cyan(\"'bashbros watch'\"), chalk.dim(\"to start protection\"))\r\n console.log()\r\n}\r\n\r\n/**\r\n * Link bashbros to bashgym integration\r\n */\r\nasync function linkBashgym(): Promise<boolean> {\r\n try {\r\n const integration = getBashgymIntegration()\r\n\r\n // Check if bashgym directory exists\r\n if (!integration.isAvailable()) {\r\n // Create the integration directory structure\r\n const integrationDir = join(homedir(), '.bashgym', 'integration')\r\n const dirs = [\r\n join(integrationDir, 'traces', 'pending'),\r\n join(integrationDir, 'traces', 'processed'),\r\n join(integrationDir, 'traces', 'failed'),\r\n join(integrationDir, 'models', 'latest'),\r\n join(integrationDir, 'config'),\r\n join(integrationDir, 'status'),\r\n ]\r\n\r\n for (const dir of dirs) {\r\n mkdirSync(dir, { recursive: true })\r\n }\r\n\r\n // Create initial settings file\r\n const settingsPath = join(integrationDir, 'config', 'settings.json')\r\n const settings = {\r\n version: '1.0',\r\n updated_at: new Date().toISOString(),\r\n updated_by: 'bashbros',\r\n integration: {\r\n enabled: true,\r\n linked_at: new Date().toISOString(),\r\n },\r\n capture: {\r\n mode: 'successful_only',\r\n auto_stream: true,\r\n },\r\n training: {\r\n auto_enabled: false,\r\n quality_threshold: 50,\r\n trigger: 'quality_based',\r\n },\r\n security: {\r\n bashbros_primary: true,\r\n policy_path: null,\r\n },\r\n model_sync: {\r\n auto_export_ollama: true,\r\n ollama_model_name: 'bashgym-sidekick',\r\n notify_on_update: true,\r\n },\r\n }\r\n\r\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2))\r\n } else {\r\n // Update existing settings to enable integration\r\n integration.updateSettings({\r\n integration: {\r\n enabled: true,\r\n linked_at: new Date().toISOString(),\r\n },\r\n } as any)\r\n }\r\n\r\n return true\r\n } catch (error) {\r\n console.error('Failed to link bashgym:', error)\r\n return false\r\n }\r\n}\r\n\r\nfunction buildConfig(answers: Record<string, string>): BashBrosConfig {\r\n const defaults = getDefaultConfig()\r\n\r\n const config: BashBrosConfig = {\r\n ...defaults,\r\n agent: answers.agent as AgentType,\r\n profile: answers.profile as SecurityProfile,\r\n secrets: {\r\n ...defaults.secrets,\r\n enabled: answers.secrets !== 'disabled',\r\n mode: answers.secrets === 'audit' ? 'audit' : 'block'\r\n },\r\n audit: {\r\n ...defaults.audit,\r\n enabled: answers.audit !== 'disabled',\r\n destination: answers.audit === 'disabled' ? 'local' : answers.audit as 'local' | 'remote' | 'both'\r\n }\r\n }\r\n\r\n // Adjust for project type\r\n if (answers.projectType === 'sensitive') {\r\n config.profile = 'strict'\r\n config.rateLimit.maxPerMinute = 50\r\n }\r\n\r\n if (answers.projectType === 'devops') {\r\n config.commands.allow.push('docker *', 'kubectl *', 'terraform *', 'aws *')\r\n }\r\n\r\n if (answers.projectType === 'data') {\r\n config.commands.allow.push('python *', 'jupyter *', 'pandas *', 'psql *')\r\n }\r\n\r\n return config\r\n}\r\n","import chalk from 'chalk'\r\nimport { existsSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { findConfig, loadConfig } from './config.js'\r\nimport { getAllAgentConfigs, getAgentConfigInfo } from './transparency/agent-config.js'\r\nimport { ExposureScanner, EgressPatternMatcher } from './policy/ward/index.js'\r\nimport type { AgentConfigInfo } from './types.js'\r\n\r\ninterface CheckResult {\r\n name: string\r\n passed: boolean\r\n message: string\r\n}\r\n\r\n/**\r\n * Check agent configurations for health issues\r\n */\r\nasync function checkAgentConfigs(agents: AgentConfigInfo[]): Promise<CheckResult[]> {\r\n const checks: CheckResult[] = []\r\n\r\n for (const agent of agents) {\r\n const agentName = agent.agent.charAt(0).toUpperCase() + agent.agent.slice(1).replace('-', ' ')\r\n\r\n // Check if config exists\r\n if (agent.configPath && !agent.configExists) {\r\n checks.push({\r\n name: `${agentName} config`,\r\n passed: false,\r\n message: `Config path known (${agent.configPath}) but file not found`\r\n })\r\n } else if (agent.configExists) {\r\n checks.push({\r\n name: `${agentName} config`,\r\n passed: true,\r\n message: `Found at ${agent.configPath}`\r\n })\r\n }\r\n\r\n // Check bashbros integration\r\n if (agent.agent === 'claude-code') {\r\n checks.push({\r\n name: `${agentName} integration`,\r\n passed: agent.bashbrosIntegrated,\r\n message: agent.bashbrosIntegrated\r\n ? 'BashBros hooks installed'\r\n : 'Hooks not installed. Run \"bashbros hook install\" to protect Claude Code'\r\n })\r\n }\r\n\r\n // Check moltbot/clawdbot specific integration\r\n if (agent.agent === 'moltbot' || agent.agent === 'clawdbot') {\r\n checks.push({\r\n name: `${agentName} integration`,\r\n passed: agent.bashbrosIntegrated,\r\n message: agent.bashbrosIntegrated\r\n ? 'BashBros hooks installed'\r\n : 'Hooks not installed. Run \"bashbros moltbot install\" to protect moltbot'\r\n })\r\n\r\n // Check for moltbot-specific settings via dynamic import\r\n try {\r\n const { MoltbotHooks } = await import('./hooks/moltbot.js')\r\n const status = MoltbotHooks.getStatus()\r\n\r\n // Check sandbox mode\r\n if (status.sandboxMode) {\r\n checks.push({\r\n name: `${agentName} sandbox`,\r\n passed: status.sandboxMode === 'strict',\r\n message: status.sandboxMode === 'strict'\r\n ? 'Sandbox mode enabled (strict)'\r\n : `Sandbox mode: ${status.sandboxMode} (consider \"strict\" for better security)`\r\n })\r\n }\r\n\r\n // Check gateway configuration\r\n if (status.gatewayRunning) {\r\n const gatewayStatus = await MoltbotHooks.getGatewayStatus()\r\n checks.push({\r\n name: `${agentName} gateway`,\r\n passed: gatewayStatus.running,\r\n message: gatewayStatus.running\r\n ? `Gateway running on port ${gatewayStatus.port}`\r\n : 'Gateway configured but not running'\r\n })\r\n }\r\n } catch {\r\n // Moltbot hooks module not available, skip additional checks\r\n }\r\n }\r\n\r\n // Check for potential permission conflicts\r\n if (agent.permissions) {\r\n const config = loadConfig()\r\n\r\n // Warn if agent has no path restrictions but bashbros does\r\n if ((!agent.permissions.allowedPaths || agent.permissions.allowedPaths.length === 0) &&\r\n config.paths.allow.length > 0 && !config.paths.allow.includes('*')) {\r\n checks.push({\r\n name: `${agentName} path policy`,\r\n passed: true, // Not a failure, just a note\r\n message: `Agent has no path restrictions; bashbros will enforce: ${config.paths.allow.slice(0, 3).join(', ')}`\r\n })\r\n }\r\n }\r\n }\r\n\r\n return checks\r\n}\r\n\r\nexport async function runDoctor(): Promise<void> {\r\n console.log(chalk.bold('\\nRunning diagnostics...\\n'))\r\n\r\n const checks: CheckResult[] = []\r\n\r\n // Check 1: Config file exists\r\n const configPath = findConfig()\r\n checks.push({\r\n name: 'Config file',\r\n passed: configPath !== null,\r\n message: configPath\r\n ? `Found at ${configPath}`\r\n : 'Not found. Run \"bashbros init\" to create one.'\r\n })\r\n\r\n // Check 2: Config is valid\r\n if (configPath) {\r\n try {\r\n const config = loadConfig(configPath)\r\n checks.push({\r\n name: 'Config valid',\r\n passed: true,\r\n message: `Profile: ${config.profile}, Agent: ${config.agent}`\r\n })\r\n } catch (error) {\r\n checks.push({\r\n name: 'Config valid',\r\n passed: false,\r\n message: `Parse error: ${error}`\r\n })\r\n }\r\n }\r\n\r\n // Check 3: Audit directory exists\r\n const auditDir = join(homedir(), '.bashbros')\r\n checks.push({\r\n name: 'Audit directory',\r\n passed: existsSync(auditDir),\r\n message: existsSync(auditDir)\r\n ? `Found at ${auditDir}`\r\n : 'Will be created on first run'\r\n })\r\n\r\n // Check 4: node-pty available\r\n try {\r\n await import('node-pty')\r\n checks.push({\r\n name: 'PTY support',\r\n passed: true,\r\n message: 'node-pty loaded successfully'\r\n })\r\n } catch (error) {\r\n checks.push({\r\n name: 'PTY support',\r\n passed: false,\r\n message: 'node-pty not available. Run \"npm install\" to install dependencies.'\r\n })\r\n }\r\n\r\n // Check 5: Secrets protection patterns\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const secretsEnabled = config.secrets.enabled\r\n checks.push({\r\n name: 'Secrets protection',\r\n passed: secretsEnabled,\r\n message: secretsEnabled\r\n ? `Enabled with ${config.secrets.patterns.length} patterns`\r\n : 'Disabled - credentials may be exposed'\r\n })\r\n }\r\n\r\n // Check 6: Rate limiting\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n checks.push({\r\n name: 'Rate limiting',\r\n passed: config.rateLimit.enabled,\r\n message: config.rateLimit.enabled\r\n ? `${config.rateLimit.maxPerMinute}/min, ${config.rateLimit.maxPerHour}/hr`\r\n : 'Disabled - runaway agents possible'\r\n })\r\n }\r\n\r\n // Check 7: Agent configurations\r\n const agents = await getAllAgentConfigs()\r\n const installedAgents = agents.filter(a => a.installed)\r\n\r\n if (installedAgents.length > 0) {\r\n // Check agent config health\r\n const agentChecks = await checkAgentConfigs(installedAgents)\r\n checks.push(...agentChecks)\r\n } else {\r\n checks.push({\r\n name: 'Agent detection',\r\n passed: true,\r\n message: 'No agents detected (install claude, aider, etc. to use bashbros protection)'\r\n })\r\n }\r\n\r\n // Check 8: Ward security\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const wardEnabled = config.ward?.enabled ?? false\r\n checks.push({\r\n name: 'Ward security',\r\n passed: wardEnabled,\r\n message: wardEnabled\r\n ? `Enabled (exposure scan: ${config.ward.exposure.scanInterval}ms)`\r\n : 'Disabled - network exposure monitoring off'\r\n })\r\n }\r\n\r\n // Check 9: Dashboard\r\n if (configPath) {\r\n const config = loadConfig(configPath)\r\n const dashEnabled = config.dashboard?.enabled ?? false\r\n checks.push({\r\n name: 'Dashboard',\r\n passed: dashEnabled,\r\n message: dashEnabled\r\n ? `Enabled on ${config.dashboard.bind}:${config.dashboard.port}`\r\n : 'Disabled - run \"bashbros dashboard\" to start'\r\n })\r\n }\r\n\r\n // Check 10: Exposure scanner\r\n try {\r\n const scanner = new ExposureScanner()\r\n const agentSignatures = scanner.getAgents()\r\n checks.push({\r\n name: 'Exposure scanner',\r\n passed: true,\r\n message: `Ready, monitoring ${agentSignatures.length} agent signatures`\r\n })\r\n } catch {\r\n checks.push({\r\n name: 'Exposure scanner',\r\n passed: false,\r\n message: 'Failed to initialize exposure scanner'\r\n })\r\n }\r\n\r\n // Check 11: Egress patterns\r\n try {\r\n const matcher = new EgressPatternMatcher()\r\n const patterns = matcher.getPatterns()\r\n const credPatterns = patterns.filter(p => p.category === 'credentials').length\r\n const piiPatterns = patterns.filter(p => p.category === 'pii').length\r\n checks.push({\r\n name: 'Egress patterns',\r\n passed: true,\r\n message: `Loaded ${patterns.length} patterns (${credPatterns} credential, ${piiPatterns} PII)`\r\n })\r\n } catch {\r\n checks.push({\r\n name: 'Egress patterns',\r\n passed: false,\r\n message: 'Failed to initialize egress patterns'\r\n })\r\n }\r\n\r\n // Print results\r\n let passed = 0\r\n let failed = 0\r\n\r\n for (const check of checks) {\r\n const icon = check.passed ? chalk.green('✓') : chalk.red('✗')\r\n const status = check.passed ? chalk.green('OK') : chalk.red('FAIL')\r\n\r\n console.log(` ${icon} ${chalk.bold(check.name)}: ${status}`)\r\n console.log(chalk.dim(` ${check.message}`))\r\n console.log()\r\n\r\n if (check.passed) passed++\r\n else failed++\r\n }\r\n\r\n // Summary\r\n console.log(chalk.bold('─'.repeat(40)))\r\n if (failed === 0) {\r\n console.log(chalk.green(`\\n✓ All ${passed} checks passed. BashBros is ready.\\n`))\r\n } else {\r\n console.log(chalk.yellow(`\\n${passed} passed, ${failed} failed. Fix issues above.\\n`))\r\n }\r\n}\r\n","/**\r\n * Agent Configuration Discovery\r\n * Discovers and reports on agent configurations for transparency\r\n */\r\n\r\nimport { existsSync, statSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir, platform } from 'os'\r\nimport { execFileSync } from 'child_process'\r\nimport type { AgentType, AgentConfigInfo } from '../types.js'\r\nimport { ClaudeCodeHooks } from '../hooks/claude-code.js'\r\nimport { parseAgentConfig } from './config-parser.js'\r\n\r\n// Known agent config paths\r\n// Primary path is checked first, then fallbacks\r\nexport const AGENT_CONFIG_PATHS: Record<AgentType, string[]> = {\r\n 'claude-code': [\r\n join(homedir(), '.claude', 'settings.json')\r\n ],\r\n 'clawdbot': [\r\n join(homedir(), '.clawdbot', 'moltbot.json'), // New primary (moltbot format)\r\n join(homedir(), '.clawdbot', 'config.yml'), // Legacy\r\n join(homedir(), '.config', 'clawdbot', 'config.yml')\r\n ],\r\n 'moltbot': [\r\n join(homedir(), '.moltbot', 'config.json'),\r\n join(homedir(), '.clawdbot', 'moltbot.json'), // Common location\r\n join(homedir(), '.config', 'moltbot', 'config.json')\r\n ],\r\n 'aider': [\r\n join(homedir(), '.aider.conf.yml'),\r\n join(homedir(), '.config', 'aider', 'aider.conf.yml')\r\n ],\r\n 'gemini-cli': [\r\n join(homedir(), '.config', 'gemini-cli', 'config.json')\r\n ],\r\n 'opencode': [\r\n join(homedir(), '.opencode', 'config.yml'),\r\n join(homedir(), '.config', 'opencode', 'config.yml')\r\n ],\r\n 'custom': []\r\n}\r\n\r\n// Command names for each agent (used to check if installed)\r\nconst AGENT_COMMANDS: Record<AgentType, string> = {\r\n 'claude-code': 'claude',\r\n 'clawdbot': 'clawdbot',\r\n 'moltbot': 'moltbot',\r\n 'aider': 'aider',\r\n 'gemini-cli': 'gemini',\r\n 'opencode': 'opencode',\r\n 'custom': ''\r\n}\r\n\r\n/**\r\n * Detect which naming convention is being used (moltbot vs clawdbot)\r\n * Returns the detected naming or null if neither is found\r\n */\r\nexport function detectMoltbotNaming(): 'moltbot' | 'clawdbot' | null {\r\n // Check environment variables first (runtime indicator)\r\n if (process.env.MOLTBOT_SESSION_ID || process.env.MOLTBOT_AGENT) {\r\n return 'moltbot'\r\n }\r\n if (process.env.CLAWDBOT_SESSION_ID || process.env.CLAWDBOT_AGENT) {\r\n return 'clawdbot'\r\n }\r\n\r\n // Check for moltbot command\r\n if (commandExists('moltbot')) {\r\n return 'moltbot'\r\n }\r\n\r\n // Check for clawdbot command\r\n if (commandExists('clawdbot')) {\r\n return 'clawdbot'\r\n }\r\n\r\n // Check for config files\r\n const moltbotPaths = AGENT_CONFIG_PATHS['moltbot']\r\n for (const p of moltbotPaths) {\r\n if (existsSync(p)) {\r\n return 'moltbot'\r\n }\r\n }\r\n\r\n const clawdbotPaths = AGENT_CONFIG_PATHS['clawdbot']\r\n for (const p of clawdbotPaths) {\r\n if (existsSync(p)) {\r\n return 'clawdbot'\r\n }\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * Check if a command exists in PATH\r\n */\r\nfunction commandExists(cmd: string): boolean {\r\n if (!cmd) return false\r\n\r\n try {\r\n const whichCmd = platform() === 'win32' ? 'where' : 'which'\r\n execFileSync(whichCmd, [cmd], {\r\n stdio: 'pipe',\r\n timeout: 3000,\r\n windowsHide: true\r\n })\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Get version of an agent command\r\n */\r\nfunction getAgentVersion(agent: AgentType): string | undefined {\r\n const cmd = AGENT_COMMANDS[agent]\r\n if (!cmd) return undefined\r\n\r\n try {\r\n const output = execFileSync(cmd, ['--version'], {\r\n encoding: 'utf-8',\r\n timeout: 5000,\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n windowsHide: true\r\n }).trim()\r\n\r\n // Extract version number\r\n const match = output.match(/(\\d+\\.\\d+(?:\\.\\d+)?(?:-[\\w.]+)?)/i)\r\n return match ? match[1] : output.split('\\n')[0].slice(0, 50)\r\n } catch {\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Find the config path for an agent\r\n */\r\nfunction findAgentConfigPath(agent: AgentType): string | undefined {\r\n const paths = AGENT_CONFIG_PATHS[agent]\r\n\r\n for (const configPath of paths) {\r\n if (existsSync(configPath)) {\r\n return configPath\r\n }\r\n }\r\n\r\n return undefined\r\n}\r\n\r\n/**\r\n * Get last modified date of a file\r\n */\r\nfunction getLastModified(filePath: string): Date | undefined {\r\n try {\r\n const stats = statSync(filePath)\r\n return stats.mtime\r\n } catch {\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Check if BashBros is integrated with an agent\r\n */\r\nasync function isBashbrosIntegrated(agent: AgentType): Promise<boolean> {\r\n if (agent === 'claude-code') {\r\n const status = ClaudeCodeHooks.getStatus()\r\n return status.hooksInstalled\r\n }\r\n\r\n if (agent === 'moltbot' || agent === 'clawdbot') {\r\n try {\r\n const { MoltbotHooks } = await import('../hooks/moltbot.js')\r\n return MoltbotHooks.isInstalled()\r\n } catch {\r\n return false\r\n }\r\n }\r\n\r\n // For other agents, check if they have bashbros hooks configured\r\n // This would need to be extended as more integrations are built\r\n return false\r\n}\r\n\r\n/**\r\n * Get configuration info for a specific agent\r\n */\r\nexport async function getAgentConfigInfo(agent: AgentType): Promise<AgentConfigInfo> {\r\n const cmd = AGENT_COMMANDS[agent]\r\n const installed = cmd ? commandExists(cmd) : false\r\n const configPath = findAgentConfigPath(agent)\r\n const configExists = configPath ? existsSync(configPath) : false\r\n\r\n const info: AgentConfigInfo = {\r\n agent,\r\n installed,\r\n configPath,\r\n configExists,\r\n bashbrosIntegrated: await isBashbrosIntegrated(agent)\r\n }\r\n\r\n if (installed) {\r\n info.version = getAgentVersion(agent)\r\n }\r\n\r\n if (configExists && configPath) {\r\n info.lastModified = getLastModified(configPath)\r\n\r\n // Parse config for permissions and hooks\r\n const parsed = await parseAgentConfig(agent, configPath)\r\n if (parsed) {\r\n info.permissions = parsed.permissions\r\n info.hooks = parsed.hooks\r\n }\r\n }\r\n\r\n return info\r\n}\r\n\r\n/**\r\n * Get configuration info for all known agents\r\n */\r\nexport async function getAllAgentConfigs(): Promise<AgentConfigInfo[]> {\r\n const agents: AgentType[] = ['claude-code', 'moltbot', 'clawdbot', 'aider', 'gemini-cli', 'opencode']\r\n const results: AgentConfigInfo[] = []\r\n\r\n for (const agent of agents) {\r\n const info = await getAgentConfigInfo(agent)\r\n results.push(info)\r\n }\r\n\r\n return results\r\n}\r\n\r\n/**\r\n * Get only installed agents\r\n */\r\nexport async function getInstalledAgents(): Promise<AgentConfigInfo[]> {\r\n const all = await getAllAgentConfigs()\r\n return all.filter(info => info.installed)\r\n}\r\n\r\n/**\r\n * Get agents with configurations\r\n */\r\nexport async function getConfiguredAgents(): Promise<AgentConfigInfo[]> {\r\n const all = await getAllAgentConfigs()\r\n return all.filter(info => info.configExists)\r\n}\r\n","/**\r\n * Exposure Scanner - Detects exposed AI agent servers\r\n *\r\n * Scans for listening ports that match known AI agent signatures\r\n * and assesses their security risk based on binding, authentication,\r\n * and external reachability.\r\n */\r\n\r\nimport { exec } from 'node:child_process'\r\nimport { promisify } from 'node:util'\r\nimport { existsSync, readFileSync } from 'node:fs'\r\nimport { platform } from 'node:os'\r\nimport type {\r\n AgentSignature,\r\n ExposureResult,\r\n ExposureSeverity,\r\n ExposureAction,\r\n ExposureConfig,\r\n} from './types.js'\r\n\r\nconst execAsync = promisify(exec)\r\n\r\n/**\r\n * Default agent signatures for common AI coding assistants\r\n */\r\nexport const DEFAULT_AGENT_SIGNATURES: AgentSignature[] = [\r\n {\r\n name: 'claude-code',\r\n processNames: ['claude', 'claude-code', 'claude_code'],\r\n defaultPorts: [3000, 3001, 8080],\r\n configPaths: [\r\n '~/.claude/config.json',\r\n '~/.config/claude/config.json',\r\n ],\r\n authIndicators: ['api_key', 'auth_token', 'authorization'],\r\n },\r\n {\r\n name: 'aider',\r\n processNames: ['aider', 'aider-chat'],\r\n defaultPorts: [8501, 8000],\r\n configPaths: [\r\n '~/.aider.conf.yml',\r\n '.aider.conf.yml',\r\n ],\r\n authIndicators: ['api_key', 'openai_api_key'],\r\n },\r\n {\r\n name: 'continue',\r\n processNames: ['continue', 'continue-server'],\r\n defaultPorts: [65432, 65433],\r\n configPaths: [\r\n '~/.continue/config.json',\r\n '.continue/config.json',\r\n ],\r\n authIndicators: ['apiKey', 'auth'],\r\n },\r\n {\r\n name: 'cursor',\r\n processNames: ['cursor', 'Cursor', 'cursor-server'],\r\n defaultPorts: [3000, 8080, 9000],\r\n configPaths: [\r\n '~/.cursor/config.json',\r\n '%APPDATA%/Cursor/config.json',\r\n ],\r\n authIndicators: ['apiKey', 'token', 'auth'],\r\n },\r\n]\r\n\r\n/**\r\n * Default mapping from severity to action\r\n */\r\nexport const DEFAULT_SEVERITY_ACTIONS: Record<ExposureSeverity, ExposureAction> = {\r\n low: 'alert',\r\n medium: 'alert',\r\n high: 'block',\r\n critical: 'block_and_kill',\r\n}\r\n\r\n/**\r\n * Input for severity assessment\r\n */\r\nexport interface SeverityInput {\r\n bindAddress: string\r\n hasAuth: boolean | 'unknown'\r\n externallyReachable: boolean\r\n hasActiveSessions: boolean\r\n}\r\n\r\n/**\r\n * Parsed netstat line result\r\n */\r\nexport interface NetstatResult {\r\n protocol: string\r\n localAddress: string\r\n localPort: number\r\n state: string\r\n pid: number\r\n}\r\n\r\n/**\r\n * ExposureScanner - Scans for exposed AI agent servers\r\n */\r\nexport class ExposureScanner {\r\n private config: ExposureConfig\r\n private agents: AgentSignature[]\r\n\r\n constructor(config?: Partial<ExposureConfig>) {\r\n this.agents = [...DEFAULT_AGENT_SIGNATURES]\r\n this.config = {\r\n enabled: true,\r\n scanInterval: 60000,\r\n externalProbe: false,\r\n severityActions: { ...DEFAULT_SEVERITY_ACTIONS },\r\n agents: this.agents,\r\n ...config,\r\n }\r\n\r\n // Merge any custom agents from config\r\n if (config?.agents) {\r\n for (const agent of config.agents) {\r\n if (!this.agents.find(a => a.name === agent.name)) {\r\n this.agents.push(agent)\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Scan for exposed agent servers\r\n */\r\n async scan(): Promise<ExposureResult[]> {\r\n const results: ExposureResult[] = []\r\n const listeningPorts = await this.getListeningPorts()\r\n\r\n for (const port of listeningPorts) {\r\n for (const agent of this.agents) {\r\n if (agent.defaultPorts.includes(port.localPort)) {\r\n const hasAuth = await this.checkAuthConfig(agent)\r\n const externallyReachable = this.isExternallyReachable(port.localAddress)\r\n\r\n const severity = this.assessSeverity({\r\n bindAddress: port.localAddress,\r\n hasAuth,\r\n externallyReachable,\r\n hasActiveSessions: false,\r\n })\r\n\r\n const action = this.getActionForSeverity(severity)\r\n\r\n results.push({\r\n agent: agent.name,\r\n pid: port.pid,\r\n port: port.localPort,\r\n bindAddress: port.localAddress,\r\n hasAuth,\r\n severity,\r\n action,\r\n message: this.generateMessage(agent.name, port, severity, hasAuth),\r\n timestamp: new Date(),\r\n })\r\n }\r\n }\r\n }\r\n\r\n return results\r\n }\r\n\r\n /**\r\n * Assess severity based on exposure factors\r\n */\r\n assessSeverity(input: SeverityInput): ExposureSeverity {\r\n const { bindAddress, hasAuth, externallyReachable, hasActiveSessions } = input\r\n\r\n // Critical: Externally reachable without auth\r\n if (externallyReachable && hasAuth !== true) {\r\n return 'critical'\r\n }\r\n\r\n // Critical: Active sessions on externally reachable\r\n if (externallyReachable && hasActiveSessions) {\r\n return 'critical'\r\n }\r\n\r\n // High: Bound to all interfaces (0.0.0.0 or ::) without auth\r\n const isWildcardBind = bindAddress === '0.0.0.0' || bindAddress === '::' || bindAddress === '*'\r\n if (isWildcardBind && hasAuth !== true) {\r\n return 'high'\r\n }\r\n\r\n // Medium: Bound to all interfaces with auth, or localhost without auth\r\n if (isWildcardBind && hasAuth === true) {\r\n return 'medium'\r\n }\r\n\r\n // Check if localhost\r\n const isLocalhost =\r\n bindAddress === '127.0.0.1' ||\r\n bindAddress === '::1' ||\r\n bindAddress === 'localhost'\r\n\r\n if (isLocalhost && hasAuth !== true) {\r\n return 'medium'\r\n }\r\n\r\n // Low: Localhost with auth\r\n return 'low'\r\n }\r\n\r\n /**\r\n * Get action for a given severity level\r\n */\r\n getActionForSeverity(severity: ExposureSeverity): ExposureAction {\r\n return this.config.severityActions[severity]\r\n }\r\n\r\n /**\r\n * Parse a Windows netstat output line\r\n */\r\n parseNetstatLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || !trimmed.includes('LISTENING')) {\r\n return null\r\n }\r\n\r\n // Windows netstat -ano format:\r\n // TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12345\r\n // TCP [::]:8000 [::]:0 LISTENING 1111\r\n\r\n const parts = trimmed.split(/\\s+/)\r\n if (parts.length < 5) {\r\n return null\r\n }\r\n\r\n const protocol = parts[0]\r\n if (protocol !== 'TCP' && protocol !== 'UDP') {\r\n return null\r\n }\r\n\r\n const localAddressPart = parts[1]\r\n const state = parts[3]\r\n const pid = parseInt(parts[4], 10)\r\n\r\n if (state !== 'LISTENING' || isNaN(pid)) {\r\n return null\r\n }\r\n\r\n // Parse address:port - handle IPv6 [addr]:port format\r\n let localAddress: string\r\n let localPort: number\r\n\r\n if (localAddressPart.startsWith('[')) {\r\n // IPv6 format: [::1]:3000 or [::]:8000\r\n const match = localAddressPart.match(/^\\[([^\\]]+)\\]:(\\d+)$/)\r\n if (!match) {\r\n return null\r\n }\r\n localAddress = match[1]\r\n localPort = parseInt(match[2], 10)\r\n } else {\r\n // IPv4 format: 0.0.0.0:3000\r\n const lastColonIndex = localAddressPart.lastIndexOf(':')\r\n if (lastColonIndex === -1) {\r\n return null\r\n }\r\n localAddress = localAddressPart.substring(0, lastColonIndex)\r\n localPort = parseInt(localAddressPart.substring(lastColonIndex + 1), 10)\r\n }\r\n\r\n if (isNaN(localPort)) {\r\n return null\r\n }\r\n\r\n return {\r\n protocol,\r\n localAddress,\r\n localPort,\r\n state,\r\n pid,\r\n }\r\n }\r\n\r\n /**\r\n * Get all listening TCP ports (cross-platform)\r\n */\r\n async getListeningPorts(): Promise<NetstatResult[]> {\r\n const results: NetstatResult[] = []\r\n\r\n try {\r\n if (platform() === 'win32') {\r\n const { stdout } = await execAsync('netstat -ano -p TCP')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseNetstatLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n } else {\r\n // Unix-like systems: use ss or netstat\r\n try {\r\n const { stdout } = await execAsync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseUnixListeningLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n } catch {\r\n // Fallback to lsof on macOS\r\n const { stdout } = await execAsync('lsof -iTCP -sTCP:LISTEN -n -P 2>/dev/null || true')\r\n const lines = stdout.split('\\n')\r\n\r\n for (const line of lines) {\r\n const parsed = this.parseLsofLine(line)\r\n if (parsed) {\r\n results.push(parsed)\r\n }\r\n }\r\n }\r\n }\r\n } catch {\r\n // Return empty array if we can't get port info\r\n }\r\n\r\n return results\r\n }\r\n\r\n /**\r\n * Parse Unix ss/netstat output line\r\n */\r\n private parseUnixListeningLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || trimmed.startsWith('State') || trimmed.startsWith('Proto')) {\r\n return null\r\n }\r\n\r\n // ss format: LISTEN 0 128 0.0.0.0:3000 0.0.0.0:* users:((\"node\",pid=1234,fd=3))\r\n // netstat format: tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 1234/node\r\n\r\n // Try ss format first\r\n const ssMatch = trimmed.match(/LISTEN\\s+\\d+\\s+\\d+\\s+([^\\s]+):(\\d+)\\s+.*?pid=(\\d+)/)\r\n if (ssMatch) {\r\n return {\r\n protocol: 'TCP',\r\n localAddress: ssMatch[1] === '*' ? '0.0.0.0' : ssMatch[1],\r\n localPort: parseInt(ssMatch[2], 10),\r\n state: 'LISTENING',\r\n pid: parseInt(ssMatch[3], 10),\r\n }\r\n }\r\n\r\n // Try netstat format\r\n const netstatMatch = trimmed.match(/tcp\\s+\\d+\\s+\\d+\\s+([^\\s]+):(\\d+)\\s+.*?LISTEN\\s+(\\d+)/)\r\n if (netstatMatch) {\r\n return {\r\n protocol: 'TCP',\r\n localAddress: netstatMatch[1] === '*' ? '0.0.0.0' : netstatMatch[1],\r\n localPort: parseInt(netstatMatch[2], 10),\r\n state: 'LISTENING',\r\n pid: parseInt(netstatMatch[3], 10),\r\n }\r\n }\r\n\r\n return null\r\n }\r\n\r\n /**\r\n * Parse lsof output line (macOS fallback)\r\n */\r\n private parseLsofLine(line: string): NetstatResult | null {\r\n const trimmed = line.trim()\r\n if (!trimmed || trimmed.startsWith('COMMAND')) {\r\n return null\r\n }\r\n\r\n // lsof format: node 1234 user 3u IPv4 0x123 0t0 TCP *:3000 (LISTEN)\r\n const parts = trimmed.split(/\\s+/)\r\n if (parts.length < 9) {\r\n return null\r\n }\r\n\r\n const pid = parseInt(parts[1], 10)\r\n if (isNaN(pid)) {\r\n return null\r\n }\r\n\r\n // Find TCP and port info\r\n const tcpIndex = parts.findIndex(p => p === 'TCP' || p === 'TCP6')\r\n if (tcpIndex === -1) {\r\n return null\r\n }\r\n\r\n const addressPart = parts[tcpIndex + 1]\r\n if (!addressPart) {\r\n return null\r\n }\r\n\r\n // Parse *:3000 or 127.0.0.1:3000\r\n const match = addressPart.match(/^([^:]+):(\\d+)$/)\r\n if (!match) {\r\n return null\r\n }\r\n\r\n return {\r\n protocol: 'TCP',\r\n localAddress: match[1] === '*' ? '0.0.0.0' : match[1],\r\n localPort: parseInt(match[2], 10),\r\n state: 'LISTENING',\r\n pid,\r\n }\r\n }\r\n\r\n /**\r\n * Check if an agent has auth configured\r\n */\r\n async checkAuthConfig(agent: AgentSignature): Promise<boolean | 'unknown'> {\r\n for (const configPath of agent.configPaths) {\r\n const expandedPath = this.expandPath(configPath)\r\n\r\n if (existsSync(expandedPath)) {\r\n try {\r\n const content = readFileSync(expandedPath, 'utf-8')\r\n\r\n for (const indicator of agent.authIndicators) {\r\n if (content.includes(indicator)) {\r\n return true\r\n }\r\n }\r\n return false\r\n } catch {\r\n // Can't read config, unknown\r\n }\r\n }\r\n }\r\n\r\n return 'unknown'\r\n }\r\n\r\n /**\r\n * Check if an address is externally reachable\r\n */\r\n private isExternallyReachable(bindAddress: string): boolean {\r\n // 0.0.0.0 or :: binds to all interfaces\r\n if (bindAddress === '0.0.0.0' || bindAddress === '::' || bindAddress === '*') {\r\n // Could be externally reachable if there's a non-loopback interface\r\n // For now, we assume it could be reachable\r\n // In a real implementation, we'd check network interfaces\r\n return this.config.externalProbe\r\n }\r\n\r\n // Localhost addresses are not externally reachable\r\n if (\r\n bindAddress === '127.0.0.1' ||\r\n bindAddress === '::1' ||\r\n bindAddress === 'localhost'\r\n ) {\r\n return false\r\n }\r\n\r\n // Private IP ranges - potentially reachable on LAN\r\n if (this.isPrivateIP(bindAddress)) {\r\n return this.config.externalProbe\r\n }\r\n\r\n // Public IP - externally reachable\r\n return true\r\n }\r\n\r\n /**\r\n * Check if an IP is in a private range\r\n */\r\n private isPrivateIP(ip: string): boolean {\r\n // IPv4 private ranges\r\n if (ip.startsWith('10.')) return true\r\n if (ip.startsWith('172.')) {\r\n const second = parseInt(ip.split('.')[1], 10)\r\n if (second >= 16 && second <= 31) return true\r\n }\r\n if (ip.startsWith('192.168.')) return true\r\n\r\n // IPv6 private ranges\r\n if (ip.toLowerCase().startsWith('fc') || ip.toLowerCase().startsWith('fd')) {\r\n return true\r\n }\r\n\r\n return false\r\n }\r\n\r\n /**\r\n * Expand path with home directory and environment variables\r\n */\r\n private expandPath(path: string): string {\r\n let expanded = path\r\n\r\n // Expand ~ to home directory\r\n if (expanded.startsWith('~')) {\r\n const home = process.env.HOME || process.env.USERPROFILE || ''\r\n expanded = expanded.replace('~', home)\r\n }\r\n\r\n // Expand %VAR% style env vars (Windows)\r\n expanded = expanded.replace(/%([^%]+)%/g, (_, name) => process.env[name] || '')\r\n\r\n // Expand $VAR style env vars (Unix)\r\n expanded = expanded.replace(/\\$([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => process.env[name] || '')\r\n\r\n return expanded\r\n }\r\n\r\n /**\r\n * Generate human-readable message for an exposure\r\n */\r\n private generateMessage(\r\n agentName: string,\r\n port: NetstatResult,\r\n severity: ExposureSeverity,\r\n hasAuth: boolean | 'unknown'\r\n ): string {\r\n const authStatus = hasAuth === true\r\n ? 'with authentication'\r\n : hasAuth === false\r\n ? 'without authentication'\r\n : 'authentication status unknown'\r\n\r\n const bindDesc = port.localAddress === '0.0.0.0' || port.localAddress === '::'\r\n ? 'all interfaces'\r\n : port.localAddress\r\n\r\n return `${agentName} server detected on port ${port.localPort} (${bindDesc}) ${authStatus}. Severity: ${severity}`\r\n }\r\n\r\n /**\r\n * Add a custom agent signature\r\n */\r\n addAgent(agent: AgentSignature): void {\r\n this.agents.push(agent)\r\n }\r\n\r\n /**\r\n * Get all configured agent signatures\r\n */\r\n getAgents(): AgentSignature[] {\r\n return [...this.agents]\r\n }\r\n}\r\n","/**\r\n * Egress Patterns - Pattern matching for sensitive data detection\r\n *\r\n * Provides pattern definitions and matching utilities for detecting\r\n * credentials, PII, and other sensitive data in egress traffic.\r\n */\r\n\r\nimport type {\r\n EgressPattern,\r\n PatternSeverity,\r\n RedactedPayload,\r\n RedactionInfo,\r\n} from './types.js'\r\n\r\n/**\r\n * Default patterns for detecting sensitive data\r\n */\r\nexport const DEFAULT_PATTERNS: EgressPattern[] = [\r\n // Credential patterns\r\n {\r\n name: 'api_key',\r\n regex: '(?:api[_-]?key|apikey)[\\\\s]*[=:][\\\\s]*[\"\\']?([a-zA-Z0-9_\\\\-]{20,})[\"\\']?',\r\n severity: 'high',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'Generic API key pattern',\r\n },\r\n {\r\n name: 'aws_secret',\r\n regex: '(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key)[\\\\s]*[=:][\\\\s]*[\"\\']?([a-zA-Z0-9/+=]{40})[\"\\']?',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'AWS Secret Access Key',\r\n },\r\n {\r\n name: 'private_key',\r\n regex: '-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'Private key header',\r\n },\r\n {\r\n name: 'github_token',\r\n regex: '(?:gh[pousr]_[a-zA-Z0-9]{36,}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'GitHub personal access token',\r\n },\r\n {\r\n name: 'openai_key',\r\n regex: 'sk-[a-zA-Z0-9]{20,}T3BlbkFJ[a-zA-Z0-9]{20,}',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'credentials',\r\n description: 'OpenAI API key',\r\n },\r\n {\r\n name: 'jwt_token',\r\n regex: 'eyJ[a-zA-Z0-9_-]*\\\\.eyJ[a-zA-Z0-9_-]*\\\\.[a-zA-Z0-9_-]*',\r\n severity: 'high',\r\n action: 'alert',\r\n category: 'credentials',\r\n description: 'JSON Web Token',\r\n },\r\n\r\n // PII patterns\r\n {\r\n name: 'ssn',\r\n regex: '\\\\b\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}\\\\b',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'pii',\r\n description: 'US Social Security Number',\r\n },\r\n {\r\n name: 'credit_card',\r\n regex: '\\\\b(?:4[0-9]{3}|5[1-5][0-9]{2}|6(?:011|5[0-9]{2})|3[47][0-9]{2})[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}\\\\b',\r\n severity: 'critical',\r\n action: 'block',\r\n category: 'pii',\r\n description: 'Credit card number (Visa, MasterCard, Amex, Discover)',\r\n },\r\n {\r\n name: 'email',\r\n regex: '\\\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}\\\\b',\r\n severity: 'low',\r\n action: 'log',\r\n category: 'pii',\r\n description: 'Email address',\r\n },\r\n {\r\n name: 'phone_us',\r\n regex: '\\\\b(?:\\\\+1[- ]?)?(?:\\\\([0-9]{3}\\\\)|[0-9]{3})[- ]?[0-9]{3}[- ]?[0-9]{4}\\\\b',\r\n severity: 'medium',\r\n action: 'alert',\r\n category: 'pii',\r\n description: 'US phone number',\r\n },\r\n]\r\n\r\n/**\r\n * Pattern match result\r\n */\r\nexport interface PatternMatch {\r\n pattern: EgressPattern\r\n matchedText: string\r\n index: number\r\n}\r\n\r\n/**\r\n * Severity ordering for comparison\r\n */\r\nconst SEVERITY_ORDER: Record<PatternSeverity, number> = {\r\n low: 1,\r\n medium: 2,\r\n high: 3,\r\n critical: 4,\r\n}\r\n\r\n/**\r\n * EgressPatternMatcher - Matches and redacts sensitive data in text\r\n */\r\nexport class EgressPatternMatcher {\r\n private patterns: EgressPattern[]\r\n private compiledPatterns: Map<string, RegExp>\r\n\r\n constructor(customPatterns?: EgressPattern[]) {\r\n this.patterns = [...DEFAULT_PATTERNS]\r\n this.compiledPatterns = new Map()\r\n\r\n if (customPatterns) {\r\n for (const pattern of customPatterns) {\r\n this.patterns.push(pattern)\r\n }\r\n }\r\n\r\n // Pre-compile all patterns\r\n this.compilePatterns()\r\n }\r\n\r\n /**\r\n * Compile regex patterns for efficient matching\r\n */\r\n private compilePatterns(): void {\r\n for (const pattern of this.patterns) {\r\n if (!this.compiledPatterns.has(pattern.name)) {\r\n try {\r\n this.compiledPatterns.set(pattern.name, new RegExp(pattern.regex, 'gi'))\r\n } catch {\r\n // Invalid regex - skip pattern\r\n console.warn(`Invalid regex for pattern ${pattern.name}: ${pattern.regex}`)\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Find all pattern matches in text\r\n */\r\n match(text: string): PatternMatch[] {\r\n const matches: PatternMatch[] = []\r\n\r\n for (const pattern of this.patterns) {\r\n const regex = this.compiledPatterns.get(pattern.name)\r\n if (!regex) continue\r\n\r\n // Reset regex state\r\n regex.lastIndex = 0\r\n\r\n let match: RegExpExecArray | null\r\n while ((match = regex.exec(text)) !== null) {\r\n matches.push({\r\n pattern,\r\n matchedText: match[0],\r\n index: match.index,\r\n })\r\n }\r\n }\r\n\r\n return matches\r\n }\r\n\r\n /**\r\n * Check if any blocking patterns match the text\r\n */\r\n shouldBlock(text: string): boolean {\r\n const matches = this.match(text)\r\n return matches.some(m => m.pattern.action === 'block')\r\n }\r\n\r\n /**\r\n * Get the highest severity level from all matches\r\n */\r\n getHighestSeverity(text: string): PatternSeverity | null {\r\n const matches = this.match(text)\r\n if (matches.length === 0) return null\r\n\r\n let highest: PatternSeverity = 'low'\r\n for (const m of matches) {\r\n if (SEVERITY_ORDER[m.pattern.severity] > SEVERITY_ORDER[highest]) {\r\n highest = m.pattern.severity\r\n }\r\n }\r\n\r\n return highest\r\n }\r\n\r\n /**\r\n * Redact sensitive data from text\r\n */\r\n redact(text: string): RedactedPayload {\r\n const matches = this.match(text)\r\n const redactions: RedactionInfo[] = []\r\n let redacted = text\r\n\r\n // Sort matches by index in reverse order to preserve positions during replacement\r\n const sortedMatches = [...matches].sort((a, b) => b.index - a.index)\r\n\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n\r\n // Map pattern category to RedactionInfo type\r\n let redactionType: RedactionInfo['type']\r\n if (m.pattern.name === 'api_key' || m.pattern.name === 'aws_secret' ||\r\n m.pattern.name === 'private_key' || m.pattern.name === 'github_token' ||\r\n m.pattern.name === 'openai_key' || m.pattern.name === 'jwt_token') {\r\n redactionType = 'api_key'\r\n } else if (m.pattern.name === 'email') {\r\n redactionType = 'email'\r\n } else if (m.pattern.name === 'phone_us') {\r\n redactionType = 'phone'\r\n } else if (m.pattern.name === 'ssn') {\r\n redactionType = 'ssn'\r\n } else if (m.pattern.name === 'credit_card') {\r\n redactionType = 'credit_card'\r\n } else {\r\n redactionType = 'custom'\r\n }\r\n\r\n redactions.push({\r\n type: redactionType,\r\n replacement,\r\n })\r\n\r\n // Replace the matched text\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n\r\n return {\r\n original: text,\r\n redacted,\r\n redactions: redactions.reverse(), // Return in original order\r\n }\r\n }\r\n\r\n /**\r\n * Add a custom pattern\r\n */\r\n addPattern(pattern: EgressPattern): void {\r\n this.patterns.push(pattern)\r\n try {\r\n this.compiledPatterns.set(pattern.name, new RegExp(pattern.regex, 'gi'))\r\n } catch {\r\n console.warn(`Invalid regex for pattern ${pattern.name}: ${pattern.regex}`)\r\n }\r\n }\r\n\r\n /**\r\n * Get all configured patterns\r\n */\r\n getPatterns(): EgressPattern[] {\r\n return [...this.patterns]\r\n }\r\n\r\n /**\r\n * Test helper - returns matches, shouldBlock, and redacted result\r\n */\r\n test(text: string): {\r\n matches: PatternMatch[]\r\n shouldBlock: boolean\r\n redacted: RedactedPayload\r\n } {\r\n return {\r\n matches: this.match(text),\r\n shouldBlock: this.shouldBlock(text),\r\n redacted: this.redact(text),\r\n }\r\n }\r\n}\r\n","/**\r\n * Egress Monitor - Monitors and blocks sensitive data in outbound traffic\r\n *\r\n * Provides inspection of content for sensitive patterns (API keys, PII, etc.)\r\n * with support for connector-based allowlisting and pattern-specific exceptions.\r\n */\r\n\r\nimport { EgressPatternMatcher, type PatternMatch } from './patterns.js'\r\nimport type {\r\n EgressPattern,\r\n EgressConfig,\r\n EgressAllowlistEntry,\r\n EgressMatch,\r\n} from './types.js'\r\n\r\n// Optional database import - gracefully handle if unavailable\r\nlet DashboardDB: typeof import('../../dashboard/db.js').DashboardDB | null = null\r\ntry {\r\n const dbModule = await import('../../dashboard/db.js')\r\n DashboardDB = dbModule.DashboardDB\r\n} catch {\r\n // Database unavailable - operate without persistence\r\n}\r\n\r\n/**\r\n * Result of content inspection\r\n */\r\nexport interface InspectionResult {\r\n /** Whether the content was blocked */\r\n blocked: boolean\r\n /** Whether the content was allowlisted (skipped inspection) */\r\n allowlisted: boolean\r\n /** Patterns that matched */\r\n matches: PatternMatch[]\r\n /** Content with sensitive data redacted */\r\n redacted: string\r\n /** Block ID if content was recorded to database */\r\n blockId?: string\r\n}\r\n\r\n/**\r\n * Default egress configuration\r\n */\r\nconst DEFAULT_EGRESS_CONFIG: EgressConfig = {\r\n enabled: true,\r\n defaultAction: 'block',\r\n allowlist: [],\r\n}\r\n\r\n/**\r\n * EgressMonitor - Monitors outbound content for sensitive data\r\n */\r\nexport class EgressMonitor {\r\n private config: EgressConfig\r\n private matcher: EgressPatternMatcher\r\n private db: InstanceType<typeof import('../../dashboard/db.js').DashboardDB> | null = null\r\n private allowlist: EgressAllowlistEntry[]\r\n\r\n constructor(config?: Partial<EgressConfig>) {\r\n this.config = { ...DEFAULT_EGRESS_CONFIG, ...config }\r\n this.matcher = new EgressPatternMatcher()\r\n this.allowlist = [...this.config.allowlist]\r\n\r\n // Try to initialize database\r\n if (DashboardDB) {\r\n try {\r\n this.db = new DashboardDB()\r\n } catch {\r\n // Database initialization failed - operate without persistence\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Inspect content for sensitive data\r\n *\r\n * @param content - The content to inspect\r\n * @param connector - Optional connector name for allowlist checking\r\n * @param destination - Optional destination for allowlist checking\r\n * @returns Inspection result with blocking decision and matches\r\n */\r\n inspect(content: string, connector?: string, destination?: string): InspectionResult {\r\n // Check if fully allowlisted (skip all inspection)\r\n if (this.isAllowlisted(connector, destination)) {\r\n return {\r\n blocked: false,\r\n allowlisted: true,\r\n matches: [],\r\n redacted: content,\r\n }\r\n }\r\n\r\n // Get all matches\r\n const allMatches = this.matcher.match(content)\r\n\r\n // Filter out pattern-specific allowlisted matches\r\n const effectiveMatches = allMatches.filter(match => {\r\n return !this.isPatternAllowlisted(match.pattern.name, connector, destination)\r\n })\r\n\r\n // Check if any remaining matches should block\r\n const shouldBlock = effectiveMatches.some(m => m.pattern.action === 'block')\r\n\r\n // Redact content based on effective matches\r\n let redacted = content\r\n if (effectiveMatches.length > 0) {\r\n // Sort by index descending to preserve positions during replacement\r\n const sortedMatches = [...effectiveMatches].sort((a, b) => b.index - a.index)\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n }\r\n\r\n // Check if all matched patterns were allowlisted\r\n const wasAllowlisted = allMatches.length > 0 && effectiveMatches.length === 0\r\n\r\n const result: InspectionResult = {\r\n blocked: shouldBlock,\r\n allowlisted: wasAllowlisted,\r\n matches: effectiveMatches,\r\n redacted,\r\n }\r\n\r\n // Record to database if blocking\r\n if (shouldBlock && this.db) {\r\n try {\r\n // Record each blocking match\r\n for (const match of effectiveMatches.filter(m => m.pattern.action === 'block')) {\r\n const blockId = this.db.insertEgressBlock({\r\n pattern: match.pattern,\r\n matchedText: match.matchedText.substring(0, 100), // Truncate for safety\r\n redactedText: redacted,\r\n connector,\r\n destination,\r\n })\r\n result.blockId = blockId\r\n }\r\n\r\n // Log the event\r\n this.db.insertEvent({\r\n source: 'ward',\r\n level: 'warn',\r\n category: 'egress',\r\n message: `Blocked egress: ${effectiveMatches.map(m => m.pattern.name).join(', ')}`,\r\n data: {\r\n connector,\r\n destination,\r\n patternNames: effectiveMatches.map(m => m.pattern.name),\r\n },\r\n })\r\n } catch {\r\n // Database operation failed - continue without persistence\r\n }\r\n }\r\n\r\n return result\r\n }\r\n\r\n /**\r\n * Check if connector/destination combination is fully allowlisted\r\n */\r\n private isAllowlisted(connector?: string, destination?: string): boolean {\r\n return this.allowlist.some(entry => {\r\n // Skip pattern-specific entries (they don't allowlist all inspection)\r\n if (entry.pattern) return false\r\n\r\n // Check connector match\r\n if (entry.connector && entry.destination) {\r\n // Both specified - must match both\r\n return entry.connector === connector && entry.destination === destination\r\n }\r\n\r\n if (entry.connector) {\r\n return entry.connector === connector\r\n }\r\n\r\n if (entry.destination) {\r\n return entry.destination === destination\r\n }\r\n\r\n return false\r\n })\r\n }\r\n\r\n /**\r\n * Check if a specific pattern is allowlisted for the connector/destination\r\n */\r\n private isPatternAllowlisted(\r\n patternName: string,\r\n connector?: string,\r\n destination?: string\r\n ): boolean {\r\n return this.allowlist.some(entry => {\r\n // Only check pattern-specific entries\r\n if (!entry.pattern || entry.pattern !== patternName) return false\r\n\r\n // Check connector/destination match\r\n if (entry.connector && entry.destination) {\r\n return entry.connector === connector && entry.destination === destination\r\n }\r\n\r\n if (entry.connector) {\r\n return entry.connector === connector\r\n }\r\n\r\n if (entry.destination) {\r\n return entry.destination === destination\r\n }\r\n\r\n // Pattern allowlist with no connector/destination matches all\r\n return true\r\n })\r\n }\r\n\r\n /**\r\n * Add an allowlist entry\r\n */\r\n addAllowlistEntry(entry: EgressAllowlistEntry): void {\r\n this.allowlist.push(entry)\r\n }\r\n\r\n /**\r\n * Add a custom pattern\r\n */\r\n addPattern(pattern: EgressPattern): void {\r\n this.matcher.addPattern(pattern)\r\n }\r\n\r\n /**\r\n * Get pending blocks from database\r\n */\r\n getPendingBlocks(): EgressMatch[] {\r\n if (!this.db) return []\r\n try {\r\n return this.db.getPendingBlocks()\r\n } catch {\r\n return []\r\n }\r\n }\r\n\r\n /**\r\n * Approve a pending block\r\n */\r\n approveBlock(id: string, approvedBy?: string): void {\r\n if (!this.db) return\r\n try {\r\n this.db.approveBlock(id, approvedBy ?? 'system')\r\n } catch {\r\n // Database operation failed\r\n }\r\n }\r\n\r\n /**\r\n * Deny a pending block\r\n */\r\n denyBlock(id: string): void {\r\n if (!this.db) return\r\n try {\r\n this.db.denyBlock(id, 'system')\r\n } catch {\r\n // Database operation failed\r\n }\r\n }\r\n\r\n /**\r\n * Test content without recording to database\r\n * Useful for CLI testing of patterns\r\n */\r\n test(content: string): {\r\n blocked: boolean\r\n matches: PatternMatch[]\r\n redacted: string\r\n } {\r\n const matches = this.matcher.match(content)\r\n const shouldBlock = matches.some(m => m.pattern.action === 'block')\r\n\r\n // Redact content\r\n let redacted = content\r\n if (matches.length > 0) {\r\n const sortedMatches = [...matches].sort((a, b) => b.index - a.index)\r\n for (const m of sortedMatches) {\r\n const replacement = `[REDACTED:${m.pattern.name}]`\r\n redacted =\r\n redacted.substring(0, m.index) +\r\n replacement +\r\n redacted.substring(m.index + m.matchedText.length)\r\n }\r\n }\r\n\r\n return {\r\n blocked: shouldBlock,\r\n matches,\r\n redacted,\r\n }\r\n }\r\n}\r\n","import chalk from 'chalk'\r\nimport { readFileSync, writeFileSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { BashBros } from './core.js'\r\nimport { findConfig } from './config.js'\r\nimport { allowForSession } from './session.js'\r\nimport { DashboardWriter } from './dashboard/writer.js'\r\nimport { RiskScorer, type RiskScore } from './policy/risk-scorer.js'\r\n\r\n// Dashboard writer and risk scorer for monitoring\r\nlet dashboardWriter: DashboardWriter | null = null\r\nlet riskScorer: RiskScorer | null = null\r\n\r\nfunction cleanup(): void {\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(false)\r\n }\r\n}\r\n\r\nexport async function startWatch(options: { verbose?: boolean }): Promise<void> {\r\n const configPath = findConfig()\r\n\r\n if (!configPath) {\r\n console.log(chalk.red('No config found. Run \"bashbros init\" first.'))\r\n process.exit(1)\r\n }\r\n\r\n console.log(chalk.dim(' \"I watch your agent\\'s back so you don\\'t have to.\"'))\r\n console.log()\r\n console.log(chalk.green('✓'), 'Protection active')\r\n console.log(chalk.dim(` Config: ${configPath}`))\r\n console.log(chalk.dim(' Press Ctrl+C to stop'))\r\n console.log()\r\n\r\n const bashbros = new BashBros(configPath)\r\n const config = bashbros.getConfig()\r\n\r\n // Initialize dashboard writer and risk scorer\r\n try {\r\n dashboardWriter = new DashboardWriter()\r\n riskScorer = new RiskScorer()\r\n\r\n // Start a new session\r\n const sessionId = dashboardWriter.startSession(config.agent, process.cwd())\r\n if (options.verbose) {\r\n console.log(chalk.dim(` Session: ${sessionId}`))\r\n }\r\n } catch (error) {\r\n // Dashboard writing is non-critical, continue without it\r\n if (options.verbose) {\r\n console.log(chalk.yellow(' Dashboard recording disabled'))\r\n }\r\n }\r\n\r\n // State for interactive prompt when command is blocked\r\n let pendingCommand: string | null = null\r\n let awaitingPromptResponse = false\r\n\r\n function showBlockedPrompt(command: string, violations: { message: string; rule: string }[]): void {\r\n pendingCommand = command\r\n awaitingPromptResponse = true\r\n\r\n console.log()\r\n console.log(chalk.red('🛡️ BashBros blocked a command'))\r\n console.log()\r\n console.log(chalk.dim(' Command:'), command)\r\n console.log(chalk.dim(' Reason:'), violations[0].message)\r\n console.log(chalk.dim(' Policy:'), violations[0].rule)\r\n console.log()\r\n console.log(chalk.yellow(' Allow this command?'))\r\n console.log(chalk.cyan(' [y]'), 'Allow once')\r\n console.log(chalk.cyan(' [s]'), 'Allow for session')\r\n console.log(chalk.cyan(' [p]'), 'Allow permanently')\r\n console.log(chalk.cyan(' [n]'), 'Block (default)')\r\n process.stdout.write(chalk.dim('\\n Choice: '))\r\n }\r\n\r\n function handlePromptResponse(choice: string): void {\r\n if (!pendingCommand) return\r\n\r\n const command = pendingCommand\r\n pendingCommand = null\r\n awaitingPromptResponse = false\r\n\r\n console.log(choice) // Echo the choice\r\n\r\n switch (choice.toLowerCase()) {\r\n case 'y':\r\n // Allow once - just execute, no persistence\r\n console.log(chalk.green(' ✓ Allowed once'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n break\r\n\r\n case 's':\r\n // Allow for session\r\n allowForSession(command)\r\n console.log(chalk.green(' ✓ Allowed for session'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n break\r\n\r\n case 'p':\r\n // Allow permanently - update config file\r\n try {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n\r\n if (!config.commands) {\r\n config.commands = { allow: [], block: [] }\r\n }\r\n if (!config.commands.allow) {\r\n config.commands.allow = []\r\n }\r\n\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n }\r\n\r\n console.log(chalk.green(' ✓ Added to allowlist permanently'))\r\n console.log()\r\n bashbros.write(command + '\\r')\r\n } catch (error) {\r\n console.log(chalk.red(' ✗ Failed to update config'))\r\n console.log()\r\n }\r\n break\r\n\r\n case 'n':\r\n default:\r\n // Keep blocked\r\n console.log(chalk.yellow(' ✗ Blocked'))\r\n console.log()\r\n break\r\n }\r\n }\r\n\r\n bashbros.on('blocked', (command, violations) => {\r\n // Record blocked command to dashboard\r\n if (dashboardWriter && riskScorer) {\r\n const risk = riskScorer.score(command)\r\n dashboardWriter.recordCommand(command, false, risk, violations, 0)\r\n }\r\n showBlockedPrompt(command, violations)\r\n })\r\n\r\n bashbros.on('allowed', (result) => {\r\n // Record allowed command to dashboard\r\n if (dashboardWriter && riskScorer) {\r\n const risk = riskScorer.score(result.command)\r\n dashboardWriter.recordCommand(result.command, true, risk, [], result.duration)\r\n }\r\n if (options.verbose) {\r\n console.log(chalk.green('✓'), chalk.dim(result.command))\r\n }\r\n })\r\n\r\n bashbros.on('output', (data) => {\r\n process.stdout.write(data)\r\n })\r\n\r\n bashbros.on('error', (error) => {\r\n console.error(chalk.red('Error:'), error.message)\r\n })\r\n\r\n // Handle PTY exit\r\n bashbros.on('exit', (exitCode) => {\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n cleanup()\r\n process.exit(exitCode ?? 0)\r\n })\r\n\r\n // Handle graceful shutdown\r\n process.on('SIGINT', () => {\r\n cleanup()\r\n console.log()\r\n console.log(chalk.yellow('Stopping BashBros...'))\r\n\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n bashbros.stop()\r\n process.exit(0)\r\n })\r\n\r\n process.on('SIGTERM', () => {\r\n cleanup()\r\n\r\n // End dashboard session\r\n if (dashboardWriter) {\r\n dashboardWriter.endSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n bashbros.stop()\r\n process.exit(0)\r\n })\r\n\r\n // Handle unexpected crashes\r\n process.on('uncaughtException', (error) => {\r\n console.error(chalk.red('Unexpected error:'), error.message)\r\n\r\n // Mark session as crashed\r\n if (dashboardWriter) {\r\n dashboardWriter.crashSession()\r\n dashboardWriter.close()\r\n }\r\n\r\n cleanup()\r\n bashbros.stop()\r\n process.exit(1)\r\n })\r\n\r\n bashbros.start()\r\n\r\n // Command buffer for validation\r\n let commandBuffer = ''\r\n\r\n // Set initial PTY size to match terminal\r\n if (process.stdout.isTTY) {\r\n bashbros.resize(process.stdout.columns, process.stdout.rows)\r\n }\r\n\r\n // Handle terminal resize\r\n process.stdout.on('resize', () => {\r\n if (process.stdout.isTTY) {\r\n bashbros.resize(process.stdout.columns, process.stdout.rows)\r\n }\r\n })\r\n\r\n // Enable raw mode for character-by-character input\r\n if (process.stdin.isTTY) {\r\n process.stdin.setRawMode(true)\r\n }\r\n process.stdin.resume()\r\n\r\n // Handle stdin with command interception\r\n process.stdin.on('data', (data) => {\r\n const str = data.toString()\r\n\r\n for (const char of str) {\r\n const code = char.charCodeAt(0)\r\n\r\n // If awaiting prompt response, handle it separately\r\n if (awaitingPromptResponse) {\r\n if (code === 3) {\r\n // Ctrl+C cancels the prompt\r\n pendingCommand = null\r\n awaitingPromptResponse = false\r\n console.log(chalk.yellow('Cancelled'))\r\n console.log()\r\n } else if (char === '\\r' || char === '\\n') {\r\n // Enter with no choice = block (default)\r\n handlePromptResponse('n')\r\n } else if (code >= 32) {\r\n // Letter response\r\n handlePromptResponse(char)\r\n }\r\n continue\r\n }\r\n\r\n // Enter key - validate command before allowing execution\r\n if (char === '\\r' || char === '\\n') {\r\n const command = commandBuffer.trim()\r\n commandBuffer = ''\r\n\r\n if (command) {\r\n // Validate the command (don't use execute() - command is already in PTY buffer)\r\n const violations = bashbros.validateOnly(command)\r\n\r\n if (violations.length > 0) {\r\n // Blocked - clear the line and emit blocked event\r\n bashbros.write('\\x15') // Ctrl+U to clear line\r\n bashbros.write('\\r') // New line\r\n bashbros.emit('blocked', command, violations)\r\n } else {\r\n // Allowed - just send Enter to execute the already-typed command\r\n bashbros.write('\\r')\r\n }\r\n } else {\r\n // Empty command (just Enter) - pass through\r\n bashbros.write('\\r')\r\n }\r\n }\r\n // Backspace/Delete - remove from buffer\r\n else if (code === 127 || code === 8) {\r\n if (commandBuffer.length > 0) {\r\n commandBuffer = commandBuffer.slice(0, -1)\r\n }\r\n bashbros.write(char)\r\n }\r\n // Escape sequence start\r\n else if (code === 27) {\r\n // Pass through escape sequences\r\n bashbros.write(char)\r\n }\r\n // Ctrl+C - clear buffer\r\n else if (code === 3) {\r\n commandBuffer = ''\r\n bashbros.write(char)\r\n }\r\n // Ctrl+U (clear line)\r\n else if (code === 21) {\r\n commandBuffer = ''\r\n bashbros.write(char)\r\n }\r\n // Regular character - add to buffer and forward\r\n else if (code >= 32 || char === '\\t') {\r\n commandBuffer += char\r\n bashbros.write(char)\r\n }\r\n // Other control characters - pass through\r\n else {\r\n bashbros.write(char)\r\n }\r\n }\r\n })\r\n\r\n // Keep process alive\r\n await new Promise(() => {})\r\n}\r\n","import chalk from 'chalk'\r\nimport { readFileSync, writeFileSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { findConfig } from './config.js'\r\nimport { allowForSession, getSessionAllowlist, clearSessionAllowlist } from './session.js'\r\n\r\nexport async function handleAllow(\r\n command: string,\r\n options: { once?: boolean; persist?: boolean }\r\n): Promise<void> {\r\n if (options.once) {\r\n // Add to session allowlist\r\n allowForSession(command)\r\n console.log(chalk.green('✓'), `Allowed for this session: ${command}`)\r\n console.log(chalk.dim(' This will reset when BashBros restarts.'))\r\n return\r\n }\r\n\r\n if (options.persist) {\r\n const configPath = findConfig()\r\n\r\n if (!configPath) {\r\n console.log(chalk.red('No config found. Run \"bashbros init\" first.'))\r\n process.exit(1)\r\n }\r\n\r\n try {\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n\r\n // Initialize commands.allow if it doesn't exist\r\n if (!config.commands) {\r\n config.commands = { allow: [], block: [] }\r\n }\r\n if (!config.commands.allow) {\r\n config.commands.allow = []\r\n }\r\n\r\n // Add command pattern if not already present\r\n if (!config.commands.allow.includes(command)) {\r\n config.commands.allow.push(command)\r\n writeFileSync(configPath, stringify(config))\r\n\r\n console.log(chalk.green('✓'), `Added to allowlist: ${command}`)\r\n console.log(chalk.dim(` Updated ${configPath}`))\r\n } else {\r\n console.log(chalk.yellow('Already in allowlist:'), command)\r\n }\r\n } catch (error) {\r\n console.error(chalk.red('Failed to update config:'), error)\r\n process.exit(1)\r\n }\r\n\r\n return\r\n }\r\n\r\n // No flag specified - show help\r\n console.log(chalk.yellow('Specify how to allow this command:'))\r\n console.log()\r\n console.log(chalk.cyan(` bashbros allow \"${command}\" --once`))\r\n console.log(chalk.dim(' Allow for current session only'))\r\n console.log()\r\n console.log(chalk.cyan(` bashbros allow \"${command}\" --persist`))\r\n console.log(chalk.dim(' Add to config file permanently'))\r\n}\r\n","/**\r\n * Dashboard Server Module\r\n * Express HTTP server with WebSocket support for real-time dashboard updates\r\n */\r\n\r\nimport express, { type Express, type Request, type Response } from 'express'\r\nimport { WebSocketServer, type WebSocket } from 'ws'\r\nimport { createServer, type Server } from 'http'\r\nimport { fileURLToPath } from 'url'\r\nimport { dirname, join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'\r\nimport { parse, stringify } from 'yaml'\r\nimport { DashboardDB } from './db.js'\r\nimport { findConfig } from '../config.js'\r\n\r\n// Default dashboard database path\r\nfunction getDefaultDbPath(): string {\r\n const bashbrosDir = join(homedir(), '.bashbros')\r\n if (!existsSync(bashbrosDir)) {\r\n mkdirSync(bashbrosDir, { recursive: true })\r\n }\r\n return join(bashbrosDir, 'dashboard.db')\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Types\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport interface ServerConfig {\r\n port?: number\r\n bind?: string\r\n dbPath?: string\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────\r\n// Dashboard Server Class\r\n// ─────────────────────────────────────────────────────────────\r\n\r\nexport class DashboardServer {\r\n private app: Express\r\n private server: Server | null = null\r\n private wss: WebSocketServer | null = null\r\n private db: DashboardDB\r\n private port: number\r\n private bind: string\r\n private clients: Set<WebSocket> = new Set()\r\n\r\n constructor(config: ServerConfig = {}) {\r\n this.port = config.port ?? 17800\r\n this.bind = config.bind ?? '127.0.0.1'\r\n // Use persistent database path by default for shared access with watch mode\r\n this.db = new DashboardDB(config.dbPath ?? getDefaultDbPath())\r\n this.app = express()\r\n\r\n this.setupMiddleware()\r\n this.setupRoutes()\r\n }\r\n\r\n private setupMiddleware(): void {\r\n this.app.use(express.json())\r\n\r\n // CORS headers for local development\r\n this.app.use((_req: Request, res: Response, next) => {\r\n res.header('Access-Control-Allow-Origin', '*')\r\n res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\r\n res.header('Access-Control-Allow-Headers', 'Content-Type')\r\n next()\r\n })\r\n }\r\n\r\n private setupRoutes(): void {\r\n // Health check endpoint\r\n this.app.get('/api/health', (_req: Request, res: Response) => {\r\n res.json({ status: 'ok', timestamp: new Date().toISOString() })\r\n })\r\n\r\n // Get dashboard stats\r\n this.app.get('/api/stats', (_req: Request, res: Response) => {\r\n try {\r\n const stats = this.db.getStats()\r\n res.json(stats)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch stats' })\r\n }\r\n })\r\n\r\n // Get events with optional filtering\r\n this.app.get('/api/events', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.source) filter.source = req.query.source\r\n if (req.query.level) filter.level = req.query.level\r\n if (req.query.category) filter.category = req.query.category\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n\r\n const events = this.db.getEvents(filter)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch events' })\r\n }\r\n })\r\n\r\n // Get unique connectors\r\n this.app.get('/api/connectors', (_req: Request, res: Response) => {\r\n try {\r\n // Get all connector events and extract unique connector names\r\n const events = this.db.getAllConnectorEvents(1000)\r\n const connectors = [...new Set(events.map(e => e.connector))]\r\n res.json(connectors)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch connectors' })\r\n }\r\n })\r\n\r\n // Get events for a specific connector\r\n this.app.get('/api/connectors/:name/events', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const events = this.db.getConnectorEvents(req.params.name, limit)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch connector events' })\r\n }\r\n })\r\n\r\n // Get pending egress blocks\r\n this.app.get('/api/blocked', (_req: Request, res: Response) => {\r\n try {\r\n const blocks = this.db.getPendingBlocks()\r\n res.json(blocks)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch blocked items' })\r\n }\r\n })\r\n\r\n // Approve a blocked egress\r\n this.app.post('/api/blocked/:id/approve', (req: Request, res: Response) => {\r\n try {\r\n const { id } = req.params\r\n const approvedBy = req.body?.approvedBy ?? 'dashboard-user'\r\n\r\n const block = this.db.getBlock(id)\r\n if (!block) {\r\n res.status(404).json({ error: 'Block not found' })\r\n return\r\n }\r\n\r\n this.db.approveBlock(id, approvedBy)\r\n this.broadcast({ type: 'block-approved', id })\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to approve block' })\r\n }\r\n })\r\n\r\n // Deny a blocked egress\r\n this.app.post('/api/blocked/:id/deny', (req: Request, res: Response) => {\r\n try {\r\n const { id } = req.params\r\n const deniedBy = req.body?.deniedBy ?? 'dashboard-user'\r\n\r\n const block = this.db.getBlock(id)\r\n if (!block) {\r\n res.status(404).json({ error: 'Block not found' })\r\n return\r\n }\r\n\r\n this.db.denyBlock(id, deniedBy)\r\n this.broadcast({ type: 'block-denied', id })\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to deny block' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Session Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // List sessions with pagination and filters\r\n this.app.get('/api/sessions', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.status) filter.status = req.query.status\r\n if (req.query.agent) filter.agent = req.query.agent\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n if (req.query.until) filter.until = new Date(req.query.until as string)\r\n\r\n const sessions = this.db.getSessions(filter)\r\n res.json(sessions)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch sessions' })\r\n }\r\n })\r\n\r\n // Get active session\r\n this.app.get('/api/sessions/active', (_req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getActiveSession()\r\n if (!session) {\r\n res.json(null)\r\n return\r\n }\r\n res.json(session)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch active session' })\r\n }\r\n })\r\n\r\n // Get session details\r\n this.app.get('/api/sessions/:id', (req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getSession(req.params.id)\r\n if (!session) {\r\n res.status(404).json({ error: 'Session not found' })\r\n return\r\n }\r\n res.json(session)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session' })\r\n }\r\n })\r\n\r\n // Get commands for a session\r\n this.app.get('/api/sessions/:id/commands', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const commands = this.db.getCommandsBySession(req.params.id, limit)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session commands' })\r\n }\r\n })\r\n\r\n // Get session metrics\r\n this.app.get('/api/sessions/:id/metrics', (req: Request, res: Response) => {\r\n try {\r\n const session = this.db.getSession(req.params.id)\r\n if (!session) {\r\n res.status(404).json({ error: 'Session not found' })\r\n return\r\n }\r\n const metrics = this.db.getSessionMetrics(req.params.id)\r\n res.json(metrics)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch session metrics' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Command Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get live commands (most recent)\r\n this.app.get('/api/commands/live', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 20\r\n const commands = this.db.getLiveCommands(limit)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch live commands' })\r\n }\r\n })\r\n\r\n // Get commands with incremental fetch support\r\n this.app.get('/api/commands', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.sessionId) filter.sessionId = req.query.sessionId\r\n if (req.query.allowed !== undefined) filter.allowed = req.query.allowed === 'true'\r\n if (req.query.riskLevel) filter.riskLevel = req.query.riskLevel\r\n if (req.query.afterId) filter.afterId = req.query.afterId\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n\r\n const commands = this.db.getCommands(filter)\r\n res.json(commands)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch commands' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Tool Uses Endpoints (all Claude Code tools)\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get live tool uses (most recent)\r\n this.app.get('/api/tools/live', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 50\r\n const tools = this.db.getLiveToolUses(limit)\r\n res.json(tools)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch live tool uses' })\r\n }\r\n })\r\n\r\n // Get tool uses with filtering\r\n this.app.get('/api/tools', (req: Request, res: Response) => {\r\n try {\r\n const filter: Record<string, unknown> = {}\r\n\r\n if (req.query.toolName) filter.toolName = req.query.toolName\r\n if (req.query.since) filter.since = new Date(req.query.since as string)\r\n if (req.query.limit) filter.limit = parseInt(req.query.limit as string, 10)\r\n if (req.query.offset) filter.offset = parseInt(req.query.offset as string, 10)\r\n\r\n const tools = this.db.getToolUses(filter)\r\n res.json(tools)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch tool uses' })\r\n }\r\n })\r\n\r\n // Get tool use stats\r\n this.app.get('/api/tools/stats', (_req: Request, res: Response) => {\r\n try {\r\n const stats = this.db.getToolUseStats()\r\n res.json(stats)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch tool use stats' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Bash Bro Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get Bash Bro status\r\n this.app.get('/api/bro/status', (_req: Request, res: Response) => {\r\n try {\r\n const status = this.db.getLatestBroStatus()\r\n res.json(status)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch Bro status' })\r\n }\r\n })\r\n\r\n // Get Bash Bro events\r\n this.app.get('/api/bro/events', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const sessionId = req.query.sessionId as string | undefined\r\n const events = this.db.getBroEvents(limit, sessionId)\r\n res.json(events)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch Bro events' })\r\n }\r\n })\r\n\r\n // Get available Ollama models\r\n this.app.get('/api/bro/models', async (_req: Request, res: Response) => {\r\n try {\r\n // Try to fetch models from Ollama\r\n const controller = new AbortController()\r\n const timeout = setTimeout(() => controller.abort(), 5000)\r\n\r\n const response = await fetch('http://localhost:11434/api/tags', {\r\n signal: controller.signal\r\n })\r\n\r\n clearTimeout(timeout)\r\n\r\n if (!response.ok) {\r\n res.json({ available: false, models: [] })\r\n return\r\n }\r\n\r\n const data = await response.json() as { models?: { name: string }[] }\r\n const models = data.models?.map((m) => m.name) || []\r\n res.json({ available: true, models })\r\n } catch (error) {\r\n res.json({ available: false, models: [] })\r\n }\r\n })\r\n\r\n // Change Ollama model (writes to a control file that watch mode can pick up)\r\n this.app.post('/api/bro/model', (req: Request, res: Response) => {\r\n try {\r\n const { model } = req.body\r\n if (!model) {\r\n res.status(400).json({ error: 'Model name required' })\r\n return\r\n }\r\n\r\n // Write to control file in .bashbros directory\r\n const controlPath = join(homedir(), '.bashbros', 'model-control.json')\r\n writeFileSync(controlPath, JSON.stringify({\r\n model,\r\n timestamp: new Date().toISOString()\r\n }), 'utf-8')\r\n\r\n res.json({ success: true, model })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to change model' })\r\n }\r\n })\r\n\r\n // Trigger system scan (writes control file)\r\n this.app.post('/api/bro/scan', (_req: Request, res: Response) => {\r\n try {\r\n const controlPath = join(homedir(), '.bashbros', 'scan-control.json')\r\n writeFileSync(controlPath, JSON.stringify({\r\n action: 'scan',\r\n timestamp: new Date().toISOString()\r\n }), 'utf-8')\r\n\r\n res.json({ success: true, message: 'Scan requested' })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to trigger scan' })\r\n }\r\n })\r\n\r\n // ─────────────────────────────────────────────────────────────\r\n // Exposure Endpoints\r\n // ─────────────────────────────────────────────────────────────\r\n\r\n // Get recent exposures\r\n this.app.get('/api/exposures', (req: Request, res: Response) => {\r\n try {\r\n const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 100\r\n const exposures = this.db.getRecentExposures(limit)\r\n res.json(exposures)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to fetch exposures' })\r\n }\r\n })\r\n\r\n // Get config\r\n this.app.get('/api/config', (_req: Request, res: Response) => {\r\n try {\r\n const configPath = findConfig()\r\n if (!configPath) {\r\n res.status(404).json({ error: 'No config file found' })\r\n return\r\n }\r\n const content = readFileSync(configPath, 'utf-8')\r\n const config = parse(content)\r\n res.json(config)\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to load config' })\r\n }\r\n })\r\n\r\n // Save config\r\n this.app.post('/api/config', (req: Request, res: Response) => {\r\n try {\r\n const configPath = findConfig()\r\n if (!configPath) {\r\n res.status(404).json({ error: 'No config file found' })\r\n return\r\n }\r\n const config = req.body\r\n const content = stringify(config)\r\n writeFileSync(configPath, content, 'utf-8')\r\n res.json({ success: true })\r\n } catch (error) {\r\n res.status(500).json({ error: 'Failed to save config' })\r\n }\r\n })\r\n\r\n // Static file serving - resolve relative to this file\r\n const __filename = fileURLToPath(import.meta.url)\r\n const __dirname = dirname(__filename)\r\n const staticPath = join(__dirname, 'static')\r\n this.app.use(express.static(staticPath))\r\n\r\n // Fallback to index.html for SPA routing (Express 5 path-to-regexp syntax)\r\n this.app.get('/{*path}', (_req: Request, res: Response) => {\r\n res.sendFile(join(staticPath, 'index.html'))\r\n })\r\n }\r\n\r\n private setupWebSocket(): void {\r\n if (!this.server) return\r\n\r\n this.wss = new WebSocketServer({ server: this.server })\r\n\r\n this.wss.on('connection', (ws: WebSocket) => {\r\n this.clients.add(ws)\r\n\r\n ws.on('close', () => {\r\n this.clients.delete(ws)\r\n })\r\n\r\n ws.on('error', () => {\r\n this.clients.delete(ws)\r\n })\r\n\r\n // Send initial stats on connection\r\n try {\r\n const stats = this.db.getStats()\r\n ws.send(JSON.stringify({ type: 'stats', data: stats }))\r\n } catch {\r\n // Ignore errors on initial send\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * Start the dashboard server\r\n */\r\n async start(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n this.server = createServer(this.app)\r\n this.setupWebSocket()\r\n\r\n this.server.on('error', (error: NodeJS.ErrnoException) => {\r\n if (error.code === 'EADDRINUSE') {\r\n reject(new Error(`Port ${this.port} is already in use`))\r\n } else {\r\n reject(error)\r\n }\r\n })\r\n\r\n this.server.listen(this.port, this.bind, () => {\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Stop the dashboard server\r\n */\r\n async stop(): Promise<void> {\r\n return new Promise((resolve) => {\r\n // Close all WebSocket connections\r\n for (const client of this.clients) {\r\n client.close()\r\n }\r\n this.clients.clear()\r\n\r\n if (this.wss) {\r\n this.wss.close()\r\n this.wss = null\r\n }\r\n\r\n if (this.server) {\r\n this.server.close(() => {\r\n this.server = null\r\n this.db.close()\r\n resolve()\r\n })\r\n } else {\r\n this.db.close()\r\n resolve()\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * Broadcast a message to all connected WebSocket clients\r\n */\r\n broadcast(message: unknown): void {\r\n const data = JSON.stringify(message)\r\n for (const client of this.clients) {\r\n if (client.readyState === 1) { // WebSocket.OPEN\r\n client.send(data)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the database instance for external use\r\n */\r\n getDB(): DashboardDB {\r\n return this.db\r\n }\r\n\r\n /**\r\n * Get the port the server is running on\r\n */\r\n getPort(): number {\r\n return this.port\r\n }\r\n}\r\n\r\nexport default DashboardServer\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAe;AACxB,OAAOA,YAAW;;;ACDlB,OAAO,cAAc;AACrB,OAAO,WAAW;AAClB,SAAS,eAAe,YAAY,iBAAiB;AACrD,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAK1B,eAAsB,gBAA+B;AACnD,UAAQ,IAAI,MAAM,IAAI;AAAA,CAAyD,CAAC;AAGhF,QAAM,mBAAmB,WAAW,KAAK,QAAQ,GAAG,YAAY,aAAa,CAAC;AAE9E,QAAM,YAAmB;AAAA,IACvB;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,eAAe,OAAO,cAAc;AAAA,QAC5C,EAAE,MAAM,uBAAuB,OAAO,UAAU;AAAA,QAChD,EAAE,MAAM,qBAAqB,OAAO,WAAW;AAAA,QAC/C,EAAE,MAAM,cAAc,OAAO,aAAa;AAAA,QAC1C,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA,QAChC,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,QACtC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,MAC5C;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,mBAAmB,OAAO,MAAM;AAAA,QACxC,EAAE,MAAM,2BAA2B,OAAO,SAAS;AAAA,QACnD,EAAE,MAAM,oBAAoB,OAAO,OAAO;AAAA,QAC1C,EAAE,MAAM,kBAAkB,OAAO,UAAU;AAAA,QAC3C,EAAE,MAAM,4BAA4B,OAAO,YAAY;AAAA,MACzD;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,4CAA4C,OAAO,QAAQ;AAAA,QACnE,EAAE,MAAM,sCAAsC,OAAO,QAAQ;AAAA,QAC7D,EAAE,MAAM,MAAM,OAAO,WAAW;AAAA,MAClC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,sCAAsC,OAAO,QAAQ;AAAA,QAC7D,EAAE,MAAM,6CAA6C,OAAO,SAAS;AAAA,QACrE,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA,QAC9B,EAAE,MAAM,QAAQ,OAAO,WAAW;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,kBAAkB;AACpB,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,MAAM,SAAS,OAAO,SAAS;AAG/C,QAAM,SAAS,YAAY,OAAO;AAGlC,QAAM,aAAa,UAAU,MAAM;AACnC,gBAAc,iBAAiB,UAAU;AAEzC,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,qBAAqB,MAAM,KAAK,eAAe,CAAC;AAC9E,UAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,mBAAmB;AACjD,UAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,iBAAiB,QAAQ,UAAU,aAAa,YAAY,UAAU;AAGpG,MAAI,QAAQ,YAAY,QAAQ;AAC9B,UAAM,SAAS,MAAM,YAAY;AACjC,QAAI,QAAQ;AACV,cAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,uBAAuB,MAAM,KAAK,QAAQ,CAAC;AACzE,cAAQ,IAAI,MAAM,IAAI,wCAAwC,CAAC;AAC/D,cAAQ,IAAI,MAAM,IAAI,sCAAsC,CAAC;AAAA,IAC/D,OAAO;AACL,cAAQ,IAAI,MAAM,OAAO,QAAG,GAAG,uBAAuB,MAAM,IAAI,mCAAmC,CAAC;AAAA,IACtG;AAAA,EACF,WAAW,kBAAkB;AAC3B,YAAQ,IAAI,MAAM,IAAI,QAAG,GAAG,uBAAuB,MAAM,IAAI,SAAS,CAAC;AAAA,EACzE;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,KAAK,mBAAmB,GAAG,MAAM,IAAI,iBAAiB,CAAC;AAC3F,UAAQ,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,KAAK,kBAAkB,GAAG,MAAM,IAAI,qBAAqB,CAAC;AAC9F,UAAQ,IAAI;AACd;AAKA,eAAe,cAAgC;AAC7C,MAAI;AACF,UAAM,cAAc,sBAAsB;AAG1C,QAAI,CAAC,YAAY,YAAY,GAAG;AAE9B,YAAM,iBAAiB,KAAK,QAAQ,GAAG,YAAY,aAAa;AAChE,YAAM,OAAO;AAAA,QACX,KAAK,gBAAgB,UAAU,SAAS;AAAA,QACxC,KAAK,gBAAgB,UAAU,WAAW;AAAA,QAC1C,KAAK,gBAAgB,UAAU,QAAQ;AAAA,QACvC,KAAK,gBAAgB,UAAU,QAAQ;AAAA,QACvC,KAAK,gBAAgB,QAAQ;AAAA,QAC7B,KAAK,gBAAgB,QAAQ;AAAA,MAC/B;AAEA,iBAAW,OAAO,MAAM;AACtB,kBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,MACpC;AAGA,YAAM,eAAe,KAAK,gBAAgB,UAAU,eAAe;AACnE,YAAM,WAAW;AAAA,QACf,SAAS;AAAA,QACT,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,YAAY;AAAA,QACZ,aAAa;AAAA,UACX,SAAS;AAAA,UACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,UAAU;AAAA,UACR,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,SAAS;AAAA,QACX;AAAA,QACA,UAAU;AAAA,UACR,kBAAkB;AAAA,UAClB,aAAa;AAAA,QACf;AAAA,QACA,YAAY;AAAA,UACV,oBAAoB;AAAA,UACpB,mBAAmB;AAAA,UACnB,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA,oBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,IAC/D,OAAO;AAEL,kBAAY,eAAe;AAAA,QACzB,aAAa;AAAA,UACX,SAAS;AAAA,UACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC;AAAA,MACF,CAAQ;AAAA,IACV;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,SAAiD;AACpE,QAAM,WAAW,iBAAiB;AAElC,QAAM,SAAyB;AAAA,IAC7B,GAAG;AAAA,IACH,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,SAAS;AAAA,MACP,GAAG,SAAS;AAAA,MACZ,SAAS,QAAQ,YAAY;AAAA,MAC7B,MAAM,QAAQ,YAAY,UAAU,UAAU;AAAA,IAChD;AAAA,IACA,OAAO;AAAA,MACL,GAAG,SAAS;AAAA,MACZ,SAAS,QAAQ,UAAU;AAAA,MAC3B,aAAa,QAAQ,UAAU,aAAa,UAAU,QAAQ;AAAA,IAChE;AAAA,EACF;AAGA,MAAI,QAAQ,gBAAgB,aAAa;AACvC,WAAO,UAAU;AACjB,WAAO,UAAU,eAAe;AAAA,EAClC;AAEA,MAAI,QAAQ,gBAAgB,UAAU;AACpC,WAAO,SAAS,MAAM,KAAK,YAAY,aAAa,eAAe,OAAO;AAAA,EAC5E;AAEA,MAAI,QAAQ,gBAAgB,QAAQ;AAClC,WAAO,SAAS,MAAM,KAAK,YAAY,aAAa,YAAY,QAAQ;AAAA,EAC1E;AAEA,SAAO;AACT;;;ACxPA,OAAOC,YAAW;AAClB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,gBAAe;;;ACExB,SAAS,cAAAC,aAAY,gBAAgB;AACrC,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,UAAS,gBAAgB;AAClC,SAAS,oBAAoB;AAOtB,IAAM,qBAAkD;AAAA,EAC7D,eAAe;AAAA,IACbC,MAAKC,SAAQ,GAAG,WAAW,eAAe;AAAA,EAC5C;AAAA,EACA,YAAY;AAAA,IACVD,MAAKC,SAAQ,GAAG,aAAa,cAAc;AAAA;AAAA,IAC3CD,MAAKC,SAAQ,GAAG,aAAa,YAAY;AAAA;AAAA,IACzCD,MAAKC,SAAQ,GAAG,WAAW,YAAY,YAAY;AAAA,EACrD;AAAA,EACA,WAAW;AAAA,IACTD,MAAKC,SAAQ,GAAG,YAAY,aAAa;AAAA,IACzCD,MAAKC,SAAQ,GAAG,aAAa,cAAc;AAAA;AAAA,IAC3CD,MAAKC,SAAQ,GAAG,WAAW,WAAW,aAAa;AAAA,EACrD;AAAA,EACA,SAAS;AAAA,IACPD,MAAKC,SAAQ,GAAG,iBAAiB;AAAA,IACjCD,MAAKC,SAAQ,GAAG,WAAW,SAAS,gBAAgB;AAAA,EACtD;AAAA,EACA,cAAc;AAAA,IACZD,MAAKC,SAAQ,GAAG,WAAW,cAAc,aAAa;AAAA,EACxD;AAAA,EACA,YAAY;AAAA,IACVD,MAAKC,SAAQ,GAAG,aAAa,YAAY;AAAA,IACzCD,MAAKC,SAAQ,GAAG,WAAW,YAAY,YAAY;AAAA,EACrD;AAAA,EACA,UAAU,CAAC;AACb;AAGA,IAAM,iBAA4C;AAAA,EAChD,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AACZ;AA8CA,SAAS,cAAc,KAAsB;AAC3C,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AACF,UAAM,WAAW,SAAS,MAAM,UAAU,UAAU;AACpD,iBAAa,UAAU,CAAC,GAAG,GAAG;AAAA,MAC5B,OAAO;AAAA,MACP,SAAS;AAAA,MACT,aAAa;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,gBAAgB,OAAsC;AAC7D,QAAM,MAAM,eAAe,KAAK;AAChC,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AACF,UAAM,SAAS,aAAa,KAAK,CAAC,WAAW,GAAG;AAAA,MAC9C,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC9B,aAAa;AAAA,IACf,CAAC,EAAE,KAAK;AAGR,UAAM,QAAQ,OAAO,MAAM,mCAAmC;AAC9D,WAAO,QAAQ,MAAM,CAAC,IAAI,OAAO,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,oBAAoB,OAAsC;AACjE,QAAM,QAAQ,mBAAmB,KAAK;AAEtC,aAAW,cAAc,OAAO;AAC9B,QAAIC,YAAW,UAAU,GAAG;AAC1B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,UAAoC;AAC3D,MAAI;AACF,UAAM,QAAQ,SAAS,QAAQ;AAC/B,WAAO,MAAM;AAAA,EACf,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,qBAAqB,OAAoC;AACtE,MAAI,UAAU,eAAe;AAC3B,UAAM,SAAS,gBAAgB,UAAU;AACzC,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,UAAU,aAAa,UAAU,YAAY;AAC/C,QAAI;AACF,YAAM,EAAE,cAAAC,cAAa,IAAI,MAAM,OAAO,uBAAqB;AAC3D,aAAOA,cAAa,YAAY;AAAA,IAClC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAIA,SAAO;AACT;AAKA,eAAsB,mBAAmB,OAA4C;AACnF,QAAM,MAAM,eAAe,KAAK;AAChC,QAAM,YAAY,MAAM,cAAc,GAAG,IAAI;AAC7C,QAAM,aAAa,oBAAoB,KAAK;AAC5C,QAAM,eAAe,aAAaD,YAAW,UAAU,IAAI;AAE3D,QAAM,OAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,MAAM,qBAAqB,KAAK;AAAA,EACtD;AAEA,MAAI,WAAW;AACb,SAAK,UAAU,gBAAgB,KAAK;AAAA,EACtC;AAEA,MAAI,gBAAgB,YAAY;AAC9B,SAAK,eAAe,gBAAgB,UAAU;AAG9C,UAAM,SAAS,MAAM,iBAAiB,OAAO,UAAU;AACvD,QAAI,QAAQ;AACV,WAAK,cAAc,OAAO;AAC1B,WAAK,QAAQ,OAAO;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,qBAAiD;AACrE,QAAM,SAAsB,CAAC,eAAe,WAAW,YAAY,SAAS,cAAc,UAAU;AACpG,QAAM,UAA6B,CAAC;AAEpC,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,mBAAmB,KAAK;AAC3C,YAAQ,KAAK,IAAI;AAAA,EACnB;AAEA,SAAO;AACT;;;ACnOA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,cAAAE,aAAY,oBAAoB;AACzC,SAAS,YAAAC,iBAAgB;AASzB,IAAM,YAAY,UAAU,IAAI;AAKzB,IAAM,2BAA6C;AAAA,EACxD;AAAA,IACE,MAAM;AAAA,IACN,cAAc,CAAC,UAAU,eAAe,aAAa;AAAA,IACrD,cAAc,CAAC,KAAM,MAAM,IAAI;AAAA,IAC/B,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB,CAAC,WAAW,cAAc,eAAe;AAAA,EAC3D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,cAAc,CAAC,SAAS,YAAY;AAAA,IACpC,cAAc,CAAC,MAAM,GAAI;AAAA,IACzB,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB,CAAC,WAAW,gBAAgB;AAAA,EAC9C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,cAAc,CAAC,YAAY,iBAAiB;AAAA,IAC5C,cAAc,CAAC,OAAO,KAAK;AAAA,IAC3B,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB,CAAC,UAAU,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,cAAc,CAAC,UAAU,UAAU,eAAe;AAAA,IAClD,cAAc,CAAC,KAAM,MAAM,GAAI;AAAA,IAC/B,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB,CAAC,UAAU,SAAS,MAAM;AAAA,EAC5C;AACF;AAKO,IAAM,2BAAqE;AAAA,EAChF,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AACZ;AA0BO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EACA;AAAA,EAER,YAAY,QAAkC;AAC5C,SAAK,SAAS,CAAC,GAAG,wBAAwB;AAC1C,SAAK,SAAS;AAAA,MACZ,SAAS;AAAA,MACT,cAAc;AAAA,MACd,eAAe;AAAA,MACf,iBAAiB,EAAE,GAAG,yBAAyB;AAAA,MAC/C,QAAQ,KAAK;AAAA,MACb,GAAG;AAAA,IACL;AAGA,QAAI,QAAQ,QAAQ;AAClB,iBAAW,SAAS,OAAO,QAAQ;AACjC,YAAI,CAAC,KAAK,OAAO,KAAK,OAAK,EAAE,SAAS,MAAM,IAAI,GAAG;AACjD,eAAK,OAAO,KAAK,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAkC;AACtC,UAAM,UAA4B,CAAC;AACnC,UAAM,iBAAiB,MAAM,KAAK,kBAAkB;AAEpD,eAAW,QAAQ,gBAAgB;AACjC,iBAAW,SAAS,KAAK,QAAQ;AAC/B,YAAI,MAAM,aAAa,SAAS,KAAK,SAAS,GAAG;AAC/C,gBAAM,UAAU,MAAM,KAAK,gBAAgB,KAAK;AAChD,gBAAM,sBAAsB,KAAK,sBAAsB,KAAK,YAAY;AAExE,gBAAM,WAAW,KAAK,eAAe;AAAA,YACnC,aAAa,KAAK;AAAA,YAClB;AAAA,YACA;AAAA,YACA,mBAAmB;AAAA,UACrB,CAAC;AAED,gBAAM,SAAS,KAAK,qBAAqB,QAAQ;AAEjD,kBAAQ,KAAK;AAAA,YACX,OAAO,MAAM;AAAA,YACb,KAAK,KAAK;AAAA,YACV,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB;AAAA,YACA;AAAA,YACA;AAAA,YACA,SAAS,KAAK,gBAAgB,MAAM,MAAM,MAAM,UAAU,OAAO;AAAA,YACjE,WAAW,oBAAI,KAAK;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,OAAwC;AACrD,UAAM,EAAE,aAAa,SAAS,qBAAqB,kBAAkB,IAAI;AAGzE,QAAI,uBAAuB,YAAY,MAAM;AAC3C,aAAO;AAAA,IACT;AAGA,QAAI,uBAAuB,mBAAmB;AAC5C,aAAO;AAAA,IACT;AAGA,UAAM,iBAAiB,gBAAgB,aAAa,gBAAgB,QAAQ,gBAAgB;AAC5F,QAAI,kBAAkB,YAAY,MAAM;AACtC,aAAO;AAAA,IACT;AAGA,QAAI,kBAAkB,YAAY,MAAM;AACtC,aAAO;AAAA,IACT;AAGA,UAAM,cACJ,gBAAgB,eAChB,gBAAgB,SAChB,gBAAgB;AAElB,QAAI,eAAe,YAAY,MAAM;AACnC,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,UAA4C;AAC/D,WAAO,KAAK,OAAO,gBAAgB,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,MAAoC;AACnD,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,WAAW,GAAG;AAC9C,aAAO;AAAA,IACT;AAMA,UAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM,CAAC;AACxB,QAAI,aAAa,SAAS,aAAa,OAAO;AAC5C,aAAO;AAAA,IACT;AAEA,UAAM,mBAAmB,MAAM,CAAC;AAChC,UAAM,QAAQ,MAAM,CAAC;AACrB,UAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AAEjC,QAAI,UAAU,eAAe,MAAM,GAAG,GAAG;AACvC,aAAO;AAAA,IACT;AAGA,QAAI;AACJ,QAAI;AAEJ,QAAI,iBAAiB,WAAW,GAAG,GAAG;AAEpC,YAAM,QAAQ,iBAAiB,MAAM,sBAAsB;AAC3D,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,MACT;AACA,qBAAe,MAAM,CAAC;AACtB,kBAAY,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,IACnC,OAAO;AAEL,YAAM,iBAAiB,iBAAiB,YAAY,GAAG;AACvD,UAAI,mBAAmB,IAAI;AACzB,eAAO;AAAA,MACT;AACA,qBAAe,iBAAiB,UAAU,GAAG,cAAc;AAC3D,kBAAY,SAAS,iBAAiB,UAAU,iBAAiB,CAAC,GAAG,EAAE;AAAA,IACzE;AAEA,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAA8C;AAClD,UAAM,UAA2B,CAAC;AAElC,QAAI;AACF,UAAIA,UAAS,MAAM,SAAS;AAC1B,cAAM,EAAE,OAAO,IAAI,MAAM,UAAU,qBAAqB;AACxD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAE/B,mBAAW,QAAQ,OAAO;AACxB,gBAAM,SAAS,KAAK,iBAAiB,IAAI;AACzC,cAAI,QAAQ;AACV,oBAAQ,KAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YAAI;AACF,gBAAM,EAAE,OAAO,IAAI,MAAM,UAAU,mDAAmD;AACtF,gBAAM,QAAQ,OAAO,MAAM,IAAI;AAE/B,qBAAW,QAAQ,OAAO;AACxB,kBAAM,SAAS,KAAK,uBAAuB,IAAI;AAC/C,gBAAI,QAAQ;AACV,sBAAQ,KAAK,MAAM;AAAA,YACrB;AAAA,UACF;AAAA,QACF,QAAQ;AAEN,gBAAM,EAAE,OAAO,IAAI,MAAM,UAAU,mDAAmD;AACtF,gBAAM,QAAQ,OAAO,MAAM,IAAI;AAE/B,qBAAW,QAAQ,OAAO;AACxB,kBAAM,SAAS,KAAK,cAAc,IAAI;AACtC,gBAAI,QAAQ;AACV,sBAAQ,KAAK,MAAM;AAAA,YACrB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,MAAoC;AACjE,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,OAAO,KAAK,QAAQ,WAAW,OAAO,GAAG;AAC1E,aAAO;AAAA,IACT;AAMA,UAAM,UAAU,QAAQ,MAAM,oDAAoD;AAClF,QAAI,SAAS;AACX,aAAO;AAAA,QACL,UAAU;AAAA,QACV,cAAc,QAAQ,CAAC,MAAM,MAAM,YAAY,QAAQ,CAAC;AAAA,QACxD,WAAW,SAAS,QAAQ,CAAC,GAAG,EAAE;AAAA,QAClC,OAAO;AAAA,QACP,KAAK,SAAS,QAAQ,CAAC,GAAG,EAAE;AAAA,MAC9B;AAAA,IACF;AAGA,UAAM,eAAe,QAAQ,MAAM,sDAAsD;AACzF,QAAI,cAAc;AAChB,aAAO;AAAA,QACL,UAAU;AAAA,QACV,cAAc,aAAa,CAAC,MAAM,MAAM,YAAY,aAAa,CAAC;AAAA,QAClE,WAAW,SAAS,aAAa,CAAC,GAAG,EAAE;AAAA,QACvC,OAAO;AAAA,QACP,KAAK,SAAS,aAAa,CAAC,GAAG,EAAE;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,MAAoC;AACxD,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,SAAS,GAAG;AAC7C,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,QAAI,MAAM,GAAG,GAAG;AACd,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,MAAM,UAAU,OAAK,MAAM,SAAS,MAAM,MAAM;AACjE,QAAI,aAAa,IAAI;AACnB,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,MAAM,WAAW,CAAC;AACtC,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,YAAY,MAAM,iBAAiB;AACjD,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,cAAc,MAAM,CAAC,MAAM,MAAM,YAAY,MAAM,CAAC;AAAA,MACpD,WAAW,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,MAChC,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,OAAqD;AACzE,eAAW,cAAc,MAAM,aAAa;AAC1C,YAAM,eAAe,KAAK,WAAW,UAAU;AAE/C,UAAID,YAAW,YAAY,GAAG;AAC5B,YAAI;AACF,gBAAM,UAAU,aAAa,cAAc,OAAO;AAElD,qBAAW,aAAa,MAAM,gBAAgB;AAC5C,gBAAI,QAAQ,SAAS,SAAS,GAAG;AAC/B,qBAAO;AAAA,YACT;AAAA,UACF;AACA,iBAAO;AAAA,QACT,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,aAA8B;AAE1D,QAAI,gBAAgB,aAAa,gBAAgB,QAAQ,gBAAgB,KAAK;AAI5E,aAAO,KAAK,OAAO;AAAA,IACrB;AAGA,QACE,gBAAgB,eAChB,gBAAgB,SAChB,gBAAgB,aAChB;AACA,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,YAAY,WAAW,GAAG;AACjC,aAAO,KAAK,OAAO;AAAA,IACrB;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,IAAqB;AAEvC,QAAI,GAAG,WAAW,KAAK,EAAG,QAAO;AACjC,QAAI,GAAG,WAAW,MAAM,GAAG;AACzB,YAAM,SAAS,SAAS,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE;AAC5C,UAAI,UAAU,MAAM,UAAU,GAAI,QAAO;AAAA,IAC3C;AACA,QAAI,GAAG,WAAW,UAAU,EAAG,QAAO;AAGtC,QAAI,GAAG,YAAY,EAAE,WAAW,IAAI,KAAK,GAAG,YAAY,EAAE,WAAW,IAAI,GAAG;AAC1E,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,MAAsB;AACvC,QAAI,WAAW;AAGf,QAAI,SAAS,WAAW,GAAG,GAAG;AAC5B,YAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAC5D,iBAAW,SAAS,QAAQ,KAAK,IAAI;AAAA,IACvC;AAGA,eAAW,SAAS,QAAQ,cAAc,CAAC,GAAG,SAAS,QAAQ,IAAI,IAAI,KAAK,EAAE;AAG9E,eAAW,SAAS,QAAQ,+BAA+B,CAAC,GAAG,SAAS,QAAQ,IAAI,IAAI,KAAK,EAAE;AAE/F,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,WACA,MACA,UACA,SACQ;AACR,UAAM,aAAa,YAAY,OAC3B,wBACA,YAAY,QACV,2BACA;AAEN,UAAM,WAAW,KAAK,iBAAiB,aAAa,KAAK,iBAAiB,OACtE,mBACA,KAAK;AAET,WAAO,GAAG,SAAS,4BAA4B,KAAK,SAAS,KAAK,QAAQ,KAAK,UAAU,eAAe,QAAQ;AAAA,EAClH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAA6B;AACpC,SAAK,OAAO,KAAK,KAAK;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,YAA8B;AAC5B,WAAO,CAAC,GAAG,KAAK,MAAM;AAAA,EACxB;AACF;;;AClhBO,IAAM,mBAAoC;AAAA;AAAA,EAE/C;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA;AAAA,EAGA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AACF;AAcA,IAAM,iBAAkD;AAAA,EACtD,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AACZ;AAKO,IAAM,uBAAN,MAA2B;AAAA,EACxB;AAAA,EACA;AAAA,EAER,YAAY,gBAAkC;AAC5C,SAAK,WAAW,CAAC,GAAG,gBAAgB;AACpC,SAAK,mBAAmB,oBAAI,IAAI;AAEhC,QAAI,gBAAgB;AAClB,iBAAW,WAAW,gBAAgB;AACpC,aAAK,SAAS,KAAK,OAAO;AAAA,MAC5B;AAAA,IACF;AAGA,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAwB;AAC9B,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,CAAC,KAAK,iBAAiB,IAAI,QAAQ,IAAI,GAAG;AAC5C,YAAI;AACF,eAAK,iBAAiB,IAAI,QAAQ,MAAM,IAAI,OAAO,QAAQ,OAAO,IAAI,CAAC;AAAA,QACzE,QAAQ;AAEN,kBAAQ,KAAK,6BAA6B,QAAQ,IAAI,KAAK,QAAQ,KAAK,EAAE;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAA8B;AAClC,UAAM,UAA0B,CAAC;AAEjC,eAAW,WAAW,KAAK,UAAU;AACnC,YAAM,QAAQ,KAAK,iBAAiB,IAAI,QAAQ,IAAI;AACpD,UAAI,CAAC,MAAO;AAGZ,YAAM,YAAY;AAElB,UAAI;AACJ,cAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA,aAAa,MAAM,CAAC;AAAA,UACpB,OAAO,MAAM;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAuB;AACjC,UAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,WAAO,QAAQ,KAAK,OAAK,EAAE,QAAQ,WAAW,OAAO;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,MAAsC;AACvD,UAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,QAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAI,UAA2B;AAC/B,eAAW,KAAK,SAAS;AACvB,UAAI,eAAe,EAAE,QAAQ,QAAQ,IAAI,eAAe,OAAO,GAAG;AAChE,kBAAU,EAAE,QAAQ;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,MAA+B;AACpC,UAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,UAAM,aAA8B,CAAC;AACrC,QAAI,WAAW;AAGf,UAAM,gBAAgB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEnE,eAAW,KAAK,eAAe;AAC7B,YAAM,cAAc,aAAa,EAAE,QAAQ,IAAI;AAG/C,UAAI;AACJ,UAAI,EAAE,QAAQ,SAAS,aAAa,EAAE,QAAQ,SAAS,gBACnD,EAAE,QAAQ,SAAS,iBAAiB,EAAE,QAAQ,SAAS,kBACvD,EAAE,QAAQ,SAAS,gBAAgB,EAAE,QAAQ,SAAS,aAAa;AACrE,wBAAgB;AAAA,MAClB,WAAW,EAAE,QAAQ,SAAS,SAAS;AACrC,wBAAgB;AAAA,MAClB,WAAW,EAAE,QAAQ,SAAS,YAAY;AACxC,wBAAgB;AAAA,MAClB,WAAW,EAAE,QAAQ,SAAS,OAAO;AACnC,wBAAgB;AAAA,MAClB,WAAW,EAAE,QAAQ,SAAS,eAAe;AAC3C,wBAAgB;AAAA,MAClB,OAAO;AACL,wBAAgB;AAAA,MAClB;AAEA,iBAAW,KAAK;AAAA,QACd,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAGD,iBACE,SAAS,UAAU,GAAG,EAAE,KAAK,IAC7B,cACA,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,MAAM;AAAA,IACrD;AAEA,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,YAAY,WAAW,QAAQ;AAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAA8B;AACvC,SAAK,SAAS,KAAK,OAAO;AAC1B,QAAI;AACF,WAAK,iBAAiB,IAAI,QAAQ,MAAM,IAAI,OAAO,QAAQ,OAAO,IAAI,CAAC;AAAA,IACzE,QAAQ;AACN,cAAQ,KAAK,6BAA6B,QAAQ,IAAI,KAAK,QAAQ,KAAK,EAAE;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAA+B;AAC7B,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAIH;AACA,WAAO;AAAA,MACL,SAAS,KAAK,MAAM,IAAI;AAAA,MACxB,aAAa,KAAK,YAAY,IAAI;AAAA,MAClC,UAAU,KAAK,OAAO,IAAI;AAAA,IAC5B;AAAA,EACF;AACF;;;ACtRA,IAAIE,eAAyE;AAC7E,IAAI;AACF,QAAM,WAAW,MAAM,OAAO,kBAAuB;AACrD,EAAAA,eAAc,SAAS;AACzB,QAAQ;AAER;AAqBA,IAAM,wBAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,eAAe;AAAA,EACf,WAAW,CAAC;AACd;AAKO,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA;AAAA,EACA,KAA8E;AAAA,EAC9E;AAAA,EAER,YAAY,QAAgC;AAC1C,SAAK,SAAS,EAAE,GAAG,uBAAuB,GAAG,OAAO;AACpD,SAAK,UAAU,IAAI,qBAAqB;AACxC,SAAK,YAAY,CAAC,GAAG,KAAK,OAAO,SAAS;AAG1C,QAAIA,cAAa;AACf,UAAI;AACF,aAAK,KAAK,IAAIA,aAAY;AAAA,MAC5B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAQ,SAAiB,WAAoB,aAAwC;AAEnF,QAAI,KAAK,cAAc,WAAW,WAAW,GAAG;AAC9C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS,CAAC;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAGA,UAAM,aAAa,KAAK,QAAQ,MAAM,OAAO;AAG7C,UAAM,mBAAmB,WAAW,OAAO,WAAS;AAClD,aAAO,CAAC,KAAK,qBAAqB,MAAM,QAAQ,MAAM,WAAW,WAAW;AAAA,IAC9E,CAAC;AAGD,UAAM,cAAc,iBAAiB,KAAK,OAAK,EAAE,QAAQ,WAAW,OAAO;AAG3E,QAAI,WAAW;AACf,QAAI,iBAAiB,SAAS,GAAG;AAE/B,YAAM,gBAAgB,CAAC,GAAG,gBAAgB,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5E,iBAAW,KAAK,eAAe;AAC7B,cAAM,cAAc,aAAa,EAAE,QAAQ,IAAI;AAC/C,mBACE,SAAS,UAAU,GAAG,EAAE,KAAK,IAC7B,cACA,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,MAAM;AAAA,MACrD;AAAA,IACF;AAGA,UAAM,iBAAiB,WAAW,SAAS,KAAK,iBAAiB,WAAW;AAE5E,UAAM,SAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,aAAa;AAAA,MACb,SAAS;AAAA,MACT;AAAA,IACF;AAGA,QAAI,eAAe,KAAK,IAAI;AAC1B,UAAI;AAEF,mBAAW,SAAS,iBAAiB,OAAO,OAAK,EAAE,QAAQ,WAAW,OAAO,GAAG;AAC9E,gBAAM,UAAU,KAAK,GAAG,kBAAkB;AAAA,YACxC,SAAS,MAAM;AAAA,YACf,aAAa,MAAM,YAAY,UAAU,GAAG,GAAG;AAAA;AAAA,YAC/C,cAAc;AAAA,YACd;AAAA,YACA;AAAA,UACF,CAAC;AACD,iBAAO,UAAU;AAAA,QACnB;AAGA,aAAK,GAAG,YAAY;AAAA,UAClB,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,UAAU;AAAA,UACV,SAAS,mBAAmB,iBAAiB,IAAI,OAAK,EAAE,QAAQ,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,UAChF,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA,cAAc,iBAAiB,IAAI,OAAK,EAAE,QAAQ,IAAI;AAAA,UACxD;AAAA,QACF,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,WAAoB,aAA+B;AACvE,WAAO,KAAK,UAAU,KAAK,WAAS;AAElC,UAAI,MAAM,QAAS,QAAO;AAG1B,UAAI,MAAM,aAAa,MAAM,aAAa;AAExC,eAAO,MAAM,cAAc,aAAa,MAAM,gBAAgB;AAAA,MAChE;AAEA,UAAI,MAAM,WAAW;AACnB,eAAO,MAAM,cAAc;AAAA,MAC7B;AAEA,UAAI,MAAM,aAAa;AACrB,eAAO,MAAM,gBAAgB;AAAA,MAC/B;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,qBACN,aACA,WACA,aACS;AACT,WAAO,KAAK,UAAU,KAAK,WAAS;AAElC,UAAI,CAAC,MAAM,WAAW,MAAM,YAAY,YAAa,QAAO;AAG5D,UAAI,MAAM,aAAa,MAAM,aAAa;AACxC,eAAO,MAAM,cAAc,aAAa,MAAM,gBAAgB;AAAA,MAChE;AAEA,UAAI,MAAM,WAAW;AACnB,eAAO,MAAM,cAAc;AAAA,MAC7B;AAEA,UAAI,MAAM,aAAa;AACrB,eAAO,MAAM,gBAAgB;AAAA,MAC/B;AAGA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,OAAmC;AACnD,SAAK,UAAU,KAAK,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAA8B;AACvC,SAAK,QAAQ,WAAW,OAAO;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAkC;AAChC,QAAI,CAAC,KAAK,GAAI,QAAO,CAAC;AACtB,QAAI;AACF,aAAO,KAAK,GAAG,iBAAiB;AAAA,IAClC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,IAAY,YAA2B;AAClD,QAAI,CAAC,KAAK,GAAI;AACd,QAAI;AACF,WAAK,GAAG,aAAa,IAAI,cAAc,QAAQ;AAAA,IACjD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,IAAkB;AAC1B,QAAI,CAAC,KAAK,GAAI;AACd,QAAI;AACF,WAAK,GAAG,UAAU,IAAI,QAAQ;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,SAIH;AACA,UAAM,UAAU,KAAK,QAAQ,MAAM,OAAO;AAC1C,UAAM,cAAc,QAAQ,KAAK,OAAK,EAAE,QAAQ,WAAW,OAAO;AAGlE,QAAI,WAAW;AACf,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,gBAAgB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACnE,iBAAW,KAAK,eAAe;AAC7B,cAAM,cAAc,aAAa,EAAE,QAAQ,IAAI;AAC/C,mBACE,SAAS,UAAU,GAAG,EAAE,KAAK,IAC7B,cACA,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,MAAM;AAAA,MACrD;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AJzRA,eAAe,kBAAkB,QAAmD;AAClF,QAAM,SAAwB,CAAC;AAE/B,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,MAAM,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,MAAM,CAAC,EAAE,QAAQ,KAAK,GAAG;AAG7F,QAAI,MAAM,cAAc,CAAC,MAAM,cAAc;AAC3C,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,SAAS;AAAA,QAClB,QAAQ;AAAA,QACR,SAAS,sBAAsB,MAAM,UAAU;AAAA,MACjD,CAAC;AAAA,IACH,WAAW,MAAM,cAAc;AAC7B,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,SAAS;AAAA,QAClB,QAAQ;AAAA,QACR,SAAS,YAAY,MAAM,UAAU;AAAA,MACvC,CAAC;AAAA,IACH;AAGA,QAAI,MAAM,UAAU,eAAe;AACjC,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,SAAS;AAAA,QAClB,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,qBACX,6BACA;AAAA,MACN,CAAC;AAAA,IACH;AAGA,QAAI,MAAM,UAAU,aAAa,MAAM,UAAU,YAAY;AAC3D,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,SAAS;AAAA,QAClB,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,qBACX,6BACA;AAAA,MACN,CAAC;AAGD,UAAI;AACF,cAAM,EAAE,cAAAC,cAAa,IAAI,MAAM,OAAO,uBAAoB;AAC1D,cAAM,SAASA,cAAa,UAAU;AAGtC,YAAI,OAAO,aAAa;AACtB,iBAAO,KAAK;AAAA,YACV,MAAM,GAAG,SAAS;AAAA,YAClB,QAAQ,OAAO,gBAAgB;AAAA,YAC/B,SAAS,OAAO,gBAAgB,WAC5B,kCACA,iBAAiB,OAAO,WAAW;AAAA,UACzC,CAAC;AAAA,QACH;AAGA,YAAI,OAAO,gBAAgB;AACzB,gBAAM,gBAAgB,MAAMA,cAAa,iBAAiB;AAC1D,iBAAO,KAAK;AAAA,YACV,MAAM,GAAG,SAAS;AAAA,YAClB,QAAQ,cAAc;AAAA,YACtB,SAAS,cAAc,UACnB,2BAA2B,cAAc,IAAI,KAC7C;AAAA,UACN,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI,MAAM,aAAa;AACrB,YAAM,SAAS,WAAW;AAG1B,WAAK,CAAC,MAAM,YAAY,gBAAgB,MAAM,YAAY,aAAa,WAAW,MAC9E,OAAO,MAAM,MAAM,SAAS,KAAK,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG,GAAG;AACtE,eAAO,KAAK;AAAA,UACV,MAAM,GAAG,SAAS;AAAA,UAClB,QAAQ;AAAA;AAAA,UACR,SAAS,0DAA0D,OAAO,MAAM,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,QAC9G,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,YAA2B;AAC/C,UAAQ,IAAIC,OAAM,KAAK,4BAA4B,CAAC;AAEpD,QAAM,SAAwB,CAAC;AAG/B,QAAM,aAAa,WAAW;AAC9B,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,eAAe;AAAA,IACvB,SAAS,aACL,YAAY,UAAU,KACtB;AAAA,EACN,CAAC;AAGD,MAAI,YAAY;AACd,QAAI;AACF,YAAM,SAAS,WAAW,UAAU;AACpC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,YAAY,OAAO,OAAO,YAAY,OAAO,KAAK;AAAA,MAC7D,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,gBAAgB,KAAK;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,WAAWC,MAAKC,SAAQ,GAAG,WAAW;AAC5C,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQC,YAAW,QAAQ;AAAA,IAC3B,SAASA,YAAW,QAAQ,IACxB,YAAY,QAAQ,KACpB;AAAA,EACN,CAAC;AAGD,MAAI;AACF,UAAM,OAAO,UAAU;AACvB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,MAAI,YAAY;AACd,UAAM,SAAS,WAAW,UAAU;AACpC,UAAM,iBAAiB,OAAO,QAAQ;AACtC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,iBACL,gBAAgB,OAAO,QAAQ,SAAS,MAAM,cAC9C;AAAA,IACN,CAAC;AAAA,EACH;AAGA,MAAI,YAAY;AACd,UAAM,SAAS,WAAW,UAAU;AACpC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,OAAO,UAAU;AAAA,MACzB,SAAS,OAAO,UAAU,UACtB,GAAG,OAAO,UAAU,YAAY,SAAS,OAAO,UAAU,UAAU,QACpE;AAAA,IACN,CAAC;AAAA,EACH;AAGA,QAAM,SAAS,MAAM,mBAAmB;AACxC,QAAM,kBAAkB,OAAO,OAAO,OAAK,EAAE,SAAS;AAEtD,MAAI,gBAAgB,SAAS,GAAG;AAE9B,UAAM,cAAc,MAAM,kBAAkB,eAAe;AAC3D,WAAO,KAAK,GAAG,WAAW;AAAA,EAC5B,OAAO;AACL,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,MAAI,YAAY;AACd,UAAM,SAAS,WAAW,UAAU;AACpC,UAAM,cAAc,OAAO,MAAM,WAAW;AAC5C,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,cACL,2BAA2B,OAAO,KAAK,SAAS,YAAY,QAC5D;AAAA,IACN,CAAC;AAAA,EACH;AAGA,MAAI,YAAY;AACd,UAAM,SAAS,WAAW,UAAU;AACpC,UAAM,cAAc,OAAO,WAAW,WAAW;AACjD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,cACL,cAAc,OAAO,UAAU,IAAI,IAAI,OAAO,UAAU,IAAI,KAC5D;AAAA,IACN,CAAC;AAAA,EACH;AAGA,MAAI;AACF,UAAM,UAAU,IAAI,gBAAgB;AACpC,UAAM,kBAAkB,QAAQ,UAAU;AAC1C,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,qBAAqB,gBAAgB,MAAM;AAAA,IACtD,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,MAAI;AACF,UAAM,UAAU,IAAI,qBAAqB;AACzC,UAAM,WAAW,QAAQ,YAAY;AACrC,UAAM,eAAe,SAAS,OAAO,OAAK,EAAE,aAAa,aAAa,EAAE;AACxE,UAAM,cAAc,SAAS,OAAO,OAAK,EAAE,aAAa,KAAK,EAAE;AAC/D,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,UAAU,SAAS,MAAM,cAAc,YAAY,gBAAgB,WAAW;AAAA,IACzF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,MAAI,SAAS;AACb,MAAI,SAAS;AAEb,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,SAASH,OAAM,MAAM,QAAG,IAAIA,OAAM,IAAI,QAAG;AAC5D,UAAM,SAAS,MAAM,SAASA,OAAM,MAAM,IAAI,IAAIA,OAAM,IAAI,MAAM;AAElE,YAAQ,IAAI,KAAK,IAAI,IAAIA,OAAM,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE;AAC5D,YAAQ,IAAIA,OAAM,IAAI,OAAO,MAAM,OAAO,EAAE,CAAC;AAC7C,YAAQ,IAAI;AAEZ,QAAI,MAAM,OAAQ;AAAA,QACb;AAAA,EACP;AAGA,UAAQ,IAAIA,OAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACtC,MAAI,WAAW,GAAG;AAChB,YAAQ,IAAIA,OAAM,MAAM;AAAA,aAAW,MAAM;AAAA,CAAsC,CAAC;AAAA,EAClF,OAAO;AACL,YAAQ,IAAIA,OAAM,OAAO;AAAA,EAAK,MAAM,YAAY,MAAM;AAAA,CAA8B,CAAC;AAAA,EACvF;AACF;;;AKxSA,OAAOI,YAAW;AAClB,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,OAAO,aAAAC,kBAAiB;AAQjC,IAAI,kBAA0C;AAC9C,IAAI,aAAgC;AAEpC,SAAS,UAAgB;AACvB,MAAI,QAAQ,MAAM,OAAO;AACvB,YAAQ,MAAM,WAAW,KAAK;AAAA,EAChC;AACF;AAEA,eAAsB,WAAW,SAA+C;AAC9E,QAAM,aAAa,WAAW;AAE9B,MAAI,CAAC,YAAY;AACf,YAAQ,IAAIC,OAAM,IAAI,6CAA6C,CAAC;AACpE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAIA,OAAM,IAAI,qDAAuD,CAAC;AAC9E,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,mBAAmB;AACjD,UAAQ,IAAIA,OAAM,IAAI,aAAa,UAAU,EAAE,CAAC;AAChD,UAAQ,IAAIA,OAAM,IAAI,wBAAwB,CAAC;AAC/C,UAAQ,IAAI;AAEZ,QAAM,WAAW,IAAI,SAAS,UAAU;AACxC,QAAM,SAAS,SAAS,UAAU;AAGlC,MAAI;AACF,sBAAkB,IAAI,gBAAgB;AACtC,iBAAa,IAAI,WAAW;AAG5B,UAAM,YAAY,gBAAgB,aAAa,OAAO,OAAO,QAAQ,IAAI,CAAC;AAC1E,QAAI,QAAQ,SAAS;AACnB,cAAQ,IAAIA,OAAM,IAAI,cAAc,SAAS,EAAE,CAAC;AAAA,IAClD;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,QAAQ,SAAS;AACnB,cAAQ,IAAIA,OAAM,OAAO,gCAAgC,CAAC;AAAA,IAC5D;AAAA,EACF;AAGA,MAAI,iBAAgC;AACpC,MAAI,yBAAyB;AAE7B,WAAS,kBAAkB,SAAiB,YAAuD;AACjG,qBAAiB;AACjB,6BAAyB;AAEzB,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,IAAI,6CAAiC,CAAC;AACxD,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,IAAI,YAAY,GAAG,OAAO;AAC5C,YAAQ,IAAIA,OAAM,IAAI,WAAW,GAAG,WAAW,CAAC,EAAE,OAAO;AACzD,YAAQ,IAAIA,OAAM,IAAI,WAAW,GAAG,WAAW,CAAC,EAAE,IAAI;AACtD,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,OAAO,uBAAuB,CAAC;AACjD,YAAQ,IAAIA,OAAM,KAAK,SAAS,GAAG,YAAY;AAC/C,YAAQ,IAAIA,OAAM,KAAK,SAAS,GAAG,mBAAmB;AACtD,YAAQ,IAAIA,OAAM,KAAK,SAAS,GAAG,mBAAmB;AACtD,YAAQ,IAAIA,OAAM,KAAK,SAAS,GAAG,iBAAiB;AACpD,YAAQ,OAAO,MAAMA,OAAM,IAAI,cAAc,CAAC;AAAA,EAChD;AAEA,WAAS,qBAAqB,QAAsB;AAClD,QAAI,CAAC,eAAgB;AAErB,UAAM,UAAU;AAChB,qBAAiB;AACjB,6BAAyB;AAEzB,YAAQ,IAAI,MAAM;AAElB,YAAQ,OAAO,YAAY,GAAG;AAAA,MAC5B,KAAK;AAEH,gBAAQ,IAAIA,OAAM,MAAM,uBAAkB,CAAC;AAC3C,gBAAQ,IAAI;AACZ,iBAAS,MAAM,UAAU,IAAI;AAC7B;AAAA,MAEF,KAAK;AAEH,wBAAgB,OAAO;AACvB,gBAAQ,IAAIA,OAAM,MAAM,8BAAyB,CAAC;AAClD,gBAAQ,IAAI;AACZ,iBAAS,MAAM,UAAU,IAAI;AAC7B;AAAA,MAEF,KAAK;AAEH,YAAI;AACF,gBAAM,UAAUC,cAAa,YAAY,OAAO;AAChD,gBAAMC,UAAS,MAAM,OAAO;AAE5B,cAAI,CAACA,QAAO,UAAU;AACpB,YAAAA,QAAO,WAAW,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,UAC3C;AACA,cAAI,CAACA,QAAO,SAAS,OAAO;AAC1B,YAAAA,QAAO,SAAS,QAAQ,CAAC;AAAA,UAC3B;AAEA,cAAI,CAACA,QAAO,SAAS,MAAM,SAAS,OAAO,GAAG;AAC5C,YAAAA,QAAO,SAAS,MAAM,KAAK,OAAO;AAClC,YAAAC,eAAc,YAAYC,WAAUF,OAAM,CAAC;AAAA,UAC7C;AAEA,kBAAQ,IAAIF,OAAM,MAAM,yCAAoC,CAAC;AAC7D,kBAAQ,IAAI;AACZ,mBAAS,MAAM,UAAU,IAAI;AAAA,QAC/B,SAAS,OAAO;AACd,kBAAQ,IAAIA,OAAM,IAAI,kCAA6B,CAAC;AACpD,kBAAQ,IAAI;AAAA,QACd;AACA;AAAA,MAEF,KAAK;AAAA,MACL;AAEE,gBAAQ,IAAIA,OAAM,OAAO,kBAAa,CAAC;AACvC,gBAAQ,IAAI;AACZ;AAAA,IACJ;AAAA,EACF;AAEA,WAAS,GAAG,WAAW,CAAC,SAAS,eAAe;AAE9C,QAAI,mBAAmB,YAAY;AACjC,YAAM,OAAO,WAAW,MAAM,OAAO;AACrC,sBAAgB,cAAc,SAAS,OAAO,MAAM,YAAY,CAAC;AAAA,IACnE;AACA,sBAAkB,SAAS,UAAU;AAAA,EACvC,CAAC;AAED,WAAS,GAAG,WAAW,CAAC,WAAW;AAEjC,QAAI,mBAAmB,YAAY;AACjC,YAAM,OAAO,WAAW,MAAM,OAAO,OAAO;AAC5C,sBAAgB,cAAc,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,OAAO,QAAQ;AAAA,IAC/E;AACA,QAAI,QAAQ,SAAS;AACnB,cAAQ,IAAIA,OAAM,MAAM,QAAG,GAAGA,OAAM,IAAI,OAAO,OAAO,CAAC;AAAA,IACzD;AAAA,EACF,CAAC;AAED,WAAS,GAAG,UAAU,CAAC,SAAS;AAC9B,YAAQ,OAAO,MAAM,IAAI;AAAA,EAC3B,CAAC;AAED,WAAS,GAAG,SAAS,CAAC,UAAU;AAC9B,YAAQ,MAAMA,OAAM,IAAI,QAAQ,GAAG,MAAM,OAAO;AAAA,EAClD,CAAC;AAGD,WAAS,GAAG,QAAQ,CAAC,aAAa;AAEhC,QAAI,iBAAiB;AACnB,sBAAgB,WAAW;AAC3B,sBAAgB,MAAM;AAAA,IACxB;AACA,YAAQ;AACR,YAAQ,KAAK,YAAY,CAAC;AAAA,EAC5B,CAAC;AAGD,UAAQ,GAAG,UAAU,MAAM;AACzB,YAAQ;AACR,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,OAAO,sBAAsB,CAAC;AAGhD,QAAI,iBAAiB;AACnB,sBAAgB,WAAW;AAC3B,sBAAgB,MAAM;AAAA,IACxB;AAEA,aAAS,KAAK;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,WAAW,MAAM;AAC1B,YAAQ;AAGR,QAAI,iBAAiB;AACnB,sBAAgB,WAAW;AAC3B,sBAAgB,MAAM;AAAA,IACxB;AAEA,aAAS,KAAK;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGD,UAAQ,GAAG,qBAAqB,CAAC,UAAU;AACzC,YAAQ,MAAMA,OAAM,IAAI,mBAAmB,GAAG,MAAM,OAAO;AAG3D,QAAI,iBAAiB;AACnB,sBAAgB,aAAa;AAC7B,sBAAgB,MAAM;AAAA,IACxB;AAEA,YAAQ;AACR,aAAS,KAAK;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,WAAS,MAAM;AAGf,MAAI,gBAAgB;AAGpB,MAAI,QAAQ,OAAO,OAAO;AACxB,aAAS,OAAO,QAAQ,OAAO,SAAS,QAAQ,OAAO,IAAI;AAAA,EAC7D;AAGA,UAAQ,OAAO,GAAG,UAAU,MAAM;AAChC,QAAI,QAAQ,OAAO,OAAO;AACxB,eAAS,OAAO,QAAQ,OAAO,SAAS,QAAQ,OAAO,IAAI;AAAA,IAC7D;AAAA,EACF,CAAC;AAGD,MAAI,QAAQ,MAAM,OAAO;AACvB,YAAQ,MAAM,WAAW,IAAI;AAAA,EAC/B;AACA,UAAQ,MAAM,OAAO;AAGrB,UAAQ,MAAM,GAAG,QAAQ,CAAC,SAAS;AACjC,UAAM,MAAM,KAAK,SAAS;AAE1B,eAAW,QAAQ,KAAK;AACtB,YAAM,OAAO,KAAK,WAAW,CAAC;AAG9B,UAAI,wBAAwB;AAC1B,YAAI,SAAS,GAAG;AAEd,2BAAiB;AACjB,mCAAyB;AACzB,kBAAQ,IAAIA,OAAM,OAAO,WAAW,CAAC;AACrC,kBAAQ,IAAI;AAAA,QACd,WAAW,SAAS,QAAQ,SAAS,MAAM;AAEzC,+BAAqB,GAAG;AAAA,QAC1B,WAAW,QAAQ,IAAI;AAErB,+BAAqB,IAAI;AAAA,QAC3B;AACA;AAAA,MACF;AAGA,UAAI,SAAS,QAAQ,SAAS,MAAM;AAClC,cAAM,UAAU,cAAc,KAAK;AACnC,wBAAgB;AAEhB,YAAI,SAAS;AAEX,gBAAM,aAAa,SAAS,aAAa,OAAO;AAEhD,cAAI,WAAW,SAAS,GAAG;AAEzB,qBAAS,MAAM,GAAM;AACrB,qBAAS,MAAM,IAAI;AACnB,qBAAS,KAAK,WAAW,SAAS,UAAU;AAAA,UAC9C,OAAO;AAEL,qBAAS,MAAM,IAAI;AAAA,UACrB;AAAA,QACF,OAAO;AAEL,mBAAS,MAAM,IAAI;AAAA,QACrB;AAAA,MACF,WAES,SAAS,OAAO,SAAS,GAAG;AACnC,YAAI,cAAc,SAAS,GAAG;AAC5B,0BAAgB,cAAc,MAAM,GAAG,EAAE;AAAA,QAC3C;AACA,iBAAS,MAAM,IAAI;AAAA,MACrB,WAES,SAAS,IAAI;AAEpB,iBAAS,MAAM,IAAI;AAAA,MACrB,WAES,SAAS,GAAG;AACnB,wBAAgB;AAChB,iBAAS,MAAM,IAAI;AAAA,MACrB,WAES,SAAS,IAAI;AACpB,wBAAgB;AAChB,iBAAS,MAAM,IAAI;AAAA,MACrB,WAES,QAAQ,MAAM,SAAS,KAAM;AACpC,yBAAiB;AACjB,iBAAS,MAAM,IAAI;AAAA,MACrB,OAEK;AACH,iBAAS,MAAM,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC5B;;;ACxUA,OAAOK,YAAW;AAClB,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AAIjC,eAAsB,YACpB,SACA,SACe;AACf,MAAI,QAAQ,MAAM;AAEhB,oBAAgB,OAAO;AACvB,YAAQ,IAAIC,OAAM,MAAM,QAAG,GAAG,6BAA6B,OAAO,EAAE;AACpE,YAAQ,IAAIA,OAAM,IAAI,2CAA2C,CAAC;AAClE;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS;AACnB,UAAM,aAAa,WAAW;AAE9B,QAAI,CAAC,YAAY;AACf,cAAQ,IAAIA,OAAM,IAAI,6CAA6C,CAAC;AACpE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,UAAUC,cAAa,YAAY,OAAO;AAChD,YAAM,SAASC,OAAM,OAAO;AAG5B,UAAI,CAAC,OAAO,UAAU;AACpB,eAAO,WAAW,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,MAC3C;AACA,UAAI,CAAC,OAAO,SAAS,OAAO;AAC1B,eAAO,SAAS,QAAQ,CAAC;AAAA,MAC3B;AAGA,UAAI,CAAC,OAAO,SAAS,MAAM,SAAS,OAAO,GAAG;AAC5C,eAAO,SAAS,MAAM,KAAK,OAAO;AAClC,QAAAC,eAAc,YAAYC,WAAU,MAAM,CAAC;AAE3C,gBAAQ,IAAIJ,OAAM,MAAM,QAAG,GAAG,uBAAuB,OAAO,EAAE;AAC9D,gBAAQ,IAAIA,OAAM,IAAI,aAAa,UAAU,EAAE,CAAC;AAAA,MAClD,OAAO;AACL,gBAAQ,IAAIA,OAAM,OAAO,uBAAuB,GAAG,OAAO;AAAA,MAC5D;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAMA,OAAM,IAAI,0BAA0B,GAAG,KAAK;AAC1D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA;AAAA,EACF;AAGA,UAAQ,IAAIA,OAAM,OAAO,oCAAoC,CAAC;AAC9D,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,qBAAqB,OAAO,UAAU,CAAC;AAC9D,UAAQ,IAAIA,OAAM,IAAI,oCAAoC,CAAC;AAC3D,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,qBAAqB,OAAO,aAAa,CAAC;AACjE,UAAQ,IAAIA,OAAM,IAAI,oCAAoC,CAAC;AAC7D;;;AC3DA,OAAO,aAA4D;AACnE,SAAS,uBAAuC;AAChD,SAAS,oBAAiC;AAC1C,SAAS,qBAAqB;AAC9B,SAAS,SAAS,QAAAK,aAAY;AAC9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,kBAAiB;AACnE,SAAS,SAAAC,QAAO,aAAAC,kBAAiB;AAKjC,SAAS,mBAA2B;AAClC,QAAM,cAAcC,MAAKC,SAAQ,GAAG,WAAW;AAC/C,MAAI,CAACC,YAAW,WAAW,GAAG;AAC5B,IAAAC,WAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5C;AACA,SAAOH,MAAK,aAAa,cAAc;AACzC;AAgBO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EACA,SAAwB;AAAA,EACxB,MAA8B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAA0B,oBAAI,IAAI;AAAA,EAE1C,YAAY,SAAuB,CAAC,GAAG;AACrC,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,OAAO,OAAO,QAAQ;AAE3B,SAAK,KAAK,IAAI,YAAY,OAAO,UAAU,iBAAiB,CAAC;AAC7D,SAAK,MAAM,QAAQ;AAEnB,SAAK,gBAAgB;AACrB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,IAAI,IAAI,QAAQ,KAAK,CAAC;AAG3B,SAAK,IAAI,IAAI,CAAC,MAAe,KAAe,SAAS;AACnD,UAAI,OAAO,+BAA+B,GAAG;AAC7C,UAAI,OAAO,gCAAgC,oBAAoB;AAC/D,UAAI,OAAO,gCAAgC,cAAc;AACzD,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEQ,cAAoB;AAE1B,SAAK,IAAI,IAAI,eAAe,CAAC,MAAe,QAAkB;AAC5D,UAAI,KAAK,EAAE,QAAQ,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAAA,IAChE,CAAC;AAGD,SAAK,IAAI,IAAI,cAAc,CAAC,MAAe,QAAkB;AAC3D,UAAI;AACF,cAAM,QAAQ,KAAK,GAAG,SAAS;AAC/B,YAAI,KAAK,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,MACzD;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,eAAe,CAAC,KAAc,QAAkB;AAC3D,UAAI;AACF,cAAM,SAAkC,CAAC;AAEzC,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,IAAI,MAAM;AAChD,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,MAAM;AAC9C,YAAI,IAAI,MAAM,SAAU,QAAO,WAAW,IAAI,MAAM;AACpD,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE;AAC1E,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,SAAS,IAAI,MAAM,QAAkB,EAAE;AAC7E,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,KAAK,IAAI,MAAM,KAAe;AAEtE,cAAM,SAAS,KAAK,GAAG,UAAU,MAAM;AACvC,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAAA,MAC1D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,mBAAmB,CAAC,MAAe,QAAkB;AAChE,UAAI;AAEF,cAAM,SAAS,KAAK,GAAG,sBAAsB,GAAI;AACjD,cAAM,aAAa,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,OAAK,EAAE,SAAS,CAAC,CAAC;AAC5D,YAAI,KAAK,UAAU;AAAA,MACrB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,6BAA6B,CAAC;AAAA,MAC9D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,gCAAgC,CAAC,KAAc,QAAkB;AAC5E,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,SAAS,KAAK,GAAG,mBAAmB,IAAI,OAAO,MAAM,KAAK;AAChE,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mCAAmC,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,gBAAgB,CAAC,MAAe,QAAkB;AAC7D,UAAI;AACF,cAAM,SAAS,KAAK,GAAG,iBAAiB;AACxC,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,gCAAgC,CAAC;AAAA,MACjE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,KAAK,4BAA4B,CAAC,KAAc,QAAkB;AACzE,UAAI;AACF,cAAM,EAAE,GAAG,IAAI,IAAI;AACnB,cAAM,aAAa,IAAI,MAAM,cAAc;AAE3C,cAAM,QAAQ,KAAK,GAAG,SAAS,EAAE;AACjC,YAAI,CAAC,OAAO;AACV,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AACjD;AAAA,QACF;AAEA,aAAK,GAAG,aAAa,IAAI,UAAU;AACnC,aAAK,UAAU,EAAE,MAAM,kBAAkB,GAAG,CAAC;AAC7C,YAAI,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,MAC5B,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,CAAC;AAAA,MAC3D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,KAAK,yBAAyB,CAAC,KAAc,QAAkB;AACtE,UAAI;AACF,cAAM,EAAE,GAAG,IAAI,IAAI;AACnB,cAAM,WAAW,IAAI,MAAM,YAAY;AAEvC,cAAM,QAAQ,KAAK,GAAG,SAAS,EAAE;AACjC,YAAI,CAAC,OAAO;AACV,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AACjD;AAAA,QACF;AAEA,aAAK,GAAG,UAAU,IAAI,QAAQ;AAC9B,aAAK,UAAU,EAAE,MAAM,gBAAgB,GAAG,CAAC;AAC3C,YAAI,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,MAC5B,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAAA,MACxD;AAAA,IACF,CAAC;AAOD,SAAK,IAAI,IAAI,iBAAiB,CAAC,KAAc,QAAkB;AAC7D,UAAI;AACF,cAAM,SAAkC,CAAC;AAEzC,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,IAAI,MAAM;AAChD,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,MAAM;AAC9C,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE;AAC1E,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,SAAS,IAAI,MAAM,QAAkB,EAAE;AAC7E,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,KAAK,IAAI,MAAM,KAAe;AACtE,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,KAAK,IAAI,MAAM,KAAe;AAEtE,cAAM,WAAW,KAAK,GAAG,YAAY,MAAM;AAC3C,YAAI,KAAK,QAAQ;AAAA,MACnB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,wBAAwB,CAAC,MAAe,QAAkB;AACrE,UAAI;AACF,cAAM,UAAU,KAAK,GAAG,iBAAiB;AACzC,YAAI,CAAC,SAAS;AACZ,cAAI,KAAK,IAAI;AACb;AAAA,QACF;AACA,YAAI,KAAK,OAAO;AAAA,MAClB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iCAAiC,CAAC;AAAA,MAClE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,qBAAqB,CAAC,KAAc,QAAkB;AACjE,UAAI;AACF,cAAM,UAAU,KAAK,GAAG,WAAW,IAAI,OAAO,EAAE;AAChD,YAAI,CAAC,SAAS;AACZ,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AACnD;AAAA,QACF;AACA,YAAI,KAAK,OAAO;AAAA,MAClB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,CAAC;AAAA,MAC3D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,8BAA8B,CAAC,KAAc,QAAkB;AAC1E,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,WAAW,KAAK,GAAG,qBAAqB,IAAI,OAAO,IAAI,KAAK;AAClE,YAAI,KAAK,QAAQ;AAAA,MACnB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mCAAmC,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,6BAA6B,CAAC,KAAc,QAAkB;AACzE,UAAI;AACF,cAAM,UAAU,KAAK,GAAG,WAAW,IAAI,OAAO,EAAE;AAChD,YAAI,CAAC,SAAS;AACZ,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AACnD;AAAA,QACF;AACA,cAAM,UAAU,KAAK,GAAG,kBAAkB,IAAI,OAAO,EAAE;AACvD,YAAI,KAAK,OAAO;AAAA,MAClB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kCAAkC,CAAC;AAAA,MACnE;AAAA,IACF,CAAC;AAOD,SAAK,IAAI,IAAI,sBAAsB,CAAC,KAAc,QAAkB;AAClE,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,WAAW,KAAK,GAAG,gBAAgB,KAAK;AAC9C,YAAI,KAAK,QAAQ;AAAA,MACnB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,gCAAgC,CAAC;AAAA,MACjE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,iBAAiB,CAAC,KAAc,QAAkB;AAC7D,UAAI;AACF,cAAM,SAAkC,CAAC;AAEzC,YAAI,IAAI,MAAM,UAAW,QAAO,YAAY,IAAI,MAAM;AACtD,YAAI,IAAI,MAAM,YAAY,OAAW,QAAO,UAAU,IAAI,MAAM,YAAY;AAC5E,YAAI,IAAI,MAAM,UAAW,QAAO,YAAY,IAAI,MAAM;AACtD,YAAI,IAAI,MAAM,QAAS,QAAO,UAAU,IAAI,MAAM;AAClD,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,KAAK,IAAI,MAAM,KAAe;AACtE,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE;AAC1E,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,SAAS,IAAI,MAAM,QAAkB,EAAE;AAE7E,cAAM,WAAW,KAAK,GAAG,YAAY,MAAM;AAC3C,YAAI,KAAK,QAAQ;AAAA,MACnB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAOD,SAAK,IAAI,IAAI,mBAAmB,CAAC,KAAc,QAAkB;AAC/D,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,QAAQ,KAAK,GAAG,gBAAgB,KAAK;AAC3C,YAAI,KAAK,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iCAAiC,CAAC;AAAA,MAClE;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,cAAc,CAAC,KAAc,QAAkB;AAC1D,UAAI;AACF,cAAM,SAAkC,CAAC;AAEzC,YAAI,IAAI,MAAM,SAAU,QAAO,WAAW,IAAI,MAAM;AACpD,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,IAAI,KAAK,IAAI,MAAM,KAAe;AACtE,YAAI,IAAI,MAAM,MAAO,QAAO,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE;AAC1E,YAAI,IAAI,MAAM,OAAQ,QAAO,SAAS,SAAS,IAAI,MAAM,QAAkB,EAAE;AAE7E,cAAM,QAAQ,KAAK,GAAG,YAAY,MAAM;AACxC,YAAI,KAAK,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,MAC7D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,oBAAoB,CAAC,MAAe,QAAkB;AACjE,UAAI;AACF,cAAM,QAAQ,KAAK,GAAG,gBAAgB;AACtC,YAAI,KAAK,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iCAAiC,CAAC;AAAA,MAClE;AAAA,IACF,CAAC;AAOD,SAAK,IAAI,IAAI,mBAAmB,CAAC,MAAe,QAAkB;AAChE,UAAI;AACF,cAAM,SAAS,KAAK,GAAG,mBAAmB;AAC1C,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,6BAA6B,CAAC;AAAA,MAC9D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,mBAAmB,CAAC,KAAc,QAAkB;AAC/D,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,YAAY,IAAI,MAAM;AAC5B,cAAM,SAAS,KAAK,GAAG,aAAa,OAAO,SAAS;AACpD,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,6BAA6B,CAAC;AAAA,MAC9D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,mBAAmB,OAAO,MAAe,QAAkB;AACtE,UAAI;AAEF,cAAM,aAAa,IAAI,gBAAgB;AACvC,cAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAI;AAEzD,cAAM,WAAW,MAAM,MAAM,mCAAmC;AAAA,UAC9D,QAAQ,WAAW;AAAA,QACrB,CAAC;AAED,qBAAa,OAAO;AAEpB,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,KAAK,EAAE,WAAW,OAAO,QAAQ,CAAC,EAAE,CAAC;AACzC;AAAA,QACF;AAEA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC;AACnD,YAAI,KAAK,EAAE,WAAW,MAAM,OAAO,CAAC;AAAA,MACtC,SAAS,OAAO;AACd,YAAI,KAAK,EAAE,WAAW,OAAO,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC3C;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,KAAK,kBAAkB,CAAC,KAAc,QAAkB;AAC/D,UAAI;AACF,cAAM,EAAE,MAAM,IAAI,IAAI;AACtB,YAAI,CAAC,OAAO;AACV,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,CAAC;AACrD;AAAA,QACF;AAGA,cAAM,cAAcA,MAAKC,SAAQ,GAAG,aAAa,oBAAoB;AACrE,QAAAG,eAAc,aAAa,KAAK,UAAU;AAAA,UACxC;AAAA,UACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,CAAC,GAAG,OAAO;AAEX,YAAI,KAAK,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,MACnC,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAAA,MAC1D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,KAAK,iBAAiB,CAAC,MAAe,QAAkB;AAC/D,UAAI;AACF,cAAM,cAAcJ,MAAKC,SAAQ,GAAG,aAAa,mBAAmB;AACpE,QAAAG,eAAc,aAAa,KAAK,UAAU;AAAA,UACxC,QAAQ;AAAA,UACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,CAAC,GAAG,OAAO;AAEX,YAAI,KAAK,EAAE,SAAS,MAAM,SAAS,iBAAiB,CAAC;AAAA,MACvD,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAAA,MAC1D;AAAA,IACF,CAAC;AAOD,SAAK,IAAI,IAAI,kBAAkB,CAAC,KAAc,QAAkB;AAC9D,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAC1E,cAAM,YAAY,KAAK,GAAG,mBAAmB,KAAK;AAClD,YAAI,KAAK,SAAS;AAAA,MACpB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,MAC7D;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,IAAI,eAAe,CAAC,MAAe,QAAkB;AAC5D,UAAI;AACF,cAAM,aAAa,WAAW;AAC9B,YAAI,CAAC,YAAY;AACf,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AACtD;AAAA,QACF;AACA,cAAM,UAAUC,cAAa,YAAY,OAAO;AAChD,cAAM,SAASC,OAAM,OAAO;AAC5B,YAAI,KAAK,MAAM;AAAA,MACjB,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,MACzD;AAAA,IACF,CAAC;AAGD,SAAK,IAAI,KAAK,eAAe,CAAC,KAAc,QAAkB;AAC5D,UAAI;AACF,cAAM,aAAa,WAAW;AAC9B,YAAI,CAAC,YAAY;AACf,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AACtD;AAAA,QACF;AACA,cAAM,SAAS,IAAI;AACnB,cAAM,UAAUC,WAAU,MAAM;AAChC,QAAAH,eAAc,YAAY,SAAS,OAAO;AAC1C,YAAI,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,MAC5B,SAAS,OAAO;AACd,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,MACzD;AAAA,IACF,CAAC;AAGD,UAAM,aAAa,cAAc,YAAY,GAAG;AAChD,UAAM,YAAY,QAAQ,UAAU;AACpC,UAAM,aAAaJ,MAAK,WAAW,QAAQ;AAC3C,SAAK,IAAI,IAAI,QAAQ,OAAO,UAAU,CAAC;AAGvC,SAAK,IAAI,IAAI,YAAY,CAAC,MAAe,QAAkB;AACzD,UAAI,SAASA,MAAK,YAAY,YAAY,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,OAAQ;AAElB,SAAK,MAAM,IAAI,gBAAgB,EAAE,QAAQ,KAAK,OAAO,CAAC;AAEtD,SAAK,IAAI,GAAG,cAAc,CAAC,OAAkB;AAC3C,WAAK,QAAQ,IAAI,EAAE;AAEnB,SAAG,GAAG,SAAS,MAAM;AACnB,aAAK,QAAQ,OAAO,EAAE;AAAA,MACxB,CAAC;AAED,SAAG,GAAG,SAAS,MAAM;AACnB,aAAK,QAAQ,OAAO,EAAE;AAAA,MACxB,CAAC;AAGD,UAAI;AACF,cAAM,QAAQ,KAAK,GAAG,SAAS;AAC/B,WAAG,KAAK,KAAK,UAAU,EAAE,MAAM,SAAS,MAAM,MAAM,CAAC,CAAC;AAAA,MACxD,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAK,SAAS,aAAa,KAAK,GAAG;AACnC,WAAK,eAAe;AAEpB,WAAK,OAAO,GAAG,SAAS,CAAC,UAAiC;AACxD,YAAI,MAAM,SAAS,cAAc;AAC/B,iBAAO,IAAI,MAAM,QAAQ,KAAK,IAAI,oBAAoB,CAAC;AAAA,QACzD,OAAO;AACL,iBAAO,KAAK;AAAA,QACd;AAAA,MACF,CAAC;AAED,WAAK,OAAO,OAAO,KAAK,MAAM,KAAK,MAAM,MAAM;AAC7C,gBAAQ;AAAA,MACV,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,WAAO,IAAI,QAAQ,CAAC,YAAY;AAE9B,iBAAW,UAAU,KAAK,SAAS;AACjC,eAAO,MAAM;AAAA,MACf;AACA,WAAK,QAAQ,MAAM;AAEnB,UAAI,KAAK,KAAK;AACZ,aAAK,IAAI,MAAM;AACf,aAAK,MAAM;AAAA,MACb;AAEA,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,MAAM,MAAM;AACtB,eAAK,SAAS;AACd,eAAK,GAAG,MAAM;AACd,kBAAQ;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AACL,aAAK,GAAG,MAAM;AACd,gBAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAAwB;AAChC,UAAM,OAAO,KAAK,UAAU,OAAO;AACnC,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,OAAO,eAAe,GAAG;AAC3B,eAAO,KAAK,IAAI;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAkB;AAChB,WAAO,KAAK;AAAA,EACd;AACF;;;AT3iBA,IAAI,mBAA4C;AAChD,IAAI,gBAAsC;AAC1C,IAAI,eAAoC;AACxC,IAAI,YAA8B;AAElC,IAAM,OAAO;AAAA;AAAA;AAAA;AAKb,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,UAAU,EACf,YAAY,uBAAuB,EACnC,QAAQ,OAAO;AAElB,QACG,QAAQ,MAAM,EACd,YAAY,kCAAkC,EAC9C,OAAO,YAAY;AAClB,UAAQ,IAAIQ,OAAM,KAAK,IAAI,CAAC;AAC5B,QAAM,cAAc;AACtB,CAAC;AAEH,QACG,QAAQ,OAAO,EACf,YAAY,6BAA6B,EACzC,OAAO,iBAAiB,+BAA+B,EACvD,OAAO,OAAO,YAAY;AACzB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,QAAM,WAAW,OAAO;AAC1B,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,mCAAmC,EAC/C,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,QAAM,UAAU;AAClB,CAAC;AAEH,QACG,QAAQ,iBAAiB,EACzB,YAAY,0BAA0B,EACtC,OAAO,UAAU,gCAAgC,EACjD,OAAO,aAAa,2BAA2B,EAC/C,OAAO,OAAO,SAAS,YAAY;AAClC,QAAM,YAAY,SAAS,OAAO;AACpC,CAAC;AAEH,QACG,QAAQ,OAAO,EACf,YAAY,6BAA6B,EACzC,OAAO,wBAAwB,2BAA2B,IAAI,EAC9D,OAAO,gBAAgB,4BAA4B,EACnD,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,qBAAY;AAC/C,QAAM,UAAU,OAAO;AACzB,CAAC;AAMH,QACG,QAAQ,MAAM,EACd,YAAY,0CAA0C,EACtD,OAAO,wBAAwB,wBAAwB,GAAG,EAC1D,OAAO,OAAO,YAAY;AACzB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,UAAQ,IAAIA,OAAM,IAAI,kCAAkC,CAAC;AAEzD,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,QAAQ,SAAS;AACnB,QAAI,YAAY,QAAQ,OAAO;AAAA,EACjC;AAEA,UAAQ,IAAI,IAAI,iBAAiB,CAAC;AAClC,UAAQ,IAAI;AAGZ,UAAQ,IAAIA,OAAM,KAAK,6BAA6B,CAAC;AACrD,QAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,uBAA2B;AACvE,QAAM,SAAS,MAAM,mBAAmB;AACxC,UAAQ,IAAI,mBAAmB,MAAM,CAAC;AACtC,UAAQ,IAAI;AAEZ,UAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,yDAAyD;AACzF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,MAAM,KAAK,EACX,YAAY,sCAAsC,EAClD,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAE5B,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,UAAQ,IAAI,IAAI,OAAO,CAAC;AAC1B,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,0CAA0C,EACtD,OAAO,uBAAuB,0BAA0B,EACxD,OAAO,qBAAqB,oBAAoB,EAChD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,QAAM,cAAc,IAAI,QAAQ;AAAA,IAC9B,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,KAAK,QAAQ,IAAI;AAAA,EACnB,CAAC;AAED,MAAI,YAAY,WAAW,GAAG;AAC5B,YAAQ,IAAIA,OAAM,IAAI,2BAA2B,CAAC;AAClD;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,gCAAyB,CAAC;AACjD,aAAW,KAAK,aAAa;AAC3B,UAAM,aAAa,KAAK,MAAM,EAAE,aAAa,GAAG;AAChD,YAAQ,IAAI,KAAKA,OAAM,KAAK,EAAE,OAAO,CAAC,EAAE;AACxC,YAAQ,IAAIA,OAAM,IAAI,OAAO,EAAE,WAAW,KAAK,UAAU,eAAe,CAAC;AACzE,YAAQ,IAAI;AAAA,EACd;AACF,CAAC;AAEH,QACG,QAAQ,iBAAiB,EACzB,YAAY,qCAAqC,EACjD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,QAAM,SAAS,IAAI,MAAM,OAAO;AAChC,QAAM,OAAO,OAAO,aAAa,QAAQ,cAAO,OAAO,aAAa,SAAS,cAAO;AACpF,QAAM,QAAQ,OAAO,aAAa,QAAQ,aAAa,OAAO,aAAa,SAAS,eAAe;AAEnG,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAG,IAAI,WAAWA,OAAM,KAAK,KAAK,CAAC,EAAE;AACjD,UAAQ,IAAIA,OAAM,IAAI,cAAc,OAAO,MAAM,EAAE,CAAC;AACpD,UAAQ,IAAIA,OAAM,IAAI,kBAAkB,KAAK,MAAM,OAAO,aAAa,GAAG,CAAC,GAAG,CAAC;AAC/E,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,eAAe,EACvB,YAAY,gCAAgC,EAC5C,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,OAAO,SAAS,YAAY;AAClC,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,QAAQ,YAAY;AACtB,UAAM,OAAO,IAAI,cAAc,OAAO;AACtC,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,4BAA4B,KAAK,EAAE,EAAE;AACnE,YAAQ,IAAIA,OAAM,IAAI,cAAc,OAAO,EAAE,CAAC;AAC9C,YAAQ,IAAIA,OAAM,IAAI,wCAAwC,CAAC;AAAA,EACjE,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,iCAA0B,OAAO;AAAA,CAAI,CAAC;AAC5D,UAAM,SAAS,MAAM,IAAI,QAAQ,OAAO;AACxC,YAAQ,IAAI,MAAM;AAAA,EACpB;AACF,CAAC;AAEH,QACG,QAAQ,OAAO,EACf,YAAY,uBAAuB,EACnC,OAAO,aAAa,mCAAmC,EACvD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,QAAQ;AAExB,QAAM,QAAQ,QAAQ,MAClB,IAAI,mBAAmB,IACvB,IAAI,mBAAmB,EAAE,OAAO,OAAK,EAAE,WAAW,SAAS;AAE/D,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAIA,OAAM,IAAI,sBAAsB,CAAC;AAC7C;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,+BAAwB,CAAC;AAChD,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,UAAU,QAAQ,KAAK,GAAI;AACzE,UAAM,aAAa,KAAK,WAAW,YAAY,WAC5B,KAAK,WAAW,cAAc,WAC9B,KAAK,WAAW,WAAW,WAAM;AAEpD,YAAQ,IAAI,KAAK,UAAU,KAAK,KAAK,EAAE,KAAK,KAAK,OAAO,EAAE;AAC1D,YAAQ,IAAIA,OAAM,IAAI,eAAe,KAAK,MAAM,cAAc,OAAO,GAAG,CAAC;AACzE,YAAQ,IAAI;AAAA,EACd;AACF,CAAC;AAMH,QACG,QAAQ,mBAAmB,EAC3B,YAAY,mCAAmC,EAC/C,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,qCAA8B,CAAC;AACrD,QAAM,cAAc,MAAM,IAAI,UAAU,OAAO;AAC/C,UAAQ,IAAI,WAAW;AACzB,CAAC;AAEH,QACG,QAAQ,eAAe,EACvB,YAAY,sCAAsC,EAClD,OAAO,yBAAyB,uCAAuC,EACvE,OAAO,OAAO,SAAS,YAAY;AAClC,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAQ,IAAIA,OAAM,IAAI,sCAA+B,CAAC;AAEtD,QAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,KAAK;AAE5C,MAAI,OAAO;AACT,YAAQ,IAAIA,OAAM,MAAM,gBAAgB,CAAC;AACzC,YAAQ,IAAIA,OAAM,KAAK,KAAK,KAAK,EAAE,CAAC;AAAA,EACtC,OAAO;AACL,YAAQ,IAAIA,OAAM,OAAO,0BAA0B,CAAC;AAAA,EACtD;AACF,CAAC;AAEH,QACG,QAAQ,aAAa,EACrB,YAAY,uBAAuB,EACnC,OAAO,OAAO,WAAW;AACxB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,qCAA8B,CAAC;AACrD,QAAM,aAAa,MAAM,IAAI,UAAU,MAAM;AAE7C,MAAI,YAAY;AACd,YAAQ,IAAIA,OAAM,KAAK,UAAU,CAAC;AAAA,EACpC,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,0BAA0B,CAAC;AAAA,EACnD;AACF,CAAC;AAEH,QACG,QAAQ,sBAAsB,EAC9B,YAAY,0CAA0C,EACtD,OAAO,uBAAuB,qBAAqB,EACnD,OAAO,OAAO,aAAa,YAAY;AACtC,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,8CAAuC,CAAC;AAC9D,QAAM,SAAS,MAAM,IAAI,iBAAiB,WAAW;AAErD,MAAI,QAAQ;AACV,YAAQ,IAAIA,OAAM,KAAK,MAAM,CAAC;AAE9B,QAAI,QAAQ,QAAQ;AAClB,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,IAAI;AAC3C,MAAAA,eAAc,QAAQ,QAAQ,QAAQ,EAAE,MAAM,IAAM,CAAC;AACrD,cAAQ,IAAID,OAAM,MAAM;AAAA,kBAAgB,QAAQ,MAAM,EAAE,CAAC;AAAA,IAC3D;AAAA,EACF,OAAO;AACL,YAAQ,IAAIA,OAAM,OAAO,4BAA4B,CAAC;AAAA,EACxD;AACF,CAAC;AAEH,QACG,QAAQ,kBAAkB,EAC1B,YAAY,sCAAsC,EAClD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,sCAA+B,CAAC;AACtD,QAAM,WAAW,MAAM,IAAI,gBAAgB,OAAO;AAElD,QAAM,aAAa;AAAA,IACjB,KAAKA,OAAM;AAAA,IACX,QAAQA,OAAM;AAAA,IACd,MAAMA,OAAM;AAAA,IACZ,UAAUA,OAAM,MAAM;AAAA,EACxB;AAEA,QAAM,OAAO,SAAS,OAAO,WAAM;AACnC,QAAM,QAAQ,WAAW,SAAS,IAAI;AAEtC,UAAQ,IAAI,GAAG,IAAI,gBAAgB,MAAM,SAAS,KAAK,YAAY,CAAC,CAAC,EAAE;AACvE,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,cAAc,CAAC;AACtC,UAAQ,IAAI,KAAK,SAAS,WAAW,EAAE;AAEvC,MAAI,SAAS,YAAY,SAAS,GAAG;AACnC,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,KAAK,cAAc,CAAC;AACtC,eAAW,cAAc,SAAS,aAAa;AAC7C,cAAQ,IAAI,YAAO,UAAU,EAAE;AAAA,IACjC;AAAA,EACF;AACF,CAAC;AAEH,QACG,QAAQ,iBAAiB,EACzB,MAAM,GAAG,EACT,YAAY,oCAAoC,EAChD,OAAO,OAAO,UAAU;AACvB,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,4CAAqC,CAAC;AAC5D,QAAM,OAAO,MAAM,IAAI,OAAO,KAAK;AACnC,UAAQ,IAAI,IAAI;AAClB,CAAC;AAEH,QACG,QAAQ,kBAAkB,EAC1B,YAAY,uCAAuC,EACnD,OAAO,iBAAiB,sCAAsC,EAC9D,OAAO,OAAO,aAAa,YAAY;AACtC,QAAM,MAAM,IAAI,QAAQ;AACxB,QAAM,IAAI,WAAW;AAErB,MAAI,CAAC,IAAI,kBAAkB,GAAG;AAC5B,YAAQ,IAAIA,OAAM,OAAO,wDAAwD,CAAC;AAClF;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,wCAAiC,CAAC;AACxD,QAAM,UAAU,MAAM,IAAI,YAAY,WAAW;AAEjD,MAAI,SAAS;AACX,YAAQ,IAAIA,OAAM,KAAK,UAAU,CAAC;AAClC,YAAQ,IAAIA,OAAM,KAAK,OAAO,OAAO,EAAE,CAAC;AAExC,QAAI,QAAQ,SAAS;AACnB,cAAQ,IAAI;AACZ,cAAQ,IAAIA,OAAM,IAAI,cAAc,CAAC;AACrC,YAAM,SAAS,MAAM,IAAI,QAAQ,OAAO;AACxC,cAAQ,IAAI,MAAM;AAAA,IACpB;AAAA,EACF,OAAO;AACL,YAAQ,IAAIA,OAAM,OAAO,mCAAmC,CAAC;AAAA,EAC/D;AACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAE5B,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAiB;AACvD,QAAM,SAAS,IAAI,aAAa;AAEhC,QAAM,YAAY,MAAM,OAAO,YAAY;AAC3C,MAAI,CAAC,WAAW;AACd,YAAQ,IAAIA,OAAM,OAAO,2DAA2D,CAAC;AACrF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,OAAO,WAAW;AAEvC,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIA,OAAM,IAAI,wDAAwD,CAAC;AAC/E;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,+BAAwB,CAAC;AAChD,aAAW,SAAS,QAAQ;AAC1B,UAAM,UAAU,UAAU,OAAO,SAAS,IAAIA,OAAM,MAAM,YAAY,IAAI;AAC1E,YAAQ,IAAI,YAAO,KAAK,GAAG,OAAO,EAAE;AAAA,EACtC;AACF,CAAC;AAMH,IAAM,UAAU,QACb,QAAQ,MAAM,EACd,YAAY,qCAAqC;AAEpD,QACG,QAAQ,SAAS,EACjB,YAAY,yCAAyC,EACrD,OAAO,MAAM;AACZ,QAAM,SAAS,gBAAgB,QAAQ;AACvC,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,WAAW,EACnB,YAAY,wCAAwC,EACpD,OAAO,MAAM;AACZ,QAAM,SAAS,gBAAgB,UAAU;AACzC,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,+BAA+B,EAC3C,OAAO,MAAM;AACZ,QAAM,SAAS,gBAAgB,UAAU;AACzC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,gCAAgC,CAAC;AACxD,UAAQ,IAAI;AACZ,UAAQ,IAAI,kBAAkB,OAAO,kBAAkBA,OAAM,MAAM,WAAW,IAAIA,OAAM,OAAO,WAAW,CAAC,EAAE;AAC7G,UAAQ,IAAI,qBAAqB,OAAO,iBAAiBA,OAAM,MAAM,QAAQ,IAAIA,OAAM,IAAI,eAAe,CAAC,EAAE;AAC7G,UAAQ,IAAI,0BAA0B,OAAO,oBAAoBA,OAAM,MAAM,QAAQ,IAAIA,OAAM,IAAI,eAAe,CAAC,EAAE;AACrH,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,YAAQ,IAAI,mBAAmB,OAAO,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1D;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,mBAAmB,EAC3B,YAAY,kEAAkE,EAC9E,OAAO,MAAM;AACZ,QAAM,SAAS,gBAAgB,gBAAgB;AAC/C,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,qBAAqB,EAC7B,YAAY,iCAAiC,EAC7C,OAAO,MAAM;AACZ,QAAM,SAAS,gBAAgB,kBAAkB;AACjD,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAMH,IAAM,aAAa,QAChB,QAAQ,SAAS,EACjB,MAAM,UAAU,EAChB,YAAY,qCAAqC;AAEpD,WACG,QAAQ,SAAS,EACjB,YAAY,qCAAqC,EACjD,OAAO,MAAM;AACZ,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,WACG,QAAQ,WAAW,EACnB,YAAY,oCAAoC,EAChD,OAAO,MAAM;AACZ,QAAM,SAAS,aAAa,UAAU;AACtC,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,WACG,QAAQ,QAAQ,EAChB,YAAY,kCAAkC,EAC9C,OAAO,YAAY;AAClB,QAAM,SAAS,aAAa,UAAU;AACtC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,4BAA4B,CAAC;AACpD,UAAQ,IAAI;AAGZ,MAAI,OAAO,kBAAkB;AAC3B,YAAQ,IAAI,oBAAoBA,OAAM,MAAM,WAAW,CAAC,EAAE;AAAA,EAC5D,WAAW,OAAO,mBAAmB;AACnC,YAAQ,IAAI,oBAAoBA,OAAM,MAAM,WAAW,CAAC,IAAIA,OAAM,IAAI,UAAU,CAAC,EAAE;AAAA,EACrF,OAAO;AACL,YAAQ,IAAI,oBAAoBA,OAAM,OAAO,WAAW,CAAC,EAAE;AAAA,EAC7D;AAGA,MAAI,OAAO,YAAY;AACrB,YAAQ,IAAI,oBAAoBA,OAAM,MAAM,OAAO,UAAU,CAAC,EAAE;AAAA,EAClE,OAAO;AACL,YAAQ,IAAI,oBAAoBA,OAAM,IAAI,WAAW,CAAC,EAAE;AAAA,EAC1D;AAGA,UAAQ,IAAI,qBAAqB,OAAO,iBAAiBA,OAAM,MAAM,QAAQ,IAAIA,OAAM,IAAI,eAAe,CAAC,EAAE;AAC7G,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,YAAQ,IAAI,oBAAoB,OAAO,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,EAC3D;AAGA,MAAI,OAAO,aAAa;AACtB,UAAM,eAAe,OAAO,gBAAgB,WAAWA,OAAM,QAAQA,OAAM;AAC3E,YAAQ,IAAI,oBAAoB,aAAa,OAAO,WAAW,CAAC,EAAE;AAAA,EACpE;AAEA,UAAQ,IAAI;AACd,CAAC;AAEH,WACG,QAAQ,SAAS,EACjB,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,wBAAwB,CAAC;AAChD,UAAQ,IAAI;AAEZ,QAAM,gBAAgB,MAAM,aAAa,iBAAiB;AAE1D,MAAI,cAAc,SAAS;AACzB,YAAQ,IAAI,iBAAiBA,OAAM,MAAM,SAAS,CAAC,EAAE;AACrD,YAAQ,IAAI,iBAAiB,cAAc,IAAI,EAAE;AACjD,YAAQ,IAAI,iBAAiB,cAAc,IAAI,EAAE;AACjD,YAAQ,IAAI,iBAAiB,cAAc,cAAcA,OAAM,MAAM,SAAS,IAAIA,OAAM,OAAO,UAAU,CAAC,EAAE;AAAA,EAC9G,OAAO;AACL,YAAQ,IAAI,iBAAiBA,OAAM,OAAO,aAAa,CAAC,EAAE;AAC1D,YAAQ,IAAI,iBAAiB,cAAc,IAAI,IAAI,cAAc,IAAI,EAAE;AACvE,QAAI,cAAc,OAAO;AACvB,cAAQ,IAAI,iBAAiBA,OAAM,IAAI,cAAc,KAAK,CAAC,EAAE;AAAA,IAC/D;AAAA,EACF;AAEA,UAAQ,IAAI;AACd,CAAC;AAEH,WACG,QAAQ,OAAO,EACf,YAAY,4BAA4B,EACxC,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,YAAY;AACzB,UAAQ,IAAIA,OAAM,IAAI,6BAA6B,CAAC;AAEpD,QAAM,SAAS,MAAM,aAAa,iBAAiB;AAEnD,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAGA,QAAM,aAAa,OAAO,SAASA,OAAM,MAAM,QAAG,IAAIA,OAAM,IAAI,QAAG;AACnE,QAAM,aAAa,OAAO,SAASA,OAAM,MAAM,QAAQ,IAAIA,OAAM,IAAI,QAAQ;AAE7E,UAAQ,IAAI,GAAG,UAAU,oBAAoB,UAAU,EAAE;AACzD,UAAQ,IAAI;AAEZ,MAAI,OAAO,SAAS,WAAW,GAAG;AAChC,YAAQ,IAAIA,OAAM,IAAI,gBAAgB,CAAC;AAAA,EACzC,OAAO;AACL,UAAM,iBAAwD;AAAA,MAC5D,UAAUA,OAAM,MAAM;AAAA,MACtB,SAASA,OAAM;AAAA,MACf,MAAMA,OAAM;AAAA,IACd;AAEA,eAAW,WAAW,OAAO,UAAU;AACrC,YAAM,QAAQ,eAAe,QAAQ,QAAQ,KAAKA,OAAM;AACxD,cAAQ,IAAI,KAAK,MAAM,IAAI,QAAQ,SAAS,YAAY,CAAC,GAAG,CAAC,IAAI,QAAQ,OAAO,EAAE;AAClF,cAAQ,IAAIA,OAAM,IAAI,iBAAiB,QAAQ,QAAQ,EAAE,CAAC;AAC1D,UAAI,QAAQ,gBAAgB;AAC1B,gBAAQ,IAAIA,OAAM,IAAI,YAAY,QAAQ,cAAc,EAAE,CAAC;AAAA,MAC7D;AACA,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,IAAI,sBAAsB,OAAO,UAAU,eAAe,CAAC,EAAE,CAAC;AAChF,UAAQ,IAAI;AACd,CAAC;AAMH,QACG,QAAQ,oBAAoB,EAC5B,YAAY,oEAAoE,EAChF,OAAO,aAAa,qCAAqC,EACzD,OAAO,OAAO,OAAO,YAAY;AAChC,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAE5B,MAAI,OAAO;AAET,UAAM,cAAc,CAAC,eAAe,WAAW,YAAY,SAAS,cAAc,UAAU;AAC5F,QAAI,CAAC,YAAY,SAAS,KAAK,GAAG;AAChC,cAAQ,IAAIA,OAAM,IAAI,kBAAkB,KAAK,EAAE,CAAC;AAChD,cAAQ,IAAIA,OAAM,IAAI,iBAAiB,YAAY,KAAK,IAAI,CAAC,EAAE,CAAC;AAChE;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,mBAAmB,KAAY;AAClD,UAAM,EAAE,iBAAAE,iBAAgB,IAAI,MAAM,OAAO,uBAA2B;AACpE,YAAQ,IAAI;AACZ,YAAQ,IAAIA,iBAAgB,IAAI,CAAC;AAGjC,QAAI,QAAQ,OAAO,KAAK,gBAAgB,KAAK,YAAY;AACvD,YAAM,EAAE,kBAAAC,kBAAiB,IAAI,MAAM,OAAO,6BAAiC;AAC3E,YAAM,SAAS,MAAMA,kBAAiB,OAAc,KAAK,UAAU;AACnE,UAAI,QAAQ,aAAa;AACvB,gBAAQ,IAAI;AACZ,gBAAQ,IAAIH,OAAM,KAAK,0CAA0C,CAAC;AAClE,gBAAQ,IAAI,qBAAqB,OAAO,WAAW,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,SAAS,MAAM,mBAAmB;AACxC,YAAQ,IAAI;AACZ,YAAQ,IAAI,oBAAoB,MAAM,CAAC;AAAA,EACzC;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,aAAa,EACrB,YAAY,2DAA2D,EACvE,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAE5B,QAAM,SAAS,MAAM,mBAAmB;AACxC,QAAM,YAAY,OAAO,OAAO,OAAK,EAAE,SAAS;AAEhD,MAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ,IAAIA,OAAM,OAAO,kDAAkD,CAAC;AAC5E,YAAQ,IAAIA,OAAM,IAAI,qEAAqE,CAAC;AAC5F;AAAA,EACF;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAI,uBAAuB,MAAM,CAAC;AAC1C,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,gBAAgB,EACxB,YAAY,sDAAsD,EAClE,OAAO,aAAa,mCAAmC,EACvD,OAAO,OAAO,SAAS,YAAY;AAClC,QAAM,SAAS,MAAM,YAAY,OAAO;AAExC,MAAI,CAAC,OAAO,SAAS;AAEnB,QAAI,QAAQ,MAAM,SAAS,CAAC,QAAQ,KAAK;AACvC,YAAM,EAAE,iBAAAI,iBAAgB,IAAI,MAAM,OAAO,uBAAc;AACvD,YAAM,EAAE,cAAAC,eAAc,eAAAJ,eAAc,IAAI,MAAM,OAAO,IAAI;AACzD,YAAM,EAAE,OAAAK,QAAO,WAAAC,WAAU,IAAI,MAAM,OAAO,MAAM;AAChD,YAAM,EAAE,YAAAC,YAAW,IAAI,MAAM,OAAO,sBAAa;AAEjD,cAAQ,MAAM;AACd,cAAQ,MAAMR,OAAM,IAAI,6CAAiC,CAAC;AAC1D,cAAQ,MAAM;AACd,cAAQ,MAAMA,OAAM,IAAI,YAAY,GAAG,OAAO;AAC9C,cAAQ,MAAMA,OAAM,IAAI,WAAW,GAAG,OAAO,MAAM;AACnD,cAAQ,MAAM;AACd,cAAQ,MAAMA,OAAM,OAAO,uBAAuB,CAAC;AACnD,cAAQ,MAAMA,OAAM,KAAK,SAAS,GAAG,YAAY;AACjD,cAAQ,MAAMA,OAAM,KAAK,SAAS,GAAG,mBAAmB;AACxD,cAAQ,MAAMA,OAAM,KAAK,SAAS,GAAG,mBAAmB;AACxD,cAAQ,MAAMA,OAAM,KAAK,SAAS,GAAG,iBAAiB;AACtD,cAAQ,OAAO,MAAMA,OAAM,IAAI,cAAc,CAAC;AAG9C,YAAM,SAAS,MAAM,IAAI,QAAgB,CAAC,YAAY;AACpD,YAAI,QAAQ,MAAM,OAAO;AACvB,kBAAQ,MAAM,WAAW,IAAI;AAAA,QAC/B;AACA,gBAAQ,MAAM,OAAO;AACrB,gBAAQ,MAAM,KAAK,QAAQ,CAAC,SAAS;AACnC,cAAI,QAAQ,MAAM,OAAO;AACvB,oBAAQ,MAAM,WAAW,KAAK;AAAA,UAChC;AACA,gBAAM,OAAO,KAAK,SAAS,EAAE,YAAY;AACzC,kBAAQ,MAAM,IAAI;AAClB,kBAAQ,IAAI;AAAA,QACd,CAAC;AAAA,MACH,CAAC;AAED,cAAQ,QAAQ;AAAA,QACd,KAAK;AACH,kBAAQ,MAAMA,OAAM,MAAM,uBAAkB,CAAC;AAC7C,kBAAQ,KAAK,CAAC;AACd;AAAA,QAEF,KAAK;AACH,UAAAI,iBAAgB,OAAO;AACvB,kBAAQ,MAAMJ,OAAM,MAAM,8BAAyB,CAAC;AACpD,kBAAQ,KAAK,CAAC;AACd;AAAA,QAEF,KAAK;AACH,cAAI;AACF,kBAAM,aAAaQ,YAAW;AAC9B,gBAAI,YAAY;AACd,oBAAM,UAAUH,cAAa,YAAY,OAAO;AAChD,oBAAM,SAASC,OAAM,OAAO;AAC5B,kBAAI,CAAC,OAAO,SAAU,QAAO,WAAW,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAC/D,kBAAI,CAAC,OAAO,SAAS,MAAO,QAAO,SAAS,QAAQ,CAAC;AACrD,kBAAI,CAAC,OAAO,SAAS,MAAM,SAAS,OAAO,GAAG;AAC5C,uBAAO,SAAS,MAAM,KAAK,OAAO;AAClC,gBAAAL,eAAc,YAAYM,WAAU,MAAM,CAAC;AAAA,cAC7C;AACA,sBAAQ,MAAMP,OAAM,MAAM,yCAAoC,CAAC;AAC/D,sBAAQ,KAAK,CAAC;AAAA,YAChB;AAAA,UACF,QAAQ;AACN,oBAAQ,MAAMA,OAAM,IAAI,kCAA6B,CAAC;AAAA,UACxD;AACA,kBAAQ,KAAK,CAAC;AACd;AAAA,QAEF;AACE,kBAAQ,MAAMA,OAAM,OAAO,kBAAa,CAAC;AACzC,kBAAQ,KAAK,CAAC;AAAA,MAClB;AAAA,IACF,OAAO;AAEL,cAAQ,MAAM,YAAY,OAAO,MAAM,EAAE;AACzC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,UAAQ,KAAK,CAAC;AAChB,CAAC;AAEH,QACG,QAAQ,aAAa,EACrB,YAAY,qDAAqD,EACjE,OAAO,qBAAqB,gDAAgD,EAC5E,OAAO,YAAY;AAElB,QAAM,YAAY,QAAQ,IAAI,qBAAqB;AAEnD,MAAI,CAAC,WAAW;AAEd;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,UAAM,SAAS,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAEpD,UAAM,EAAE,iBAAAS,iBAAgB,IAAI,MAAM,OAAO,sBAAuB;AAChE,UAAM,SAAS,IAAIA,iBAAgB;AAEnC,eAAW,OAAO,QAAQ;AACxB,YAAM,WAAW,IAAI,aAAa,IAAI,QAAQ;AAC9C,YAAM,YAAY,IAAI,cAAc,IAAI,SAAS,CAAC;AAClD,YAAM,aAAa,IAAI,eAAe,IAAI,UAAU;AAGpD,UAAI;AACJ,UAAI,OAAO,cAAc,UAAU;AACjC,mBAAW;AAAA,MACb,WAAW,OAAO,cAAc,UAAU;AACxC,mBAAW,KAAK,UAAU,WAAW,MAAM,CAAC;AAAA,MAC9C,OAAO;AACL,mBAAW,OAAO,SAAS;AAAA,MAC7B;AAGA,UAAI;AACJ,UAAI,WAA0B;AAC9B,UAAI,UAA0B;AAE9B,UAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,qBAAa,WAAW,UAAU,OAAO,WAAW,UAAU;AAC9D,mBAAW,WAAW,aAAa,WAAW,YAAY;AAC1D,YAAI,aAAa,MAAM;AACrB,oBAAU,aAAa;AAAA,QACzB;AAAA,MACF,OAAO;AACL,oBAAY,OAAO,cAAc,EAAE;AAAA,MACrC;AAGA,YAAM,WAAW,IAAI,MAAM,QAAQ;AACnC,YAAM,WAAW,IAAI,MAAM,QAAQ;AAEnC,aAAO,cAAc;AAAA,QACnB;AAAA,QACA,WAAW;AAAA,QACX,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,KAAK,IAAI,OAAO,QAAQ,IAAI;AAAA,QAC5B;AAAA,QACA;AAAA,MACF,CAAC;AAGD,YAAM,UAAU,SAAS,UAAU,GAAG,EAAE,EAAE,QAAQ,OAAO,GAAG;AAC5D,cAAQ,IAAI,cAAc,QAAQ,KAAK,OAAO,GAAG,SAAS,SAAS,KAAK,QAAQ,EAAE,EAAE;AAAA,IACtF;AAEA,WAAO,MAAM;AAAA,EACf,SAAS,GAAG;AAEV,YAAQ,MAAM,oCAAoC,aAAa,QAAQ,EAAE,UAAU,CAAC,EAAE;AAAA,EACxF;AACF,CAAC;AAEH,QACG,QAAQ,kBAAkB,EAC1B,YAAY,4CAA4C,EACxD,OAAO,yBAAyB,gBAAgB,EAChD,OAAO,0BAA0B,aAAa,GAAG,EACjD,OAAO,OAAO,SAAS,YAAY;AAElC,MAAI,CAAC,iBAAkB,oBAAmB,IAAI,iBAAiB;AAC/D,MAAI,CAAC,cAAe,iBAAgB,IAAI,cAAc;AACtD,MAAI,CAAC,aAAc,gBAAe,IAAI,aAAa;AACnD,MAAI,CAAC,UAAW,aAAY,IAAI,UAAU;AAE1C,QAAM,SAAS,IAAI,WAAW;AAC9B,QAAM,OAAO,OAAO,MAAM,OAAO;AAGjC,mBAAiB,OAAO;AAAA,IACtB;AAAA,IACA,WAAW,oBAAI,KAAK;AAAA,IACpB,UAAU;AAAA;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY,CAAC;AAAA,IACb,UAAU,SAAS,QAAQ,QAAQ,KAAK;AAAA,EAC1C,CAAC;AAGD,gBAAc,eAAe,SAAS,QAAQ,UAAU,EAAE;AAG1D,QAAM,YAAY,aAAa,MAAM,OAAO;AAC5C,MAAI,WAAW;AACb,YAAQ,MAAMT,OAAM,OAAO,yBAAoB,UAAU,OAAO,EAAE,CAAC;AAAA,EACrE;AAGA,QAAM,QAAQ,QAAQ,MAAM,qCAAqC,KAAK,CAAC;AACvE,QAAM,aAAa,MAAM,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC;AACpD,MAAI,WAAW,SAAS,GAAG;AACzB,cAAU,kBAAkB,SAAS,UAAU;AAAA,EACjD;AACF,CAAC;AAEH,QACG,QAAQ,aAAa,EACrB,YAAY,yCAAyC,EACrD,OAAO,yBAAyB,wCAAwC,MAAM,EAC9E,OAAO,CAAC,YAAY;AACnB,MAAI,CAAC,kBAAkB;AACrB,YAAQ,IAAIA,OAAM,IAAI,4BAA4B,CAAC;AACnD;AAAA,EACF;AAEA,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,OAAO,eAAe,YAAY;AACxC,QAAM,SAAS,gBAAgB,SAAS,SAAS,MAAM,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAEjF,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM;AAClB,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,2BAA2B,EACvC,OAAO,yBAAyB,wCAAwC,MAAM,EAC9E,OAAO,aAAa,oBAAoB,EACxC,OAAO,aAAa,wBAAwB,EAC5C,OAAO,CAAC,YAAY;AACnB,MAAI,CAAC,kBAAkB;AACrB,YAAQ,IAAIA,OAAM,IAAI,2CAA2C,CAAC;AAClE;AAAA,EACF;AAEA,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,OAAO,QAAQ,OAAO,eAAe,YAAY,IAAI;AAC3D,QAAM,SAAS,gBAAgB,SAAS,SAAS,MAAM;AAAA,IACrD,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,EACpB,CAAC;AAED,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM;AAClB,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,gBAAgB,EACxB,YAAY,mCAAmC,EAC/C,OAAO,CAAC,YAAY;AACnB,QAAM,SAAS,IAAI,WAAW;AAC9B,QAAM,SAAS,OAAO,MAAM,OAAO;AAEnC,QAAM,SAAgD;AAAA,IACpD,MAAMA,OAAM;AAAA,IACZ,SAASA,OAAM;AAAA,IACf,WAAWA,OAAM;AAAA,IACjB,UAAUA,OAAM,MAAM;AAAA,EACxB;AAEA,QAAM,QAAQ,OAAO,OAAO,KAAK;AAEjC,UAAQ,IAAI;AACZ,UAAQ,IAAI,iBAAiB,MAAM,GAAG,OAAO,KAAK,KAAK,CAAC,KAAK,MAAM,OAAO,MAAM,YAAY,CAAC,CAAC,GAAG;AACjG,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,YAAY,CAAC;AACpC,aAAW,UAAU,OAAO,SAAS;AACnC,YAAQ,IAAI,cAAS,MAAM,EAAE;AAAA,EAC/B;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,IAAM,UAAU,QACb,QAAQ,MAAM,EACd,YAAY,sBAAsB;AAErC,QACG,QAAQ,MAAM,EACd,MAAM,KAAK,EACX,YAAY,8BAA8B,EAC1C,OAAO,MAAM;AACZ,MAAI,CAAC,WAAW;AACd,YAAQ,IAAIA,OAAM,IAAI,wBAAwB,CAAC;AAC/C;AAAA,EACF;AAEA,QAAM,SAAS,UAAU,KAAK;AAC9B,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAAA,EAC9C,OAAO;AACL,YAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAAA,EAC5C;AACF,CAAC;AAEH,QACG,QAAQ,KAAK,EACb,YAAY,qCAAqC,EACjD,OAAO,MAAM;AACZ,MAAI,CAAC,aAAa,UAAU,KAAK,MAAM,GAAG;AACxC,YAAQ,IAAIA,OAAM,IAAI,wBAAwB,CAAC;AAC/C;AAAA,EACF;AAEA,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,UAAU,GAAG,SAAS;AAE1B,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS;AAClB,cAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,OAAO,OAAO;AAC5C;AAAA,IACF,OAAO;AACL,cAAQ,IAAIA,OAAM,IAAI,QAAG,GAAG,OAAO,OAAO;AAC1C;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAI,WAAW,OAAO,gBAAgB,MAAM,SAAS;AAC/D,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,iBAAiB,EAC7B,OAAO,MAAM;AACZ,MAAI,CAAC,WAAW;AACd,gBAAY,IAAI,UAAU;AAAA,EAC5B;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAI,UAAU,YAAY,CAAC;AACnC,UAAQ,IAAI;AACd,CAAC;AAMH,IAAI,kBAA0C;AAE9C,QACG,QAAQ,WAAW,EACnB,YAAY,8BAA8B,EAC1C,OAAO,qBAAqB,kBAAkB,MAAM,EACpD,OAAO,wBAAwB,sBAAsB,WAAW,EAChE,OAAO,OAAO,YAAY;AACzB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,UAAQ,IAAIA,OAAM,IAAI,2BAA2B,CAAC;AAElD,oBAAkB,IAAI,gBAAgB;AAAA,IACpC,MAAM,SAAS,QAAQ,IAAI;AAAA,IAC3B,MAAM,QAAQ;AAAA,EAChB,CAAC;AAED,QAAM,gBAAgB,MAAM;AAC5B,UAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,+BAA+B,QAAQ,IAAI,IAAI,QAAQ,IAAI,EAAE;AAC3F,UAAQ,IAAIA,OAAM,IAAI,wBAAwB,CAAC;AAG/C,UAAQ,GAAG,UAAU,YAAY;AAC/B,YAAQ,IAAIA,OAAM,IAAI,2BAA2B,CAAC;AAClD,UAAM,iBAAiB,KAAK;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH,CAAC;AAMH,IAAM,UAAU,QACb,QAAQ,MAAM,EACd,YAAY,gCAAgC;AAE/C,QACG,QAAQ,QAAQ,EAChB,YAAY,2BAA2B,EACvC,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,UAAQ,IAAIA,OAAM,KAAK,wBAAwB,CAAC;AAEhD,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,mCAAmC;AAAA,EACnE,OAAO;AACL,YAAQ,IAAIA,OAAM,OAAO,QAAG,GAAG,SAAS,QAAQ,MAAM;AAAA,CAAiB;AACvE,eAAW,KAAK,SAAS;AACvB,YAAM,QAAQ,EAAE,aAAa,aAAaA,OAAM,MAAM,QACxC,EAAE,aAAa,SAASA,OAAM,MAC9B,EAAE,aAAa,WAAWA,OAAM,SAChCA,OAAM;AACpB,cAAQ,IAAI,KAAK,MAAM,EAAE,SAAS,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,IAC3E;AAAA,EACF;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,mBAAmB,EAC/B,OAAO,YAAY;AAClB,UAAQ,IAAIA,OAAM,KAAK,IAAI,CAAC;AAC5B,UAAQ,IAAIA,OAAM,IAAI,2CAA2C,CAAC;AAElE,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,mCAAmC;AAAA,EACnE,OAAO;AACL,eAAW,KAAK,SAAS;AACvB,YAAM,OAAO,EAAE,aAAa,aAAa,cAC5B,EAAE,aAAa,SAAS,iBACxB,EAAE,aAAa,WAAW,WAAM;AAE7C,cAAQ,IAAI,GAAG,IAAI,IAAI,EAAE,KAAK,EAAE;AAChC,cAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,IAAI,EAAE,CAAC;AAC3C,cAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,WAAW,EAAE,CAAC;AAClD,cAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,OAAO,EAAE,CAAC;AAC9C,cAAQ,IAAIA,OAAM,IAAI,gBAAgB,EAAE,QAAQ,EAAE,CAAC;AACnD,cAAQ,IAAIA,OAAM,IAAI,cAAc,EAAE,MAAM,EAAE,CAAC;AAC/C,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AACF,CAAC;AAEH,IAAM,cAAc,QACjB,QAAQ,UAAU,EAClB,YAAY,2BAA2B;AAE1C,YACG,QAAQ,MAAM,EACd,YAAY,uBAAuB,EACnC,OAAO,MAAM;AACZ,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,SAAS,QAAQ,UAAU;AAEjC,UAAQ,IAAIA,OAAM,KAAK,iCAAiC,CAAC;AACzD,aAAW,SAAS,QAAQ;AAC1B,YAAQ,IAAI,KAAKA,OAAM,KAAK,MAAM,IAAI,CAAC,EAAE;AACzC,YAAQ,IAAIA,OAAM,IAAI,kBAAkB,MAAM,aAAa,KAAK,IAAI,CAAC,EAAE,CAAC;AACxE,YAAQ,IAAIA,OAAM,IAAI,cAAc,MAAM,aAAa,KAAK,IAAI,CAAC,EAAE,CAAC;AACpE,YAAQ,IAAI;AAAA,EACd;AACF,CAAC;AAEH,YACG,QAAQ,MAAM,EACd,YAAY,6BAA6B,EACzC,OAAO,YAAY;AAClB,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,UAAQ,IAAIA,OAAM,KAAK,4BAA4B,CAAC;AAEpD,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIA,OAAM,MAAM,gCAA2B,CAAC;AAAA,EACtD,OAAO;AACL,eAAW,KAAK,SAAS;AACvB,YAAM,QAAQ,EAAE,aAAa,aAAaA,OAAM,MAAM,QACxC,EAAE,aAAa,SAASA,OAAM,MAC9B,EAAE,aAAa,WAAWA,OAAM,SAASA,OAAM;AAC7D,cAAQ,IAAI,KAAK,MAAM,EAAE,SAAS,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,IAC5E;AAAA,EACF;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,mCAAmC,EAC/C,OAAO,MAAM;AACZ,QAAM,UAAU,IAAI,cAAc;AAClC,QAAM,UAAU,QAAQ,iBAAiB;AAEzC,UAAQ,IAAIA,OAAM,KAAK,4BAA4B,CAAC;AAEpD,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIA,OAAM,IAAI,qBAAqB,CAAC;AAAA,EAC9C,OAAO;AACL,eAAW,SAAS,SAAS;AAC3B,YAAM,gBAAgB,MAAM,QAAQ,aAAa,aAAaA,OAAM,MAAM,QACpD,MAAM,QAAQ,aAAa,SAASA,OAAM,MAC1C,MAAM,QAAQ,aAAa,WAAWA,OAAM,SAASA,OAAM;AACjF,cAAQ,IAAI,KAAKA,OAAM,KAAK,MAAM,EAAE,CAAC,IAAI,cAAc,MAAM,QAAQ,SAAS,YAAY,CAAC,CAAC,EAAE;AAC9F,cAAQ,IAAIA,OAAM,IAAI,gBAAgB,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,QAAQ,GAAG,CAAC;AACvF,cAAQ,IAAIA,OAAM,IAAI,gBAAgB,MAAM,YAAY,UAAU,GAAG,EAAE,CAAC,GAAG,MAAM,YAAY,SAAS,KAAK,QAAQ,EAAE,EAAE,CAAC;AACxH,UAAI,MAAM,UAAW,SAAQ,IAAIA,OAAM,IAAI,kBAAkB,MAAM,SAAS,EAAE,CAAC;AAC/E,UAAI,MAAM,YAAa,SAAQ,IAAIA,OAAM,IAAI,oBAAoB,MAAM,WAAW,EAAE,CAAC;AACrF,cAAQ,IAAI;AAAA,IACd;AACA,YAAQ,IAAIA,OAAM,IAAI,4EAA4E,CAAC;AAAA,EACrG;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,eAAe,oBAAoB,MAAM,EAChD,OAAO,CAAC,IAAI,YAAY;AACvB,QAAM,UAAU,IAAI,cAAc;AAClC,UAAQ,aAAa,IAAI,QAAQ,EAAE;AACnC,UAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,kBAAkB,EAAE,EAAE;AACtD,CAAC;AAEH,QACG,QAAQ,WAAW,EACnB,YAAY,4BAA4B,EACxC,OAAO,CAAC,OAAO;AACd,QAAM,UAAU,IAAI,cAAc;AAClC,UAAQ,UAAU,EAAE;AACpB,UAAQ,IAAIA,OAAM,MAAM,QAAG,GAAG,gBAAgB,EAAE,EAAE;AACpD,CAAC;AAEH,IAAM,cAAc,QACjB,QAAQ,UAAU,EAClB,YAAY,mCAAmC;AAElD,YACG,QAAQ,MAAM,EACd,YAAY,gCAAgC,EAC5C,OAAO,oBAAoB,uCAAuC,EAClE,OAAO,CAAC,YAAY;AACnB,QAAM,UAAU,IAAI,qBAAqB;AACzC,MAAI,WAAW,QAAQ,YAAY;AAEnC,MAAI,QAAQ,UAAU;AACpB,eAAW,SAAS,OAAO,OAAK,EAAE,aAAa,QAAQ,QAAQ;AAAA,EACjE;AAEA,UAAQ,IAAIA,OAAM,KAAK,6BAA6B,CAAC;AAErD,QAAM,aAA8C,CAAC;AACrD,aAAW,KAAK,UAAU;AACxB,UAAM,MAAM,EAAE;AACd,QAAI,CAAC,WAAW,GAAG,EAAG,YAAW,GAAG,IAAI,CAAC;AACzC,eAAW,GAAG,EAAE,KAAK,CAAC;AAAA,EACxB;AAEA,aAAW,CAAC,UAAU,gBAAgB,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrE,YAAQ,IAAIA,OAAM,KAAK,KAAK,SAAS,YAAY,CAAC,EAAE,CAAC;AACrD,eAAW,KAAK,kBAAkB;AAChC,YAAM,gBAAgB,EAAE,aAAa,aAAaA,OAAM,MAClC,EAAE,aAAa,SAASA,OAAM,SAC9B,EAAE,aAAa,WAAWA,OAAM,OAAOA,OAAM;AACnE,YAAM,cAAc,EAAE,WAAW,UAAUA,OAAM,MAC9B,EAAE,WAAW,UAAUA,OAAM,SAASA,OAAM;AAC/D,cAAQ,IAAI,OAAOA,OAAM,KAAK,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,cAAc,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE;AAAA,IAChJ;AACA,YAAQ,IAAI;AAAA,EACd;AACF,CAAC;AAEH,YACG,QAAQ,aAAa,EACrB,YAAY,4CAA4C,EACxD,OAAO,CAAC,SAAS;AAChB,QAAM,UAAU,IAAI,cAAc;AAClC,QAAM,SAAS,QAAQ,KAAK,IAAI;AAEhC,UAAQ,IAAIA,OAAM,KAAK,2BAA2B,CAAC;AAEnD,MAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B,YAAQ,IAAIA,OAAM,MAAM,8BAAyB,CAAC;AAAA,EACpD,OAAO;AACL,YAAQ,IAAI,KAAK,OAAO,UAAUA,OAAM,IAAI,aAAa,IAAIA,OAAM,OAAO,aAAa,CAAC,EAAE;AAC1F,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,KAAK,YAAY,CAAC;AACpC,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,gBAAgB,EAAE,QAAQ,aAAa,aAAaA,OAAM,MAC1C,EAAE,QAAQ,aAAa,SAASA,OAAM,SACtC,EAAE,QAAQ,aAAa,WAAWA,OAAM,OAAOA,OAAM;AAC3E,cAAQ,IAAI,OAAOA,OAAM,KAAK,EAAE,QAAQ,IAAI,CAAC,IAAI,cAAc,IAAI,EAAE,QAAQ,QAAQ,GAAG,CAAC,OAAO,EAAE,YAAY,UAAU,GAAG,EAAE,CAAC,GAAG,EAAE,YAAY,SAAS,KAAK,QAAQ,EAAE,GAAG;AAAA,IAC5K;AACA,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,KAAK,oBAAoB,CAAC;AAC5C,YAAQ,IAAIA,OAAM,IAAI,OAAO,OAAO,SAAS,UAAU,GAAG,GAAG,CAAC,GAAG,OAAO,SAAS,SAAS,MAAM,QAAQ,EAAE,EAAE,CAAC;AAAA,EAC/G;AACA,UAAQ,IAAI;AACd,CAAC;AAEH,QAAQ,MAAM;","names":["chalk","chalk","existsSync","join","homedir","existsSync","join","homedir","join","homedir","existsSync","MoltbotHooks","existsSync","platform","DashboardDB","MoltbotHooks","chalk","join","homedir","existsSync","chalk","readFileSync","writeFileSync","stringify","chalk","readFileSync","config","writeFileSync","stringify","chalk","readFileSync","writeFileSync","parse","stringify","chalk","readFileSync","parse","writeFileSync","stringify","join","homedir","readFileSync","writeFileSync","existsSync","mkdirSync","parse","stringify","join","homedir","existsSync","mkdirSync","writeFileSync","readFileSync","parse","stringify","chalk","writeFileSync","formatAgentInfo","parseAgentConfig","allowForSession","readFileSync","parse","stringify","findConfig","DashboardWriter"]}