@wispbit/local 1.0.25
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/build.d.ts +3 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/cli.js +3668 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.js +3868 -0
- package/dist/index.js.map +7 -0
- package/dist/package.json +72 -0
- package/dist/src/cli.d.ts +16 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/config.d.ts +6 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/environment/Config.d.ts +69 -0
- package/dist/src/environment/Config.d.ts.map +1 -0
- package/dist/src/environment/Environment.d.ts +23 -0
- package/dist/src/environment/Environment.d.ts.map +1 -0
- package/dist/src/environment/Sandbox.d.ts +48 -0
- package/dist/src/environment/Sandbox.d.ts.map +1 -0
- package/dist/src/environment/Storage.d.ts +84 -0
- package/dist/src/environment/Storage.d.ts.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/languages.d.ts +36 -0
- package/dist/src/languages.d.ts.map +1 -0
- package/dist/src/providers/AstGrepAstProvider.d.ts +44 -0
- package/dist/src/providers/AstGrepAstProvider.d.ts.map +1 -0
- package/dist/src/providers/LanguageBackend.d.ts +74 -0
- package/dist/src/providers/LanguageBackend.d.ts.map +1 -0
- package/dist/src/providers/RuleProvider.d.ts +46 -0
- package/dist/src/providers/RuleProvider.d.ts.map +1 -0
- package/dist/src/providers/ScipIntelligenceProvider.d.ts +84 -0
- package/dist/src/providers/ScipIntelligenceProvider.d.ts.map +1 -0
- package/dist/src/providers/ViolationValidationProvider.d.ts +42 -0
- package/dist/src/providers/ViolationValidationProvider.d.ts.map +1 -0
- package/dist/src/providers/WispbitRuleProvider.d.ts +45 -0
- package/dist/src/providers/WispbitRuleProvider.d.ts.map +1 -0
- package/dist/src/providers/WispbitViolationValidationProvider.d.ts +15 -0
- package/dist/src/providers/WispbitViolationValidationProvider.d.ts.map +1 -0
- package/dist/src/schemas.d.ts +1771 -0
- package/dist/src/schemas.d.ts.map +1 -0
- package/dist/src/steps/ExecutionEventEmitter.d.ts +156 -0
- package/dist/src/steps/ExecutionEventEmitter.d.ts.map +1 -0
- package/dist/src/steps/FileExecutionContext.d.ts +85 -0
- package/dist/src/steps/FileExecutionContext.d.ts.map +1 -0
- package/dist/src/steps/FileFilterStep.d.ts +35 -0
- package/dist/src/steps/FileFilterStep.d.ts.map +1 -0
- package/dist/src/steps/FileFilterStep.test.d.ts +2 -0
- package/dist/src/steps/FileFilterStep.test.d.ts.map +1 -0
- package/dist/src/steps/FindMatchesStep.d.ts +41 -0
- package/dist/src/steps/FindMatchesStep.d.ts.map +1 -0
- package/dist/src/steps/FindMatchesStep.test.d.ts +2 -0
- package/dist/src/steps/FindMatchesStep.test.d.ts.map +1 -0
- package/dist/src/steps/GotoDefinitionStep.d.ts +86 -0
- package/dist/src/steps/GotoDefinitionStep.d.ts.map +1 -0
- package/dist/src/steps/LLMStep.d.ts +50 -0
- package/dist/src/steps/LLMStep.d.ts.map +1 -0
- package/dist/src/steps/RuleExecutor.d.ts +35 -0
- package/dist/src/steps/RuleExecutor.d.ts.map +1 -0
- package/dist/src/steps/RuleExecutor.test.d.ts +2 -0
- package/dist/src/steps/RuleExecutor.test.d.ts.map +1 -0
- package/dist/src/test/TestExecutor.d.ts +33 -0
- package/dist/src/test/TestExecutor.d.ts.map +1 -0
- package/dist/src/test/rules.test.d.ts +2 -0
- package/dist/src/test/rules.test.d.ts.map +1 -0
- package/dist/src/types.d.ts +200 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils/asciiFrames.d.ts +5 -0
- package/dist/src/utils/asciiFrames.d.ts.map +1 -0
- package/dist/src/utils/formatters.d.ts +55 -0
- package/dist/src/utils/formatters.d.ts.map +1 -0
- package/dist/src/utils/generateTreeDump.d.ts +19 -0
- package/dist/src/utils/generateTreeDump.d.ts.map +1 -0
- package/dist/src/utils/git.d.ts +39 -0
- package/dist/src/utils/git.d.ts.map +1 -0
- package/dist/src/utils/hashString.d.ts +2 -0
- package/dist/src/utils/hashString.d.ts.map +1 -0
- package/dist/src/utils/readTextAtRange.d.ts +10 -0
- package/dist/src/utils/readTextAtRange.d.ts.map +1 -0
- package/dist/src/utils/snapshotComparison.d.ts +16 -0
- package/dist/src/utils/snapshotComparison.d.ts.map +1 -0
- package/dist/src/utils/startupScreen.d.ts +5 -0
- package/dist/src/utils/startupScreen.d.ts.map +1 -0
- package/dist/src/utils/validateRule.d.ts +16 -0
- package/dist/src/utils/validateRule.d.ts.map +1 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/vitest.config.d.mts +3 -0
- package/dist/vitest.config.d.mts.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/version.ts", "../src/environment/Config.ts", "../src/utils/hashString.ts", "../src/utils/git.ts", "../src/environment/Environment.ts", "../src/environment/Storage.ts", "../src/providers/WispbitRuleProvider.ts", "../src/steps/ExecutionEventEmitter.ts", "../src/steps/FileExecutionContext.ts", "../src/steps/FileFilterStep.ts", "../src/languages.ts", "../src/providers/AstGrepAstProvider.ts", "../src/utils/readTextAtRange.ts", "../src/providers/ScipIntelligenceProvider.ts", "../src/providers/LanguageBackend.ts", "../src/steps/FindMatchesStep.ts", "../src/steps/GotoDefinitionStep.ts", "../src/providers/WispbitViolationValidationProvider.ts", "../src/steps/LLMStep.ts", "../src/steps/RuleExecutor.ts", "../src/types.ts", "../src/utils/formatters.ts", "../src/utils/asciiFrames.ts", "../src/utils/startupScreen.ts", "../src/cli.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { readFileSync } from \"fs\"\nimport { dirname, join } from \"path\"\nimport { fileURLToPath } from \"url\"\n\nimport latestVersion from \"latest-version\"\n\nexport function getCurrentVersion(): string {\n const filename = fileURLToPath(import.meta.url ? import.meta.url : __filename)\n const __dirname = dirname(filename)\n\n // Path to package.json relative to this file\n const packageJsonPath = join(__dirname, \"../package.json\")\n try {\n const file = readFileSync(packageJsonPath, \"utf8\")\n const packageJson = JSON.parse(file)\n return packageJson.version\n } catch {\n return \"0.0.0\"\n }\n}\n\nexport async function getLatestVersion(): Promise<string> {\n try {\n const latestCliVersion = await latestVersion(\"@wispbit/local\")\n return latestCliVersion\n } catch {\n return getCurrentVersion()\n }\n}\n", "import { PowerLintConfig } from \"powerlint/config\"\nimport { Environment } from \"powerlint/environment/Environment\"\nimport { getCurrentVersion } from \"powerlint/version\"\n\nexport interface InitializeResult {\n configured: boolean\n invalid_api_key?: boolean\n is_valid_repository?: boolean\n config?: {\n ignored_globs: string[]\n }\n}\n\nexport class Config {\n private config: PowerLintConfig\n private apiKey: string | null = null\n private baseUrl: string | null = null\n\n constructor(config: Partial<PowerLintConfig>) {\n this.config = {\n ...config,\n ignoredGlobs: config.ignoredGlobs || [],\n }\n this.apiKey = config.apiKey || null\n this.baseUrl = config.baseUrl || null\n }\n\n getIgnoredGlobs(): string[] {\n return this.config.ignoredGlobs || []\n }\n\n /**\n * Get the Wispbit API key\n * @returns The API key or null if not set\n */\n getApiKey(): string {\n return this.apiKey!\n }\n\n /**\n * Get the Wispbit API base URL\n * @returns The base URL\n */\n getBaseUrl(): string {\n return this.baseUrl!\n }\n\n /**\n * Get the local PowerLint version\n * @returns The current PowerLint version\n */\n getLocalVersion(): string {\n return getCurrentVersion()\n }\n\n /**\n * Get the schema version\n * @returns The schema version\n */\n getSchemaVersion(): string {\n return \"v1\"\n }\n\n /**\n * Validate API key with Wispbit API\n */\n private static async validateApiKey(\n apiKey: string,\n repositoryUrl: string,\n baseUrl: string\n ): Promise<boolean> {\n const response = await fetch(`${baseUrl}/plv1/initialize`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n repository_url: repositoryUrl,\n powerlint_version: getCurrentVersion(),\n schema_version: \"v1\",\n }),\n })\n\n return response.ok\n }\n\n /**\n * Initialize configuration without network validation (for testing)\n * @param options Optional configuration options\n * @returns Config instance\n */\n public static initializeWithoutNetwork(\n options: {\n ignoredGlobs?: string[]\n apiKey?: string\n baseUrl?: string\n } = {}\n ): Config {\n const finalBaseUrl =\n options.baseUrl || process.env.WISPBIT_API_BASE_URL || \"https://api.wispbit.com\"\n const finalApiKey = options.apiKey || process.env.WISPBIT_API_KEY || null\n const ignoredGlobs = options.ignoredGlobs || []\n\n return new Config({\n ignoredGlobs,\n apiKey: finalApiKey || undefined,\n baseUrl: finalBaseUrl,\n })\n }\n\n /**\n * Initialize configuration by validating API key and repository URL with Wispbit\n * @param environment Environment instance to get repository URL\n * @param apiKey Optional API key to use for initialization. If not provided, will use environment variable\n * @returns Promise<Config | null> - Config if valid, null if API key missing/invalid\n */\n public static async initialize(\n environment: Environment,\n {\n apiKey,\n baseUrl,\n }: {\n apiKey?: string\n baseUrl?: string\n }\n ): Promise<Config | { failed: true; error: \"INVALID_API_KEY\" | \"INVALID_REPOSITORY\" }> {\n const finalBaseUrl = baseUrl || process.env.WISPBIT_API_BASE_URL || \"https://api.wispbit.com\"\n\n // Use provided API key or fall back to environment variable\n const finalApiKey = apiKey || process.env.WISPBIT_API_KEY || null\n\n // Return null if no API key found\n if (!finalApiKey) {\n console.log(\"No API key found\")\n return { failed: true, error: \"INVALID_API_KEY\" }\n }\n\n const repositoryUrl = await environment.getRepositoryUrl()\n\n // Validate API key with Wispbit\n const isValidApiKey = await Config.validateApiKey(finalApiKey, repositoryUrl, finalBaseUrl)\n if (!isValidApiKey) {\n return { failed: true, error: \"INVALID_API_KEY\" }\n }\n\n const response = await fetch(`${finalBaseUrl}/plv1/initialize`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${finalApiKey}`,\n },\n body: JSON.stringify({\n repository_url: repositoryUrl,\n powerlint_version: getCurrentVersion(),\n schema_version: \"v1\",\n }),\n })\n\n const result = await response.json()\n\n if (result.invalid_api_key) {\n return { failed: true, error: \"INVALID_API_KEY\" }\n }\n\n if (!result.is_valid_repository) {\n return { failed: true, error: \"INVALID_REPOSITORY\" }\n }\n\n const ignoredGlobs = result.config?.ignored_globs || []\n\n const config = new Config({ ignoredGlobs, apiKey: finalApiKey, baseUrl: finalBaseUrl })\n\n return config\n }\n\n /**\n * Check if PowerLint is configured (has valid API key)\n */\n isConfigured(): boolean {\n return this.getApiKey() !== null\n }\n}\n", "import { createHash } from \"crypto\"\n\nexport function hashString(str: string) {\n return createHash(\"sha256\").update(str).digest(\"hex\")\n}\n", "import { exec, execSync } from \"child_process\"\nimport { promisify } from \"util\"\n\nimport { hashString } from \"powerlint/utils/hashString\"\n\nconst execPromise = promisify(exec)\n\nexport interface FileChange {\n filename: string\n status: \"added\" | \"modified\" | \"removed\"\n patch: string\n additions: number\n deletions: number\n sha: string\n}\n\nexport interface GitChanges {\n files: FileChange[]\n currentBranch: string\n currentCommit: string\n diffBranch: string\n diffCommit: string\n}\n\n/**\n * Find the Git repository root directory by looking for .git\n */\nexport function findGitRoot(): string {\n const stdout = execSync(\"git rev-parse --show-toplevel\", { encoding: \"utf-8\" })\n return stdout.trim()\n}\n\n/**\n * Get the remote repository URL from Git config\n * @param repoRoot Path to the Git repository root\n * @param remoteName Name of the remote (default: origin)\n * @returns The remote repository URL or null if not found\n */\nexport async function getRepositoryUrl(\n repoRoot: string,\n remoteName: string = \"origin\"\n): Promise<string | null> {\n const { stdout } = await execPromise(`git remote show ${remoteName}`, {\n cwd: repoRoot,\n })\n\n // Parse the URL from the output\n const fetchUrlLine = stdout.split(\"\\n\").find((line) => line.includes(\"Fetch URL:\"))\n if (fetchUrlLine) {\n return fetchUrlLine.split(\"Fetch URL:\").pop()?.trim() || null\n }\n return null\n}\n\n/**\n * Get the default branch from remote (typically main or master)\n * @param repoRoot Path to the Git repository root\n * @param remoteName Name of the remote (default: origin)\n */\nexport async function getDefaultBranch(\n repoRoot: string,\n remoteName: string = \"origin\"\n): Promise<string | null> {\n const { stdout } = await execPromise(`git remote show ${remoteName}`, {\n cwd: repoRoot,\n })\n\n const headBranchLine = stdout.split(\"\\n\").find((line) => line.includes(\"HEAD branch\"))\n if (headBranchLine) {\n return headBranchLine.split(\":\").pop()?.trim() || null\n }\n return null\n}\n\n/**\n * Get list of changed files in the current Git repository with their changes\n * @param repoRoot Path to the Git repository root\n * @param base Optional base commit/branch to compare against\n */\nexport async function getChangedFiles(repoRoot: string, base?: string): Promise<GitChanges> {\n // Get current branch name\n const { stdout: currentBranchOutput } = await execPromise(\"git rev-parse --abbrev-ref HEAD\", {\n cwd: repoRoot,\n })\n const currentBranch = currentBranchOutput.trim()\n\n // Try to get the default branch from origin\n const defaultBranch = await getDefaultBranch(repoRoot)\n const compareTo = base ?? (defaultBranch ? `origin/${defaultBranch}` : \"HEAD^\")\n\n // Get current commit hash from the remote branch instead of local HEAD\n let currentCommit: string\n try {\n // First try to get the commit from the remote tracking branch\n const { stdout: remoteCommitOutput } = await execPromise(\n `git rev-parse origin/${currentBranch}`,\n { cwd: repoRoot }\n )\n currentCommit = remoteCommitOutput.trim()\n } catch (error) {\n // Fallback to local HEAD if remote branch doesn't exist\n const { stdout: currentCommitOutput } = await execPromise(\"git rev-parse HEAD\", {\n cwd: repoRoot,\n })\n currentCommit = currentCommitOutput.trim()\n }\n\n // Find the merge-base (common ancestor) between current branch and comparison branch\n let mergeBase\n try {\n const { stdout: mergeBaseOutput } = await execPromise(\n `git merge-base ${currentBranch} ${compareTo}`,\n { cwd: repoRoot }\n )\n mergeBase = mergeBaseOutput.trim()\n } catch (error) {\n // More conservative fallback - use HEAD^ instead of the entire branch difference\n // This prevents diffing against the entire repo when merge-base fails\n mergeBase = \"HEAD^\"\n }\n\n // Get status of files in the repository for metadata\n const { stdout: statusOutput } = await execPromise(\"git status --porcelain\", {\n cwd: repoRoot,\n })\n const statusLines = statusOutput.split(\"\\n\").filter(Boolean)\n const fileStatuses = new Map<string, string>()\n statusLines.forEach((line) => {\n const statusCode = line.substring(0, 2).trim()\n const filename = line.substring(3)\n fileStatuses.set(filename, statusCode)\n })\n\n // Get all files changed compared to the merge-base\n const { stdout: diffOutput } = await execPromise(`git diff ${mergeBase} --name-only`, {\n cwd: repoRoot,\n })\n const allFiles = diffOutput.split(\"\\n\").filter(Boolean)\n\n // Get list of deleted files\n const { stdout: deletedFilesOutput } = await execPromise(\"git ls-files --deleted\", {\n cwd: repoRoot,\n })\n const deletedFiles = deletedFilesOutput.split(\"\\n\").filter(Boolean)\n\n // Add deleted files that might not be captured in diff\n allFiles.push(...deletedFiles.filter((file) => !allFiles.includes(file)))\n\n // Get untracked files and add them to the list\n const { stdout: untrackedOutput } = await execPromise(\n \"git ls-files --others --exclude-standard\",\n {\n cwd: repoRoot,\n }\n )\n const untrackedFiles = untrackedOutput.split(\"\\n\").filter(Boolean)\n\n // Add untracked files to the list\n allFiles.push(...untrackedFiles.filter((file) => !allFiles.includes(file)))\n\n // Separate deleted and non-deleted files for batch processing\n const nonDeletedFiles: string[] = []\n const deletedFilesSet = new Set(deletedFiles)\n const fileIsDeleted = new Map<string, boolean>()\n\n for (const file of allFiles) {\n const isDeleted =\n deletedFilesSet.has(file) ||\n fileStatuses.get(file)?.includes(\"D\") ||\n fileStatuses.get(file)?.includes(\"R\")\n\n fileIsDeleted.set(file, Boolean(isDeleted))\n if (!isDeleted) {\n nonDeletedFiles.push(file)\n }\n }\n\n // Batch get numstat for all non-deleted files at once\n const fileStats = new Map<string, { additions: number; deletions: number }>()\n if (nonDeletedFiles.length > 0) {\n const { stdout: batchNumstatOutput } = await execPromise(\n `git diff ${mergeBase} --numstat -- ${nonDeletedFiles.map((f) => `'${f.replace(/'/g, \"'\\\\''\")}'`).join(\" \")}`,\n { cwd: repoRoot }\n )\n\n const numstatLines = batchNumstatOutput.split(\"\\n\").filter(Boolean)\n numstatLines.forEach((line) => {\n const parts = line.split(\"\\t\")\n if (parts.length >= 3) {\n const [additionsStr, deletionsStr, filename] = parts\n fileStats.set(filename, {\n additions: parseInt(additionsStr) || 0,\n deletions: parseInt(deletionsStr) || 0,\n })\n }\n })\n }\n\n // Batch get diff content for all non-deleted files at once\n const fileDiffs = new Map<string, string>()\n if (nonDeletedFiles.length > 0) {\n const { stdout: batchDiffOutput } = await execPromise(\n `git diff ${mergeBase} -- ${nonDeletedFiles.map((f) => `'${f.replace(/'/g, \"'\\\\''\")}'`).join(\" \")}`,\n { cwd: repoRoot }\n )\n\n // Parse the batch diff output to extract individual file diffs\n const diffSections = batchDiffOutput.split(/^diff --git /m).filter(Boolean)\n diffSections.forEach((section) => {\n const lines = section.split(\"\\n\")\n // Extract filename from the first line: \"a/path/to/file b/path/to/file\"\n const firstLine = lines[0]\n const match = firstLine.match(/a\\/(.+?) b\\//)\n if (match) {\n const filename = match[1]\n // Remove git headers and keep only the actual diff content\n const diffContent = lines\n .slice(1)\n .filter((line) => {\n return !(\n line.startsWith(\"index \") ||\n line.startsWith(\"--- \") ||\n line.startsWith(\"+++ \")\n )\n })\n .join(\"\\n\")\n fileDiffs.set(filename, diffContent)\n }\n })\n }\n\n // Process deleted files in batch\n const deletedFileContents = new Map<string, string>()\n const actualDeletedFiles = allFiles.filter((file) => fileIsDeleted.get(file))\n\n if (actualDeletedFiles.length > 0) {\n // Use Promise.allSettled to handle files that might not exist in merge-base\n const deletedFilePromises = actualDeletedFiles.map(async (file) => {\n const { stdout: lastContent } = await execPromise(\n `git show '${mergeBase}:${file.replace(/'/g, \"'\\\\''\")}'`,\n {\n cwd: repoRoot,\n }\n )\n return { file, content: lastContent }\n })\n\n const results = await Promise.allSettled(deletedFilePromises)\n results.forEach((result, index) => {\n if (result.status === \"fulfilled\") {\n deletedFileContents.set(actualDeletedFiles[index], result.value.content)\n }\n })\n }\n\n // Build file changes array\n const fileChanges: FileChange[] = []\n for (const file of allFiles) {\n const isDeleted = fileIsDeleted.get(file)!\n let additions = 0\n let deletions = 0\n let diffOutput = \"\"\n\n if (isDeleted) {\n const lastContent = deletedFileContents.get(file)\n if (lastContent) {\n deletions = lastContent.split(\"\\n\").length\n diffOutput = lastContent\n .split(\"\\n\")\n .map((line) => `-${line}`)\n .join(\"\\n\")\n }\n } else {\n const stats = fileStats.get(file)\n if (stats) {\n additions = stats.additions\n deletions = stats.deletions\n }\n diffOutput = fileDiffs.get(file) || \"\"\n }\n\n const status = isDeleted ? \"removed\" : additions > 0 && deletions === 0 ? \"added\" : \"modified\"\n\n fileChanges.push({\n filename: file,\n status: status as \"added\" | \"modified\" | \"removed\",\n patch: diffOutput,\n additions,\n deletions,\n sha: hashString(diffOutput),\n })\n }\n\n return {\n files: fileChanges,\n currentBranch,\n currentCommit,\n diffCommit: mergeBase,\n diffBranch: compareTo,\n }\n}\n", "import { findGitRoot, getRepositoryUrl } from \"powerlint/utils/git\"\n\n/**\n * Environment contains workspace configuration\n * Used by providers and steps to access common configuration\n */\nexport class Environment {\n private readonly workspaceRoot: string\n private readonly repositoryUrl: string | null\n\n constructor(config?: { workspaceRoot?: string; repositoryUrl?: string }) {\n this.repositoryUrl = config?.repositoryUrl || null\n this.workspaceRoot = config?.workspaceRoot || findGitRoot()\n }\n\n /**\n * Get the workspace root directory\n */\n getWorkspaceRoot(): string {\n return this.workspaceRoot\n }\n\n /**\n * Get the remote repository URL from Git config\n * @param remoteName Name of the remote (default: origin)\n * @returns The remote repository URL or null if not found\n */\n async getRepositoryUrl(remoteName: string = \"origin\"): Promise<string> {\n if (this.repositoryUrl) {\n return this.repositoryUrl\n }\n const repositoryUrl = await getRepositoryUrl(this.workspaceRoot, remoteName)\n if (!repositoryUrl) {\n throw new Error(\n \"Could not determine repository URL. Make sure you're in a Git repository with a remote origin.\"\n )\n }\n return repositoryUrl\n }\n}\n", "import * as fs from \"fs/promises\"\nimport os from \"os\"\nimport path from \"path\"\n\nimport Keyv from \"keyv\"\nimport { KeyvFile } from \"keyv-file\"\n\nimport { Environment } from \"powerlint/environment/Environment\"\nimport type { Language } from \"powerlint/languages\"\nimport { hashString } from \"powerlint/utils/hashString\"\n\n/**\n * Storage class manages cache and index storage directories\n * Provides centralized storage management for the powerlint environment\n */\nexport class Storage {\n private environment: Environment\n private cacheStore?: Keyv\n\n constructor(environment: Environment) {\n this.environment = environment\n }\n\n /**\n * Get the base storage directory for powerlint\n * This replaces the getConfigDirectory functionality\n */\n getStorageDirectory(): string {\n return path.join(os.homedir(), \".powerlint\")\n }\n\n /**\n * Get the base directory for indexes\n */\n getIndexDirectory(): string {\n return path.join(\n this.getStorageDirectory(),\n \"indexes\",\n hashString(this.environment.getWorkspaceRoot())\n )\n }\n\n /**\n * Get the base directory for caches\n */\n getCacheDirectory(): string {\n return path.join(\n this.getStorageDirectory(),\n \"cache\",\n hashString(this.environment.getWorkspaceRoot())\n )\n }\n\n /**\n * Ensure a directory exists, creating it if necessary\n */\n async ensureDirectory(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true })\n }\n\n /**\n * Get the file path for a specific index\n * Ensures the index directory exists\n */\n async getIndexFilePath(language: Language, fileName?: string): Promise<string> {\n const indexDir = this.getIndexDirectory()\n await this.ensureDirectory(indexDir)\n\n const file = fileName || `${language.toLowerCase()}-index.scip`\n return path.join(indexDir, `${language.toLowerCase()}-${file}`)\n }\n\n /**\n * Check if an index exists for a language\n */\n async indexExists(language: Language, fileName?: string): Promise<boolean> {\n const indexPath = await this.getIndexFilePath(language, fileName)\n try {\n await fs.access(indexPath)\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Read an index file for a language\n */\n async readIndex(language: Language, fileName?: string): Promise<Buffer | null> {\n const indexPath = await this.getIndexFilePath(language, fileName)\n try {\n await fs.access(indexPath)\n return await fs.readFile(indexPath)\n } catch {\n return null\n }\n }\n\n /**\n * Save an index file for a language\n */\n async saveIndex(language: Language, data: Buffer, fileName?: string): Promise<void> {\n const indexPath = await this.getIndexFilePath(language, fileName)\n await fs.writeFile(indexPath, data)\n }\n\n /**\n * Get the cache file path\n */\n getCacheFilePath(): string {\n return path.join(this.getCacheDirectory(), \"cache.json\")\n }\n\n /**\n * Purge all storage (cache and indexes)\n * @returns Object with success status and details about what was purged\n */\n async purgeStorage(): Promise<{\n success: boolean\n deletedCount: number\n }> {\n let deletedCount = 0\n const storagePath = this.getStorageDirectory()\n\n try {\n await fs.access(storagePath)\n await fs.rm(storagePath, { recursive: true, force: true })\n deletedCount++\n } catch {\n // Directory doesn't exist, which is fine\n }\n\n return {\n success: true,\n deletedCount,\n }\n }\n\n /**\n * Purge only cache data\n */\n async purgeCache(): Promise<{\n success: boolean\n deletedCount: number\n }> {\n let deletedCount = 0\n const cachePath = this.getCacheDirectory()\n\n try {\n await fs.access(cachePath)\n await fs.rm(cachePath, { recursive: true, force: true })\n deletedCount++\n } catch {\n // Directory doesn't exist, which is fine\n }\n\n return {\n success: true,\n deletedCount,\n }\n }\n\n /**\n * Get or initialize the cache store\n */\n private getCacheStore(): Keyv {\n if (!this.cacheStore) {\n const cacheDir = this.getCacheDirectory()\n this.cacheStore = new Keyv({\n store: new KeyvFile({\n filename: path.join(cacheDir, \"cache.json\"),\n }),\n })\n }\n return this.cacheStore\n }\n\n /**\n * Save data to cache\n */\n async saveCache(ruleId: string, cacheKey: string, data: any): Promise<void> {\n const cache = this.getCacheStore()\n const key = `${ruleId}:${cacheKey}`\n await cache.set(key, data)\n }\n\n /**\n * Read data from cache\n */\n async readCache<T = any>(ruleId: string, cacheKey: string): Promise<T | null> {\n const cache = this.getCacheStore()\n const key = `${ruleId}:${cacheKey}`\n const data = await cache.get(key)\n return data || null\n }\n\n /**\n * Purge only index data\n */\n async purgeIndexes(): Promise<{\n success: boolean\n deletedCount: number\n }> {\n let deletedCount = 0\n const indexPath = this.getIndexDirectory()\n\n try {\n await fs.access(indexPath)\n await fs.rm(indexPath, { recursive: true, force: true })\n deletedCount++\n } catch {\n // Directory doesn't exist, which is fine\n }\n\n return {\n success: true,\n deletedCount,\n }\n }\n}\n", "import { z } from \"zod\"\n\nimport type { Config } from \"powerlint/environment/Config\"\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { RuleProvider } from \"powerlint/providers/RuleProvider\"\nimport type { Rule } from \"powerlint/types\"\n\n/**\n * Schema for the get-rules API request\n */\nconst GetRulesSchema = z.object({\n repository_url: z.string(),\n rule_ids: z.array(z.string()).optional(),\n schema_version: z.string(),\n powerlint_version: z.string(),\n})\n\ntype GetRulesRequest = z.infer<typeof GetRulesSchema>\n\n/**\n * Rule provider that fetches rules from Wispbit Cloud\n */\nexport class WispbitRuleProvider implements RuleProvider {\n private config: Config\n private environment: Environment\n\n constructor(config: Config, environment: Environment) {\n this.config = config\n this.environment = environment\n }\n\n /**\n * Make a request to the Wispbit API\n */\n private async makeApiRequest(endpoint: string, data: any): Promise<any> {\n const baseUrl = this.config.getBaseUrl()\n const apiKey = this.config.getApiKey()!\n const url = `${baseUrl}${endpoint}`\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(data),\n })\n\n if (!response.ok) {\n throw new Error(`Wispbit API request failed: ${response.status} ${response.statusText}`)\n }\n\n return await response.json()\n }\n\n /**\n * Get the repository URL for API requests\n */\n private async getRepositoryUrl(): Promise<string> {\n const repoUrl = await this.environment.getRepositoryUrl()\n if (!repoUrl) {\n throw new Error(\n \"Could not determine repository URL. Make sure you're in a Git repository with a remote origin.\"\n )\n }\n return repoUrl\n }\n\n /**\n * Load a specific rule by ID from Wispbit Cloud\n */\n async loadRuleById(ruleId: string): Promise<Rule> {\n const rules = await this.fetchRules([ruleId])\n if (rules.length === 0) {\n throw new Error(`Rule with ID '${ruleId}' not found`)\n }\n return rules[0]\n }\n\n /**\n * Load all rules from Wispbit Cloud for the configured repository\n */\n async loadAllRules(): Promise<Rule[]> {\n return await this.fetchRules()\n }\n\n /**\n * Fetch rules from Wispbit Cloud API\n */\n private async fetchRules(ruleIds?: string[]): Promise<Rule[]> {\n const repositoryUrl = await this.getRepositoryUrl()\n\n const requestData: GetRulesRequest = {\n repository_url: repositoryUrl,\n rule_ids: ruleIds,\n schema_version: this.config.getSchemaVersion(),\n powerlint_version: this.config.getLocalVersion(),\n }\n\n // Validate request data\n GetRulesSchema.parse(requestData)\n\n const response = await this.makeApiRequest(\"/plv1/get-rules\", requestData)\n\n // Assuming the API returns an array of rules\n if (!Array.isArray(response.rules)) {\n throw new Error(\"Invalid response format from Wispbit API: expected rules array\")\n }\n\n const rules: {\n id: string\n internalId: string\n message: string\n prompt: string\n severity: \"suggestion\" | \"violation\"\n schema: any\n }[] = response.rules\n\n return rules.map((rule) => ({\n id: rule.id,\n internalId: rule.internalId,\n config: {\n message: rule.message,\n severity: rule.severity,\n steps: rule.schema,\n },\n prompt: rule.prompt,\n testCases: [],\n }))\n }\n\n /**\n * Create a new rule in Wispbit Cloud\n */\n async createRule(_rule: Rule): Promise<string> {\n await Promise.resolve()\n throw new Error(\"Creating rules in Wispbit Cloud is not yet implemented\")\n }\n\n /**\n * Update an existing rule in Wispbit Cloud\n */\n async updateRule(_ruleId: string, _rule: Rule): Promise<void> {\n await Promise.resolve()\n throw new Error(\"Updating rules in Wispbit Cloud is not yet implemented\")\n }\n\n /**\n * Delete a rule from Wispbit Cloud\n */\n async deleteRule(_ruleId: string): Promise<void> {\n await Promise.resolve()\n throw new Error(\"Deleting rules from Wispbit Cloud is not yet implemented\")\n }\n}\n", "import { EventEmitter } from \"events\"\n\nimport { Language } from \"powerlint/languages\"\nimport { Match } from \"powerlint/types\"\n\n// Streamlined event types focused on key progress indicators\nexport interface ExecutionEvents {\n // Execution mode tracking\n \"execution:mode\": {\n mode: \"check\" | \"diff\"\n filePath?: string\n baseCommit?: string\n headCommit?: string\n }\n\n // Rule execution progress\n \"rules:start\": { totalRules: number }\n \"rules:progress\": {\n currentRule: number\n totalRules: number\n ruleId: string\n percentage: number\n isLlm: boolean\n }\n \"rules:complete\": { totalRules: number; totalMatches: number; executionTime: number }\n\n // Rule step execution debugging\n \"step:start\": {\n ruleId: string\n stepName: string\n stepType: string\n inputs: { filePaths: string[]; matches: Match[] }\n }\n \"step:complete\": {\n ruleId: string\n stepName: string\n stepType: string\n outputs: { filePaths?: string[]; matches?: Match[] }\n executionTime: number\n }\n\n // Test execution events\n \"test:start\": { ruleId: string; testName: string }\n \"test:matches\": { ruleId: string; testName: string; matches: Match[] }\n\n // File discovery and filtering progress\n \"files:discovery:start\": { mode: \"check\" | \"diff\" }\n \"files:discovery:progress\": { message: string; currentCount?: number }\n \"files:discovery:complete\": { totalFiles: number; mode: \"check\" | \"diff\"; executionTime: number }\n \"files:filter\": { originalCount: number; filteredCount: number; filterType: string }\n\n // Indexing progress\n \"indexing:start\": { language: Language }\n \"indexing:progress\": {\n language: Language\n message: string\n packageName?: string\n timeMs?: number\n }\n \"indexing:complete\": { language: Language; executionTime: number }\n\n \"scip:match-lookup:start\": { language: Language; match: Match }\n \"scip:match-lookup:progress\": { language: Language; document: any }\n \"scip:match-lookup:complete\": { language: Language; document?: any }\n\n // LLM validation progress events\n \"llm:validation:start\": {\n ruleId: string\n matchCount: number\n estimatedCost?: string\n }\n \"llm:validation:progress\": {\n ruleId: string\n tokenCount: number\n elapsedTime: number\n streamedText?: string\n }\n \"llm:validation:complete\": {\n ruleId: string\n tokenCount: number\n executionTime: number\n violationCount: number\n fromCache: boolean\n }\n}\n\nexport class ExecutionEventEmitter extends EventEmitter {\n private rulesStartTime = 0\n private indexingStartTimes = new Map<Language, number>()\n private fileDiscoveryStartTime = 0\n\n constructor() {\n super()\n this.setMaxListeners(20) // Reasonable limit for concurrent listeners\n }\n\n // Type-safe event emission\n emit<K extends keyof ExecutionEvents>(event: K, data: ExecutionEvents[K]): boolean {\n return super.emit(event, data)\n }\n\n // Type-safe event listening\n on<K extends keyof ExecutionEvents>(\n event: K,\n listener: (data: ExecutionEvents[K]) => void\n ): this {\n return super.on(event, listener)\n }\n\n once<K extends keyof ExecutionEvents>(\n event: K,\n listener: (data: ExecutionEvents[K]) => void\n ): this {\n return super.once(event, listener)\n }\n\n off<K extends keyof ExecutionEvents>(\n event: K,\n listener: (data: ExecutionEvents[K]) => void\n ): this {\n return super.off(event, listener)\n }\n\n // Helper method for execution mode\n setExecutionMode(\n mode: \"check\" | \"diff\",\n options?: { filePath?: string; baseCommit?: string; headCommit?: string }\n ): void {\n this.emit(\"execution:mode\", { mode, ...options })\n }\n\n // Helper methods for rule progress\n startRules(totalRules: number): void {\n this.rulesStartTime = Date.now()\n this.emit(\"rules:start\", { totalRules })\n }\n\n progressRule(currentRule: number, totalRules: number, ruleId: string, isLlm: boolean): void {\n const percentage = Math.round((currentRule / totalRules) * 100)\n this.emit(\"rules:progress\", { currentRule, totalRules, ruleId, percentage, isLlm })\n }\n\n completeRules(totalRules: number, totalMatches: number): void {\n const executionTime = Date.now() - this.rulesStartTime\n this.emit(\"rules:complete\", { totalRules, totalMatches, executionTime })\n }\n\n // Helper methods for file discovery\n startFileDiscovery(mode: \"check\" | \"diff\"): void {\n this.fileDiscoveryStartTime = Date.now()\n this.emit(\"files:discovery:start\", { mode })\n }\n\n fileDiscoveryProgress(message: string, currentCount?: number): void {\n this.emit(\"files:discovery:progress\", { message, currentCount })\n }\n\n completeFileDiscovery(totalFiles: number, mode: \"check\" | \"diff\"): void {\n const executionTime = Date.now() - this.fileDiscoveryStartTime\n this.emit(\"files:discovery:complete\", { totalFiles, mode, executionTime })\n }\n\n fileFilter(originalCount: number, filteredCount: number, filterType: string): void {\n this.emit(\"files:filter\", { originalCount, filteredCount, filterType })\n }\n\n startScipMatchLookup(language: Language, match: Match): void {\n this.emit(\"scip:match-lookup:start\", { language, match })\n }\n\n scipMatchLookupProgress(language: Language, document: unknown): void {\n this.emit(\"scip:match-lookup:progress\", { language, document })\n }\n\n scipMatchLookupComplete(language: Language, document?: unknown): void {\n this.emit(\"scip:match-lookup:complete\", { language, document })\n }\n\n // Helper methods for indexing\n startIndexing(language: Language): void {\n this.indexingStartTimes.set(language, Date.now())\n this.emit(\"indexing:start\", { language })\n }\n\n indexingProgress(\n language: Language,\n message: string,\n packageName?: string,\n timeMs?: number\n ): void {\n this.emit(\"indexing:progress\", { language, message, packageName, timeMs })\n }\n\n completeIndexing(language: Language): void {\n const startTime = this.indexingStartTimes.get(language) || Date.now()\n const executionTime = Date.now() - startTime\n this.indexingStartTimes.delete(language)\n this.emit(\"indexing:complete\", { language, executionTime })\n }\n\n // Helper methods for step debugging\n startStep(\n ruleId: string,\n stepName: string,\n stepType: string,\n inputs: { filePaths: string[]; matches: Match[] }\n ): void {\n this.emit(\"step:start\", { ruleId, stepName, stepType, inputs })\n }\n\n completeStep(\n ruleId: string,\n stepName: string,\n stepType: string,\n outputs: { filePaths?: string[]; matches?: Match[] },\n executionTime: number = 0\n ): void {\n this.emit(\"step:complete\", { ruleId, stepName, stepType, outputs, executionTime })\n }\n\n // Helper methods for test events\n startTest(ruleId: string, testName: string): void {\n this.emit(\"test:start\", { ruleId, testName })\n }\n\n testMatches(ruleId: string, testName: string, matches: Match[]): void {\n this.emit(\"test:matches\", { ruleId, testName, matches })\n }\n\n // Helper methods for LLM validation events\n startLLMValidation(ruleId: string, matchCount: number, estimatedCost?: string): void {\n this.emit(\"llm:validation:start\", { ruleId, matchCount, estimatedCost })\n }\n\n llmValidationProgress(\n ruleId: string,\n tokenCount: number,\n elapsedTime: number,\n streamedText?: string\n ): void {\n this.emit(\"llm:validation:progress\", { ruleId, tokenCount, elapsedTime, streamedText })\n }\n\n completeLLMValidation(\n ruleId: string,\n tokenCount: number,\n executionTime: number,\n violationCount: number,\n fromCache: boolean\n ): void {\n this.emit(\"llm:validation:complete\", {\n ruleId,\n tokenCount,\n executionTime,\n violationCount,\n fromCache,\n })\n }\n}\n", "import * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { glob } from \"glob\"\nimport { minimatch } from \"minimatch\"\n\nimport { Config } from \"powerlint/environment/Config\"\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { Match } from \"powerlint/types\"\nimport { GitChanges, FileChange, getChangedFiles } from \"powerlint/utils/git\"\n\nexport type ExecutionMode = \"check\" | \"diff\"\n\nexport class FileExecutionContext {\n private environment: Environment\n private _filePaths: string[] = []\n private mode: ExecutionMode\n private eventEmitter: ExecutionEventEmitter\n private config: Config\n private diffMode?: {\n gitChanges: GitChanges\n changedFiles: string[]\n fileChangeMap: Map<string, FileChange> // For quick lookup\n }\n\n private constructor(\n config: Config,\n environment: Environment,\n mode: ExecutionMode,\n eventEmitter?: ExecutionEventEmitter\n ) {\n this.environment = environment\n this.mode = mode\n this.eventEmitter = eventEmitter || new ExecutionEventEmitter()\n this.config = config\n }\n\n /**\n * Create and initialize an ExecutionContext\n */\n static async initialize(\n config: Config,\n environment: Environment,\n mode: ExecutionMode,\n eventEmitter?: ExecutionEventEmitter,\n filePath?: string,\n baseSha?: string\n ): Promise<FileExecutionContext> {\n const context = new FileExecutionContext(config, environment, mode, eventEmitter)\n\n // Initialize file discovery\n const initialFiles = await context.discoverFiles(filePath, baseSha)\n context._filePaths = initialFiles\n\n return context\n }\n\n // ===== State Management =====\n\n get filePaths(): string[] {\n return this._filePaths\n }\n\n /**\n * Filter files based on execution mode and return filtered files\n */\n filterFiles(filePaths: string[]): string[] {\n const originalCount = filePaths.length\n let filteredFiles: string[]\n\n if (this.mode === \"check\") {\n filteredFiles = filePaths // In scan mode, all files are valid\n } else if (!this.diffMode) {\n filteredFiles = filePaths // Fallback for safety\n } else {\n filteredFiles = filePaths.filter((filePath) => this.isFileValid({ filePath }))\n }\n\n // Emit filter event if there's a change\n if (originalCount !== filteredFiles.length) {\n this.eventEmitter.fileFilter(originalCount, filteredFiles.length, `${this.mode}-mode-files`)\n }\n\n return filteredFiles\n }\n\n /**\n * Filter matches based on execution mode and return filtered matches\n */\n filterMatches(matches: Match[]): Match[] {\n const originalCount = matches.length\n // Filter matches to only include valid ones based on execution mode\n const filteredMatches = matches.filter((match) => this.isMatchValid({ match }))\n\n // Emit filter event if there's a change\n if (originalCount !== filteredMatches.length) {\n this.eventEmitter.fileFilter(\n originalCount,\n filteredMatches.length,\n `${this.mode}-mode-matches`\n )\n }\n\n return filteredMatches\n }\n\n /**\n * Filter matches to only include those from the given file paths\n */\n filterMatchesByFilePaths(matches: Match[], filePaths: string[]): Match[] {\n if (matches.length === 0) {\n return matches\n }\n\n const filePathSet = new Set(filePaths)\n return matches.filter((match) => filePathSet.has(match.filePath))\n }\n\n get executionMode(): ExecutionMode {\n return this.mode\n }\n\n // ===== File Discovery =====\n\n /**\n * Discover files based on the execution mode\n * In 'scan' mode: discovers all files in workspace\n * In 'diff' mode: gets changed files from git and returns only those\n *\n * The filePath parameter can be:\n * - A specific filename (e.g., \"src/file.ts\")\n * - A directory path (e.g., \"src/components/\")\n * - A glob pattern (e.g., \".ts\")\n */\n private async discoverFiles(filePath?: string, baseSha?: string): Promise<string[]> {\n // Emit start event\n this.eventEmitter.startFileDiscovery(this.mode)\n\n let discoveredFiles: string[]\n\n // If a specific file path is provided, handle file, directory, or glob pattern\n if (filePath) {\n discoveredFiles = await this.discoverFilesFromPath(filePath)\n } else if (this.mode === \"diff\") {\n // In diff mode, get changed files from git\n const workspaceRoot = this.environment.getWorkspaceRoot()\n\n if (baseSha) {\n this.eventEmitter.fileDiscoveryProgress(`Getting changed files from ${baseSha}...`)\n } else {\n this.eventEmitter.fileDiscoveryProgress(\"Getting changed files from git...\")\n }\n\n const gitChanges = await getChangedFiles(workspaceRoot, baseSha)\n\n // Store diff mode data for validation methods\n this.diffMode = {\n gitChanges,\n changedFiles: gitChanges.files.map((f) => f.filename),\n fileChangeMap: new Map(gitChanges.files.map((file) => [file.filename, file])),\n }\n\n this.eventEmitter.fileDiscoveryProgress(\n `Found ${this.diffMode.changedFiles.length} changed files`\n )\n\n // Git diff returns relative paths from repo root, so we can use them directly\n // Just filter out deleted files that don't exist on disk\n discoveredFiles = this.diffMode.changedFiles\n .filter((file) => fs.existsSync(path.resolve(workspaceRoot, file)))\n .map((file) => file) // Already relative paths from git\n\n // Apply ignore patterns for diff mode\n this.eventEmitter.fileDiscoveryProgress(\"Applying ignore patterns...\")\n\n const allIgnorePatterns = this.config.getIgnoredGlobs()\n if (allIgnorePatterns.length > 0) {\n const beforeIgnore = discoveredFiles.length\n discoveredFiles = discoveredFiles.filter((filePath) => {\n const matchesIgnore = allIgnorePatterns.some((pattern) =>\n this.matchesPattern(filePath, pattern)\n )\n return !matchesIgnore\n })\n\n if (beforeIgnore !== discoveredFiles.length) {\n this.eventEmitter.fileDiscoveryProgress(\n `Filtered out ${beforeIgnore - discoveredFiles.length} ignored files`\n )\n }\n }\n } else {\n // In scan mode, discover all files from workspace root with ignore patterns\n this.eventEmitter.fileDiscoveryProgress(\"Scanning workspace for files...\")\n\n const workspaceRoot = this.environment.getWorkspaceRoot()\n const allIgnorePatterns = this.config.getIgnoredGlobs()\n discoveredFiles = await this.discoverAllFiles([workspaceRoot], allIgnorePatterns)\n }\n\n // Emit completion event\n this.eventEmitter.completeFileDiscovery(discoveredFiles.length, this.mode)\n\n return discoveredFiles\n }\n\n /**\n * Discover files from a given path which can be a file, directory, or glob pattern\n */\n private async discoverFilesFromPath(filePath: string): Promise<string[]> {\n const workspaceRoot = this.environment.getWorkspaceRoot()\n const fullPath = path.resolve(workspaceRoot, filePath)\n const allIgnorePatterns = this.config.getIgnoredGlobs()\n\n // Check if it's a glob pattern (contains glob characters)\n if (this.isGlobPattern(filePath)) {\n this.eventEmitter.fileDiscoveryProgress(\n `Discovering files matching glob pattern: ${filePath}`\n )\n return await this.discoverFilesFromGlob(filePath, allIgnorePatterns)\n }\n\n // Check if path exists\n if (!fs.existsSync(fullPath)) {\n throw new Error(`Path not found: ${filePath}`)\n }\n\n const stats = fs.statSync(fullPath)\n\n if (stats.isFile()) {\n // Handle single file\n this.eventEmitter.fileDiscoveryProgress(`Checking specific file: ${filePath}`)\n\n // Check if file matches ignore patterns\n const matchesIgnore = allIgnorePatterns.some((pattern) =>\n this.matchesPattern(filePath, pattern)\n )\n\n if (matchesIgnore) {\n this.eventEmitter.fileDiscoveryProgress(`File ${filePath} is ignored by patterns`)\n return []\n } else {\n return [filePath]\n }\n } else if (stats.isDirectory()) {\n // Handle directory\n this.eventEmitter.fileDiscoveryProgress(`Discovering files in directory: ${filePath}`)\n return await this.discoverFilesFromDirectory(filePath, allIgnorePatterns)\n } else {\n throw new Error(`Path is neither a file nor directory: ${filePath}`)\n }\n }\n\n /**\n * Check if a path contains glob pattern characters\n */\n private isGlobPattern(filePath: string): boolean {\n return /[*?[\\]{}]/.test(filePath)\n }\n\n /**\n * Discover files matching a glob pattern\n */\n private async discoverFilesFromGlob(\n globPattern: string,\n ignorePatterns: string[]\n ): Promise<string[]> {\n const workspaceRoot = this.environment.getWorkspaceRoot()\n\n // Combine default ignore patterns with custom ones\n const allIgnorePatterns = [\"**/node_modules/**\", \"**/.git/**\", ...ignorePatterns]\n\n const matches = await glob(globPattern, {\n cwd: workspaceRoot,\n nodir: true,\n absolute: false,\n ignore: allIgnorePatterns,\n })\n\n this.eventEmitter.fileDiscoveryProgress(`Found ${matches.length} files matching pattern`)\n return matches\n }\n\n /**\n * Discover all files in a directory\n */\n private async discoverFilesFromDirectory(\n dirPath: string,\n ignorePatterns: string[]\n ): Promise<string[]> {\n const workspaceRoot = this.environment.getWorkspaceRoot()\n\n // Use glob to find all files in the directory\n const globPattern = path.join(dirPath, \"**/*\").replace(/\\\\/g, \"/\") // Normalize path separators\n\n // Combine default ignore patterns with custom ones\n const allIgnorePatterns = [\"**/node_modules/**\", \"**/.git/**\", ...ignorePatterns]\n\n const matches = await glob(globPattern, {\n cwd: workspaceRoot,\n nodir: true,\n absolute: false,\n ignore: allIgnorePatterns,\n })\n\n this.eventEmitter.fileDiscoveryProgress(`Found ${matches.length} files in directory`)\n return matches\n }\n\n /**\n * Discover all files from directories using glob patterns (scan mode)\n */\n private async discoverAllFiles(\n directories: string[],\n ignorePatterns: string[]\n ): Promise<string[]> {\n const allFiles: string[] = []\n const workspaceRoot = this.environment.getWorkspaceRoot()\n\n // Combine default ignore patterns with custom ones\n const allIgnorePatterns = [\"**/node_modules/**\", \"**/.git/**\", ...ignorePatterns]\n\n for (const dir of directories) {\n // Check if it's a directory\n const stats = fs.statSync(dir)\n if (!stats.isDirectory()) {\n // If it's a file, just add it directly (and filter it if needed)\n const shouldIgnore = ignorePatterns.some((pattern) => this.matchesPattern(dir, pattern))\n if (!shouldIgnore) {\n allFiles.push(path.relative(workspaceRoot, dir))\n }\n continue\n }\n\n // Discover all files with ignore patterns passed directly to glob\n const matches = await glob(\"**/*\", {\n cwd: dir,\n nodir: true,\n absolute: false, // Get relative paths from the directory\n ignore: allIgnorePatterns,\n })\n\n // Convert to relative paths from workspace root\n const relativePaths = matches.map((match) => {\n const absolutePath = path.resolve(dir, match)\n return path.relative(workspaceRoot, absolutePath)\n })\n\n allFiles.push(...relativePaths)\n }\n\n // Remove duplicates\n return [...new Set(allFiles)]\n }\n\n /**\n * Pattern matching function that uses consistent options\n */\n private matchesPattern(filePath: string, pattern: string): boolean {\n return minimatch(filePath, pattern, { dot: true })\n }\n\n /**\n * Check if a file should be processed\n */\n private isFileValid(options: { filePath: string }): boolean {\n if (this.mode === \"check\") {\n return true // In scan mode, all files are valid\n }\n\n if (!this.diffMode) {\n return true // Fallback for safety\n }\n\n const { filePath } = options\n\n // Both filePath and changedFiles are relative paths\n return this.diffMode.changedFiles.some((changedFile) => {\n return (\n filePath === changedFile || filePath.endsWith(changedFile) || changedFile.endsWith(filePath)\n )\n })\n }\n\n /**\n * Check if a specific line range should be processed\n */\n private isLineRangeValid(options: {\n filePath: string\n startLine: number\n endLine: number\n }): boolean {\n if (this.mode === \"check\") {\n return true // In scan mode, all lines are valid\n }\n\n if (!this.diffMode) {\n return true // Fallback for safety\n }\n\n const { filePath, startLine, endLine } = options\n\n // Both filePath and fileChangeMap keys are relative paths\n const fileChange = this.diffMode.fileChangeMap.get(filePath)\n if (!fileChange) {\n return false // File not in diff\n }\n\n // For added files, all lines are considered valid\n if (fileChange.status === \"added\") {\n return true\n }\n\n // For removed files, no lines are valid (since the file doesn't exist)\n if (fileChange.status === \"removed\") {\n return false\n }\n\n // For modified files, check if the line range intersects with changed lines\n return this.isLineRangeInPatch({ patch: fileChange.patch, startLine, endLine })\n }\n\n /**\n * Check if a match should be processed\n */\n private isMatchValid(options: { match: Match }): boolean {\n if (this.mode === \"check\") {\n return true // In scan mode, all matches are valid\n }\n\n if (!this.diffMode) {\n return true // Fallback for safety\n }\n\n const { match } = options\n return (\n this.isFileValid({ filePath: match.filePath }) &&\n this.isLineRangeValid({\n filePath: match.filePath,\n startLine: match.range.start.line,\n endLine: match.range.end.line,\n })\n )\n }\n\n // ===== Helper Methods =====\n\n /**\n * Parse a git patch to determine if a line range intersects with changed lines\n * Adapted from patchParser.ts logic\n */\n private isLineRangeInPatch(options: {\n patch: string\n startLine: number\n endLine: number\n }): boolean {\n const { patch, startLine, endLine } = options\n\n const lines = patch.split(\"\\n\")\n let currentNewLine = 0\n let inHunk = false\n\n for (const line of lines) {\n // Parse hunk headers like @@ -1,4 +1,6 @@\n const hunkMatch = line.match(/^@@\\s+-\\d+(?:,\\d+)?\\s+\\+(\\d+)(?:,\\d+)?\\s+@@/)\n if (hunkMatch) {\n currentNewLine = parseInt(hunkMatch[1], 10)\n inHunk = true\n continue\n }\n\n if (!inHunk) continue\n\n if (line.startsWith(\"+\")) {\n // Addition - check if this line intersects with our range\n if (currentNewLine >= startLine && currentNewLine <= endLine) {\n return true\n }\n currentNewLine++\n } else if (line.startsWith(\"-\")) {\n // Deletion - don't increment new line counter\n continue\n } else if (!line.startsWith(\"\\\\\")) {\n // Context line - check if this line intersects with our range\n if (currentNewLine >= startLine && currentNewLine <= endLine) {\n return true\n }\n currentNewLine++\n }\n }\n\n return false\n }\n}\n", "import * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { minimatch } from \"minimatch\"\n\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { FileFilterCondition, FileFilterConditions } from \"powerlint/types\"\n\nexport interface FileFilterResult {\n filteredPaths: string[]\n executionTime: number\n}\n\nexport interface FileFilterOptions {\n include?: string[]\n ignore?: string[]\n conditions?: FileFilterConditions\n}\n\nexport class FileFilterStep {\n private environment: Environment\n\n constructor(environment: Environment) {\n this.environment = environment\n }\n\n /**\n * Centralized pattern matching function that uses consistent options\n * @param path - The path to test\n * @param pattern - The glob pattern to match against\n * @returns true if the path matches the pattern\n */\n private matchesPattern(path: string, pattern: string): boolean {\n return minimatch(path, pattern, { dot: true })\n }\n\n /**\n * Evaluate a single file filter condition for a given file path\n */\n private evaluateCondition(condition: FileFilterCondition, filePath: string): boolean {\n const workspaceRoot = this.environment.getWorkspaceRoot()\n const absoluteFilePath = path.resolve(workspaceRoot, filePath)\n\n // Handle fs.siblingExists\n if (\"fs.siblingExists\" in condition) {\n const { filename } = condition[\"fs.siblingExists\"]\n const dir = path.dirname(absoluteFilePath)\n const siblingPath = path.join(dir, filename)\n return fs.existsSync(siblingPath)\n }\n\n // Handle fs.pathMatches\n if (\"fs.pathMatches\" in condition) {\n const { pattern } = condition[\"fs.pathMatches\"]\n return this.matchesPattern(filePath, pattern)\n }\n\n // Handle fs.ancestorHas\n if (\"fs.ancestorHas\" in condition) {\n const { filename } = condition[\"fs.ancestorHas\"]\n let currentDir = path.dirname(absoluteFilePath)\n const root = path.parse(currentDir).root\n\n while (currentDir !== root) {\n const targetPath = path.join(currentDir, filename)\n if (fs.existsSync(targetPath)) {\n return true\n }\n const parentDir = path.dirname(currentDir)\n if (parentDir === currentDir) break // Reached root\n currentDir = parentDir\n }\n return false\n }\n\n // Handle fs.siblingAny\n if (\"fs.siblingAny\" in condition) {\n const { pattern } = condition[\"fs.siblingAny\"]\n const dir = path.dirname(absoluteFilePath)\n if (!fs.existsSync(dir)) {\n return false\n }\n const siblings = fs.readdirSync(dir)\n return siblings.some((sibling) => this.matchesPattern(sibling, pattern))\n }\n\n return false\n }\n\n /**\n * Evaluate file filter conditions for a given file path\n */\n private evaluateConditions(conditions: FileFilterConditions, filePath: string): boolean {\n const results: boolean[] = []\n\n // Handle 'all' - all conditions must be true (AND)\n if (conditions.all) {\n results.push(conditions.all.every((condition) => this.evaluateCondition(condition, filePath)))\n }\n\n // Handle 'any' - at least one condition must be true (OR)\n if (conditions.any) {\n results.push(conditions.any.some((condition) => this.evaluateCondition(condition, filePath)))\n }\n\n // Handle 'not' - all conditions must be false (NOT)\n if (conditions.not) {\n results.push(!conditions.not.some((condition) => this.evaluateCondition(condition, filePath)))\n }\n\n // All evaluated conditions must be true (AND them together)\n return results.length === 0 ? true : results.every((result) => result === true)\n }\n\n /**\n * Execute file filter on file paths\n */\n async execute(filePaths: string[], options: FileFilterOptions): Promise<FileFilterResult> {\n const startTime = Date.now()\n\n let filteredPaths = filePaths\n\n // Apply include patterns if provided\n if (options.include?.length) {\n filteredPaths = filteredPaths.filter((filePath) =>\n options.include!.some((pattern) => this.matchesPattern(filePath, pattern))\n )\n }\n\n // Apply ignore patterns if provided\n if (options.ignore?.length) {\n filteredPaths = filteredPaths.filter((filePath) => {\n const matchesIgnore = options.ignore!.some((pattern) =>\n this.matchesPattern(filePath, pattern)\n )\n return !matchesIgnore\n })\n }\n\n // Apply complex conditions if provided\n if (options.conditions) {\n filteredPaths = filteredPaths.filter((filePath) =>\n this.evaluateConditions(options.conditions!, filePath)\n )\n }\n\n const executionTime = Date.now() - startTime\n\n return await Promise.resolve({\n filteredPaths,\n executionTime,\n })\n }\n}\n", "// ast-grep gives annoying warnings\nconsole.debug = () => {}\n\nimport { existsSync } from \"fs\"\nimport { createRequire } from \"module\"\nimport path from \"path\"\n\nimport angular from \"@ast-grep/lang-angular\"\nimport bash from \"@ast-grep/lang-bash\"\nimport c from \"@ast-grep/lang-c\"\nimport cpp from \"@ast-grep/lang-cpp\"\nimport csharp from \"@ast-grep/lang-csharp\"\nimport css from \"@ast-grep/lang-css\"\nimport dart from \"@ast-grep/lang-dart\"\nimport elixir from \"@ast-grep/lang-elixir\"\nimport go from \"@ast-grep/lang-go\"\nimport haskell from \"@ast-grep/lang-haskell\"\nimport html from \"@ast-grep/lang-html\"\nimport java from \"@ast-grep/lang-java\"\nimport javascript from \"@ast-grep/lang-javascript\"\nimport json from \"@ast-grep/lang-json\"\nimport kotlin from \"@ast-grep/lang-kotlin\"\nimport lua from \"@ast-grep/lang-lua\"\nimport markdown from \"@ast-grep/lang-markdown\"\nimport php from \"@ast-grep/lang-php\"\nimport python from \"@ast-grep/lang-python\"\nimport ruby from \"@ast-grep/lang-ruby\"\nimport rust from \"@ast-grep/lang-rust\"\nimport scala from \"@ast-grep/lang-scala\"\nimport sql from \"@ast-grep/lang-sql\"\nimport swift from \"@ast-grep/lang-swift\"\nimport toml from \"@ast-grep/lang-toml\"\nimport tsx from \"@ast-grep/lang-tsx\"\nimport typescript from \"@ast-grep/lang-typescript\"\nimport yaml from \"@ast-grep/lang-yaml\"\nimport { registerDynamicLanguage } from \"@ast-grep/napi\"\nimport { LangRegistration } from \"@ast-grep/napi/types/registerDynamicLang\"\n\nexport enum Language {\n Angular = \"Angular\",\n Bash = \"Bash\",\n C = \"C\",\n Cpp = \"Cpp\",\n Csharp = \"Csharp\",\n Css = \"Css\",\n Dart = \"Dart\",\n Elixir = \"Elixir\",\n Go = \"Go\",\n Haskell = \"Haskell\",\n Html = \"Html\",\n Java = \"Java\",\n JavaScript = \"JavaScript\",\n Json = \"Json\",\n Kotlin = \"Kotlin\",\n Lua = \"Lua\",\n Markdown = \"Markdown\",\n Php = \"Php\",\n Python = \"Python\",\n Ruby = \"Ruby\",\n Rust = \"Rust\",\n Scala = \"Scala\",\n Sql = \"Sql\",\n Swift = \"Swift\",\n Toml = \"Toml\",\n Tsx = \"Tsx\",\n TypeScript = \"TypeScript\",\n Yaml = \"Yaml\",\n GraphQL = \"GraphQL\",\n Unknown = \"Unknown\",\n}\n\n// For tree-sitter-graphql from GitHub repo\nconst require = createRequire(import.meta.url ? import.meta.url : __filename)\n\nfunction getGraphQLLibPath() {\n const graphqlDir = path.dirname(require.resolve(\"tree-sitter-graphql\"))\n\n // Try node-gyp-build output (Release build)\n const releaseNode = path.join(graphqlDir, \"../../build/Release/tree_sitter_graphql_binding.node\")\n if (existsSync(releaseNode)) {\n return releaseNode\n }\n\n // Try Debug build\n const debugNode = path.join(graphqlDir, \"../../build/Debug/tree_sitter_graphql_binding.node\")\n if (existsSync(debugNode)) {\n return debugNode\n }\n\n // Try .so file (Linux style)\n const soFile = path.join(graphqlDir, \"parser.so\")\n if (existsSync(soFile)) {\n return soFile\n }\n\n return null\n}\n\nconst graphqlPath = getGraphQLLibPath()\n\nconst graphql: LangRegistration = {\n // node-gyp-build puts the .node file in build/Release/\n libraryPath: graphqlPath!,\n /** the file extensions of the language. e.g. mojo */\n extensions: [\"graphql\"],\n /** the dylib symbol to load ts-language, default is `tree_sitter_{name}` */\n languageSymbol: \"tree_sitter_graphql\",\n /** the meta variable leading character, default is $ */\n metaVarChar: \"$\",\n /**\n * An optional char to replace $ in your pattern.\n * See https://ast-grep.github.io/advanced/custom-language.html#register-language-in-sgconfig-yml\n */\n expandoChar: undefined,\n}\n\nconst registeredLanguages = {\n [Language.Angular]: angular,\n [Language.Bash]: bash,\n [Language.C]: c,\n [Language.Cpp]: cpp,\n [Language.Csharp]: csharp,\n [Language.Css]: css,\n [Language.Dart]: dart,\n [Language.Elixir]: elixir,\n [Language.Go]: go,\n [Language.Haskell]: haskell,\n [Language.Html]: html,\n [Language.Java]: java,\n [Language.JavaScript]: javascript,\n [Language.Json]: json,\n [Language.Kotlin]: kotlin,\n [Language.Lua]: lua,\n [Language.Markdown]: markdown,\n [Language.Php]: php,\n [Language.Python]: python,\n [Language.Ruby]: ruby,\n [Language.Rust]: rust,\n [Language.Scala]: scala,\n [Language.Sql]: sql,\n [Language.Swift]: swift,\n [Language.Toml]: toml,\n [Language.Tsx]: tsx,\n [Language.TypeScript]: typescript,\n [Language.Yaml]: yaml,\n ...(graphqlPath ? { [Language.GraphQL]: graphql } : {}),\n}\n\n// Register all supported languages with ast-grep\nregisterDynamicLanguage(registeredLanguages)\n\nexport const REGISTERED_LANGUAGE_EXTENSIONS: Record<Language, string[]> = Object.entries(\n registeredLanguages\n).reduce(\n (acc, [language, registration]) => {\n acc[language as Language] = registration.extensions ?? []\n return acc\n },\n {} as Record<Language, string[]>\n)\n\nexport function getLanguageFromFilePath(filePath: string): Language {\n const extension = path.extname(filePath).slice(1)\n const language = findRegisteredLanguageFromExtension(extension)\n return language ?? Language.Unknown\n}\n\nfunction findRegisteredLanguageFromExtension(extension: string): Language | undefined {\n return (Object.keys(REGISTERED_LANGUAGE_EXTENSIONS) as Language[]).find((language) =>\n REGISTERED_LANGUAGE_EXTENSIONS[language].includes(extension)\n )\n}\n\nexport function getLanguageGlobsForLanguage(language: Language): string[] {\n return REGISTERED_LANGUAGE_EXTENSIONS[language].map((extension) => `**/*.${extension}`)\n}\n", "import { readFile } from \"fs/promises\"\nimport path from \"path\"\n\nimport { parse, parseAsync } from \"@ast-grep/napi\"\nimport { NapiConfig } from \"@ast-grep/napi/types/config\"\nimport { SgNode } from \"@ast-grep/napi/types/sgnode\"\n\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { Language } from \"powerlint/languages\"\nimport type { AstProvider } from \"powerlint/providers/LanguageBackend\"\nimport { Match } from \"powerlint/types\"\n\n/**\n * Ast-grep implementation of AstProvider\n * Provides pattern-based code matching using ast-grep\n */\nexport class AstGrepAstProvider implements AstProvider {\n private environment: Environment\n private language: Language\n\n constructor(environment: Environment, language: Language) {\n this.environment = environment\n this.language = language\n }\n\n /**\n * Find all matches based on ast-grep pattern\n * @param filePaths File paths to search in (relative to workspace root)\n * @param schema The ast-grep schema (rule, constraints, etc.)\n * @returns Array of matches found\n */\n async findMatches(filePaths: string[], schema: NapiConfig): Promise<Match[]> {\n if (filePaths.length === 0) {\n return []\n }\n\n // Parse the schema\n const { rule, constraints } = schema\n\n // Process files in batches to avoid overwhelming the thread pool\n const batchSize = this.getBatchSize()\n const matches: Match[] = []\n\n for (let i = 0; i < filePaths.length; i += batchSize) {\n const batch = filePaths.slice(i, i + batchSize)\n const batchMatches = await this.processBatch(batch, rule, constraints)\n matches.push(...batchMatches)\n }\n\n return matches\n }\n\n /**\n * Get optimal batch size based on available CPU cores and thread pool size\n */\n private getBatchSize(): number {\n // Node.js default thread pool size is 4, but can be configured via UV_THREADPOOL_SIZE\n // We use a conservative approach to avoid overwhelming the thread pool\n const threadPoolSize = parseInt(process.env.UV_THREADPOOL_SIZE || \"4\", 10)\n // Use half the thread pool size to leave room for other operations\n return Math.max(2, Math.floor(threadPoolSize / 2))\n }\n\n /**\n * Process a batch of files with memory-efficient approach\n */\n private async processBatch(filePaths: string[], rule: any, constraints: any): Promise<Match[]> {\n // Process files one by one to avoid memory overload, but parse in parallel\n const parsePromises = filePaths.map(async (filePath) => {\n // Read file content (sequential per file to manage memory)\n const content = await readFile(\n path.resolve(this.environment.getWorkspaceRoot(), filePath),\n \"utf-8\"\n )\n\n // Parse using parseAsync (this uses thread pool efficiently)\n const node = await parseAsync(this.language, content)\n const foundNodes = node.root().findAll({\n rule,\n language: this.language,\n constraints,\n })\n\n return foundNodes.map((sgNode) => ({ filePath, sgNode }))\n })\n\n // Execute all parse operations in parallel (limited by batch size)\n const batchResults = await Promise.all(parsePromises)\n const sgNodes = batchResults.flat()\n\n // Convert to matches\n const matches: Match[] = []\n for (const { filePath, sgNode } of sgNodes) {\n const range = sgNode.range()\n\n matches.push({\n filePath,\n text: sgNode.text(),\n range: {\n start: {\n line: range.start.line,\n column: range.start.column,\n },\n end: {\n line: range.end.line,\n column: range.end.column,\n },\n },\n // Try to extract symbol if possible\n symbol: this.extractSymbol(sgNode),\n language: this.language,\n })\n }\n\n return matches\n }\n\n /**\n * Extract symbol name from ast-grep node if possible\n */\n private extractSymbol(node: any): string | undefined {\n const kind = node.kind()\n\n // Handle different node types\n if (kind === \"call_expression\") {\n const functionNode = node.field(\"function\")\n if (functionNode) {\n return this.extractSymbol(functionNode)\n }\n } else if (kind === \"member_expression\") {\n const propertyNode = node.field(\"property\")\n if (propertyNode) {\n return propertyNode.text()\n }\n } else if (kind === \"identifier\") {\n return node.text()\n }\n\n return undefined\n }\n\n /**\n * Expand a match to its enclosing function, method, or class definition\n * @param match The match to expand (typically a small range like a method name)\n * @returns Expanded match with the full function/method/class body, or null if not found\n */\n async expandMatch(match: Match): Promise<Match | null> {\n // Node kinds that represent top-level declarations we want to expand to\n const targetNodeKinds = new Set([\n \"method_definition\",\n \"function_declaration\",\n \"function_expression\",\n \"arrow_function\",\n \"class_declaration\",\n \"export_statement\",\n \"lexical_declaration\", // For const/let function expressions\n ])\n\n const absolutePath = path.resolve(this.environment.getWorkspaceRoot(), match.filePath)\n const content = await readFile(absolutePath, \"utf-8\")\n\n // Parse the file with ast-grep\n const root = parse(this.language, content).root()\n\n // Find the deepest node at the match position\n const nodeAtPosition = this.findNodeAtPosition(\n root,\n match.range.start.line,\n match.range.start.column\n )\n\n if (!nodeAtPosition) {\n return null\n }\n\n // Walk up the tree to find an enclosing declaration node\n let current: SgNode | null = nodeAtPosition\n while (current) {\n const kindValue = current.kind()\n // Convert kind to string for comparison (handle both string and number types)\n const kindStr = typeof kindValue === \"string\" ? kindValue : String(kindValue)\n\n if (targetNodeKinds.has(kindStr)) {\n const range = current.range()\n return {\n filePath: match.filePath,\n text: current.text(),\n range: {\n start: { line: range.start.line, column: range.start.column },\n end: { line: range.end.line, column: range.end.column },\n },\n symbol: match.symbol,\n language: this.language,\n }\n }\n\n current = current.parent()\n }\n\n // No enclosing declaration found\n return null\n }\n\n /**\n * Find the deepest node at a given position\n */\n private findNodeAtPosition(node: SgNode, line: number, column: number): SgNode | null {\n const range = node.range()\n\n // Check if position is within this node's range\n const isAfterStart =\n line > range.start.line || (line === range.start.line && column >= range.start.column)\n const isBeforeEnd =\n line < range.end.line || (line === range.end.line && column <= range.end.column)\n\n if (!isAfterStart || !isBeforeEnd) {\n return null\n }\n\n // Check children to find a deeper node\n const children = node.children()\n for (const child of children) {\n const deeperNode = this.findNodeAtPosition(child, line, column)\n if (deeperNode) {\n return deeperNode\n }\n }\n\n // No deeper node found, return this node\n return node\n }\n}\n", "import { readFile } from \"fs/promises\"\nimport path from \"path\"\n\nimport type { MatchRange } from \"powerlint/types\"\n\n/**\n * Read text from a file at the given range\n * @param workspaceRoot - The workspace root directory\n * @param filePath - The relative file path from workspace root\n * @param range - The range object with start and end positions\n * @returns The text content at the specified range\n */\nexport async function readTextAtRange(\n workspaceRoot: string,\n filePath: string,\n range: MatchRange\n): Promise<string> {\n const absolutePath = path.resolve(workspaceRoot, filePath)\n const content = await readFile(absolutePath, \"utf-8\")\n const lines = content.split(\"\\n\")\n\n const { start, end } = range\n\n if (start.line === end.line) {\n const line = lines[start.line] || \"\"\n return line.substring(start.column, end.column)\n }\n\n const result: string[] = []\n for (let i = start.line; i <= end.line && i < lines.length; i++) {\n const line = lines[i]\n if (i === start.line) {\n result.push(line.substring(start.column))\n } else if (i === end.line) {\n result.push(line.substring(0, end.column))\n } else {\n result.push(line)\n }\n }\n\n return result.join(\"\\n\")\n}\n", "import { spawn } from \"child_process\"\nimport fs from \"fs/promises\"\nimport { createRequire } from \"module\"\nimport os from \"os\"\nimport path from \"path\"\n\nimport type { scip } from \"@sourcegraph/scip-root/bindings/typescript/scip\"\n\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { Storage } from \"powerlint/environment/Storage\"\nimport { Language } from \"powerlint/languages\"\nimport type { IntelligenceProvider } from \"powerlint/providers/LanguageBackend\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { Match } from \"powerlint/types\"\nimport { readTextAtRange } from \"powerlint/utils/readTextAtRange\"\n\n// Use createRequire to import CommonJS module in ES module context\nconst require = createRequire(import.meta.url ? import.meta.url : __filename)\n// @ts-expect-error this is a CommonJS module\nconst { scip } = require(\"@sourcegraph/scip-root/bindings/typescript/scip.js\")\n/**\n * Helper functions for parsing SCIP progress output\n */\nconst PACKAGE_REGEX = /^\\+ (.+?) \\((\\d+)ms\\)$/\n\nfunction processScipProgressData(\n data: Buffer | string,\n buffer: string,\n eventEmitter: ExecutionEventEmitter,\n language: Language,\n rootPath: string\n): string {\n const text = data.toString()\n buffer += text\n\n // Process complete lines\n const lines = buffer.split(\"\\n\")\n const newBuffer = lines.pop() || \"\" // Keep incomplete line in buffer\n\n // Find the latest line that has a package match\n let latestPackageLine: string | null = null\n for (const line of lines) {\n const trimmedLine = line.trim()\n const packageMatch = trimmedLine.match(PACKAGE_REGEX)\n if (packageMatch) {\n latestPackageLine = trimmedLine\n }\n }\n\n // Process all lines, but for package matches, only process the latest one\n for (const line of lines) {\n const trimmedLine = line.trim()\n if (!trimmedLine) continue\n\n const packageMatch = trimmedLine.match(PACKAGE_REGEX)\n\n if (packageMatch) {\n // Only process this package line if it's the latest one\n if (trimmedLine === latestPackageLine) {\n const [, packagePath, timeMs] = packageMatch\n const relativePackagePath = path.relative(rootPath, packagePath)\n eventEmitter.indexingProgress(\n language,\n `Indexed ${relativePackagePath}`,\n relativePackagePath,\n parseInt(timeMs, 10)\n )\n }\n } else {\n // Process non-package lines normally\n eventEmitter.indexingProgress(language, trimmedLine)\n }\n }\n\n return newBuffer\n}\n\n/**\n * SCIP (Source Code Intelligence Protocol) implementation of IntelligenceProvider\n * Provides code navigation features using SCIP indexes\n */\nexport class ScipIntelligenceProvider implements IntelligenceProvider {\n private environment: Environment\n private storage: Storage\n private language: Language\n private scipIndex: scip.Index | null = null\n private indexingPromise: Promise<void> | null = null\n private eventEmitter: ExecutionEventEmitter\n\n constructor(environment: Environment, language: Language, eventEmitter?: ExecutionEventEmitter) {\n this.environment = environment\n this.storage = new Storage(environment)\n this.language = language\n this.eventEmitter = eventEmitter || new ExecutionEventEmitter()\n }\n\n /**\n * Get the SCIP CLI command for the given language\n */\n private getScipCommand(): string {\n switch (this.language) {\n case Language.TypeScript:\n case Language.JavaScript:\n case Language.Tsx:\n return \"scip-typescript\"\n case Language.Python:\n return \"scip-python\"\n default:\n throw new Error(`SCIP is not supported for language: ${this.language}`)\n }\n }\n\n /**\n * Ensure the index is ready, starting indexing if needed\n */\n private async ensureIndexReady(): Promise<void> {\n // If already indexed, return immediately\n if (this.scipIndex !== null) {\n return\n }\n\n // If indexing is in progress, wait for it\n if (this.indexingPromise !== null) {\n return this.indexingPromise\n }\n\n // Start indexing\n this.indexingPromise = this.startIndexing()\n await this.indexingPromise\n }\n\n /**\n * Start the indexing process\n */\n private async startIndexing(): Promise<void> {\n // Check if index already exists\n if (await this.storage.indexExists(this.language, `index.scip`)) {\n // Load existing index directly\n await this.loadIndex()\n return\n }\n\n // Get the final index path and create a temporary path in system temp directory\n const finalIndexPath = await this.storage.getIndexFilePath(this.language, `index.scip`)\n const tempIndexPath = path.join(os.tmpdir(), `scip-index-${this.language}-${Date.now()}.tmp`)\n\n // Emit indexing start event\n this.eventEmitter.startIndexing(this.language)\n\n // Run language-specific SCIP command and stream stdout as it comes out\n const scipCommand = this.getScipCommand()\n const child = spawn(scipCommand, [\"index\", \"--output\", tempIndexPath], {\n cwd: this.environment.getWorkspaceRoot(),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n })\n\n // Track progress buffer for parsing stdout\n let progressBuffer = \"\"\n\n child.stdout.on(\"data\", (data) => {\n // Parse progress data\n progressBuffer = processScipProgressData(\n data,\n progressBuffer,\n this.eventEmitter,\n this.language,\n this.environment.getWorkspaceRoot()\n )\n })\n\n let stderr = \"\"\n child.stderr.on(\"data\", (data) => {\n stderr += data.toString()\n process.stderr.write(data)\n })\n\n await new Promise<void>((resolve, reject) => {\n child.on(\"close\", async (code) => {\n if (code === 0) {\n // Indexing completed successfully, atomically move temp file to final location\n await fs.rename(tempIndexPath, finalIndexPath)\n resolve()\n } else {\n // Indexing failed, clean up temp file if it exists\n await fs.unlink(tempIndexPath).catch(() => {\n // Ignore errors if temp file doesn't exist\n })\n reject(new Error(`${scipCommand} index exited with code ${code}, stderr: ${stderr}`))\n }\n })\n child.on(\"error\", async (err) => {\n // Process failed to start, clean up temp file if it exists\n await fs.unlink(tempIndexPath).catch(() => {\n // Ignore errors if temp file doesn't exist\n })\n reject(err)\n })\n })\n\n if (stderr) {\n console.error(\"SCIP indexing stderr:\", stderr)\n }\n\n // Emit indexing complete event\n this.eventEmitter.completeIndexing(this.language)\n\n // Load the newly created index (no need to save since it's already written to the correct location)\n await this.loadIndex()\n }\n\n /**\n * Find all definitions for a given match\n * Automatically filters out external symbols\n */\n async findDefinitions(match: Match): Promise<Match[]> {\n await this.ensureIndexReady()\n\n if (!this.scipIndex) throw new Error(\"SCIP index not ready\")\n\n this.eventEmitter.startScipMatchLookup(this.language, match)\n\n const definitions: Match[] = []\n const documents = this.scipIndex.documents\n\n for (const document of documents) {\n // look only at the file that the match is in\n if (document.relative_path !== match.filePath) continue\n\n this.eventEmitter.scipMatchLookupProgress(this.language, document)\n\n // Find the best matching SCIP occurrence for this span\n const scipOcc = this.findBestOverlappingOccurrence(document.occurrences, match)\n\n if (scipOcc) {\n // Skip external symbols\n if (this.isExternalSymbol(scipOcc.symbol)) {\n continue\n }\n\n this.eventEmitter.scipMatchLookupProgress(this.language, scipOcc)\n\n // Find the definition for this symbol\n const def = await this.findDefinitionForSymbol(scipOcc.symbol, documents)\n if (def) {\n definitions.push(def)\n }\n }\n }\n\n return definitions\n }\n\n /**\n * Find all references for a given match\n * Automatically filters out external symbols\n */\n async findReferences(match: Match): Promise<Match[]> {\n await this.ensureIndexReady()\n\n if (!this.scipIndex) {\n return []\n }\n\n const references: Match[] = []\n const documents = this.scipIndex.documents\n\n for (const document of documents) {\n // look only at the file that the match is in\n if (document.relative_path !== match.filePath) continue\n\n // Find the best matching SCIP occurrence for this span\n const scipOcc = this.findBestOverlappingOccurrence(document.occurrences, match)\n\n if (scipOcc) {\n // Skip external symbols\n if (this.isExternalSymbol(scipOcc.symbol)) {\n break\n }\n\n // Find all references to this symbol\n const refs = await this.findReferencesForSymbol(scipOcc.symbol, documents)\n references.push(...refs)\n break\n }\n }\n\n return references\n }\n\n /**\n * Check if a symbol is from an external library (internal use)\n */\n private isExternalSymbol(symbol: string): boolean {\n // Check if symbol starts with external package prefixes\n // This is a simple heuristic that can be enhanced\n return symbol.includes(\"node_modules\") || symbol.startsWith(\"npm/\")\n }\n\n /**\n * Find the best SCIP occurrence that overlaps with the given match\n * Uses heuristics to pick the most relevant occurrence when multiple overlap\n */\n private findBestOverlappingOccurrence(\n occurrences: scip.Occurrence[],\n match: Match\n ): scip.Occurrence | null {\n interface ScoredOccurrence {\n occurrence: scip.Occurrence\n score: number\n }\n\n const candidates: ScoredOccurrence[] = []\n\n for (const scipOcc of occurrences) {\n const range = scipOcc.range\n if (!range || range.length < 3) continue\n\n // Check if SCIP occurrence overlaps with our match\n if (!this.rangesOverlap(range, match)) continue\n\n // Score this occurrence\n let score = 0\n\n // 1. Must be fully inside the span (not just overlapping)\n if (!this.rangeFullyInside(range, match)) continue\n\n // 2. Prefer rightmost startCol (deepest/most specific identifier)\n const startCol = range.length === 3 ? range[1] : range[1]\n score += startCol * 1000\n\n // 3. Prefer Reference role over Definition (we're looking from a usage site)\n if (scipOcc.symbol_roles !== scip.SymbolRole.Definition) {\n score += 100\n }\n\n // 4. Boost if symbol name matches the match's symbol\n if (match.symbol) {\n const { className, methodName } = this.extractSymbolNames(scipOcc.symbol)\n if (methodName === match.symbol || className === match.symbol) {\n score += 10000\n }\n }\n\n candidates.push({ occurrence: scipOcc, score })\n }\n\n // Return the highest scoring occurrence\n if (candidates.length === 0) return null\n\n candidates.sort((a, b) => b.score - a.score)\n return candidates[0].occurrence\n }\n\n /**\n * Check if two ranges overlap\n */\n private rangesOverlap(scipRange: number[], match: Match): boolean {\n if (scipRange.length === 3) {\n const [line, startCol, endCol] = scipRange\n // Single line SCIP range\n if (match.range.start.line === match.range.end.line) {\n // Both single line\n return (\n line === match.range.start.line &&\n !(endCol <= match.range.start.column || startCol >= match.range.end.column)\n )\n } else {\n // Multi-line match, single-line SCIP\n if (line < match.range.start.line || line > match.range.end.line) return false\n if (line === match.range.start.line && endCol <= match.range.start.column) return false\n if (line === match.range.end.line && startCol >= match.range.end.column) return false\n return true\n }\n } else if (scipRange.length === 4) {\n const [startLine, _startCol, endLine, _endCol] = scipRange\n // Both multi-line or one multi-line\n if (endLine < match.range.start.line || startLine > match.range.end.line) return false\n return true\n }\n return false\n }\n\n /**\n * Check if SCIP range is fully inside the match span\n */\n private rangeFullyInside(scipRange: number[], match: Match): boolean {\n if (scipRange.length === 3) {\n const [line, startCol, endCol] = scipRange\n if (line < match.range.start.line || line > match.range.end.line) return false\n if (line === match.range.start.line && startCol < match.range.start.column) return false\n if (line === match.range.end.line && endCol > match.range.end.column) return false\n return true\n } else if (scipRange.length === 4) {\n const [startLine, startCol, endLine, endCol] = scipRange\n if (startLine < match.range.start.line) return false\n if (endLine > match.range.end.line) return false\n if (startLine === match.range.start.line && startCol < match.range.start.column) return false\n if (endLine === match.range.end.line && endCol > match.range.end.column) return false\n return true\n }\n return false\n }\n\n /**\n * Extract class and method names from SCIP symbol\n * e.g., \"scip-typescript npm @wispbit/server 1.0.0 src/services/`OrganizationService`#updateViolationCounts().\"\n * returns { className: \"OrganizationService\", methodName: \"updateViolationCounts\" }\n *\n * For standalone functions without a class:\n * e.g., \"scip-typescript npm @wispbit/server 1.0.0 src/utils/helper().\"\n * returns { className: null, methodName: \"helper\" }\n */\n private extractSymbolNames(symbol: string): {\n className: string | null\n methodName: string | null\n } {\n // SCIP symbols have format like:\n // - Class method: ...`ClassName`#methodName().\n // - Standalone function: ...functionName().\n\n // Try to extract class#method pattern\n const classMethodMatch = symbol.match(/`([^`]+)`#([^#./`(]+)(?:\\(\\))?[.`]*$/)\n if (classMethodMatch) {\n return {\n className: classMethodMatch[1],\n methodName: classMethodMatch[2],\n }\n }\n\n // Try to extract just method/function name (no class)\n const methodMatch = symbol.match(/([^#./`(]+)(?:\\(\\))?[.`]*$/)\n if (methodMatch) {\n return {\n className: null,\n methodName: methodMatch[1],\n }\n }\n\n return { className: null, methodName: null }\n }\n\n /**\n * Find definition for a symbol across all documents\n */\n private async findDefinitionForSymbol(\n symbol: string,\n documents: scip.Document[]\n ): Promise<Match | null> {\n for (const document of documents) {\n for (const occ of document.occurrences) {\n if (occ.symbol === symbol && occ.symbol_roles === scip.SymbolRole.Definition) {\n const range = occ.range ?? []\n // For 3-element ranges: [line, startCol, endCol]\n // For 4-element ranges: [startLine, startCol, endLine, endCol]\n const startLine = range[0] ?? 0\n const startColumn = range[1] ?? 0\n const endLine = range.length === 4 ? range[2] : startLine\n const endColumn = range.length === 4 ? range[3] : range[2] ?? startColumn\n\n const text = await readTextAtRange(\n this.environment.getWorkspaceRoot(),\n document.relative_path,\n {\n start: { line: startLine, column: startColumn },\n end: { line: endLine, column: endColumn },\n }\n )\n\n return {\n language: this.language,\n filePath: document.relative_path,\n range: {\n start: { line: startLine, column: startColumn },\n end: { line: endLine, column: endColumn },\n },\n symbol,\n text,\n }\n }\n }\n }\n\n return null\n }\n\n /**\n * Find all references for a symbol across all documents\n */\n private async findReferencesForSymbol(\n symbol: string,\n documents: scip.Document[]\n ): Promise<Match[]> {\n const references: Match[] = []\n\n for (const document of documents) {\n for (const occ of document.occurrences) {\n // Match all occurrences of this symbol (excluding definitions)\n if (occ.symbol === symbol && occ.symbol_roles !== scip.SymbolRole.Definition) {\n const range = occ.range ?? []\n // For 3-element ranges: [line, startCol, endCol]\n // For 4-element ranges: [startLine, startCol, endLine, endCol]\n const startLine = range[0] ?? 0\n const startColumn = range[1] ?? 0\n const endLine = range.length === 4 ? range[2] : startLine\n const endColumn = range.length === 4 ? range[3] : range[2] ?? startColumn\n\n const text = await readTextAtRange(\n this.environment.getWorkspaceRoot(),\n document.relative_path,\n {\n start: { line: startLine, column: startColumn },\n end: { line: endLine, column: endColumn },\n }\n )\n\n references.push({\n language: this.language,\n filePath: document.relative_path,\n range: {\n start: { line: startLine, column: startColumn },\n end: { line: endLine, column: endColumn },\n },\n symbol,\n text,\n })\n }\n }\n }\n\n return references\n }\n\n /**\n * Load SCIP index from the configured path\n */\n async loadIndex(): Promise<void> {\n const buffer = await this.storage.readIndex(this.language, `index.scip`)\n if (!buffer) {\n throw new Error(`Index not found for language: ${this.language}`)\n }\n this.scipIndex = this.parseIndex(new Uint8Array(buffer))\n }\n\n /**\n * Parse a SCIP index from bytes\n */\n private parseIndex(buffer: Uint8Array): scip.Index {\n return scip.Index.deserialize(buffer)\n }\n}\n", "import type { Environment } from \"powerlint/environment/Environment\"\nimport type { Language } from \"powerlint/languages\"\nimport { AstGrepAstProvider } from \"powerlint/providers/AstGrepAstProvider\"\nimport { ScipIntelligenceProvider } from \"powerlint/providers/ScipIntelligenceProvider\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { Match } from \"powerlint/types\"\n\n/**\n * Provider interface for AST-based code operations\n */\nexport interface AstProvider {\n /**\n * Find all matches based on the provider's matching strategy\n * @param filePaths File paths to search in\n * @param schema The provider-specific schema (RuleStep config without the \"type\" field)\n * @returns Array of matches found\n */\n findMatches(filePaths: string[], schema: Record<string, any>): Promise<Match[]>\n\n /**\n * Expand a match to its enclosing function, method, or class definition\n * @param match The match to expand\n * @returns The expanded match with full function/class body, or null if not found\n */\n expandMatch(match: Match): Promise<Match | null>\n}\n\n/**\n * Provider interface for code intelligence features (definitions, references)\n * Providers should filter out external symbols internally by default\n */\nexport interface IntelligenceProvider {\n /**\n * Find all definitions for a given match\n * @param match The match to find definitions for\n * @returns Array of matches representing definition locations\n */\n findDefinitions(match: Match): Promise<Match[]>\n\n /**\n * Find all references for a given match\n * @param match The match to find references for\n * @returns Array of matches representing reference locations\n */\n findReferences(match: Match): Promise<Match[]>\n}\n\n/**\n * Error thrown when a language backend method is not supported\n */\nexport class LanguageBackendNotSupportedError extends Error {\n constructor(methodName: string, reason: string) {\n super(`${methodName} is not supported: ${reason}`)\n this.name = \"LanguageBackendNotSupportedError\"\n }\n}\n\n/**\n * Language backend that delegates to various providers\n * Manages providers for pattern matching, definitions, references, etc.\n */\nexport class LanguageBackend {\n private astProvider?: AstProvider\n private intelligenceProvider?: IntelligenceProvider\n private language: Language\n\n constructor(environment: Environment, language: Language, eventEmitter?: ExecutionEventEmitter) {\n this.language = language\n // Set up providers based on language\n this.astProvider = new AstGrepAstProvider(environment, language)\n this.intelligenceProvider = new ScipIntelligenceProvider(environment, language, eventEmitter)\n }\n\n /**\n * Find all matches based on the AST provider\n */\n async findMatches(filePaths: string[], schema: Record<string, any>): Promise<Match[]> {\n if (!this.astProvider) {\n throw new LanguageBackendNotSupportedError(\n \"findMatches\",\n \"no AST provider configured for this language\"\n )\n }\n return await this.astProvider.findMatches(filePaths, schema)\n }\n\n /**\n * Find all definitions for a given match\n */\n async findDefinitions(match: Match): Promise<Match[]> {\n if (!this.intelligenceProvider) {\n throw new LanguageBackendNotSupportedError(\n \"findDefinitions\",\n \"no intelligence provider configured for this language\"\n )\n }\n return await this.intelligenceProvider.findDefinitions(match)\n }\n\n /**\n * Find all references for a given match\n */\n async findReferences(match: Match): Promise<Match[]> {\n if (!this.intelligenceProvider) {\n throw new LanguageBackendNotSupportedError(\n \"findReferences\",\n \"no intelligence provider configured for this language\"\n )\n }\n return await this.intelligenceProvider.findReferences(match)\n }\n\n /**\n * Expand a match to its enclosing function, method, or class definition\n * Useful for expanding a definition point (e.g., method name) to the full body\n */\n async expandMatch(match: Match): Promise<Match | null> {\n if (!this.astProvider) {\n throw new LanguageBackendNotSupportedError(\n \"expandMatch\",\n \"no AST provider configured for this language\"\n )\n }\n return await this.astProvider.expandMatch(match)\n }\n}\n", "import path from \"path\"\n\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport type { Language } from \"powerlint/languages\"\nimport { getLanguageFromFilePath } from \"powerlint/languages\"\nimport { LanguageBackend } from \"powerlint/providers/LanguageBackend\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { Match } from \"powerlint/types\"\n\nexport interface FindMatchesResult {\n matches: Match[]\n totalMatches: number\n executionTime: number\n}\n\nexport class FindMatchesStep {\n private environment: Environment\n private eventEmitter?: ExecutionEventEmitter\n\n constructor(environment: Environment, eventEmitter?: ExecutionEventEmitter) {\n this.environment = environment\n this.eventEmitter = eventEmitter\n }\n\n /**\n * Execute pattern matching on files\n * @param schema - The matching schema (rule, constraints, etc.) - provider-specific\n * @param language - The language to use for pattern matching\n * @param context - Context containing filePaths and optional previousMatches to filter against\n */\n async execute(\n schema: Record<string, any>,\n language: Language,\n context: { filePaths: string[]; previousMatches?: Match[] }\n ): Promise<FindMatchesResult> {\n const startTime = Date.now()\n\n // Filter file paths to only include files that match the specified language\n const languageFilteredPaths = context.filePaths.filter((filePath) => {\n const fileLanguage = getLanguageFromFilePath(filePath)\n return fileLanguage === language\n })\n\n // Create language backend with the specified language\n const backend = new LanguageBackend(this.environment, language, this.eventEmitter)\n\n // Find matches using the backend with filtered file paths\n const allMatches = await backend.findMatches(languageFilteredPaths, schema)\n\n // Add language to all matches and validate paths\n const matchesWithLanguage = allMatches.map((match) => {\n if (path.isAbsolute(match.filePath)) {\n throw new Error(\n `Match provider returned absolute path: ${match.filePath}. All file paths must be relative to workspace root.`\n )\n }\n return {\n ...match,\n language,\n }\n })\n\n // If previousMatches are provided, filter against their ranges\n let filteredMatches =\n context.previousMatches && context.previousMatches.length > 0\n ? this.filterMatchesByRanges(matchesWithLanguage, context.previousMatches, language)\n : matchesWithLanguage\n\n // Remove duplicate overlapping matches, keeping only the largest ones\n filteredMatches = this.deduplicateMatches(filteredMatches)\n\n const executionTime = Date.now() - startTime\n\n return {\n matches: filteredMatches,\n totalMatches: filteredMatches.length,\n executionTime,\n }\n }\n\n /**\n * Filter matches to only include those within the ranges of previous matches\n * A match is included if it falls within any of the previous match ranges\n * The source is propagated from the previous match\n */\n private filterMatchesByRanges(\n matches: Match[],\n previousMatches: Match[],\n _language: Language\n ): Match[] {\n const result: Match[] = []\n\n for (const match of matches) {\n // Find the previous match that contains this match\n const containingMatch = previousMatches.find((prevMatch) =>\n this.isMatchInRange(match, prevMatch)\n )\n\n if (!containingMatch) {\n continue\n }\n\n // Build source chain by extending the previous match's source\n const source: Omit<Match, \"source\">[] = [\n ...(containingMatch.source || []),\n {\n filePath: containingMatch.filePath,\n text: containingMatch.text,\n range: containingMatch.range,\n symbol: containingMatch.symbol,\n language: containingMatch.language,\n },\n ]\n\n result.push({\n ...match,\n source,\n })\n }\n\n return result\n }\n\n /**\n * Check if a match falls within the range of another match\n * Both matches must be in the same file\n */\n private isMatchInRange(match: Match, rangeMatch: Match): boolean {\n // Must be in the same file\n if (match.filePath !== rangeMatch.filePath) {\n return false\n }\n\n const matchStart = match.range.start\n const matchEnd = match.range.end\n const rangeStart = rangeMatch.range.start\n const rangeEnd = rangeMatch.range.end\n\n // Check if match start is after or at range start\n const startInRange =\n matchStart.line > rangeStart.line ||\n (matchStart.line === rangeStart.line && matchStart.column >= rangeStart.column)\n\n // Check if match end is before or at range end\n const endInRange =\n matchEnd.line < rangeEnd.line ||\n (matchEnd.line === rangeEnd.line && matchEnd.column <= rangeEnd.column)\n\n return startInRange && endInRange\n }\n\n /**\n * Remove duplicate matches by keeping only the largest overlapping match.\n * If multiple matches overlap (one is contained within another), keep only the largest one.\n */\n private deduplicateMatches(matches: Match[]): Match[] {\n if (matches.length <= 1) {\n return matches\n }\n\n const result: Match[] = []\n\n for (const match of matches) {\n // Check if this match is contained by any other match\n const isContainedByAnother = matches.some((otherMatch) => {\n if (match === otherMatch) return false\n // Check if match is completely contained within otherMatch\n return this.isMatchInRange(match, otherMatch)\n })\n\n // Only keep matches that aren't contained by others\n if (!isContainedByAnother) {\n result.push(match)\n }\n }\n\n return result\n }\n}\n", "import path from \"path\"\n\nimport { minimatch } from \"minimatch\"\n\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport type { Language } from \"powerlint/languages\"\nimport { LanguageBackend } from \"powerlint/providers/LanguageBackend\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { Match } from \"powerlint/types\"\n\n/** Exact or regex name matching */\ninterface NameSpec {\n equals?: string\n anyOf?: string[]\n regex?: string\n}\n\n/** File matcher (path OR glob OR regex) */\ninterface FileMatch {\n path?: string\n glob?: string\n regex?: string\n}\n\n/** Method filter */\ninterface MethodSelector {\n file?: FileMatch\n name: NameSpec\n}\n\n/** Class filter */\ninterface ClassSelector {\n file?: FileMatch\n name: NameSpec\n method?: MethodSelector\n}\n\n/** Top-level function filter */\ninterface FunctionSelector {\n file?: FileMatch\n name: NameSpec\n}\n\n/** Definition-side predicates (post-hop) */\ninterface DefinitionPredicate {\n file?: FileMatch\n class?: ClassSelector\n method?: MethodSelector\n function?: FunctionSelector\n}\n\n/** Boolean combinators for definition filters */\ninterface DefinitionFilter extends Partial<DefinitionPredicate> {\n all?: DefinitionFilter[]\n any?: DefinitionFilter[]\n not?: DefinitionFilter\n}\n\ninterface MatchWithDepth extends Match {\n depth: number\n /** The source match that led to this definition */\n sourceMatch?: Match\n}\n\nexport interface GotoDefinitionResult {\n definitions: Match[]\n totalDefinitions: number\n executionTime: number\n}\n\nexport interface GotoDefinitionOptions {\n /** Filter for which definitions to include (default: all non-external) */\n where?: DefinitionFilter\n}\n\nexport class GotoDefinitionStep {\n private readonly maxDepth: number = 1\n private environment: Environment\n private eventEmitter?: ExecutionEventEmitter\n\n constructor(environment: Environment, eventEmitter?: ExecutionEventEmitter) {\n this.environment = environment\n this.eventEmitter = eventEmitter || new ExecutionEventEmitter()\n }\n\n /**\n * Execute goto-definition on matches\n */\n async execute(\n matches: Match[],\n language: Language,\n options: GotoDefinitionOptions = {}\n ): Promise<GotoDefinitionResult> {\n const startTime = Date.now()\n\n // Create language backend with the specified language\n const backend = new LanguageBackend(this.environment, language, this.eventEmitter)\n\n // Follow definitions up to maxDepth\n const definitions = await this.followDefinitions(\n matches,\n backend,\n this.maxDepth,\n options.where,\n language\n )\n\n const executionTime = Date.now() - startTime\n\n // Flatten MatchWithDepth to Match[] and build source chains\n const flattenedDefinitions: Match[] = definitions.map((def) => {\n const { depth: _depth, sourceMatch, ...match } = def\n\n // Build source chain from the sourceMatch\n const source = sourceMatch\n ? [\n {\n filePath: sourceMatch.filePath,\n text: sourceMatch.text,\n range: sourceMatch.range,\n symbol: sourceMatch.symbol,\n language: sourceMatch.language,\n },\n ...(sourceMatch.source || []),\n ]\n : []\n\n return {\n ...match,\n source,\n }\n })\n\n return {\n definitions: flattenedDefinitions,\n totalDefinitions: flattenedDefinitions.length,\n executionTime,\n }\n }\n\n /**\n * Follow definitions up to maxDepth\n */\n private async followDefinitions(\n matches: Match[],\n backend: LanguageBackend,\n maxDepth: number,\n filter: DefinitionFilter | undefined,\n language: Language\n ): Promise<MatchWithDepth[]> {\n const definitions: MatchWithDepth[] = []\n const visited = new Set<string>()\n\n for (const match of matches) {\n await this.followDefinitionsRecursive(\n match,\n backend,\n 0,\n maxDepth,\n filter,\n definitions,\n visited,\n match,\n language\n )\n }\n\n return definitions\n }\n\n /**\n * Recursively follow definitions\n */\n private async followDefinitionsRecursive(\n match: Match,\n backend: LanguageBackend,\n currentDepth: number,\n maxDepth: number,\n filter: DefinitionFilter | undefined,\n definitions: MatchWithDepth[],\n visited: Set<string>,\n sourceMatch: Match | undefined,\n language: Language\n ): Promise<void> {\n if (currentDepth >= maxDepth) {\n return\n }\n\n // Create a unique key for this match\n const key = `${match.filePath}:${match.range.start.line}:${match.range.start.column}:${match.symbol ?? \"\"}`\n if (visited.has(key)) {\n return\n }\n visited.add(key)\n\n // Find definitions using the backend (provider filters external symbols)\n const backendDefinitions = await backend.findDefinitions(match)\n\n for (const backendDef of backendDefinitions) {\n // Expand definition to full function/method/class body if possible\n const expandedDef = (await backend.expandMatch(backendDef)) ?? backendDef\n\n // Convert to MatchWithDepth and track the source match, and add language\n const defResult: MatchWithDepth = {\n ...expandedDef,\n language,\n depth: currentDepth,\n sourceMatch: sourceMatch || match,\n }\n\n // Check if definition matches filter\n if (filter && !this.matchesDefinitionFilter(defResult, filter)) {\n continue\n }\n\n definitions.push(defResult)\n\n // Recursively follow definitions (use original backendDef for navigation, not expanded)\n if (currentDepth + 1 < maxDepth) {\n await this.followDefinitionsRecursive(\n backendDef,\n backend,\n currentDepth + 1,\n maxDepth,\n filter,\n definitions,\n visited,\n sourceMatch || match,\n language\n )\n }\n }\n }\n\n /**\n * Check if a definition matches a filter\n */\n private matchesDefinitionFilter(def: MatchWithDepth, filter: DefinitionFilter): boolean {\n // Handle boolean combinators\n if (filter.all) {\n return filter.all.every((f) => this.matchesDefinitionFilter(def, f))\n }\n if (filter.any) {\n return filter.any.some((f) => this.matchesDefinitionFilter(def, f))\n }\n if (filter.not) {\n return !this.matchesDefinitionFilter(def, filter.not)\n }\n\n // Handle predicates\n if (filter.file) {\n if (!this.matchesFileSpec((def as Match).filePath, filter.file)) {\n return false\n }\n }\n\n if (filter.method?.name) {\n const symbol = (def as Match).symbol\n if (!symbol || !this.matchesNameSpec(symbol, filter.method.name)) {\n return false\n }\n }\n\n if (filter.function?.name) {\n const symbol = (def as Match).symbol\n if (!symbol || !this.matchesNameSpec(symbol, filter.function.name)) {\n return false\n }\n }\n\n if (filter.class?.name) {\n // Would need more context to determine if symbol is in a class\n // This is a placeholder\n }\n\n return true\n }\n\n /**\n * Check if a name matches a name specification\n */\n private matchesNameSpec(name: string, spec: NameSpec): boolean {\n if (spec.equals) {\n return name === spec.equals\n }\n if (spec.anyOf) {\n return spec.anyOf.includes(name)\n }\n if (spec.regex) {\n const regex = new RegExp(spec.regex)\n return regex.test(name)\n }\n return true\n }\n\n /**\n * Check if a file path matches a file specification\n */\n private matchesFileSpec(filePath: string, spec: FileMatch): boolean {\n const relativePath = path.relative(this.environment.getWorkspaceRoot(), filePath)\n\n if (spec.path) {\n return relativePath === spec.path\n }\n if (spec.glob) {\n return minimatch(relativePath, spec.glob)\n }\n if (spec.regex) {\n const regex = new RegExp(spec.regex)\n return regex.test(relativePath)\n }\n return true\n }\n}\n", "import type { Config } from \"powerlint/environment/Config\"\nimport type {\n ViolationValidationProvider,\n ViolationValidationParams,\n ViolationValidationResult,\n} from \"powerlint/providers/ViolationValidationProvider\"\nimport type { Match } from \"powerlint/types\"\nimport { hashString } from \"powerlint/utils/hashString\"\n\n/**\n * Violation validation provider that uses Wispbit's specialized validation endpoint\n */\nexport class WispbitViolationValidationProvider implements ViolationValidationProvider {\n private config: Config\n\n constructor(config: Config) {\n this.config = config\n }\n\n async validateViolations(\n params: ViolationValidationParams\n ): Promise<ViolationValidationResult[]> {\n // Generate match IDs for tracking\n const matchesWithIds = params.matches.map((match) => ({\n match,\n matchId: this.generateMatchId(match),\n }))\n\n const baseUrl = this.config.getBaseUrl()\n const apiKey = this.config.getApiKey()!\n\n const response = await fetch(`${baseUrl}/plv1/validate-violation`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n rule: params.rule,\n matches: matchesWithIds.map(({ match, matchId }) => ({\n matchId,\n filePath: match.filePath,\n range: match.range,\n text: match.text,\n language: match.language,\n symbol: match.symbol,\n source: match.source,\n })),\n powerlint_version: this.config.getLocalVersion(),\n schema_version: this.config.getSchemaVersion(),\n }),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(\n `Wispbit validation failed: ${response.status} ${response.statusText} - ${errorText}`\n )\n }\n\n const result = await response.json()\n\n // Ensure we have results for all matches\n const results: ViolationValidationResult[] = []\n for (const { matchId } of matchesWithIds) {\n const validationResult = result.results?.find((r: any) => r.matchId === matchId)\n\n results.push({\n matchId,\n isViolation: Boolean(validationResult?.isViolation),\n reason: String(validationResult?.reason || \"No violation detected\"),\n confidence:\n typeof validationResult?.confidence === \"number\" ? validationResult.confidence : 1.0,\n })\n }\n\n return results\n }\n\n /**\n * Generate a unique ID for a single match\n */\n private generateMatchId(match: Match): string {\n const matchData = {\n filePath: match.filePath,\n startLine: match.range.start.line,\n startColumn: match.range.start.column || 0,\n endLine: match.range.end.line,\n endColumn: match.range.end.column || 0,\n text: match.text,\n }\n return hashString(JSON.stringify(matchData)).substring(0, 16)\n }\n}\n", "import { Config } from \"powerlint/environment/Config\"\nimport type { Environment } from \"powerlint/environment/Environment\"\nimport { Storage } from \"powerlint/environment/Storage\"\nimport type { ViolationValidationParams } from \"powerlint/providers/ViolationValidationProvider\"\nimport { WispbitViolationValidationProvider } from \"powerlint/providers/WispbitViolationValidationProvider\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport type { Match } from \"powerlint/types\"\nimport { Rule } from \"powerlint/types\"\nimport { hashString } from \"powerlint/utils/hashString\"\n\nexport interface LLMStepResult {\n matches: Match[]\n executionTime: number\n}\n\nexport type LLMStepExecutionResult = LLMStepResult\n\nexport interface LLMMatchDecision {\n matchId: string\n isViolation: boolean\n confidence: number\n reason: string\n}\n\nexport class LLMStep {\n private environment: Environment\n private eventEmitter: ExecutionEventEmitter\n private config: Config\n private storage: Storage\n constructor(config: Config, environment: Environment, eventEmitter?: ExecutionEventEmitter) {\n this.environment = environment\n this.eventEmitter = eventEmitter || new ExecutionEventEmitter()\n this.config = config\n this.storage = new Storage(environment)\n }\n\n /**\n * Generate a unique ID for a single match\n * Hash is based on filePath + range + text\n */\n private generateMatchId(match: Match): string {\n const matchData = {\n filePath: match.filePath,\n startLine: match.range.start.line,\n startColumn: match.range.start.column || 0,\n endLine: match.range.end.line,\n endColumn: match.range.end.column || 0,\n text: match.text,\n }\n return hashString(JSON.stringify(matchData)).substring(0, 16)\n }\n\n /**\n * Generate a hash for a prompt string\n */\n private hashPrompt(prompt: string): string {\n return hashString(prompt)\n }\n\n /**\n * Generate a cache key for a single match LLM validation\n */\n private generateMatchCacheKey(matchId: string, promptHash: string): string {\n return `match_${matchId}_prompt_${promptHash}.json`\n }\n\n /**\n * Execute the actual LLM validation for uncached matches\n * @param config - LLM step configuration (contains provider and model)\n * @param uncachedMatches - Matches that need LLM evaluation\n * @param promptContent - The loaded prompt content\n */\n private async executeLLMValidation(rule: Rule, uncachedMatches: Match[]): Promise<LLMStepResult> {\n const llmStartTime = Date.now()\n\n // Generate prompt hash for cache keys\n const promptHash = this.hashPrompt(rule.prompt)\n\n // Create validation provider (factory handles choosing the right provider)\n const validationProvider = new WispbitViolationValidationProvider(this.config)\n\n const validationParams: ViolationValidationParams = {\n rule,\n matches: uncachedMatches,\n }\n\n // Emit start event\n this.eventEmitter.startLLMValidation(rule.id, uncachedMatches.length)\n\n // Validate using the provider\n const validationResults = await validationProvider.validateViolations(validationParams)\n\n // Process results and cache decisions\n const newViolationMatches: Match[] = []\n for (const result of validationResults) {\n const originalMatch = uncachedMatches.find(\n (match) => this.generateMatchId(match) === result.matchId\n )\n if (originalMatch && result.isViolation) {\n newViolationMatches.push({\n ...originalMatch,\n metadata: {\n fromCache: false,\n llmValidation: {\n isViolation: true,\n confidence: result.confidence,\n reason: result.reason,\n },\n },\n })\n }\n\n // Cache the decision\n const cacheKey = this.generateMatchCacheKey(result.matchId, promptHash)\n const decision: LLMMatchDecision = {\n matchId: result.matchId,\n isViolation: result.isViolation,\n confidence: result.confidence,\n reason: result.reason,\n }\n await this.storage.saveCache(rule.id, cacheKey, decision)\n }\n\n // Emit completion event (token usage will be 0 for wispbit, actual for LLM providers)\n this.eventEmitter.completeLLMValidation(\n rule.id,\n 0, // Token usage is handled internally by the validation providers\n Date.now() - llmStartTime,\n newViolationMatches.length,\n false\n )\n\n return {\n matches: newViolationMatches,\n executionTime: Date.now() - llmStartTime,\n }\n }\n\n /**\n * Execute the LLM step - always runs LLM validation immediately\n * @param config - LLM step configuration\n * @param previousMatches - Matches from previous steps to be judged by LLM\n */\n async execute(rule: Rule, previousMatches: Match[]): Promise<LLMStepExecutionResult> {\n const startTime = Date.now()\n\n // Use step config to override environment config\n // Generate prompt hash for cache keys\n const promptHash = this.hashPrompt(rule.prompt)\n\n // Check cache for each match individually\n const cachedMatches: Match[] = []\n const uncachedMatches: Match[] = []\n\n for (const match of previousMatches) {\n const matchId = this.generateMatchId(match)\n const cacheKey = this.generateMatchCacheKey(matchId, promptHash)\n\n const cachedDecision = await this.storage.readCache<LLMMatchDecision>(rule.id, cacheKey)\n\n if (cachedDecision) {\n // We have a cached decision for this match\n if (cachedDecision.isViolation) {\n // This match is a cached violation, include it in results\n cachedMatches.push({\n ...match,\n metadata: {\n fromCache: true,\n llmValidation: {\n isViolation: cachedDecision.isViolation,\n confidence: cachedDecision.confidence,\n reason: cachedDecision.reason,\n },\n },\n })\n }\n // If it's not a violation, we filter it out (don't add to results)\n } else {\n // No cached decision, needs LLM evaluation\n uncachedMatches.push(match)\n }\n }\n\n // If we have uncached matches, execute LLM validation immediately\n let newViolationMatches: Match[] = []\n if (uncachedMatches.length > 0) {\n const llmResult = await this.executeLLMValidation(rule, uncachedMatches)\n newViolationMatches = llmResult.matches\n }\n\n // If we have only cached matches, emit completion event\n if (uncachedMatches.length === 0) {\n this.eventEmitter.completeLLMValidation(\n rule.id,\n 0, // No tokens for cached result\n Date.now() - startTime,\n cachedMatches.length,\n true // fromCache = true\n )\n }\n\n // Combine cached and new violation matches\n const allMatches = [...cachedMatches, ...newViolationMatches]\n\n return {\n matches: allMatches,\n executionTime: Date.now() - startTime,\n }\n }\n}\n", "import { Config } from \"powerlint/environment/Config\"\nimport { Environment } from \"powerlint/environment/Environment\"\nimport { Language } from \"powerlint/languages\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { FileExecutionContext, ExecutionMode } from \"powerlint/steps/FileExecutionContext\"\nimport { FileFilterStep } from \"powerlint/steps/FileFilterStep\"\nimport { FindMatchesStep } from \"powerlint/steps/FindMatchesStep\"\nimport { GotoDefinitionStep } from \"powerlint/steps/GotoDefinitionStep\"\nimport { LLMStep } from \"powerlint/steps/LLMStep\"\nimport { RuleStep, Match, Rule } from \"powerlint/types\"\n\nexport interface RuleExecutionResult {\n ruleId: string\n matches: Match[]\n}\n\nexport interface RuleExecutionOptions {\n mode: ExecutionMode\n filePath?: string\n baseSha?: string\n}\n\nexport class RuleExecutor {\n private fileFilterStep: FileFilterStep\n private findMatchesStep: FindMatchesStep\n private gotoDefinitionStep: GotoDefinitionStep\n private llmStep: LLMStep\n private environment: Environment\n private executionContext?: FileExecutionContext\n private currentMode?: ExecutionMode\n private eventEmitter: ExecutionEventEmitter\n private config: Config\n\n constructor(config: Config, environment: Environment, eventEmitter?: ExecutionEventEmitter) {\n this.environment = environment\n this.eventEmitter = eventEmitter || new ExecutionEventEmitter()\n this.config = config\n this.fileFilterStep = new FileFilterStep(this.environment)\n this.findMatchesStep = new FindMatchesStep(this.environment, this.eventEmitter)\n this.gotoDefinitionStep = new GotoDefinitionStep(this.environment, this.eventEmitter)\n this.llmStep = new LLMStep(this.config, this.environment, this.eventEmitter)\n }\n\n /**\n * Execute a single step\n */\n private async executeStep(\n rule: Rule,\n stepName: string,\n stepConfig: RuleStep,\n filePaths: string[],\n matches: Match[],\n options?: RuleExecutionOptions\n ): Promise<{ filePaths?: string[]; matches?: Match[] }> {\n const stepType = stepConfig.type\n\n if (stepType === \"ast-grep\") {\n // Execute ast-grep step\n // Extract language and pass remaining config as schema\n const { type: _type, language, ...schema } = stepConfig\n\n const stepResult = await this.findMatchesStep.execute(schema, language as Language, {\n filePaths,\n previousMatches: matches,\n })\n\n return {\n matches: stepResult.matches,\n }\n }\n\n if (stepType === \"step-group\") {\n // Execute step-group: run all steps and combine their results\n let allMatches: Match[] = []\n\n for (let i = 0; i < stepConfig.steps.length; i++) {\n const subStep = stepConfig.steps[i]\n const subStepName = `${stepName}[${i}]`\n const subResult = await this.executeStep(\n rule,\n subStepName,\n subStep,\n filePaths,\n matches,\n options\n )\n\n if (subResult.matches) {\n allMatches = allMatches.concat(subResult.matches)\n }\n }\n\n return {\n matches: allMatches,\n }\n }\n\n if (stepType === \"file-filter\") {\n // Execute file filter step with include/ignore and conditions\n const stepResult = await this.fileFilterStep.execute(filePaths, {\n include: stepConfig.include,\n ignore: stepConfig.ignore,\n conditions: stepConfig.conditions,\n })\n\n return {\n filePaths: stepResult.filteredPaths,\n }\n }\n\n if (stepType === \"goto-definition\") {\n // Nothing to resolve for definitions, skip\n if (matches.length === 0) {\n return {\n matches: [],\n }\n }\n\n // Extract language from step config\n const { language } = stepConfig\n\n // Filter previous matches to only include those matching the language\n const matchesForLanguage = matches.filter((m) => m.language === language)\n\n if (matchesForLanguage.length === 0) {\n // No matches for this language, return empty\n return {\n matches: [],\n }\n }\n\n const stepResult = await this.gotoDefinitionStep.execute(matchesForLanguage, language, {\n where: stepConfig.where,\n })\n\n const definitionFilePaths = [...new Set(stepResult.definitions.map((d) => d.filePath))]\n\n return {\n filePaths: definitionFilePaths,\n matches: stepResult.definitions,\n }\n }\n\n if (stepType === \"llm\") {\n // Execute LLM step directly without deferring\n if (matches.length === 0) {\n return {\n matches: [],\n }\n }\n\n const llmResult = await this.llmStep.execute(rule, matches)\n\n return {\n matches: llmResult.matches,\n }\n }\n\n throw new Error(`Unknown step type: ${stepType}`)\n }\n\n /**\n * Execute all steps in multiple rule configurations\n */\n async execute(rules: Rule[], options: RuleExecutionOptions): Promise<RuleExecutionResult[]> {\n // Validate execution mode consistency\n if (this.currentMode && this.currentMode !== options.mode) {\n throw new Error(`Execution mode mismatch: expected ${this.currentMode}, got ${options.mode}`)\n }\n\n // Initialize execution context if not exists or mode changed\n if (!this.executionContext || this.currentMode !== options.mode) {\n this.executionContext = await FileExecutionContext.initialize(\n this.config,\n this.environment,\n options.mode,\n this.eventEmitter,\n options.filePath,\n options.baseSha\n )\n this.currentMode = options.mode\n }\n\n // Emit start event\n this.eventEmitter.startRules(rules.length)\n\n // Execute each rule individually (LLM steps get saved as promises)\n const results: RuleExecutionResult[] = []\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i]\n const ruleId = rule.id\n\n let isLlm = false\n\n for (const stepWithId of rule.config.steps) {\n if (stepWithId.step.type === \"llm\") {\n isLlm = true\n break\n }\n }\n\n // Emit progress event\n this.eventEmitter.progressRule(i + 1, rules.length, ruleId, isLlm)\n // Use the rule configuration directly\n const ruleConfig = rule.config\n\n // Initialize local arrays from context\n let currentFilePaths = [...this.executionContext.filePaths]\n let currentMatches: Match[] = []\n\n // Execute steps sequentially\n for (const stepWithId of ruleConfig.steps) {\n const stepName = stepWithId.id\n const stepConfig = stepWithId.step\n\n // Emit step start event\n this.eventEmitter.startStep(ruleId, stepName, stepConfig.type, {\n filePaths: currentFilePaths,\n matches: currentMatches,\n })\n\n const stepStartTime = Date.now()\n const result = await this.executeStep(\n rule,\n stepName,\n stepConfig,\n currentFilePaths,\n currentMatches,\n options\n )\n const stepExecutionTime = Date.now() - stepStartTime\n\n // Emit step completion event\n this.eventEmitter.emit(\"step:complete\", {\n ruleId,\n stepName,\n stepType: stepConfig.type,\n outputs: result,\n executionTime: stepExecutionTime,\n })\n\n // Update local arrays with filtered results\n if (result.filePaths !== undefined) {\n currentFilePaths = this.executionContext.filterFiles(result.filePaths)\n // When file paths are filtered, also filter existing matches to only include those from the filtered files\n currentMatches = this.executionContext.filterMatchesByFilePaths(\n currentMatches,\n currentFilePaths\n )\n }\n\n if (result.matches !== undefined) {\n currentMatches = this.executionContext.filterMatches(result.matches)\n }\n\n // If no files left, stop execution\n if (currentFilePaths.length === 0) {\n break\n }\n }\n\n // Sort matches by filePath for consistent ordering\n const sortedMatches = currentMatches.sort((a, b) => a.filePath.localeCompare(b.filePath))\n\n results.push({\n ruleId,\n matches: sortedMatches,\n })\n }\n\n // Emit completion event\n const totalMatches = results.reduce((sum, result) => sum + result.matches.length, 0)\n this.eventEmitter.completeRules(rules.length, totalMatches)\n\n return results\n }\n}\n", "import { Language } from \"powerlint/languages\"\n\nexport type LLMProvider = \"wispbit\"\n\nexport class InvalidRuleFormatError extends Error {\n constructor(\n ruleId: string,\n message: string,\n public validationErrors?: string[]\n ) {\n super(`Invalid rule format in '${ruleId}': ${message}`)\n this.name = \"InvalidRuleFormatError\"\n }\n}\n\nexport interface RuleTestCaseFile {\n path: string\n content: string\n}\n\nexport interface RuleTestCase {\n it: string\n files: RuleTestCaseFile[]\n snapshot?: any[] // Optional snapshot data for this test case\n}\n\nexport interface RangePosition {\n line: number\n column?: number\n}\n\nexport interface RangeObject {\n start: RangePosition\n end: RangePosition\n}\n\nexport interface PatternObject {\n selector?: string\n context?: string\n strictness?: \"cst\" | \"smart\" | \"ast\" | \"relaxed\" | \"signature\"\n}\n\nexport type NthChild =\n | number\n | string\n | {\n position: number | string\n reverse?: boolean\n ofRule?: AstGrepRule\n }\n\nexport interface AstGrepRule {\n pattern?: string | PatternObject\n kind?: string\n regex?: string\n nthChild?: NthChild\n range?: RangeObject\n inside?: {\n stopBy?: \"neighbor\" | \"end\" | AstGrepRule\n field?: string\n } & AstGrepRule\n has?: {\n stopBy?: \"neighbor\" | \"end\" | AstGrepRule\n field?: string\n } & AstGrepRule\n precedes?: {\n stopBy?: \"neighbor\" | \"end\" | AstGrepRule\n } & AstGrepRule\n follows?: {\n stopBy?: \"neighbor\" | \"end\" | AstGrepRule\n } & AstGrepRule\n all?: AstGrepRule[]\n any?: AstGrepRule[]\n not?: AstGrepRule\n matches?: string\n}\n\nexport interface FactPredicate {\n fact: \"fs.siblingAny\" | \"fs.siblingExists\" | \"fs.pathMatches\" | \"fs.ancestorHas\"\n args?:\n | null\n | string\n | boolean\n | number\n | (string | number | boolean | object | any[] | null)[]\n | object\n equals?: boolean\n}\n\nexport interface WhereExpr {\n all?: FactPredicate[]\n any?: FactPredicate[]\n not?: FactPredicate[]\n}\n\nexport type FileFilterCondition =\n | { \"fs.siblingExists\": { filename: string } }\n | { \"fs.pathMatches\": { pattern: string } }\n | { \"fs.ancestorHas\": { filename: string } }\n | { \"fs.siblingAny\": { pattern: string } }\n\nexport interface FileFilterConditions {\n all?: FileFilterCondition[]\n any?: FileFilterCondition[]\n not?: FileFilterCondition[]\n}\n\nexport interface AstGrepStep {\n type: \"ast-grep\"\n language: Language\n rule: AstGrepRule\n constraints?: Record<string, AstGrepRule>\n}\n\nexport interface FileFilterStep {\n type: \"file-filter\"\n include?: string[]\n ignore?: string[]\n conditions?: FileFilterConditions\n}\n\nexport interface LLMStep {\n type: \"llm\"\n}\n\ninterface NameSpec {\n equals?: string\n anyOf?: string[]\n regex?: string\n}\n\ninterface FileMatch {\n path?: string\n glob?: string\n regex?: string\n}\n\ninterface MethodSelector {\n file?: FileMatch\n name: NameSpec\n}\n\ninterface ClassSelector {\n file?: FileMatch\n name: NameSpec\n method?: MethodSelector\n}\n\ninterface FunctionSelector {\n file?: FileMatch\n name: NameSpec\n}\n\ninterface DefinitionPredicateBase {\n file?: FileMatch\n class?: ClassSelector\n method?: MethodSelector\n function?: FunctionSelector\n}\n\ninterface DefinitionFilter {\n all?: DefinitionPredicateBase[]\n any?: DefinitionPredicateBase[]\n not?: DefinitionPredicateBase\n}\n\nexport interface GotoDefinitionStep {\n type: \"goto-definition\"\n language: Language\n where?: DefinitionFilter\n}\n\nexport interface StepGroupStep {\n type: \"step-group\"\n steps: (AstGrepStep | FileFilterStep | LLMStep | GotoDefinitionStep)[]\n}\n\nexport type RuleStep = AstGrepStep | FileFilterStep | LLMStep | GotoDefinitionStep | StepGroupStep\n\nexport interface MatchRange {\n start: { line: number; column: number }\n end: { line: number; column: number }\n}\n\nexport interface MatchSource {\n filePath: string\n text?: string\n range: MatchRange\n symbol?: string\n language: Language\n}\n\nexport interface Match {\n filePath: string\n text?: string\n range: MatchRange\n symbol?: string\n language: Language\n source?: MatchSource[]\n metadata?: {\n fromCache?: boolean\n llmValidation?: {\n isViolation: boolean\n confidence: number\n reason: string\n }\n }\n}\n\n// Rule configuration types\n\nexport interface RuleStepWithId {\n id: string\n step: RuleStep\n}\n\nexport interface RuleConfig {\n message: string\n severity: \"suggestion\" | \"violation\"\n steps: RuleStepWithId[]\n}\n\nexport interface Rule {\n id: string\n internalId: string\n config: RuleConfig\n prompt: string\n testCases: RuleTestCase[]\n}\n", "import { stripVTControlCharacters } from \"node:util\"\n\nimport chalk from \"chalk\"\nimport ora, { Ora } from \"ora\"\n\nimport { ScanResult } from \"powerlint/cli\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\n\n// Color constants\nexport const VIOLATION_COLOR = \"#ff6b35\"\nexport const SUGGESTION_COLOR = \"#4a90e2\"\nexport const SKIPPED_COLOR = \"#9b59b6\"\n\n// Brand color for consistent theming\nexport const BRAND_COLOR = \"#fbbf24\"\n\n/**\n * Format a rule ID as a clickable link with underline\n */\nfunction formatClickableRuleId(ruleId: string, internalId?: string): string {\n if (internalId) {\n // Make it underlined and clickable\n return chalk.underline.dim(\n `\\u001b]8;;https://app.wispbit.com/rules/${internalId}\\u001b\\\\${ruleId}\\u001b]8;;\\u001b\\\\`\n )\n }\n // Fallback to just dimmed text if no internalId\n return chalk.dim(ruleId)\n}\n\n// Line number box colors\nexport const LINE_NUMBER_BG_COLOR = \"#f8f8f8\"\nexport const LINE_NUMBER_TEXT_COLOR = \"#888888\"\n\n// Custom tentacle frames for branding with chalk coloring\nconst loadingFrames = [\n chalk.hex(BRAND_COLOR)(\"~(oo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(oO)~\"),\n chalk.hex(BRAND_COLOR)(\"~(Oo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(OO)~\"),\n chalk.hex(BRAND_COLOR)(\"~(\u25CFo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(o\u25CF)~\"),\n chalk.hex(BRAND_COLOR)(\"~(\u25C9o)~\"),\n chalk.hex(BRAND_COLOR)(\"~(o\u25C9)~\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(oo)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(oO)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(Oo)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(OO)/\"),\n chalk.hex(BRAND_COLOR)(\"~(Oo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(oO)~\"),\n chalk.hex(BRAND_COLOR)(\"~(\u25CEo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(o\u25CE)~\"),\n chalk.hex(BRAND_COLOR)(\"~(oo)~\"),\n chalk.hex(BRAND_COLOR)(\"~(OO)~\"),\n chalk.hex(BRAND_COLOR)(\"~(Oo)~\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(oo)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(oO)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(Oo)/\"),\n chalk.hex(BRAND_COLOR)(\"\\\\(OO)/\"),\n]\n\nexport interface LintSummary {\n totalRules: number\n violationCount: number\n suggestionCount: number\n totalMatches: number\n totalLLMCost: string\n totalLLMTokens: number\n executionMode?: {\n mode: \"check\" | \"diff\"\n filePath?: string\n baseCommit?: string\n headCommit?: string\n }\n executionTime?: number\n totalFiles?: number\n}\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Given a word and a count, append an s if count is not one.\n * @param {string} word A word in its singular form.\n * @param {number} count A number controlling whether word should be pluralized.\n * @returns {string} The original word with an s on the end if count is not one.\n */\nfunction pluralize(word: string, count: number): string {\n return count === 1 ? word : `${word}s`\n}\n\n/**\n * Text table utility function based on ESLint's implementation\n * @param {string[][]} rows Array of rows, each row is an array of strings\n * @param {object} opts Options object with align and stringLength properties\n * @returns {string} Formatted table as string\n */\nexport function textTable(\n rows: string[][],\n opts: {\n align?: string[]\n stringLength?: (str: string) => number\n } = {}\n): string {\n const hsep = \" \"\n const align = opts.align || []\n const stringLength = opts.stringLength || ((str: string) => stripVTControlCharacters(str).length)\n\n const sizes = rows.reduce((acc: number[], row) => {\n row.forEach((c, ix) => {\n const n = stringLength(c)\n\n if (!acc[ix] || n > acc[ix]) {\n acc[ix] = n\n }\n })\n return acc\n }, [])\n\n return rows\n .map((row) =>\n row\n .map((c, ix) => {\n const n = sizes[ix] - stringLength(c) || 0\n const s = Array(Math.max(n + 1, 1)).join(\" \")\n\n if (align[ix] === \"r\") {\n return s + c\n }\n\n return c + s\n })\n .join(hsep)\n .trimEnd()\n )\n .join(\"\\n\")\n}\n\nexport function printSummary(results: ScanResult[], summary: LintSummary): void {\n let output = \"\\n\"\n\n let violationCount = 0\n let suggestionCount = 0\n\n // Group results by rule instead of file\n const ruleResults = new Map<\n string,\n {\n message: string\n severity: \"violation\" | \"suggestion\" | \"skipped\"\n internalId?: string\n matches: Array<{\n filePath: string\n line: number\n column: number\n endLine?: number\n text?: string\n }>\n hasLlmValidation: boolean\n }\n >()\n\n results.forEach((result) => {\n if (result.matches.length === 0) {\n return\n }\n\n const ruleId = result.ruleId || \"unknown\"\n if (!ruleResults.has(ruleId)) {\n ruleResults.set(ruleId, {\n message: result.message,\n severity: result.severity,\n internalId: result.internalId,\n matches: [],\n hasLlmValidation: false,\n })\n }\n\n const ruleData = ruleResults.get(ruleId)!\n\n result.matches.forEach((match) => {\n ruleData.matches.push({\n filePath: match.filePath,\n line: match.range.start.line + 1,\n column: match.range.start.column + 1,\n endLine:\n match.range.end.line !== match.range.start.line ? match.range.end.line + 1 : undefined,\n text: match.text,\n })\n\n // Check if this match has LLM validation metadata\n if (match.metadata?.llmValidation) {\n ruleData.hasLlmValidation = true\n }\n\n if (result.severity === \"violation\") {\n violationCount++\n } else {\n suggestionCount++\n }\n })\n })\n\n // Print results grouped by rule\n ruleResults.forEach((ruleData, ruleId) => {\n if (ruleData.matches.length === 0 && ruleData.severity !== \"skipped\") {\n return\n }\n\n // Rule header with severity, message, and rule ID\n let messageType: string\n if (ruleData.severity === \"violation\") {\n messageType = chalk.hex(VIOLATION_COLOR)(\" violation\".padStart(9))\n } else if (ruleData.severity === \"suggestion\") {\n messageType = chalk.hex(SUGGESTION_COLOR)(\"suggestion\".padEnd(7))\n } else {\n messageType = chalk.hex(SKIPPED_COLOR)(\" skipped\".padEnd(9))\n }\n\n // Add (llm) indicator if this rule went through LLM validation\n const llmIndicator = ruleData.hasLlmValidation ? `${chalk.hex(SKIPPED_COLOR)(\"(llm)\")} ` : \"\"\n const clickableRuleId = formatClickableRuleId(ruleId, ruleData.internalId)\n const ruleHeader = `${messageType} ${chalk.dim(\"\u2502\")} ${llmIndicator}${ruleData.message.replace(/([^ ])\\.$/u, \"$1\")} ${chalk.dim(\"(\")}${clickableRuleId}${chalk.dim(\")\")}`\n output += `${ruleHeader}\\n`\n output += `${chalk.dim(\"\u2500\".repeat(80))}\\n`\n\n // Handle skipped rules (no matches to display)\n if (ruleData.severity === \"skipped\") {\n output += `\\n`\n } else {\n // Sort matches by path\n const sortedMatches = ruleData.matches.sort((a, b) => a.filePath.localeCompare(b.filePath))\n\n // Determine if we should show code snippets\n const shouldShowCodeSnippets =\n sortedMatches.length < 10 &&\n sortedMatches.some((match) => match.text && match.text.split(\"\\n\").length <= 10)\n\n if (shouldShowCodeSnippets) {\n // Show code snippets format\n sortedMatches.forEach((match, index) => {\n // Show filename only (no line numbers since they'll be in the snippet)\n output += ` ${match.filePath}\\n`\n\n // Show code snippet if available and <= 10 lines\n if (match.text && match.text.split(\"\\n\").length <= 10) {\n const lines = match.text.split(\"\\n\")\n lines.forEach((line, lineIndex) => {\n const lineNumber = match.line + lineIndex\n const lineNumberBox = chalk.bgHex(LINE_NUMBER_BG_COLOR).hex(LINE_NUMBER_TEXT_COLOR)(\n ` ${String(lineNumber)} `\n )\n output += ` ${lineNumberBox} ${chalk.dim(line)}\\n`\n })\n }\n\n // Add spacing between matches (except for the last one)\n if (index < sortedMatches.length - 1) {\n output += `\\n`\n }\n })\n } else {\n // Show traditional table format for many matches or long code snippets\n sortedMatches.forEach((match) => {\n const lineRange = match.endLine ? `(${match.line}:${match.endLine})` : `(${match.line})`\n output += ` ${match.filePath} ${chalk.dim(lineRange)}\\n`\n })\n }\n\n output += `\\n\\n`\n }\n })\n\n const total = violationCount + suggestionCount\n\n if (total === 0) {\n console.log(`\\nno results`)\n }\n\n // Create violations and suggestions text with labels and colored numbers\n const violationText =\n violationCount > 0\n ? `${chalk.dim(\"violations\".padStart(12))} ${chalk.hex(VIOLATION_COLOR)(\"\u25A0\")} ${chalk.hex(VIOLATION_COLOR).bold(violationCount)}`\n : `${chalk.dim(\"violations\".padStart(12))} ${chalk.dim(violationCount)}`\n\n const suggestionText =\n suggestionCount > 0\n ? `${chalk.dim(\"suggestions\".padStart(12))} ${chalk.hex(SUGGESTION_COLOR)(\"\u25CF\")} ${chalk.hex(SUGGESTION_COLOR).bold(suggestionCount)}`\n : `${chalk.dim(\"suggestions\".padStart(12))} ${chalk.dim(suggestionCount)}`\n\n // Create details summary in one line\n const filesText = summary.totalFiles\n ? `${summary.totalFiles} ${pluralize(\"file\", summary.totalFiles)}`\n : \"0 files\"\n const rulesText = `${summary.totalRules} ${pluralize(\"rule\", summary.totalRules)}`\n const timeText = summary.executionTime ? `${Math.round(summary.executionTime)}ms` : \"\"\n\n const detailsText = [filesText, rulesText, timeText].filter(Boolean).join(\", \")\n\n // Format with proper alignment\n output += `${violationText}\\n`\n output += `${suggestionText}\\n`\n output += `${chalk.dim(\"summary\".padStart(12))} ${detailsText}\\n`\n\n // Print the formatted output\n console.log(total > 0 ? chalk.reset(output) : output)\n\n // Exit code\n if (violationCount > 0) {\n process.exit(1)\n }\n}\n\n/**\n * Print a formatted list of rules with their ID, severity, and message\n */\nexport function printRulesList(\n rules: Array<{\n id: string\n internalId?: string\n config: { severity: \"violation\" | \"suggestion\"; message: string }\n }>\n): void {\n if (rules.length === 0) {\n console.log(chalk.yellow(\"No rules found.\"))\n console.log(chalk.dim(\"Go to https://app.wispbit.com/rules to create a rule.\"))\n return\n }\n\n // Create table data with consistent formatting style\n const tableData: string[][] = []\n\n // Add header row\n tableData.push([\n \"\",\n `${\"id\".padEnd(12)} ${chalk.dim(\"\u2502\")} ${\"severity\".padEnd(12)} ${chalk.dim(\"\u2502\")} message`,\n ])\n\n // Add separator row\n tableData.push([\n \"\",\n `${chalk.dim(\"\u2500\".repeat(12))} ${chalk.dim(\"\u253C\")} ${chalk.dim(\"\u2500\".repeat(12))} ${chalk.dim(\"\u253C\")} ${chalk.dim(\"\u2500\".repeat(80))}`,\n ])\n\n // Add rule data\n for (const rule of rules) {\n const severityColor =\n rule.config.severity === \"violation\"\n ? chalk.hex(VIOLATION_COLOR)\n : chalk.hex(SUGGESTION_COLOR)\n const severityText = severityColor(rule.config.severity)\n const ruleId = formatClickableRuleId(rule.id, rule.internalId)\n\n // Calculate padding correctly for styled text\n const idPadding = Math.max(0, 12 - rule.id.length)\n const severityPadding = Math.max(0, 12 - rule.config.severity.length)\n\n // Format: ID first, then severity, then message\n tableData.push([\n \"\",\n `${ruleId}${\" \".repeat(idPadding)} ${chalk.dim(\"\u2502\")} ${severityText}${\" \".repeat(severityPadding)} ${chalk.dim(\"\u2502\")} ${rule.config.message}`,\n ])\n }\n\n const table = textTable(tableData, {\n align: [\"\", \"l\"],\n stringLength(str: string) {\n return stripVTControlCharacters(str).length\n },\n })\n\n console.log(\"\\n\" + table)\n console.log(chalk.dim(`\\nUse 'wispbit check --rule <rule-id>' to run a specific rule.`))\n}\n\n/**\n * Output results in JSON format compatible with ast-grep\n */\nexport function outputJSON(\n results: ScanResult[],\n format: \"pretty\" | \"stream\" | \"compact\" = \"pretty\"\n): void {\n const matches: any[] = []\n\n for (const result of results) {\n for (const match of result.matches) {\n const jsonMatch = {\n filePath: match.filePath,\n range: match.range,\n language: match.language,\n text: match.text,\n symbol: match.symbol,\n source: match.source,\n ruleId: result.ruleId,\n internalId: result.internalId,\n severity: result.severity,\n message: result.message,\n }\n\n matches.push(jsonMatch)\n }\n }\n\n if (format === \"stream\") {\n for (const match of matches) {\n console.log(JSON.stringify(match))\n }\n } else if (format === \"compact\") {\n console.log(JSON.stringify(matches))\n } else {\n // pretty\n console.log(JSON.stringify(matches, null, 2))\n }\n}\n\n/**\n * Set up terminal reporting for the event emitter\n */\nexport function setupTerminalReporter(\n eventEmitter: ExecutionEventEmitter,\n debugMode: boolean = false\n): () => void {\n let spinner: Ora | null = null\n let indexingStartTime: number | null = null\n let executionMode: {\n mode: \"check\" | \"diff\"\n filePath?: string\n baseCommit?: string\n headCommit?: string\n } | null = null\n\n // Set up event listeners\n eventEmitter.on(\"execution:mode\", (data) => {\n executionMode = data\n })\n\n eventEmitter.on(\"rules:start\", (_data) => {\n // Start spinner without any initial message\n spinner = ora({\n spinner: {\n interval: 120,\n frames: loadingFrames,\n },\n color: false,\n }).start()\n\n // Handle process interruption\n const handleInterrupt = () => {\n if (spinner) {\n spinner.stop()\n }\n process.exit(130) // Standard exit code for Ctrl+C\n }\n\n process.on(\"SIGINT\", handleInterrupt)\n process.on(\"SIGTERM\", handleInterrupt)\n })\n\n eventEmitter.on(\"rules:progress\", (data) => {\n if (spinner) {\n let modeText = \"\"\n if (executionMode) {\n if (executionMode.mode === \"check\") {\n modeText = executionMode.filePath ? ` (${executionMode.filePath})` : \" (ALL FILES)\"\n } else if (executionMode.mode === \"diff\") {\n modeText = ` (${executionMode.baseCommit} \u2192 ${executionMode.headCommit})`\n }\n }\n spinner.text = `${data.isLlm ? chalk.hex(SKIPPED_COLOR)(\"(llm) \") : \"\"}${data.ruleId}${modeText}`\n }\n })\n\n eventEmitter.on(\"rules:complete\", () => {\n if (spinner) {\n spinner.stop()\n spinner = null\n }\n })\n\n eventEmitter.on(\"files:discovery:start\", (data) => {\n if (debugMode) {\n console.log(`\\n${chalk.blue(\"Discovering files\")} in ${chalk.bold(data.mode)} mode...`)\n }\n })\n\n eventEmitter.on(\"files:discovery:progress\", (data) => {\n if (debugMode) {\n console.log(` ${data.message}`)\n }\n })\n\n eventEmitter.on(\"files:discovery:complete\", (data) => {\n if (debugMode) {\n console.log(\n chalk.green(\"File discovery complete:\"),\n `${data.totalFiles} files found (${data.executionTime}ms)`\n )\n }\n })\n\n eventEmitter.on(\"files:filter\", (data) => {\n if (debugMode && data.originalCount !== data.filteredCount) {\n console.log(\n chalk.yellow(\"Filtered:\"),\n `${data.originalCount} \u2192 ${data.filteredCount} ${data.filterType}`\n )\n }\n })\n\n // New indexing events with 1-second threshold\n eventEmitter.on(\"indexing:start\", (_data) => {\n indexingStartTime = Date.now()\n })\n\n eventEmitter.on(\"indexing:progress\", (data) => {\n if (spinner) {\n spinner.color = \"yellow\"\n }\n // Check if indexing has been running for more than 1 second\n if (indexingStartTime && Date.now() - indexingStartTime > 1000) {\n if (spinner) {\n spinner.text = `Indexing ${data.language}...`\n }\n }\n\n // Update spinner text if we're showing indexing progress\n if (spinner) {\n if (data.packageName && data.timeMs) {\n spinner.text = `Indexing ${data.language}: ${data.packageName}`\n } else if (data.message !== \"Indexing files...\") {\n spinner.text = `Indexing ${data.language}: ${data.message}`\n }\n }\n\n // Still show debug output if enabled\n if (debugMode) {\n if (data.packageName && data.timeMs) {\n console.log(` + ${data.packageName} (${data.timeMs}ms)`)\n } else if (data.message === \"Indexing files...\") {\n process.stdout.write(\".\")\n } else if (data.message !== \"Indexing files...\") {\n console.log(` ${data.message}`)\n }\n }\n })\n\n eventEmitter.on(\"indexing:complete\", (data) => {\n indexingStartTime = null\n if (spinner) {\n spinner.color = \"blue\"\n }\n\n if (debugMode) {\n process.stdout.write(\"\\n\") // New line after dots\n console.log(\n chalk.green(\"Indexing complete for\"),\n `${data.language} (${data.executionTime}ms)`\n )\n }\n })\n\n // Debug event handlers\n if (debugMode) {\n eventEmitter.on(\"scip:match-lookup:start\", (data) => {\n console.log(\n chalk.cyan(\n `\\n\uD83D\uDD0D [${data.language}] Starting SCIP match lookup for: ${JSON.stringify(data.match)}`\n )\n )\n })\n\n eventEmitter.on(\"scip:match-lookup:progress\", (data) => {\n console.log(`${JSON.stringify(data.document)}`)\n })\n\n eventEmitter.on(\"scip:match-lookup:complete\", (data) => {\n console.log(chalk.green(`SCIP match lookup complete for: ${data.language}`))\n })\n\n eventEmitter.on(\"step:start\", (data) => {\n console.log(\n chalk.cyan(`\\n\uD83D\uDD27 [${data.ruleId}] Starting step: ${data.stepName} (${data.stepType})`)\n )\n console.log(` Input files: ${data.inputs.filePaths.length}`)\n console.log(` Input matches: ${data.inputs.matches.length}`)\n\n // Print full match data\n if (data.inputs.matches.length > 0) {\n console.log(` Match details:`)\n data.inputs.matches.forEach((match, idx) => {\n console.log(` Match ${idx + 1}:`)\n console.log(` File: ${match.filePath}`)\n console.log(\n ` Range: ${match.range.start.line}:${match.range.start.column} \u2192 ${match.range.end.line}:${match.range.end.column}`\n )\n if (match.symbol) {\n console.log(` Symbol: ${match.symbol}`)\n }\n if (match.source && match.source.length > 0) {\n console.log(` Source chain: ${match.source.length} step(s)`)\n match.source.forEach((src, srcIdx) => {\n const range = `${src.range.start.line}:${src.range.start.column} \u2192 ${src.range.end.line}:${src.range.end.column}`\n console.log(\n ` ${srcIdx + 1}. ${src.filePath} [${src.symbol || \"N/A\"}] @ ${range}`\n )\n })\n }\n console.log(` Text preview: ${match.text?.substring(0, 120)}...`)\n })\n }\n })\n\n eventEmitter.on(\"step:complete\", (data) => {\n console.log(\n chalk.cyan(\n `\u2705 [${data.ruleId}] Completed step: ${data.stepName} (${data.stepType}) (${data.executionTime}ms)`\n )\n )\n if (data.outputs.filePaths !== undefined) {\n console.log(` Output files: ${data.outputs.filePaths.length}`)\n }\n if (data.outputs.matches !== undefined) {\n console.log(` Output matches: ${data.outputs.matches.length}`)\n\n // Print full match data for outputs\n if (data.outputs.matches.length > 0) {\n console.log(` Output match details:`)\n data.outputs.matches.forEach((match, idx) => {\n console.log(` Match ${idx + 1}:`)\n console.log(` File: ${match.filePath}`)\n console.log(\n ` Range: ${match.range.start.line}:${match.range.start.column} \u2192 ${match.range.end.line}:${match.range.end.column}`\n )\n if (match.symbol) {\n console.log(` Symbol: ${match.symbol}`)\n }\n if (match.source && match.source.length > 0) {\n console.log(` Source chain: ${match.source.length} step(s)`)\n match.source.forEach((src, srcIdx) => {\n const range = `${src.range.start.line}:${src.range.start.column} \u2192 ${src.range.end.line}:${src.range.end.column}`\n console.log(\n ` ${srcIdx + 1}. ${src.filePath} [${src.symbol || \"N/A\"}] @ ${range}`\n )\n })\n }\n console.log(` Text preview: ${match.text?.substring(0, 120)}...`)\n })\n }\n }\n })\n\n eventEmitter.on(\"test:start\", (data) => {\n console.log(chalk.magenta(`\\n\uD83E\uDDEA [${data.ruleId}] Running test: \"${data.testName}\"`))\n })\n\n eventEmitter.on(\"test:matches\", (data) => {\n console.log(chalk.magenta(` Found ${data.matches.length} match(es):`))\n data.matches.forEach((match, idx) => {\n console.log(` Match ${idx + 1}:`)\n console.log(` File: ${match.filePath}`)\n console.log(\n ` Range: ${match.range.start.line}:${match.range.start.column} \u2192 ${match.range.end.line}:${match.range.end.column}`\n )\n if (match.symbol) {\n console.log(` Symbol: ${match.symbol}`)\n }\n if (match.source && match.source.length > 0) {\n console.log(` Source chain: ${match.source.length} step(s)`)\n match.source.forEach((src, srcIdx) => {\n const range = `${src.range.start.line}:${src.range.start.column} \u2192 ${src.range.end.line}:${src.range.end.column}`\n console.log(` ${srcIdx + 1}. ${src.filePath} [${src.symbol || \"N/A\"}] @ ${range}`)\n })\n }\n console.log(` Text preview: ${match.text?.substring(0, 120)}...`)\n })\n })\n }\n\n // Return cleanup function\n return () => {\n if (spinner) {\n spinner.stop()\n spinner = null\n }\n }\n}\n", "import chalk from \"chalk\"\n\n// Brand colors from formatters.ts\nconst BRAND_COLOR = \"#fbbf24\" // oklch(87% .169 91.605) converted to hex\nconst VIOLATION_COLOR = \"#ff6b35\"\nconst SUGGESTION_COLOR = \"#4a90e2\"\nconst SKIPPED_COLOR = \"#9b59b6\"\n\n/**\n * ASCII art frames for animated WISPBIT text with waving effect\n */\nexport const WISPBIT_FRAMES = [\n // Frame 1 - Normal position\n `\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \")}\n`,\n\n // Frame 2 - Wave starts from left\n `\n${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2557 \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\")}\n${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551 \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\")}\n${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551 \u2588\u2557 \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551\u2588\u2588\u2588\u2557\")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(SUGGESTION_COLOR)(\" \u255A\u2588\u2588\u2588\u2554\u2588\u2588\")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(SUGGESTION_COLOR)(\" \u255A\u2550\u2550\u255D\u255A\u2550\")}${chalk.hex(BRAND_COLOR)(\"\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \")}\n`,\n\n // Frame 3 - Wave in middle\n `\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\")}${chalk.hex(SKIPPED_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\")}${chalk.hex(SKIPPED_COLOR)(\"\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\")}${chalk.hex(SKIPPED_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551\")}${chalk.hex(SKIPPED_COLOR)(\"\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\")}${chalk.hex(SKIPPED_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \")}${chalk.hex(BRAND_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D\")}${chalk.hex(SKIPPED_COLOR)(\"\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \")}${chalk.hex(BRAND_COLOR)(\"\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \")}\n`,\n\n // Frame 4 - Wave towards right\n `\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \")}${chalk.hex(VIOLATION_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\")}${chalk.hex(VIOLATION_COLOR)(\"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\")}${chalk.hex(VIOLATION_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \")}${chalk.hex(VIOLATION_COLOR)(\"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \")}${chalk.hex(VIOLATION_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \")}${chalk.hex(VIOLATION_COLOR)(\"\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \")}\n`,\n\n // Frame 5 - Wave at end\n `\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\")}${chalk.hex(SUGGESTION_COLOR)(\"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\")}${chalk.hex(SUGGESTION_COLOR)(\"\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\")}${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\")}${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\")}${chalk.hex(SUGGESTION_COLOR)(\" \u2588\u2588\u2551 \")}\n${chalk.hex(BRAND_COLOR)(\" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D\")}${chalk.hex(SUGGESTION_COLOR)(\" \u255A\u2550\u255D \")}\n`,\n]\n", "import readline from \"readline\"\n\nimport chalk from \"chalk\"\nimport ora from \"ora\"\n\nimport { WISPBIT_FRAMES } from \"powerlint/utils/asciiFrames\"\nimport { SUGGESTION_COLOR, VIOLATION_COLOR } from \"powerlint/utils/formatters\"\n\n/**\n * Clears the terminal screen and moves cursor to top\n */\nfunction clearScreen(): void {\n process.stdout.write(\"\\x1b[2J\\x1b[H\")\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Displays animated octopus using ora spinner for a specified duration\n */\nasync function showAnimatedFrames(durationMs: number = 3000): Promise<void> {\n const spinner = ora({\n text: \"\",\n spinner: {\n interval: 100, // ms per frame\n frames: WISPBIT_FRAMES,\n },\n }).start()\n\n // Let the animation run for the specified duration\n await sleep(durationMs)\n\n // Stop the spinner\n spinner.stop()\n}\n\n/**\n * Prompts user for text input\n */\nasync function promptForInput(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n return await new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/**\n * Shows the PowerLint startup screen and prompts for API key\n */\nexport async function showStartupScreen(): Promise<string | null> {\n // Clear screen first\n clearScreen()\n\n // Show animated octopus\n await showAnimatedFrames(1500)\n\n // Show final frame with welcome message (ora will have cleared the screen)\n console.log(WISPBIT_FRAMES[0])\n\n console.log(chalk.hex(VIOLATION_COLOR)(\"\\n Welcome to wispbit\"))\n console.log(chalk(\" The linter for AI\\n\"))\n\n console.log(chalk.dim(\" To use wispbit, you need an API key.\"))\n console.log(chalk.dim(\" You can get one at: https://app.wispbit.com/api-keys\\n\"))\n\n const apiKey = await promptForInput(\n chalk.bold.hex(SUGGESTION_COLOR)(\" Enter your Wispbit API key (or press Enter to exit): \")\n )\n\n if (!apiKey) {\n console.log(chalk.dim(\"\\n Setup cancelled.\"))\n return null\n }\n\n return apiKey\n}\n", "#!/usr/bin/env node\n\nimport * as fs from \"fs/promises\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport Big from \"big.js\"\nimport chalk from \"chalk\"\nimport dotenv from \"dotenv\"\nimport meow from \"meow\"\nimport semver from \"semver\"\n\nimport { Config } from \"powerlint/environment/Config\"\nimport { Environment } from \"powerlint/environment/Environment\"\nimport { Storage } from \"powerlint/environment/Storage\"\nimport { WispbitRuleProvider } from \"powerlint/providers/WispbitRuleProvider\"\nimport { ExecutionEventEmitter } from \"powerlint/steps/ExecutionEventEmitter\"\nimport { RuleExecutor } from \"powerlint/steps/RuleExecutor\"\nimport { Match, Rule, InvalidRuleFormatError } from \"powerlint/types\"\nimport {\n outputJSON,\n printSummary,\n printRulesList,\n setupTerminalReporter,\n} from \"powerlint/utils/formatters\"\nimport { showStartupScreen } from \"powerlint/utils/startupScreen\"\nimport { getCurrentVersion, getLatestVersion } from \"powerlint/version\"\n\ndotenv.config()\n\n/**\n * Get the config file path in .powerlint directory\n */\nfunction getConfigFilePath(): string {\n return path.join(os.homedir(), \".powerlint\", \"config.json\")\n}\n\n/**\n * Save API key to config file\n */\nasync function saveApiKey(apiKey: string): Promise<void> {\n const configPath = getConfigFilePath()\n const configDir = path.dirname(configPath)\n\n // Ensure .powerlint directory exists\n await fs.mkdir(configDir, { recursive: true })\n\n let existingConfig = {}\n try {\n const configContent = await fs.readFile(configPath, \"utf-8\")\n existingConfig = JSON.parse(configContent)\n } catch {\n // Config file doesn't exist or is invalid, start fresh\n }\n\n const newConfig = {\n ...existingConfig,\n apiKey,\n }\n\n await fs.writeFile(configPath, JSON.stringify(newConfig, null, 2))\n}\n\n/**\n * Load API key from config file\n */\nasync function loadApiKey(): Promise<string | null> {\n const configPath = getConfigFilePath()\n try {\n const configContent = await fs.readFile(configPath, \"utf-8\")\n const config = JSON.parse(configContent)\n return config.apiKey || null\n } catch {\n return null\n }\n}\n\n/**\n * Check if PowerLint is configured and show startup screen if not\n */\nasync function ensureConfigured(): Promise<Config> {\n const environment = new Environment()\n // Try to get API key from environment or stored config\n let apiKey: string | null = process.env.WISPBIT_API_KEY || null\n if (!apiKey) {\n apiKey = await loadApiKey()\n }\n\n // Try to initialize with available API key (or just environment variable)\n let config = await Config.initialize(environment, { apiKey: apiKey || undefined })\n\n if (\"failed\" in config) {\n if (config.error === \"INVALID_API_KEY\") {\n // Show startup screen and prompt for API key\n const newApiKey = await showStartupScreen()\n\n if (!newApiKey) {\n process.exit(0)\n }\n\n // Validate the API key\n const repositoryUrl = await environment.getRepositoryUrl()\n if (!repositoryUrl) {\n console.log(chalk.red(\"Repository URL not found. Make sure you're in a git repository.\"))\n process.exit(1)\n }\n\n console.log(chalk.dim(\"Validating API key...\"))\n\n // Save the API key first\n await saveApiKey(newApiKey)\n\n // Try to initialize with the new API key\n config = await Config.initialize(environment, { apiKey: newApiKey })\n\n if (\"failed\" in config) {\n console.log(chalk.red(\"Invalid API key. Please check your API key and try again.\"))\n process.exit(1)\n } else {\n console.log(chalk.green(\"Setup complete! powerlint has been configured.\"))\n return config\n }\n } else if (config.error === \"INVALID_REPOSITORY\") {\n const repositoryUrl = await environment.getRepositoryUrl()\n console.log(\n chalk.red(\n `No repository in wispbit found for url: ${repositoryUrl}. If your git remote URL was recently modified, use \"git remote set-url origin <new-url>\" to update the remote URL.`\n )\n )\n process.exit(1)\n }\n }\n\n return config as Config\n}\n\n/**\n * Check for available updates\n */\nexport async function checkForUpdates() {\n const currentVersion = getCurrentVersion()\n const latestCliVersion = await getLatestVersion()\n\n if (semver.gt(latestCliVersion, currentVersion)) {\n console.log(\n chalk\n .bgHex(\"#b2f5ea\")\n .black.bold(` NEW VERSION AVAILABLE: ${latestCliVersion} (current: ${currentVersion}) `)\n )\n console.log(\n chalk.bgHex(\"#b2f5ea\").black.bold(` Run 'pnpm install -g @wispbit/cli' to update \\n`)\n )\n }\n}\n\nexport interface ScanResult {\n ruleId: string\n internalId?: string\n message: string\n severity: \"violation\" | \"suggestion\"\n matches: Match[]\n llmCost?: string\n llmTokens?: number\n}\n\n// Create the CLI with meow\nconst cli = meow(\n `\nwispbit - the linter for AI\nhttps://wispbit.com/\n\nUsage:\n $ wispbit [diff-options] (run diff by default)\n $ wispbit check [file-path/directory] [check-options]\n $ wispbit diff [diff-options]\n $ wispbit list\n $ wispbit cache purge\n\nCommands:\n check [file-path/directory] Run linting rules against a specific file/folder or entire codebase\n diff Run linting rules only on changed files in the current PR\n list List all available rules with their ID, message, and severity\n cache purge Purge the cache directory (indexes, caching, etc.)\n\nOptions for check:\n --rule <ruleId> Optional rule ID to run specific rule\n --json [format] Output in JSON format (pretty, stream, compact)\n -d, --debug Enable debug output\n\nOptions for diff:\n --rule <ruleId> Optional rule ID to run specific rule\n --json [format] Output in JSON format (pretty, stream, compact)\n --base <commit> Base commit/branch/SHA to compare against (defaults to origin/main)\n --head <commit> Head commit/branch/SHA to compare against (defaults to current branch)\n -d, --debug Enable debug output\n\n\nGlobal options:\n -v, --version Show version number\n -h, --help Show help\n`,\n {\n importMeta: import.meta,\n flags: {\n // Scan/diff options\n rule: {\n type: \"string\",\n },\n\n json: {\n type: \"string\",\n },\n base: {\n type: \"string\",\n },\n head: {\n type: \"string\",\n },\n\n // Debug option\n debug: {\n type: \"boolean\",\n shortFlag: \"d\",\n default: false,\n },\n\n // Global options\n version: {\n type: \"boolean\",\n shortFlag: \"v\",\n },\n help: {\n type: \"boolean\",\n shortFlag: \"h\",\n },\n },\n version: getCurrentVersion(),\n }\n)\n\nasync function executeCommand(options: {\n ruleId?: string\n json?: string\n debug?: boolean\n mode: \"check\" | \"diff\"\n filePath?: string\n}): Promise<ScanResult[]> {\n // Track execution timing\n\n // Initialize core components\n const environment = new Environment()\n const config = await ensureConfigured()\n\n const { ruleId, json, mode, filePath } = options\n\n // Handle JSON output\n let jsonOutput = false\n let jsonFormat: \"pretty\" | \"stream\" | \"compact\" = \"pretty\"\n\n if (json) {\n jsonOutput = true\n if (json === \"stream\") {\n jsonFormat = \"stream\"\n } else if (json === \"compact\") {\n jsonFormat = \"compact\"\n } else {\n jsonFormat = \"pretty\"\n }\n } else {\n // Check for updates (but not in JSON mode)\n await checkForUpdates()\n }\n\n // Load rules using rule provider\n let rules: Rule[]\n try {\n const ruleProvider = new WispbitRuleProvider(config, environment)\n if (ruleId) {\n // Run specific rule\n const rule = await ruleProvider.loadRuleById(ruleId)\n rules = [rule]\n } else {\n rules = await ruleProvider.loadAllRules()\n }\n } catch (error) {\n if (error instanceof InvalidRuleFormatError) {\n console.error(chalk.red(\"Rule Validation Error:\"), error.message)\n if (error.validationErrors && error.validationErrors.length > 0) {\n console.error(chalk.red(\"Validation errors:\"))\n error.validationErrors.forEach((err) => {\n console.error(chalk.red(\" \u2022\"), err)\n })\n }\n process.exit(1)\n }\n throw error // Re-throw other errors\n }\n\n // Display mode information before starting (for non-JSON output)\n if (!json) {\n if (mode === \"check\") {\n const modeBox = chalk.bgHex(\"#eab308\").black(\" CHECK \") // Yellow warning color background box for CHECK\n const targetInfo = chalk.dim(` (${filePath || \"all files\"})`)\n console.log(`${modeBox}${targetInfo}`)\n } else {\n const baseCommit = cli.flags.base || \"origin/main\"\n const headCommit = cli.flags.head || \"HEAD\"\n const modeBox = chalk.bgHex(\"#4a90e2\").black(\" DIFF \") // Blue background box for DIFF\n const branchInfo = chalk.dim(` (${headCommit}..${baseCommit})`)\n console.log(`${modeBox}${branchInfo}`)\n }\n }\n\n // Create event emitter and set up terminal reporter for non-JSON output\n const eventEmitter = new ExecutionEventEmitter()\n\n // Emit execution mode event\n if (mode === \"check\") {\n eventEmitter.setExecutionMode(\"check\", { filePath })\n } else {\n // For diff mode, we'll need to get the base/head commits from flags or defaults\n const baseCommit = cli.flags.base || \"origin/main\"\n const headCommit = cli.flags.head || \"current branch\"\n eventEmitter.setExecutionMode(\"diff\", { baseCommit, headCommit })\n }\n\n const cleanupTerminalReporter = !options.json\n ? setupTerminalReporter(eventEmitter, options.debug || false)\n : undefined\n\n const executionStartTime = Date.now()\n\n const ruleExecutor = new RuleExecutor(config, environment, eventEmitter)\n\n // Track file count\n let totalFiles = 0\n\n // Listen for file discovery completion to capture total file count\n eventEmitter.on(\"files:discovery:complete\", (data) => {\n totalFiles = data.totalFiles\n })\n\n // Execute all rules at once\n const ruleResults = await ruleExecutor.execute(rules, {\n mode,\n filePath,\n baseSha: cli.flags.base,\n })\n\n // Convert results to ScanResult format\n const results: ScanResult[] = []\n for (const ruleResult of ruleResults) {\n const rule = rules.find((r) => r.id === ruleResult.ruleId)\n\n if (rule) {\n // Handle LLM cost tracking (if available in execution result)\n let llmCost: string | undefined\n let llmTokens: number | undefined\n\n // Note: We'll need to extend RuleExecutionResult to include LLM costs\n // For now, we'll leave these undefined and add them later\n\n const result: ScanResult = {\n ruleId: ruleResult.ruleId,\n internalId: rule.internalId,\n message: rule.config.message,\n severity: rule.config.severity,\n matches: ruleResult.matches,\n llmCost,\n llmTokens,\n }\n\n results.push(result)\n }\n }\n\n // Clean up terminal reporter\n cleanupTerminalReporter?.()\n\n // Output results\n if (jsonOutput) {\n outputJSON(results, jsonFormat)\n } else {\n // Print summary\n const violationResults = results.filter((r) => r.severity === \"violation\")\n const suggestionResults = results.filter((r) => r.severity === \"suggestion\")\n const violationCount = violationResults.reduce((sum, r) => sum + r.matches.length, 0)\n const suggestionCount = suggestionResults.reduce((sum, r) => sum + r.matches.length, 0)\n const totalMatches = violationCount + suggestionCount\n\n // Calculate LLM costs\n const totalLLMCost = results\n .filter((r) => r.llmCost)\n .reduce((sum, r) => sum.plus(new Big(r.llmCost || 0)), new Big(0))\n\n const totalLLMTokens = results\n .filter((r) => r.llmTokens)\n .reduce((sum, r) => sum + (r.llmTokens || 0), 0)\n\n // Prepare execution mode info for summary\n let executionModeInfo:\n | { mode: \"check\" | \"diff\"; filePath?: string; baseCommit?: string; headCommit?: string }\n | undefined\n if (mode === \"check\") {\n executionModeInfo = { mode: \"check\", filePath }\n } else {\n const baseCommit = cli.flags.base || \"origin/main\"\n const headCommit = cli.flags.head || \"current branch\"\n executionModeInfo = { mode: \"diff\", baseCommit, headCommit }\n }\n\n // Calculate execution time\n const executionTime = Date.now() - executionStartTime\n\n printSummary(results, {\n totalRules: rules.length,\n violationCount,\n suggestionCount,\n totalMatches,\n totalLLMCost: totalLLMCost.toString(),\n totalLLMTokens,\n executionMode: executionModeInfo,\n executionTime,\n totalFiles,\n })\n }\n\n return results\n}\n\n/**\n * List all available rules with their ID, message, and severity\n */\nasync function listRules(): Promise<void> {\n const config = await ensureConfigured()\n const environment = new Environment()\n\n const ruleProvider = new WispbitRuleProvider(config, environment)\n const rules = await ruleProvider.loadAllRules()\n\n printRulesList(rules)\n}\n\n/**\n * Main function to orchestrate the workflow\n */\nasync function main() {\n const command = cli.input[0]\n const subcommand = cli.input[1]\n\n switch (command) {\n case \"check\": {\n const filePath = cli.input[1] // Get the optional file path argument\n await executeCommand({\n ruleId: cli.flags.rule,\n json: cli.flags.json,\n debug: cli.flags.debug,\n mode: \"check\",\n filePath,\n })\n break\n }\n\n case \"diff\": {\n await executeCommand({\n ruleId: cli.flags.rule,\n json: cli.flags.json,\n debug: cli.flags.debug,\n mode: \"diff\",\n })\n break\n }\n\n case \"list\": {\n await listRules()\n break\n }\n\n case \"cache\": {\n if (subcommand === \"purge\") {\n const environment = new Environment()\n const storage = new Storage(environment)\n const result = await storage.purgeCache()\n console.log(\n `\\n${chalk.green(\"Cache purged successfully.\")} Removed ${result.deletedCount} item(s).`\n )\n } else {\n console.error(chalk.red(\"Unknown cache subcommand:\"), subcommand)\n cli.showHelp()\n process.exit(1)\n }\n break\n }\n\n default: {\n // If no command is provided, run diff by default\n if (!command) {\n await executeCommand({\n ruleId: cli.flags.rule,\n json: cli.flags.json,\n debug: cli.flags.debug,\n mode: \"diff\",\n })\n } else {\n console.error(chalk.red(\"Unknown command:\"), command)\n cli.showHelp()\n process.exit(1)\n }\n break\n }\n }\n}\n\n// Execute the main function\nmain()\n", "#!/usr/bin/env node\n\nprocess.emitWarning = () => {}\nprocess.removeAllListeners(\"warning\")\n\n// ast-grep gives annoying warnings\nconsole.debug = () => {}\n\n// Suppress specific experimental warnings\nconst originalEmit = process.emit\nprocess.emit = function (event, ...args) {\n if (\n event === \"warning\" &&\n ((args[0] && (args[0] as any).name === \"ExperimentalWarning\") ||\n (args[0] && (args[0] as any).code === \"DEP0040\"))\n ) {\n return false\n }\n // @ts-expect-error - This is a workaround to suppress experimental warnings\n return originalEmit.apply(process, [event, ...args])\n} as typeof process.emit\n\n// Use the file extension to help the module resolver find the file\n// eslint-disable-next-line import/no-unresolved\nimport(\"./cli.js\").catch(console.error)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,OAAO,mBAAmB;AAEnB,SAAS,oBAA4B;AAC1C,QAAM,WAAW,cAAc,YAAY,MAAM,YAAY,MAAM,UAAU;AAC7E,QAAM,YAAY,QAAQ,QAAQ;AAGlC,QAAM,kBAAkB,KAAK,WAAW,iBAAiB;AACzD,MAAI;AACF,UAAM,OAAO,aAAa,iBAAiB,MAAM;AACjD,UAAM,cAAc,KAAK,MAAM,IAAI;AACnC,WAAO,YAAY;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,mBAAoC;AACxD,MAAI;AACF,UAAM,mBAAmB,MAAM,cAAc,gBAAgB;AAC7D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,kBAAkB;AAAA,EAC3B;AACF;AA5BA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAaa;AAbb;AAAA;AAAA;AAEA;AAWO,IAAM,SAAN,MAAM,QAAO;AAAA,MACV;AAAA,MACA,SAAwB;AAAA,MACxB,UAAyB;AAAA,MAEjC,YAAY,QAAkC;AAC5C,aAAK,SAAS;AAAA,UACZ,GAAG;AAAA,UACH,cAAc,OAAO,gBAAgB,CAAC;AAAA,QACxC;AACA,aAAK,SAAS,OAAO,UAAU;AAC/B,aAAK,UAAU,OAAO,WAAW;AAAA,MACnC;AAAA,MAEA,kBAA4B;AAC1B,eAAO,KAAK,OAAO,gBAAgB,CAAC;AAAA,MACtC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,YAAoB;AAClB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,aAAqB;AACnB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,kBAA0B;AACxB,eAAO,kBAAkB;AAAA,MAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,mBAA2B;AACzB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,aAAqB,eACnB,QACA,eACA,SACkB;AAClB,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,oBAAoB;AAAA,UACzD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,gBAAgB;AAAA,YAChB,mBAAmB,kBAAkB;AAAA,YACrC,gBAAgB;AAAA,UAClB,CAAC;AAAA,QACH,CAAC;AAED,eAAO,SAAS;AAAA,MAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,OAAc,yBACZ,UAII,CAAC,GACG;AACR,cAAM,eACJ,QAAQ,WAAW,QAAQ,IAAI,wBAAwB;AACzD,cAAM,cAAc,QAAQ,UAAU,QAAQ,IAAI,mBAAmB;AACrE,cAAM,eAAe,QAAQ,gBAAgB,CAAC;AAE9C,eAAO,IAAI,QAAO;AAAA,UAChB;AAAA,UACA,QAAQ,eAAe;AAAA,UACvB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,aAAoB,WAClB,aACA;AAAA,QACE;AAAA,QACA;AAAA,MACF,GAIqF;AA9HzF;AA+HI,cAAM,eAAe,WAAW,QAAQ,IAAI,wBAAwB;AAGpE,cAAM,cAAc,UAAU,QAAQ,IAAI,mBAAmB;AAG7D,YAAI,CAAC,aAAa;AAChB,kBAAQ,IAAI,kBAAkB;AAC9B,iBAAO,EAAE,QAAQ,MAAM,OAAO,kBAAkB;AAAA,QAClD;AAEA,cAAM,gBAAgB,MAAM,YAAY,iBAAiB;AAGzD,cAAM,gBAAgB,MAAM,QAAO,eAAe,aAAa,eAAe,YAAY;AAC1F,YAAI,CAAC,eAAe;AAClB,iBAAO,EAAE,QAAQ,MAAM,OAAO,kBAAkB;AAAA,QAClD;AAEA,cAAM,WAAW,MAAM,MAAM,GAAG,YAAY,oBAAoB;AAAA,UAC9D,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,WAAW;AAAA,UACtC;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,gBAAgB;AAAA,YAChB,mBAAmB,kBAAkB;AAAA,YACrC,gBAAgB;AAAA,UAClB,CAAC;AAAA,QACH,CAAC;AAED,cAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,YAAI,OAAO,iBAAiB;AAC1B,iBAAO,EAAE,QAAQ,MAAM,OAAO,kBAAkB;AAAA,QAClD;AAEA,YAAI,CAAC,OAAO,qBAAqB;AAC/B,iBAAO,EAAE,QAAQ,MAAM,OAAO,qBAAqB;AAAA,QACrD;AAEA,cAAM,iBAAe,YAAO,WAAP,mBAAe,kBAAiB,CAAC;AAEtD,cAAM,SAAS,IAAI,QAAO,EAAE,cAAc,QAAQ,aAAa,SAAS,aAAa,CAAC;AAEtF,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,eAAwB;AACtB,eAAO,KAAK,UAAU,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA;AAAA;;;ACtLA,SAAS,kBAAkB;AAEpB,SAAS,WAAW,KAAa;AACtC,SAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AACtD;AAJA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,MAAM,gBAAgB;AAC/B,SAAS,iBAAiB;AA0BnB,SAAS,cAAsB;AACpC,QAAM,SAAS,SAAS,iCAAiC,EAAE,UAAU,QAAQ,CAAC;AAC9E,SAAO,OAAO,KAAK;AACrB;AAQA,eAAsB,iBACpB,UACA,aAAqB,UACG;AAzC1B;AA0CE,QAAM,EAAE,OAAO,IAAI,MAAM,YAAY,mBAAmB,UAAU,IAAI;AAAA,IACpE,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,eAAe,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,YAAY,CAAC;AAClF,MAAI,cAAc;AAChB,aAAO,kBAAa,MAAM,YAAY,EAAE,IAAI,MAArC,mBAAwC,WAAU;AAAA,EAC3D;AACA,SAAO;AACT;AAOA,eAAsB,iBACpB,UACA,aAAqB,UACG;AA9D1B;AA+DE,QAAM,EAAE,OAAO,IAAI,MAAM,YAAY,mBAAmB,UAAU,IAAI;AAAA,IACpE,KAAK;AAAA,EACP,CAAC;AAED,QAAM,iBAAiB,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,aAAa,CAAC;AACrF,MAAI,gBAAgB;AAClB,aAAO,oBAAe,MAAM,GAAG,EAAE,IAAI,MAA9B,mBAAiC,WAAU;AAAA,EACpD;AACA,SAAO;AACT;AAOA,eAAsB,gBAAgB,UAAkB,MAAoC;AA/E5F;AAiFE,QAAM,EAAE,QAAQ,oBAAoB,IAAI,MAAM,YAAY,mCAAmC;AAAA,IAC3F,KAAK;AAAA,EACP,CAAC;AACD,QAAM,gBAAgB,oBAAoB,KAAK;AAG/C,QAAM,gBAAgB,MAAM,iBAAiB,QAAQ;AACrD,QAAM,YAAY,SAAS,gBAAgB,UAAU,aAAa,KAAK;AAGvE,MAAI;AACJ,MAAI;AAEF,UAAM,EAAE,QAAQ,mBAAmB,IAAI,MAAM;AAAA,MAC3C,wBAAwB,aAAa;AAAA,MACrC,EAAE,KAAK,SAAS;AAAA,IAClB;AACA,oBAAgB,mBAAmB,KAAK;AAAA,EAC1C,SAAS,OAAO;AAEd,UAAM,EAAE,QAAQ,oBAAoB,IAAI,MAAM,YAAY,sBAAsB;AAAA,MAC9E,KAAK;AAAA,IACP,CAAC;AACD,oBAAgB,oBAAoB,KAAK;AAAA,EAC3C;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,EAAE,QAAQ,gBAAgB,IAAI,MAAM;AAAA,MACxC,kBAAkB,aAAa,IAAI,SAAS;AAAA,MAC5C,EAAE,KAAK,SAAS;AAAA,IAClB;AACA,gBAAY,gBAAgB,KAAK;AAAA,EACnC,SAAS,OAAO;AAGd,gBAAY;AAAA,EACd;AAGA,QAAM,EAAE,QAAQ,aAAa,IAAI,MAAM,YAAY,0BAA0B;AAAA,IAC3E,KAAK;AAAA,EACP,CAAC;AACD,QAAM,cAAc,aAAa,MAAM,IAAI,EAAE,OAAO,OAAO;AAC3D,QAAM,eAAe,oBAAI,IAAoB;AAC7C,cAAY,QAAQ,CAAC,SAAS;AAC5B,UAAM,aAAa,KAAK,UAAU,GAAG,CAAC,EAAE,KAAK;AAC7C,UAAM,WAAW,KAAK,UAAU,CAAC;AACjC,iBAAa,IAAI,UAAU,UAAU;AAAA,EACvC,CAAC;AAGD,QAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,YAAY,YAAY,SAAS,gBAAgB;AAAA,IACpF,KAAK;AAAA,EACP,CAAC;AACD,QAAM,WAAW,WAAW,MAAM,IAAI,EAAE,OAAO,OAAO;AAGtD,QAAM,EAAE,QAAQ,mBAAmB,IAAI,MAAM,YAAY,0BAA0B;AAAA,IACjF,KAAK;AAAA,EACP,CAAC;AACD,QAAM,eAAe,mBAAmB,MAAM,IAAI,EAAE,OAAO,OAAO;AAGlE,WAAS,KAAK,GAAG,aAAa,OAAO,CAAC,SAAS,CAAC,SAAS,SAAS,IAAI,CAAC,CAAC;AAGxE,QAAM,EAAE,QAAQ,gBAAgB,IAAI,MAAM;AAAA,IACxC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAM,iBAAiB,gBAAgB,MAAM,IAAI,EAAE,OAAO,OAAO;AAGjE,WAAS,KAAK,GAAG,eAAe,OAAO,CAAC,SAAS,CAAC,SAAS,SAAS,IAAI,CAAC,CAAC;AAG1E,QAAM,kBAA4B,CAAC;AACnC,QAAM,kBAAkB,IAAI,IAAI,YAAY;AAC5C,QAAM,gBAAgB,oBAAI,IAAqB;AAE/C,aAAW,QAAQ,UAAU;AAC3B,UAAM,YACJ,gBAAgB,IAAI,IAAI,OACxB,kBAAa,IAAI,IAAI,MAArB,mBAAwB,SAAS,WACjC,kBAAa,IAAI,IAAI,MAArB,mBAAwB,SAAS;AAEnC,kBAAc,IAAI,MAAM,QAAQ,SAAS,CAAC;AAC1C,QAAI,CAAC,WAAW;AACd,sBAAgB,KAAK,IAAI;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,YAAY,oBAAI,IAAsD;AAC5E,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,EAAE,QAAQ,mBAAmB,IAAI,MAAM;AAAA,MAC3C,YAAY,SAAS,iBAAiB,gBAAgB,IAAI,CAAC,MAAM,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,MAC3G,EAAE,KAAK,SAAS;AAAA,IAClB;AAEA,UAAM,eAAe,mBAAmB,MAAM,IAAI,EAAE,OAAO,OAAO;AAClE,iBAAa,QAAQ,CAAC,SAAS;AAC7B,YAAM,QAAQ,KAAK,MAAM,GAAI;AAC7B,UAAI,MAAM,UAAU,GAAG;AACrB,cAAM,CAAC,cAAc,cAAc,QAAQ,IAAI;AAC/C,kBAAU,IAAI,UAAU;AAAA,UACtB,WAAW,SAAS,YAAY,KAAK;AAAA,UACrC,WAAW,SAAS,YAAY,KAAK;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,YAAY,oBAAI,IAAoB;AAC1C,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,EAAE,QAAQ,gBAAgB,IAAI,MAAM;AAAA,MACxC,YAAY,SAAS,OAAO,gBAAgB,IAAI,CAAC,MAAM,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,MACjG,EAAE,KAAK,SAAS;AAAA,IAClB;AAGA,UAAM,eAAe,gBAAgB,MAAM,eAAe,EAAE,OAAO,OAAO;AAC1E,iBAAa,QAAQ,CAAC,YAAY;AAChC,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,YAAM,YAAY,MAAM,CAAC;AACzB,YAAM,QAAQ,UAAU,MAAM,cAAc;AAC5C,UAAI,OAAO;AACT,cAAM,WAAW,MAAM,CAAC;AAExB,cAAM,cAAc,MACjB,MAAM,CAAC,EACP,OAAO,CAAC,SAAS;AAChB,iBAAO,EACL,KAAK,WAAW,QAAQ,KACxB,KAAK,WAAW,MAAM,KACtB,KAAK,WAAW,MAAM;AAAA,QAE1B,CAAC,EACA,KAAK,IAAI;AACZ,kBAAU,IAAI,UAAU,WAAW;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,sBAAsB,oBAAI,IAAoB;AACpD,QAAM,qBAAqB,SAAS,OAAO,CAAC,SAAS,cAAc,IAAI,IAAI,CAAC;AAE5E,MAAI,mBAAmB,SAAS,GAAG;AAEjC,UAAM,sBAAsB,mBAAmB,IAAI,OAAO,SAAS;AACjE,YAAM,EAAE,QAAQ,YAAY,IAAI,MAAM;AAAA,QACpC,aAAa,SAAS,IAAI,KAAK,QAAQ,MAAM,OAAO,CAAC;AAAA,QACrD;AAAA,UACE,KAAK;AAAA,QACP;AAAA,MACF;AACA,aAAO,EAAE,MAAM,SAAS,YAAY;AAAA,IACtC,CAAC;AAED,UAAM,UAAU,MAAM,QAAQ,WAAW,mBAAmB;AAC5D,YAAQ,QAAQ,CAAC,QAAQ,UAAU;AACjC,UAAI,OAAO,WAAW,aAAa;AACjC,4BAAoB,IAAI,mBAAmB,KAAK,GAAG,OAAO,MAAM,OAAO;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,cAA4B,CAAC;AACnC,aAAW,QAAQ,UAAU;AAC3B,UAAM,YAAY,cAAc,IAAI,IAAI;AACxC,QAAI,YAAY;AAChB,QAAI,YAAY;AAChB,QAAIA,cAAa;AAEjB,QAAI,WAAW;AACb,YAAM,cAAc,oBAAoB,IAAI,IAAI;AAChD,UAAI,aAAa;AACf,oBAAY,YAAY,MAAM,IAAI,EAAE;AACpC,QAAAA,cAAa,YACV,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,EACxB,KAAK,IAAI;AAAA,MACd;AAAA,IACF,OAAO;AACL,YAAM,QAAQ,UAAU,IAAI,IAAI;AAChC,UAAI,OAAO;AACT,oBAAY,MAAM;AAClB,oBAAY,MAAM;AAAA,MACpB;AACA,MAAAA,cAAa,UAAU,IAAI,IAAI,KAAK;AAAA,IACtC;AAEA,UAAM,SAAS,YAAY,YAAY,YAAY,KAAK,cAAc,IAAI,UAAU;AAEpF,gBAAY,KAAK;AAAA,MACf,UAAU;AAAA,MACV;AAAA,MACA,OAAOA;AAAA,MACP;AAAA,MACA;AAAA,MACA,KAAK,WAAWA,WAAU;AAAA,IAC5B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AA5SA,IAKM;AALN;AAAA;AAAA;AAGA;AAEA,IAAM,cAAc,UAAU,IAAI;AAAA;AAAA;;;ACLlC,IAMa;AANb;AAAA;AAAA;AAAA;AAMO,IAAM,cAAN,MAAkB;AAAA,MACN;AAAA,MACA;AAAA,MAEjB,YAAY,QAA6D;AACvE,aAAK,iBAAgB,iCAAQ,kBAAiB;AAC9C,aAAK,iBAAgB,iCAAQ,kBAAiB,YAAY;AAAA,MAC5D;AAAA;AAAA;AAAA;AAAA,MAKA,mBAA2B;AACzB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,MAAM,iBAAiB,aAAqB,UAA2B;AACrE,YAAI,KAAK,eAAe;AACtB,iBAAO,KAAK;AAAA,QACd;AACA,cAAM,gBAAgB,MAAM,iBAAiB,KAAK,eAAe,UAAU;AAC3E,YAAI,CAAC,eAAe;AAClB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACvCA,YAAY,QAAQ;AACpB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,OAAO,UAAU;AACjB,SAAS,gBAAgB;AALzB,IAea;AAfb;AAAA;AAAA;AASA;AAMO,IAAM,UAAN,MAAc;AAAA,MACX;AAAA,MACA;AAAA,MAER,YAAY,aAA0B;AACpC,aAAK,cAAc;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,sBAA8B;AAC5B,eAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,YAAY;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA,MAKA,oBAA4B;AAC1B,eAAO,KAAK;AAAA,UACV,KAAK,oBAAoB;AAAA,UACzB;AAAA,UACA,WAAW,KAAK,YAAY,iBAAiB,CAAC;AAAA,QAChD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,oBAA4B;AAC1B,eAAO,KAAK;AAAA,UACV,KAAK,oBAAoB;AAAA,UACzB;AAAA,UACA,WAAW,KAAK,YAAY,iBAAiB,CAAC;AAAA,QAChD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,gBAAgB,SAAgC;AACpD,cAAS,SAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,iBAAiB,UAAoB,UAAoC;AAC7E,cAAM,WAAW,KAAK,kBAAkB;AACxC,cAAM,KAAK,gBAAgB,QAAQ;AAEnC,cAAM,OAAO,YAAY,GAAG,SAAS,YAAY,CAAC;AAClD,eAAO,KAAK,KAAK,UAAU,GAAG,SAAS,YAAY,CAAC,IAAI,IAAI,EAAE;AAAA,MAChE;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,YAAY,UAAoB,UAAqC;AACzE,cAAM,YAAY,MAAM,KAAK,iBAAiB,UAAU,QAAQ;AAChE,YAAI;AACF,gBAAS,UAAO,SAAS;AACzB,iBAAO;AAAA,QACT,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,UAAU,UAAoB,UAA2C;AAC7E,cAAM,YAAY,MAAM,KAAK,iBAAiB,UAAU,QAAQ;AAChE,YAAI;AACF,gBAAS,UAAO,SAAS;AACzB,iBAAO,MAAS,YAAS,SAAS;AAAA,QACpC,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,UAAU,UAAoB,MAAc,UAAkC;AAClF,cAAM,YAAY,MAAM,KAAK,iBAAiB,UAAU,QAAQ;AAChE,cAAS,aAAU,WAAW,IAAI;AAAA,MACpC;AAAA;AAAA;AAAA;AAAA,MAKA,mBAA2B;AACzB,eAAO,KAAK,KAAK,KAAK,kBAAkB,GAAG,YAAY;AAAA,MACzD;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,eAGH;AACD,YAAI,eAAe;AACnB,cAAM,cAAc,KAAK,oBAAoB;AAE7C,YAAI;AACF,gBAAS,UAAO,WAAW;AAC3B,gBAAS,MAAG,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACzD;AAAA,QACF,QAAQ;AAAA,QAER;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,aAGH;AACD,YAAI,eAAe;AACnB,cAAM,YAAY,KAAK,kBAAkB;AAEzC,YAAI;AACF,gBAAS,UAAO,SAAS;AACzB,gBAAS,MAAG,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACvD;AAAA,QACF,QAAQ;AAAA,QAER;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,gBAAsB;AAC5B,YAAI,CAAC,KAAK,YAAY;AACpB,gBAAM,WAAW,KAAK,kBAAkB;AACxC,eAAK,aAAa,IAAI,KAAK;AAAA,YACzB,OAAO,IAAI,SAAS;AAAA,cAClB,UAAU,KAAK,KAAK,UAAU,YAAY;AAAA,YAC5C,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AACA,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,UAAU,QAAgB,UAAkB,MAA0B;AAC1E,cAAM,QAAQ,KAAK,cAAc;AACjC,cAAM,MAAM,GAAG,MAAM,IAAI,QAAQ;AACjC,cAAM,MAAM,IAAI,KAAK,IAAI;AAAA,MAC3B;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,UAAmB,QAAgB,UAAqC;AAC5E,cAAM,QAAQ,KAAK,cAAc;AACjC,cAAM,MAAM,GAAG,MAAM,IAAI,QAAQ;AACjC,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,eAAO,QAAQ;AAAA,MACjB;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,eAGH;AACD,YAAI,eAAe;AACnB,cAAM,YAAY,KAAK,kBAAkB;AAEzC,YAAI;AACF,gBAAS,UAAO,SAAS;AACzB,gBAAS,MAAG,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACvD;AAAA,QACF,QAAQ;AAAA,QAER;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC3NA,SAAS,SAAS;AAAlB,IAUM,gBAYO;AAtBb;AAAA;AAAA;AAUA,IAAM,iBAAiB,EAAE,OAAO;AAAA,MAC9B,gBAAgB,EAAE,OAAO;AAAA,MACzB,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACvC,gBAAgB,EAAE,OAAO;AAAA,MACzB,mBAAmB,EAAE,OAAO;AAAA,IAC9B,CAAC;AAOM,IAAM,sBAAN,MAAkD;AAAA,MAC/C;AAAA,MACA;AAAA,MAER,YAAY,QAAgB,aAA0B;AACpD,aAAK,SAAS;AACd,aAAK,cAAc;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,eAAe,UAAkB,MAAyB;AACtE,cAAM,UAAU,KAAK,OAAO,WAAW;AACvC,cAAM,SAAS,KAAK,OAAO,UAAU;AACrC,cAAM,MAAM,GAAG,OAAO,GAAG,QAAQ;AAEjC,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,+BAA+B,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,QACzF;AAEA,eAAO,MAAM,SAAS,KAAK;AAAA,MAC7B;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,mBAAoC;AAChD,cAAM,UAAU,MAAM,KAAK,YAAY,iBAAiB;AACxD,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,aAAa,QAA+B;AAChD,cAAM,QAAQ,MAAM,KAAK,WAAW,CAAC,MAAM,CAAC;AAC5C,YAAI,MAAM,WAAW,GAAG;AACtB,gBAAM,IAAI,MAAM,iBAAiB,MAAM,aAAa;AAAA,QACtD;AACA,eAAO,MAAM,CAAC;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,eAAgC;AACpC,eAAO,MAAM,KAAK,WAAW;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,WAAW,SAAqC;AAC5D,cAAM,gBAAgB,MAAM,KAAK,iBAAiB;AAElD,cAAM,cAA+B;AAAA,UACnC,gBAAgB;AAAA,UAChB,UAAU;AAAA,UACV,gBAAgB,KAAK,OAAO,iBAAiB;AAAA,UAC7C,mBAAmB,KAAK,OAAO,gBAAgB;AAAA,QACjD;AAGA,uBAAe,MAAM,WAAW;AAEhC,cAAM,WAAW,MAAM,KAAK,eAAe,mBAAmB,WAAW;AAGzE,YAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,GAAG;AAClC,gBAAM,IAAI,MAAM,gEAAgE;AAAA,QAClF;AAEA,cAAM,QAOA,SAAS;AAEf,eAAO,MAAM,IAAI,CAAC,UAAU;AAAA,UAC1B,IAAI,KAAK;AAAA,UACT,YAAY,KAAK;AAAA,UACjB,QAAQ;AAAA,YACN,SAAS,KAAK;AAAA,YACd,UAAU,KAAK;AAAA,YACf,OAAO,KAAK;AAAA,UACd;AAAA,UACA,QAAQ,KAAK;AAAA,UACb,WAAW,CAAC;AAAA,QACd,EAAE;AAAA,MACJ;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,WAAW,OAA8B;AAC7C,cAAM,QAAQ,QAAQ;AACtB,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,WAAW,SAAiB,OAA4B;AAC5D,cAAM,QAAQ,QAAQ;AACtB,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,WAAW,SAAgC;AAC/C,cAAM,QAAQ,QAAQ;AACtB,cAAM,IAAI,MAAM,0DAA0D;AAAA,MAC5E;AAAA,IACF;AAAA;AAAA;;;AC1JA,SAAS,oBAAoB;AAA7B,IAsFa;AAtFb;AAAA;AAAA;AAsFO,IAAM,wBAAN,cAAoC,aAAa;AAAA,MAC9C,iBAAiB;AAAA,MACjB,qBAAqB,oBAAI,IAAsB;AAAA,MAC/C,yBAAyB;AAAA,MAEjC,cAAc;AACZ,cAAM;AACN,aAAK,gBAAgB,EAAE;AAAA,MACzB;AAAA;AAAA,MAGA,KAAsC,OAAU,MAAmC;AACjF,eAAO,MAAM,KAAK,OAAO,IAAI;AAAA,MAC/B;AAAA;AAAA,MAGA,GACE,OACA,UACM;AACN,eAAO,MAAM,GAAG,OAAO,QAAQ;AAAA,MACjC;AAAA,MAEA,KACE,OACA,UACM;AACN,eAAO,MAAM,KAAK,OAAO,QAAQ;AAAA,MACnC;AAAA,MAEA,IACE,OACA,UACM;AACN,eAAO,MAAM,IAAI,OAAO,QAAQ;AAAA,MAClC;AAAA;AAAA,MAGA,iBACE,MACA,SACM;AACN,aAAK,KAAK,kBAAkB,EAAE,MAAM,GAAG,QAAQ,CAAC;AAAA,MAClD;AAAA;AAAA,MAGA,WAAW,YAA0B;AACnC,aAAK,iBAAiB,KAAK,IAAI;AAC/B,aAAK,KAAK,eAAe,EAAE,WAAW,CAAC;AAAA,MACzC;AAAA,MAEA,aAAa,aAAqB,YAAoB,QAAgB,OAAsB;AAC1F,cAAM,aAAa,KAAK,MAAO,cAAc,aAAc,GAAG;AAC9D,aAAK,KAAK,kBAAkB,EAAE,aAAa,YAAY,QAAQ,YAAY,MAAM,CAAC;AAAA,MACpF;AAAA,MAEA,cAAc,YAAoB,cAA4B;AAC5D,cAAM,gBAAgB,KAAK,IAAI,IAAI,KAAK;AACxC,aAAK,KAAK,kBAAkB,EAAE,YAAY,cAAc,cAAc,CAAC;AAAA,MACzE;AAAA;AAAA,MAGA,mBAAmB,MAA8B;AAC/C,aAAK,yBAAyB,KAAK,IAAI;AACvC,aAAK,KAAK,yBAAyB,EAAE,KAAK,CAAC;AAAA,MAC7C;AAAA,MAEA,sBAAsB,SAAiB,cAA6B;AAClE,aAAK,KAAK,4BAA4B,EAAE,SAAS,aAAa,CAAC;AAAA,MACjE;AAAA,MAEA,sBAAsB,YAAoB,MAA8B;AACtE,cAAM,gBAAgB,KAAK,IAAI,IAAI,KAAK;AACxC,aAAK,KAAK,4BAA4B,EAAE,YAAY,MAAM,cAAc,CAAC;AAAA,MAC3E;AAAA,MAEA,WAAW,eAAuB,eAAuB,YAA0B;AACjF,aAAK,KAAK,gBAAgB,EAAE,eAAe,eAAe,WAAW,CAAC;AAAA,MACxE;AAAA,MAEA,qBAAqB,UAAoB,OAAoB;AAC3D,aAAK,KAAK,2BAA2B,EAAE,UAAU,MAAM,CAAC;AAAA,MAC1D;AAAA,MAEA,wBAAwB,UAAoB,UAAyB;AACnE,aAAK,KAAK,8BAA8B,EAAE,UAAU,SAAS,CAAC;AAAA,MAChE;AAAA,MAEA,wBAAwB,UAAoB,UAA0B;AACpE,aAAK,KAAK,8BAA8B,EAAE,UAAU,SAAS,CAAC;AAAA,MAChE;AAAA;AAAA,MAGA,cAAc,UAA0B;AACtC,aAAK,mBAAmB,IAAI,UAAU,KAAK,IAAI,CAAC;AAChD,aAAK,KAAK,kBAAkB,EAAE,SAAS,CAAC;AAAA,MAC1C;AAAA,MAEA,iBACE,UACA,SACA,aACA,QACM;AACN,aAAK,KAAK,qBAAqB,EAAE,UAAU,SAAS,aAAa,OAAO,CAAC;AAAA,MAC3E;AAAA,MAEA,iBAAiB,UAA0B;AACzC,cAAM,YAAY,KAAK,mBAAmB,IAAI,QAAQ,KAAK,KAAK,IAAI;AACpE,cAAM,gBAAgB,KAAK,IAAI,IAAI;AACnC,aAAK,mBAAmB,OAAO,QAAQ;AACvC,aAAK,KAAK,qBAAqB,EAAE,UAAU,cAAc,CAAC;AAAA,MAC5D;AAAA;AAAA,MAGA,UACE,QACA,UACA,UACA,QACM;AACN,aAAK,KAAK,cAAc,EAAE,QAAQ,UAAU,UAAU,OAAO,CAAC;AAAA,MAChE;AAAA,MAEA,aACE,QACA,UACA,UACA,SACA,gBAAwB,GAClB;AACN,aAAK,KAAK,iBAAiB,EAAE,QAAQ,UAAU,UAAU,SAAS,cAAc,CAAC;AAAA,MACnF;AAAA;AAAA,MAGA,UAAU,QAAgB,UAAwB;AAChD,aAAK,KAAK,cAAc,EAAE,QAAQ,SAAS,CAAC;AAAA,MAC9C;AAAA,MAEA,YAAY,QAAgB,UAAkB,SAAwB;AACpE,aAAK,KAAK,gBAAgB,EAAE,QAAQ,UAAU,QAAQ,CAAC;AAAA,MACzD;AAAA;AAAA,MAGA,mBAAmB,QAAgB,YAAoB,eAA8B;AACnF,aAAK,KAAK,wBAAwB,EAAE,QAAQ,YAAY,cAAc,CAAC;AAAA,MACzE;AAAA,MAEA,sBACE,QACA,YACA,aACA,cACM;AACN,aAAK,KAAK,2BAA2B,EAAE,QAAQ,YAAY,aAAa,aAAa,CAAC;AAAA,MACxF;AAAA,MAEA,sBACE,QACA,YACA,eACA,gBACA,WACM;AACN,aAAK,KAAK,2BAA2B;AAAA,UACnC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AClQA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAEtB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAJ1B,IAca;AAdb;AAAA;AAAA;AAQA;AAEA;AAIO,IAAM,uBAAN,MAAM,sBAAqB;AAAA,MACxB;AAAA,MACA,aAAuB,CAAC;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAMA,YACN,QACA,aACA,MACA,cACA;AACA,aAAK,cAAc;AACnB,aAAK,OAAO;AACZ,aAAK,eAAe,gBAAgB,IAAI,sBAAsB;AAC9D,aAAK,SAAS;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA,MAKA,aAAa,WACX,QACA,aACA,MACA,cACA,UACA,SAC+B;AAC/B,cAAM,UAAU,IAAI,sBAAqB,QAAQ,aAAa,MAAM,YAAY;AAGhF,cAAM,eAAe,MAAM,QAAQ,cAAc,UAAU,OAAO;AAClE,gBAAQ,aAAa;AAErB,eAAO;AAAA,MACT;AAAA;AAAA,MAIA,IAAI,YAAsB;AACxB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA,MAKA,YAAY,WAA+B;AACzC,cAAM,gBAAgB,UAAU;AAChC,YAAI;AAEJ,YAAI,KAAK,SAAS,SAAS;AACzB,0BAAgB;AAAA,QAClB,WAAW,CAAC,KAAK,UAAU;AACzB,0BAAgB;AAAA,QAClB,OAAO;AACL,0BAAgB,UAAU,OAAO,CAAC,aAAa,KAAK,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,QAC/E;AAGA,YAAI,kBAAkB,cAAc,QAAQ;AAC1C,eAAK,aAAa,WAAW,eAAe,cAAc,QAAQ,GAAG,KAAK,IAAI,aAAa;AAAA,QAC7F;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc,SAA2B;AACvC,cAAM,gBAAgB,QAAQ;AAE9B,cAAM,kBAAkB,QAAQ,OAAO,CAAC,UAAU,KAAK,aAAa,EAAE,MAAM,CAAC,CAAC;AAG9E,YAAI,kBAAkB,gBAAgB,QAAQ;AAC5C,eAAK,aAAa;AAAA,YAChB;AAAA,YACA,gBAAgB;AAAA,YAChB,GAAG,KAAK,IAAI;AAAA,UACd;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,yBAAyB,SAAkB,WAA8B;AACvE,YAAI,QAAQ,WAAW,GAAG;AACxB,iBAAO;AAAA,QACT;AAEA,cAAM,cAAc,IAAI,IAAI,SAAS;AACrC,eAAO,QAAQ,OAAO,CAAC,UAAU,YAAY,IAAI,MAAM,QAAQ,CAAC;AAAA,MAClE;AAAA,MAEA,IAAI,gBAA+B;AACjC,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,MAAc,cAAc,UAAmB,SAAqC;AAElF,aAAK,aAAa,mBAAmB,KAAK,IAAI;AAE9C,YAAI;AAGJ,YAAI,UAAU;AACZ,4BAAkB,MAAM,KAAK,sBAAsB,QAAQ;AAAA,QAC7D,WAAW,KAAK,SAAS,QAAQ;AAE/B,gBAAM,gBAAgB,KAAK,YAAY,iBAAiB;AAExD,cAAI,SAAS;AACX,iBAAK,aAAa,sBAAsB,8BAA8B,OAAO,KAAK;AAAA,UACpF,OAAO;AACL,iBAAK,aAAa,sBAAsB,mCAAmC;AAAA,UAC7E;AAEA,gBAAM,aAAa,MAAM,gBAAgB,eAAe,OAAO;AAG/D,eAAK,WAAW;AAAA,YACd;AAAA,YACA,cAAc,WAAW,MAAM,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,YACpD,eAAe,IAAI,IAAI,WAAW,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,UAAU,IAAI,CAAC,CAAC;AAAA,UAC9E;AAEA,eAAK,aAAa;AAAA,YAChB,SAAS,KAAK,SAAS,aAAa,MAAM;AAAA,UAC5C;AAIA,4BAAkB,KAAK,SAAS,aAC7B,OAAO,CAAC,SAAY,eAAgB,cAAQ,eAAe,IAAI,CAAC,CAAC,EACjE,IAAI,CAAC,SAAS,IAAI;AAGrB,eAAK,aAAa,sBAAsB,6BAA6B;AAErE,gBAAM,oBAAoB,KAAK,OAAO,gBAAgB;AACtD,cAAI,kBAAkB,SAAS,GAAG;AAChC,kBAAM,eAAe,gBAAgB;AACrC,8BAAkB,gBAAgB,OAAO,CAACC,cAAa;AACrD,oBAAM,gBAAgB,kBAAkB;AAAA,gBAAK,CAAC,YAC5C,KAAK,eAAeA,WAAU,OAAO;AAAA,cACvC;AACA,qBAAO,CAAC;AAAA,YACV,CAAC;AAED,gBAAI,iBAAiB,gBAAgB,QAAQ;AAC3C,mBAAK,aAAa;AAAA,gBAChB,gBAAgB,eAAe,gBAAgB,MAAM;AAAA,cACvD;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AAEL,eAAK,aAAa,sBAAsB,iCAAiC;AAEzE,gBAAM,gBAAgB,KAAK,YAAY,iBAAiB;AACxD,gBAAM,oBAAoB,KAAK,OAAO,gBAAgB;AACtD,4BAAkB,MAAM,KAAK,iBAAiB,CAAC,aAAa,GAAG,iBAAiB;AAAA,QAClF;AAGA,aAAK,aAAa,sBAAsB,gBAAgB,QAAQ,KAAK,IAAI;AAEzE,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,sBAAsB,UAAqC;AACvE,cAAM,gBAAgB,KAAK,YAAY,iBAAiB;AACxD,cAAM,WAAgB,cAAQ,eAAe,QAAQ;AACrD,cAAM,oBAAoB,KAAK,OAAO,gBAAgB;AAGtD,YAAI,KAAK,cAAc,QAAQ,GAAG;AAChC,eAAK,aAAa;AAAA,YAChB,4CAA4C,QAAQ;AAAA,UACtD;AACA,iBAAO,MAAM,KAAK,sBAAsB,UAAU,iBAAiB;AAAA,QACrE;AAGA,YAAI,CAAI,eAAW,QAAQ,GAAG;AAC5B,gBAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,QAC/C;AAEA,cAAM,QAAW,aAAS,QAAQ;AAElC,YAAI,MAAM,OAAO,GAAG;AAElB,eAAK,aAAa,sBAAsB,2BAA2B,QAAQ,EAAE;AAG7E,gBAAM,gBAAgB,kBAAkB;AAAA,YAAK,CAAC,YAC5C,KAAK,eAAe,UAAU,OAAO;AAAA,UACvC;AAEA,cAAI,eAAe;AACjB,iBAAK,aAAa,sBAAsB,QAAQ,QAAQ,yBAAyB;AACjF,mBAAO,CAAC;AAAA,UACV,OAAO;AACL,mBAAO,CAAC,QAAQ;AAAA,UAClB;AAAA,QACF,WAAW,MAAM,YAAY,GAAG;AAE9B,eAAK,aAAa,sBAAsB,mCAAmC,QAAQ,EAAE;AACrF,iBAAO,MAAM,KAAK,2BAA2B,UAAU,iBAAiB;AAAA,QAC1E,OAAO;AACL,gBAAM,IAAI,MAAM,yCAAyC,QAAQ,EAAE;AAAA,QACrE;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,cAAc,UAA2B;AAC/C,eAAO,YAAY,KAAK,QAAQ;AAAA,MAClC;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,sBACZ,aACA,gBACmB;AACnB,cAAM,gBAAgB,KAAK,YAAY,iBAAiB;AAGxD,cAAM,oBAAoB,CAAC,sBAAsB,cAAc,GAAG,cAAc;AAEhF,cAAM,UAAU,MAAM,KAAK,aAAa;AAAA,UACtC,KAAK;AAAA,UACL,OAAO;AAAA,UACP,UAAU;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AAED,aAAK,aAAa,sBAAsB,SAAS,QAAQ,MAAM,yBAAyB;AACxF,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,2BACZ,SACA,gBACmB;AACnB,cAAM,gBAAgB,KAAK,YAAY,iBAAiB;AAGxD,cAAM,cAAmB,WAAK,SAAS,MAAM,EAAE,QAAQ,OAAO,GAAG;AAGjE,cAAM,oBAAoB,CAAC,sBAAsB,cAAc,GAAG,cAAc;AAEhF,cAAM,UAAU,MAAM,KAAK,aAAa;AAAA,UACtC,KAAK;AAAA,UACL,OAAO;AAAA,UACP,UAAU;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AAED,aAAK,aAAa,sBAAsB,SAAS,QAAQ,MAAM,qBAAqB;AACpF,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,iBACZ,aACA,gBACmB;AACnB,cAAM,WAAqB,CAAC;AAC5B,cAAM,gBAAgB,KAAK,YAAY,iBAAiB;AAGxD,cAAM,oBAAoB,CAAC,sBAAsB,cAAc,GAAG,cAAc;AAEhF,mBAAW,OAAO,aAAa;AAE7B,gBAAM,QAAW,aAAS,GAAG;AAC7B,cAAI,CAAC,MAAM,YAAY,GAAG;AAExB,kBAAM,eAAe,eAAe,KAAK,CAAC,YAAY,KAAK,eAAe,KAAK,OAAO,CAAC;AACvF,gBAAI,CAAC,cAAc;AACjB,uBAAS,KAAU,eAAS,eAAe,GAAG,CAAC;AAAA,YACjD;AACA;AAAA,UACF;AAGA,gBAAM,UAAU,MAAM,KAAK,QAAQ;AAAA,YACjC,KAAK;AAAA,YACL,OAAO;AAAA,YACP,UAAU;AAAA;AAAA,YACV,QAAQ;AAAA,UACV,CAAC;AAGD,gBAAM,gBAAgB,QAAQ,IAAI,CAAC,UAAU;AAC3C,kBAAM,eAAoB,cAAQ,KAAK,KAAK;AAC5C,mBAAY,eAAS,eAAe,YAAY;AAAA,UAClD,CAAC;AAED,mBAAS,KAAK,GAAG,aAAa;AAAA,QAChC;AAGA,eAAO,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA,MAKQ,eAAe,UAAkB,SAA0B;AACjE,eAAO,UAAU,UAAU,SAAS,EAAE,KAAK,KAAK,CAAC;AAAA,MACnD;AAAA;AAAA;AAAA;AAAA,MAKQ,YAAY,SAAwC;AAC1D,YAAI,KAAK,SAAS,SAAS;AACzB,iBAAO;AAAA,QACT;AAEA,YAAI,CAAC,KAAK,UAAU;AAClB,iBAAO;AAAA,QACT;AAEA,cAAM,EAAE,SAAS,IAAI;AAGrB,eAAO,KAAK,SAAS,aAAa,KAAK,CAAC,gBAAgB;AACtD,iBACE,aAAa,eAAe,SAAS,SAAS,WAAW,KAAK,YAAY,SAAS,QAAQ;AAAA,QAE/F,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKQ,iBAAiB,SAIb;AACV,YAAI,KAAK,SAAS,SAAS;AACzB,iBAAO;AAAA,QACT;AAEA,YAAI,CAAC,KAAK,UAAU;AAClB,iBAAO;AAAA,QACT;AAEA,cAAM,EAAE,UAAU,WAAW,QAAQ,IAAI;AAGzC,cAAM,aAAa,KAAK,SAAS,cAAc,IAAI,QAAQ;AAC3D,YAAI,CAAC,YAAY;AACf,iBAAO;AAAA,QACT;AAGA,YAAI,WAAW,WAAW,SAAS;AACjC,iBAAO;AAAA,QACT;AAGA,YAAI,WAAW,WAAW,WAAW;AACnC,iBAAO;AAAA,QACT;AAGA,eAAO,KAAK,mBAAmB,EAAE,OAAO,WAAW,OAAO,WAAW,QAAQ,CAAC;AAAA,MAChF;AAAA;AAAA;AAAA;AAAA,MAKQ,aAAa,SAAoC;AACvD,YAAI,KAAK,SAAS,SAAS;AACzB,iBAAO;AAAA,QACT;AAEA,YAAI,CAAC,KAAK,UAAU;AAClB,iBAAO;AAAA,QACT;AAEA,cAAM,EAAE,MAAM,IAAI;AAClB,eACE,KAAK,YAAY,EAAE,UAAU,MAAM,SAAS,CAAC,KAC7C,KAAK,iBAAiB;AAAA,UACpB,UAAU,MAAM;AAAA,UAChB,WAAW,MAAM,MAAM,MAAM;AAAA,UAC7B,SAAS,MAAM,MAAM,IAAI;AAAA,QAC3B,CAAC;AAAA,MAEL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQQ,mBAAmB,SAIf;AACV,cAAM,EAAE,OAAO,WAAW,QAAQ,IAAI;AAEtC,cAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,YAAI,iBAAiB;AACrB,YAAI,SAAS;AAEb,mBAAW,QAAQ,OAAO;AAExB,gBAAM,YAAY,KAAK,MAAM,6CAA6C;AAC1E,cAAI,WAAW;AACb,6BAAiB,SAAS,UAAU,CAAC,GAAG,EAAE;AAC1C,qBAAS;AACT;AAAA,UACF;AAEA,cAAI,CAAC,OAAQ;AAEb,cAAI,KAAK,WAAW,GAAG,GAAG;AAExB,gBAAI,kBAAkB,aAAa,kBAAkB,SAAS;AAC5D,qBAAO;AAAA,YACT;AACA;AAAA,UACF,WAAW,KAAK,WAAW,GAAG,GAAG;AAE/B;AAAA,UACF,WAAW,CAAC,KAAK,WAAW,IAAI,GAAG;AAEjC,gBAAI,kBAAkB,aAAa,kBAAkB,SAAS;AAC5D,qBAAO;AAAA,YACT;AACA;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;AC9eA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAEtB,SAAS,aAAAC,kBAAiB;AAH1B,IAmBa;AAnBb;AAAA;AAAA;AAmBO,IAAM,iBAAN,MAAqB;AAAA,MAClB;AAAA,MAER,YAAY,aAA0B;AACpC,aAAK,cAAc;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQQ,eAAeD,QAAc,SAA0B;AAC7D,eAAOC,WAAUD,QAAM,SAAS,EAAE,KAAK,KAAK,CAAC;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA,MAKQ,kBAAkB,WAAgC,UAA2B;AACnF,cAAM,gBAAgB,KAAK,YAAY,iBAAiB;AACxD,cAAM,mBAAwB,cAAQ,eAAe,QAAQ;AAG7D,YAAI,sBAAsB,WAAW;AACnC,gBAAM,EAAE,SAAS,IAAI,UAAU,kBAAkB;AACjD,gBAAM,MAAW,cAAQ,gBAAgB;AACzC,gBAAM,cAAmB,WAAK,KAAK,QAAQ;AAC3C,iBAAU,eAAW,WAAW;AAAA,QAClC;AAGA,YAAI,oBAAoB,WAAW;AACjC,gBAAM,EAAE,QAAQ,IAAI,UAAU,gBAAgB;AAC9C,iBAAO,KAAK,eAAe,UAAU,OAAO;AAAA,QAC9C;AAGA,YAAI,oBAAoB,WAAW;AACjC,gBAAM,EAAE,SAAS,IAAI,UAAU,gBAAgB;AAC/C,cAAI,aAAkB,cAAQ,gBAAgB;AAC9C,gBAAM,OAAY,YAAM,UAAU,EAAE;AAEpC,iBAAO,eAAe,MAAM;AAC1B,kBAAM,aAAkB,WAAK,YAAY,QAAQ;AACjD,gBAAO,eAAW,UAAU,GAAG;AAC7B,qBAAO;AAAA,YACT;AACA,kBAAM,YAAiB,cAAQ,UAAU;AACzC,gBAAI,cAAc,WAAY;AAC9B,yBAAa;AAAA,UACf;AACA,iBAAO;AAAA,QACT;AAGA,YAAI,mBAAmB,WAAW;AAChC,gBAAM,EAAE,QAAQ,IAAI,UAAU,eAAe;AAC7C,gBAAM,MAAW,cAAQ,gBAAgB;AACzC,cAAI,CAAI,eAAW,GAAG,GAAG;AACvB,mBAAO;AAAA,UACT;AACA,gBAAM,WAAc,gBAAY,GAAG;AACnC,iBAAO,SAAS,KAAK,CAAC,YAAY,KAAK,eAAe,SAAS,OAAO,CAAC;AAAA,QACzE;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,mBAAmB,YAAkC,UAA2B;AACtF,cAAM,UAAqB,CAAC;AAG5B,YAAI,WAAW,KAAK;AAClB,kBAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,cAAc,KAAK,kBAAkB,WAAW,QAAQ,CAAC,CAAC;AAAA,QAC/F;AAGA,YAAI,WAAW,KAAK;AAClB,kBAAQ,KAAK,WAAW,IAAI,KAAK,CAAC,cAAc,KAAK,kBAAkB,WAAW,QAAQ,CAAC,CAAC;AAAA,QAC9F;AAGA,YAAI,WAAW,KAAK;AAClB,kBAAQ,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,cAAc,KAAK,kBAAkB,WAAW,QAAQ,CAAC,CAAC;AAAA,QAC/F;AAGA,eAAO,QAAQ,WAAW,IAAI,OAAO,QAAQ,MAAM,CAAC,WAAW,WAAW,IAAI;AAAA,MAChF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,QAAQ,WAAqB,SAAuD;AArH5F;AAsHI,cAAM,YAAY,KAAK,IAAI;AAE3B,YAAI,gBAAgB;AAGpB,aAAI,aAAQ,YAAR,mBAAiB,QAAQ;AAC3B,0BAAgB,cAAc;AAAA,YAAO,CAAC,aACpC,QAAQ,QAAS,KAAK,CAAC,YAAY,KAAK,eAAe,UAAU,OAAO,CAAC;AAAA,UAC3E;AAAA,QACF;AAGA,aAAI,aAAQ,WAAR,mBAAgB,QAAQ;AAC1B,0BAAgB,cAAc,OAAO,CAAC,aAAa;AACjD,kBAAM,gBAAgB,QAAQ,OAAQ;AAAA,cAAK,CAAC,YAC1C,KAAK,eAAe,UAAU,OAAO;AAAA,YACvC;AACA,mBAAO,CAAC;AAAA,UACV,CAAC;AAAA,QACH;AAGA,YAAI,QAAQ,YAAY;AACtB,0BAAgB,cAAc;AAAA,YAAO,CAAC,aACpC,KAAK,mBAAmB,QAAQ,YAAa,QAAQ;AAAA,UACvD;AAAA,QACF;AAEA,cAAM,gBAAgB,KAAK,IAAI,IAAI;AAEnC,eAAO,MAAM,QAAQ,QAAQ;AAAA,UAC3B;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACtJA,SAAS,cAAAE,mBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,OAAOC,WAAU;AAEjB,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,OAAO;AACd,OAAO,SAAS;AAChB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,UAAU;AACjB,OAAO,YAAY;AACnB,OAAO,QAAQ;AACf,OAAO,aAAa;AACpB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,gBAAgB;AACvB,OAAO,UAAU;AACjB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,cAAc;AACrB,OAAO,SAAS;AAChB,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,gBAAgB;AACvB,OAAO,UAAU;AACjB,SAAS,+BAA+B;AAuCxC,SAAS,oBAAoB;AAC3B,QAAM,aAAaA,MAAK,QAAQC,SAAQ,QAAQ,qBAAqB,CAAC;AAGtE,QAAM,cAAcD,MAAK,KAAK,YAAY,sDAAsD;AAChG,MAAID,YAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,YAAYC,MAAK,KAAK,YAAY,oDAAoD;AAC5F,MAAID,YAAW,SAAS,GAAG;AACzB,WAAO;AAAA,EACT;AAGA,QAAM,SAASC,MAAK,KAAK,YAAY,WAAW;AAChD,MAAID,YAAW,MAAM,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAiEO,SAAS,wBAAwB,UAA4B;AAClE,QAAM,YAAYC,MAAK,QAAQ,QAAQ,EAAE,MAAM,CAAC;AAChD,QAAM,WAAW,oCAAoC,SAAS;AAC9D,SAAO,YAAY;AACrB;AAEA,SAAS,oCAAoC,WAAyC;AACpF,SAAQ,OAAO,KAAK,8BAA8B,EAAiB;AAAA,IAAK,CAAC,aACvE,+BAA+B,QAAQ,EAAE,SAAS,SAAS;AAAA,EAC7D;AACF;AA3KA,IAwEMC,UA0BA,aAEA,SAgBA,qBAmCO;AAvJb;AAAA;AAAA;AACA,YAAQ,QAAQ,MAAM;AAAA,IAAC;AAuEvB,IAAMA,WAAU,cAAc,YAAY,MAAM,YAAY,MAAM,UAAU;AA0B5E,IAAM,cAAc,kBAAkB;AAEtC,IAAM,UAA4B;AAAA;AAAA,MAEhC,aAAa;AAAA;AAAA,MAEb,YAAY,CAAC,SAAS;AAAA;AAAA,MAEtB,gBAAgB;AAAA;AAAA,MAEhB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,MAKb,aAAa;AAAA,IACf;AAEA,IAAM,sBAAsB;AAAA,MAC1B,CAAC,uBAAgB,GAAG;AAAA,MACpB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,WAAU,GAAG;AAAA,MACd,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,qBAAe,GAAG;AAAA,MACnB,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,qBAAe,GAAG;AAAA,MACnB,CAAC,aAAW,GAAG;AAAA,MACf,CAAC,uBAAgB,GAAG;AAAA,MACpB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,6BAAmB,GAAG;AAAA,MACvB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,qBAAe,GAAG;AAAA,MACnB,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,yBAAiB,GAAG;AAAA,MACrB,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,qBAAe,GAAG;AAAA,MACnB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,mBAAc,GAAG;AAAA,MAClB,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,mBAAc,GAAG;AAAA,MAClB,CAAC,iBAAa,GAAG;AAAA,MACjB,CAAC,eAAY,GAAG;AAAA,MAChB,CAAC,6BAAmB,GAAG;AAAA,MACvB,CAAC,iBAAa,GAAG;AAAA,MACjB,GAAI,cAAc,EAAE,CAAC,uBAAgB,GAAG,QAAQ,IAAI,CAAC;AAAA,IACvD;AAGA,4BAAwB,mBAAmB;AAEpC,IAAM,iCAA6D,OAAO;AAAA,MAC/E;AAAA,IACF,EAAE;AAAA,MACA,CAAC,KAAK,CAAC,UAAU,YAAY,MAAM;AACjC,YAAI,QAAoB,IAAI,aAAa,cAAc,CAAC;AACxD,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AAAA;AAAA;;;AC/JA,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,WAAU;AAEjB,SAAS,SAAAC,QAAO,kBAAkB;AAHlC,IAgBa;AAhBb;AAAA;AAAA;AAgBO,IAAM,qBAAN,MAAgD;AAAA,MAC7C;AAAA,MACA;AAAA,MAER,YAAY,aAA0B,UAAoB;AACxD,aAAK,cAAc;AACnB,aAAK,WAAW;AAAA,MAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,MAAM,YAAY,WAAqB,QAAsC;AAC3E,YAAI,UAAU,WAAW,GAAG;AAC1B,iBAAO,CAAC;AAAA,QACV;AAGA,cAAM,EAAE,MAAM,YAAY,IAAI;AAG9B,cAAM,YAAY,KAAK,aAAa;AACpC,cAAM,UAAmB,CAAC;AAE1B,iBAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;AACpD,gBAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,SAAS;AAC9C,gBAAM,eAAe,MAAM,KAAK,aAAa,OAAO,MAAM,WAAW;AACrE,kBAAQ,KAAK,GAAG,YAAY;AAAA,QAC9B;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,eAAuB;AAG7B,cAAM,iBAAiB,SAAS,QAAQ,IAAI,sBAAsB,KAAK,EAAE;AAEzE,eAAO,KAAK,IAAI,GAAG,KAAK,MAAM,iBAAiB,CAAC,CAAC;AAAA,MACnD;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,aAAa,WAAqB,MAAW,aAAoC;AAE7F,cAAM,gBAAgB,UAAU,IAAI,OAAO,aAAa;AAEtD,gBAAM,UAAU,MAAMF;AAAA,YACpBC,MAAK,QAAQ,KAAK,YAAY,iBAAiB,GAAG,QAAQ;AAAA,YAC1D;AAAA,UACF;AAGA,gBAAM,OAAO,MAAM,WAAW,KAAK,UAAU,OAAO;AACpD,gBAAM,aAAa,KAAK,KAAK,EAAE,QAAQ;AAAA,YACrC;AAAA,YACA,UAAU,KAAK;AAAA,YACf;AAAA,UACF,CAAC;AAED,iBAAO,WAAW,IAAI,CAAC,YAAY,EAAE,UAAU,OAAO,EAAE;AAAA,QAC1D,CAAC;AAGD,cAAM,eAAe,MAAM,QAAQ,IAAI,aAAa;AACpD,cAAM,UAAU,aAAa,KAAK;AAGlC,cAAM,UAAmB,CAAC;AAC1B,mBAAW,EAAE,UAAU,OAAO,KAAK,SAAS;AAC1C,gBAAM,QAAQ,OAAO,MAAM;AAE3B,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,MAAM,OAAO,KAAK;AAAA,YAClB,OAAO;AAAA,cACL,OAAO;AAAA,gBACL,MAAM,MAAM,MAAM;AAAA,gBAClB,QAAQ,MAAM,MAAM;AAAA,cACtB;AAAA,cACA,KAAK;AAAA,gBACH,MAAM,MAAM,IAAI;AAAA,gBAChB,QAAQ,MAAM,IAAI;AAAA,cACpB;AAAA,YACF;AAAA;AAAA,YAEA,QAAQ,KAAK,cAAc,MAAM;AAAA,YACjC,UAAU,KAAK;AAAA,UACjB,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,cAAc,MAA+B;AACnD,cAAM,OAAO,KAAK,KAAK;AAGvB,YAAI,SAAS,mBAAmB;AAC9B,gBAAM,eAAe,KAAK,MAAM,UAAU;AAC1C,cAAI,cAAc;AAChB,mBAAO,KAAK,cAAc,YAAY;AAAA,UACxC;AAAA,QACF,WAAW,SAAS,qBAAqB;AACvC,gBAAM,eAAe,KAAK,MAAM,UAAU;AAC1C,cAAI,cAAc;AAChB,mBAAO,aAAa,KAAK;AAAA,UAC3B;AAAA,QACF,WAAW,SAAS,cAAc;AAChC,iBAAO,KAAK,KAAK;AAAA,QACnB;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,MAAM,YAAY,OAAqC;AAErD,cAAM,kBAAkB,oBAAI,IAAI;AAAA,UAC9B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,QACF,CAAC;AAED,cAAM,eAAeA,MAAK,QAAQ,KAAK,YAAY,iBAAiB,GAAG,MAAM,QAAQ;AACrF,cAAM,UAAU,MAAMD,UAAS,cAAc,OAAO;AAGpD,cAAM,OAAOE,OAAM,KAAK,UAAU,OAAO,EAAE,KAAK;AAGhD,cAAM,iBAAiB,KAAK;AAAA,UAC1B;AAAA,UACA,MAAM,MAAM,MAAM;AAAA,UAClB,MAAM,MAAM,MAAM;AAAA,QACpB;AAEA,YAAI,CAAC,gBAAgB;AACnB,iBAAO;AAAA,QACT;AAGA,YAAI,UAAyB;AAC7B,eAAO,SAAS;AACd,gBAAM,YAAY,QAAQ,KAAK;AAE/B,gBAAM,UAAU,OAAO,cAAc,WAAW,YAAY,OAAO,SAAS;AAE5E,cAAI,gBAAgB,IAAI,OAAO,GAAG;AAChC,kBAAM,QAAQ,QAAQ,MAAM;AAC5B,mBAAO;AAAA,cACL,UAAU,MAAM;AAAA,cAChB,MAAM,QAAQ,KAAK;AAAA,cACnB,OAAO;AAAA,gBACL,OAAO,EAAE,MAAM,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,OAAO;AAAA,gBAC5D,KAAK,EAAE,MAAM,MAAM,IAAI,MAAM,QAAQ,MAAM,IAAI,OAAO;AAAA,cACxD;AAAA,cACA,QAAQ,MAAM;AAAA,cACd,UAAU,KAAK;AAAA,YACjB;AAAA,UACF;AAEA,oBAAU,QAAQ,OAAO;AAAA,QAC3B;AAGA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,mBAAmB,MAAc,MAAc,QAA+B;AACpF,cAAM,QAAQ,KAAK,MAAM;AAGzB,cAAM,eACJ,OAAO,MAAM,MAAM,QAAS,SAAS,MAAM,MAAM,QAAQ,UAAU,MAAM,MAAM;AACjF,cAAM,cACJ,OAAO,MAAM,IAAI,QAAS,SAAS,MAAM,IAAI,QAAQ,UAAU,MAAM,IAAI;AAE3E,YAAI,CAAC,gBAAgB,CAAC,aAAa;AACjC,iBAAO;AAAA,QACT;AAGA,cAAM,WAAW,KAAK,SAAS;AAC/B,mBAAW,SAAS,UAAU;AAC5B,gBAAM,aAAa,KAAK,mBAAmB,OAAO,MAAM,MAAM;AAC9D,cAAI,YAAY;AACd,mBAAO;AAAA,UACT;AAAA,QACF;AAGA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACvOA,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,WAAU;AAWjB,eAAsB,gBACpB,eACA,UACA,OACiB;AACjB,QAAM,eAAeA,MAAK,QAAQ,eAAe,QAAQ;AACzD,QAAM,UAAU,MAAMD,UAAS,cAAc,OAAO;AACpD,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,QAAM,EAAE,OAAO,IAAI,IAAI;AAEvB,MAAI,MAAM,SAAS,IAAI,MAAM;AAC3B,UAAM,OAAO,MAAM,MAAM,IAAI,KAAK;AAClC,WAAO,KAAK,UAAU,MAAM,QAAQ,IAAI,MAAM;AAAA,EAChD;AAEA,QAAM,SAAmB,CAAC;AAC1B,WAAS,IAAI,MAAM,MAAM,KAAK,IAAI,QAAQ,IAAI,MAAM,QAAQ,KAAK;AAC/D,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,MAAM,MAAM,MAAM;AACpB,aAAO,KAAK,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,IAC1C,WAAW,MAAM,IAAI,MAAM;AACzB,aAAO,KAAK,KAAK,UAAU,GAAG,IAAI,MAAM,CAAC;AAAA,IAC3C,OAAO;AACL,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;AAzCA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,aAAa;AACtB,OAAOE,SAAQ;AACf,SAAS,iBAAAC,sBAAqB;AAC9B,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAqBjB,SAAS,wBACP,MACA,QACA,cACA,UACA,UACQ;AACR,QAAM,OAAO,KAAK,SAAS;AAC3B,YAAU;AAGV,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,QAAM,YAAY,MAAM,IAAI,KAAK;AAGjC,MAAI,oBAAmC;AACvC,aAAW,QAAQ,OAAO;AACxB,UAAM,cAAc,KAAK,KAAK;AAC9B,UAAM,eAAe,YAAY,MAAM,aAAa;AACpD,QAAI,cAAc;AAChB,0BAAoB;AAAA,IACtB;AAAA,EACF;AAGA,aAAW,QAAQ,OAAO;AACxB,UAAM,cAAc,KAAK,KAAK;AAC9B,QAAI,CAAC,YAAa;AAElB,UAAM,eAAe,YAAY,MAAM,aAAa;AAEpD,QAAI,cAAc;AAEhB,UAAI,gBAAgB,mBAAmB;AACrC,cAAM,CAAC,EAAE,aAAa,MAAM,IAAI;AAChC,cAAM,sBAAsBA,MAAK,SAAS,UAAU,WAAW;AAC/D,qBAAa;AAAA,UACX;AAAA,UACA,WAAW,mBAAmB;AAAA,UAC9B;AAAA,UACA,SAAS,QAAQ,EAAE;AAAA,QACrB;AAAA,MACF;AAAA,IACF,OAAO;AAEL,mBAAa,iBAAiB,UAAU,WAAW;AAAA,IACrD;AAAA,EACF;AAEA,SAAO;AACT;AA3EA,IAiBMC,UAEE,MAIF,eA0DO;AAjFb;AAAA;AAAA;AASA;AACA;AAEA;AAEA;AAGA,IAAMA,WAAUH,eAAc,YAAY,MAAM,YAAY,MAAM,UAAU;AAE5E,KAAM,EAAE,SAASG,SAAQ,oDAAoD;AAI7E,IAAM,gBAAgB;AA0Df,IAAM,2BAAN,MAA+D;AAAA,MAC5D;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAA+B;AAAA,MAC/B,kBAAwC;AAAA,MACxC;AAAA,MAER,YAAY,aAA0B,UAAoB,cAAsC;AAC9F,aAAK,cAAc;AACnB,aAAK,UAAU,IAAI,QAAQ,WAAW;AACtC,aAAK,WAAW;AAChB,aAAK,eAAe,gBAAgB,IAAI,sBAAsB;AAAA,MAChE;AAAA;AAAA;AAAA;AAAA,MAKQ,iBAAyB;AAC/B,gBAAQ,KAAK,UAAU;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AACE,mBAAO;AAAA,UACT;AACE,mBAAO;AAAA,UACT;AACE,kBAAM,IAAI,MAAM,uCAAuC,KAAK,QAAQ,EAAE;AAAA,QAC1E;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,mBAAkC;AAE9C,YAAI,KAAK,cAAc,MAAM;AAC3B;AAAA,QACF;AAGA,YAAI,KAAK,oBAAoB,MAAM;AACjC,iBAAO,KAAK;AAAA,QACd;AAGA,aAAK,kBAAkB,KAAK,cAAc;AAC1C,cAAM,KAAK;AAAA,MACb;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,gBAA+B;AAE3C,YAAI,MAAM,KAAK,QAAQ,YAAY,KAAK,UAAU,YAAY,GAAG;AAE/D,gBAAM,KAAK,UAAU;AACrB;AAAA,QACF;AAGA,cAAM,iBAAiB,MAAM,KAAK,QAAQ,iBAAiB,KAAK,UAAU,YAAY;AACtF,cAAM,gBAAgBD,MAAK,KAAKD,IAAG,OAAO,GAAG,cAAc,KAAK,QAAQ,IAAI,KAAK,IAAI,CAAC,MAAM;AAG5F,aAAK,aAAa,cAAc,KAAK,QAAQ;AAG7C,cAAM,cAAc,KAAK,eAAe;AACxC,cAAM,QAAQ,MAAM,aAAa,CAAC,SAAS,YAAY,aAAa,GAAG;AAAA,UACrE,KAAK,KAAK,YAAY,iBAAiB;AAAA,UACvC,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,UAChC,KAAK,QAAQ;AAAA,QACf,CAAC;AAGD,YAAI,iBAAiB;AAErB,cAAM,OAAO,GAAG,QAAQ,CAAC,SAAS;AAEhC,2BAAiB;AAAA,YACf;AAAA,YACA;AAAA,YACA,KAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK,YAAY,iBAAiB;AAAA,UACpC;AAAA,QACF,CAAC;AAED,YAAI,SAAS;AACb,cAAM,OAAO,GAAG,QAAQ,CAAC,SAAS;AAChC,oBAAU,KAAK,SAAS;AACxB,kBAAQ,OAAO,MAAM,IAAI;AAAA,QAC3B,CAAC;AAED,cAAM,IAAI,QAAc,CAACG,UAAS,WAAW;AAC3C,gBAAM,GAAG,SAAS,OAAO,SAAS;AAChC,gBAAI,SAAS,GAAG;AAEd,oBAAML,IAAG,OAAO,eAAe,cAAc;AAC7C,cAAAK,SAAQ;AAAA,YACV,OAAO;AAEL,oBAAML,IAAG,OAAO,aAAa,EAAE,MAAM,MAAM;AAAA,cAE3C,CAAC;AACD,qBAAO,IAAI,MAAM,GAAG,WAAW,2BAA2B,IAAI,aAAa,MAAM,EAAE,CAAC;AAAA,YACtF;AAAA,UACF,CAAC;AACD,gBAAM,GAAG,SAAS,OAAO,QAAQ;AAE/B,kBAAMA,IAAG,OAAO,aAAa,EAAE,MAAM,MAAM;AAAA,YAE3C,CAAC;AACD,mBAAO,GAAG;AAAA,UACZ,CAAC;AAAA,QACH,CAAC;AAED,YAAI,QAAQ;AACV,kBAAQ,MAAM,yBAAyB,MAAM;AAAA,QAC/C;AAGA,aAAK,aAAa,iBAAiB,KAAK,QAAQ;AAGhD,cAAM,KAAK,UAAU;AAAA,MACvB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,gBAAgB,OAAgC;AACpD,cAAM,KAAK,iBAAiB;AAE5B,YAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,sBAAsB;AAE3D,aAAK,aAAa,qBAAqB,KAAK,UAAU,KAAK;AAE3D,cAAM,cAAuB,CAAC;AAC9B,cAAM,YAAY,KAAK,UAAU;AAEjC,mBAAW,YAAY,WAAW;AAEhC,cAAI,SAAS,kBAAkB,MAAM,SAAU;AAE/C,eAAK,aAAa,wBAAwB,KAAK,UAAU,QAAQ;AAGjE,gBAAM,UAAU,KAAK,8BAA8B,SAAS,aAAa,KAAK;AAE9E,cAAI,SAAS;AAEX,gBAAI,KAAK,iBAAiB,QAAQ,MAAM,GAAG;AACzC;AAAA,YACF;AAEA,iBAAK,aAAa,wBAAwB,KAAK,UAAU,OAAO;AAGhE,kBAAM,MAAM,MAAM,KAAK,wBAAwB,QAAQ,QAAQ,SAAS;AACxE,gBAAI,KAAK;AACP,0BAAY,KAAK,GAAG;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,eAAe,OAAgC;AACnD,cAAM,KAAK,iBAAiB;AAE5B,YAAI,CAAC,KAAK,WAAW;AACnB,iBAAO,CAAC;AAAA,QACV;AAEA,cAAM,aAAsB,CAAC;AAC7B,cAAM,YAAY,KAAK,UAAU;AAEjC,mBAAW,YAAY,WAAW;AAEhC,cAAI,SAAS,kBAAkB,MAAM,SAAU;AAG/C,gBAAM,UAAU,KAAK,8BAA8B,SAAS,aAAa,KAAK;AAE9E,cAAI,SAAS;AAEX,gBAAI,KAAK,iBAAiB,QAAQ,MAAM,GAAG;AACzC;AAAA,YACF;AAGA,kBAAM,OAAO,MAAM,KAAK,wBAAwB,QAAQ,QAAQ,SAAS;AACzE,uBAAW,KAAK,GAAG,IAAI;AACvB;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,iBAAiB,QAAyB;AAGhD,eAAO,OAAO,SAAS,cAAc,KAAK,OAAO,WAAW,MAAM;AAAA,MACpE;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,8BACN,aACA,OACwB;AAMxB,cAAM,aAAiC,CAAC;AAExC,mBAAW,WAAW,aAAa;AACjC,gBAAM,QAAQ,QAAQ;AACtB,cAAI,CAAC,SAAS,MAAM,SAAS,EAAG;AAGhC,cAAI,CAAC,KAAK,cAAc,OAAO,KAAK,EAAG;AAGvC,cAAI,QAAQ;AAGZ,cAAI,CAAC,KAAK,iBAAiB,OAAO,KAAK,EAAG;AAG1C,gBAAM,WAAW,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC;AACxD,mBAAS,WAAW;AAGpB,cAAI,QAAQ,iBAAiB,KAAK,WAAW,YAAY;AACvD,qBAAS;AAAA,UACX;AAGA,cAAI,MAAM,QAAQ;AAChB,kBAAM,EAAE,WAAW,WAAW,IAAI,KAAK,mBAAmB,QAAQ,MAAM;AACxE,gBAAI,eAAe,MAAM,UAAU,cAAc,MAAM,QAAQ;AAC7D,uBAAS;AAAA,YACX;AAAA,UACF;AAEA,qBAAW,KAAK,EAAE,YAAY,SAAS,MAAM,CAAC;AAAA,QAChD;AAGA,YAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,mBAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,eAAO,WAAW,CAAC,EAAE;AAAA,MACvB;AAAA;AAAA;AAAA;AAAA,MAKQ,cAAc,WAAqB,OAAuB;AAChE,YAAI,UAAU,WAAW,GAAG;AAC1B,gBAAM,CAAC,MAAM,UAAU,MAAM,IAAI;AAEjC,cAAI,MAAM,MAAM,MAAM,SAAS,MAAM,MAAM,IAAI,MAAM;AAEnD,mBACE,SAAS,MAAM,MAAM,MAAM,QAC3B,EAAE,UAAU,MAAM,MAAM,MAAM,UAAU,YAAY,MAAM,MAAM,IAAI;AAAA,UAExE,OAAO;AAEL,gBAAI,OAAO,MAAM,MAAM,MAAM,QAAQ,OAAO,MAAM,MAAM,IAAI,KAAM,QAAO;AACzE,gBAAI,SAAS,MAAM,MAAM,MAAM,QAAQ,UAAU,MAAM,MAAM,MAAM,OAAQ,QAAO;AAClF,gBAAI,SAAS,MAAM,MAAM,IAAI,QAAQ,YAAY,MAAM,MAAM,IAAI,OAAQ,QAAO;AAChF,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,UAAU,WAAW,GAAG;AACjC,gBAAM,CAAC,WAAW,WAAW,SAAS,OAAO,IAAI;AAEjD,cAAI,UAAU,MAAM,MAAM,MAAM,QAAQ,YAAY,MAAM,MAAM,IAAI,KAAM,QAAO;AACjF,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,iBAAiB,WAAqB,OAAuB;AACnE,YAAI,UAAU,WAAW,GAAG;AAC1B,gBAAM,CAAC,MAAM,UAAU,MAAM,IAAI;AACjC,cAAI,OAAO,MAAM,MAAM,MAAM,QAAQ,OAAO,MAAM,MAAM,IAAI,KAAM,QAAO;AACzE,cAAI,SAAS,MAAM,MAAM,MAAM,QAAQ,WAAW,MAAM,MAAM,MAAM,OAAQ,QAAO;AACnF,cAAI,SAAS,MAAM,MAAM,IAAI,QAAQ,SAAS,MAAM,MAAM,IAAI,OAAQ,QAAO;AAC7E,iBAAO;AAAA,QACT,WAAW,UAAU,WAAW,GAAG;AACjC,gBAAM,CAAC,WAAW,UAAU,SAAS,MAAM,IAAI;AAC/C,cAAI,YAAY,MAAM,MAAM,MAAM,KAAM,QAAO;AAC/C,cAAI,UAAU,MAAM,MAAM,IAAI,KAAM,QAAO;AAC3C,cAAI,cAAc,MAAM,MAAM,MAAM,QAAQ,WAAW,MAAM,MAAM,MAAM,OAAQ,QAAO;AACxF,cAAI,YAAY,MAAM,MAAM,IAAI,QAAQ,SAAS,MAAM,MAAM,IAAI,OAAQ,QAAO;AAChF,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWQ,mBAAmB,QAGzB;AAMA,cAAM,mBAAmB,OAAO,MAAM,sCAAsC;AAC5E,YAAI,kBAAkB;AACpB,iBAAO;AAAA,YACL,WAAW,iBAAiB,CAAC;AAAA,YAC7B,YAAY,iBAAiB,CAAC;AAAA,UAChC;AAAA,QACF;AAGA,cAAM,cAAc,OAAO,MAAM,4BAA4B;AAC7D,YAAI,aAAa;AACf,iBAAO;AAAA,YACL,WAAW;AAAA,YACX,YAAY,YAAY,CAAC;AAAA,UAC3B;AAAA,QACF;AAEA,eAAO,EAAE,WAAW,MAAM,YAAY,KAAK;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,wBACZ,QACA,WACuB;AACvB,mBAAW,YAAY,WAAW;AAChC,qBAAW,OAAO,SAAS,aAAa;AACtC,gBAAI,IAAI,WAAW,UAAU,IAAI,iBAAiB,KAAK,WAAW,YAAY;AAC5E,oBAAM,QAAQ,IAAI,SAAS,CAAC;AAG5B,oBAAM,YAAY,MAAM,CAAC,KAAK;AAC9B,oBAAM,cAAc,MAAM,CAAC,KAAK;AAChC,oBAAM,UAAU,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI;AAChD,oBAAM,YAAY,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;AAE9D,oBAAM,OAAO,MAAM;AAAA,gBACjB,KAAK,YAAY,iBAAiB;AAAA,gBAClC,SAAS;AAAA,gBACT;AAAA,kBACE,OAAO,EAAE,MAAM,WAAW,QAAQ,YAAY;AAAA,kBAC9C,KAAK,EAAE,MAAM,SAAS,QAAQ,UAAU;AAAA,gBAC1C;AAAA,cACF;AAEA,qBAAO;AAAA,gBACL,UAAU,KAAK;AAAA,gBACf,UAAU,SAAS;AAAA,gBACnB,OAAO;AAAA,kBACL,OAAO,EAAE,MAAM,WAAW,QAAQ,YAAY;AAAA,kBAC9C,KAAK,EAAE,MAAM,SAAS,QAAQ,UAAU;AAAA,gBAC1C;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,wBACZ,QACA,WACkB;AAClB,cAAM,aAAsB,CAAC;AAE7B,mBAAW,YAAY,WAAW;AAChC,qBAAW,OAAO,SAAS,aAAa;AAEtC,gBAAI,IAAI,WAAW,UAAU,IAAI,iBAAiB,KAAK,WAAW,YAAY;AAC5E,oBAAM,QAAQ,IAAI,SAAS,CAAC;AAG5B,oBAAM,YAAY,MAAM,CAAC,KAAK;AAC9B,oBAAM,cAAc,MAAM,CAAC,KAAK;AAChC,oBAAM,UAAU,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI;AAChD,oBAAM,YAAY,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;AAE9D,oBAAM,OAAO,MAAM;AAAA,gBACjB,KAAK,YAAY,iBAAiB;AAAA,gBAClC,SAAS;AAAA,gBACT;AAAA,kBACE,OAAO,EAAE,MAAM,WAAW,QAAQ,YAAY;AAAA,kBAC9C,KAAK,EAAE,MAAM,SAAS,QAAQ,UAAU;AAAA,gBAC1C;AAAA,cACF;AAEA,yBAAW,KAAK;AAAA,gBACd,UAAU,KAAK;AAAA,gBACf,UAAU,SAAS;AAAA,gBACnB,OAAO;AAAA,kBACL,OAAO,EAAE,MAAM,WAAW,QAAQ,YAAY;AAAA,kBAC9C,KAAK,EAAE,MAAM,SAAS,QAAQ,UAAU;AAAA,gBAC1C;AAAA,gBACA;AAAA,gBACA;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,YAA2B;AAC/B,cAAM,SAAS,MAAM,KAAK,QAAQ,UAAU,KAAK,UAAU,YAAY;AACvE,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,MAAM,iCAAiC,KAAK,QAAQ,EAAE;AAAA,QAClE;AACA,aAAK,YAAY,KAAK,WAAW,IAAI,WAAW,MAAM,CAAC;AAAA,MACzD;AAAA;AAAA;AAAA;AAAA,MAKQ,WAAW,QAAgC;AACjD,eAAO,KAAK,MAAM,YAAY,MAAM;AAAA,MACtC;AAAA,IACF;AAAA;AAAA;;;ACtiBA,IAkDa,kCAWA;AA7Db;AAAA;AAAA;AAEA;AACA;AA+CO,IAAM,mCAAN,cAA+C,MAAM;AAAA,MAC1D,YAAY,YAAoB,QAAgB;AAC9C,cAAM,GAAG,UAAU,sBAAsB,MAAM,EAAE;AACjD,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAMO,IAAM,kBAAN,MAAsB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MAER,YAAY,aAA0B,UAAoB,cAAsC;AAC9F,aAAK,WAAW;AAEhB,aAAK,cAAc,IAAI,mBAAmB,aAAa,QAAQ;AAC/D,aAAK,uBAAuB,IAAI,yBAAyB,aAAa,UAAU,YAAY;AAAA,MAC9F;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,YAAY,WAAqB,QAA+C;AACpF,YAAI,CAAC,KAAK,aAAa;AACrB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO,MAAM,KAAK,YAAY,YAAY,WAAW,MAAM;AAAA,MAC7D;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,gBAAgB,OAAgC;AACpD,YAAI,CAAC,KAAK,sBAAsB;AAC9B,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO,MAAM,KAAK,qBAAqB,gBAAgB,KAAK;AAAA,MAC9D;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,eAAe,OAAgC;AACnD,YAAI,CAAC,KAAK,sBAAsB;AAC9B,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO,MAAM,KAAK,qBAAqB,eAAe,KAAK;AAAA,MAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,YAAY,OAAqC;AACrD,YAAI,CAAC,KAAK,aAAa;AACrB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO,MAAM,KAAK,YAAY,YAAY,KAAK;AAAA,MACjD;AAAA,IACF;AAAA;AAAA;;;AC7HA,OAAOM,WAAU;AAAjB,IAea;AAfb;AAAA;AAAA;AAIA;AACA;AAUO,IAAM,kBAAN,MAAsB;AAAA,MACnB;AAAA,MACA;AAAA,MAER,YAAY,aAA0B,cAAsC;AAC1E,aAAK,cAAc;AACnB,aAAK,eAAe;AAAA,MACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,MAAM,QACJ,QACA,UACA,SAC4B;AAC5B,cAAM,YAAY,KAAK,IAAI;AAG3B,cAAM,wBAAwB,QAAQ,UAAU,OAAO,CAAC,aAAa;AACnE,gBAAM,eAAe,wBAAwB,QAAQ;AACrD,iBAAO,iBAAiB;AAAA,QAC1B,CAAC;AAGD,cAAM,UAAU,IAAI,gBAAgB,KAAK,aAAa,UAAU,KAAK,YAAY;AAGjF,cAAM,aAAa,MAAM,QAAQ,YAAY,uBAAuB,MAAM;AAG1E,cAAM,sBAAsB,WAAW,IAAI,CAAC,UAAU;AACpD,cAAIA,MAAK,WAAW,MAAM,QAAQ,GAAG;AACnC,kBAAM,IAAI;AAAA,cACR,0CAA0C,MAAM,QAAQ;AAAA,YAC1D;AAAA,UACF;AACA,iBAAO;AAAA,YACL,GAAG;AAAA,YACH;AAAA,UACF;AAAA,QACF,CAAC;AAGD,YAAI,kBACF,QAAQ,mBAAmB,QAAQ,gBAAgB,SAAS,IACxD,KAAK,sBAAsB,qBAAqB,QAAQ,iBAAiB,QAAQ,IACjF;AAGN,0BAAkB,KAAK,mBAAmB,eAAe;AAEzD,cAAM,gBAAgB,KAAK,IAAI,IAAI;AAEnC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,cAAc,gBAAgB;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOQ,sBACN,SACA,iBACA,WACS;AACT,cAAM,SAAkB,CAAC;AAEzB,mBAAW,SAAS,SAAS;AAE3B,gBAAM,kBAAkB,gBAAgB;AAAA,YAAK,CAAC,cAC5C,KAAK,eAAe,OAAO,SAAS;AAAA,UACtC;AAEA,cAAI,CAAC,iBAAiB;AACpB;AAAA,UACF;AAGA,gBAAM,SAAkC;AAAA,YACtC,GAAI,gBAAgB,UAAU,CAAC;AAAA,YAC/B;AAAA,cACE,UAAU,gBAAgB;AAAA,cAC1B,MAAM,gBAAgB;AAAA,cACtB,OAAO,gBAAgB;AAAA,cACvB,QAAQ,gBAAgB;AAAA,cACxB,UAAU,gBAAgB;AAAA,YAC5B;AAAA,UACF;AAEA,iBAAO,KAAK;AAAA,YACV,GAAG;AAAA,YACH;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,eAAe,OAAc,YAA4B;AAE/D,YAAI,MAAM,aAAa,WAAW,UAAU;AAC1C,iBAAO;AAAA,QACT;AAEA,cAAM,aAAa,MAAM,MAAM;AAC/B,cAAM,WAAW,MAAM,MAAM;AAC7B,cAAM,aAAa,WAAW,MAAM;AACpC,cAAM,WAAW,WAAW,MAAM;AAGlC,cAAM,eACJ,WAAW,OAAO,WAAW,QAC5B,WAAW,SAAS,WAAW,QAAQ,WAAW,UAAU,WAAW;AAG1E,cAAM,aACJ,SAAS,OAAO,SAAS,QACxB,SAAS,SAAS,SAAS,QAAQ,SAAS,UAAU,SAAS;AAElE,eAAO,gBAAgB;AAAA,MACzB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,mBAAmB,SAA2B;AACpD,YAAI,QAAQ,UAAU,GAAG;AACvB,iBAAO;AAAA,QACT;AAEA,cAAM,SAAkB,CAAC;AAEzB,mBAAW,SAAS,SAAS;AAE3B,gBAAM,uBAAuB,QAAQ,KAAK,CAAC,eAAe;AACxD,gBAAI,UAAU,WAAY,QAAO;AAEjC,mBAAO,KAAK,eAAe,OAAO,UAAU;AAAA,UAC9C,CAAC;AAGD,cAAI,CAAC,sBAAsB;AACzB,mBAAO,KAAK,KAAK;AAAA,UACnB;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;AClLA,OAAOC,WAAU;AAEjB,SAAS,aAAAC,kBAAiB;AAF1B,IA2Ea;AA3Eb;AAAA;AAAA;AAMA;AACA;AAoEO,IAAM,qBAAN,MAAyB;AAAA,MACb,WAAmB;AAAA,MAC5B;AAAA,MACA;AAAA,MAER,YAAY,aAA0B,cAAsC;AAC1E,aAAK,cAAc;AACnB,aAAK,eAAe,gBAAgB,IAAI,sBAAsB;AAAA,MAChE;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,QACJ,SACA,UACA,UAAiC,CAAC,GACH;AAC/B,cAAM,YAAY,KAAK,IAAI;AAG3B,cAAM,UAAU,IAAI,gBAAgB,KAAK,aAAa,UAAU,KAAK,YAAY;AAGjF,cAAM,cAAc,MAAM,KAAK;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,QAAQ;AAAA,UACR;AAAA,QACF;AAEA,cAAM,gBAAgB,KAAK,IAAI,IAAI;AAGnC,cAAM,uBAAgC,YAAY,IAAI,CAAC,QAAQ;AAC7D,gBAAM,EAAE,OAAO,QAAQ,aAAa,GAAG,MAAM,IAAI;AAGjD,gBAAM,SAAS,cACX;AAAA,YACE;AAAA,cACE,UAAU,YAAY;AAAA,cACtB,MAAM,YAAY;AAAA,cAClB,OAAO,YAAY;AAAA,cACnB,QAAQ,YAAY;AAAA,cACpB,UAAU,YAAY;AAAA,YACxB;AAAA,YACA,GAAI,YAAY,UAAU,CAAC;AAAA,UAC7B,IACA,CAAC;AAEL,iBAAO;AAAA,YACL,GAAG;AAAA,YACH;AAAA,UACF;AAAA,QACF,CAAC;AAED,eAAO;AAAA,UACL,aAAa;AAAA,UACb,kBAAkB,qBAAqB;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,kBACZ,SACA,SACA,UACA,QACA,UAC2B;AAC3B,cAAM,cAAgC,CAAC;AACvC,cAAM,UAAU,oBAAI,IAAY;AAEhC,mBAAW,SAAS,SAAS;AAC3B,gBAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,2BACZ,OACA,SACA,cACA,UACA,QACA,aACA,SACA,aACA,UACe;AACf,YAAI,gBAAgB,UAAU;AAC5B;AAAA,QACF;AAGA,cAAM,MAAM,GAAG,MAAM,QAAQ,IAAI,MAAM,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM,MAAM,MAAM,IAAI,MAAM,UAAU,EAAE;AACzG,YAAI,QAAQ,IAAI,GAAG,GAAG;AACpB;AAAA,QACF;AACA,gBAAQ,IAAI,GAAG;AAGf,cAAM,qBAAqB,MAAM,QAAQ,gBAAgB,KAAK;AAE9D,mBAAW,cAAc,oBAAoB;AAE3C,gBAAM,cAAe,MAAM,QAAQ,YAAY,UAAU,KAAM;AAG/D,gBAAM,YAA4B;AAAA,YAChC,GAAG;AAAA,YACH;AAAA,YACA,OAAO;AAAA,YACP,aAAa,eAAe;AAAA,UAC9B;AAGA,cAAI,UAAU,CAAC,KAAK,wBAAwB,WAAW,MAAM,GAAG;AAC9D;AAAA,UACF;AAEA,sBAAY,KAAK,SAAS;AAG1B,cAAI,eAAe,IAAI,UAAU;AAC/B,kBAAM,KAAK;AAAA,cACT;AAAA,cACA;AAAA,cACA,eAAe;AAAA,cACf;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,eAAe;AAAA,cACf;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,wBAAwB,KAAqB,QAAmC;AA7O1F;AA+OI,YAAI,OAAO,KAAK;AACd,iBAAO,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,wBAAwB,KAAK,CAAC,CAAC;AAAA,QACrE;AACA,YAAI,OAAO,KAAK;AACd,iBAAO,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,wBAAwB,KAAK,CAAC,CAAC;AAAA,QACpE;AACA,YAAI,OAAO,KAAK;AACd,iBAAO,CAAC,KAAK,wBAAwB,KAAK,OAAO,GAAG;AAAA,QACtD;AAGA,YAAI,OAAO,MAAM;AACf,cAAI,CAAC,KAAK,gBAAiB,IAAc,UAAU,OAAO,IAAI,GAAG;AAC/D,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,aAAI,YAAO,WAAP,mBAAe,MAAM;AACvB,gBAAM,SAAU,IAAc;AAC9B,cAAI,CAAC,UAAU,CAAC,KAAK,gBAAgB,QAAQ,OAAO,OAAO,IAAI,GAAG;AAChE,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,aAAI,YAAO,aAAP,mBAAiB,MAAM;AACzB,gBAAM,SAAU,IAAc;AAC9B,cAAI,CAAC,UAAU,CAAC,KAAK,gBAAgB,QAAQ,OAAO,SAAS,IAAI,GAAG;AAClE,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,aAAI,YAAO,UAAP,mBAAc,MAAM;AAAA,QAGxB;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,gBAAgB,MAAc,MAAyB;AAC7D,YAAI,KAAK,QAAQ;AACf,iBAAO,SAAS,KAAK;AAAA,QACvB;AACA,YAAI,KAAK,OAAO;AACd,iBAAO,KAAK,MAAM,SAAS,IAAI;AAAA,QACjC;AACA,YAAI,KAAK,OAAO;AACd,gBAAM,QAAQ,IAAI,OAAO,KAAK,KAAK;AACnC,iBAAO,MAAM,KAAK,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,gBAAgB,UAAkB,MAA0B;AAClE,cAAM,eAAeD,MAAK,SAAS,KAAK,YAAY,iBAAiB,GAAG,QAAQ;AAEhF,YAAI,KAAK,MAAM;AACb,iBAAO,iBAAiB,KAAK;AAAA,QAC/B;AACA,YAAI,KAAK,MAAM;AACb,iBAAOC,WAAU,cAAc,KAAK,IAAI;AAAA,QAC1C;AACA,YAAI,KAAK,OAAO;AACd,gBAAM,QAAQ,IAAI,OAAO,KAAK,KAAK;AACnC,iBAAO,MAAM,KAAK,YAAY;AAAA,QAChC;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACzTA,IAYa;AAZb;AAAA;AAAA;AAOA;AAKO,IAAM,qCAAN,MAAgF;AAAA,MAC7E;AAAA,MAER,YAAY,QAAgB;AAC1B,aAAK,SAAS;AAAA,MAChB;AAAA,MAEA,MAAM,mBACJ,QACsC;AArB1C;AAuBI,cAAM,iBAAiB,OAAO,QAAQ,IAAI,CAAC,WAAW;AAAA,UACpD;AAAA,UACA,SAAS,KAAK,gBAAgB,KAAK;AAAA,QACrC,EAAE;AAEF,cAAM,UAAU,KAAK,OAAO,WAAW;AACvC,cAAM,SAAS,KAAK,OAAO,UAAU;AAErC,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,4BAA4B;AAAA,UACjE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,MAAM,OAAO;AAAA,YACb,SAAS,eAAe,IAAI,CAAC,EAAE,OAAO,QAAQ,OAAO;AAAA,cACnD;AAAA,cACA,UAAU,MAAM;AAAA,cAChB,OAAO,MAAM;AAAA,cACb,MAAM,MAAM;AAAA,cACZ,UAAU,MAAM;AAAA,cAChB,QAAQ,MAAM;AAAA,cACd,QAAQ,MAAM;AAAA,YAChB,EAAE;AAAA,YACF,mBAAmB,KAAK,OAAO,gBAAgB;AAAA,YAC/C,gBAAgB,KAAK,OAAO,iBAAiB;AAAA,UAC/C,CAAC;AAAA,QACH,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,gBAAM,IAAI;AAAA,YACR,8BAA8B,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,UACrF;AAAA,QACF;AAEA,cAAM,SAAS,MAAM,SAAS,KAAK;AAGnC,cAAM,UAAuC,CAAC;AAC9C,mBAAW,EAAE,QAAQ,KAAK,gBAAgB;AACxC,gBAAM,oBAAmB,YAAO,YAAP,mBAAgB,KAAK,CAAC,MAAW,EAAE,YAAY;AAExE,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,aAAa,QAAQ,qDAAkB,WAAW;AAAA,YAClD,QAAQ,QAAO,qDAAkB,WAAU,uBAAuB;AAAA,YAClE,YACE,QAAO,qDAAkB,gBAAe,WAAW,iBAAiB,aAAa;AAAA,UACrF,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,gBAAgB,OAAsB;AAC5C,cAAM,YAAY;AAAA,UAChB,UAAU,MAAM;AAAA,UAChB,WAAW,MAAM,MAAM,MAAM;AAAA,UAC7B,aAAa,MAAM,MAAM,MAAM,UAAU;AAAA,UACzC,SAAS,MAAM,MAAM,IAAI;AAAA,UACzB,WAAW,MAAM,MAAM,IAAI,UAAU;AAAA,UACrC,MAAM,MAAM;AAAA,QACd;AACA,eAAO,WAAW,KAAK,UAAU,SAAS,CAAC,EAAE,UAAU,GAAG,EAAE;AAAA,MAC9D;AAAA,IACF;AAAA;AAAA;;;AC7FA,IAwBa;AAxBb;AAAA;AAAA;AAEA;AAEA;AACA;AAGA;AAgBO,IAAM,UAAN,MAAc;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACR,YAAY,QAAgB,aAA0B,cAAsC;AAC1F,aAAK,cAAc;AACnB,aAAK,eAAe,gBAAgB,IAAI,sBAAsB;AAC9D,aAAK,SAAS;AACd,aAAK,UAAU,IAAI,QAAQ,WAAW;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,gBAAgB,OAAsB;AAC5C,cAAM,YAAY;AAAA,UAChB,UAAU,MAAM;AAAA,UAChB,WAAW,MAAM,MAAM,MAAM;AAAA,UAC7B,aAAa,MAAM,MAAM,MAAM,UAAU;AAAA,UACzC,SAAS,MAAM,MAAM,IAAI;AAAA,UACzB,WAAW,MAAM,MAAM,IAAI,UAAU;AAAA,UACrC,MAAM,MAAM;AAAA,QACd;AACA,eAAO,WAAW,KAAK,UAAU,SAAS,CAAC,EAAE,UAAU,GAAG,EAAE;AAAA,MAC9D;AAAA;AAAA;AAAA;AAAA,MAKQ,WAAW,QAAwB;AACzC,eAAO,WAAW,MAAM;AAAA,MAC1B;AAAA;AAAA;AAAA;AAAA,MAKQ,sBAAsB,SAAiB,YAA4B;AACzE,eAAO,SAAS,OAAO,WAAW,UAAU;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,MAAc,qBAAqB,MAAY,iBAAkD;AAC/F,cAAM,eAAe,KAAK,IAAI;AAG9B,cAAM,aAAa,KAAK,WAAW,KAAK,MAAM;AAG9C,cAAM,qBAAqB,IAAI,mCAAmC,KAAK,MAAM;AAE7E,cAAM,mBAA8C;AAAA,UAClD;AAAA,UACA,SAAS;AAAA,QACX;AAGA,aAAK,aAAa,mBAAmB,KAAK,IAAI,gBAAgB,MAAM;AAGpE,cAAM,oBAAoB,MAAM,mBAAmB,mBAAmB,gBAAgB;AAGtF,cAAM,sBAA+B,CAAC;AACtC,mBAAW,UAAU,mBAAmB;AACtC,gBAAM,gBAAgB,gBAAgB;AAAA,YACpC,CAAC,UAAU,KAAK,gBAAgB,KAAK,MAAM,OAAO;AAAA,UACpD;AACA,cAAI,iBAAiB,OAAO,aAAa;AACvC,gCAAoB,KAAK;AAAA,cACvB,GAAG;AAAA,cACH,UAAU;AAAA,gBACR,WAAW;AAAA,gBACX,eAAe;AAAA,kBACb,aAAa;AAAA,kBACb,YAAY,OAAO;AAAA,kBACnB,QAAQ,OAAO;AAAA,gBACjB;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAGA,gBAAM,WAAW,KAAK,sBAAsB,OAAO,SAAS,UAAU;AACtE,gBAAM,WAA6B;AAAA,YACjC,SAAS,OAAO;AAAA,YAChB,aAAa,OAAO;AAAA,YACpB,YAAY,OAAO;AAAA,YACnB,QAAQ,OAAO;AAAA,UACjB;AACA,gBAAM,KAAK,QAAQ,UAAU,KAAK,IAAI,UAAU,QAAQ;AAAA,QAC1D;AAGA,aAAK,aAAa;AAAA,UAChB,KAAK;AAAA,UACL;AAAA;AAAA,UACA,KAAK,IAAI,IAAI;AAAA,UACb,oBAAoB;AAAA,UACpB;AAAA,QACF;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe,KAAK,IAAI,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,MAAM,QAAQ,MAAY,iBAA2D;AACnF,cAAM,YAAY,KAAK,IAAI;AAI3B,cAAM,aAAa,KAAK,WAAW,KAAK,MAAM;AAG9C,cAAM,gBAAyB,CAAC;AAChC,cAAM,kBAA2B,CAAC;AAElC,mBAAW,SAAS,iBAAiB;AACnC,gBAAM,UAAU,KAAK,gBAAgB,KAAK;AAC1C,gBAAM,WAAW,KAAK,sBAAsB,SAAS,UAAU;AAE/D,gBAAM,iBAAiB,MAAM,KAAK,QAAQ,UAA4B,KAAK,IAAI,QAAQ;AAEvF,cAAI,gBAAgB;AAElB,gBAAI,eAAe,aAAa;AAE9B,4BAAc,KAAK;AAAA,gBACjB,GAAG;AAAA,gBACH,UAAU;AAAA,kBACR,WAAW;AAAA,kBACX,eAAe;AAAA,oBACb,aAAa,eAAe;AAAA,oBAC5B,YAAY,eAAe;AAAA,oBAC3B,QAAQ,eAAe;AAAA,kBACzB;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UAEF,OAAO;AAEL,4BAAgB,KAAK,KAAK;AAAA,UAC5B;AAAA,QACF;AAGA,YAAI,sBAA+B,CAAC;AACpC,YAAI,gBAAgB,SAAS,GAAG;AAC9B,gBAAM,YAAY,MAAM,KAAK,qBAAqB,MAAM,eAAe;AACvE,gCAAsB,UAAU;AAAA,QAClC;AAGA,YAAI,gBAAgB,WAAW,GAAG;AAChC,eAAK,aAAa;AAAA,YAChB,KAAK;AAAA,YACL;AAAA;AAAA,YACA,KAAK,IAAI,IAAI;AAAA,YACb,cAAc;AAAA,YACd;AAAA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,aAAa,CAAC,GAAG,eAAe,GAAG,mBAAmB;AAE5D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe,KAAK,IAAI,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjNA,IAsBa;AAtBb;AAAA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AAcO,IAAM,eAAN,MAAmB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAER,YAAY,QAAgB,aAA0B,cAAsC;AAC1F,aAAK,cAAc;AACnB,aAAK,eAAe,gBAAgB,IAAI,sBAAsB;AAC9D,aAAK,SAAS;AACd,aAAK,iBAAiB,IAAI,eAAe,KAAK,WAAW;AACzD,aAAK,kBAAkB,IAAI,gBAAgB,KAAK,aAAa,KAAK,YAAY;AAC9E,aAAK,qBAAqB,IAAI,mBAAmB,KAAK,aAAa,KAAK,YAAY;AACpF,aAAK,UAAU,IAAI,QAAQ,KAAK,QAAQ,KAAK,aAAa,KAAK,YAAY;AAAA,MAC7E;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,YACZ,MACA,UACA,YACA,WACA,SACA,SACsD;AACtD,cAAM,WAAW,WAAW;AAE5B,YAAI,aAAa,YAAY;AAG3B,gBAAM,EAAE,MAAM,OAAO,UAAU,GAAG,OAAO,IAAI;AAE7C,gBAAM,aAAa,MAAM,KAAK,gBAAgB,QAAQ,QAAQ,UAAsB;AAAA,YAClF;AAAA,YACA,iBAAiB;AAAA,UACnB,CAAC;AAED,iBAAO;AAAA,YACL,SAAS,WAAW;AAAA,UACtB;AAAA,QACF;AAEA,YAAI,aAAa,cAAc;AAE7B,cAAI,aAAsB,CAAC;AAE3B,mBAAS,IAAI,GAAG,IAAI,WAAW,MAAM,QAAQ,KAAK;AAChD,kBAAM,UAAU,WAAW,MAAM,CAAC;AAClC,kBAAM,cAAc,GAAG,QAAQ,IAAI,CAAC;AACpC,kBAAM,YAAY,MAAM,KAAK;AAAA,cAC3B;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAEA,gBAAI,UAAU,SAAS;AACrB,2BAAa,WAAW,OAAO,UAAU,OAAO;AAAA,YAClD;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,SAAS;AAAA,UACX;AAAA,QACF;AAEA,YAAI,aAAa,eAAe;AAE9B,gBAAM,aAAa,MAAM,KAAK,eAAe,QAAQ,WAAW;AAAA,YAC9D,SAAS,WAAW;AAAA,YACpB,QAAQ,WAAW;AAAA,YACnB,YAAY,WAAW;AAAA,UACzB,CAAC;AAED,iBAAO;AAAA,YACL,WAAW,WAAW;AAAA,UACxB;AAAA,QACF;AAEA,YAAI,aAAa,mBAAmB;AAElC,cAAI,QAAQ,WAAW,GAAG;AACxB,mBAAO;AAAA,cACL,SAAS,CAAC;AAAA,YACZ;AAAA,UACF;AAGA,gBAAM,EAAE,SAAS,IAAI;AAGrB,gBAAM,qBAAqB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AAExE,cAAI,mBAAmB,WAAW,GAAG;AAEnC,mBAAO;AAAA,cACL,SAAS,CAAC;AAAA,YACZ;AAAA,UACF;AAEA,gBAAM,aAAa,MAAM,KAAK,mBAAmB,QAAQ,oBAAoB,UAAU;AAAA,YACrF,OAAO,WAAW;AAAA,UACpB,CAAC;AAED,gBAAM,sBAAsB,CAAC,GAAG,IAAI,IAAI,WAAW,YAAY,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEtF,iBAAO;AAAA,YACL,WAAW;AAAA,YACX,SAAS,WAAW;AAAA,UACtB;AAAA,QACF;AAEA,YAAI,aAAa,OAAO;AAEtB,cAAI,QAAQ,WAAW,GAAG;AACxB,mBAAO;AAAA,cACL,SAAS,CAAC;AAAA,YACZ;AAAA,UACF;AAEA,gBAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ,MAAM,OAAO;AAE1D,iBAAO;AAAA,YACL,SAAS,UAAU;AAAA,UACrB;AAAA,QACF;AAEA,cAAM,IAAI,MAAM,sBAAsB,QAAQ,EAAE;AAAA,MAClD;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,QAAQ,OAAe,SAA+D;AAE1F,YAAI,KAAK,eAAe,KAAK,gBAAgB,QAAQ,MAAM;AACzD,gBAAM,IAAI,MAAM,qCAAqC,KAAK,WAAW,SAAS,QAAQ,IAAI,EAAE;AAAA,QAC9F;AAGA,YAAI,CAAC,KAAK,oBAAoB,KAAK,gBAAgB,QAAQ,MAAM;AAC/D,eAAK,mBAAmB,MAAM,qBAAqB;AAAA,YACjD,KAAK;AAAA,YACL,KAAK;AAAA,YACL,QAAQ;AAAA,YACR,KAAK;AAAA,YACL,QAAQ;AAAA,YACR,QAAQ;AAAA,UACV;AACA,eAAK,cAAc,QAAQ;AAAA,QAC7B;AAGA,aAAK,aAAa,WAAW,MAAM,MAAM;AAGzC,cAAM,UAAiC,CAAC;AAExC,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,OAAO,MAAM,CAAC;AACpB,gBAAM,SAAS,KAAK;AAEpB,cAAI,QAAQ;AAEZ,qBAAW,cAAc,KAAK,OAAO,OAAO;AAC1C,gBAAI,WAAW,KAAK,SAAS,OAAO;AAClC,sBAAQ;AACR;AAAA,YACF;AAAA,UACF;AAGA,eAAK,aAAa,aAAa,IAAI,GAAG,MAAM,QAAQ,QAAQ,KAAK;AAEjE,gBAAM,aAAa,KAAK;AAGxB,cAAI,mBAAmB,CAAC,GAAG,KAAK,iBAAiB,SAAS;AAC1D,cAAI,iBAA0B,CAAC;AAG/B,qBAAW,cAAc,WAAW,OAAO;AACzC,kBAAM,WAAW,WAAW;AAC5B,kBAAM,aAAa,WAAW;AAG9B,iBAAK,aAAa,UAAU,QAAQ,UAAU,WAAW,MAAM;AAAA,cAC7D,WAAW;AAAA,cACX,SAAS;AAAA,YACX,CAAC;AAED,kBAAM,gBAAgB,KAAK,IAAI;AAC/B,kBAAM,SAAS,MAAM,KAAK;AAAA,cACxB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,kBAAM,oBAAoB,KAAK,IAAI,IAAI;AAGvC,iBAAK,aAAa,KAAK,iBAAiB;AAAA,cACtC;AAAA,cACA;AAAA,cACA,UAAU,WAAW;AAAA,cACrB,SAAS;AAAA,cACT,eAAe;AAAA,YACjB,CAAC;AAGD,gBAAI,OAAO,cAAc,QAAW;AAClC,iCAAmB,KAAK,iBAAiB,YAAY,OAAO,SAAS;AAErE,+BAAiB,KAAK,iBAAiB;AAAA,gBACrC;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAEA,gBAAI,OAAO,YAAY,QAAW;AAChC,+BAAiB,KAAK,iBAAiB,cAAc,OAAO,OAAO;AAAA,YACrE;AAGA,gBAAI,iBAAiB,WAAW,GAAG;AACjC;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,gBAAgB,eAAe,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AAExF,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAGA,cAAM,eAAe,QAAQ,OAAO,CAAC,KAAK,WAAW,MAAM,OAAO,QAAQ,QAAQ,CAAC;AACnF,aAAK,aAAa,cAAc,MAAM,QAAQ,YAAY;AAE1D,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACrRA,IAIa;AAJb;AAAA;AAAA;AAIO,IAAM,yBAAN,cAAqC,MAAM;AAAA,MAChD,YACE,QACA,SACO,kBACP;AACA,cAAM,2BAA2B,MAAM,MAAM,OAAO,EAAE;AAF/C;AAGP,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACbA,SAAS,gCAAgC;AAEzC,OAAO,WAAW;AAClB,OAAO,SAAkB;AAgBzB,SAAS,sBAAsB,QAAgB,YAA6B;AAC1E,MAAI,YAAY;AAEd,WAAO,MAAM,UAAU;AAAA,MACrB,yCAA2C,UAAU,SAAW,MAAM;AAAA,IACxE;AAAA,EACF;AAEA,SAAO,MAAM,IAAI,MAAM;AACzB;AA4DA,SAAS,UAAU,MAAc,OAAuB;AACtD,SAAO,UAAU,IAAI,OAAO,GAAG,IAAI;AACrC;AAQO,SAAS,UACd,MACA,OAGI,CAAC,GACG;AACR,QAAM,OAAO;AACb,QAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,QAAM,eAAe,KAAK,iBAAiB,CAAC,QAAgB,yBAAyB,GAAG,EAAE;AAE1F,QAAM,QAAQ,KAAK,OAAO,CAAC,KAAe,QAAQ;AAChD,QAAI,QAAQ,CAACC,IAAG,OAAO;AACrB,YAAM,IAAI,aAAaA,EAAC;AAExB,UAAI,CAAC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,GAAG;AAC3B,YAAI,EAAE,IAAI;AAAA,MACZ;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,SAAO,KACJ;AAAA,IAAI,CAAC,QACJ,IACG,IAAI,CAACA,IAAG,OAAO;AACd,YAAM,IAAI,MAAM,EAAE,IAAI,aAAaA,EAAC,KAAK;AACzC,YAAM,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAE5C,UAAI,MAAM,EAAE,MAAM,KAAK;AACrB,eAAO,IAAIA;AAAA,MACb;AAEA,aAAOA,KAAI;AAAA,IACb,CAAC,EACA,KAAK,IAAI,EACT,QAAQ;AAAA,EACb,EACC,KAAK,IAAI;AACd;AAEO,SAAS,aAAa,SAAuB,SAA4B;AAC9E,MAAI,SAAS;AAEb,MAAI,iBAAiB;AACrB,MAAI,kBAAkB;AAGtB,QAAM,cAAc,oBAAI,IAetB;AAEF,UAAQ,QAAQ,CAAC,WAAW;AAC1B,QAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B;AAAA,IACF;AAEA,UAAM,SAAS,OAAO,UAAU;AAChC,QAAI,CAAC,YAAY,IAAI,MAAM,GAAG;AAC5B,kBAAY,IAAI,QAAQ;AAAA,QACtB,SAAS,OAAO;AAAA,QAChB,UAAU,OAAO;AAAA,QACjB,YAAY,OAAO;AAAA,QACnB,SAAS,CAAC;AAAA,QACV,kBAAkB;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,YAAY,IAAI,MAAM;AAEvC,WAAO,QAAQ,QAAQ,CAAC,UAAU;AArLtC;AAsLM,eAAS,QAAQ,KAAK;AAAA,QACpB,UAAU,MAAM;AAAA,QAChB,MAAM,MAAM,MAAM,MAAM,OAAO;AAAA,QAC/B,QAAQ,MAAM,MAAM,MAAM,SAAS;AAAA,QACnC,SACE,MAAM,MAAM,IAAI,SAAS,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI;AAAA,QAC/E,MAAM,MAAM;AAAA,MACd,CAAC;AAGD,WAAI,WAAM,aAAN,mBAAgB,eAAe;AACjC,iBAAS,mBAAmB;AAAA,MAC9B;AAEA,UAAI,OAAO,aAAa,aAAa;AACnC;AAAA,MACF,OAAO;AACL;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,cAAY,QAAQ,CAAC,UAAU,WAAW;AACxC,QAAI,SAAS,QAAQ,WAAW,KAAK,SAAS,aAAa,WAAW;AACpE;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,SAAS,aAAa,aAAa;AACrC,oBAAc,MAAM,IAAI,eAAe,EAAE,aAAa,SAAS,CAAC,CAAC;AAAA,IACnE,WAAW,SAAS,aAAa,cAAc;AAC7C,oBAAc,MAAM,IAAI,gBAAgB,EAAE,aAAa,OAAO,CAAC,CAAC;AAAA,IAClE,OAAO;AACL,oBAAc,MAAM,IAAI,aAAa,EAAE,aAAa,OAAO,CAAC,CAAC;AAAA,IAC/D;AAGA,UAAM,eAAe,SAAS,mBAAmB,GAAG,MAAM,IAAI,aAAa,EAAE,OAAO,CAAC,MAAM;AAC3F,UAAM,kBAAkB,sBAAsB,QAAQ,SAAS,UAAU;AACzE,UAAM,aAAa,GAAG,WAAW,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,YAAY,GAAG,SAAS,QAAQ,QAAQ,cAAc,IAAI,CAAC,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,eAAe,GAAG,MAAM,IAAI,GAAG,CAAC;AACvK,cAAU,GAAG,UAAU;AAAA;AACvB,cAAU,GAAG,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA;AAGtC,QAAI,SAAS,aAAa,WAAW;AACnC,gBAAU;AAAA;AAAA,IACZ,OAAO;AAEL,YAAM,gBAAgB,SAAS,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AAG1F,YAAM,yBACJ,cAAc,SAAS,MACvB,cAAc,KAAK,CAAC,UAAU,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,EAAE,UAAU,EAAE;AAEjF,UAAI,wBAAwB;AAE1B,sBAAc,QAAQ,CAAC,OAAO,UAAU;AAEtC,oBAAU,KAAK,MAAM,QAAQ;AAAA;AAG7B,cAAI,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,EAAE,UAAU,IAAI;AACrD,kBAAM,QAAQ,MAAM,KAAK,MAAM,IAAI;AACnC,kBAAM,QAAQ,CAAC,MAAM,cAAc;AACjC,oBAAM,aAAa,MAAM,OAAO;AAChC,oBAAM,gBAAgB,MAAM,MAAM,oBAAoB,EAAE,IAAI,sBAAsB;AAAA,gBAChF,IAAI,OAAO,UAAU,CAAC;AAAA,cACxB;AACA,wBAAU,KAAK,aAAa,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA;AAAA,YACjD,CAAC;AAAA,UACH;AAGA,cAAI,QAAQ,cAAc,SAAS,GAAG;AACpC,sBAAU;AAAA;AAAA,UACZ;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AAEL,sBAAc,QAAQ,CAAC,UAAU;AAC/B,gBAAM,YAAY,MAAM,UAAU,IAAI,MAAM,IAAI,IAAI,MAAM,OAAO,MAAM,IAAI,MAAM,IAAI;AACrF,oBAAU,KAAK,MAAM,QAAQ,IAAI,MAAM,IAAI,SAAS,CAAC;AAAA;AAAA,QACvD,CAAC;AAAA,MACH;AAEA,gBAAU;AAAA;AAAA;AAAA,IACZ;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,iBAAiB;AAE/B,MAAI,UAAU,GAAG;AACf,YAAQ,IAAI;AAAA,WAAc;AAAA,EAC5B;AAGA,QAAM,gBACJ,iBAAiB,IACb,GAAG,MAAM,IAAI,aAAa,SAAS,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,eAAe,EAAE,QAAG,CAAC,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,cAAc,CAAC,KAC7H,GAAG,MAAM,IAAI,aAAa,SAAS,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,cAAc,CAAC;AAE1E,QAAM,iBACJ,kBAAkB,IACd,GAAG,MAAM,IAAI,cAAc,SAAS,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,gBAAgB,EAAE,QAAG,CAAC,IAAI,MAAM,IAAI,gBAAgB,EAAE,KAAK,eAAe,CAAC,KACjI,GAAG,MAAM,IAAI,cAAc,SAAS,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,eAAe,CAAC;AAG5E,QAAM,YAAY,QAAQ,aACtB,GAAG,QAAQ,UAAU,IAAI,UAAU,QAAQ,QAAQ,UAAU,CAAC,KAC9D;AACJ,QAAM,YAAY,GAAG,QAAQ,UAAU,IAAI,UAAU,QAAQ,QAAQ,UAAU,CAAC;AAChF,QAAM,WAAW,QAAQ,gBAAgB,GAAG,KAAK,MAAM,QAAQ,aAAa,CAAC,OAAO;AAEpF,QAAM,cAAc,CAAC,WAAW,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAG9E,YAAU,GAAG,aAAa;AAAA;AAC1B,YAAU,GAAG,cAAc;AAAA;AAC3B,YAAU,GAAG,MAAM,IAAI,UAAU,SAAS,EAAE,CAAC,CAAC,IAAI,WAAW;AAAA;AAG7D,UAAQ,IAAI,QAAQ,IAAI,MAAM,MAAM,MAAM,IAAI,MAAM;AAGpD,MAAI,iBAAiB,GAAG;AACtB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAKO,SAAS,eACd,OAKM;AACN,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAI,MAAM,OAAO,iBAAiB,CAAC;AAC3C,YAAQ,IAAI,MAAM,IAAI,uDAAuD,CAAC;AAC9E;AAAA,EACF;AAGA,QAAM,YAAwB,CAAC;AAG/B,YAAU,KAAK;AAAA,IACb;AAAA,IACA,GAAG,KAAK,OAAO,EAAE,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,WAAW,OAAO,EAAE,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC;AAAA,EACjF,CAAC;AAGD,YAAU,KAAK;AAAA,IACb;AAAA,IACA,GAAG,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,EAC5H,CAAC;AAGD,aAAW,QAAQ,OAAO;AACxB,UAAM,gBACJ,KAAK,OAAO,aAAa,cACrB,MAAM,IAAI,eAAe,IACzB,MAAM,IAAI,gBAAgB;AAChC,UAAM,eAAe,cAAc,KAAK,OAAO,QAAQ;AACvD,UAAM,SAAS,sBAAsB,KAAK,IAAI,KAAK,UAAU;AAG7D,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,KAAK,GAAG,MAAM;AACjD,UAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,KAAK,OAAO,SAAS,MAAM;AAGpE,cAAU,KAAK;AAAA,MACb;AAAA,MACA,GAAG,MAAM,GAAG,IAAI,OAAO,SAAS,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,YAAY,GAAG,IAAI,OAAO,eAAe,CAAC,IAAI,MAAM,IAAI,QAAG,CAAC,IAAI,KAAK,OAAO,OAAO;AAAA,IAC5I,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,UAAU,WAAW;AAAA,IACjC,OAAO,CAAC,IAAI,GAAG;AAAA,IACf,aAAa,KAAa;AACxB,aAAO,yBAAyB,GAAG,EAAE;AAAA,IACvC;AAAA,EACF,CAAC;AAED,UAAQ,IAAI,OAAO,KAAK;AACxB,UAAQ,IAAI,MAAM,IAAI;AAAA,6DAAgE,CAAC;AACzF;AAKO,SAAS,WACd,SACA,SAA0C,UACpC;AACN,QAAM,UAAiB,CAAC;AAExB,aAAW,UAAU,SAAS;AAC5B,eAAW,SAAS,OAAO,SAAS;AAClC,YAAM,YAAY;AAAA,QAChB,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,QACb,UAAU,MAAM;AAAA,QAChB,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,QACnB,UAAU,OAAO;AAAA,QACjB,SAAS,OAAO;AAAA,MAClB;AAEA,cAAQ,KAAK,SAAS;AAAA,IACxB;AAAA,EACF;AAEA,MAAI,WAAW,UAAU;AACvB,eAAW,SAAS,SAAS;AAC3B,cAAQ,IAAI,KAAK,UAAU,KAAK,CAAC;AAAA,IACnC;AAAA,EACF,WAAW,WAAW,WAAW;AAC/B,YAAQ,IAAI,KAAK,UAAU,OAAO,CAAC;AAAA,EACrC,OAAO;AAEL,YAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,EAC9C;AACF;AAKO,SAAS,sBACd,cACA,YAAqB,OACT;AACZ,MAAI,UAAsB;AAC1B,MAAI,oBAAmC;AACvC,MAAI,gBAKO;AAGX,eAAa,GAAG,kBAAkB,CAAC,SAAS;AAC1C,oBAAgB;AAAA,EAClB,CAAC;AAED,eAAa,GAAG,eAAe,CAAC,UAAU;AAExC,cAAU,IAAI;AAAA,MACZ,SAAS;AAAA,QACP,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,IACT,CAAC,EAAE,MAAM;AAGT,UAAM,kBAAkB,MAAM;AAC5B,UAAI,SAAS;AACX,gBAAQ,KAAK;AAAA,MACf;AACA,cAAQ,KAAK,GAAG;AAAA,IAClB;AAEA,YAAQ,GAAG,UAAU,eAAe;AACpC,YAAQ,GAAG,WAAW,eAAe;AAAA,EACvC,CAAC;AAED,eAAa,GAAG,kBAAkB,CAAC,SAAS;AAC1C,QAAI,SAAS;AACX,UAAI,WAAW;AACf,UAAI,eAAe;AACjB,YAAI,cAAc,SAAS,SAAS;AAClC,qBAAW,cAAc,WAAW,KAAK,cAAc,QAAQ,MAAM;AAAA,QACvE,WAAW,cAAc,SAAS,QAAQ;AACxC,qBAAW,KAAK,cAAc,UAAU,WAAM,cAAc,UAAU;AAAA,QACxE;AAAA,MACF;AACA,cAAQ,OAAO,GAAG,KAAK,QAAQ,MAAM,IAAI,aAAa,EAAE,QAAQ,IAAI,EAAE,GAAG,KAAK,MAAM,GAAG,QAAQ;AAAA,IACjG;AAAA,EACF,CAAC;AAED,eAAa,GAAG,kBAAkB,MAAM;AACtC,QAAI,SAAS;AACX,cAAQ,KAAK;AACb,gBAAU;AAAA,IACZ;AAAA,EACF,CAAC;AAED,eAAa,GAAG,yBAAyB,CAAC,SAAS;AACjD,QAAI,WAAW;AACb,cAAQ,IAAI;AAAA,EAAK,MAAM,KAAK,mBAAmB,CAAC,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC,UAAU;AAAA,IACxF;AAAA,EACF,CAAC;AAED,eAAa,GAAG,4BAA4B,CAAC,SAAS;AACpD,QAAI,WAAW;AACb,cAAQ,IAAI,MAAM,KAAK,OAAO,EAAE;AAAA,IAClC;AAAA,EACF,CAAC;AAED,eAAa,GAAG,4BAA4B,CAAC,SAAS;AACpD,QAAI,WAAW;AACb,cAAQ;AAAA,QACN,MAAM,MAAM,0BAA0B;AAAA,QACtC,GAAG,KAAK,UAAU,iBAAiB,KAAK,aAAa;AAAA,MACvD;AAAA,IACF;AAAA,EACF,CAAC;AAED,eAAa,GAAG,gBAAgB,CAAC,SAAS;AACxC,QAAI,aAAa,KAAK,kBAAkB,KAAK,eAAe;AAC1D,cAAQ;AAAA,QACN,MAAM,OAAO,WAAW;AAAA,QACxB,GAAG,KAAK,aAAa,WAAM,KAAK,aAAa,IAAI,KAAK,UAAU;AAAA,MAClE;AAAA,IACF;AAAA,EACF,CAAC;AAGD,eAAa,GAAG,kBAAkB,CAAC,UAAU;AAC3C,wBAAoB,KAAK,IAAI;AAAA,EAC/B,CAAC;AAED,eAAa,GAAG,qBAAqB,CAAC,SAAS;AAC7C,QAAI,SAAS;AACX,cAAQ,QAAQ;AAAA,IAClB;AAEA,QAAI,qBAAqB,KAAK,IAAI,IAAI,oBAAoB,KAAM;AAC9D,UAAI,SAAS;AACX,gBAAQ,OAAO,YAAY,KAAK,QAAQ;AAAA,MAC1C;AAAA,IACF;AAGA,QAAI,SAAS;AACX,UAAI,KAAK,eAAe,KAAK,QAAQ;AACnC,gBAAQ,OAAO,YAAY,KAAK,QAAQ,KAAK,KAAK,WAAW;AAAA,MAC/D,WAAW,KAAK,YAAY,qBAAqB;AAC/C,gBAAQ,OAAO,YAAY,KAAK,QAAQ,KAAK,KAAK,OAAO;AAAA,MAC3D;AAAA,IACF;AAGA,QAAI,WAAW;AACb,UAAI,KAAK,eAAe,KAAK,QAAQ;AACnC,gBAAQ,IAAI,QAAQ,KAAK,WAAW,KAAK,KAAK,MAAM,KAAK;AAAA,MAC3D,WAAW,KAAK,YAAY,qBAAqB;AAC/C,gBAAQ,OAAO,MAAM,GAAG;AAAA,MAC1B,WAAW,KAAK,YAAY,qBAAqB;AAC/C,gBAAQ,IAAI,MAAM,KAAK,OAAO,EAAE;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAC;AAED,eAAa,GAAG,qBAAqB,CAAC,SAAS;AAC7C,wBAAoB;AACpB,QAAI,SAAS;AACX,cAAQ,QAAQ;AAAA,IAClB;AAEA,QAAI,WAAW;AACb,cAAQ,OAAO,MAAM,IAAI;AACzB,cAAQ;AAAA,QACN,MAAM,MAAM,uBAAuB;AAAA,QACnC,GAAG,KAAK,QAAQ,KAAK,KAAK,aAAa;AAAA,MACzC;AAAA,IACF;AAAA,EACF,CAAC;AAGD,MAAI,WAAW;AACb,iBAAa,GAAG,2BAA2B,CAAC,SAAS;AACnD,cAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,aAAS,KAAK,QAAQ,qCAAqC,KAAK,UAAU,KAAK,KAAK,CAAC;AAAA,QACvF;AAAA,MACF;AAAA,IACF,CAAC;AAED,iBAAa,GAAG,8BAA8B,CAAC,SAAS;AACtD,cAAQ,IAAI,GAAG,KAAK,UAAU,KAAK,QAAQ,CAAC,EAAE;AAAA,IAChD,CAAC;AAED,iBAAa,GAAG,8BAA8B,CAAC,SAAS;AACtD,cAAQ,IAAI,MAAM,MAAM,mCAAmC,KAAK,QAAQ,EAAE,CAAC;AAAA,IAC7E,CAAC;AAED,iBAAa,GAAG,cAAc,CAAC,SAAS;AACtC,cAAQ;AAAA,QACN,MAAM,KAAK;AAAA,aAAS,KAAK,MAAM,oBAAoB,KAAK,QAAQ,KAAK,KAAK,QAAQ,GAAG;AAAA,MACvF;AACA,cAAQ,IAAI,mBAAmB,KAAK,OAAO,UAAU,MAAM,EAAE;AAC7D,cAAQ,IAAI,qBAAqB,KAAK,OAAO,QAAQ,MAAM,EAAE;AAG7D,UAAI,KAAK,OAAO,QAAQ,SAAS,GAAG;AAClC,gBAAQ,IAAI,mBAAmB;AAC/B,aAAK,OAAO,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AA9kBpD;AA+kBU,kBAAQ,IAAI,cAAc,MAAM,CAAC,GAAG;AACpC,kBAAQ,IAAI,gBAAgB,MAAM,QAAQ,EAAE;AAC5C,kBAAQ;AAAA,YACN,iBAAiB,MAAM,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM,MAAM,MAAM,WAAM,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM;AAAA,UACzH;AACA,cAAI,MAAM,QAAQ;AAChB,oBAAQ,IAAI,kBAAkB,MAAM,MAAM,EAAE;AAAA,UAC9C;AACA,cAAI,MAAM,UAAU,MAAM,OAAO,SAAS,GAAG;AAC3C,oBAAQ,IAAI,wBAAwB,MAAM,OAAO,MAAM,UAAU;AACjE,kBAAM,OAAO,QAAQ,CAAC,KAAK,WAAW;AACpC,oBAAM,QAAQ,GAAG,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,MAAM,WAAM,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,MAAM,IAAI,MAAM;AAC/G,sBAAQ;AAAA,gBACN,YAAY,SAAS,CAAC,KAAK,IAAI,QAAQ,KAAK,IAAI,UAAU,KAAK,OAAO,KAAK;AAAA,cAC7E;AAAA,YACF,CAAC;AAAA,UACH;AACA,kBAAQ,IAAI,yBAAwB,WAAM,SAAN,mBAAY,UAAU,GAAG,IAAI,KAAK;AAAA,QACxE,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,iBAAa,GAAG,iBAAiB,CAAC,SAAS;AACzC,cAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAM,KAAK,MAAM,qBAAqB,KAAK,QAAQ,KAAK,KAAK,QAAQ,MAAM,KAAK,aAAa;AAAA,QAC/F;AAAA,MACF;AACA,UAAI,KAAK,QAAQ,cAAc,QAAW;AACxC,gBAAQ,IAAI,oBAAoB,KAAK,QAAQ,UAAU,MAAM,EAAE;AAAA,MACjE;AACA,UAAI,KAAK,QAAQ,YAAY,QAAW;AACtC,gBAAQ,IAAI,sBAAsB,KAAK,QAAQ,QAAQ,MAAM,EAAE;AAG/D,YAAI,KAAK,QAAQ,QAAQ,SAAS,GAAG;AACnC,kBAAQ,IAAI,0BAA0B;AACtC,eAAK,QAAQ,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AApnBvD;AAqnBY,oBAAQ,IAAI,cAAc,MAAM,CAAC,GAAG;AACpC,oBAAQ,IAAI,gBAAgB,MAAM,QAAQ,EAAE;AAC5C,oBAAQ;AAAA,cACN,iBAAiB,MAAM,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM,MAAM,MAAM,WAAM,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM;AAAA,YACzH;AACA,gBAAI,MAAM,QAAQ;AAChB,sBAAQ,IAAI,kBAAkB,MAAM,MAAM,EAAE;AAAA,YAC9C;AACA,gBAAI,MAAM,UAAU,MAAM,OAAO,SAAS,GAAG;AAC3C,sBAAQ,IAAI,wBAAwB,MAAM,OAAO,MAAM,UAAU;AACjE,oBAAM,OAAO,QAAQ,CAAC,KAAK,WAAW;AACpC,sBAAM,QAAQ,GAAG,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,MAAM,WAAM,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,MAAM,IAAI,MAAM;AAC/G,wBAAQ;AAAA,kBACN,YAAY,SAAS,CAAC,KAAK,IAAI,QAAQ,KAAK,IAAI,UAAU,KAAK,OAAO,KAAK;AAAA,gBAC7E;AAAA,cACF,CAAC;AAAA,YACH;AACA,oBAAQ,IAAI,yBAAwB,WAAM,SAAN,mBAAY,UAAU,GAAG,IAAI,KAAK;AAAA,UACxE,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAED,iBAAa,GAAG,cAAc,CAAC,SAAS;AACtC,cAAQ,IAAI,MAAM,QAAQ;AAAA,aAAS,KAAK,MAAM,oBAAoB,KAAK,QAAQ,GAAG,CAAC;AAAA,IACrF,CAAC;AAED,iBAAa,GAAG,gBAAgB,CAAC,SAAS;AACxC,cAAQ,IAAI,MAAM,QAAQ,YAAY,KAAK,QAAQ,MAAM,aAAa,CAAC;AACvE,WAAK,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAlpB3C;AAmpBQ,gBAAQ,IAAI,YAAY,MAAM,CAAC,GAAG;AAClC,gBAAQ,IAAI,cAAc,MAAM,QAAQ,EAAE;AAC1C,gBAAQ;AAAA,UACN,eAAe,MAAM,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM,MAAM,MAAM,WAAM,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM;AAAA,QACvH;AACA,YAAI,MAAM,QAAQ;AAChB,kBAAQ,IAAI,gBAAgB,MAAM,MAAM,EAAE;AAAA,QAC5C;AACA,YAAI,MAAM,UAAU,MAAM,OAAO,SAAS,GAAG;AAC3C,kBAAQ,IAAI,sBAAsB,MAAM,OAAO,MAAM,UAAU;AAC/D,gBAAM,OAAO,QAAQ,CAAC,KAAK,WAAW;AACpC,kBAAM,QAAQ,GAAG,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,MAAM,MAAM,MAAM,WAAM,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,MAAM,IAAI,MAAM;AAC/G,oBAAQ,IAAI,UAAU,SAAS,CAAC,KAAK,IAAI,QAAQ,KAAK,IAAI,UAAU,KAAK,OAAO,KAAK,EAAE;AAAA,UACzF,CAAC;AAAA,QACH;AACA,gBAAQ,IAAI,uBAAsB,WAAM,SAAN,mBAAY,UAAU,GAAG,IAAI,KAAK;AAAA,MACtE,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,SAAO,MAAM;AACX,QAAI,SAAS;AACX,cAAQ,KAAK;AACb,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;AA9qBA,IASa,iBACA,kBACA,eAGA,aAiBA,sBACA,wBAGP;AAnCN;AAAA;AAAA;AASO,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAGtB,IAAM,cAAc;AAiBpB,IAAM,uBAAuB;AAC7B,IAAM,yBAAyB;AAGtC,IAAM,gBAAgB;AAAA,MACpB,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,aAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,QAAQ;AAAA,MAC/B,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,MAChC,MAAM,IAAI,WAAW,EAAE,SAAS;AAAA,IAClC;AAAA;AAAA;;;AC3DA,OAAOC,YAAW;AAAlB,IAGMC,cACAC,kBACAC,mBACAC,gBAKO;AAXb;AAAA;AAAA;AAGA,IAAMH,eAAc;AACpB,IAAMC,mBAAkB;AACxB,IAAMC,oBAAmB;AACzB,IAAMC,iBAAgB;AAKf,IAAM,iBAAiB;AAAA;AAAA,MAE5B;AAAA,EACAJ,OAAM,IAAIC,YAAW,EAAE,8QAAuD,CAAC;AAAA,EAC/ED,OAAM,IAAIC,YAAW,EAAE,wRAAuD,CAAC;AAAA,EAC/ED,OAAM,IAAIC,YAAW,EAAE,oQAAuD,CAAC;AAAA,EAC/ED,OAAM,IAAIC,YAAW,EAAE,yQAAuD,CAAC;AAAA,EAC/ED,OAAM,IAAIC,YAAW,EAAE,qPAAuD,CAAC;AAAA,EAC/ED,OAAM,IAAIC,YAAW,EAAE,sOAAuD,CAAC;AAAA;AAAA;AAAA,MAI/E;AAAA,EACAD,OAAM,IAAIG,iBAAgB,EAAE,4BAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,oPAA4C,CAAC;AAAA,EACjHD,OAAM,IAAIG,iBAAgB,EAAE,4BAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,8PAA4C,CAAC;AAAA,EACjHD,OAAM,IAAIG,iBAAgB,EAAE,sCAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,gOAA4C,CAAC;AAAA,EACjHD,OAAM,IAAIG,iBAAgB,EAAE,gDAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,2NAA4C,CAAC;AAAA,EACjHD,OAAM,IAAIG,iBAAgB,EAAE,gDAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,uMAA4C,CAAC;AAAA,EACjHD,OAAM,IAAIG,iBAAgB,EAAE,2CAAa,CAAC,GAAGH,OAAM,IAAIC,YAAW,EAAE,6LAA4C,CAAC;AAAA;AAAA;AAAA,MAIjH;AAAA,EACAD,OAAM,IAAIC,YAAW,EAAE,gEAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,6FAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,qHAAsB,CAAC;AAAA,EAC3ID,OAAM,IAAIC,YAAW,EAAE,gEAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,kGAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,0HAAsB,CAAC;AAAA,EAC3ID,OAAM,IAAIC,YAAW,EAAE,0EAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,kGAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,4FAAsB,CAAC;AAAA,EAC3ID,OAAM,IAAIC,YAAW,EAAE,oFAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,6FAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,4FAAsB,CAAC;AAAA,EAC3ID,OAAM,IAAIC,YAAW,EAAE,oFAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,yEAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,4FAAsB,CAAC;AAAA,EAC3ID,OAAM,IAAIC,YAAW,EAAE,0EAAmB,CAAC,GAAGD,OAAM,IAAII,cAAa,EAAE,yEAAkB,CAAC,GAAGJ,OAAM,IAAIC,YAAW,EAAE,uFAAsB,CAAC;AAAA;AAAA;AAAA,MAI3I;AAAA,EACAD,OAAM,IAAIC,YAAW,EAAE,2JAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,qHAAsB,CAAC;AAAA,EAChHF,OAAM,IAAIC,YAAW,EAAE,gKAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,0HAAsB,CAAC;AAAA,EAChHF,OAAM,IAAIC,YAAW,EAAE,0KAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,4FAAsB,CAAC;AAAA,EAChHF,OAAM,IAAIC,YAAW,EAAE,+KAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,4FAAsB,CAAC;AAAA,EAChHF,OAAM,IAAIC,YAAW,EAAE,2JAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,4FAAsB,CAAC;AAAA,EAChHF,OAAM,IAAIC,YAAW,EAAE,iJAAmC,CAAC,GAAGD,OAAM,IAAIE,gBAAe,EAAE,uFAAsB,CAAC;AAAA;AAAA;AAAA,MAIhH;AAAA,EACAF,OAAM,IAAIC,YAAW,EAAE,wNAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,wDAAW,CAAC;AAAA,EACjHH,OAAM,IAAIC,YAAW,EAAE,kOAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,wDAAW,CAAC;AAAA,EACjHH,OAAM,IAAIC,YAAW,EAAE,4OAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,0BAAW,CAAC;AAAA,EACjHH,OAAM,IAAIC,YAAW,EAAE,iPAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,0BAAW,CAAC;AAAA,EACjHH,OAAM,IAAIC,YAAW,EAAE,6NAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,0BAAW,CAAC;AAAA,EACjHH,OAAM,IAAIC,YAAW,EAAE,8MAA8C,CAAC,GAAGD,OAAM,IAAIG,iBAAgB,EAAE,0BAAW,CAAC;AAAA;AAAA,IAEnH;AAAA;AAAA;;;AC7DA,OAAO,cAAc;AAErB,OAAOE,YAAW;AAClB,OAAOC,UAAS;AAQhB,SAAS,cAAoB;AAC3B,UAAQ,OAAO,MAAM,eAAe;AACtC;AAKA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAACC,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;AAKA,eAAe,mBAAmB,aAAqB,KAAqB;AAC1E,QAAM,UAAUD,KAAI;AAAA,IAClB,MAAM;AAAA,IACN,SAAS;AAAA,MACP,UAAU;AAAA;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,EACF,CAAC,EAAE,MAAM;AAGT,QAAM,MAAM,UAAU;AAGtB,UAAQ,KAAK;AACf;AAKA,eAAe,eAAe,UAAmC;AAC/D,QAAM,KAAK,SAAS,gBAAgB;AAAA,IAClC,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,EAClB,CAAC;AAED,SAAO,MAAM,IAAI,QAAQ,CAACC,aAAY;AACpC,OAAG,SAAS,UAAU,CAAC,WAAW;AAChC,SAAG,MAAM;AACT,MAAAA,SAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAsB,oBAA4C;AAEhE,cAAY;AAGZ,QAAM,mBAAmB,IAAI;AAG7B,UAAQ,IAAI,eAAe,CAAC,CAAC;AAE7B,UAAQ,IAAIF,OAAM,IAAI,eAAe,EAAE,wBAAwB,CAAC;AAChE,UAAQ,IAAIA,OAAM,uBAAuB,CAAC;AAE1C,UAAQ,IAAIA,OAAM,IAAI,wCAAwC,CAAC;AAC/D,UAAQ,IAAIA,OAAM,IAAI,0DAA0D,CAAC;AAEjF,QAAM,SAAS,MAAM;AAAA,IACnBA,OAAM,KAAK,IAAI,gBAAgB,EAAE,yDAAyD;AAAA,EAC5F;AAEA,MAAI,CAAC,QAAQ;AACX,YAAQ,IAAIA,OAAM,IAAI,sBAAsB,CAAC;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAvFA;AAAA;AAAA;AAKA;AACA;AAAA;AAAA;;;ACNA;AAAA;AAAA;AAAA;AAEA,YAAYG,SAAQ;AACpB,YAAYC,SAAQ;AACpB,YAAYC,YAAU;AAEtB,OAAO,SAAS;AAChB,OAAOC,YAAW;AAClB,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,OAAO,YAAY;AAuBnB,SAAS,oBAA4B;AACnC,SAAY,YAAQ,YAAQ,GAAG,cAAc,aAAa;AAC5D;AAKA,eAAe,WAAW,QAA+B;AACvD,QAAM,aAAa,kBAAkB;AACrC,QAAM,YAAiB,eAAQ,UAAU;AAGzC,QAAS,UAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAE7C,MAAI,iBAAiB,CAAC;AACtB,MAAI;AACF,UAAM,gBAAgB,MAAS,aAAS,YAAY,OAAO;AAC3D,qBAAiB,KAAK,MAAM,aAAa;AAAA,EAC3C,QAAQ;AAAA,EAER;AAEA,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH;AAAA,EACF;AAEA,QAAS,cAAU,YAAY,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AACnE;AAKA,eAAe,aAAqC;AAClD,QAAM,aAAa,kBAAkB;AACrC,MAAI;AACF,UAAM,gBAAgB,MAAS,aAAS,YAAY,OAAO;AAC3D,UAAM,SAAS,KAAK,MAAM,aAAa;AACvC,WAAO,OAAO,UAAU;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,mBAAoC;AACjD,QAAM,cAAc,IAAI,YAAY;AAEpC,MAAI,SAAwB,QAAQ,IAAI,mBAAmB;AAC3D,MAAI,CAAC,QAAQ;AACX,aAAS,MAAM,WAAW;AAAA,EAC5B;AAGA,MAAI,SAAS,MAAM,OAAO,WAAW,aAAa,EAAE,QAAQ,UAAU,OAAU,CAAC;AAEjF,MAAI,YAAY,QAAQ;AACtB,QAAI,OAAO,UAAU,mBAAmB;AAEtC,YAAM,YAAY,MAAM,kBAAkB;AAE1C,UAAI,CAAC,WAAW;AACd,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAGA,YAAM,gBAAgB,MAAM,YAAY,iBAAiB;AACzD,UAAI,CAAC,eAAe;AAClB,gBAAQ,IAAIA,OAAM,IAAI,iEAAiE,CAAC;AACxF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,cAAQ,IAAIA,OAAM,IAAI,uBAAuB,CAAC;AAG9C,YAAM,WAAW,SAAS;AAG1B,eAAS,MAAM,OAAO,WAAW,aAAa,EAAE,QAAQ,UAAU,CAAC;AAEnE,UAAI,YAAY,QAAQ;AACtB,gBAAQ,IAAIA,OAAM,IAAI,2DAA2D,CAAC;AAClF,gBAAQ,KAAK,CAAC;AAAA,MAChB,OAAO;AACL,gBAAQ,IAAIA,OAAM,MAAM,gDAAgD,CAAC;AACzE,eAAO;AAAA,MACT;AAAA,IACF,WAAW,OAAO,UAAU,sBAAsB;AAChD,YAAM,gBAAgB,MAAM,YAAY,iBAAiB;AACzD,cAAQ;AAAA,QACNA,OAAM;AAAA,UACJ,2CAA2C,aAAa;AAAA,QAC1D;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,kBAAkB;AACtC,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,mBAAmB,MAAM,iBAAiB;AAEhD,MAAI,OAAO,GAAG,kBAAkB,cAAc,GAAG;AAC/C,YAAQ;AAAA,MACNA,OACG,MAAM,SAAS,EACf,MAAM,KAAK,2BAA2B,gBAAgB,cAAc,cAAc,IAAI;AAAA,IAC3F;AACA,YAAQ;AAAA,MACNA,OAAM,MAAM,SAAS,EAAE,MAAM,KAAK;AAAA,CAAkD;AAAA,IACtF;AAAA,EACF;AACF;AAuFA,eAAe,eAAe,SAMJ;AAIxB,QAAM,cAAc,IAAI,YAAY;AACpC,QAAM,SAAS,MAAM,iBAAiB;AAEtC,QAAM,EAAE,QAAQ,MAAAC,OAAM,MAAM,SAAS,IAAI;AAGzC,MAAI,aAAa;AACjB,MAAI,aAA8C;AAElD,MAAIA,OAAM;AACR,iBAAa;AACb,QAAIA,UAAS,UAAU;AACrB,mBAAa;AAAA,IACf,WAAWA,UAAS,WAAW;AAC7B,mBAAa;AAAA,IACf,OAAO;AACL,mBAAa;AAAA,IACf;AAAA,EACF,OAAO;AAEL,UAAM,gBAAgB;AAAA,EACxB;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,eAAe,IAAI,oBAAoB,QAAQ,WAAW;AAChE,QAAI,QAAQ;AAEV,YAAM,OAAO,MAAM,aAAa,aAAa,MAAM;AACnD,cAAQ,CAAC,IAAI;AAAA,IACf,OAAO;AACL,cAAQ,MAAM,aAAa,aAAa;AAAA,IAC1C;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,wBAAwB;AAC3C,cAAQ,MAAMD,OAAM,IAAI,wBAAwB,GAAG,MAAM,OAAO;AAChE,UAAI,MAAM,oBAAoB,MAAM,iBAAiB,SAAS,GAAG;AAC/D,gBAAQ,MAAMA,OAAM,IAAI,oBAAoB,CAAC;AAC7C,cAAM,iBAAiB,QAAQ,CAAC,QAAQ;AACtC,kBAAQ,MAAMA,OAAM,IAAI,UAAK,GAAG,GAAG;AAAA,QACrC,CAAC;AAAA,MACH;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AAGA,MAAI,CAACC,OAAM;AACT,QAAI,SAAS,SAAS;AACpB,YAAM,UAAUD,OAAM,MAAM,SAAS,EAAE,MAAM,SAAS;AACtD,YAAM,aAAaA,OAAM,IAAI,KAAK,YAAY,WAAW,GAAG;AAC5D,cAAQ,IAAI,GAAG,OAAO,GAAG,UAAU,EAAE;AAAA,IACvC,OAAO;AACL,YAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,YAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,YAAM,UAAUA,OAAM,MAAM,SAAS,EAAE,MAAM,QAAQ;AACrD,YAAM,aAAaA,OAAM,IAAI,KAAK,UAAU,KAAK,UAAU,GAAG;AAC9D,cAAQ,IAAI,GAAG,OAAO,GAAG,UAAU,EAAE;AAAA,IACvC;AAAA,EACF;AAGA,QAAM,eAAe,IAAI,sBAAsB;AAG/C,MAAI,SAAS,SAAS;AACpB,iBAAa,iBAAiB,SAAS,EAAE,SAAS,CAAC;AAAA,EACrD,OAAO;AAEL,UAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,UAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,iBAAa,iBAAiB,QAAQ,EAAE,YAAY,WAAW,CAAC;AAAA,EAClE;AAEA,QAAM,0BAA0B,CAAC,QAAQ,OACrC,sBAAsB,cAAc,QAAQ,SAAS,KAAK,IAC1D;AAEJ,QAAM,qBAAqB,KAAK,IAAI;AAEpC,QAAM,eAAe,IAAI,aAAa,QAAQ,aAAa,YAAY;AAGvE,MAAI,aAAa;AAGjB,eAAa,GAAG,4BAA4B,CAAC,SAAS;AACpD,iBAAa,KAAK;AAAA,EACpB,CAAC;AAGD,QAAM,cAAc,MAAM,aAAa,QAAQ,OAAO;AAAA,IACpD;AAAA,IACA;AAAA,IACA,SAAS,IAAI,MAAM;AAAA,EACrB,CAAC;AAGD,QAAM,UAAwB,CAAC;AAC/B,aAAW,cAAc,aAAa;AACpC,UAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,WAAW,MAAM;AAEzD,QAAI,MAAM;AAER,UAAI;AACJ,UAAI;AAKJ,YAAM,SAAqB;AAAA,QACzB,QAAQ,WAAW;AAAA,QACnB,YAAY,KAAK;AAAA,QACjB,SAAS,KAAK,OAAO;AAAA,QACrB,UAAU,KAAK,OAAO;AAAA,QACtB,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAEA,cAAQ,KAAK,MAAM;AAAA,IACrB;AAAA,EACF;AAGA;AAGA,MAAI,YAAY;AACd,eAAW,SAAS,UAAU;AAAA,EAChC,OAAO;AAEL,UAAM,mBAAmB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,WAAW;AACzE,UAAM,oBAAoB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,YAAY;AAC3E,UAAM,iBAAiB,iBAAiB,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,QAAQ,CAAC;AACpF,UAAM,kBAAkB,kBAAkB,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,QAAQ,CAAC;AACtF,UAAM,eAAe,iBAAiB;AAGtC,UAAM,eAAe,QAClB,OAAO,CAAC,MAAM,EAAE,OAAO,EACvB,OAAO,CAAC,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AAEnE,UAAM,iBAAiB,QACpB,OAAO,CAAC,MAAM,EAAE,SAAS,EACzB,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,aAAa,IAAI,CAAC;AAGjD,QAAI;AAGJ,QAAI,SAAS,SAAS;AACpB,0BAAoB,EAAE,MAAM,SAAS,SAAS;AAAA,IAChD,OAAO;AACL,YAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,YAAM,aAAa,IAAI,MAAM,QAAQ;AACrC,0BAAoB,EAAE,MAAM,QAAQ,YAAY,WAAW;AAAA,IAC7D;AAGA,UAAM,gBAAgB,KAAK,IAAI,IAAI;AAEnC,iBAAa,SAAS;AAAA,MACpB,YAAY,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,aAAa,SAAS;AAAA,MACpC;AAAA,MACA,eAAe;AAAA,MACf;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKA,eAAe,YAA2B;AACxC,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,cAAc,IAAI,YAAY;AAEpC,QAAM,eAAe,IAAI,oBAAoB,QAAQ,WAAW;AAChE,QAAM,QAAQ,MAAM,aAAa,aAAa;AAE9C,iBAAe,KAAK;AACtB;AAKA,eAAe,OAAO;AACpB,QAAM,UAAU,IAAI,MAAM,CAAC;AAC3B,QAAM,aAAa,IAAI,MAAM,CAAC;AAE9B,UAAQ,SAAS;AAAA,IACf,KAAK,SAAS;AACZ,YAAM,WAAW,IAAI,MAAM,CAAC;AAC5B,YAAM,eAAe;AAAA,QACnB,QAAQ,IAAI,MAAM;AAAA,QAClB,MAAM,IAAI,MAAM;AAAA,QAChB,OAAO,IAAI,MAAM;AAAA,QACjB,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,eAAe;AAAA,QACnB,QAAQ,IAAI,MAAM;AAAA,QAClB,MAAM,IAAI,MAAM;AAAA,QAChB,OAAO,IAAI,MAAM;AAAA,QACjB,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,UAAU;AAChB;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,UAAI,eAAe,SAAS;AAC1B,cAAM,cAAc,IAAI,YAAY;AACpC,cAAM,UAAU,IAAI,QAAQ,WAAW;AACvC,cAAM,SAAS,MAAM,QAAQ,WAAW;AACxC,gBAAQ;AAAA,UACN;AAAA,EAAKA,OAAM,MAAM,4BAA4B,CAAC,YAAY,OAAO,YAAY;AAAA,QAC/E;AAAA,MACF,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,2BAA2B,GAAG,UAAU;AAChE,YAAI,SAAS;AACb,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,SAAS;AAEP,UAAI,CAAC,SAAS;AACZ,cAAM,eAAe;AAAA,UACnB,QAAQ,IAAI,MAAM;AAAA,UAClB,MAAM,IAAI,MAAM;AAAA,UAChB,OAAO,IAAI,MAAM;AAAA,UACjB,MAAM;AAAA,QACR,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,kBAAkB,GAAG,OAAO;AACpD,YAAI,SAAS;AACb,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,EACF;AACF;AA/fA,IAsKM;AAtKN;AAAA;AAAA;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AAEA,WAAO,OAAO;AA0Id,IAAM,MAAM;AAAA,MACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkCA;AAAA,QACE,YAAY;AAAA,QACZ,OAAO;AAAA;AAAA,UAEL,MAAM;AAAA,YACJ,MAAM;AAAA,UACR;AAAA,UAEA,MAAM;AAAA,YACJ,MAAM;AAAA,UACR;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,UACR;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,UACR;AAAA;AAAA,UAGA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,WAAW;AAAA,YACX,SAAS;AAAA,UACX;AAAA;AAAA,UAGA,SAAS;AAAA,YACP,MAAM;AAAA,YACN,WAAW;AAAA,UACb;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,WAAW;AAAA,UACb;AAAA,QACF;AAAA,QACA,SAAS,kBAAkB;AAAA,MAC7B;AAAA,IACF;AAoRA,SAAK;AAAA;AAAA;;;AChgBL,QAAQ,cAAc,MAAM;AAAC;AAC7B,QAAQ,mBAAmB,SAAS;AAGpC,QAAQ,QAAQ,MAAM;AAAC;AAGvB,IAAM,eAAe,QAAQ;AAC7B,QAAQ,OAAO,SAAU,UAAU,MAAM;AACvC,MACE,UAAU,cACR,KAAK,CAAC,KAAM,KAAK,CAAC,EAAU,SAAS,yBACpC,KAAK,CAAC,KAAM,KAAK,CAAC,EAAU,SAAS,YACxC;AACA,WAAO;AAAA,EACT;AAEA,SAAO,aAAa,MAAM,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;AACrD;AAIA,wDAAmB,MAAM,QAAQ,KAAK;",
|
|
6
|
+
"names": ["diffOutput", "fs", "path", "filePath", "fs", "path", "minimatch", "existsSync", "path", "require", "readFile", "path", "parse", "readFile", "path", "fs", "createRequire", "os", "path", "require", "resolve", "path", "path", "minimatch", "c", "chalk", "BRAND_COLOR", "VIOLATION_COLOR", "SUGGESTION_COLOR", "SKIPPED_COLOR", "chalk", "ora", "resolve", "fs", "os", "path", "chalk", "json"]
|
|
7
|
+
}
|