uilint 0.2.71 → 0.2.72

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/scan.ts","../src/utils/input.ts","../src/utils/path-specifiers.ts","../src/utils/llm-client.ts","../src/utils/timing.ts","../src/utils/output.ts","../src/commands/analyze.ts","../src/commands/consistency.ts","../src/commands/update.ts","../src/commands/serve.ts","../src/utils/vision-run.ts","../src/commands/vision.ts","../src/commands/config.ts","../src/commands/duplicates/index.ts","../src/commands/duplicates/index-cmd.ts","../src/commands/duplicates/find.ts","../src/commands/duplicates/search.ts","../src/commands/duplicates/similar.ts","../src/commands/socket/index.ts","../src/commands/socket/client.ts"],"sourcesContent":["/**\n * UILint CLI - AI-powered UI consistency checking\n */\n\nimport { Command } from \"commander\";\nimport { scan } from \"./commands/scan.js\";\nimport { analyze } from \"./commands/analyze.js\";\nimport { consistency } from \"./commands/consistency.js\";\nimport { update } from \"./commands/update.js\";\nimport { serve } from \"./commands/serve.js\";\nimport { vision } from \"./commands/vision.js\";\nimport { config } from \"./commands/config.js\";\nimport { createDuplicatesCommand } from \"./commands/duplicates/index.js\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number, minMinor: number): void {\n const ver = process.versions.node || \"\";\n const parts = ver.split(\".\");\n const major = Number.parseInt(parts[0] || \"\", 10);\n const minor = Number.parseInt(parts[1] || \"\", 10);\n\n const meetsRequirement =\n Number.isFinite(major) &&\n Number.isFinite(minor) &&\n (major > minMajor || (major === minMajor && minor >= minMinor));\n\n if (!meetsRequirement) {\n // Keep this dependency-free and stdout/stderr friendly.\n // eslint-disable-next-line no-console\n console.error(\n `uilint requires Node.js >= ${minMajor}.${minMinor}.0. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\n// Required by dependencies: chokidar, jsdom, readdirp, etc.\nassertNodeVersion(20, 19);\n\nconst program = new Command();\n\nfunction getCLIVersion(): string {\n try {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n version?: string;\n };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nprogram\n .name(\"uilint\")\n .description(\"AI-powered UI consistency checker\")\n .version(getCLIVersion());\n\n// Analyze command\nprogram\n .command(\"analyze\")\n .description(\n \"Analyze a source file/snippet for style issues (data-loc aware)\"\n )\n .option(\"-f, --input-file <path>\", \"Path to a source file to analyze\")\n .option(\"--source-code <code>\", \"Source code to analyze (string)\")\n .option(\"--file-path <path>\", \"File path label shown in the prompt\")\n .option(\"--style-guide <text>\", \"Inline styleguide content to use\")\n .option(\"--styleguide-path <path>\", \"Path to a style guide file\")\n .option(\"--component-name <name>\", \"Component name for focused analysis\")\n .option(\"--component-line <n>\", \"Component line number (integer)\", (v) =>\n parseInt(v, 10)\n )\n .option(\"--include-children\", \"Scope: selected element + children\")\n .option(\n \"--data-loc <value>\",\n \"data-loc value (repeatable) in format path:line:column\",\n (v, prev: string[] | undefined) => (prev ? [...prev, v] : [v]),\n []\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--stream\", \"Stream progress while analyzing (text mode UI only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/source/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await analyze({\n inputFile: options.inputFile,\n sourceCode: options.sourceCode,\n filePath: options.filePath,\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n output: options.output,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Scan command\nprogram\n .command(\"scan\")\n .description(\"Scan HTML for UI consistency issues\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to scan\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/style summary/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await scan({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n output: options.output,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Consistency command\nprogram\n .command(\"consistency\")\n .description(\"Analyze grouped DOM elements for visual inconsistencies\")\n .option(\"-j, --input-json <json>\", \"JSON input with GroupedSnapshot\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n await consistency({\n inputJson: options.inputJson,\n output: options.output,\n });\n });\n\n// Update command\nprogram\n .command(\"update\")\n .description(\"Update existing style guide with new styles\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to analyze\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"--llm\", \"Use LLM to suggest updates\")\n .action(async (options) => {\n await update({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n llm: options.llm,\n });\n });\n\n// Init command\nprogram\n .command(\"init\")\n .description(\"Initialize UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .action(async (options) => {\n const { initUI } = await import(\"./commands/init-ui.js\");\n await initUI({ force: options.force });\n });\n\n// Remove command\nprogram\n .command(\"remove\")\n .description(\"Remove UILint components from your project\")\n .option(\"--dry-run\", \"Preview changes without removing anything\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(async (options) => {\n const { removeUI } = await import(\"./commands/remove-ui.js\");\n await removeUI({ dryRun: options.dryRun, yes: options.yes });\n });\n\n// Serve command - WebSocket server for UI overlay\nprogram\n .command(\"serve\")\n .description(\"Start WebSocket server for real-time UI linting\")\n .option(\"-p, --port <number>\", \"Port to listen on\", \"9234\")\n .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\n });\n });\n\n// Vision command\nprogram\n .command(\"vision\")\n .description(\"Analyze a screenshot with Ollama vision models (requires a manifest)\")\n .option(\"--list\", \"List available .uilint/screenshots sidecars and exit\")\n .option(\n \"--screenshots-dir <path>\",\n \"Screenshots directory for --list (default: nearest .uilint/screenshots)\"\n )\n .option(\"--image <path>\", \"Path to a screenshot image (png/jpg)\")\n .option(\n \"--sidecar <path>\",\n \"Path to a .uilint/screenshots/*.json sidecar (contains manifest + metadata)\"\n )\n .option(\"--manifest-file <path>\", \"Path to a manifest JSON file (array)\")\n .option(\"--manifest-json <json>\", \"Inline manifest JSON (array)\")\n .option(\"--route <route>\", \"Optional route label (e.g., /todos)\")\n .option(\n \"-s, --styleguide <path>\",\n \"Path to style guide file OR project directory (falls back to upward search)\"\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--model <name>\", \"Ollama vision model override\", undefined)\n .option(\"--base-url <url>\", \"Ollama base URL (default: http://localhost:11434)\")\n .option(\"--stream\", \"Stream model output/progress to stderr (text mode only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/styleguide and include base64 in dumps (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full analysis payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await vision({\n list: options.list,\n screenshotsDir: options.screenshotsDir,\n image: options.image,\n sidecar: options.sidecar,\n manifestFile: options.manifestFile,\n manifestJson: options.manifestJson,\n route: options.route,\n styleguide: options.styleguide,\n output: options.output,\n model: options.model,\n baseUrl: options.baseUrl,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Config command\nprogram\n .command(\"config\")\n .description(\"Get or set UILint configuration options\")\n .argument(\"<action>\", \"Action: set or get\")\n .argument(\"<key>\", \"Config key (e.g., position, rule)\")\n .argument(\"[value]\", \"Value to set (for set action)\")\n .argument(\"[extraArg]\", \"Extra argument (e.g., options JSON for rule config)\")\n .option(\"-p, --port <number>\", \"WebSocket server port\", \"9234\")\n .action(async (action, key, value, extraArg, options) => {\n await config(action, key, value, extraArg, {\n port: parseInt(options.port, 10),\n });\n });\n\n// Duplicates command group - semantic code duplicate detection\nprogram.addCommand(createDuplicatesCommand());\n\n// Socket command - CLI for interacting with socket server\nimport { createSocketCommand } from \"./commands/socket/index.js\";\nprogram.addCommand(createSocketCommand());\n\n// Upgrade command - update installed rules\nprogram\n .command(\"upgrade\")\n .description(\"Update installed ESLint rules to latest versions\")\n .option(\"--check\", \"Show available updates without applying\")\n .option(\"-y, --yes\", \"Auto-confirm all updates\")\n .option(\"--dry-run\", \"Show what would change without modifying files\")\n .option(\"--rule <id>\", \"Upgrade only a specific rule\")\n .action(async (options) => {\n const { upgrade } = await import(\"./commands/upgrade.js\");\n await upgrade({\n check: options.check,\n yes: options.yes,\n dryRun: options.dryRun,\n rule: options.rule,\n });\n });\n\nprogram.parse();\n","/**\n * Scan command - scans HTML for UI consistency issues\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, statSync, writeFileSync } from \"fs\";\nimport {\n createStyleSummary,\n buildAnalysisPrompt,\n buildSourceAnalysisPrompt,\n formatViolationsText,\n sanitizeIssues,\n ensureOllamaReady,\n readStyleGuide,\n readStyleGuideFromProject,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n STYLEGUIDE_PATHS,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport {\n getScanInput,\n type InputOptions,\n type ScanInput,\n} from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ScanOptions extends InputOptions {\n styleguide?: string;\n output?: \"text\" | \"json\";\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleSummary/styleGuide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: ScanOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: ScanOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: ScanOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nexport async function scan(options: ScanOptions): Promise<void> {\n // For JSON output, skip the fancy UI\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Scan for UI Issues\");\n }\n\n try {\n // Get input\n let snapshot: ScanInput;\n try {\n const normalizedOptions: ScanOptions = {\n ...options,\n inputFile: options.inputFile\n ? resolvePathSpecifier(options.inputFile, process.cwd())\n : options.inputFile,\n };\n if (isJsonOutput) {\n snapshot = await getScanInput(normalizedOptions);\n } else {\n snapshot = await withSpinner(\"Parsing input\", async () => {\n return await getScanInput(normalizedOptions);\n });\n }\n } catch {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n output: options.output,\n });\n\n if (snapshot.kind === \"dom\") {\n const dom = snapshot.snapshot;\n debugLog(dbg, \"Parsed snapshot (high-level)\", {\n elementCount: dom.elementCount,\n timestamp: dom.timestamp,\n htmlLength: dom.html.length,\n styles: {\n colors: dom.styles.colors.size,\n fontSizes: dom.styles.fontSizes.size,\n fontFamilies: dom.styles.fontFamilies.size,\n fontWeights: dom.styles.fontWeights.size,\n spacing: dom.styles.spacing.size,\n borderRadius: dom.styles.borderRadius.size,\n },\n });\n if (dbgFull) {\n debugLog(dbg, \"Snapshot HTML (full)\", dom.html);\n } else if (dbg) {\n debugLog(dbg, \"Snapshot HTML (preview)\", preview(dom.html, 800));\n }\n\n if (!isJsonOutput) {\n logInfo(`Scanning ${pc.cyan(String(dom.elementCount))} elements`);\n }\n } else {\n debugLog(dbg, \"Parsed source input (high-level)\", {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n length: snapshot.source.length,\n lines: snapshot.source.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source (full)\", snapshot.source);\n } else if (dbg) {\n debugLog(dbg, \"Source (preview)\", preview(snapshot.source, 1200));\n }\n\n if (!isJsonOutput) {\n logInfo(\n `Scanning ${pc.cyan(snapshot.extension || \"source\")} (${pc.cyan(\n String(snapshot.source.split(\"\\n\").length)\n )} lines)`\n );\n }\n }\n\n // Get style guide\n // --styleguide can be either:\n // 1. Direct path to a styleguide file (e.g., /path/to/.uilint/styleguide.md)\n // 2. Path to a project directory to search in\n // 3. Not provided - search from cwd\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const projectPath = process.cwd();\n\n if (options.styleguide) {\n const styleguideArg = resolvePathSpecifier(\n options.styleguide,\n projectPath\n );\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n // Direct path to styleguide file\n styleguideLocation = styleguideArg;\n styleGuide = await readStyleGuide(styleguideArg);\n } else if (stat.isDirectory()) {\n // Path to project directory - search within it\n styleguideLocation = findStyleGuidePath(styleguideArg);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n } else {\n if (!isJsonOutput) {\n logWarning(`Styleguide not found: ${styleguideArg}`);\n }\n }\n } else {\n // No --styleguide provided:\n // Prefer searching upward from the input file directory for `.uilint/styleguide.md`\n // (helps when running from repo root but scanning a nested app/package).\n const startPath =\n snapshot.kind === \"source\"\n ? snapshot.inputPath\n : snapshot.kind === \"dom\"\n ? snapshot.inputPath\n : undefined;\n if (startPath) {\n styleguideLocation = findUILintStyleGuideUpwards(dirname(startPath));\n }\n\n // Fallback: search from cwd\n styleguideLocation =\n styleguideLocation ?? findStyleGuidePath(projectPath);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n }\n } else if (!styleGuide) {\n if (!isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n }\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleguideArg: options.styleguide,\n styleguideLocation: styleguideLocation ?? null,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", styleGuide ?? \"\");\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide contents (preview)\", preview(styleGuide, 800));\n }\n\n // Create style summary\n const tailwindSearchDir =\n (snapshot.kind === \"source\" || snapshot.kind === \"dom\") &&\n snapshot.inputPath\n ? dirname(snapshot.inputPath)\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n const styleSummary =\n snapshot.kind === \"dom\"\n ? createStyleSummary(snapshot.snapshot.styles, {\n html: snapshot.snapshot.html,\n tailwindTheme,\n })\n : null;\n\n debugLog(dbg, \"Tailwind context\", {\n tailwindSearchDir,\n tailwindTheme: tailwindTheme\n ? {\n configPath: tailwindTheme.configPath,\n colors: tailwindTheme.colors.length,\n spacingKeys: tailwindTheme.spacingKeys.length,\n borderRadiusKeys: tailwindTheme.borderRadiusKeys.length,\n fontFamilyKeys: tailwindTheme.fontFamilyKeys.length,\n fontSizeKeys: tailwindTheme.fontSizeKeys.length,\n }\n : null,\n });\n\n debugLog(dbg, \"Style summary (stats)\", {\n length: styleSummary ? styleSummary.length : 0,\n lines: styleSummary ? styleSummary.split(\"\\n\").length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Style summary (full)\", styleSummary ?? \"\");\n } else if (dbg && styleSummary) {\n debugLog(dbg, \"Style summary (preview)\", preview(styleSummary, 800));\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n // Call Ollama for analysis\n const client = await createLLMClient({});\n let result;\n\n // Build the exact prompt (this is what analyzeStyles() uses internally)\n const prompt =\n snapshot.kind === \"dom\"\n ? buildAnalysisPrompt(styleSummary ?? \"\", styleGuide)\n : buildSourceAnalysisPrompt(snapshot.source, styleGuide, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `scan-debug-${safeStamp}.json`);\n\n // If path looks like a directory (or a non-json file), ensure dir exists.\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n options: {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n styleguideLocation,\n output: options.output,\n model: client.getModel(),\n },\n snapshot: {\n kind: snapshot.kind,\n ...(snapshot.kind === \"dom\"\n ? {\n elementCount: snapshot.snapshot.elementCount,\n timestamp: snapshot.snapshot.timestamp,\n html: snapshot.snapshot.html,\n styles: {\n colors: [...snapshot.snapshot.styles.colors.entries()],\n fontSizes: [\n ...snapshot.snapshot.styles.fontSizes.entries(),\n ],\n fontFamilies: [\n ...snapshot.snapshot.styles.fontFamilies.entries(),\n ],\n fontWeights: [\n ...snapshot.snapshot.styles.fontWeights.entries(),\n ],\n spacing: [\n ...snapshot.snapshot.styles.spacing.entries(),\n ],\n borderRadius: [\n ...snapshot.snapshot.styles.borderRadius.entries(),\n ],\n },\n }\n : {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n source: snapshot.source,\n }),\n },\n styleGuide,\n styleSummary,\n prompt,\n tailwindTheme,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n if (isJsonOutput) {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(styleSummary ?? \"\", styleGuide)\n : await client.analyzeSource(snapshot.source, styleGuide, undefined, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n } else {\n // Use streaming to show progress\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n const onProgress = (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ): void => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[scan] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n // Truncate line if too long for terminal\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n };\n\n try {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(\n styleSummary ?? \"\",\n styleGuide,\n onProgress\n )\n : await client.analyzeSource(\n snapshot.source,\n styleGuide,\n onProgress,\n {\n filePath: snapshot.inputPath,\n languageHint:\n snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n }\n );\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (error) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw error;\n }\n }\n\n // Sanitize (enforce violations-only output)\n const issues = sanitizeIssues(result.issues);\n\n // Output results\n if (isJsonOutput) {\n printJSON({\n issues,\n analysisTime: result.analysisTime,\n elementCount:\n snapshot.kind === \"dom\" ? snapshot.snapshot.elementCount : 0,\n });\n } else {\n // Minimal output: list violations only, plus footer to consult the style guide.\n process.stdout.write(\n formatViolationsText(issues, { includeFooter: issues.length > 0 }) +\n \"\\n\"\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Scan failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Input handling utilities for CLI\n */\n\nimport { readFile } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { extname } from \"path\";\nimport {\n parseCLIInput,\n hasStdin,\n readStdin,\n type DOMSnapshot,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport interface InputOptions {\n inputFile?: string;\n inputJson?: string;\n}\n\nexport type ScanInput =\n | {\n kind: \"dom\";\n snapshot: DOMSnapshot;\n source: \"json\" | \"file\" | \"stdin\";\n inputPath?: string;\n }\n | {\n kind: \"source\";\n source: string;\n inputPath: string;\n extension: string;\n };\n\nfunction isHtmlLikeExtension(ext: string): boolean {\n return ext === \".html\" || ext === \".htm\";\n}\n\nfunction isJsonLikeExtension(ext: string): boolean {\n return ext === \".json\";\n}\n\n/**\n * Gets input from various sources: stdin, file, or JSON string\n */\nexport async function getInput(options: InputOptions): Promise<DOMSnapshot> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return parseCLIInput(options.inputJson);\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n return parseCLIInput(content);\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return parseCLIInput(content);\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets scan input:\n * - If input is a file and it's not HTML/JSON, treat it as raw source (TSX/JSX/etc).\n * - Otherwise, treat it as HTML/DOM input (including JSON-wrapped snapshots).\n */\nexport async function getScanInput(options: InputOptions): Promise<ScanInput> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(options.inputJson),\n source: \"json\",\n };\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n const ext = extname(filePath).toLowerCase();\n\n if (isHtmlLikeExtension(ext) || isJsonLikeExtension(ext)) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"file\",\n inputPath: filePath,\n };\n }\n\n return {\n kind: \"source\",\n source: content,\n inputPath: filePath,\n extension: ext,\n };\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"stdin\",\n };\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets code input from various sources\n */\nexport async function getCodeInput(options: {\n code?: string;\n file?: string;\n}): Promise<string> {\n if (options.code) {\n return options.code;\n }\n\n if (options.file) {\n const filePath = resolvePathSpecifier(options.file, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.file}`);\n }\n return readFile(filePath, \"utf-8\");\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No code provided via stdin\");\n }\n return content;\n }\n\n throw new Error(\n \"No code provided. Use --code, provide a file, or pipe to stdin.\"\n );\n}\n\n/**\n * Validates that a path exists\n */\nexport function validatePath(path: string, description: string): void {\n if (!existsSync(path)) {\n throw new Error(`${description} not found: ${path}`);\n }\n}\n","/**\n * Path specifier utilities for CLI.\n *\n * We support \"workspace-relative\" specifiers using a leading \"@\", e.g.:\n * - @apps/test-app/app/page.tsx\n * - @apps/test-app/.uilint/styleguide.md\n *\n * This mirrors how some tools (and humans) refer to \"repo-relative\" paths.\n */\n\nimport { isAbsolute, resolve } from \"path\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n/**\n * Resolve a user-provided path specifier into an absolute filesystem path.\n *\n * Rules:\n * - Absolute paths are left absolute (normalized with resolve()).\n * - \"@<path>\" is resolved relative to the workspace root (pnpm-workspace/.git).\n * - Everything else is resolved relative to cwd.\n */\nexport function resolvePathSpecifier(\n spec: string,\n cwd: string = process.cwd()\n): string {\n const raw = (spec ?? \"\").trim();\n if (!raw) return resolve(cwd, spec);\n\n if (raw.startsWith(\"@\")) {\n const workspaceRoot = findWorkspaceRoot(cwd);\n let rest = raw.slice(1);\n if (rest.startsWith(\"/\")) rest = rest.slice(1);\n // Note: resolve(workspaceRoot, rest) is safe even if rest contains \"..\";\n // callers that need a security boundary should validate separately.\n return resolve(workspaceRoot, rest);\n }\n\n if (isAbsolute(raw)) return resolve(raw);\n return resolve(cwd, raw);\n}\n","/**\n * LLM Client Factory with Optional Langfuse Instrumentation\n *\n * This module provides a centralized way to create OllamaClient instances\n * with optional Langfuse tracing enabled. Langfuse is only loaded if:\n * 1. LANGFUSE_ENABLED=1 (or true/yes)\n * 2. LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY are set\n */\n\nimport { config } from \"dotenv\";\nimport { join } from \"path\";\nimport {\n OllamaClient,\n type LLMInstrumentationCallbacks,\n type InstrumentationSpan,\n findWorkspaceRoot,\n} from \"uilint-core/node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { LangfuseSpanProcessor } from \"@langfuse/otel\";\nimport {\n startActiveObservation,\n startObservation,\n type LangfuseObservation,\n type LangfuseGeneration,\n} from \"@langfuse/tracing\";\n\n// Load .env.local from workspace root\nlet envLoaded = false;\nfunction loadEnvLocal(): void {\n if (envLoaded) return;\n envLoaded = true;\n\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n const envLocalPath = join(workspaceRoot, \".env.local\");\n\n // Load .env.local if it exists (dotenv will silently skip if file doesn't exist)\n config({ path: envLocalPath });\n}\n\n// Load environment variables immediately on module load\nloadEnvLocal();\n\n// Lazy-loaded instrumentation\nlet langfuseInitialized = false;\nlet langfuseInstrumentation: LLMInstrumentationCallbacks | undefined;\nlet sdkInstance: NodeSDK | undefined;\nlet spanProcessor: LangfuseSpanProcessor | undefined;\n\n/**\n * Checks if Langfuse is enabled via environment variable\n */\nfunction isLangfuseEnabled(): boolean {\n const enabled = process.env.LANGFUSE_ENABLED;\n if (!enabled) return false;\n return (\n enabled === \"1\" ||\n enabled.toLowerCase() === \"true\" ||\n enabled.toLowerCase() === \"yes\"\n );\n}\n\n/**\n * Initialize Langfuse if enabled. This is called automatically on first client creation,\n * but can also be called explicitly at app startup.\n */\nexport async function initializeLangfuseIfEnabled(): Promise<void> {\n if (langfuseInitialized) return;\n langfuseInitialized = true;\n\n if (!isLangfuseEnabled()) {\n return;\n }\n\n const publicKey = process.env.LANGFUSE_PUBLIC_KEY;\n const secretKey = process.env.LANGFUSE_SECRET_KEY;\n\n if (!publicKey || !secretKey) {\n console.error(\n \"[uilint] LANGFUSE_ENABLED=1 but missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY\"\n );\n return;\n }\n\n try {\n const baseUrl = process.env.LANGFUSE_BASE_URL || \"http://localhost:3333\";\n\n // Create the span processor with immediate export mode for CLI usage\n spanProcessor = new LangfuseSpanProcessor({\n publicKey,\n secretKey,\n baseUrl,\n // Use immediate mode to ensure spans are exported right away in CLI context\n exportMode: \"immediate\",\n });\n\n // Initialize OpenTelemetry with LangfuseSpanProcessor\n const sdk = new NodeSDK({\n spanProcessors: [spanProcessor],\n });\n\n sdk.start();\n sdkInstance = sdk;\n\n // Create instrumentation callbacks using @langfuse/tracing\n // Use startActiveObservation at top level to create the trace context\n langfuseInstrumentation = {\n onGenerationStart: ({\n name,\n model,\n prompt,\n metadata,\n }: {\n name: string;\n model: string;\n prompt: string;\n metadata?: Record<string, unknown>;\n }): InstrumentationSpan => {\n // We need to bridge the callback-based startActiveObservation with our\n // synchronous start / async end pattern. Use a promise to control when the trace ends.\n let resolveTrace: () => void;\n let generationRef: LangfuseGeneration | undefined;\n let traceRef: LangfuseObservation | undefined;\n let endData:\n | {\n output: string;\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n };\n }\n | undefined;\n\n // Start the active observation (trace) - this runs the callback immediately\n // but doesn't resolve until we call resolveTrace()\n const tracePromise = startActiveObservation(\n `uilint-${name}`,\n async (span) => {\n traceRef = span;\n span.update({\n input: { operation: name },\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n });\n\n // Create the generation as a child - startObservation within startActiveObservation\n // automatically nests under the active trace\n generationRef = startObservation(\n name,\n {\n model,\n input: prompt,\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n },\n { asType: \"generation\" }\n );\n\n // Wait for end() to be called before completing the trace\n await new Promise<void>((resolve) => {\n resolveTrace = resolve;\n });\n\n // Now process the end data\n if (endData && generationRef) {\n const usageDetails: Record<string, number> | undefined =\n endData.usage\n ? Object.fromEntries(\n Object.entries({\n input: endData.usage.promptTokens,\n output: endData.usage.completionTokens,\n total: endData.usage.totalTokens,\n }).filter(([, v]) => v !== undefined) as [\n string,\n number\n ][]\n )\n : undefined;\n\n // End the generation\n generationRef.update({\n output: endData.output,\n usageDetails:\n usageDetails && Object.keys(usageDetails).length > 0\n ? usageDetails\n : undefined,\n metadata: endData.usage?.error\n ? { ...metadata, error: endData.usage.error }\n : metadata,\n });\n generationRef.end();\n\n // Update the trace output\n span.update({\n output: endData.usage?.error\n ? `Error: ${endData.usage.error}`\n : \"completed\",\n });\n }\n // The trace automatically ends when the callback completes\n }\n );\n\n // Handle any errors from the trace promise\n tracePromise.catch((error) => {\n console.error(\"[uilint] Langfuse trace error:\", error);\n });\n\n return {\n end: (\n output: string,\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n }\n ) => {\n // Store the end data and resolve the trace promise\n endData = { output, usage };\n if (resolveTrace) {\n resolveTrace();\n }\n },\n };\n },\n };\n\n console.error(`[uilint] Langfuse tracing enabled (${baseUrl})`);\n } catch (error) {\n console.error(\n \"[uilint] Failed to initialize Langfuse:\",\n error instanceof Error ? error.message : error\n );\n }\n}\n\n/**\n * Creates an OllamaClient with optional Langfuse instrumentation.\n * Automatically initializes Langfuse on first call if enabled.\n */\nexport async function createLLMClient(options: {\n model?: string;\n baseUrl?: string;\n timeout?: number;\n}): Promise<OllamaClient> {\n // Initialize Langfuse on first client creation\n await initializeLangfuseIfEnabled();\n\n return new OllamaClient({\n ...options,\n instrumentation: langfuseInstrumentation,\n });\n}\n\n/**\n * Flushes Langfuse traces. Call this before process exit to ensure all traces are sent.\n */\nexport async function flushLangfuse(): Promise<void> {\n // Force flush the span processor first to ensure all pending spans are sent\n if (spanProcessor) {\n try {\n await spanProcessor.forceFlush();\n } catch (error) {\n console.error(\n \"[uilint] Failed to flush Langfuse spans:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n\n // Then shutdown the SDK\n if (sdkInstance) {\n try {\n await sdkInstance.shutdown();\n } catch (error) {\n console.error(\n \"[uilint] Failed to shutdown OpenTelemetry SDK:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n}\n\n/**\n * Returns true if Langfuse is currently initialized and active.\n */\nexport function isLangfuseActive(): boolean {\n return spanProcessor !== undefined;\n}\n\n// Register shutdown handler\nlet shutdownRegistered = false;\nfunction registerShutdownHandler(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n\n const cleanup = async () => {\n await flushLangfuse();\n };\n\n process.on(\"beforeExit\", cleanup);\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(130);\n });\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(143);\n });\n}\n\n// Auto-register on module load\nregisterShutdownHandler();\n","/**\n * High-precision timing helpers for CLI UX\n */\n\nexport function nsNow(): bigint {\n return process.hrtime.bigint();\n}\n\nexport function nsToMs(ns: bigint): number {\n return Number(ns) / 1_000_000;\n}\n\nexport function formatMs(ms: number): string {\n if (!Number.isFinite(ms)) return \"n/a\";\n if (ms < 1000) return `${ms.toFixed(ms < 10 ? 2 : ms < 100 ? 1 : 0)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${s.toFixed(s < 10 ? 2 : 1)}s`;\n const m = Math.floor(s / 60);\n const rem = s - m * 60;\n return `${m}m ${rem.toFixed(rem < 10 ? 1 : 0)}s`;\n}\n\nexport function maybeMs(ms: number | null | undefined): string {\n return ms == null ? \"n/a\" : formatMs(ms);\n}\n","/**\n * Output formatting utilities for CLI\n */\n\nimport chalk from \"chalk\";\nimport {\n formatViolationsText,\n sanitizeIssues,\n type UILintIssue,\n} from \"uilint-core\";\n\n/**\n * Formats UILint issues for console output\n */\nexport function formatIssues(issues: UILintIssue[]): string {\n const sanitized = sanitizeIssues(issues);\n const text = formatViolationsText(sanitized, {\n includeFooter: sanitized.length > 0,\n });\n // Preserve existing callers expecting a string; apply minimal coloring only.\n return sanitized.length === 0 ? chalk.green(text) : text;\n}\n\n/**\n * Prints JSON output\n */\nexport function printJSON(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * Prints an error message\n */\nexport function printError(message: string): void {\n console.error(chalk.red(`Error: ${message}`));\n}\n\n/**\n * Prints a success message\n */\nexport function printSuccess(message: string): void {\n console.log(chalk.green(`✓ ${message}`));\n}\n\n/**\n * Prints a warning message\n */\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n\n/**\n * Prints an info message\n */\nexport function printInfo(message: string): void {\n console.log(chalk.blue(`ℹ ${message}`));\n}\n\n/**\n * Prints a debug/path message (dimmed)\n */\nexport function printPath(label: string, path: string): void {\n console.log(chalk.gray(` ${label}: ${chalk.dim(path)}`));\n}\n\n/**\n * Prints a styled box for important messages\n */\nexport function printBox(\n title: string,\n lines: string[],\n style: \"warning\" | \"error\" | \"info\" = \"info\"\n): void {\n const colors = {\n warning: { border: chalk.yellow, title: chalk.yellow.bold, icon: \"⚠\" },\n error: { border: chalk.red, title: chalk.red.bold, icon: \"✖\" },\n info: { border: chalk.blue, title: chalk.blue.bold, icon: \"ℹ\" },\n };\n const { border, title: titleColor, icon } = colors[style];\n\n const maxLen = Math.max(title.length, ...lines.map((l) => l.length)) + 4;\n const horizontal = \"─\".repeat(maxLen);\n\n console.log();\n console.log(border(`╭${horizontal}╮`));\n console.log(border(`│ ${icon} ${titleColor(title.padEnd(maxLen - 3))}│`));\n console.log(border(`├${horizontal}┤`));\n lines.forEach((line) => {\n console.log(border(`│ ${chalk.gray(line.padEnd(maxLen - 1))}│`));\n });\n console.log(border(`╰${horizontal}╯`));\n console.log();\n}\n\n/**\n * Prints styleguide status information\n */\nexport function printStyleguideNotFound(\n searchedPaths: string[],\n projectPath: string\n): void {\n printBox(\n \"No styleguide found\",\n [\n `Searched in: ${projectPath}`,\n \"\",\n \"Looked for:\",\n ...searchedPaths.map((p) => ` • ${p}`),\n \"\",\n \"To create one, run:\",\n ` ${chalk.cyan(\"/genstyleguide\")} ${chalk.gray(\"(Cursor)\")}`,\n ],\n \"warning\"\n );\n}\n\n/**\n * Prints styleguide found confirmation\n */\nexport function printStyleguideFound(path: string): void {\n console.log(chalk.green(`📋 Using styleguide: ${chalk.dim(path)}`));\n}\n","/**\n * Analyze command - analyzes a source file/snippet for style issues (data-loc aware)\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n buildSourceScanPrompt,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findWorkspaceRoot,\n findUILintStyleGuideUpwards,\n} from \"uilint-core/node\";\nimport { getCodeInput } from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logError,\n logWarning,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\ntype UILintScanIssue = {\n line?: number;\n message: string;\n dataLoc?: string;\n};\n\nexport interface AnalyzeOptions {\n // Input\n inputFile?: string;\n sourceCode?: string;\n\n // Styleguide\n styleGuide?: string;\n styleguidePath?: string;\n\n // Prompt context\n filePath?: string;\n componentName?: string;\n componentLine?: number;\n includeChildren?: boolean;\n dataLoc?: string[]; // repeatable\n\n // LLM\n stream?: boolean;\n\n // Output\n output?: \"text\" | \"json\";\n\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleguide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: AnalyzeOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nasync function resolveStyleGuideForAnalyze(options: {\n styleGuide?: string;\n styleguidePath?: string;\n inputFile?: string;\n}): Promise<{ content: string | null; path: string | null }> {\n // 1) Inline (highest priority)\n if (options.styleGuide && typeof options.styleGuide === \"string\") {\n return { content: options.styleGuide, path: null };\n }\n\n // 2) Explicit path\n if (options.styleguidePath && typeof options.styleguidePath === \"string\") {\n const p = resolvePathSpecifier(options.styleguidePath, process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n return { content: null, path: null };\n }\n\n // 3) Env var pin\n const env = process.env.UILINT_STYLEGUIDE_PATH;\n if (env && env.trim()) {\n const p = resolvePathSpecifier(env.trim(), process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n }\n\n // 4) Smarter default: walk upward from the input file dir looking for `.uilint/styleguide.md`\n if (options.inputFile) {\n const absInput = resolvePathSpecifier(options.inputFile, process.cwd());\n const found = findUILintStyleGuideUpwards(dirname(absInput));\n if (found) return { content: await readStyleGuide(found), path: found };\n }\n\n // 5) Fallbacks: cwd, then workspace root (monorepo)\n const cwdPath = findStyleGuidePath(process.cwd());\n if (cwdPath) return { content: await readStyleGuide(cwdPath), path: cwdPath };\n\n const wsRoot = findWorkspaceRoot(process.cwd());\n const wsPath = findStyleGuidePath(wsRoot);\n if (wsPath) return { content: await readStyleGuide(wsPath), path: wsPath };\n\n return { content: null, path: null };\n}\n\nfunction formatScanIssuesText(issues: UILintScanIssue[]): string {\n if (issues.length === 0) return pc.green(\"No issues found.\");\n const lines = issues.map((i) => {\n const line = typeof i.line === \"number\" ? `Line ${i.line}: ` : \"\";\n const loc = i.dataLoc ? ` ${pc.dim(`(${i.dataLoc})`)}` : \"\";\n return `- ${line}${i.message}${loc}`;\n });\n return lines.join(\"\\n\");\n}\n\nexport async function analyze(options: AnalyzeOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Analyze Source Code\");\n }\n\n try {\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n stream: options.stream,\n output: options.output,\n });\n\n // Input\n const sourceCode = await getCodeInput({\n code: options.sourceCode,\n file: options.inputFile\n ? resolvePathSpecifier(options.inputFile)\n : undefined,\n });\n\n debugLog(dbg, \"Source code (high-level)\", {\n length: sourceCode.length,\n lines: sourceCode.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source code (full)\", sourceCode);\n } else if (dbg) {\n debugLog(dbg, \"Source code (preview)\", preview(sourceCode, 800));\n }\n\n const resolvedStyle = await resolveStyleGuideForAnalyze({\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n inputFile: options.inputFile,\n });\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleGuideArg:\n options.styleguidePath ?? options.styleGuide ? \"(inline)\" : null,\n styleguideLocation: resolvedStyle.path,\n styleGuideLength: resolvedStyle.content\n ? resolvedStyle.content.length\n : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", resolvedStyle.content ?? \"\");\n } else if (dbg && resolvedStyle.content) {\n debugLog(\n dbg,\n \"Styleguide contents (preview)\",\n preview(resolvedStyle.content, 800)\n );\n }\n\n if (!resolvedStyle.content && !isJsonOutput) {\n logWarning(\"No styleguide found (analyzing without it)\");\n } else if (resolvedStyle.path && !isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(resolvedStyle.path)}`);\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n const client = await createLLMClient({});\n\n const promptContext = {\n filePath:\n options.filePath ||\n (options.inputFile ? options.inputFile : undefined) ||\n \"component.tsx\",\n componentName: options.componentName,\n componentLine:\n typeof options.componentLine === \"number\"\n ? options.componentLine\n : undefined,\n includeChildren: options.includeChildren === true,\n dataLocs: Array.isArray(options.dataLoc) ? options.dataLoc : undefined,\n };\n\n const prompt = buildSourceScanPrompt(\n sourceCode,\n resolvedStyle.content,\n promptContext\n );\n\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n // Debug dump\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `analyze-debug-${safeStamp}.json`);\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n command: \"analyze\",\n options: {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n styleguideLocation: resolvedStyle.path,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n model: client.getModel(),\n stream: options.stream,\n output: options.output,\n },\n input: {\n sourceCode,\n sourceLines: sourceCode.split(\"\\n\").length,\n },\n styleGuide: resolvedStyle.content,\n promptContext,\n prompt,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n let responseText = \"\";\n if (options.stream) {\n if (!isJsonOutput) {\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n try {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[analyze] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n const maxLen = 60;\n const line =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(line || \"...\")}`);\n },\n });\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (e) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw e;\n }\n } else {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: () => {\n // JSON mode: never write progress to stdout\n },\n });\n }\n } else {\n responseText = await client.complete(prompt, { json: true });\n }\n\n const parsed = JSON.parse(responseText) as { issues?: UILintScanIssue[] };\n const issues = Array.isArray(parsed.issues) ? parsed.issues : [];\n\n if (isJsonOutput) {\n printJSON({ issues });\n } else {\n process.stdout.write(formatScanIssuesText(issues) + \"\\n\");\n }\n\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analyze failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Consistency command - analyzes grouped DOM elements for visual inconsistencies\n */\n\nimport { createInterface } from \"readline\";\nimport {\n parseGroupedSnapshot,\n analyzeConsistency,\n formatConsistencyViolations,\n countElements,\n hasAnalyzableGroups,\n type ConsistencyResult,\n} from \"uilint-core\";\nimport { ensureOllamaReady } from \"uilint-core/node\";\nimport {\n intro,\n withSpinner,\n logInfo,\n logError,\n logSuccess,\n logWarning,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ConsistencyOptions {\n inputJson?: string;\n output?: \"text\" | \"json\";\n}\n\n/**\n * Reads JSON input from stdin\n */\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n const rl = createInterface({ input: process.stdin });\n rl.on(\"line\", (line) => {\n data += line;\n });\n rl.on(\"close\", () => {\n resolve(data);\n });\n });\n}\n\n/**\n * Main consistency analysis command\n */\nexport async function consistency(options: ConsistencyOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n\n if (!isJsonOutput) {\n intro(\"UI Consistency Analysis\");\n }\n\n try {\n // Get input\n let inputJson = options.inputJson;\n if (!inputJson) {\n // Check if stdin has data\n if (!process.stdin.isTTY) {\n inputJson = await readStdin();\n }\n }\n\n if (!inputJson) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", violations: [] });\n } else {\n logError(\"No input provided. Use --input-json or pipe JSON to stdin.\");\n }\n process.exit(1);\n }\n\n // Parse snapshot\n const snapshot = parseGroupedSnapshot(inputJson);\n if (!snapshot) {\n if (isJsonOutput) {\n printJSON({ error: \"Invalid JSON input\", violations: [] });\n } else {\n logError(\"Failed to parse input as GroupedSnapshot.\");\n }\n process.exit(1);\n }\n\n const elementCount = countElements(snapshot);\n\n if (!isJsonOutput) {\n logInfo(`Analyzing ${pc.cyan(String(elementCount))} elements`);\n }\n\n // Check if there are analyzable groups\n if (!hasAnalyzableGroups(snapshot)) {\n const result: ConsistencyResult = {\n violations: [],\n elementCount,\n analysisTime: 0,\n };\n\n if (isJsonOutput) {\n printJSON(result);\n } else {\n logWarning(\"No groups with 2+ elements to analyze.\");\n }\n return;\n }\n\n // Prepare Ollama\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n\n // Analyze with core function\n let result: ConsistencyResult;\n if (isJsonOutput) {\n result = await analyzeConsistency(snapshot, {});\n } else {\n result = await withSpinner(\"Analyzing with LLM\", async () => {\n return await analyzeConsistency(snapshot, {});\n });\n }\n\n // Output results\n if (isJsonOutput) {\n printJSON(result);\n } else {\n console.log();\n console.log(formatConsistencyViolations(result.violations));\n\n if (result.violations.length > 0) {\n logInfo(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n } else {\n logSuccess(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n }\n }\n\n // Exit with error code if violations found\n if (result.violations.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n violations: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analysis failed\");\n }\n process.exit(1);\n }\n}\n","/**\n * Update command - updates existing style guide with new styles\n */\n\nimport { dirname, resolve } from \"path\";\nimport {\n createStyleSummary,\n parseStyleGuide,\n mergeStyleGuides,\n styleGuideToMarkdown,\n} from \"uilint-core\";\nimport {\n readStyleGuide,\n writeStyleGuide,\n findStyleGuidePath,\n ensureOllamaReady,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport { getInput, type InputOptions } from \"../utils/input.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport {\n intro,\n outro,\n withSpinner,\n note,\n logSuccess,\n logInfo,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface UpdateOptions extends InputOptions {\n styleguide?: string;\n llm?: boolean;\n}\n\nexport async function update(options: UpdateOptions): Promise<void> {\n intro(\"Update Style Guide\");\n\n try {\n const projectPath = process.cwd();\n const styleGuidePath =\n options.styleguide || findStyleGuidePath(projectPath);\n\n if (!styleGuidePath) {\n logError(\"No style guide found\");\n note(\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} first (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n \"Tip\"\n );\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Using styleguide: ${pc.dim(styleGuidePath)}`);\n\n // Read existing style guide\n const existingContent = await readStyleGuide(styleGuidePath);\n const existingGuide = parseStyleGuide(existingContent);\n\n // Get input\n let snapshot;\n try {\n snapshot = await withSpinner(\"Analyzing project\", async () => {\n return await getInput(options);\n });\n } catch {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Found ${pc.cyan(String(snapshot.elementCount))} elements`);\n\n const tailwindSearchDir = options.inputFile\n ? dirname(resolve(projectPath, options.inputFile))\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n\n if (options.llm) {\n // Use LLM to suggest updates\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n\n const result = await withSpinner(\n \"Analyzing styles with LLM\",\n async () => {\n const client = await createLLMClient({});\n const styleSummary = createStyleSummary(snapshot.styles, {\n html: snapshot.html,\n tailwindTheme,\n });\n return await client.analyzeStyles(styleSummary, existingContent);\n }\n );\n\n if (result.issues.length > 0) {\n const suggestions = result.issues.map((issue) => {\n let line = `• ${issue.message}`;\n if (issue.suggestion) {\n line += `\\n ${pc.cyan(\"→\")} ${issue.suggestion}`;\n }\n return line;\n });\n\n note(\n suggestions.join(\"\\n\\n\"),\n `Found ${result.issues.length} suggestion(s)`\n );\n logInfo(\"Edit the styleguide manually to apply these changes.\");\n outro(\"Analysis complete\");\n } else {\n logSuccess(\"Style guide is up to date!\");\n outro(\"No changes needed\");\n }\n } else {\n // Parse new styles and merge\n const updatedContent = await withSpinner(\"Merging styles\", async () => {\n // Create a new guide from detected styles\n const mergedColors = new Map(snapshot.styles.colors);\n for (const m of (snapshot.html || \"\").matchAll(/#[A-Fa-f0-9]{6}\\b/g)) {\n const hex = (m[0] || \"\").toUpperCase();\n if (!hex) continue;\n mergedColors.set(hex, (mergedColors.get(hex) || 0) + 1);\n }\n\n const detectedColors = [...mergedColors.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([value], index) => ({\n name: `Color ${index + 1}`,\n value: value.toUpperCase(),\n usage: \"\",\n }));\n\n const detectedGuide = {\n colors: detectedColors,\n typography: [],\n spacing: [],\n components: [],\n };\n\n // Merge with existing\n const mergedGuide = mergeStyleGuides(existingGuide, detectedGuide);\n return styleGuideToMarkdown(mergedGuide);\n });\n\n // Check if there are any changes\n if (updatedContent === existingContent) {\n logSuccess(\"Style guide is already up to date!\");\n outro(\"No changes needed\");\n return;\n }\n\n // Write updated style guide\n await withSpinner(\"Writing styleguide\", async () => {\n await writeStyleGuide(styleGuidePath, updatedContent);\n });\n\n note(`Updated: ${pc.dim(styleGuidePath)}`, \"Success\");\n outro(\"Style guide updated!\");\n }\n } catch (error) {\n logError(error instanceof Error ? error.message : \"Update failed\");\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * UILint WebSocket Server\n *\n * Provides real-time lint results for the UI overlay.\n *\n * Protocol:\n * - Client -> Server: { type: 'lint:file', filePath: string, requestId?: string }\n * - Client -> Server: { type: 'lint:element', filePath: string, dataLoc: string, requestId?: string }\n * - Client -> Server: { type: 'subscribe:file', filePath: string }\n * - Client -> Server: { type: 'cache:invalidate', filePath?: string }\n * - Client -> Server: { type: 'vision:analyze', route: string, timestamp: number, screenshot?: string, screenshotFile?: string, manifest: ElementManifest[], requestId?: string }\n * - Client -> Server: { type: 'vision:check', requestId?: string }\n * - Client -> Server: { type: 'config:set', key: string, value: any }\n * - Client -> Server: { type: 'rule:config:set', ruleId: string, severity: 'error'|'warn'|'off', options?: object, requestId?: string }\n * - Server -> Client: { type: 'lint:result', filePath: string, issues: Issue[], requestId?: string }\n * - Server -> Client: { type: 'lint:progress', filePath: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'file:changed', filePath: string }\n * - Server -> Client: { type: 'vision:result', route: string, issues: VisionIssue[], analysisTime: number, error?: string, requestId?: string }\n * - Server -> Client: { type: 'vision:progress', route: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'vision:status', available: boolean, model?: string, requestId?: string }\n * - Server -> Client: { type: 'config:update', key: string, value: any }\n * - Server -> Client: { type: 'rule:config:result', ruleId: string, severity: string, options?: object, success: boolean, error?: string, requestId?: string }\n * - Server -> Client: { type: 'rule:config:changed', ruleId: string, severity: string, options?: object }\n * - Server -> Client: { type: 'duplicates:indexing:start' }\n * - Server -> Client: { type: 'duplicates:indexing:progress', message: string, current?: number, total?: number }\n * - Server -> Client: { type: 'duplicates:indexing:complete', added: number, modified: number, deleted: number, totalChunks: number, duration: number }\n * - Server -> Client: { type: 'duplicates:indexing:error', error: string }\n * - Server -> Client: { type: 'coverage:setup:start' }\n * - Server -> Client: { type: 'coverage:setup:progress', message: string, phase: string }\n * - Server -> Client: { type: 'coverage:setup:complete', packageAdded: boolean, configModified: boolean, testsRan: boolean, coverageGenerated: boolean, duration: number, error?: string }\n * - Server -> Client: { type: 'coverage:setup:error', error: string }\n * - Client -> Server: { type: 'coverage:request', requestId?: string }\n * - Server -> Client: { type: 'coverage:result', coverage: object, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'coverage:error', error: string, requestId?: string }\n * - Client -> Server: { type: 'source:fetch', filePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:result', filePath: string, content: string, totalLines: number, relativePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:error', filePath: string, error: string, requestId?: string }\n * - Client -> Server: { type: 'screenshot:save', dataUrl: string, route: string, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'screenshot:saved', filename: string, path: string, requestId?: string }\n * - Server -> Client: { type: 'screenshot:error', error: string, requestId?: string }\n */\n\nimport { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSync } from \"fs\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport {\n findWorkspaceRoot,\n getVisionAnalyzer as getCoreVisionAnalyzer,\n} from \"uilint-core/node\";\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport {\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n logInfo,\n logSuccess,\n logWarning,\n logError,\n pc,\n} from \"../utils/prompts.js\";\nimport { ruleRegistry, type RuleOptionSchema } from \"uilint-eslint\";\nimport {\n findEslintConfigFile,\n updateRuleSeverityInConfig,\n updateRuleConfigInConfig,\n readRuleConfigsFromConfig,\n} from \"../utils/eslint-config-inject.js\";\nimport { detectCoverageSetup } from \"../utils/coverage-detect.js\";\nimport {\n prepareCoverage,\n needsCoveragePreparation,\n} from \"../utils/coverage-prepare.js\";\n\nexport interface ServeOptions {\n port?: number;\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\n}\n\n// Message types\ninterface LintFileMessage {\n type: \"lint:file\";\n filePath: string;\n requestId?: string;\n}\n\ninterface LintElementMessage {\n type: \"lint:element\";\n filePath: string;\n dataLoc: string;\n requestId?: string;\n}\n\ninterface SubscribeFileMessage {\n type: \"subscribe:file\";\n filePath: string;\n}\n\ninterface CacheInvalidateMessage {\n type: \"cache:invalidate\";\n filePath?: string;\n}\n\ninterface VisionAnalyzeMessage {\n type: \"vision:analyze\";\n route: string;\n timestamp: number;\n screenshot?: string;\n /** Screenshot filename persisted under `.uilint/screenshots/` (e.g. uilint-...png) */\n screenshotFile?: string;\n manifest: ElementManifest[];\n requestId?: string;\n}\n\ninterface VisionCheckMessage {\n type: \"vision:check\";\n requestId?: string;\n}\n\ninterface ConfigSetMessage {\n type: \"config:set\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigSetMessage {\n type: \"rule:config:set\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n requestId?: string;\n}\n\ninterface SourceFetchMessage {\n type: \"source:fetch\";\n filePath: string;\n requestId?: string;\n}\n\ninterface ScreenshotSaveMessage {\n type: \"screenshot:save\";\n dataUrl: string;\n route: string;\n timestamp: number;\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage\n | VisionCheckMessage\n | ConfigSetMessage\n | RuleConfigSetMessage\n | CoverageRequestMessage\n | SourceFetchMessage\n | ScreenshotSaveMessage;\n\ninterface LintResultMessage {\n type: \"lint:result\";\n filePath: string;\n issues: LintIssue[];\n requestId?: string;\n}\n\ninterface LintProgressMessage {\n type: \"lint:progress\";\n filePath: string;\n phase: string;\n requestId?: string;\n}\n\ninterface FileChangedMessage {\n type: \"file:changed\";\n filePath: string;\n}\n\ninterface WorkspaceInfoMessage {\n type: \"workspace:info\";\n /**\n * Absolute path to the Next.js app project root (dir containing app/ or src/app/).\n * This is the base dir we should use to resolve `data-loc` relative file paths.\n */\n appRoot: string;\n workspaceRoot: string;\n serverCwd: string;\n}\n\ninterface WorkspaceCapabilitiesMessage {\n type: \"workspace:capabilities\";\n postToolUseHook: {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n };\n}\n\ninterface VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: VisionIssue[];\n analysisTime: number;\n error?: string;\n requestId?: string;\n}\n\ninterface VisionProgressMessage {\n type: \"vision:progress\";\n route: string;\n phase: string;\n requestId?: string;\n}\n\ninterface VisionStatusMessage {\n type: \"vision:status\";\n available: boolean;\n model?: string;\n requestId?: string;\n}\n\ninterface RulesMetadataMessage {\n type: \"rules:metadata\";\n rules: Array<{\n id: string;\n name: string;\n description: string;\n category: \"static\" | \"semantic\";\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Current severity from ESLint config (may differ from default) */\n currentSeverity?: \"error\" | \"warn\" | \"off\";\n /** Current options from ESLint config */\n currentOptions?: Record<string, unknown>;\n docs?: string;\n optionSchema?: RuleOptionSchema;\n defaultOptions?: unknown[];\n }>;\n}\n\ninterface ConfigUpdateMessage {\n type: \"config:update\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigResultMessage {\n type: \"rule:config:result\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n success: boolean;\n error?: string;\n requestId?: string;\n}\n\ninterface RuleConfigChangedMessage {\n type: \"rule:config:changed\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n}\n\n// Duplicates indexing messages\ninterface DuplicatesIndexingStartMessage {\n type: \"duplicates:indexing:start\";\n}\n\ninterface DuplicatesIndexingProgressMessage {\n type: \"duplicates:indexing:progress\";\n message: string;\n current?: number;\n total?: number;\n}\n\ninterface DuplicatesIndexingCompleteMessage {\n type: \"duplicates:indexing:complete\";\n added: number;\n modified: number;\n deleted: number;\n totalChunks: number;\n duration: number;\n}\n\ninterface DuplicatesIndexingErrorMessage {\n type: \"duplicates:indexing:error\";\n error: string;\n}\n\n// Coverage heatmap messages\ninterface CoverageRequestMessage {\n type: \"coverage:request\";\n requestId?: string;\n}\n\ninterface CoverageResultMessage {\n type: \"coverage:result\";\n coverage: Record<string, unknown>;\n timestamp: number;\n requestId?: string;\n}\n\ninterface CoverageErrorMessage {\n type: \"coverage:error\";\n error: string;\n requestId?: string;\n}\n\n// Coverage setup messages (existing)\ninterface CoverageSetupStartMessage {\n type: \"coverage:setup:start\";\n}\n\ninterface CoverageSetupProgressMessage {\n type: \"coverage:setup:progress\";\n message: string;\n phase: string;\n}\n\ninterface CoverageSetupCompleteMessage {\n type: \"coverage:setup:complete\";\n packageAdded: boolean;\n configModified: boolean;\n testsRan: boolean;\n coverageGenerated: boolean;\n duration: number;\n error?: string;\n}\n\ninterface CoverageSetupErrorMessage {\n type: \"coverage:setup:error\";\n error: string;\n}\n\ninterface SourceResultMessage {\n type: \"source:result\";\n filePath: string;\n content: string;\n totalLines: number;\n relativePath: string;\n requestId?: string;\n}\n\ninterface SourceErrorMessage {\n type: \"source:error\";\n filePath: string;\n error: string;\n requestId?: string;\n}\n\ninterface ScreenshotSavedMessage {\n type: \"screenshot:saved\";\n filename: string;\n path: string;\n requestId?: string;\n}\n\ninterface ScreenshotErrorMessage {\n type: \"screenshot:error\";\n error: string;\n requestId?: string;\n}\n\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | WorkspaceCapabilitiesMessage\n | VisionResultMessage\n | VisionProgressMessage\n | VisionStatusMessage\n | RulesMetadataMessage\n | ConfigUpdateMessage\n | RuleConfigResultMessage\n | RuleConfigChangedMessage\n | DuplicatesIndexingStartMessage\n | DuplicatesIndexingProgressMessage\n | DuplicatesIndexingCompleteMessage\n | DuplicatesIndexingErrorMessage\n | CoverageResultMessage\n | CoverageErrorMessage\n | CoverageSetupStartMessage\n | CoverageSetupProgressMessage\n | CoverageSetupCompleteMessage\n | CoverageSetupErrorMessage\n | SourceResultMessage\n | SourceErrorMessage\n | ScreenshotSavedMessage\n | ScreenshotErrorMessage;\n\nfunction pickAppRoot(params: { cwd: string; workspaceRoot: string }): string {\n const { cwd, workspaceRoot } = params;\n\n // If started from a Next.js app root (app/ or src/app/ exists), use cwd.\n if (detectNextAppRouter(cwd)) return cwd;\n\n // Otherwise, try to discover Next apps from the workspace root.\n const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });\n if (matches.length === 0) return cwd;\n if (matches.length === 1) return matches[0]!.projectPath;\n\n // Prefer a project that contains the current cwd (common in monorepos).\n const containing = matches.find(\n (m) => cwd === m.projectPath || cwd.startsWith(m.projectPath + \"/\")\n );\n if (containing) return containing.projectPath;\n\n // Fallback: pick the first match deterministically.\n return matches[0]!.projectPath;\n}\n\n/**\n * Detect if a post-tool-use hook is configured for Claude or Cursor.\n * These hooks can automatically run ESLint when files are edited.\n */\nfunction detectPostToolUseHook(projectRoot: string): {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n} {\n // Check Claude settings.json for PostToolUse hooks\n const claudeSettingsPath = join(projectRoot, \".claude\", \"settings.json\");\n if (existsSync(claudeSettingsPath)) {\n try {\n const content = readFileSync(claudeSettingsPath, \"utf-8\");\n const settings = JSON.parse(content);\n const hooks = settings.hooks?.PostToolUse;\n if (Array.isArray(hooks)) {\n // Check if any hook matches Edit or Write tools\n const hasEditHook = hooks.some((h: { matcher?: string }) =>\n h.matcher?.includes(\"Edit\") || h.matcher?.includes(\"Write\")\n );\n if (hasEditHook) {\n return { enabled: true, provider: \"claude\" };\n }\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check Cursor hooks.json\n const cursorHooksPath = join(projectRoot, \".cursor\", \"hooks.json\");\n if (existsSync(cursorHooksPath)) {\n try {\n const content = readFileSync(cursorHooksPath, \"utf-8\");\n const hooks = JSON.parse(content);\n if (hooks.hooks?.afterFileEdit?.length > 0) {\n return { enabled: true, provider: \"cursor\" };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n return { enabled: false, provider: null };\n}\n\n// Simple in-memory cache\ninterface CacheEntry {\n issues: LintIssue[];\n mtimeMs: number;\n timestamp: number;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// Vision analyzer instance (lazy loaded)\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\n\ntype ElementManifest = {\n id: string;\n text: string;\n dataLoc: string;\n rect: { x: number; y: number; width: number; height: number };\n tagName: string;\n role?: string;\n instanceCount?: number;\n};\n\nlet visionAnalyzer: ReturnType<typeof getCoreVisionAnalyzer> | null = null;\n\nfunction getVisionAnalyzerInstance(): ReturnType<typeof getCoreVisionAnalyzer> {\n if (!visionAnalyzer) {\n visionAnalyzer = getCoreVisionAnalyzer();\n }\n return visionAnalyzer;\n}\n\n// Default styleguide search root for vision analysis (set when `serve()` starts)\nlet serverAppRootForVision = process.cwd();\n\nfunction isValidScreenshotFilename(filename: string): boolean {\n // Only allow alphanumeric, hyphens, underscores, and dots; must end with a safe image extension.\n const validPattern = /^[a-zA-Z0-9_-]+\\.(png|jpeg|jpg)$/;\n return validPattern.test(filename) && !filename.includes(\"..\");\n}\n\n// Cache resolved paths for incoming filePath strings\nconst resolvedPathCache = new Map<string, string>();\n\n// File subscriptions: absolutePath -> Set of clients (and the original client filePath string)\nconst subscriptions = new Map<\n string,\n Set<{ ws: WebSocket; clientFilePath: string }>\n>();\n\n// File watcher\nlet fileWatcher: FSWatcher | null = null;\n\n// Basic client tracking for CLI feedback\nlet connectedClients = 0;\n\n// Local require (from uilint deps) for TSX parsing\nconst localRequire = createRequire(import.meta.url);\n\ntype JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\nfunction buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\nfunction offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\nfunction buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => any;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement;\n const loc = opening?.loc?.start;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = (node as any)[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\") {\n walk(child);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make “smallest containing span” selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\nfunction mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nconst ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nfunction findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\nfunction normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nfunction normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\nfunction resolveRequestedFilePath(filePath: string): string {\n // Absolute (POSIX) or Windows drive path\n if (filePath.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(filePath)) {\n return resolve(filePath);\n }\n\n const cached = resolvedPathCache.get(filePath);\n if (cached) return cached;\n\n const cwd = process.cwd();\n const fromCwd = resolve(cwd, filePath);\n if (existsSync(fromCwd)) {\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n }\n\n const wsRoot = findWorkspaceRoot(cwd);\n const fromWs = resolve(wsRoot, filePath);\n if (existsSync(fromWs)) {\n resolvedPathCache.set(filePath, fromWs);\n return fromWs;\n }\n\n // Monorepo helper: try common workspace folders (apps/*, packages/*)\n // Example: filePath=\"app/page.tsx\" -> apps/test-app/app/page.tsx\n for (const top of [\"apps\", \"packages\"]) {\n const base = join(wsRoot, top);\n if (!existsSync(base)) continue;\n try {\n const entries = readdirSync(base, { withFileTypes: true });\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const p = resolve(base, ent.name, filePath);\n if (existsSync(p)) {\n resolvedPathCache.set(filePath, p);\n return p;\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Cache deterministic fallback so repeated requests don't thrash\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n}\n\nasync function getESLintForProject(projectCwd: string): Promise<any | null> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached as any;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = req(\"eslint\");\n const ESLintCtor =\n mod?.ESLint ?? mod?.default?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const eslint = new ESLintCtor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Lint a file and return issues\n */\nasync function lintFile(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Check if file exists\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check cache (mtime-based)\n const cached = cache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(\n projectCwd\n )} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await eslint.lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n\n try {\n onProgress(\"Building JSX map...\");\n const code = readFileSync(absolutePath, \"utf-8\");\n codeLength = code.length;\n lineStarts = buildLineStarts(code);\n spans = buildJsxElementSpans(code, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n // If parsing fails, we still return ESLint messages (unmapped).\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n console.error(\"[uilint-serve] JSX map failed:\", e);\n spans = [];\n lineStarts = [];\n codeLength = 0;\n }\n\n const issues: LintIssue[] = messages\n .filter((m: any) => typeof m?.message === \"string\")\n .map((m: any) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n console.error(\"[uilint-serve] ESLint failed:\", error);\n return [];\n }\n}\n\n/**\n * Send message to client\n */\nfunction sendMessage(ws: WebSocket, message: ServerMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n}\n\n/**\n * Handle incoming client message\n */\nasync function handleMessage(ws: WebSocket, data: string): Promise<void> {\n let message: ClientMessage;\n try {\n message = JSON.parse(data) as ClientMessage;\n } catch {\n return;\n }\n\n // Server-side tracing to confirm activity\n if (message.type === \"lint:file\" || message.type === \"lint:element\") {\n const fp = (message as any).filePath as string | undefined;\n const rid = (message as any).requestId as string | undefined;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(message.type)} ${pc.dim(fp ?? \"\")}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n } else if (message.type === \"subscribe:file\") {\n logInfo(`${pc.dim(\"[ws]\")} subscribe:file ${pc.dim(message.filePath)}`);\n } else if (message.type === \"cache:invalidate\") {\n logInfo(\n `${pc.dim(\"[ws]\")} cache:invalidate ${pc.dim(\n message.filePath ?? \"(all)\"\n )}`\n );\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\n } else if (message.type === \"vision:check\") {\n // Logged in handler\n } else if (message.type === \"config:set\") {\n // Logged in handler\n } else if (message.type === \"screenshot:save\") {\n const rid = (message as ScreenshotSaveMessage).requestId;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"screenshot:save\")} ${pc.dim(message.route)}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n }\n\n switch (message.type) {\n case \"lint:file\": {\n const { filePath, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const resolved = resolveRequestedFilePath(filePath);\n if (!existsSync(resolved)) {\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n logWarning(\n [\n `${pc.dim(\"[ws]\")} File not found for request`,\n ` filePath: ${pc.dim(filePath)}`,\n ` resolved: ${pc.dim(resolved)}`,\n ` cwd: ${pc.dim(cwd)}`,\n ` wsRoot: ${pc.dim(wsRoot)}`,\n ` hint: In monorepos, ensure paths like ${pc.dim(\n \"app/page.tsx\"\n )} exist under ${pc.dim(\"apps/*/\")} or use absolute paths.`,\n ].join(\"\\n\")\n );\n }\n\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} lint:file done ${pc.dim(filePath)} → ${pc.bold(\n `${issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${issues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues });\n break;\n }\n\n case \"lint:element\": {\n const { filePath, dataLoc, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n // Filter to only issues matching the dataLoc\n const filteredIssues = issues.filter(\n (issue) => issue.dataLoc === dataLoc\n );\n\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${filteredIssues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: filteredIssues,\n });\n break;\n }\n\n case \"subscribe:file\": {\n const { filePath } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Add to subscriptions\n let subscribers = subscriptions.get(absolutePath);\n if (!subscribers) {\n subscribers = new Set();\n subscriptions.set(absolutePath, subscribers);\n\n // Start watching this file\n if (fileWatcher) {\n fileWatcher.add(absolutePath);\n }\n }\n subscribers.add({ ws, clientFilePath: filePath });\n break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n } else {\n cache.clear();\n }\n break;\n }\n\n case \"vision:analyze\": {\n const {\n route,\n timestamp,\n screenshot,\n screenshotFile,\n manifest,\n requestId,\n } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:analyze\")} ${pc.dim(route)}${\n requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"\n }`\n );\n\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase: \"Starting vision analysis...\",\n });\n\n const startedAt = Date.now();\n const analyzer = getVisionAnalyzerInstance();\n\n try {\n const screenshotBytes =\n typeof screenshot === \"string\" ? Buffer.byteLength(screenshot) : 0;\n const analyzerModel =\n typeof (analyzer as any).getModel === \"function\"\n ? ((analyzer as any).getModel() as string)\n : undefined;\n const analyzerBaseUrl =\n typeof (analyzer as any).getBaseUrl === \"function\"\n ? ((analyzer as any).getBaseUrl() as string)\n : undefined;\n logInfo(\n [\n `${pc.dim(\"[ws]\")} ${pc.dim(\"vision\")} details`,\n ` route: ${pc.dim(route)}`,\n ` requestId: ${pc.dim(requestId ?? \"(none)\")}`,\n ` manifest: ${pc.dim(String(manifest.length))} element(s)`,\n ` screenshot: ${pc.dim(\n screenshot ? `${Math.round(screenshotBytes / 1024)}kb` : \"none\"\n )}`,\n ` screenshotFile: ${pc.dim(screenshotFile ?? \"(none)\")}`,\n ` ollamaUrl: ${pc.dim(analyzerBaseUrl ?? \"(default)\")}`,\n ` visionModel: ${pc.dim(analyzerModel ?? \"(default)\")}`,\n ].join(\"\\n\")\n );\n\n if (!screenshot) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: \"No screenshot provided for vision analysis\",\n requestId,\n });\n break;\n }\n\n const result = await runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n // In the overlay/server context, default to upward search from app root.\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer: analyzer as any,\n onPhase: (phase) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n },\n });\n\n // Write a markdown report alongside the saved screenshot (best-effort).\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (!isValidScreenshotFilename(screenshotFile)) {\n logWarning(\n `Skipping vision report write: invalid screenshotFile ${pc.dim(\n screenshotFile\n )}`\n );\n } else {\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (!existsSync(imagePath)) {\n logWarning(\n `Skipping vision report write: screenshot file not found ${pc.dim(\n imagePath\n )}`\n );\n } else {\n const report = writeVisionMarkdownReport({\n imagePath,\n route,\n timestamp,\n visionModel: result.visionModel,\n baseUrl: result.baseUrl,\n analysisTimeMs: result.analysisTime,\n prompt: result.prompt ?? null,\n rawResponse: result.rawResponse ?? null,\n metadata: {\n screenshotFile: parse(imagePath).base,\n appRoot: serverAppRootForVision,\n manifestElements: manifest.length,\n requestId: requestId ?? null,\n },\n });\n logInfo(\n `${pc.dim(\"[ws]\")} wrote vision report ${pc.dim(\n report.outPath\n )}`\n );\n }\n } catch (e) {\n logWarning(\n `Failed to write vision report for ${pc.dim(screenshotFile)}: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} vision:analyze done ${pc.dim(route)} → ${pc.bold(\n `${result.issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n if (result.rawResponse) {\n logInfo(\n `${pc.dim(\"[ws]\")} vision rawResponse ${pc.dim(\n `${result.rawResponse.length} chars`\n )}`\n );\n }\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: result.issues,\n analysisTime: result.analysisTime,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? error.stack : undefined;\n logError(\n [\n `Vision analysis failed`,\n ` route: ${route}`,\n ` requestId: ${requestId ?? \"(none)\"}`,\n ` error: ${errorMessage}`,\n stack ? ` stack:\\n${stack}` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n );\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"vision:check\": {\n const { requestId } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:check\")}${requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"}`\n );\n\n try {\n const analyzer = getVisionAnalyzerInstance();\n const model =\n typeof (analyzer as any).getModel === \"function\"\n ? (analyzer as any).getModel()\n : undefined;\n\n sendMessage(ws, {\n type: \"vision:status\",\n available: true,\n model,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"vision:status\",\n available: false,\n requestId,\n });\n }\n break;\n }\n\n case \"config:set\": {\n const { key, value } = message;\n handleConfigSet(key, value);\n break;\n }\n\n case \"rule:config:set\": {\n const { ruleId, severity, options, requestId } = message;\n handleRuleConfigSet(ws, ruleId, severity, options, requestId);\n break;\n }\n\n case \"source:fetch\": {\n const { filePath, requestId } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: \"File not found\",\n requestId,\n });\n break;\n }\n\n try {\n const content = readFileSync(absolutePath, \"utf-8\");\n const totalLines = content.split(\"\\n\").length;\n const relativePath = normalizeDataLocFilePath(absolutePath, serverAppRootForVision);\n\n sendMessage(ws, {\n type: \"source:result\",\n filePath,\n content,\n totalLines,\n relativePath,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: error instanceof Error ? error.message : \"Failed to read file\",\n requestId,\n });\n }\n break;\n }\n\n case \"coverage:request\": {\n const { requestId } = message;\n try {\n const coveragePath = join(serverAppRootForVision, \"coverage\", \"coverage-final.json\");\n\n if (!existsSync(coveragePath)) {\n sendMessage(ws, {\n type: \"coverage:error\",\n error: \"Coverage data not found. Run tests with coverage first (e.g., `vitest run --coverage`)\",\n requestId,\n });\n break;\n }\n\n const coverageData = JSON.parse(readFileSync(coveragePath, \"utf-8\"));\n logInfo(`${pc.dim(\"[ws]\")} coverage:result ${pc.dim(`${Object.keys(coverageData).length} files`)}`);\n\n sendMessage(ws, {\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n requestId,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} coverage:error ${errorMessage}`);\n sendMessage(ws, {\n type: \"coverage:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"screenshot:save\": {\n const { dataUrl, route, timestamp, requestId } = message;\n\n try {\n // Validate the dataUrl is a valid base64 PNG data URL\n if (!dataUrl || typeof dataUrl !== \"string\") {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a non-empty string\",\n requestId,\n });\n break;\n }\n\n const dataUrlPattern = /^data:image\\/png;base64,/;\n if (!dataUrlPattern.test(dataUrl)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a base64 PNG data URL (data:image/png;base64,...)\",\n requestId,\n });\n break;\n }\n\n // Extract base64 data\n const base64Data = dataUrl.replace(dataUrlPattern, \"\");\n\n // Sanitize route for filename (replace / with -, remove special chars)\n const sanitizedRoute = route\n .replace(/^\\//, \"\") // Remove leading slash\n .replace(/\\//g, \"-\") // Replace slashes with dashes\n .replace(/[^a-zA-Z0-9_-]/g, \"_\") // Replace special chars with underscore\n || \"root\"; // Default to \"root\" for empty route\n\n // Generate filename\n const filename = `uilint-${timestamp}-${sanitizedRoute}.png`;\n\n // Validate generated filename\n if (!isValidScreenshotFilename(filename)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: `Generated filename is invalid: ${filename}`,\n requestId,\n });\n break;\n }\n\n // Create screenshots directory if needed\n const screenshotsDir = join(serverAppRootForVision, \".uilint\", \"screenshots\");\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n // Write the image file\n const imagePath = join(screenshotsDir, filename);\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n writeFileSync(imagePath, imageBuffer);\n\n // Write JSON sidecar with metadata\n const sidecarFilename = filename.replace(/\\.png$/, \".json\");\n const sidecarPath = join(screenshotsDir, sidecarFilename);\n const sidecarData = {\n route,\n timestamp,\n filename,\n savedAt: new Date().toISOString(),\n };\n writeFileSync(sidecarPath, JSON.stringify(sidecarData, null, 2));\n\n logInfo(\n `${pc.dim(\"[ws]\")} screenshot:saved ${pc.dim(filename)} ${pc.dim(\n `(${Math.round(imageBuffer.length / 1024)}kb)`\n )}`\n );\n\n // Send success response\n sendMessage(ws, {\n type: \"screenshot:saved\",\n filename,\n path: imagePath,\n requestId,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} screenshot:error ${errorMessage}`);\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n }\n}\n\n/**\n * Handle client disconnect\n */\nfunction handleDisconnect(ws: WebSocket): void {\n // Remove from all subscriptions\n for (const [filePath, subscribers] of subscriptions.entries()) {\n for (const entry of subscribers) {\n if (entry.ws === ws) {\n subscribers.delete(entry);\n }\n }\n if (subscribers.size === 0) {\n subscriptions.delete(filePath);\n // Stop watching if no subscribers\n if (fileWatcher) {\n fileWatcher.unwatch(filePath);\n }\n }\n }\n}\n\n/**\n * Handle file change\n */\nfunction handleFileChange(filePath: string): void {\n const subscribers = subscriptions.get(filePath);\n if (!subscribers || subscribers.size === 0) return;\n\n // Invalidate cache\n cache.delete(filePath);\n\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Handle coverage-final.json file change - broadcast new coverage data to all clients\n */\nfunction handleCoverageFileChange(filePath: string): void {\n try {\n const coverageData = JSON.parse(readFileSync(filePath, \"utf-8\"));\n logInfo(`${pc.dim(\"[ws]\")} coverage:changed ${pc.dim(`${Object.keys(coverageData).length} files`)}`);\n\n broadcast({\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} Failed to read coverage data: ${errorMessage}`);\n broadcast({\n type: \"coverage:error\",\n error: `Failed to read coverage: ${errorMessage}`,\n });\n }\n}\n\n// In-memory config store (runtime only, for broadcasting to clients)\nconst configStore = new Map<string, unknown>();\n\n// Track connected clients for broadcasting\nlet connectedClientsSet = new Set<WebSocket>();\n\n/**\n * Broadcast config update to all connected clients\n */\nfunction broadcastConfigUpdate(key: string, value: unknown): void {\n const message: ConfigUpdateMessage = { type: \"config:update\", key, value };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Handle config:set message\n */\nfunction handleConfigSet(key: string, value: unknown): void {\n configStore.set(key, value);\n logInfo(`${pc.dim(\"[ws]\")} config:set ${pc.bold(key)} = ${pc.dim(JSON.stringify(value))}`);\n broadcastConfigUpdate(key, value);\n}\n\n/**\n * Broadcast rule config change to all connected clients\n */\nfunction broadcastRuleConfigChange(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): void {\n const message: RuleConfigChangedMessage = {\n type: \"rule:config:changed\",\n ruleId,\n severity,\n options,\n };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Broadcast a message to all connected clients\n */\nfunction broadcast(message: ServerMessage): void {\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n// Duplicates indexing state\nlet isIndexing = false;\nlet reindexTimeout: NodeJS.Timeout | null = null;\nconst pendingIndexChanges = new Set<string>();\n\n/**\n * Build or update the duplicates index\n * Runs incrementally - very fast if no files changed\n */\nasync function buildDuplicatesIndex(appRoot: string): Promise<void> {\n if (isIndexing) {\n // Already indexing, skip\n return;\n }\n\n isIndexing = true;\n logInfo(`${pc.blue(\"Building duplicates index...\")}`);\n broadcast({ type: \"duplicates:indexing:start\" });\n\n try {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n const result = await indexDirectory(appRoot, {\n onProgress: (message, current, total) => {\n // Log to console\n if (current !== undefined && total !== undefined) {\n logInfo(` ${message} (${current}/${total})`);\n } else {\n logInfo(` ${message}`);\n }\n // Broadcast to connected clients\n broadcast({\n type: \"duplicates:indexing:progress\",\n message,\n current,\n total,\n });\n },\n });\n\n logSuccess(\n `${pc.green(\"Index complete:\")} ${result.totalChunks} chunks (${result.added} added, ${result.modified} modified, ${result.deleted} deleted) in ${(result.duration / 1000).toFixed(1)}s`\n );\n broadcast({\n type: \"duplicates:indexing:complete\",\n added: result.added,\n modified: result.modified,\n deleted: result.deleted,\n totalChunks: result.totalChunks,\n duration: result.duration,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logError(`Index failed: ${msg}`);\n broadcast({ type: \"duplicates:indexing:error\", error: msg });\n } finally {\n isIndexing = false;\n }\n}\n\n/**\n * Schedule a debounced re-index when source files change\n */\nfunction scheduleReindex(appRoot: string, filePath: string): void {\n // Only reindex for source files\n if (!/\\.(tsx?|jsx?)$/.test(filePath)) return;\n\n pendingIndexChanges.add(filePath);\n\n if (reindexTimeout) clearTimeout(reindexTimeout);\n reindexTimeout = setTimeout(async () => {\n const count = pendingIndexChanges.size;\n pendingIndexChanges.clear();\n logInfo(`${pc.dim(`[index] ${count} file(s) changed, updating index...`)}`);\n await buildDuplicatesIndex(appRoot);\n }, 2000); // 2 second debounce\n}\n\n// Coverage preparation state\nlet isPreparingCoverage = false;\n\n/**\n * Check if require-test-coverage rule is enabled in ESLint config\n */\nfunction isCoverageRuleEnabled(appRoot: string): boolean {\n const eslintConfigPath = findEslintConfigFile(appRoot);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const coverageConfig = ruleConfigs.get(\"require-test-coverage\");\n if (!coverageConfig) return false;\n\n // Rule is enabled if severity is not \"off\"\n return coverageConfig.severity !== \"off\";\n}\n\n/**\n * Prepare coverage data for require-test-coverage rule.\n * Runs only on startup:\n * - Installs @vitest/coverage-v8 if missing\n * - Adds coverage config to vitest.config.ts if missing\n * - Runs tests with coverage to generate coverage-final.json\n */\nasync function buildCoverageData(appRoot: string): Promise<void> {\n if (isPreparingCoverage) return;\n\n isPreparingCoverage = true;\n\n try {\n // Check if coverage rule is enabled\n if (!isCoverageRuleEnabled(appRoot)) {\n logInfo(`${pc.dim(\"Coverage rule not enabled, skipping preparation\")}`);\n return;\n }\n\n // Detect current setup\n const setup = detectCoverageSetup(appRoot);\n\n // Check if preparation needed\n if (!needsCoveragePreparation(setup)) {\n logInfo(`${pc.dim(\"Coverage data is up-to-date\")}`);\n return;\n }\n\n // Run preparation\n logInfo(`${pc.blue(\"Preparing coverage data...\")}`);\n broadcast({ type: \"coverage:setup:start\" });\n\n // Check environment variables for skipping\n const skipPackageInstall = process.env.UILINT_SKIP_COVERAGE_INSTALL === \"1\";\n const skipTests = process.env.UILINT_SKIP_COVERAGE_TESTS === \"1\";\n\n const result = await prepareCoverage({\n appRoot,\n skipPackageInstall,\n skipTests,\n onProgress: (message, phase) => {\n logInfo(` ${message}`);\n broadcast({ type: \"coverage:setup:progress\", message, phase });\n },\n });\n\n if (result.error) {\n // Continue with warning on test failures (don't block server startup)\n logWarning(`Coverage preparation completed with errors: ${result.error}`);\n } else {\n const parts = [];\n if (result.packageAdded) parts.push(\"package installed\");\n if (result.configModified) parts.push(\"config modified\");\n if (result.testsRan) parts.push(\"tests ran\");\n if (result.coverageGenerated) parts.push(\"coverage generated\");\n\n logSuccess(\n `${pc.green(\"Coverage prepared:\")} ${parts.join(\", \")} in ${(result.duration / 1000).toFixed(1)}s`\n );\n }\n\n broadcast({\n type: \"coverage:setup:complete\",\n ...result,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logError(`Coverage preparation failed: ${msg}`);\n broadcast({ type: \"coverage:setup:error\", error: msg });\n } finally {\n isPreparingCoverage = false;\n }\n}\n\n/**\n * Handle rule:config:set message\n * Updates the ESLint config file and broadcasts the change to all clients\n */\nfunction handleRuleConfigSet(\n ws: WebSocket,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n requestId?: string\n): void {\n logInfo(\n `${pc.dim(\"[ws]\")} rule:config:set ${pc.bold(ruleId)} -> ${pc.dim(severity)}${\n options ? ` with options` : \"\"\n }`\n );\n\n // Find the ESLint config file\n const configPath = findEslintConfigFile(serverAppRootForVision);\n if (!configPath) {\n const error = `No ESLint config file found in ${serverAppRootForVision}`;\n logError(`${pc.dim(\"[ws]\")} ${error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error,\n requestId,\n });\n return;\n }\n\n // Update the config file\n let result;\n if (options && Object.keys(options).length > 0) {\n // Update severity AND options\n result = updateRuleConfigInConfig(configPath, ruleId, severity, options);\n } else {\n // Update severity only\n result = updateRuleSeverityInConfig(configPath, ruleId, severity);\n }\n\n if (result.success) {\n logSuccess(\n `${pc.dim(\"[ws]\")} Updated ${pc.bold(`uilint/${ruleId}`)} -> ${pc.dim(severity)}`\n );\n\n // Clear ESLint instance cache to pick up the new config\n eslintInstances.clear();\n cache.clear();\n\n // Send success response to requesting client\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: true,\n requestId,\n });\n\n // Broadcast change to all connected clients\n broadcastRuleConfigChange(ruleId, severity, options);\n } else {\n logError(`${pc.dim(\"[ws]\")} Failed to update rule: ${result.error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error: result.error,\n requestId,\n });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const port = options.port || 9234;\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n logInfo(`Workspace root: ${pc.dim(wsRoot)}`);\n logInfo(`App root: ${pc.dim(appRoot)}`);\n logInfo(`Server cwd: ${pc.dim(cwd)}`);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n const resolvedPath = resolve(path);\n\n // Check if coverage-final.json changed - broadcast to all clients\n if (resolvedPath.endsWith(\"coverage-final.json\")) {\n handleCoverageFileChange(resolvedPath);\n return;\n }\n\n handleFileChange(resolvedPath);\n // Also schedule re-indexing for duplicates detection\n scheduleReindex(appRoot, resolvedPath);\n });\n\n // Watch coverage-final.json for changes\n const coveragePath = join(appRoot, \"coverage\", \"coverage-final.json\");\n if (existsSync(coveragePath)) {\n fileWatcher.add(coveragePath);\n logInfo(`Watching coverage: ${pc.dim(coveragePath)}`);\n }\n\n // Create WebSocket server\n const wss = new WebSocketServer({ port });\n\n // Start building the duplicates index in the background\n // This runs incrementally - very fast if nothing changed\n buildDuplicatesIndex(appRoot).catch((err) => {\n logError(`Failed to build duplicates index: ${err.message}`);\n });\n\n // Prepare coverage data for require-test-coverage rule (startup only)\n // This installs packages, modifies config, and runs tests if needed\n buildCoverageData(appRoot).catch((err) => {\n // Don't block server startup on coverage failures\n logWarning(`Failed to prepare coverage: ${err.message}`);\n });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n connectedClientsSet.add(ws);\n logInfo(`Client connected (${connectedClients} total)`);\n\n // Send workspace info to client on connect\n sendMessage(ws, {\n type: \"workspace:info\",\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n });\n\n // Send workspace capabilities (hook availability, etc.)\n const hookInfo = detectPostToolUseHook(appRoot);\n sendMessage(ws, {\n type: \"workspace:capabilities\",\n postToolUseHook: hookInfo,\n });\n if (hookInfo.enabled) {\n logInfo(`${pc.dim(\"[ws]\")} Post-tool-use hook detected: ${pc.bold(hookInfo.provider!)}`);\n }\n\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<string, { severity: \"error\" | \"warn\" | \"off\"; options?: Record<string, unknown> }>();\n\n // Send installed rules metadata (only rules that exist in the ESLint config)\n // Include current severities from the ESLint config so UI reflects saved state\n sendMessage(ws, {\n type: \"rules:metadata\",\n rules: ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: rule.id,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n currentOptions: currentConfig?.options,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n defaultOptions: rule.defaultOptions,\n };\n }),\n });\n\n // Send current config state to new client\n for (const [key, value] of configStore) {\n sendMessage(ws, { type: \"config:update\", key, value });\n }\n\n ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n connectedClientsSet.delete(ws);\n logInfo(`Client disconnected (${connectedClients} total)`);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logError(`WebSocket error: ${error.message}`);\n });\n });\n\n wss.on(\"error\", (error) => {\n logError(`Server error: ${error.message}`);\n });\n\n logSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n logInfo(\"Press Ctrl+C to stop\");\n\n // Keep the server running\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n wss.close();\n fileWatcher?.close();\n resolve();\n });\n });\n}\n","import { dirname, join, parse } from \"path\";\nimport { existsSync, statSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n ensureOllamaReady,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n readStyleGuide,\n VisionAnalyzer,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n type VisionAnalysisResult,\n type StreamProgressCallback,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport type ResolveVisionStyleGuideArgs = {\n /** Project root / cwd used to resolve relative path specifiers */\n projectPath: string;\n /** Path to style guide file OR project directory */\n styleguide?: string;\n /** A starting point for upward search (directory). Defaults to projectPath. */\n startDir?: string;\n};\n\nexport type ResolveVisionStyleGuideResult = {\n styleGuide: string | null;\n styleguideLocation: string | null;\n};\n\nexport async function resolveVisionStyleGuide(\n args: ResolveVisionStyleGuideArgs\n): Promise<ResolveVisionStyleGuideResult> {\n const projectPath = args.projectPath;\n const startDir = args.startDir ?? projectPath;\n\n if (args.styleguide) {\n const styleguideArg = resolvePathSpecifier(args.styleguide, projectPath);\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n return {\n styleguideLocation: styleguideArg,\n styleGuide: await readStyleGuide(styleguideArg),\n };\n }\n if (stat.isDirectory()) {\n const found = findStyleGuidePath(styleguideArg);\n return {\n styleguideLocation: found,\n styleGuide: found ? await readStyleGuide(found) : null,\n };\n }\n }\n return { styleGuide: null, styleguideLocation: null };\n }\n\n const upwards = findUILintStyleGuideUpwards(startDir);\n const fallback = upwards ?? findStyleGuidePath(projectPath);\n return {\n styleguideLocation: fallback,\n styleGuide: fallback ? await readStyleGuide(fallback) : null,\n };\n}\n\nexport type RunVisionAnalysisArgs = {\n /** base64 image data (NO data: prefix) */\n imageBase64: string;\n manifest: ElementManifest[];\n /** Used to resolve styleguide arg and as default search root */\n projectPath: string;\n /** Path to style guide file OR directory; if omitted uses upward search */\n styleguide?: string;\n /** Directory for upward styleguide search; defaults to projectPath */\n styleguideStartDir?: string;\n /**\n * Override resolved styleguide content (lets callers do logging/notes based on resolution once).\n * If provided (even null), styleguide resolution is skipped.\n */\n styleGuide?: string | null;\n /**\n * Override resolved styleguide location (pairs with styleGuide override).\n * If provided, this is returned in the result.\n */\n styleguideLocation?: string | null;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /**\n * Optional analyzer instance (lets servers reuse a singleton and lets tests inject a mock).\n * If omitted, a new `VisionAnalyzer` is created with baseUrl+model.\n */\n analyzer?: Pick<VisionAnalyzer, \"analyzeScreenshot\">;\n /** Optional streaming progress callback passed into the analyzer */\n onProgress?: StreamProgressCallback;\n /** Optional coarse-grained phase callback (good for spinners / WS progress) */\n onPhase?: (phase: string) => void;\n /** When true, skip calling `ensureOllamaReady` (caller is responsible). */\n skipEnsureOllama?: boolean;\n /** Optional debug dump destination (file path or directory) */\n debugDump?: string;\n /** When true, include base64 image and full styleguide in debug dump */\n debugDumpIncludeSensitive?: boolean;\n /** Optional extra metadata to include in debug dumps */\n debugDumpMetadata?: Record<string, unknown>;\n};\n\nexport type RunVisionAnalysisResult = {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n styleguideLocation: string | null;\n visionModel: string;\n baseUrl: string;\n};\n\nconst ollamaReadyOnce = new Map<string, Promise<void>>();\n\nasync function ensureOllamaReadyCached(params: {\n model: string;\n baseUrl: string;\n}): Promise<void> {\n const key = `${params.baseUrl}::${params.model}`;\n const existing = ollamaReadyOnce.get(key);\n if (existing) return existing;\n\n const p = ensureOllamaReady({ model: params.model, baseUrl: params.baseUrl })\n .then(() => undefined)\n .catch((e) => {\n // If startup/pull fails, allow retry on next request.\n ollamaReadyOnce.delete(key);\n throw e;\n });\n ollamaReadyOnce.set(key, p);\n return p;\n}\n\nfunction writeVisionDebugDump(params: {\n dumpPath: string;\n now: Date;\n inputs: {\n imageBase64: string;\n manifest: ElementManifest[];\n styleguideLocation: string | null;\n styleGuide: string | null;\n };\n runtime: { visionModel: string; baseUrl: string };\n includeSensitive: boolean;\n metadata?: Record<string, unknown>;\n}): string {\n const resolvedDirOrFile = resolvePathSpecifier(\n params.dumpPath,\n process.cwd()\n );\n const safeStamp = params.now.toISOString().replace(/[:.]/g, \"-\");\n const dumpFile =\n resolvedDirOrFile.endsWith(\".json\") || resolvedDirOrFile.endsWith(\".jsonl\")\n ? resolvedDirOrFile\n : `${resolvedDirOrFile}/vision-debug-${safeStamp}.json`;\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: params.now.toISOString(),\n runtime: params.runtime,\n metadata: params.metadata ?? null,\n inputs: {\n imageBase64: params.includeSensitive\n ? params.inputs.imageBase64\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n manifest: params.inputs.manifest,\n styleguideLocation: params.inputs.styleguideLocation,\n styleGuide: params.includeSensitive\n ? params.inputs.styleGuide\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n\n return dumpFile;\n}\n\nexport async function runVisionAnalysis(\n args: RunVisionAnalysisArgs\n): Promise<RunVisionAnalysisResult> {\n const visionModel = args.model || UILINT_DEFAULT_VISION_MODEL;\n const baseUrl = args.baseUrl ?? \"http://localhost:11434\";\n\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n\n if (args.styleGuide !== undefined) {\n styleGuide = args.styleGuide;\n styleguideLocation = args.styleguideLocation ?? null;\n } else {\n args.onPhase?.(\"Resolving styleguide...\");\n const resolved = await resolveVisionStyleGuide({\n projectPath: args.projectPath,\n styleguide: args.styleguide,\n startDir: args.styleguideStartDir,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (!args.skipEnsureOllama) {\n args.onPhase?.(\"Preparing Ollama...\");\n await ensureOllamaReadyCached({ model: visionModel, baseUrl });\n }\n\n if (args.debugDump) {\n writeVisionDebugDump({\n dumpPath: args.debugDump,\n now: new Date(),\n runtime: { visionModel, baseUrl },\n inputs: {\n imageBase64: args.imageBase64,\n manifest: args.manifest,\n styleguideLocation,\n styleGuide,\n },\n includeSensitive: Boolean(args.debugDumpIncludeSensitive),\n metadata: args.debugDumpMetadata,\n });\n }\n\n const analyzer =\n args.analyzer ??\n new VisionAnalyzer({\n baseUrl: args.baseUrl,\n visionModel,\n });\n\n args.onPhase?.(`Analyzing ${args.manifest.length} elements...`);\n const result: VisionAnalysisResult = await analyzer.analyzeScreenshot(\n args.imageBase64,\n args.manifest,\n {\n styleGuide,\n onProgress: args.onProgress,\n }\n );\n\n args.onPhase?.(\n `Done (${result.issues.length} issues, ${result.analysisTime}ms)`\n );\n\n return {\n issues: result.issues,\n analysisTime: result.analysisTime,\n // Prompt is available in newer uilint-core versions; keep this resilient across versions.\n prompt: (result as any).prompt,\n rawResponse: result.rawResponse,\n styleguideLocation,\n visionModel,\n baseUrl,\n };\n}\n\nexport type WriteVisionMarkdownReportArgs = {\n /** Absolute path to the source image file */\n imagePath: string;\n /** Route label (optional; included in report) */\n route?: string;\n /** Unix ms timestamp (optional; included in report) */\n timestamp?: number;\n visionModel?: string;\n baseUrl?: string;\n analysisTimeMs?: number;\n prompt?: string | null;\n rawResponse?: string | null;\n /** Extra JSON-ish metadata to include */\n metadata?: Record<string, unknown>;\n /**\n * Optional output path; if omitted, writes alongside the image:\n * `<basename>.vision.md`\n */\n outPath?: string;\n};\n\nexport function writeVisionMarkdownReport(\n args: WriteVisionMarkdownReportArgs\n): {\n outPath: string;\n content: string;\n} {\n const p = parse(args.imagePath);\n const outPath = args.outPath ?? join(p.dir, `${p.name || p.base}.vision.md`);\n\n const lines: string[] = [];\n lines.push(`# UILint Vision Report`);\n lines.push(``);\n lines.push(`- Image: \\`${p.base}\\``);\n if (args.route) lines.push(`- Route: \\`${args.route}\\``);\n if (typeof args.timestamp === \"number\") {\n lines.push(`- Timestamp: \\`${new Date(args.timestamp).toISOString()}\\``);\n }\n if (args.visionModel) lines.push(`- Model: \\`${args.visionModel}\\``);\n if (args.baseUrl) lines.push(`- Ollama baseUrl: \\`${args.baseUrl}\\``);\n if (typeof args.analysisTimeMs === \"number\")\n lines.push(`- Analysis time: \\`${args.analysisTimeMs}ms\\``);\n lines.push(`- Generated: \\`${new Date().toISOString()}\\``);\n lines.push(``);\n\n if (args.metadata && Object.keys(args.metadata).length > 0) {\n lines.push(`## Metadata`);\n lines.push(``);\n lines.push(\"```json\");\n lines.push(JSON.stringify(args.metadata, null, 2));\n lines.push(\"```\");\n lines.push(``);\n }\n\n lines.push(`## Prompt`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.prompt ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n lines.push(`## Raw Response`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.rawResponse ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n const content = lines.join(\"\\n\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, \"utf-8\");\n return { outPath, content };\n}\n","/**\n * Vision command - analyze a screenshot with Ollama vision models\n *\n * Mirrors the \"scan\" command UX (debug flags, JSON/text output), but operates on images.\n */\n\nimport { dirname, resolve, join } from \"path\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from \"fs\";\nimport {\n ensureOllamaReady,\n STYLEGUIDE_PATHS,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n resolveVisionStyleGuide,\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n intro,\n withSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface VisionOptions {\n /** Path to a screenshot image (png/jpg). */\n image?: string;\n /** Path to a `.json` sidecar containing { manifest, ... } (as saved by the Next screenshot route). */\n sidecar?: string;\n /** Inline manifest JSON string (array). */\n manifestJson?: string;\n /** Path to a manifest JSON file (array). */\n manifestFile?: string;\n /** Explicit route label (used in output and debug dump). */\n route?: string;\n /** Path to style guide file or project dir (same semantics as scan.ts). */\n styleguide?: string;\n /** Output format */\n output?: \"text\" | \"json\";\n /** List available `.uilint/screenshots/*.json` sidecars and exit */\n list?: boolean;\n /** Optional screenshots directory to list from (default: nearest `.uilint/screenshots`) */\n screenshotsDir?: string;\n /** Stream model output/progress (text mode only; JSON output stays non-streaming) */\n stream?: boolean;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /** Enable debug logging (stderr only; never pollutes JSON stdout). Can also be enabled via UILINT_DEBUG=1 */\n debug?: boolean;\n /** Print full prompt/styleguide (can be very large). Can also be enabled via UILINT_DEBUG_FULL=1 */\n debugFull?: boolean;\n /** Dump payload to file. Can also be set via UILINT_DEBUG_DUMP=/path */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: VisionOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: VisionOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: VisionOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nfunction findScreenshotsDirUpwards(startDir: string): string | null {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n const candidate = join(dir, \".uilint\", \"screenshots\");\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\ntype ScreenshotSidecarSummary = {\n path: string;\n filename: string;\n timestamp?: number;\n route?: string;\n issueCount?: number;\n};\n\nfunction listScreenshotSidecars(dirPath: string): ScreenshotSidecarSummary[] {\n if (!existsSync(dirPath)) return [];\n const entries = readdirSync(dirPath)\n .filter((f) => f.endsWith(\".json\"))\n .map((f) => join(dirPath, f));\n\n const out: ScreenshotSidecarSummary[] = [];\n for (const p of entries) {\n try {\n const json = loadJsonFile<any>(p);\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : json?.analysisResult?.issues;\n out.push({\n path: p,\n filename:\n json?.filename || json?.screenshotFile || p.split(\"/\").pop() || p,\n timestamp:\n typeof json?.timestamp === \"number\" ? json.timestamp : undefined,\n route: typeof json?.route === \"string\" ? json.route : undefined,\n issueCount: Array.isArray(issues) ? issues.length : undefined,\n });\n } catch {\n out.push({\n path: p,\n filename: p.split(\"/\").pop() || p,\n });\n }\n }\n\n // Newest first (fallback to filename sort)\n out.sort((a, b) => {\n const at = a.timestamp ?? 0;\n const bt = b.timestamp ?? 0;\n if (at !== bt) return bt - at;\n return b.path.localeCompare(a.path);\n });\n\n return out;\n}\n\nfunction readImageAsBase64(imagePath: string): {\n base64: string;\n sizeBytes: number;\n} {\n const bytes = readFileSync(imagePath);\n return { base64: bytes.toString(\"base64\"), sizeBytes: bytes.byteLength };\n}\n\nfunction loadJsonFile<T>(filePath: string): T {\n const raw = readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nfunction formatIssuesText(issues: VisionIssue[]): string {\n if (issues.length === 0) return \"No vision issues found.\\n\";\n return (\n issues\n .map((i) => {\n const sev = i.severity || \"info\";\n const cat = i.category || \"other\";\n const where = i.dataLoc ? ` (${i.dataLoc})` : \"\";\n return `- [${sev}/${cat}] ${i.message}${where}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n}\n\nexport async function vision(options: VisionOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) intro(\"Vision (Screenshot) Analysis\");\n\n try {\n const projectPath = process.cwd();\n\n // List mode (no analysis)\n if (options.list) {\n const base =\n (options.screenshotsDir\n ? resolvePathSpecifier(options.screenshotsDir, projectPath)\n : null) || findScreenshotsDirUpwards(projectPath);\n\n if (!base) {\n if (isJsonOutput) {\n printJSON({ screenshotsDir: null, sidecars: [] });\n } else {\n logWarning(\n \"No `.uilint/screenshots` directory found (walked up from cwd).\"\n );\n }\n await flushLangfuse();\n return;\n }\n\n const sidecars = listScreenshotSidecars(base);\n if (isJsonOutput) {\n printJSON({ screenshotsDir: base, sidecars });\n } else {\n logInfo(`Screenshots dir: ${pc.dim(base)}`);\n if (sidecars.length === 0) {\n process.stdout.write(\"No sidecars found.\\n\");\n } else {\n process.stdout.write(\n sidecars\n .map((s, idx) => {\n const stamp = s.timestamp\n ? new Date(s.timestamp).toLocaleString()\n : \"(no timestamp)\";\n const route = s.route ? ` ${pc.dim(s.route)}` : \"\";\n const count =\n typeof s.issueCount === \"number\"\n ? ` ${pc.dim(`(${s.issueCount} issues)`)}`\n : \"\";\n return `${idx === 0 ? \"*\" : \"-\"} ${s.path}${pc.dim(\n ` — ${stamp}`\n )}${route}${count}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n process.stdout.write(\n pc.dim(\n `Tip: run \\`uilint vision --sidecar <path>\\` (the newest is marked with \"*\").\\n`\n )\n );\n }\n }\n await flushLangfuse();\n return;\n }\n\n // Resolve inputs\n const imagePath = options.image\n ? resolvePathSpecifier(options.image, projectPath)\n : undefined;\n const sidecarPath = options.sidecar\n ? resolvePathSpecifier(options.sidecar, projectPath)\n : undefined;\n const manifestFilePath = options.manifestFile\n ? resolvePathSpecifier(options.manifestFile, projectPath)\n : undefined;\n\n if (!imagePath && !sidecarPath) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --image or --sidecar.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n if (imagePath && !existsSync(imagePath)) {\n throw new Error(`Image not found: ${imagePath}`);\n }\n if (sidecarPath && !existsSync(sidecarPath)) {\n throw new Error(`Sidecar not found: ${sidecarPath}`);\n }\n if (manifestFilePath && !existsSync(manifestFilePath)) {\n throw new Error(`Manifest file not found: ${manifestFilePath}`);\n }\n\n // Load sidecar if provided (supports the Next screenshot route payload)\n const sidecar = sidecarPath\n ? loadJsonFile<{\n filename?: string;\n screenshotFile?: string;\n route?: string;\n manifest?: unknown;\n analysisResult?: unknown;\n issues?: unknown;\n }>(sidecarPath)\n : null;\n\n const routeLabel =\n options.route ||\n (typeof sidecar?.route === \"string\" ? sidecar.route : undefined) ||\n (sidecarPath ? `(from ${sidecarPath})` : \"(unknown)\");\n\n // Manifest sources (priority: --manifest-json > --manifest-file > sidecar.manifest)\n let manifest: ElementManifest[] | null = null;\n if (options.manifestJson) {\n manifest = JSON.parse(options.manifestJson) as ElementManifest[];\n } else if (manifestFilePath) {\n manifest = loadJsonFile<ElementManifest[]>(manifestFilePath);\n } else if (sidecar && Array.isArray(sidecar.manifest)) {\n manifest = sidecar.manifest as ElementManifest[];\n }\n\n if (!manifest || manifest.length === 0) {\n throw new Error(\n \"No manifest provided. Supply --manifest-json, --manifest-file, or a sidecar JSON with a `manifest` array.\"\n );\n }\n\n // Styleguide resolution: same semantics as scan.ts (path/file/dir), with a good default start dir.\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const startPath =\n (imagePath ?? sidecarPath ?? manifestFilePath ?? undefined) || undefined;\n\n {\n const resolved = await resolveVisionStyleGuide({\n projectPath,\n styleguide: options.styleguide,\n startDir: startPath ? dirname(startPath) : projectPath,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput)\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n } else if (!styleGuide && !isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n\n debugLog(dbg, \"Vision input (high-level)\", {\n imagePath: imagePath ?? null,\n sidecarPath: sidecarPath ?? null,\n manifestFile: manifestFilePath ?? null,\n manifestElements: manifest.length,\n route: routeLabel,\n styleguideLocation,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n\n // Prepare Ollama (ensure model exists & server up)\n const visionModel = options.model || UILINT_DEFAULT_VISION_MODEL;\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady({\n model: visionModel,\n baseUrl: options.baseUrl,\n });\n });\n } else {\n await ensureOllamaReady({ model: visionModel, baseUrl: options.baseUrl });\n }\n const prepEndNs = nsNow();\n\n // Load screenshot bytes\n const resolvedImagePath =\n imagePath ||\n (() => {\n // If sidecar contains screenshotFile and is relative, resolve relative to the sidecar dir.\n const screenshotFile =\n typeof sidecar?.screenshotFile === \"string\"\n ? sidecar.screenshotFile\n : typeof sidecar?.filename === \"string\"\n ? sidecar.filename\n : undefined;\n if (!screenshotFile) return null;\n const baseDir = sidecarPath ? dirname(sidecarPath) : projectPath;\n const abs = resolve(baseDir, screenshotFile);\n return abs;\n })();\n\n if (!resolvedImagePath) {\n throw new Error(\n \"No image path could be resolved. Provide --image or a sidecar with `screenshotFile`/`filename`.\"\n );\n }\n if (!existsSync(resolvedImagePath)) {\n throw new Error(`Image not found: ${resolvedImagePath}`);\n }\n\n const { base64, sizeBytes } = readImageAsBase64(resolvedImagePath);\n debugLog(dbg, \"Image loaded\", {\n imagePath: resolvedImagePath,\n sizeBytes,\n base64Length: base64.length,\n });\n\n if (dbgFull && styleGuide) {\n debugLog(dbg, \"Styleguide (full)\", styleGuide);\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide (preview)\", preview(styleGuide, 800));\n }\n\n // Run analysis (optionally show streaming progress in text mode)\n let result: {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n } | null = null;\n\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n if (isJsonOutput) {\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n });\n } else {\n if (options.stream) {\n let lastStatus = \"\";\n let printedAnyText = false;\n let inThinking = false;\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n inThinking = true;\n } else if (!inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nThinking:\\n\"));\n inThinking = true;\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n\n // If we got a text delta, stream it directly\n if (delta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n }\n if (inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nAnswer:\\n\"));\n inThinking = false;\n }\n // Stream raw text to stderr to avoid corrupting stdout.\n process.stderr.write(delta);\n return;\n }\n\n // Fallback to status output (latest line / heartbeats).\n const line = (latestLine || \"\").trim();\n if (!line || line === lastStatus) return;\n lastStatus = line;\n console.error(pc.dim(\"[vision]\"), line);\n },\n });\n } else {\n result = await withSpinner(\n \"Analyzing screenshot with vision model\",\n async (s) => {\n return await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta))\n firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n },\n });\n }\n );\n }\n }\n\n const analysisEndNs = nsNow();\n\n const issues = result?.issues ?? [];\n\n if (isJsonOutput) {\n printJSON({\n route: routeLabel,\n model: visionModel,\n issues,\n analysisTime: result?.analysisTime ?? 0,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n });\n } else {\n logInfo(`Route: ${pc.dim(routeLabel)}`);\n logInfo(`Model: ${pc.dim(visionModel)}`);\n process.stdout.write(formatIssuesText(issues));\n\n // Pretty timings (TTY-only so we don't clutter non-interactive usage)\n if (process.stdout.isTTY) {\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n }\n\n // Write markdown report alongside the image (best-effort; never affects stdout JSON).\n try {\n writeVisionMarkdownReport({\n imagePath: resolvedImagePath,\n route: routeLabel,\n visionModel,\n baseUrl: options.baseUrl ?? \"http://localhost:11434\",\n analysisTimeMs: result?.analysisTime ?? 0,\n prompt: result?.prompt ?? null,\n rawResponse: result?.rawResponse ?? null,\n metadata: {\n imageSizeBytes: sizeBytes,\n styleguideLocation,\n },\n });\n debugLog(dbg, \"Wrote .vision.md report alongside image\");\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write .vision.md report\",\n e instanceof Error ? e.message : e\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(\n error instanceof Error ? error.message : \"Vision analysis failed\"\n );\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n await flushLangfuse();\n}\n","/**\n * UILint Config Command\n *\n * Allows setting configuration options that are broadcast to connected clients.\n *\n * Usage:\n * uilint config set position <x,y> - Set floating icon position\n * uilint config set position top-center - Use preset position\n * uilint config get position - Get current position (from server)\n * uilint config set rule <ruleId>:<severity> [optionsJson] - Set rule config\n *\n * Examples:\n * uilint config set rule consistent-dark-mode:warn\n * uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'\n * uilint config set rule no-mixed-component-libraries:off\n */\n\nimport { WebSocket } from \"ws\";\nimport { logInfo, logSuccess, logError, pc } from \"../utils/prompts.js\";\n\nexport interface ConfigOptions {\n port?: number;\n}\n\n/** Parse position value from string */\nfunction parsePosition(\n value: string\n): { x: number; y: number } | { preset: string } | null {\n // Check for presets\n const presets: Record<string, true> = {\n \"top-center\": true,\n \"top-left\": true,\n \"top-right\": true,\n \"bottom-center\": true,\n \"bottom-left\": true,\n \"bottom-right\": true,\n };\n\n if (presets[value]) {\n return { preset: value };\n }\n\n // Try to parse as x,y coordinates\n const match = value.match(/^(\\d+),(\\d+)$/);\n if (match) {\n return { x: parseInt(match[1], 10), y: parseInt(match[2], 10) };\n }\n\n return null;\n}\n\n/** Convert preset to position (approximate, client will recalculate) */\nfunction presetToPosition(preset: string): { x: number; y: number } {\n // These are approximate defaults - the client can recalculate based on viewport\n const positions: Record<string, { x: number; y: number }> = {\n \"top-center\": { x: 500, y: 30 },\n \"top-left\": { x: 60, y: 30 },\n \"top-right\": { x: 940, y: 30 },\n \"bottom-center\": { x: 500, y: 700 },\n \"bottom-left\": { x: 60, y: 700 },\n \"bottom-right\": { x: 940, y: 700 },\n };\n return positions[preset] || { x: 500, y: 30 };\n}\n\n/** Parse rule configuration from value string */\nfunction parseRuleConfig(value: string): {\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n} | null {\n // Format: <ruleId>:<severity>\n const match = value.match(/^([^:]+):(error|warn|off)$/);\n if (!match) {\n return null;\n }\n return {\n ruleId: match[1],\n severity: match[2] as \"error\" | \"warn\" | \"off\",\n };\n}\n\n/** Parse options JSON string */\nfunction parseOptionsJson(optionsStr: string | undefined): Record<string, unknown> | undefined {\n if (!optionsStr) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(optionsStr);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return undefined;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Send config message via WebSocket\n */\nasync function sendConfigMessage(\n port: number,\n key: string,\n value: unknown\n): Promise<boolean> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve(false);\n }\n }, 5000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({ type: \"config:set\", key, value });\n ws.send(message);\n\n // Give the server time to process and broadcast\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve(true);\n }\n }, 100);\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n}\n\n/**\n * Send rule config message via WebSocket and wait for result\n */\nasync function sendRuleConfigMessage(\n port: number,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n const requestId = `cli-${Date.now()}`;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve({ success: false, error: \"Request timed out\" });\n }\n }, 10000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n ws.send(message);\n });\n\n ws.on(\"message\", (data: Buffer) => {\n try {\n const msg = JSON.parse(data.toString());\n if (msg.type === \"rule:config:result\" && msg.requestId === requestId) {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve({\n success: msg.success,\n error: msg.error,\n });\n }\n }\n } catch {\n // Ignore parse errors\n }\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve({ success: false, error: \"Connection error\" });\n }\n });\n });\n}\n\n/**\n * Handle config set command\n */\nasync function handleSet(\n key: string,\n value: string,\n port: number,\n extraArg?: string\n): Promise<void> {\n switch (key) {\n case \"position\": {\n const parsed = parsePosition(value);\n if (!parsed) {\n logError(\n `Invalid position value: ${value}\\n` +\n `Expected format: x,y (e.g., 100,50) or preset (top-center, top-left, etc.)`\n );\n process.exit(1);\n }\n\n let position: { x: number; y: number };\n if (\"preset\" in parsed) {\n position = presetToPosition(parsed.preset);\n logInfo(`Using preset \"${parsed.preset}\" → (${position.x}, ${position.y})`);\n } else {\n position = parsed;\n }\n\n const success = await sendConfigMessage(\n port,\n \"floatingIconPosition\",\n position\n );\n\n if (success) {\n logSuccess(\n `Set floating icon position to (${position.x}, ${position.y})`\n );\n } else {\n logError(\n `Failed to set position. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n case \"rule\": {\n const parsed = parseRuleConfig(value);\n if (!parsed) {\n logError(\n `Invalid rule config: ${value}\\n` +\n `Expected format: <ruleId>:<severity>\\n` +\n ` severity: error, warn, or off\\n\\n` +\n `Examples:\\n` +\n ` uilint config set rule consistent-dark-mode:warn\\n` +\n ` uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'`\n );\n process.exit(1);\n }\n\n // Parse optional options JSON from extra argument\n const options = parseOptionsJson(extraArg);\n if (extraArg && !options) {\n logError(\n `Invalid options JSON: ${extraArg}\\n` +\n `Expected a valid JSON object, e.g., '{\"maxDepth\": 3}'`\n );\n process.exit(1);\n }\n\n logInfo(\n `Setting rule \"${parsed.ruleId}\" to ${parsed.severity}` +\n (options ? ` with options: ${JSON.stringify(options)}` : \"\")\n );\n\n const result = await sendRuleConfigMessage(\n port,\n parsed.ruleId,\n parsed.severity,\n options\n );\n\n if (result.success) {\n logSuccess(\n `Rule \"${parsed.ruleId}\" set to ${parsed.severity}` +\n (options ? ` with options` : \"\")\n );\n } else {\n logError(\n result.error ||\n `Failed to set rule config. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position, rule`);\n process.exit(1);\n }\n}\n\n/**\n * Handle config get command\n */\nasync function handleGet(key: string, _port: number): Promise<void> {\n switch (key) {\n case \"position\":\n logInfo(\n `Position is stored in the browser's localStorage.\\n` +\n `To view it, check your browser's dev tools:\\n` +\n ` localStorage.getItem(\"uilint:floatingIconPosition\")`\n );\n break;\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position`);\n process.exit(1);\n }\n}\n\n/**\n * Config command entry point\n */\nexport async function config(\n action: string,\n key: string,\n value?: string,\n extraArg?: string,\n options: ConfigOptions = {}\n): Promise<void> {\n const port = options.port || 9234;\n\n switch (action) {\n case \"set\":\n if (!value) {\n logError(`Missing value for config set ${key}`);\n process.exit(1);\n }\n await handleSet(key, value, port, extraArg);\n break;\n\n case \"get\":\n await handleGet(key, port);\n break;\n\n default:\n logError(`Unknown action: ${action}`);\n logInfo(`Usage: uilint config <set|get> <key> [value] [options]`);\n process.exit(1);\n }\n}\n","/**\n * Duplicates command - semantic code duplicate detection\n */\n\nimport { Command } from \"commander\";\nimport { indexCommand } from \"./index-cmd.js\";\nimport { findCommand } from \"./find.js\";\nimport { searchCommand } from \"./search.js\";\nimport { similarCommand } from \"./similar.js\";\n\nexport function createDuplicatesCommand(): Command {\n const duplicates = new Command(\"duplicates\")\n .description(\"Semantic code duplicate detection\");\n\n // Add subcommands\n duplicates.addCommand(indexCommand());\n duplicates.addCommand(findCommand());\n duplicates.addCommand(searchCommand());\n duplicates.addCommand(similarCommand());\n\n return duplicates;\n}\n","/**\n * Index command - build or update the semantic duplicates index\n */\n\nimport { Command } from \"commander\";\nimport { resolve } from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\nexport function indexCommand(): Command {\n return new Command(\"index\")\n .description(\"Build or update the semantic duplicates index\")\n .option(\"--force\", \"Rebuild index from scratch\")\n .option(\"--model <name>\", \"Embedding model (default: nomic-embed-text)\")\n .option(\n \"--exclude <glob>\",\n \"Exclude patterns (repeatable)\",\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n let spinner: ReturnType<typeof ora> | undefined;\n if (!isJson) {\n spinner = ora(\"Initializing indexer...\").start();\n }\n\n try {\n const result = await indexDirectory(projectRoot, {\n force: options.force,\n model: options.model,\n exclude: options.exclude,\n onProgress: (message, current, total) => {\n if (spinner) {\n if (current && total) {\n spinner.text = `${message} (${current}/${total})`;\n } else {\n spinner.text = message;\n }\n }\n },\n });\n\n if (isJson) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n spinner?.succeed(chalk.green(\"Index complete\"));\n console.log();\n console.log(chalk.bold(\"Index Statistics:\"));\n console.log(` Files added: ${result.added}`);\n console.log(` Files modified: ${result.modified}`);\n console.log(` Files deleted: ${result.deleted}`);\n console.log(` Total chunks: ${result.totalChunks}`);\n console.log(` Duration: ${(result.duration / 1000).toFixed(2)}s`);\n }\n } catch (error) {\n if (spinner) {\n spinner.fail(chalk.red(\"Index failed\"));\n }\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Find command - find semantic duplicate groups\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\nimport type { ChunkKind } from \"uilint-duplicates\";\n\nexport function findCommand(): Command {\n return new Command(\"find\")\n .description(\"Find semantic duplicate groups in the codebase\")\n .option(\n \"--threshold <n>\",\n \"Similarity threshold 0-1 (default: 0.85)\",\n parseFloat\n )\n .option(\"--min-size <n>\", \"Minimum group size (default: 2)\", parseInt)\n .option(\"--kind <type>\", \"Filter: component, hook, function\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { findDuplicates } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const groups = await findDuplicates({\n path: projectRoot,\n threshold: options.threshold,\n minGroupSize: options.minSize,\n kind: options.kind as ChunkKind | undefined,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ groups }, null, 2));\n return;\n }\n\n if (groups.length === 0) {\n console.log(chalk.green(\"No semantic duplicates found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${groups.length} duplicate group${groups.length > 1 ? \"s\" : \"\"}:\\n`\n )\n );\n\n groups.forEach((group, idx) => {\n const similarity = Math.round(group.avgSimilarity * 100);\n console.log(\n chalk.yellow(\n `Duplicate Group ${idx + 1} (${similarity}% similar, ${group.members.length} occurrences):`\n )\n );\n\n group.members.forEach((member) => {\n const relPath = relative(projectRoot, member.filePath);\n const location = `${relPath}:${member.startLine}-${member.endLine}`;\n const name = member.name || \"(anonymous)\";\n const score =\n member.score === 1.0\n ? \"\"\n : chalk.dim(` (${Math.round(member.score * 100)}%)`);\n console.log(` ${chalk.cyan(location.padEnd(50))} ${name}${score}`);\n });\n\n console.log(\n chalk.dim(\n ` Suggestion: Consider extracting shared logic into a reusable ${group.kind}\\n`\n )\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Search command - semantic search for code\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\n\nexport function searchCommand(): Command {\n return new Command(\"search\")\n .description(\"Semantic search for similar code\")\n .argument(\"<query>\", \"Search query (natural language)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.5)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (query: string, options) => {\n const { searchSimilar } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const results = await searchSimilar(query, {\n path: projectRoot,\n top: options.top,\n threshold: options.threshold,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No matching code found.\"));\n return;\n }\n\n console.log(chalk.bold(`Found ${results.length} matching results:\\n`));\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const location = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(location)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Similar command - find code similar to a specific location\n */\n\nimport { Command } from \"commander\";\nimport { relative, resolve, isAbsolute } from \"path\";\nimport chalk from \"chalk\";\n\nexport function similarCommand(): Command {\n return new Command(\"similar\")\n .description(\"Find code similar to a specific location\")\n .argument(\"<location>\", \"File location in format file:line (e.g., src/Button.tsx:15)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.7)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (location: string, options) => {\n const { findSimilarAtLocation } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n // Parse location\n const colonIdx = location.lastIndexOf(\":\");\n if (colonIdx === -1) {\n const message = \"Invalid location format. Use file:line (e.g., src/Button.tsx:15)\";\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePart = location.slice(0, colonIdx);\n const linePart = location.slice(colonIdx + 1);\n const line = parseInt(linePart, 10);\n\n if (isNaN(line)) {\n const message = `Invalid line number: ${linePart}`;\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePath = isAbsolute(filePart)\n ? filePart\n : resolve(projectRoot, filePart);\n\n try {\n const results = await findSimilarAtLocation({\n path: projectRoot,\n filePath,\n line,\n top: options.top,\n threshold: options.threshold ?? 0.7,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No similar code found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${results.length} similar code locations to ${relative(projectRoot, filePath)}:${line}:\\n`\n )\n );\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const locationStr = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(locationStr)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Socket CLI Command\n *\n * Provides a CLI interface for interacting with the UILint socket server.\n * Useful for testing, debugging, and scripting.\n *\n * Usage:\n * uilint socket # Start interactive REPL\n * uilint socket lint:file <path> # Lint a file\n * uilint socket vision:check # Check vision availability\n * uilint socket listen # Listen for all messages\n */\n\nimport { Command } from \"commander\";\nimport { readFileSync, existsSync } from \"fs\";\nimport chalk from \"chalk\";\nimport { createSocketClient, SocketClient } from \"./client.js\";\nimport type { ServerMessage, ElementManifest } from \"./types.js\";\n\nexport interface SocketOptions {\n port: number;\n debug: boolean;\n json: boolean;\n timeout: number;\n}\n\n/**\n * Format a message for display\n */\nfunction formatMessage(msg: ServerMessage, json: boolean): string {\n if (json) {\n return JSON.stringify(msg, null, 2);\n }\n\n switch (msg.type) {\n case \"lint:result\": {\n const lines = [`${chalk.cyan(\"lint:result\")} ${msg.filePath}`];\n if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const loc = issue.column\n ? `${issue.line}:${issue.column}`\n : `${issue.line}`;\n const rule = issue.ruleId ? chalk.dim(` [${issue.ruleId}]`) : \"\";\n lines.push(` ${chalk.yellow(loc)} ${issue.message}${rule}`);\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"vision:status\":\n if (msg.available) {\n return `${chalk.cyan(\"vision:status\")} ${chalk.green(\"available\")} (${msg.model})`;\n }\n return `${chalk.cyan(\"vision:status\")} ${chalk.red(\"not available\")}`;\n\n case \"vision:result\": {\n const lines = [\n `${chalk.cyan(\"vision:result\")} ${msg.route} (${msg.analysisTime}ms)`,\n ];\n if (msg.error) {\n lines.push(chalk.red(` Error: ${msg.error}`));\n } else if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const severity =\n issue.severity === \"error\"\n ? chalk.red(\"error\")\n : issue.severity === \"warning\"\n ? chalk.yellow(\"warn\")\n : chalk.blue(\"info\");\n lines.push(` ${severity} [${issue.category}] ${issue.message}`);\n if (issue.dataLoc) {\n lines.push(chalk.dim(` at ${issue.dataLoc}`));\n }\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"workspace:info\":\n return `${chalk.cyan(\"workspace:info\")}\\n appRoot: ${msg.appRoot}\\n workspaceRoot: ${msg.workspaceRoot}`;\n\n case \"rules:metadata\":\n return `${chalk.cyan(\"rules:metadata\")} ${msg.rules.length} rules available`;\n\n case \"source:result\":\n return `${chalk.cyan(\"source:result\")} ${msg.filePath} (${msg.totalLines} lines)`;\n\n case \"source:error\":\n return `${chalk.cyan(\"source:error\")} ${msg.filePath}: ${chalk.red(msg.error)}`;\n\n case \"coverage:result\":\n return `${chalk.cyan(\"coverage:result\")} Coverage data received`;\n\n case \"coverage:error\":\n return `${chalk.cyan(\"coverage:error\")} ${chalk.red(msg.error)}`;\n\n case \"rule:config:result\":\n if (msg.success) {\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} -> ${msg.severity}`;\n }\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} ${chalk.red(\"failed\")}: ${msg.error}`;\n\n case \"duplicates:indexing:start\":\n return `${chalk.cyan(\"duplicates:indexing:start\")}`;\n\n case \"duplicates:indexing:progress\":\n return `${chalk.cyan(\"duplicates:indexing:progress\")} ${msg.message}`;\n\n case \"duplicates:indexing:complete\":\n return `${chalk.cyan(\"duplicates:indexing:complete\")} ${msg.totalChunks} chunks in ${msg.duration}ms`;\n\n case \"duplicates:indexing:error\":\n return `${chalk.cyan(\"duplicates:indexing:error\")} ${chalk.red(msg.error)}`;\n\n case \"file:changed\":\n return `${chalk.cyan(\"file:changed\")} ${msg.filePath}`;\n\n case \"config:update\":\n return `${chalk.cyan(\"config:update\")} ${msg.key} = ${JSON.stringify(msg.value)}`;\n\n default:\n return `${chalk.cyan(msg.type)} ${JSON.stringify(msg)}`;\n }\n}\n\n/**\n * Run interactive REPL mode\n */\nasync function runRepl(client: SocketClient, options: SocketOptions): Promise<void> {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.green(\"uilint> \"),\n });\n\n console.log(chalk.bold(\"\\nUILint Socket REPL\"));\n console.log(\"Type 'help' for available commands, 'exit' to quit.\\n\");\n\n // Set up message handler\n client.onMessage((msg) => {\n console.log(\"\\n\" + formatMessage(msg, options.json));\n rl.prompt();\n });\n\n // Wait for initial messages\n try {\n await client.waitForWorkspaceInfo(2000);\n } catch {\n // Ignore timeout\n }\n\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) {\n rl.prompt();\n return;\n }\n\n const [cmd, ...args] = trimmed.split(/\\s+/);\n\n try {\n switch (cmd) {\n case \"help\":\n console.log(`\nAvailable commands:\n lint:file <path> Lint a file\n lint:element <path> <dataLoc> Lint a specific element\n vision:check Check if vision is available\n vision:analyze <route> <manifestFile> [screenshotFile]\n Run vision analysis\n source:fetch <path> Fetch source code\n coverage:request Request coverage data\n rule:config <ruleId> <severity> [optionsJson]\n Set rule configuration\n config:set <key> <value> Set a config value\n subscribe <path> Subscribe to file changes\n invalidate [path] Invalidate cache\n messages Show queued messages\n clear Clear message queue\n json Toggle JSON output\n exit Exit REPL\n`);\n break;\n\n case \"lint:file\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: lint:file <path>\"));\n } else {\n const result = await client.lintFile(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"lint:element\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: lint:element <path> <dataLoc>\"));\n } else {\n const result = await client.lintElement(args[0], args[1], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"vision:check\": {\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"vision:analyze\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: vision:analyze <route> <manifestFile> [screenshotFile]\"));\n } else {\n const manifestPath = args[1];\n if (!existsSync(manifestPath)) {\n console.log(chalk.red(`Manifest file not found: ${manifestPath}`));\n } else {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\")) as ElementManifest[];\n const params: {\n route: string;\n manifest: ElementManifest[];\n screenshotFile?: string;\n screenshot?: string;\n } = { route: args[0], manifest };\n\n if (args[2]) {\n if (existsSync(args[2])) {\n // Read as base64\n const imageBuffer = readFileSync(args[2]);\n params.screenshot = imageBuffer.toString(\"base64\");\n } else {\n console.log(chalk.red(`Screenshot file not found: ${args[2]}`));\n break;\n }\n }\n\n const result = await client.visionAnalyze(params, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n }\n break;\n\n case \"source:fetch\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: source:fetch <path>\"));\n } else {\n const result = await client.fetchSource(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"coverage:request\": {\n const result = await client.requestCoverage(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"rule:config\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: rule:config <ruleId> <severity> [optionsJson]\"));\n } else {\n const severity = args[1] as \"error\" | \"warn\" | \"off\";\n const ruleOptions = args[2] ? JSON.parse(args[2]) : undefined;\n const result = await client.setRuleConfig(args[0], severity, ruleOptions, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"config:set\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: config:set <key> <value>\"));\n } else {\n let value: unknown = args[1];\n try {\n value = JSON.parse(args[1]);\n } catch {\n // Keep as string\n }\n client.setConfig(args[0], value);\n console.log(chalk.green(`Set ${args[0]} = ${JSON.stringify(value)}`));\n }\n break;\n\n case \"subscribe\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: subscribe <path>\"));\n } else {\n client.subscribeFile(args[0]);\n console.log(chalk.green(`Subscribed to ${args[0]}`));\n }\n break;\n\n case \"invalidate\":\n client.invalidateCache(args[0]);\n console.log(chalk.green(args[0] ? `Invalidated ${args[0]}` : \"Invalidated all cache\"));\n break;\n\n case \"messages\": {\n const msgs = client.getMessages();\n if (msgs.length === 0) {\n console.log(chalk.dim(\"No queued messages\"));\n } else {\n for (const msg of msgs) {\n console.log(formatMessage(msg, options.json));\n }\n }\n break;\n }\n\n case \"clear\":\n client.clearMessages();\n console.log(chalk.green(\"Message queue cleared\"));\n break;\n\n case \"json\":\n options.json = !options.json;\n console.log(chalk.green(`JSON output ${options.json ? \"enabled\" : \"disabled\"}`));\n break;\n\n case \"exit\":\n case \"quit\":\n client.disconnect();\n rl.close();\n process.exit(0);\n break;\n\n default:\n console.log(chalk.red(`Unknown command: ${cmd}. Type 'help' for available commands.`));\n }\n } catch (err) {\n console.log(chalk.red(`Error: ${(err as Error).message}`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n client.disconnect();\n process.exit(0);\n });\n}\n\n/**\n * Run listen mode (print all messages)\n */\nasync function runListen(\n client: SocketClient,\n options: SocketOptions,\n filter?: string\n): Promise<void> {\n console.log(chalk.bold(\"\\nListening for messages...\"));\n if (filter) {\n console.log(chalk.dim(`Filter: ${filter}`));\n }\n console.log(chalk.dim(\"Press Ctrl+C to stop.\\n\"));\n\n client.onMessage((msg) => {\n if (filter && !msg.type.includes(filter.replace(\"*\", \"\"))) {\n return;\n }\n console.log(formatMessage(msg, options.json));\n });\n\n // Keep running\n await new Promise(() => {});\n}\n\n/**\n * Create the socket command\n */\nexport function createSocketCommand(): Command {\n const cmd = new Command(\"socket\")\n .description(\"Interact with the UILint socket server\")\n .option(\"-p, --port <number>\", \"Socket server port\", \"9234\")\n .option(\"-d, --debug\", \"Enable debug logging\", false)\n .option(\"-j, --json\", \"Output JSON format\", false)\n .option(\"-t, --timeout <ms>\", \"Request timeout in milliseconds\", \"30000\");\n\n // Default action: start REPL\n cmd.action(async (cmdOptions) => {\n const options: SocketOptions = {\n port: parseInt(cmdOptions.port, 10),\n debug: cmdOptions.debug,\n json: cmdOptions.json,\n timeout: parseInt(cmdOptions.timeout, 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runRepl(client, options);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n console.error(chalk.dim(`Make sure the server is running: uilint serve -p ${options.port}`));\n process.exit(1);\n }\n });\n\n // listen subcommand\n cmd\n .command(\"listen\")\n .description(\"Listen for all messages from the server\")\n .option(\"-f, --filter <pattern>\", \"Filter messages by type pattern (e.g., lint:*, vision:*)\")\n .action(async (subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runListen(client, options, subOptions.filter);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // lint:file subcommand\n cmd\n .command(\"lint:file <path>\")\n .description(\"Lint a file and output results\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.lintFile(filePath, options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.issues.length > 0 ? 1 : 0);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // vision:check subcommand\n cmd\n .command(\"vision:check\")\n .description(\"Check if vision analysis is available\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.available ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // source:fetch subcommand\n cmd\n .command(\"source:fetch <path>\")\n .description(\"Fetch source code for a file\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.fetchSource(filePath, options.timeout);\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else if (result.type === \"source:result\") {\n console.log(result.content);\n } else {\n console.error(chalk.red(`Error: ${result.error}`));\n }\n client.disconnect();\n process.exit(result.type === \"source:result\" ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // rules subcommand\n cmd\n .command(\"rules\")\n .description(\"List available rules\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const metadata = await client.waitForRulesMetadata(options.timeout);\n\n if (options.json) {\n console.log(JSON.stringify(metadata.rules, null, 2));\n } else {\n console.log(chalk.bold(`\\n${metadata.rules.length} rules available:\\n`));\n for (const rule of metadata.rules) {\n const severity =\n rule.currentSeverity === \"error\"\n ? chalk.red(\"error\")\n : rule.currentSeverity === \"warn\"\n ? chalk.yellow(\"warn\")\n : chalk.dim(\"off\");\n console.log(` ${chalk.cyan(rule.id)} [${severity}]`);\n console.log(chalk.dim(` ${rule.description}`));\n }\n }\n\n client.disconnect();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\n// Re-export types and client for programmatic use\nexport { SocketClient, createSocketClient } from \"./client.js\";\nexport { SocketTestHarness, createTestHarness } from \"./test-harness.js\";\nexport type * from \"./types.js\";\n","/**\n * Socket Client\n *\n * WebSocket client for communicating with the UILint socket server.\n * Provides request/response correlation and message handling.\n */\n\nimport WebSocket from \"ws\";\nimport type {\n ClientMessage,\n ServerMessage,\n LintResultMessage,\n VisionStatusMessage,\n VisionResultMessage,\n SourceResultMessage,\n SourceErrorMessage,\n CoverageResultMessage,\n CoverageErrorMessage,\n RuleConfigResultMessage,\n WorkspaceInfoMessage,\n RulesMetadataMessage,\n ElementManifest,\n} from \"./types.js\";\n\nexport interface SocketClientOptions {\n /** WebSocket URL (default: ws://localhost:9234) */\n url?: string;\n /** Port number (convenience, overrides url) */\n port?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Connection timeout in ms (default: 10000) */\n connectTimeout?: number;\n}\n\ntype MessageHandler = (message: ServerMessage) => void;\n\ninterface PendingRequest {\n predicate: (msg: ServerMessage) => boolean;\n resolve: (msg: ServerMessage) => void;\n reject: (err: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\nexport class SocketClient {\n private ws: WebSocket | null = null;\n private url: string;\n private debug: boolean;\n private connectTimeout: number;\n private connected = false;\n private connectionPromise: Promise<void> | null = null;\n private pendingRequests: PendingRequest[] = [];\n private messageQueue: ServerMessage[] = [];\n private messageHandlers: MessageHandler[] = [];\n\n constructor(options: SocketClientOptions = {}) {\n const port = options.port || 9234;\n this.url = options.url || `ws://localhost:${port}`;\n this.debug = options.debug || false;\n this.connectTimeout = options.connectTimeout || 10000;\n }\n\n /**\n * Connect to the socket server\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n if (this.connectionPromise) return this.connectionPromise;\n\n this.connectionPromise = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout to ${this.url}`));\n }, this.connectTimeout);\n\n this.ws = new WebSocket(this.url);\n\n this.ws.on(\"open\", () => {\n clearTimeout(timeout);\n this.connected = true;\n this.log(\"Connected to\", this.url);\n resolve();\n });\n\n this.ws.on(\"message\", (data: WebSocket.Data) => {\n try {\n const message = JSON.parse(data.toString()) as ServerMessage;\n this.log(\"Received:\", message.type);\n this.handleMessage(message);\n } catch (e) {\n console.error(\"Failed to parse message:\", e);\n }\n });\n\n this.ws.on(\"error\", (err) => {\n clearTimeout(timeout);\n if (!this.connected) {\n reject(err);\n } else {\n console.error(\"WebSocket error:\", err);\n }\n });\n\n this.ws.on(\"close\", () => {\n this.connected = false;\n this.log(\"Disconnected\");\n // Reject all pending requests\n for (const req of this.pendingRequests) {\n clearTimeout(req.timeout);\n req.reject(new Error(\"Disconnected\"));\n }\n this.pendingRequests = [];\n });\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n this.connectionPromise = null;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Add a handler for all incoming messages\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.push(handler);\n return () => {\n this.messageHandlers = this.messageHandlers.filter((h) => h !== handler);\n };\n }\n\n /**\n * Send a raw message\n */\n send(message: ClientMessage): void {\n if (!this.ws || !this.connected) {\n throw new Error(\"Not connected\");\n }\n this.log(\"Sending:\", message.type);\n this.ws.send(JSON.stringify(message));\n }\n\n /**\n * Wait for a message matching the predicate\n */\n waitFor(\n predicate: (msg: ServerMessage) => boolean,\n timeout = 30000\n ): Promise<ServerMessage> {\n // Check existing messages first\n const existing = this.messageQueue.find(predicate);\n if (existing) {\n this.messageQueue = this.messageQueue.filter((m) => m !== existing);\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests = this.pendingRequests.filter(\n (r) => r.timeout !== timeoutId\n );\n reject(new Error(`Timeout waiting for message (${timeout}ms)`));\n }, timeout);\n\n this.pendingRequests.push({\n predicate,\n resolve,\n reject,\n timeout: timeoutId,\n });\n });\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(): string {\n return `cli-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n // ==========================================================================\n // High-Level API Methods\n // ==========================================================================\n\n /**\n * Wait for workspace info (sent on connect)\n */\n async waitForWorkspaceInfo(timeout = 5000): Promise<WorkspaceInfoMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"workspace:info\");\n if (existing) {\n return existing as WorkspaceInfoMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"workspace:info\",\n timeout\n )) as WorkspaceInfoMessage;\n }\n\n /**\n * Wait for rules metadata (sent on connect)\n */\n async waitForRulesMetadata(timeout = 5000): Promise<RulesMetadataMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"rules:metadata\");\n if (existing) {\n return existing as RulesMetadataMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"rules:metadata\",\n timeout\n )) as RulesMetadataMessage;\n }\n\n /**\n * Lint a file\n */\n async lintFile(filePath: string, timeout = 30000): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:file\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Lint a specific element\n */\n async lintElement(\n filePath: string,\n dataLoc: string,\n timeout = 30000\n ): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:element\", filePath, dataLoc, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Check if vision analysis is available\n */\n async visionCheck(timeout = 10000): Promise<VisionStatusMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"vision:check\", requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:status\" &&\n (msg as VisionStatusMessage).requestId === requestId,\n timeout\n )) as VisionStatusMessage;\n }\n\n /**\n * Run vision analysis\n */\n async visionAnalyze(\n params: {\n route: string;\n manifest: ElementManifest[];\n screenshot?: string;\n screenshotFile?: string;\n },\n timeout = 120000\n ): Promise<VisionResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"vision:analyze\",\n route: params.route,\n timestamp: Date.now(),\n screenshot: params.screenshot,\n screenshotFile: params.screenshotFile,\n manifest: params.manifest,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:result\" &&\n (msg as VisionResultMessage).requestId === requestId,\n timeout\n )) as VisionResultMessage;\n }\n\n /**\n * Fetch source code\n */\n async fetchSource(\n filePath: string,\n timeout = 10000\n ): Promise<SourceResultMessage | SourceErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"source:fetch\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"source:result\" || msg.type === \"source:error\") &&\n ((msg as SourceResultMessage).requestId === requestId ||\n (msg as SourceErrorMessage).requestId === requestId),\n timeout\n )) as SourceResultMessage | SourceErrorMessage;\n }\n\n /**\n * Request coverage data\n */\n async requestCoverage(\n timeout = 30000\n ): Promise<CoverageResultMessage | CoverageErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"coverage:request\", requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"coverage:result\" || msg.type === \"coverage:error\") &&\n ((msg as CoverageResultMessage).requestId === requestId ||\n (msg as CoverageErrorMessage).requestId === requestId),\n timeout\n )) as CoverageResultMessage | CoverageErrorMessage;\n }\n\n /**\n * Set rule configuration\n */\n async setRuleConfig(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n timeout = 10000\n ): Promise<RuleConfigResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"rule:config:result\" &&\n (msg as RuleConfigResultMessage).requestId === requestId,\n timeout\n )) as RuleConfigResultMessage;\n }\n\n /**\n * Set a configuration value\n */\n setConfig(key: string, value: unknown): void {\n this.send({ type: \"config:set\", key, value });\n }\n\n /**\n * Subscribe to file changes\n */\n subscribeFile(filePath: string): void {\n this.send({ type: \"subscribe:file\", filePath });\n }\n\n /**\n * Invalidate cache\n */\n invalidateCache(filePath?: string): void {\n this.send({ type: \"cache:invalidate\", filePath });\n }\n\n /**\n * Get all queued messages\n */\n getMessages(): ServerMessage[] {\n return [...this.messageQueue];\n }\n\n /**\n * Clear message queue\n */\n clearMessages(): void {\n this.messageQueue = [];\n }\n\n private handleMessage(message: ServerMessage): void {\n // Notify all handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n\n // Check if any pending request matches\n for (let i = 0; i < this.pendingRequests.length; i++) {\n const req = this.pendingRequests[i]!;\n if (req.predicate(message)) {\n clearTimeout(req.timeout);\n this.pendingRequests.splice(i, 1);\n req.resolve(message);\n return;\n }\n }\n\n // Otherwise queue it\n this.messageQueue.push(message);\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log(\"[SocketClient]\", ...args);\n }\n }\n}\n\n/**\n * Create a connected socket client\n */\nexport async function createSocketClient(\n options: SocketClientOptions = {}\n): Promise<SocketClient> {\n const client = new SocketClient(options);\n await client.connect();\n return client;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,WAAAA,gBAAe;;;ACAxB,SAAS,SAAS,WAAAC,gBAAe;AACjC,SAAS,cAAAC,aAAY,WAAW,UAAU,qBAAqB;AAC/D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACfP,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;;;ACFP,SAAS,YAAY,eAAe;AACpC,SAAS,yBAAyB;AAU3B,SAAS,qBACd,MACA,MAAc,QAAQ,IAAI,GAClB;AACR,QAAM,OAAO,QAAQ,IAAI,KAAK;AAC9B,MAAI,CAAC,IAAK,QAAO,QAAQ,KAAK,IAAI;AAElC,MAAI,IAAI,WAAW,GAAG,GAAG;AACvB,UAAM,gBAAgB,kBAAkB,GAAG;AAC3C,QAAI,OAAO,IAAI,MAAM,CAAC;AACtB,QAAI,KAAK,WAAW,GAAG,EAAG,QAAO,KAAK,MAAM,CAAC;AAG7C,WAAO,QAAQ,eAAe,IAAI;AAAA,EACpC;AAEA,MAAI,WAAW,GAAG,EAAG,QAAO,QAAQ,GAAG;AACvC,SAAO,QAAQ,KAAK,GAAG;AACzB;;;ADLA,SAAS,oBAAoB,KAAsB;AACjD,SAAO,QAAQ,WAAW,QAAQ;AACpC;AAEA,SAAS,oBAAoB,KAAsB;AACjD,SAAO,QAAQ;AACjB;AAKA,eAAsB,SAAS,SAA6C;AAE1E,MAAI,QAAQ,WAAW;AACrB,WAAO,cAAc,QAAQ,SAAS;AAAA,EACxC;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,WAAW,qBAAqB,QAAQ,WAAW,QAAQ,IAAI,CAAC;AACtE,QAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,YAAM,IAAI,MAAM,mBAAmB,QAAQ,SAAS,EAAE;AAAA,IACxD;AACA,UAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,WAAO,cAAc,OAAO;AAAA,EAC9B;AAEA,MAAI,SAAS,GAAG;AACd,UAAM,UAAU,MAAM,UAAU;AAChC,QAAI,CAAC,QAAQ,KAAK,GAAG;AACnB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO,cAAc,OAAO;AAAA,EAC9B;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAOA,eAAsB,aAAa,SAA2C;AAE5E,MAAI,QAAQ,WAAW;AACrB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,cAAc,QAAQ,SAAS;AAAA,MACzC,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,WAAW,qBAAqB,QAAQ,WAAW,QAAQ,IAAI,CAAC;AACtE,QAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,YAAM,IAAI,MAAM,mBAAmB,QAAQ,SAAS,EAAE;AAAA,IACxD;AACA,UAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,UAAM,MAAM,QAAQ,QAAQ,EAAE,YAAY;AAE1C,QAAI,oBAAoB,GAAG,KAAK,oBAAoB,GAAG,GAAG;AACxD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,cAAc,OAAO;AAAA,QAC/B,QAAQ;AAAA,QACR,WAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI,SAAS,GAAG;AACd,UAAM,UAAU,MAAM,UAAU;AAChC,QAAI,CAAC,QAAQ,KAAK,GAAG;AACnB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,cAAc,OAAO;AAAA,MAC/B,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAKA,eAAsB,aAAa,SAGf;AAClB,MAAI,QAAQ,MAAM;AAChB,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,MAAM;AAChB,UAAM,WAAW,qBAAqB,QAAQ,MAAM,QAAQ,IAAI,CAAC;AACjE,QAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,YAAM,IAAI,MAAM,mBAAmB,QAAQ,IAAI,EAAE;AAAA,IACnD;AACA,WAAO,SAAS,UAAU,OAAO;AAAA,EACnC;AAEA,MAAI,SAAS,GAAG;AACd,UAAM,UAAU,MAAM,UAAU;AAChC,QAAI,CAAC,QAAQ,KAAK,GAAG;AACnB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;;;AEvJA,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EAGA,qBAAAC;AAAA,OACK;AACP,SAAS,eAAe;AACxB,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP,IAAI,YAAY;AAChB,SAAS,eAAqB;AAC5B,MAAI,UAAW;AACf,cAAY;AAEZ,QAAM,gBAAgBA,mBAAkB,QAAQ,IAAI,CAAC;AACrD,QAAM,eAAe,KAAK,eAAe,YAAY;AAGrD,SAAO,EAAE,MAAM,aAAa,CAAC;AAC/B;AAGA,aAAa;AAGb,IAAI,sBAAsB;AAC1B,IAAI;AACJ,IAAI;AACJ,IAAI;AAKJ,SAAS,oBAA6B;AACpC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,SACE,YAAY,OACZ,QAAQ,YAAY,MAAM,UAC1B,QAAQ,YAAY,MAAM;AAE9B;AAMA,eAAsB,8BAA6C;AACjE,MAAI,oBAAqB;AACzB,wBAAsB;AAEtB,MAAI,CAAC,kBAAkB,GAAG;AACxB;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,YAAY,QAAQ,IAAI;AAE9B,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,YAAQ;AAAA,MACN;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,QAAQ,IAAI,qBAAqB;AAGjD,oBAAgB,IAAI,sBAAsB;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA,YAAY;AAAA,IACd,CAAC;AAGD,UAAM,MAAM,IAAI,QAAQ;AAAA,MACtB,gBAAgB,CAAC,aAAa;AAAA,IAChC,CAAC;AAED,QAAI,MAAM;AACV,kBAAc;AAId,8BAA0B;AAAA,MACxB,mBAAmB,CAAC;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,MAK2B;AAGzB,YAAI;AACJ,YAAI;AACJ,YAAI;AACJ,YAAI;AAcJ,cAAM,eAAe;AAAA,UACnB,UAAU,IAAI;AAAA,UACd,OAAO,SAAS;AACd,uBAAW;AACX,iBAAK,OAAO;AAAA,cACV,OAAO,EAAE,WAAW,KAAK;AAAA,cACzB,UAAU;AAAA,gBACR,GAAG;AAAA,gBACH,QAAQ;AAAA,cACV;AAAA,YACF,CAAC;AAID,4BAAgB;AAAA,cACd;AAAA,cACA;AAAA,gBACE;AAAA,gBACA,OAAO;AAAA,gBACP,UAAU;AAAA,kBACR,GAAG;AAAA,kBACH,QAAQ;AAAA,gBACV;AAAA,cACF;AAAA,cACA,EAAE,QAAQ,aAAa;AAAA,YACzB;AAGA,kBAAM,IAAI,QAAc,CAACC,aAAY;AACnC,6BAAeA;AAAA,YACjB,CAAC;AAGD,gBAAI,WAAW,eAAe;AAC5B,oBAAM,eACJ,QAAQ,QACJ,OAAO;AAAA,gBACL,OAAO,QAAQ;AAAA,kBACb,OAAO,QAAQ,MAAM;AAAA,kBACrB,QAAQ,QAAQ,MAAM;AAAA,kBACtB,OAAO,QAAQ,MAAM;AAAA,gBACvB,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS;AAAA,cAItC,IACA;AAGN,4BAAc,OAAO;AAAA,gBACnB,QAAQ,QAAQ;AAAA,gBAChB,cACE,gBAAgB,OAAO,KAAK,YAAY,EAAE,SAAS,IAC/C,eACA;AAAA,gBACN,UAAU,QAAQ,OAAO,QACrB,EAAE,GAAG,UAAU,OAAO,QAAQ,MAAM,MAAM,IAC1C;AAAA,cACN,CAAC;AACD,4BAAc,IAAI;AAGlB,mBAAK,OAAO;AAAA,gBACV,QAAQ,QAAQ,OAAO,QACnB,UAAU,QAAQ,MAAM,KAAK,KAC7B;AAAA,cACN,CAAC;AAAA,YACH;AAAA,UAEF;AAAA,QACF;AAGA,qBAAa,MAAM,CAAC,UAAU;AAC5B,kBAAQ,MAAM,kCAAkC,KAAK;AAAA,QACvD,CAAC;AAED,eAAO;AAAA,UACL,KAAK,CACH,QACA,UAMG;AAEH,sBAAU,EAAE,QAAQ,MAAM;AAC1B,gBAAI,cAAc;AAChB,2BAAa;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,MAAM,sCAAsC,OAAO,GAAG;AAAA,EAChE,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AACF;AAMA,eAAsB,gBAAgB,SAIZ;AAExB,QAAM,4BAA4B;AAElC,SAAO,IAAI,aAAa;AAAA,IACtB,GAAG;AAAA,IACH,iBAAiB;AAAA,EACnB,CAAC;AACH;AAKA,eAAsB,gBAA+B;AAEnD,MAAI,eAAe;AACjB,QAAI;AACF,YAAM,cAAc,WAAW;AAAA,IACjC,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAGA,MAAI,aAAa;AACf,QAAI;AACF,YAAM,YAAY,SAAS;AAAA,IAC7B,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAUA,IAAI,qBAAqB;AACzB,SAAS,0BAAgC;AACvC,MAAI,mBAAoB;AACxB,uBAAqB;AAErB,QAAM,UAAU,YAAY;AAC1B,UAAM,cAAc;AAAA,EACtB;AAEA,UAAQ,GAAG,cAAc,OAAO;AAChC,UAAQ,GAAG,UAAU,YAAY;AAC/B,UAAM,QAAQ;AACd,YAAQ,KAAK,GAAG;AAAA,EAClB,CAAC;AACD,UAAQ,GAAG,WAAW,YAAY;AAChC,UAAM,QAAQ;AACd,YAAQ,KAAK,GAAG;AAAA,EAClB,CAAC;AACH;AAGA,wBAAwB;;;AC1TjB,SAAS,QAAgB;AAC9B,SAAO,QAAQ,OAAO,OAAO;AAC/B;AAEO,SAAS,OAAO,IAAoB;AACzC,SAAO,OAAO,EAAE,IAAI;AACtB;AAEO,SAAS,SAAS,IAAoB;AAC3C,MAAI,CAAC,OAAO,SAAS,EAAE,EAAG,QAAO;AACjC,MAAI,KAAK,IAAM,QAAO,GAAG,GAAG,QAAQ,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AACnE,QAAM,IAAI,KAAK;AACf,MAAI,IAAI,GAAI,QAAO,GAAG,EAAE,QAAQ,IAAI,KAAK,IAAI,CAAC,CAAC;AAC/C,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,QAAM,MAAM,IAAI,IAAI;AACpB,SAAO,GAAG,CAAC,KAAK,IAAI,QAAQ,MAAM,KAAK,IAAI,CAAC,CAAC;AAC/C;AAEO,SAAS,QAAQ,IAAuC;AAC7D,SAAO,MAAM,OAAO,QAAQ,SAAS,EAAE;AACzC;;;ACpBA,OAAO,WAAW;AAClB;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAiBA,SAAS,UAAU,MAAqB;AAC7C,UAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC3C;;;ALiCA,SAAS,UAAU,MAAuB;AACxC,QAAM,IAAI,QAAQ,IAAI,IAAI;AAC1B,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM;AACxE;AAEA,SAAS,QAAQ,MAAc,QAAwB;AACrD,MAAI,KAAK,UAAU,OAAQ,QAAO;AAClC,SAAO,KAAK,MAAM,GAAG,MAAM,IAAI,gCAAsB,KAAK,MAAM,CAAC,MAAM;AACzE;AAEA,SAAS,aAAa,SAA+B;AACnD,SAAO,QAAQ,QAAQ,KAAK,KAAK,UAAU,cAAc;AAC3D;AAEA,SAAS,iBAAiB,SAA+B;AACvD,SAAO,QAAQ,QAAQ,SAAS,KAAK,UAAU,mBAAmB;AACpE;AAEA,SAAS,cAAc,SAAqC;AAC1D,QAAM,IAAI,QAAQ,aAAa,QAAQ,IAAI;AAC3C,MAAI,CAAC,EAAG,QAAO;AAEf,MAAI,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM,OAAO;AACxE,WAAOC,SAAQ,QAAQ,IAAI,GAAG,SAAS;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,SAAS,SAAkB,SAAiB,KAAqB;AACxE,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,QAAW;AACrB,YAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,EACjD,OAAO;AACL,QAAI;AACF,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,SAAS,GAAG;AAAA,IACtD,QAAQ;AACN,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,IACjD;AAAA,EACF;AACF;AAEA,eAAsB,KAAK,SAAqC;AAE9D,QAAM,eAAe,QAAQ,WAAW;AACxC,QAAM,MAAM,aAAa,OAAO;AAChC,QAAM,UAAU,iBAAiB,OAAO;AACxC,QAAM,UAAU,cAAc,OAAO;AAErC,MAAI,CAAC,cAAc;AACjB,UAAM,oBAAoB;AAAA,EAC5B;AAEA,MAAI;AAEF,QAAI;AACJ,QAAI;AACF,YAAM,oBAAiC;AAAA,QACrC,GAAG;AAAA,QACH,WAAW,QAAQ,YACf,qBAAqB,QAAQ,WAAW,QAAQ,IAAI,CAAC,IACrD,QAAQ;AAAA,MACd;AACA,UAAI,cAAc;AAChB,mBAAW,MAAM,aAAa,iBAAiB;AAAA,MACjD,OAAO;AACL,mBAAW,MAAM,YAAY,iBAAiB,YAAY;AACxD,iBAAO,MAAM,aAAa,iBAAiB;AAAA,QAC7C,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AACN,UAAI,cAAc;AAChB,kBAAU,EAAE,OAAO,qBAAqB,QAAQ,CAAC,EAAE,CAAC;AAAA,MACtD,OAAO;AACL,iBAAS,4DAA4D;AAAA,MACvE;AACA,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,aAAS,KAAK,iBAAiB;AAAA,MAC7B,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ,YAAY,eAAe;AAAA,MAC9C,YAAY,QAAQ;AAAA,MACpB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,QAAI,SAAS,SAAS,OAAO;AAC3B,YAAM,MAAM,SAAS;AACrB,eAAS,KAAK,gCAAgC;AAAA,QAC5C,cAAc,IAAI;AAAA,QAClB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI,KAAK;AAAA,QACrB,QAAQ;AAAA,UACN,QAAQ,IAAI,OAAO,OAAO;AAAA,UAC1B,WAAW,IAAI,OAAO,UAAU;AAAA,UAChC,cAAc,IAAI,OAAO,aAAa;AAAA,UACtC,aAAa,IAAI,OAAO,YAAY;AAAA,UACpC,SAAS,IAAI,OAAO,QAAQ;AAAA,UAC5B,cAAc,IAAI,OAAO,aAAa;AAAA,QACxC;AAAA,MACF,CAAC;AACD,UAAI,SAAS;AACX,iBAAS,KAAK,wBAAwB,IAAI,IAAI;AAAA,MAChD,WAAW,KAAK;AACd,iBAAS,KAAK,2BAA2B,QAAQ,IAAI,MAAM,GAAG,CAAC;AAAA,MACjE;AAEA,UAAI,CAAC,cAAc;AACjB,gBAAQ,YAAY,GAAG,KAAK,OAAO,IAAI,YAAY,CAAC,CAAC,WAAW;AAAA,MAClE;AAAA,IACF,OAAO;AACL,eAAS,KAAK,oCAAoC;AAAA,QAChD,WAAW,SAAS;AAAA,QACpB,WAAW,SAAS;AAAA,QACpB,QAAQ,SAAS,OAAO;AAAA,QACxB,OAAO,SAAS,OAAO,MAAM,IAAI,EAAE;AAAA,MACrC,CAAC;AACD,UAAI,SAAS;AACX,iBAAS,KAAK,iBAAiB,SAAS,MAAM;AAAA,MAChD,WAAW,KAAK;AACd,iBAAS,KAAK,oBAAoB,QAAQ,SAAS,QAAQ,IAAI,CAAC;AAAA,MAClE;AAEA,UAAI,CAAC,cAAc;AACjB;AAAA,UACE,YAAY,GAAG,KAAK,SAAS,aAAa,QAAQ,CAAC,KAAK,GAAG;AAAA,YACzD,OAAO,SAAS,OAAO,MAAM,IAAI,EAAE,MAAM;AAAA,UAC3C,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAOA,QAAI,aAA4B;AAChC,QAAI,qBAAoC;AACxC,UAAM,cAAc,QAAQ,IAAI;AAEhC,QAAI,QAAQ,YAAY;AACtB,YAAM,gBAAgB;AAAA,QACpB,QAAQ;AAAA,QACR;AAAA,MACF;AACA,UAAIC,YAAW,aAAa,GAAG;AAC7B,cAAM,OAAO,SAAS,aAAa;AACnC,YAAI,KAAK,OAAO,GAAG;AAEjB,+BAAqB;AACrB,uBAAa,MAAM,eAAe,aAAa;AAAA,QACjD,WAAW,KAAK,YAAY,GAAG;AAE7B,+BAAqB,mBAAmB,aAAa;AACrD,cAAI,oBAAoB;AACtB,yBAAa,MAAM,eAAe,kBAAkB;AAAA,UACtD;AAAA,QACF;AAAA,MACF,OAAO;AACL,YAAI,CAAC,cAAc;AACjB,qBAAW,yBAAyB,aAAa,EAAE;AAAA,QACrD;AAAA,MACF;AAAA,IACF,OAAO;AAIL,YAAM,YACJ,SAAS,SAAS,WACd,SAAS,YACT,SAAS,SAAS,QAClB,SAAS,YACT;AACN,UAAI,WAAW;AACb,6BAAqB,4BAA4B,QAAQ,SAAS,CAAC;AAAA,MACrE;AAGA,2BACE,sBAAsB,mBAAmB,WAAW;AACtD,UAAI,oBAAoB;AACtB,qBAAa,MAAM,eAAe,kBAAkB;AAAA,MACtD;AAAA,IACF;AAEA,QAAI,sBAAsB,YAAY;AACpC,UAAI,CAAC,cAAc;AACjB,mBAAW,qBAAqB,GAAG,IAAI,kBAAkB,CAAC,EAAE;AAAA,MAC9D;AAAA,IACF,WAAW,CAAC,YAAY;AACtB,UAAI,CAAC,cAAc;AACjB,mBAAW,qBAAqB;AAChC;AAAA,UACE;AAAA,YACE,gBAAgB,QAAQ,cAAc,WAAW;AAAA,YACjD;AAAA,YACA;AAAA,YACA,GAAG,iBAAiB,IAAI,CAAC,MAAM,YAAO,CAAC,EAAE;AAAA,YACzC;AAAA,YACA,UAAU,GAAG;AAAA,cACX;AAAA,YACF,CAAC,sBAAsB,GAAG,KAAK,gBAAgB,CAAC;AAAA,UAClD,EAAE,KAAK,IAAI;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,aAAS,KAAK,uBAAuB;AAAA,MACnC,eAAe,QAAQ;AAAA,MACvB,oBAAoB,sBAAsB;AAAA,MAC1C,kBAAkB,aAAa,WAAW,SAAS;AAAA,IACrD,CAAC;AACD,QAAI,SAAS;AACX,eAAS,KAAK,8BAA8B,cAAc,EAAE;AAAA,IAC9D,WAAW,OAAO,YAAY;AAC5B,eAAS,KAAK,iCAAiC,QAAQ,YAAY,GAAG,CAAC;AAAA,IACzE;AAGA,UAAM,qBACH,SAAS,SAAS,YAAY,SAAS,SAAS,UACjD,SAAS,YACL,QAAQ,SAAS,SAAS,IAC1B;AACN,UAAM,gBAAgB,wBAAwB,iBAAiB;AAC/D,UAAM,eACJ,SAAS,SAAS,QACd,mBAAmB,SAAS,SAAS,QAAQ;AAAA,MAC3C,MAAM,SAAS,SAAS;AAAA,MACxB;AAAA,IACF,CAAC,IACD;AAEN,aAAS,KAAK,oBAAoB;AAAA,MAChC;AAAA,MACA,eAAe,gBACX;AAAA,QACE,YAAY,cAAc;AAAA,QAC1B,QAAQ,cAAc,OAAO;AAAA,QAC7B,aAAa,cAAc,YAAY;AAAA,QACvC,kBAAkB,cAAc,iBAAiB;AAAA,QACjD,gBAAgB,cAAc,eAAe;AAAA,QAC7C,cAAc,cAAc,aAAa;AAAA,MAC3C,IACA;AAAA,IACN,CAAC;AAED,aAAS,KAAK,yBAAyB;AAAA,MACrC,QAAQ,eAAe,aAAa,SAAS;AAAA,MAC7C,OAAO,eAAe,aAAa,MAAM,IAAI,EAAE,SAAS;AAAA,IAC1D,CAAC;AACD,QAAI,SAAS;AACX,eAAS,KAAK,wBAAwB,gBAAgB,EAAE;AAAA,IAC1D,WAAW,OAAO,cAAc;AAC9B,eAAS,KAAK,2BAA2B,QAAQ,cAAc,GAAG,CAAC;AAAA,IACrE;AAGA,UAAM,cAAc,MAAM;AAC1B,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,oBAAoB,YAAY;AAChD,cAAM,kBAAkB;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AACL,YAAM,kBAAkB;AAAA,IAC1B;AACA,UAAM,YAAY,MAAM;AAGxB,UAAM,SAAS,MAAM,gBAAgB,CAAC,CAAC;AACvC,QAAI;AAGJ,UAAM,SACJ,SAAS,SAAS,QACd,oBAAoB,gBAAgB,IAAI,UAAU,IAClD,0BAA0B,SAAS,QAAQ,YAAY;AAAA,MACrD,UAAU,SAAS;AAAA,MACnB,cAAc,SAAS,UAAU,QAAQ,OAAO,EAAE,KAAK;AAAA,MACvD,cAAc,gBACV,sCAAsC,cAAc,UAAU;AAAA,YAAe,cAAc,OAAO,MAAM;AAAA,iBAAoB,cAAc,YAAY,MAAM;AAAA,sBAAyB,cAAc,iBAAiB,MAAM;AAAA,oBAAuB,cAAc,eAAe,MAAM;AAAA,kBAAqB,cAAc,aAAa,MAAM,KAC1U;AAAA,IACN,CAAC;AACP,aAAS,KAAK,4BAA4B;AAAA,MACxC,SAAS;AAAA,MACT,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ,CAAC;AAAA,MACT,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO,MAAM,IAAI,EAAE;AAAA,IAClC,CAAC;AAED,QAAI,SAAS;AACX,eAAS,KAAK,qBAAqB,MAAM;AAAA,IAC3C,WAAW,KAAK;AACd,eAAS,KAAK,wBAAwB,QAAQ,QAAQ,IAAI,CAAC;AAAA,IAC7D;AAEA,QAAI,SAAS;AACX,UAAI;AACF,cAAM,MAAM,oBAAI,KAAK;AACrB,cAAM,YAAY,IAAI,YAAY,EAAE,QAAQ,SAAS,GAAG;AACxD,cAAM,WAAWD,SAAQ,QAAQ,IAAI,GAAG,OAAO;AAC/C,cAAM,WACJ,SAAS,SAAS,OAAO,KAAK,SAAS,SAAS,QAAQ,IACpD,WACAA,SAAQ,UAAU,cAAc,SAAS,OAAO;AAGtD,kBAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD;AAAA,UACE;AAAA,UACA,KAAK;AAAA,YACH;AAAA,cACE,SAAS;AAAA,cACT,WAAW,IAAI,YAAY;AAAA,cAC3B,SAAS;AAAA,gBACP,WAAW,QAAQ;AAAA,gBACnB,WAAW,QAAQ,YAAY,eAAe;AAAA,gBAC9C,YAAY,QAAQ;AAAA,gBACpB;AAAA,gBACA,QAAQ,QAAQ;AAAA,gBAChB,OAAO,OAAO,SAAS;AAAA,cACzB;AAAA,cACA,UAAU;AAAA,gBACR,MAAM,SAAS;AAAA,gBACf,GAAI,SAAS,SAAS,QAClB;AAAA,kBACE,cAAc,SAAS,SAAS;AAAA,kBAChC,WAAW,SAAS,SAAS;AAAA,kBAC7B,MAAM,SAAS,SAAS;AAAA,kBACxB,QAAQ;AAAA,oBACN,QAAQ,CAAC,GAAG,SAAS,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,oBACrD,WAAW;AAAA,sBACT,GAAG,SAAS,SAAS,OAAO,UAAU,QAAQ;AAAA,oBAChD;AAAA,oBACA,cAAc;AAAA,sBACZ,GAAG,SAAS,SAAS,OAAO,aAAa,QAAQ;AAAA,oBACnD;AAAA,oBACA,aAAa;AAAA,sBACX,GAAG,SAAS,SAAS,OAAO,YAAY,QAAQ;AAAA,oBAClD;AAAA,oBACA,SAAS;AAAA,sBACP,GAAG,SAAS,SAAS,OAAO,QAAQ,QAAQ;AAAA,oBAC9C;AAAA,oBACA,cAAc;AAAA,sBACZ,GAAG,SAAS,SAAS,OAAO,aAAa,QAAQ;AAAA,oBACnD;AAAA,kBACF;AAAA,gBACF,IACA;AAAA,kBACE,WAAW,SAAS;AAAA,kBACpB,WAAW,SAAS;AAAA,kBACpB,QAAQ,SAAS;AAAA,gBACnB;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,YAAY;AAAA,gBACV,SAAS;AAAA,gBACT,OAAO,OAAO,SAAS;AAAA,gBACvB,QAAQ;AAAA,gBACR,QAAQ,CAAC;AAAA,cACX;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA,iBAAS,KAAK,uBAAuB,QAAQ,EAAE;AAAA,MACjD,SAAS,GAAG;AACV;AAAA,UACE;AAAA,UACA;AAAA,UACA,aAAa,QAAQ,EAAE,UAAU;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,cAAc;AAChB,eACE,SAAS,SAAS,QACd,MAAM,OAAO,cAAc,gBAAgB,IAAI,UAAU,IACzD,MAAM,OAAO,cAAc,SAAS,QAAQ,YAAY,QAAW;AAAA,QACjE,UAAU,SAAS;AAAA,QACnB,cAAc,SAAS,UAAU,QAAQ,OAAO,EAAE,KAAK;AAAA,QACvD,cAAc,gBACV,sCAAsC,cAAc,UAAU;AAAA,YAAe,cAAc,OAAO,MAAM;AAAA,iBAAoB,cAAc,YAAY,MAAM;AAAA,sBAAyB,cAAc,iBAAiB,MAAM;AAAA,oBAAuB,cAAc,eAAe,MAAM;AAAA,kBAAqB,cAAc,aAAa,MAAM,KAC1U;AAAA,MACN,CAAC;AAAA,IACT,OAAO;AAEL,YAAM,IAAI,cAAc;AACxB,QAAE,MAAM,oBAAoB;AAC5B,UAAI,kBAAkB;AACtB,YAAM,kBAAkB,MAAM;AAC9B,UAAI,eAA8B;AAClC,UAAI,kBAAiC;AACrC,UAAI,iBAAgC;AACpC,UAAI,gBAA+B;AACnC,UAAI,eAA8B;AAElC,YAAM,aAAa,CACjB,YACA,eACA,OACA,kBACS;AACT,cAAM,QAAQ,MAAM;AACpB,YAAI,CAAC,iBAAiB,iBAAiB,OAAQ,gBAAe;AAC9D,YAAI,eAAe;AACjB,cAAI,CAAC,gBAAiB,mBAAkB;AACxC,2BAAiB;AAAA,QACnB;AACA,YAAI,OAAO;AACT,cAAI,CAAC,cAAe,iBAAgB;AACpC,yBAAe;AAAA,QACjB;AAEA,YAAI,eAAe;AACjB,cAAI,CAAC,iBAAiB;AACpB,8BAAkB;AAClB,cAAE,KAAK,GAAG,IAAI,4BAA4B,CAAC;AAC3C,oBAAQ,OAAO,MAAM,GAAG,IAAI,aAAa,CAAC;AAAA,UAC5C;AACA,kBAAQ,OAAO,MAAM,aAAa;AAClC;AAAA,QACF;AAEA,cAAM,SAAS;AACf,cAAM,cACJ,WAAW,SAAS,SAChB,WAAW,MAAM,GAAG,MAAM,IAAI,WAC9B;AACN,UAAE,QAAQ,cAAc,GAAG,IAAI,eAAe,KAAK,CAAC,EAAE;AAAA,MACxD;AAEA,UAAI;AACF,iBACE,SAAS,SAAS,QACd,MAAM,OAAO;AAAA,UACX,gBAAgB;AAAA,UAChB;AAAA,UACA;AAAA,QACF,IACA,MAAM,OAAO;AAAA,UACX,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,YACE,UAAU,SAAS;AAAA,YACnB,cACE,SAAS,UAAU,QAAQ,OAAO,EAAE,KAAK;AAAA,YAC3C,cAAc,gBACV,sCAAsC,cAAc,UAAU;AAAA,YAAe,cAAc,OAAO,MAAM;AAAA,iBAAoB,cAAc,YAAY,MAAM;AAAA,sBAAyB,cAAc,iBAAiB,MAAM;AAAA,oBAAuB,cAAc,eAAe,MAAM;AAAA,kBAAqB,cAAc,aAAa,MAAM,KAC1U;AAAA,UACN;AAAA,QACF;AACN,UAAE,KAAK,GAAG,MAAM,SAAI,IAAI,oBAAoB;AAE5C,YAAI,QAAQ,OAAO,OAAO;AACxB,gBAAM,gBAAgB,MAAM;AAC5B,gBAAM,SAAS,OAAO,YAAY,WAAW;AAC7C,gBAAM,UAAU,OAAO,gBAAgB,eAAe;AACtD,gBAAM,aAAa,OAAO,gBAAgB,WAAW;AACrD,gBAAM,SAAS,eACX,OAAO,eAAe,eAAe,IACrC;AACJ,gBAAM,aACJ,oBAAoB,iBAAiB,kBACjC;AAAA,aACG,iBAAiB,kBAAkB,iBAClC;AAAA,UACJ,IACA;AACN,gBAAM,WACJ,kBAAkB,gBAAgB,iBAC9B,QAAQ,gBAAgB,iBAAiB,aAAa,IACtD;AAEN;AAAA,YACE;AAAA,cACE,mBAAmB,SAAS,MAAM,CAAC;AAAA,cACnC,wBAAwB,QAAQ,MAAM,CAAC;AAAA,cACvC,aAAa,QAAQ,UAAU,CAAC;AAAA,cAChC,eAAe,QAAQ,QAAQ,CAAC;AAAA,cAChC,cAAc,SAAS,OAAO,CAAC;AAAA,cAC/B,eAAe,SAAS,UAAU,CAAC;AAAA,cACnC,QAAQ,eACJ,GAAG,IAAI,uBAAuB,SAAS,OAAO,YAAY,CAAC,GAAG,IAC9D,GAAG,IAAI,0BAA0B;AAAA,YACvC,EAAE,KAAK,IAAI;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,UAAE,KAAK,GAAG,IAAI,SAAI,IAAI,oBAAoB;AAC1C,cAAM;AAAA,MACR;AAAA,IACF;AAGA,UAAM,SAASE,gBAAe,OAAO,MAAM;AAG3C,QAAI,cAAc;AAChB,gBAAU;AAAA,QACR;AAAA,QACA,cAAc,OAAO;AAAA,QACrB,cACE,SAAS,SAAS,QAAQ,SAAS,SAAS,eAAe;AAAA,MAC/D,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,OAAO;AAAA,QACbC,sBAAqB,QAAQ,EAAE,eAAe,OAAO,SAAS,EAAE,CAAC,IAC/D;AAAA,MACJ;AAAA,IACF;AAGA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,SAAS,OAAO;AACd,QAAI,QAAQ,WAAW,QAAQ;AAC7B,gBAAU;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,QAAQ,CAAC;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL,eAAS,iBAAiB,QAAQ,MAAM,UAAU,aAAa;AAAA,IACjE;AACA,UAAM,cAAc;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,cAAc;AACtB;;;AM3lBA,SAAS,WAAAC,UAAS,WAAAC,gBAAe;AACjC,SAAS,cAAAC,aAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD;AAAA,EACE;AAAA,EACA,qBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,+BAAAC;AAAA,OACK;AA8DP,SAASC,WAAU,MAAuB;AACxC,QAAM,IAAI,QAAQ,IAAI,IAAI;AAC1B,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM;AACxE;AAEA,SAASC,SAAQ,MAAc,QAAwB;AACrD,MAAI,KAAK,UAAU,OAAQ,QAAO;AAClC,SAAO,KAAK,MAAM,GAAG,MAAM,IAAI,gCAAsB,KAAK,MAAM,CAAC,MAAM;AACzE;AAEA,SAASC,cAAa,SAAkC;AACtD,SAAO,QAAQ,QAAQ,KAAK,KAAKF,WAAU,cAAc;AAC3D;AAEA,SAASG,kBAAiB,SAAkC;AAC1D,SAAO,QAAQ,QAAQ,SAAS,KAAKH,WAAU,mBAAmB;AACpE;AAEA,SAASI,eAAc,SAAwC;AAC7D,QAAM,IAAI,QAAQ,aAAa,QAAQ,IAAI;AAC3C,MAAI,CAAC,EAAG,QAAO;AAEf,MAAI,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM,OAAO;AACxE,WAAOC,SAAQ,QAAQ,IAAI,GAAG,SAAS;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAASC,UAAS,SAAkB,SAAiB,KAAqB;AACxE,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,QAAW;AACrB,YAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,EACjD,OAAO;AACL,QAAI;AACF,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,SAAS,GAAG;AAAA,IACtD,QAAQ;AACN,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,IACjD;AAAA,EACF;AACF;AAEA,eAAe,4BAA4B,SAIkB;AAE3D,MAAI,QAAQ,cAAc,OAAO,QAAQ,eAAe,UAAU;AAChE,WAAO,EAAE,SAAS,QAAQ,YAAY,MAAM,KAAK;AAAA,EACnD;AAGA,MAAI,QAAQ,kBAAkB,OAAO,QAAQ,mBAAmB,UAAU;AACxE,UAAM,IAAI,qBAAqB,QAAQ,gBAAgB,QAAQ,IAAI,CAAC;AACpE,QAAIC,YAAW,CAAC,GAAG;AACjB,aAAO,EAAE,SAAS,MAAMC,gBAAe,CAAC,GAAG,MAAM,EAAE;AAAA,IACrD;AACA,WAAO,EAAE,SAAS,MAAM,MAAM,KAAK;AAAA,EACrC;AAGA,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,OAAO,IAAI,KAAK,GAAG;AACrB,UAAM,IAAI,qBAAqB,IAAI,KAAK,GAAG,QAAQ,IAAI,CAAC;AACxD,QAAID,YAAW,CAAC,GAAG;AACjB,aAAO,EAAE,SAAS,MAAMC,gBAAe,CAAC,GAAG,MAAM,EAAE;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,QAAQ,WAAW;AACrB,UAAM,WAAW,qBAAqB,QAAQ,WAAW,QAAQ,IAAI,CAAC;AACtE,UAAM,QAAQC,6BAA4BC,SAAQ,QAAQ,CAAC;AAC3D,QAAI,MAAO,QAAO,EAAE,SAAS,MAAMF,gBAAe,KAAK,GAAG,MAAM,MAAM;AAAA,EACxE;AAGA,QAAM,UAAUG,oBAAmB,QAAQ,IAAI,CAAC;AAChD,MAAI,QAAS,QAAO,EAAE,SAAS,MAAMH,gBAAe,OAAO,GAAG,MAAM,QAAQ;AAE5E,QAAM,SAASI,mBAAkB,QAAQ,IAAI,CAAC;AAC9C,QAAM,SAASD,oBAAmB,MAAM;AACxC,MAAI,OAAQ,QAAO,EAAE,SAAS,MAAMH,gBAAe,MAAM,GAAG,MAAM,OAAO;AAEzE,SAAO,EAAE,SAAS,MAAM,MAAM,KAAK;AACrC;AAEA,SAAS,qBAAqB,QAAmC;AAC/D,MAAI,OAAO,WAAW,EAAG,QAAO,GAAG,MAAM,kBAAkB;AAC3D,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM;AAC9B,UAAM,OAAO,OAAO,EAAE,SAAS,WAAW,QAAQ,EAAE,IAAI,OAAO;AAC/D,UAAM,MAAM,EAAE,UAAU,IAAI,GAAG,IAAI,IAAI,EAAE,OAAO,GAAG,CAAC,KAAK;AACzD,WAAO,KAAK,IAAI,GAAG,EAAE,OAAO,GAAG,GAAG;AAAA,EACpC,CAAC;AACD,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAsB,QAAQ,SAAwC;AACpE,QAAM,eAAe,QAAQ,WAAW;AACxC,QAAM,MAAMN,cAAa,OAAO;AAChC,QAAM,UAAUC,kBAAiB,OAAO;AACxC,QAAM,UAAUC,eAAc,OAAO;AAErC,MAAI,CAAC,cAAc;AACjB,UAAM,qBAAqB;AAAA,EAC7B;AAEA,MAAI;AACF,IAAAE,UAAS,KAAK,iBAAiB;AAAA,MAC7B,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ,aAAa,eAAe;AAAA,MAChD,YAAY,QAAQ,aAAa,aAAa;AAAA,MAC9C,gBAAgB,QAAQ;AAAA,MACxB,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,MACvB,eAAe,QAAQ;AAAA,MACvB,iBAAiB,QAAQ;AAAA,MACzB,SAAS,QAAQ;AAAA,MACjB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAGD,UAAM,aAAa,MAAM,aAAa;AAAA,MACpC,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ,YACV,qBAAqB,QAAQ,SAAS,IACtC;AAAA,IACN,CAAC;AAED,IAAAA,UAAS,KAAK,4BAA4B;AAAA,MACxC,QAAQ,WAAW;AAAA,MACnB,OAAO,WAAW,MAAM,IAAI,EAAE;AAAA,IAChC,CAAC;AACD,QAAI,SAAS;AACX,MAAAA,UAAS,KAAK,sBAAsB,UAAU;AAAA,IAChD,WAAW,KAAK;AACd,MAAAA,UAAS,KAAK,yBAAyBL,SAAQ,YAAY,GAAG,CAAC;AAAA,IACjE;AAEA,UAAM,gBAAgB,MAAM,4BAA4B;AAAA,MACtD,YAAY,QAAQ;AAAA,MACpB,gBAAgB,QAAQ;AAAA,MACxB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAED,IAAAK,UAAS,KAAK,uBAAuB;AAAA,MACnC,eACE,QAAQ,kBAAkB,QAAQ,aAAa,aAAa;AAAA,MAC9D,oBAAoB,cAAc;AAAA,MAClC,kBAAkB,cAAc,UAC5B,cAAc,QAAQ,SACtB;AAAA,IACN,CAAC;AACD,QAAI,SAAS;AACX,MAAAA,UAAS,KAAK,8BAA8B,cAAc,WAAW,EAAE;AAAA,IACzE,WAAW,OAAO,cAAc,SAAS;AACvC,MAAAA;AAAA,QACE;AAAA,QACA;AAAA,QACAL,SAAQ,cAAc,SAAS,GAAG;AAAA,MACpC;AAAA,IACF;AAEA,QAAI,CAAC,cAAc,WAAW,CAAC,cAAc;AAC3C,iBAAW,4CAA4C;AAAA,IACzD,WAAW,cAAc,QAAQ,CAAC,cAAc;AAC9C,iBAAW,qBAAqB,GAAG,IAAI,cAAc,IAAI,CAAC,EAAE;AAAA,IAC9D;AAGA,UAAM,cAAc,MAAM;AAC1B,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,oBAAoB,YAAY;AAChD,cAAMY,mBAAkB;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AACL,YAAMA,mBAAkB;AAAA,IAC1B;AACA,UAAM,YAAY,MAAM;AAExB,UAAM,SAAS,MAAM,gBAAgB,CAAC,CAAC;AAEvC,UAAM,gBAAgB;AAAA,MACpB,UACE,QAAQ,aACP,QAAQ,YAAY,QAAQ,YAAY,WACzC;AAAA,MACF,eAAe,QAAQ;AAAA,MACvB,eACE,OAAO,QAAQ,kBAAkB,WAC7B,QAAQ,gBACR;AAAA,MACN,iBAAiB,QAAQ,oBAAoB;AAAA,MAC7C,UAAU,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU;AAAA,IAC/D;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,cAAc;AAAA,MACd;AAAA,IACF;AAEA,IAAAP,UAAS,KAAK,4BAA4B;AAAA,MACxC,SAAS;AAAA,MACT,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ,QAAQ,UAAU;AAAA,MAC1B,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO,MAAM,IAAI,EAAE;AAAA,IAClC,CAAC;AAED,QAAI,SAAS;AACX,MAAAA,UAAS,KAAK,qBAAqB,MAAM;AAAA,IAC3C,WAAW,KAAK;AACd,MAAAA,UAAS,KAAK,wBAAwBL,SAAQ,QAAQ,IAAI,CAAC;AAAA,IAC7D;AAGA,QAAI,SAAS;AACX,UAAI;AACF,cAAM,MAAM,oBAAI,KAAK;AACrB,cAAM,YAAY,IAAI,YAAY,EAAE,QAAQ,SAAS,GAAG;AACxD,cAAM,WAAWI,SAAQ,QAAQ,IAAI,GAAG,OAAO;AAC/C,cAAM,WACJ,SAAS,SAAS,OAAO,KAAK,SAAS,SAAS,QAAQ,IACpD,WACAA,SAAQ,UAAU,iBAAiB,SAAS,OAAO;AAEzD,QAAAS,WAAUJ,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,QAAAK;AAAA,UACE;AAAA,UACA,KAAK;AAAA,YACH;AAAA,cACE,SAAS;AAAA,cACT,WAAW,IAAI,YAAY;AAAA,cAC3B,SAAS;AAAA,cACT,SAAS;AAAA,gBACP,WAAW,QAAQ;AAAA,gBACnB,YAAY,QAAQ,aAAa,eAAe;AAAA,gBAChD,YAAY,QAAQ,aAAa,aAAa;AAAA,gBAC9C,gBAAgB,QAAQ;AAAA,gBACxB,oBAAoB,cAAc;AAAA,gBAClC,UAAU,QAAQ;AAAA,gBAClB,eAAe,QAAQ;AAAA,gBACvB,eAAe,QAAQ;AAAA,gBACvB,iBAAiB,QAAQ;AAAA,gBACzB,SAAS,QAAQ;AAAA,gBACjB,OAAO,OAAO,SAAS;AAAA,gBACvB,QAAQ,QAAQ;AAAA,gBAChB,QAAQ,QAAQ;AAAA,cAClB;AAAA,cACA,OAAO;AAAA,gBACL;AAAA,gBACA,aAAa,WAAW,MAAM,IAAI,EAAE;AAAA,cACtC;AAAA,cACA,YAAY,cAAc;AAAA,cAC1B;AAAA,cACA;AAAA,cACA,YAAY;AAAA,gBACV,SAAS;AAAA,gBACT,OAAO,OAAO,SAAS;AAAA,gBACvB,QAAQ;AAAA,gBACR,QAAQ,QAAQ,UAAU;AAAA,cAC5B;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA,QAAAT,UAAS,KAAK,uBAAuB,QAAQ,EAAE;AAAA,MACjD,SAAS,GAAG;AACV,QAAAA;AAAA,UACE;AAAA,UACA;AAAA,UACA,aAAa,QAAQ,EAAE,UAAU;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe;AACnB,QAAI,QAAQ,QAAQ;AAClB,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,cAAc;AACxB,UAAE,MAAM,oBAAoB;AAC5B,YAAI,kBAAkB;AACtB,cAAM,kBAAkB,MAAM;AAC9B,YAAI,eAA8B;AAClC,YAAI,kBAAiC;AACrC,YAAI,iBAAgC;AACpC,YAAI,gBAA+B;AACnC,YAAI,eAA8B;AAClC,YAAI;AACF,yBAAe,MAAM,OAAO,SAAS,QAAQ;AAAA,YAC3C,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,YAAY,CACV,YACA,eACA,OACA,kBACG;AACH,oBAAM,QAAQ,MAAM;AACpB,kBAAI,CAAC,iBAAiB,iBAAiB,OAAQ,gBAAe;AAC9D,kBAAI,eAAe;AACjB,oBAAI,CAAC,gBAAiB,mBAAkB;AACxC,iCAAiB;AAAA,cACnB;AACA,kBAAI,OAAO;AACT,oBAAI,CAAC,cAAe,iBAAgB;AACpC,+BAAe;AAAA,cACjB;AAEA,kBAAI,eAAe;AACjB,oBAAI,CAAC,iBAAiB;AACpB,oCAAkB;AAClB,oBAAE,KAAK,GAAG,IAAI,+BAA+B,CAAC;AAC9C,0BAAQ,OAAO,MAAM,GAAG,IAAI,aAAa,CAAC;AAAA,gBAC5C;AACA,wBAAQ,OAAO,MAAM,aAAa;AAClC;AAAA,cACF;AACA,oBAAM,SAAS;AACf,oBAAM,OACJ,WAAW,SAAS,SAChB,WAAW,MAAM,GAAG,MAAM,IAAI,WAC9B;AACN,gBAAE,QAAQ,cAAc,GAAG,IAAI,QAAQ,KAAK,CAAC,EAAE;AAAA,YACjD;AAAA,UACF,CAAC;AACD,YAAE,KAAK,GAAG,MAAM,SAAI,IAAI,oBAAoB;AAE5C,cAAI,QAAQ,OAAO,OAAO;AACxB,kBAAM,gBAAgB,MAAM;AAC5B,kBAAM,SAAS,OAAO,YAAY,WAAW;AAC7C,kBAAM,UAAU,OAAO,gBAAgB,eAAe;AACtD,kBAAM,aAAa,OAAO,gBAAgB,WAAW;AACrD,kBAAM,SAAS,eACX,OAAO,eAAe,eAAe,IACrC;AACJ,kBAAM,aACJ,oBAAoB,iBAAiB,kBACjC;AAAA,eACG,iBAAiB,kBAAkB,iBAClC;AAAA,YACJ,IACA;AACN,kBAAM,WACJ,kBAAkB,gBAAgB,iBAC9B,QAAQ,gBAAgB,iBAAiB,aAAa,IACtD;AAEN;AAAA,cACE;AAAA,gBACE,mBAAmB,SAAS,MAAM,CAAC;AAAA,gBACnC,wBAAwB,QAAQ,MAAM,CAAC;AAAA,gBACvC,aAAa,QAAQ,UAAU,CAAC;AAAA,gBAChC,eAAe,QAAQ,QAAQ,CAAC;AAAA,gBAChC,cAAc,SAAS,OAAO,CAAC;AAAA,gBAC/B,eAAe,SAAS,UAAU,CAAC;AAAA,cACrC,EAAE,KAAK,IAAI;AAAA,cACX;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,GAAG;AACV,YAAE,KAAK,GAAG,IAAI,SAAI,IAAI,oBAAoB;AAC1C,gBAAM;AAAA,QACR;AAAA,MACF,OAAO;AACL,uBAAe,MAAM,OAAO,SAAS,QAAQ;AAAA,UAC3C,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,YAAY,MAAM;AAAA,UAElB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,qBAAe,MAAM,OAAO,SAAS,QAAQ,EAAE,MAAM,KAAK,CAAC;AAAA,IAC7D;AAEA,UAAM,SAAS,KAAK,MAAM,YAAY;AACtC,UAAM,SAAS,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC;AAE/D,QAAI,cAAc;AAChB,gBAAU,EAAE,OAAO,CAAC;AAAA,IACtB,OAAO;AACL,cAAQ,OAAO,MAAM,qBAAqB,MAAM,IAAI,IAAI;AAAA,IAC1D;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,SAAS,OAAO;AACd,QAAI,cAAc;AAChB,gBAAU;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,QAAQ,CAAC;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL,eAAS,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AAAA,IACpE;AACA,UAAM,cAAc;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,cAAc;AACtB;;;ACleA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,qBAAAU,0BAAyB;AAoBlC,eAAeC,aAA6B;AAC1C,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,QAAI,OAAO;AACX,UAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,MAAM,CAAC;AACnD,OAAG,GAAG,QAAQ,CAAC,SAAS;AACtB,cAAQ;AAAA,IACV,CAAC;AACD,OAAG,GAAG,SAAS,MAAM;AACnB,MAAAA,SAAQ,IAAI;AAAA,IACd,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAsB,YAAY,SAA4C;AAC5E,QAAM,eAAe,QAAQ,WAAW;AAExC,MAAI,CAAC,cAAc;AACjB,UAAM,yBAAyB;AAAA,EACjC;AAEA,MAAI;AAEF,QAAI,YAAY,QAAQ;AACxB,QAAI,CAAC,WAAW;AAEd,UAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,oBAAY,MAAMD,WAAU;AAAA,MAC9B;AAAA,IACF;AAEA,QAAI,CAAC,WAAW;AACd,UAAI,cAAc;AAChB,kBAAU,EAAE,OAAO,qBAAqB,YAAY,CAAC,EAAE,CAAC;AAAA,MAC1D,OAAO;AACL,iBAAS,4DAA4D;AAAA,MACvE;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,WAAW,qBAAqB,SAAS;AAC/C,QAAI,CAAC,UAAU;AACb,UAAI,cAAc;AAChB,kBAAU,EAAE,OAAO,sBAAsB,YAAY,CAAC,EAAE,CAAC;AAAA,MAC3D,OAAO;AACL,iBAAS,2CAA2C;AAAA,MACtD;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,eAAe,cAAc,QAAQ;AAE3C,QAAI,CAAC,cAAc;AACjB,cAAQ,aAAa,GAAG,KAAK,OAAO,YAAY,CAAC,CAAC,WAAW;AAAA,IAC/D;AAGA,QAAI,CAAC,oBAAoB,QAAQ,GAAG;AAClC,YAAME,UAA4B;AAAA,QAChC,YAAY,CAAC;AAAA,QACb;AAAA,QACA,cAAc;AAAA,MAChB;AAEA,UAAI,cAAc;AAChB,kBAAUA,OAAM;AAAA,MAClB,OAAO;AACL,mBAAW,wCAAwC;AAAA,MACrD;AACA;AAAA,IACF;AAGA,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,oBAAoB,YAAY;AAChD,cAAMC,mBAAkB;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AACL,YAAMA,mBAAkB;AAAA,IAC1B;AAGA,QAAI;AACJ,QAAI,cAAc;AAChB,eAAS,MAAM,mBAAmB,UAAU,CAAC,CAAC;AAAA,IAChD,OAAO;AACL,eAAS,MAAM,YAAY,sBAAsB,YAAY;AAC3D,eAAO,MAAM,mBAAmB,UAAU,CAAC,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAGA,QAAI,cAAc;AAChB,gBAAU,MAAM;AAAA,IAClB,OAAO;AACL,cAAQ,IAAI;AACZ,cAAQ,IAAI,4BAA4B,OAAO,UAAU,CAAC;AAE1D,UAAI,OAAO,WAAW,SAAS,GAAG;AAChC;AAAA,UACE,yBAAyB,GAAG,IAAI,OAAO,OAAO,YAAY,IAAI,IAAI,CAAC;AAAA,QACrE;AAAA,MACF,OAAO;AACL;AAAA,UACE,yBAAyB,GAAG,IAAI,OAAO,OAAO,YAAY,IAAI,IAAI,CAAC;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,WAAW,SAAS,GAAG;AAChC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,SAAS,OAAO;AACd,QAAI,cAAc;AAChB,gBAAU;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,YAAY,CAAC;AAAA,MACf,CAAC;AAAA,IACH,OAAO;AACL,eAAS,iBAAiB,QAAQ,MAAM,UAAU,iBAAiB;AAAA,IACrE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AC5JA,SAAS,WAAAC,UAAS,WAAAC,gBAAe;AACjC;AAAA,EACE,sBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,kBAAAC;AAAA,EACA;AAAA,EACA,sBAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,2BAAAC;AAAA,OACK;AAmBP,eAAsB,OAAO,SAAuC;AAClE,QAAM,oBAAoB;AAE1B,MAAI;AACF,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,iBACJ,QAAQ,cAAcC,oBAAmB,WAAW;AAEtD,QAAI,CAAC,gBAAgB;AACnB,eAAS,sBAAsB;AAC/B;AAAA,QACE,UAAU,GAAG;AAAA,UACX;AAAA,QACF,CAAC,4BAA4B,GAAG,KAAK,gBAAgB,CAAC;AAAA,QACtD;AAAA,MACF;AACA,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,qBAAqB,GAAG,IAAI,cAAc,CAAC,EAAE;AAGrD,UAAM,kBAAkB,MAAMC,gBAAe,cAAc;AAC3D,UAAM,gBAAgB,gBAAgB,eAAe;AAGrD,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,YAAY,qBAAqB,YAAY;AAC5D,eAAO,MAAM,SAAS,OAAO;AAAA,MAC/B,CAAC;AAAA,IACH,QAAQ;AACN,eAAS,4DAA4D;AACrE,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,SAAS,GAAG,KAAK,OAAO,SAAS,YAAY,CAAC,CAAC,WAAW;AAElE,UAAM,oBAAoB,QAAQ,YAC9BC,SAAQC,SAAQ,aAAa,QAAQ,SAAS,CAAC,IAC/C;AACJ,UAAM,gBAAgBC,yBAAwB,iBAAiB;AAE/D,QAAI,QAAQ,KAAK;AAEf,YAAM,YAAY,oBAAoB,YAAY;AAChD,cAAMC,mBAAkB;AAAA,MAC1B,CAAC;AAED,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,YAAY;AACV,gBAAM,SAAS,MAAM,gBAAgB,CAAC,CAAC;AACvC,gBAAM,eAAeC,oBAAmB,SAAS,QAAQ;AAAA,YACvD,MAAM,SAAS;AAAA,YACf;AAAA,UACF,CAAC;AACD,iBAAO,MAAM,OAAO,cAAc,cAAc,eAAe;AAAA,QACjE;AAAA,MACF;AAEA,UAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,cAAM,cAAc,OAAO,OAAO,IAAI,CAAC,UAAU;AAC/C,cAAI,OAAO,UAAK,MAAM,OAAO;AAC7B,cAAI,MAAM,YAAY;AACpB,oBAAQ;AAAA,IAAO,GAAG,KAAK,QAAG,CAAC,IAAI,MAAM,UAAU;AAAA,UACjD;AACA,iBAAO;AAAA,QACT,CAAC;AAED;AAAA,UACE,YAAY,KAAK,MAAM;AAAA,UACvB,SAAS,OAAO,OAAO,MAAM;AAAA,QAC/B;AACA,gBAAQ,sDAAsD;AAC9D,cAAM,mBAAmB;AAAA,MAC3B,OAAO;AACL,mBAAW,4BAA4B;AACvC,cAAM,mBAAmB;AAAA,MAC3B;AAAA,IACF,OAAO;AAEL,YAAM,iBAAiB,MAAM,YAAY,kBAAkB,YAAY;AAErE,cAAM,eAAe,IAAI,IAAI,SAAS,OAAO,MAAM;AACnD,mBAAW,MAAM,SAAS,QAAQ,IAAI,SAAS,oBAAoB,GAAG;AACpE,gBAAM,OAAO,EAAE,CAAC,KAAK,IAAI,YAAY;AACrC,cAAI,CAAC,IAAK;AACV,uBAAa,IAAI,MAAM,aAAa,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,QACxD;AAEA,cAAM,iBAAiB,CAAC,GAAG,aAAa,QAAQ,CAAC,EAC9C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,CAAC,KAAK,GAAG,WAAW;AAAA,UACxB,MAAM,SAAS,QAAQ,CAAC;AAAA,UACxB,OAAO,MAAM,YAAY;AAAA,UACzB,OAAO;AAAA,QACT,EAAE;AAEJ,cAAM,gBAAgB;AAAA,UACpB,QAAQ;AAAA,UACR,YAAY,CAAC;AAAA,UACb,SAAS,CAAC;AAAA,UACV,YAAY,CAAC;AAAA,QACf;AAGA,cAAM,cAAc,iBAAiB,eAAe,aAAa;AACjE,eAAO,qBAAqB,WAAW;AAAA,MACzC,CAAC;AAGD,UAAI,mBAAmB,iBAAiB;AACtC,mBAAW,oCAAoC;AAC/C,cAAM,mBAAmB;AACzB;AAAA,MACF;AAGA,YAAM,YAAY,sBAAsB,YAAY;AAClD,cAAM,gBAAgB,gBAAgB,cAAc;AAAA,MACtD,CAAC;AAED,WAAK,YAAY,GAAG,IAAI,cAAc,CAAC,IAAI,SAAS;AACpD,YAAM,sBAAsB;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,aAAS,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AACjE,UAAM,cAAc;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,cAAc;AACtB;;;ACnIA,SAAS,cAAAC,aAAY,YAAAC,WAAU,aAAa,cAAc,aAAAC,YAAW,iBAAAC,sBAAqB;AAC1F,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,UAAS,WAAAC,UAAS,UAAU,QAAAC,OAAM,SAAAC,cAAa;AACxD,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,aAA6B;AACtC;AAAA,EACE,qBAAAC;AAAA,EACA,qBAAqB;AAAA,OAChB;;;AClDP,SAAS,WAAAC,UAAS,QAAAC,OAAM,aAAa;AACrC,SAAS,cAAAC,aAAY,YAAAC,WAAU,aAAAC,YAAW,iBAAAC,sBAAqB;AAC/D;AAAA,EACE,qBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,+BAAAC;AAAA,EACA,kBAAAC;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAiBP,eAAsB,wBACpB,MACwC;AACxC,QAAM,cAAc,KAAK;AACzB,QAAM,WAAW,KAAK,YAAY;AAElC,MAAI,KAAK,YAAY;AACnB,UAAM,gBAAgB,qBAAqB,KAAK,YAAY,WAAW;AACvE,QAAIC,YAAW,aAAa,GAAG;AAC7B,YAAM,OAAOC,UAAS,aAAa;AACnC,UAAI,KAAK,OAAO,GAAG;AACjB,eAAO;AAAA,UACL,oBAAoB;AAAA,UACpB,YAAY,MAAMC,gBAAe,aAAa;AAAA,QAChD;AAAA,MACF;AACA,UAAI,KAAK,YAAY,GAAG;AACtB,cAAM,QAAQC,oBAAmB,aAAa;AAC9C,eAAO;AAAA,UACL,oBAAoB;AAAA,UACpB,YAAY,QAAQ,MAAMD,gBAAe,KAAK,IAAI;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,YAAY,MAAM,oBAAoB,KAAK;AAAA,EACtD;AAEA,QAAM,UAAUE,6BAA4B,QAAQ;AACpD,QAAM,WAAW,WAAWD,oBAAmB,WAAW;AAC1D,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,YAAY,WAAW,MAAMD,gBAAe,QAAQ,IAAI;AAAA,EAC1D;AACF;AAuDA,IAAM,kBAAkB,oBAAI,IAA2B;AAEvD,eAAe,wBAAwB,QAGrB;AAChB,QAAM,MAAM,GAAG,OAAO,OAAO,KAAK,OAAO,KAAK;AAC9C,QAAM,WAAW,gBAAgB,IAAI,GAAG;AACxC,MAAI,SAAU,QAAO;AAErB,QAAM,IAAIG,mBAAkB,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,CAAC,EACzE,KAAK,MAAM,MAAS,EACpB,MAAM,CAAC,MAAM;AAEZ,oBAAgB,OAAO,GAAG;AAC1B,UAAM;AAAA,EACR,CAAC;AACH,kBAAgB,IAAI,KAAK,CAAC;AAC1B,SAAO;AACT;AAEA,SAAS,qBAAqB,QAYnB;AACT,QAAM,oBAAoB;AAAA,IACxB,OAAO;AAAA,IACP,QAAQ,IAAI;AAAA,EACd;AACA,QAAM,YAAY,OAAO,IAAI,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC/D,QAAM,WACJ,kBAAkB,SAAS,OAAO,KAAK,kBAAkB,SAAS,QAAQ,IACtE,oBACA,GAAG,iBAAiB,iBAAiB,SAAS;AAEpD,EAAAC,WAAUC,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,EAAAC;AAAA,IACE;AAAA,IACA,KAAK;AAAA,MACH;AAAA,QACE,SAAS;AAAA,QACT,WAAW,OAAO,IAAI,YAAY;AAAA,QAClC,SAAS,OAAO;AAAA,QAChB,UAAU,OAAO,YAAY;AAAA,QAC7B,QAAQ;AAAA,UACN,aAAa,OAAO,mBAChB,OAAO,OAAO,cACd;AAAA,UACJ,UAAU,OAAO,OAAO;AAAA,UACxB,oBAAoB,OAAO,OAAO;AAAA,UAClC,YAAY,OAAO,mBACf,OAAO,OAAO,aACd;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,kBACpB,MACkC;AAClC,QAAM,cAAc,KAAK,SAAS;AAClC,QAAM,UAAU,KAAK,WAAW;AAEhC,MAAI,aAA4B;AAChC,MAAI,qBAAoC;AAExC,MAAI,KAAK,eAAe,QAAW;AACjC,iBAAa,KAAK;AAClB,yBAAqB,KAAK,sBAAsB;AAAA,EAClD,OAAO;AACL,SAAK,UAAU,yBAAyB;AACxC,UAAM,WAAW,MAAM,wBAAwB;AAAA,MAC7C,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,IACjB,CAAC;AACD,iBAAa,SAAS;AACtB,yBAAqB,SAAS;AAAA,EAChC;AAEA,MAAI,CAAC,KAAK,kBAAkB;AAC1B,SAAK,UAAU,qBAAqB;AACpC,UAAM,wBAAwB,EAAE,OAAO,aAAa,QAAQ,CAAC;AAAA,EAC/D;AAEA,MAAI,KAAK,WAAW;AAClB,yBAAqB;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,KAAK,oBAAI,KAAK;AAAA,MACd,SAAS,EAAE,aAAa,QAAQ;AAAA,MAChC,QAAQ;AAAA,QACN,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,MACA,kBAAkB,QAAQ,KAAK,yBAAyB;AAAA,MACxD,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,QAAM,WACJ,KAAK,YACL,IAAI,eAAe;AAAA,IACjB,SAAS,KAAK;AAAA,IACd;AAAA,EACF,CAAC;AAEH,OAAK,UAAU,aAAa,KAAK,SAAS,MAAM,cAAc;AAC9D,QAAM,SAA+B,MAAM,SAAS;AAAA,IAClD,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,MACE;AAAA,MACA,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,OAAK;AAAA,IACH,SAAS,OAAO,OAAO,MAAM,YAAY,OAAO,YAAY;AAAA,EAC9D;AAEA,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,cAAc,OAAO;AAAA;AAAA,IAErB,QAAS,OAAe;AAAA,IACxB,aAAa,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAuBO,SAAS,0BACd,MAIA;AACA,QAAM,IAAI,MAAM,KAAK,SAAS;AAC9B,QAAM,UAAU,KAAK,WAAWC,MAAK,EAAE,KAAK,GAAG,EAAE,QAAQ,EAAE,IAAI,YAAY;AAE3E,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,wBAAwB;AACnC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,cAAc,EAAE,IAAI,IAAI;AACnC,MAAI,KAAK,MAAO,OAAM,KAAK,cAAc,KAAK,KAAK,IAAI;AACvD,MAAI,OAAO,KAAK,cAAc,UAAU;AACtC,UAAM,KAAK,kBAAkB,IAAI,KAAK,KAAK,SAAS,EAAE,YAAY,CAAC,IAAI;AAAA,EACzE;AACA,MAAI,KAAK,YAAa,OAAM,KAAK,cAAc,KAAK,WAAW,IAAI;AACnE,MAAI,KAAK,QAAS,OAAM,KAAK,uBAAuB,KAAK,OAAO,IAAI;AACpE,MAAI,OAAO,KAAK,mBAAmB;AACjC,UAAM,KAAK,sBAAsB,KAAK,cAAc,MAAM;AAC5D,QAAM,KAAK,mBAAkB,oBAAI,KAAK,GAAE,YAAY,CAAC,IAAI;AACzD,QAAM,KAAK,EAAE;AAEb,MAAI,KAAK,YAAY,OAAO,KAAK,KAAK,QAAQ,EAAE,SAAS,GAAG;AAC1D,UAAM,KAAK,aAAa;AACxB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,SAAS;AACpB,UAAM,KAAK,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,CAAC;AACjD,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,WAAW;AACtB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,SAAS;AACpB,QAAM,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC;AACrC,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AAEb,QAAM,KAAK,iBAAiB;AAC5B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,SAAS;AACpB,QAAM,MAAM,KAAK,eAAe,IAAI,KAAK,CAAC;AAC1C,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AAEb,QAAM,UAAU,MAAM,KAAK,IAAI;AAC/B,EAAAH,WAAUC,SAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C,EAAAC,eAAc,SAAS,SAAS,OAAO;AACvC,SAAO,EAAE,SAAS,QAAQ;AAC5B;;;ADlRA,SAAS,oBAA2C;AAgVpD,SAAS,YAAY,QAAwD;AAC3E,QAAM,EAAE,KAAK,cAAc,IAAI;AAG/B,MAAI,oBAAoB,GAAG,EAAG,QAAO;AAGrC,QAAM,UAAU,0BAA0B,eAAe,EAAE,UAAU,EAAE,CAAC;AACxE,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ,CAAC,EAAG;AAG7C,QAAM,aAAa,QAAQ;AAAA,IACzB,CAAC,MAAM,QAAQ,EAAE,eAAe,IAAI,WAAW,EAAE,cAAc,GAAG;AAAA,EACpE;AACA,MAAI,WAAY,QAAO,WAAW;AAGlC,SAAO,QAAQ,CAAC,EAAG;AACrB;AAMA,SAAS,sBAAsB,aAG7B;AAEA,QAAM,qBAAqBE,MAAK,aAAa,WAAW,eAAe;AACvE,MAAIC,YAAW,kBAAkB,GAAG;AAClC,QAAI;AACF,YAAM,UAAU,aAAa,oBAAoB,OAAO;AACxD,YAAM,WAAW,KAAK,MAAM,OAAO;AACnC,YAAM,QAAQ,SAAS,OAAO;AAC9B,UAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,cAAM,cAAc,MAAM;AAAA,UAAK,CAAC,MAC9B,EAAE,SAAS,SAAS,MAAM,KAAK,EAAE,SAAS,SAAS,OAAO;AAAA,QAC5D;AACA,YAAI,aAAa;AACf,iBAAO,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA,QAC7C;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,kBAAkBD,MAAK,aAAa,WAAW,YAAY;AACjE,MAAIC,YAAW,eAAe,GAAG;AAC/B,QAAI;AACF,YAAM,UAAU,aAAa,iBAAiB,OAAO;AACrD,YAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,UAAI,MAAM,OAAO,eAAe,SAAS,GAAG;AAC1C,eAAO,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA,MAC7C;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,OAAO,UAAU,KAAK;AAC1C;AASA,IAAM,QAAQ,oBAAI,IAAwB;AAG1C,IAAM,kBAAkB,oBAAI,IAAqB;AAsBjD,IAAI,iBAAkE;AAEtE,SAAS,4BAAsE;AAC7E,MAAI,CAAC,gBAAgB;AACnB,qBAAiB,sBAAsB;AAAA,EACzC;AACA,SAAO;AACT;AAGA,IAAI,yBAAyB,QAAQ,IAAI;AAEzC,SAAS,0BAA0B,UAA2B;AAE5D,QAAM,eAAe;AACrB,SAAO,aAAa,KAAK,QAAQ,KAAK,CAAC,SAAS,SAAS,IAAI;AAC/D;AAGA,IAAM,oBAAoB,oBAAI,IAAoB;AAGlD,IAAM,gBAAgB,oBAAI,IAGxB;AAGF,IAAI,cAAgC;AAGpC,IAAI,mBAAmB;AAGvB,IAAM,eAAe,cAAc,YAAY,GAAG;AAQlD,SAAS,gBAAgB,MAAwB;AAC/C,QAAM,SAAmB,CAAC,CAAC;AAC3B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,WAAW,CAAC,MAAM,GAAI,QAAO,KAAK,IAAI,CAAC;AAAA,EAClD;AACA,SAAO;AACT;AAEA,SAAS,kBACP,YACA,OACA,MACA,YACQ;AACR,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,SAAS,GAAG,QAAQ,CAAC,CAAC;AACxE,QAAM,OAAO,WAAW,SAAS,KAAK;AACtC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,YAAY,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AACnE;AAEA,SAAS,qBACP,MACA,aACkB;AAElB,QAAM,EAAE,OAAAC,OAAM,IAAI,aAAa,sCAAsC;AAIrE,QAAM,MAAMA,OAAM,MAAM;AAAA,IACtB,KAAK;AAAA,IACL,OAAO;AAAA,IACP,KAAK;AAAA,IACL,SAAS;AAAA,IACT,uBAAuB;AAAA,EACzB,CAAC;AAED,QAAM,QAA0B,CAAC;AAEjC,WAAS,KAAK,MAAiB;AAC7B,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AAGvC,QAAI,KAAK,SAAS,cAAc;AAC9B,YAAM,QAAQ,KAAK;AACnB,YAAM,UAAU,KAAK;AACrB,YAAM,MAAM,SAAS,KAAK;AAC1B,UACE,SACA,OAAO,MAAM,CAAC,MAAM,YACpB,OAAO,MAAM,CAAC,MAAM,YACpB,OACA,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,WAAW,UACtB;AACA,cAAM,UAAU,GAAG,WAAW,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM;AACxD,cAAM,KAAK,EAAE,OAAO,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,QAAQ,CAAC;AAAA,MACxD;AAAA,IACF;AAEA,eAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,YAAM,QAAS,KAAa,GAAG;AAC/B,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,mBAAW,QAAQ,MAAO,MAAK,IAAI;AAAA,MACrC,WAAW,SAAS,OAAO,UAAU,UAAU;AAC7C,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,OAAK,GAAG;AAGR,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM;AACxD,SAAO;AACT;AAEA,SAAS,oBAAoB,QAMN;AACrB,QAAM,OACJ,OAAO,OAAO,gBAAgB,WAC1B,KAAK,IAAI,GAAG,OAAO,cAAc,CAAC,IAClC;AACN,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA,OAAO;AAAA,EACT;AAGA,aAAW,KAAK,OAAO,OAAO;AAC5B,QAAI,EAAE,SAAS,UAAU,SAAS,EAAE,IAAK,QAAO,EAAE;AAAA,EACpD;AACA,SAAO;AACT;AAKA,IAAM,sBAAsB;AAAA;AAAA,EAE1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,cAAc,UAA0B;AAC/C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,eAAW,OAAO,qBAAqB;AACrC,UAAID,YAAWD,MAAK,KAAK,GAAG,CAAC,EAAG,QAAO;AAAA,IACzC;AACA,QAAIC,YAAWD,MAAK,KAAK,cAAc,CAAC,EAAG,QAAO;AAClD,UAAM,SAASG,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAMA,SAAS,yBACP,kBACA,YACQ;AACR,QAAM,MAAM,qBAAqBC,SAAQ,gBAAgB,CAAC;AAC1D,QAAM,MAAM,qBAAqBA,SAAQ,UAAU,CAAC;AACpD,MAAI,QAAQ,OAAO,IAAI,WAAW,MAAM,GAAG,GAAG;AAC5C,WAAO,qBAAqB,SAAS,KAAK,GAAG,CAAC;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,UAA0B;AAE1D,MAAI,SAAS,WAAW,GAAG,KAAK,kBAAkB,KAAK,QAAQ,GAAG;AAChE,WAAOA,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,SAAS,kBAAkB,IAAI,QAAQ;AAC7C,MAAI,OAAQ,QAAO;AAEnB,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAUA,SAAQ,KAAK,QAAQ;AACrC,MAAIH,YAAW,OAAO,GAAG;AACvB,sBAAkB,IAAI,UAAU,OAAO;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,SAASI,mBAAkB,GAAG;AACpC,QAAM,SAASD,SAAQ,QAAQ,QAAQ;AACvC,MAAIH,YAAW,MAAM,GAAG;AACtB,sBAAkB,IAAI,UAAU,MAAM;AACtC,WAAO;AAAA,EACT;AAIA,aAAW,OAAO,CAAC,QAAQ,UAAU,GAAG;AACtC,UAAM,OAAOD,MAAK,QAAQ,GAAG;AAC7B,QAAI,CAACC,YAAW,IAAI,EAAG;AACvB,QAAI;AACF,YAAM,UAAU,YAAY,MAAM,EAAE,eAAe,KAAK,CAAC;AACzD,iBAAW,OAAO,SAAS;AACzB,YAAI,CAAC,IAAI,YAAY,EAAG;AACxB,cAAM,IAAIG,SAAQ,MAAM,IAAI,MAAM,QAAQ;AAC1C,YAAIH,YAAW,CAAC,GAAG;AACjB,4BAAkB,IAAI,UAAU,CAAC;AACjC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,oBAAkB,IAAI,UAAU,OAAO;AACvC,SAAO;AACT;AAEA,eAAe,oBAAoB,YAAyC;AAC1E,QAAM,SAAS,gBAAgB,IAAI,UAAU;AAC7C,MAAI,OAAQ,QAAO;AAEnB,MAAI;AACF,UAAM,MAAM,cAAcD,MAAK,YAAY,cAAc,CAAC;AAE1D,UAAM,MAAM,IAAI,QAAQ;AACxB,UAAM,aACJ,KAAK,UAAU,KAAK,SAAS,UAAU,KAAK,WAAW;AACzD,QAAI,CAAC,WAAY,QAAO;AAExB,UAAM,SAAS,IAAI,WAAW,EAAE,KAAK,WAAW,CAAC;AACjD,oBAAgB,IAAI,YAAY,MAAM;AACtC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,SACb,UACA,YACsB;AACtB,QAAM,eAAe,yBAAyB,QAAQ;AAGtD,MAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,eAAW,mBAAmB,GAAG,IAAI,YAAY,CAAC,EAAE;AACpD,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,MAAM;AACrB,QAAI;AACF,aAAOK,UAAS,YAAY,EAAE;AAAA,IAChC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AAGH,QAAM,SAAS,MAAM,IAAI,YAAY;AACrC,MAAI,UAAU,OAAO,YAAY,SAAS;AACxC,eAAW,uBAAuB;AAClC,WAAO,OAAO;AAAA,EAChB;AAEA,QAAM,UAAUH,SAAQ,YAAY;AACpC,QAAM,aAAa,cAAc,OAAO;AAExC,aAAW,+BAA+B,GAAG,IAAI,UAAU,CAAC,EAAE;AAE9D,QAAM,SAAS,MAAM,oBAAoB,UAAU;AACnD,MAAI,CAAC,QAAQ;AACX;AAAA,MACE,8CAA8C,GAAG;AAAA,QAC/C;AAAA,MACF,CAAC;AAAA,IACH;AACA,eAAW,uDAAuD;AAClE,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACF,eAAW,mBAAmB;AAC9B,UAAM,UAAU,MAAM,OAAO,UAAU,CAAC,YAAY,CAAC;AACrD,UAAM,WACJ,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,IACvC,QAAQ,CAAC,EAAE,YAAY,CAAC,IACxB,CAAC;AAEP,UAAM,cAAc,yBAAyB,cAAc,UAAU;AACrE,QAAI,QAA0B,CAAC;AAC/B,QAAI,aAAuB,CAAC;AAC5B,QAAI,aAAa;AAEjB,QAAI;AACF,iBAAW,qBAAqB;AAChC,YAAM,OAAO,aAAa,cAAc,OAAO;AAC/C,mBAAa,KAAK;AAClB,mBAAa,gBAAgB,IAAI;AACjC,cAAQ,qBAAqB,MAAM,WAAW;AAC9C,iBAAW,YAAY,MAAM,MAAM,aAAa;AAAA,IAClD,SAAS,GAAG;AAEV,iBAAW,kDAAkD;AAC7D,cAAQ,MAAM,kCAAkC,CAAC;AACjD,cAAQ,CAAC;AACT,mBAAa,CAAC;AACd,mBAAa;AAAA,IACf;AAEA,UAAM,SAAsB,SACzB,OAAO,CAAC,MAAW,OAAO,GAAG,YAAY,QAAQ,EACjD,IAAI,CAAC,MAAW;AACf,YAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AACnD,YAAM,SAAS,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;AACzD,YAAM,gBACJ,MAAM,SAAS,KAAK,WAAW,SAAS,KAAK,aAAa,IACtD,oBAAoB;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,aAAa;AAAA,MACf,CAAC,IACD;AACN,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,SAAS,EAAE;AAAA,QACX,QAAQ,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;AAAA,QAClD,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAEH,UAAM,cAAc,OAAO,OAAO,CAAC,MAAM,QAAQ,EAAE,OAAO,CAAC,EAAE;AAC7D,QAAI,OAAO,SAAS,GAAG;AACrB;AAAA,QACE,UAAU,WAAW,IAAI,OAAO,MAAM;AAAA,MACxC;AAAA,IACF;AAEA,UAAM,IAAI,cAAc,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,EAAE,CAAC;AAClE,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,CAAC;AAAA,EACV;AACF;AAKA,SAAS,YAAY,IAAe,SAA8B;AAChE,MAAI,GAAG,eAAe,UAAU,MAAM;AACpC,OAAG,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,EACjC;AACF;AAKA,eAAe,cAAc,IAAe,MAA6B;AACvE,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,IAAI;AAAA,EAC3B,QAAQ;AACN;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,eAAe,QAAQ,SAAS,gBAAgB;AACnE,UAAM,KAAM,QAAgB;AAC5B,UAAM,MAAO,QAAgB;AAC7B;AAAA,MACE,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC,GAC5D,MAAM,IAAI,GAAG,IAAI,QAAQ,GAAG,GAAG,CAAC,KAAK,EACvC;AAAA,IACF;AAAA,EACF,WAAW,QAAQ,SAAS,kBAAkB;AAC5C,YAAQ,GAAG,GAAG,IAAI,MAAM,CAAC,mBAAmB,GAAG,IAAI,QAAQ,QAAQ,CAAC,EAAE;AAAA,EACxE,WAAW,QAAQ,SAAS,oBAAoB;AAC9C;AAAA,MACE,GAAG,GAAG,IAAI,MAAM,CAAC,qBAAqB,GAAG;AAAA,QACvC,QAAQ,YAAY;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF,WAAW,QAAQ,SAAS,kBAAkB;AAAA,EAE9C,WAAW,QAAQ,SAAS,gBAAgB;AAAA,EAE5C,WAAW,QAAQ,SAAS,cAAc;AAAA,EAE1C,WAAW,QAAQ,SAAS,mBAAmB;AAC7C,UAAM,MAAO,QAAkC;AAC/C;AAAA,MACE,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,iBAAiB,CAAC,IAAI,GAAG,IAAI,QAAQ,KAAK,CAAC,GACtE,MAAM,IAAI,GAAG,IAAI,QAAQ,GAAG,GAAG,CAAC,KAAK,EACvC;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,aAAa;AAChB,YAAM,EAAE,UAAU,UAAU,IAAI;AAChC,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAED,YAAM,YAAY,KAAK,IAAI;AAC3B,YAAM,WAAW,yBAAyB,QAAQ;AAClD,UAAI,CAACF,YAAW,QAAQ,GAAG;AACzB,cAAM,MAAM,QAAQ,IAAI;AACxB,cAAM,SAASI,mBAAkB,GAAG;AACpC;AAAA,UACE;AAAA,YACE,GAAG,GAAG,IAAI,MAAM,CAAC;AAAA,YACjB,eAAe,GAAG,IAAI,QAAQ,CAAC;AAAA,YAC/B,eAAe,GAAG,IAAI,QAAQ,CAAC;AAAA,YAC/B,eAAe,GAAG,IAAI,GAAG,CAAC;AAAA,YAC1B,eAAe,GAAG,IAAI,MAAM,CAAC;AAAA,YAC7B,2CAA2C,GAAG;AAAA,cAC5C;AAAA,YACF,CAAC,gBAAgB,GAAG,IAAI,SAAS,CAAC;AAAA,UACpC,EAAE,KAAK,IAAI;AAAA,QACb;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,SAAS,UAAU,CAAC,UAAU;AACjD,oBAAY,IAAI,EAAE,MAAM,iBAAiB,UAAU,WAAW,MAAM,CAAC;AAAA,MACvE,CAAC;AAED,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B;AAAA,QACE,GAAG,GAAG,IAAI,MAAM,CAAC,mBAAmB,GAAG,IAAI,QAAQ,CAAC,WAAM,GAAG;AAAA,UAC3D,GAAG,OAAO,MAAM;AAAA,QAClB,CAAC,aAAa,GAAG,IAAI,IAAI,OAAO,KAAK,CAAC;AAAA,MACxC;AAEA,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,SAAS,OAAO,MAAM,YAAY,OAAO;AAAA,MAClD,CAAC;AACD,kBAAY,IAAI,EAAE,MAAM,eAAe,UAAU,WAAW,OAAO,CAAC;AACpE;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,EAAE,UAAU,SAAS,UAAU,IAAI;AACzC,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAED,YAAM,YAAY,KAAK,IAAI;AAC3B,YAAM,SAAS,MAAM,SAAS,UAAU,CAAC,UAAU;AACjD,oBAAY,IAAI,EAAE,MAAM,iBAAiB,UAAU,WAAW,MAAM,CAAC;AAAA,MACvE,CAAC;AAGD,YAAM,iBAAiB,OAAO;AAAA,QAC5B,CAAC,UAAU,MAAM,YAAY;AAAA,MAC/B;AAEA,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,SAAS,eAAe,MAAM,YAAY,OAAO;AAAA,MAC1D,CAAC;AACD,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK,kBAAkB;AACrB,YAAM,EAAE,SAAS,IAAI;AACrB,YAAM,eAAe,yBAAyB,QAAQ;AAGtD,UAAI,cAAc,cAAc,IAAI,YAAY;AAChD,UAAI,CAAC,aAAa;AAChB,sBAAc,oBAAI,IAAI;AACtB,sBAAc,IAAI,cAAc,WAAW;AAG3C,YAAI,aAAa;AACf,sBAAY,IAAI,YAAY;AAAA,QAC9B;AAAA,MACF;AACA,kBAAY,IAAI,EAAE,IAAI,gBAAgB,SAAS,CAAC;AAChD;AAAA,IACF;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,EAAE,SAAS,IAAI;AACrB,UAAI,UAAU;AACZ,cAAM,eAAe,yBAAyB,QAAQ;AACtD,cAAM,OAAO,YAAY;AAAA,MAC3B,OAAO;AACL,cAAM,MAAM;AAAA,MACd;AACA;AAAA,IACF;AAAA,IAEA,KAAK,kBAAkB;AACrB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI;AACJ;AAAA,QACE,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,gBAAgB,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,GAC7D,YAAY,IAAI,GAAG,IAAI,QAAQ,SAAS,GAAG,CAAC,KAAK,EACnD;AAAA,MACF;AAEA,kBAAY,IAAI;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAED,YAAM,YAAY,KAAK,IAAI;AAC3B,YAAM,WAAW,0BAA0B;AAE3C,UAAI;AACF,cAAM,kBACJ,OAAO,eAAe,WAAW,OAAO,WAAW,UAAU,IAAI;AACnE,cAAM,gBACJ,OAAQ,SAAiB,aAAa,aAChC,SAAiB,SAAS,IAC5B;AACN,cAAM,kBACJ,OAAQ,SAAiB,eAAe,aAClC,SAAiB,WAAW,IAC9B;AACN;AAAA,UACE;AAAA,YACE,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC;AAAA,YACrC,mBAAmB,GAAG,IAAI,KAAK,CAAC;AAAA,YAChC,mBAAmB,GAAG,IAAI,aAAa,QAAQ,CAAC;AAAA,YAChD,mBAAmB,GAAG,IAAI,OAAO,SAAS,MAAM,CAAC,CAAC;AAAA,YAClD,mBAAmB,GAAG;AAAA,cACpB,aAAa,GAAG,KAAK,MAAM,kBAAkB,IAAI,CAAC,OAAO;AAAA,YAC3D,CAAC;AAAA,YACD,qBAAqB,GAAG,IAAI,kBAAkB,QAAQ,CAAC;AAAA,YACvD,mBAAmB,GAAG,IAAI,mBAAmB,WAAW,CAAC;AAAA,YACzD,mBAAmB,GAAG,IAAI,iBAAiB,WAAW,CAAC;AAAA,UACzD,EAAE,KAAK,IAAI;AAAA,QACb;AAEA,YAAI,CAAC,YAAY;AACf,sBAAY,IAAI;AAAA,YACd,MAAM;AAAA,YACN;AAAA,YACA,QAAQ,CAAC;AAAA,YACT,cAAc,KAAK,IAAI,IAAI;AAAA,YAC3B,OAAO;AAAA,YACP;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAEA,cAAM,SAAS,MAAM,kBAAkB;AAAA,UACrC,aAAa;AAAA,UACb;AAAA,UACA,aAAa;AAAA;AAAA,UAEb,SAAS;AAAA,UACT,OAAO;AAAA,UACP;AAAA,UACA,SAAS,CAAC,UAAU;AAClB,wBAAY,IAAI;AAAA,cACd,MAAM;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAGD,YAAI,OAAO,mBAAmB,YAAY,eAAe,SAAS,GAAG;AACnE,cAAI,CAAC,0BAA0B,cAAc,GAAG;AAC9C;AAAA,cACE,wDAAwD,GAAG;AAAA,gBACzD;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF,OAAO;AACL,kBAAM,iBAAiBL;AAAA,cACrB;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,kBAAM,YAAYA,MAAK,gBAAgB,cAAc;AACrD,gBAAI;AACF,kBAAI,CAACC,YAAW,SAAS,GAAG;AAC1B;AAAA,kBACE,2DAA2D,GAAG;AAAA,oBAC5D;AAAA,kBACF,CAAC;AAAA,gBACH;AAAA,cACF,OAAO;AACL,sBAAM,SAAS,0BAA0B;AAAA,kBACvC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,aAAa,OAAO;AAAA,kBACpB,SAAS,OAAO;AAAA,kBAChB,gBAAgB,OAAO;AAAA,kBACvB,QAAQ,OAAO,UAAU;AAAA,kBACzB,aAAa,OAAO,eAAe;AAAA,kBACnC,UAAU;AAAA,oBACR,gBAAgBC,OAAM,SAAS,EAAE;AAAA,oBACjC,SAAS;AAAA,oBACT,kBAAkB,SAAS;AAAA,oBAC3B,WAAW,aAAa;AAAA,kBAC1B;AAAA,gBACF,CAAC;AACD;AAAA,kBACE,GAAG,GAAG,IAAI,MAAM,CAAC,wBAAwB,GAAG;AAAA,oBAC1C,OAAO;AAAA,kBACT,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,YACF,SAAS,GAAG;AACV;AAAA,gBACE,qCAAqC,GAAG,IAAI,cAAc,CAAC,KACzD,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAC3C;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAU,KAAK,IAAI,IAAI;AAC7B;AAAA,UACE,GAAG,GAAG,IAAI,MAAM,CAAC,wBAAwB,GAAG,IAAI,KAAK,CAAC,WAAM,GAAG;AAAA,YAC7D,GAAG,OAAO,OAAO,MAAM;AAAA,UACzB,CAAC,aAAa,GAAG,IAAI,IAAI,OAAO,KAAK,CAAC;AAAA,QACxC;AAEA,YAAI,OAAO,aAAa;AACtB;AAAA,YACE,GAAG,GAAG,IAAI,MAAM,CAAC,uBAAuB,GAAG;AAAA,cACzC,GAAG,OAAO,YAAY,MAAM;AAAA,YAC9B,CAAC;AAAA,UACH;AAAA,QACF;AAEA,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,cAAc,OAAO;AAAA,UACrB;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,cAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,cAAM,QAAQ,iBAAiB,QAAQ,MAAM,QAAQ;AACrD;AAAA,UACE;AAAA,YACE;AAAA,YACA,gBAAgB,KAAK;AAAA,YACrB,gBAAgB,aAAa,QAAQ;AAAA,YACrC,gBAAgB,YAAY;AAAA,YAC5B,QAAQ;AAAA,EAAa,KAAK,KAAK;AAAA,UACjC,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,QACd;AAEA,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,QAAQ,CAAC;AAAA,UACT,cAAc,KAAK,IAAI,IAAI;AAAA,UAC3B,OAAO;AAAA,UACP;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,EAAE,UAAU,IAAI;AACtB;AAAA,QACE,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,cAAc,CAAC,GAAG,YAAY,IAAI,GAAG,IAAI,QAAQ,SAAS,GAAG,CAAC,KAAK,EAAE;AAAA,MACpG;AAEA,UAAI;AACF,cAAM,WAAW,0BAA0B;AAC3C,cAAM,QACJ,OAAQ,SAAiB,aAAa,aACjC,SAAiB,SAAS,IAC3B;AAEN,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN,WAAW;AAAA,UACX;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN,WAAW;AAAA,UACX;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AACjB,YAAM,EAAE,KAAK,MAAM,IAAI;AACvB,sBAAgB,KAAK,KAAK;AAC1B;AAAA,IACF;AAAA,IAEA,KAAK,mBAAmB;AACtB,YAAM,EAAE,QAAQ,UAAU,SAAS,UAAU,IAAI;AACjD,0BAAoB,IAAI,QAAQ,UAAU,SAAS,SAAS;AAC5D;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,EAAE,UAAU,UAAU,IAAI;AAChC,YAAM,eAAe,yBAAyB,QAAQ;AAEtD,UAAI,CAACD,YAAW,YAAY,GAAG;AAC7B,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,OAAO;AAAA,UACP;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,UAAI;AACF,cAAM,UAAU,aAAa,cAAc,OAAO;AAClD,cAAM,aAAa,QAAQ,MAAM,IAAI,EAAE;AACvC,cAAM,eAAe,yBAAyB,cAAc,sBAAsB;AAElF,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAChD;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,EAAE,UAAU,IAAI;AACtB,UAAI;AACF,cAAM,eAAeD,MAAK,wBAAwB,YAAY,qBAAqB;AAEnF,YAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,sBAAY,IAAI;AAAA,YACd,MAAM;AAAA,YACN,OAAO;AAAA,YACP;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAEA,cAAM,eAAe,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AACnE,gBAAQ,GAAG,GAAG,IAAI,MAAM,CAAC,oBAAoB,GAAG,IAAI,GAAG,OAAO,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC,EAAE;AAElG,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW,KAAK,IAAI;AAAA,UACpB;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,cAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,iBAAS,GAAG,GAAG,IAAI,MAAM,CAAC,mBAAmB,YAAY,EAAE;AAC3D,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN,OAAO;AAAA,UACP;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IAEA,KAAK,mBAAmB;AACtB,YAAM,EAAE,SAAS,OAAO,WAAW,UAAU,IAAI;AAEjD,UAAI;AAEF,YAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,sBAAY,IAAI;AAAA,YACd,MAAM;AAAA,YACN,OAAO;AAAA,YACP;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAEA,cAAM,iBAAiB;AACvB,YAAI,CAAC,eAAe,KAAK,OAAO,GAAG;AACjC,sBAAY,IAAI;AAAA,YACd,MAAM;AAAA,YACN,OAAO;AAAA,YACP;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAGA,cAAM,aAAa,QAAQ,QAAQ,gBAAgB,EAAE;AAGrD,cAAM,iBAAiB,MACpB,QAAQ,OAAO,EAAE,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,mBAAmB,GAAG,KAC5B;AAGL,cAAM,WAAW,UAAU,SAAS,IAAI,cAAc;AAGtD,YAAI,CAAC,0BAA0B,QAAQ,GAAG;AACxC,sBAAY,IAAI;AAAA,YACd,MAAM;AAAA,YACN,OAAO,kCAAkC,QAAQ;AAAA,YACjD;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAGA,cAAM,iBAAiBD,MAAK,wBAAwB,WAAW,aAAa;AAC5E,YAAI,CAACC,YAAW,cAAc,GAAG;AAC/B,UAAAM,WAAU,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAAA,QAC/C;AAGA,cAAM,YAAYP,MAAK,gBAAgB,QAAQ;AAC/C,cAAM,cAAc,OAAO,KAAK,YAAY,QAAQ;AACpD,QAAAQ,eAAc,WAAW,WAAW;AAGpC,cAAM,kBAAkB,SAAS,QAAQ,UAAU,OAAO;AAC1D,cAAM,cAAcR,MAAK,gBAAgB,eAAe;AACxD,cAAM,cAAc;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC;AACA,QAAAQ,eAAc,aAAa,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAE/D;AAAA,UACE,GAAG,GAAG,IAAI,MAAM,CAAC,qBAAqB,GAAG,IAAI,QAAQ,CAAC,IAAI,GAAG;AAAA,YAC3D,IAAI,KAAK,MAAM,YAAY,SAAS,IAAI,CAAC;AAAA,UAC3C,CAAC;AAAA,QACH;AAGA,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,cAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,iBAAS,GAAG,GAAG,IAAI,MAAM,CAAC,qBAAqB,YAAY,EAAE;AAC7D,oBAAY,IAAI;AAAA,UACd,MAAM;AAAA,UACN,OAAO;AAAA,UACP;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,iBAAiB,IAAqB;AAE7C,aAAW,CAAC,UAAU,WAAW,KAAK,cAAc,QAAQ,GAAG;AAC7D,eAAW,SAAS,aAAa;AAC/B,UAAI,MAAM,OAAO,IAAI;AACnB,oBAAY,OAAO,KAAK;AAAA,MAC1B;AAAA,IACF;AACA,QAAI,YAAY,SAAS,GAAG;AAC1B,oBAAc,OAAO,QAAQ;AAE7B,UAAI,aAAa;AACf,oBAAY,QAAQ,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,iBAAiB,UAAwB;AAChD,QAAM,cAAc,cAAc,IAAI,QAAQ;AAC9C,MAAI,CAAC,eAAe,YAAY,SAAS,EAAG;AAG5C,QAAM,OAAO,QAAQ;AAGrB,aAAW,EAAE,IAAI,eAAe,KAAK,aAAa;AAChD,gBAAY,IAAI,EAAE,MAAM,gBAAgB,UAAU,eAAe,CAAC;AAAA,EACpE;AACF;AAKA,SAAS,yBAAyB,UAAwB;AACxD,MAAI;AACF,UAAM,eAAe,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;AAC/D,YAAQ,GAAG,GAAG,IAAI,MAAM,CAAC,qBAAqB,GAAG,IAAI,GAAG,OAAO,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC,EAAE;AAEnG,cAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,aAAS,GAAG,GAAG,IAAI,MAAM,CAAC,kCAAkC,YAAY,EAAE;AAC1E,cAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO,4BAA4B,YAAY;AAAA,IACjD,CAAC;AAAA,EACH;AACF;AAGA,IAAM,cAAc,oBAAI,IAAqB;AAG7C,IAAI,sBAAsB,oBAAI,IAAe;AAK7C,SAAS,sBAAsB,KAAa,OAAsB;AAChE,QAAM,UAA+B,EAAE,MAAM,iBAAiB,KAAK,MAAM;AACzE,aAAW,MAAM,qBAAqB;AACpC,gBAAY,IAAI,OAAO;AAAA,EACzB;AACF;AAKA,SAAS,gBAAgB,KAAa,OAAsB;AAC1D,cAAY,IAAI,KAAK,KAAK;AAC1B,UAAQ,GAAG,GAAG,IAAI,MAAM,CAAC,eAAe,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,IAAI,KAAK,UAAU,KAAK,CAAC,CAAC,EAAE;AACzF,wBAAsB,KAAK,KAAK;AAClC;AAKA,SAAS,0BACP,QACA,UACA,SACM;AACN,QAAM,UAAoC;AAAA,IACxC,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,MAAM,qBAAqB;AACpC,gBAAY,IAAI,OAAO;AAAA,EACzB;AACF;AAKA,SAAS,UAAU,SAA8B;AAC/C,aAAW,MAAM,qBAAqB;AACpC,gBAAY,IAAI,OAAO;AAAA,EACzB;AACF;AAGA,IAAI,aAAa;AACjB,IAAI,iBAAwC;AAC5C,IAAM,sBAAsB,oBAAI,IAAY;AAM5C,eAAe,qBAAqB,SAAgC;AAClE,MAAI,YAAY;AAEd;AAAA,EACF;AAEA,eAAa;AACb,UAAQ,GAAG,GAAG,KAAK,8BAA8B,CAAC,EAAE;AACpD,YAAU,EAAE,MAAM,4BAA4B,CAAC;AAE/C,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAC3D,UAAM,SAAS,MAAM,eAAe,SAAS;AAAA,MAC3C,YAAY,CAAC,SAAS,SAAS,UAAU;AAEvC,YAAI,YAAY,UAAa,UAAU,QAAW;AAChD,kBAAQ,KAAK,OAAO,KAAK,OAAO,IAAI,KAAK,GAAG;AAAA,QAC9C,OAAO;AACL,kBAAQ,KAAK,OAAO,EAAE;AAAA,QACxB;AAEA,kBAAU;AAAA,UACR,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED;AAAA,MACE,GAAG,GAAG,MAAM,iBAAiB,CAAC,IAAI,OAAO,WAAW,YAAY,OAAO,KAAK,WAAW,OAAO,QAAQ,cAAc,OAAO,OAAO,iBAAiB,OAAO,WAAW,KAAM,QAAQ,CAAC,CAAC;AAAA,IACvL;AACA,cAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,MAChB,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,IACnB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,aAAS,iBAAiB,GAAG,EAAE;AAC/B,cAAU,EAAE,MAAM,6BAA6B,OAAO,IAAI,CAAC;AAAA,EAC7D,UAAE;AACA,iBAAa;AAAA,EACf;AACF;AAKA,SAAS,gBAAgB,SAAiB,UAAwB;AAEhE,MAAI,CAAC,iBAAiB,KAAK,QAAQ,EAAG;AAEtC,sBAAoB,IAAI,QAAQ;AAEhC,MAAI,eAAgB,cAAa,cAAc;AAC/C,mBAAiB,WAAW,YAAY;AACtC,UAAM,QAAQ,oBAAoB;AAClC,wBAAoB,MAAM;AAC1B,YAAQ,GAAG,GAAG,IAAI,WAAW,KAAK,qCAAqC,CAAC,EAAE;AAC1E,UAAM,qBAAqB,OAAO;AAAA,EACpC,GAAG,GAAI;AACT;AAGA,IAAI,sBAAsB;AAK1B,SAAS,sBAAsB,SAA0B;AACvD,QAAM,mBAAmB,qBAAqB,OAAO;AACrD,MAAI,CAAC,iBAAkB,QAAO;AAE9B,QAAM,cAAc,0BAA0B,gBAAgB;AAC9D,QAAM,iBAAiB,YAAY,IAAI,uBAAuB;AAC9D,MAAI,CAAC,eAAgB,QAAO;AAG5B,SAAO,eAAe,aAAa;AACrC;AASA,eAAe,kBAAkB,SAAgC;AAC/D,MAAI,oBAAqB;AAEzB,wBAAsB;AAEtB,MAAI;AAEF,QAAI,CAAC,sBAAsB,OAAO,GAAG;AACnC,cAAQ,GAAG,GAAG,IAAI,iDAAiD,CAAC,EAAE;AACtE;AAAA,IACF;AAGA,UAAM,QAAQ,oBAAoB,OAAO;AAGzC,QAAI,CAAC,yBAAyB,KAAK,GAAG;AACpC,cAAQ,GAAG,GAAG,IAAI,6BAA6B,CAAC,EAAE;AAClD;AAAA,IACF;AAGA,YAAQ,GAAG,GAAG,KAAK,4BAA4B,CAAC,EAAE;AAClD,cAAU,EAAE,MAAM,uBAAuB,CAAC;AAG1C,UAAM,qBAAqB,QAAQ,IAAI,iCAAiC;AACxE,UAAM,YAAY,QAAQ,IAAI,+BAA+B;AAE7D,UAAM,SAAS,MAAM,gBAAgB;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,CAAC,SAAS,UAAU;AAC9B,gBAAQ,KAAK,OAAO,EAAE;AACtB,kBAAU,EAAE,MAAM,2BAA2B,SAAS,MAAM,CAAC;AAAA,MAC/D;AAAA,IACF,CAAC;AAED,QAAI,OAAO,OAAO;AAEhB,iBAAW,+CAA+C,OAAO,KAAK,EAAE;AAAA,IAC1E,OAAO;AACL,YAAM,QAAQ,CAAC;AACf,UAAI,OAAO,aAAc,OAAM,KAAK,mBAAmB;AACvD,UAAI,OAAO,eAAgB,OAAM,KAAK,iBAAiB;AACvD,UAAI,OAAO,SAAU,OAAM,KAAK,WAAW;AAC3C,UAAI,OAAO,kBAAmB,OAAM,KAAK,oBAAoB;AAE7D;AAAA,QACE,GAAG,GAAG,MAAM,oBAAoB,CAAC,IAAI,MAAM,KAAK,IAAI,CAAC,QAAQ,OAAO,WAAW,KAAM,QAAQ,CAAC,CAAC;AAAA,MACjG;AAAA,IACF;AAEA,cAAU;AAAA,MACR,MAAM;AAAA,MACN,GAAG;AAAA,IACL,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,aAAS,gCAAgC,GAAG,EAAE;AAC9C,cAAU,EAAE,MAAM,wBAAwB,OAAO,IAAI,CAAC;AAAA,EACxD,UAAE;AACA,0BAAsB;AAAA,EACxB;AACF;AAMA,SAAS,oBACP,IACA,QACA,UACA,SACA,WACM;AACN;AAAA,IACE,GAAG,GAAG,IAAI,MAAM,CAAC,oBAAoB,GAAG,KAAK,MAAM,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC,GACzE,UAAU,kBAAkB,EAC9B;AAAA,EACF;AAGA,QAAM,aAAa,qBAAqB,sBAAsB;AAC9D,MAAI,CAAC,YAAY;AACf,UAAM,QAAQ,kCAAkC,sBAAsB;AACtE,aAAS,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE;AACrC,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AACD;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAE9C,aAAS,yBAAyB,YAAY,QAAQ,UAAU,OAAO;AAAA,EACzE,OAAO;AAEL,aAAS,2BAA2B,YAAY,QAAQ,QAAQ;AAAA,EAClE;AAEA,MAAI,OAAO,SAAS;AAClB;AAAA,MACE,GAAG,GAAG,IAAI,MAAM,CAAC,YAAY,GAAG,KAAK,UAAU,MAAM,EAAE,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC;AAAA,IACjF;AAGA,oBAAgB,MAAM;AACtB,UAAM,MAAM;AAGZ,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAGD,8BAA0B,QAAQ,UAAU,OAAO;AAAA,EACrD,OAAO;AACL,aAAS,GAAG,GAAG,IAAI,MAAM,CAAC,2BAA2B,OAAO,KAAK,EAAE;AACnE,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAO,OAAO;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAKA,eAAsB,MAAM,SAAsC;AAChE,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAASH,mBAAkB,GAAG;AACpC,QAAM,UAAU,YAAY,EAAE,KAAK,eAAe,OAAO,CAAC;AAC1D,2BAAyB;AACzB,UAAQ,mBAAmB,GAAG,IAAI,MAAM,CAAC,EAAE;AAC3C,UAAQ,oBAAoB,GAAG,IAAI,OAAO,CAAC,EAAE;AAC7C,UAAQ,mBAAmB,GAAG,IAAI,GAAG,CAAC,EAAE;AAGxC,gBAAc,MAAM,CAAC,GAAG;AAAA,IACtB,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAED,cAAY,GAAG,UAAU,CAAC,SAAS;AACjC,UAAM,eAAeD,SAAQ,IAAI;AAGjC,QAAI,aAAa,SAAS,qBAAqB,GAAG;AAChD,+BAAyB,YAAY;AACrC;AAAA,IACF;AAEA,qBAAiB,YAAY;AAE7B,oBAAgB,SAAS,YAAY;AAAA,EACvC,CAAC;AAGD,QAAM,eAAeJ,MAAK,SAAS,YAAY,qBAAqB;AACpE,MAAIC,YAAW,YAAY,GAAG;AAC5B,gBAAY,IAAI,YAAY;AAC5B,YAAQ,sBAAsB,GAAG,IAAI,YAAY,CAAC,EAAE;AAAA,EACtD;AAGA,QAAM,MAAM,IAAI,gBAAgB,EAAE,KAAK,CAAC;AAIxC,uBAAqB,OAAO,EAAE,MAAM,CAAC,QAAQ;AAC3C,aAAS,qCAAqC,IAAI,OAAO,EAAE;AAAA,EAC7D,CAAC;AAID,oBAAkB,OAAO,EAAE,MAAM,CAAC,QAAQ;AAExC,eAAW,+BAA+B,IAAI,OAAO,EAAE;AAAA,EACzD,CAAC;AAED,MAAI,GAAG,cAAc,CAAC,OAAO;AAC3B,wBAAoB;AACpB,wBAAoB,IAAI,EAAE;AAC1B,YAAQ,qBAAqB,gBAAgB,SAAS;AAGtD,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN;AAAA,MACA,eAAe;AAAA,MACf,WAAW;AAAA,IACb,CAAC;AAGD,UAAM,WAAW,sBAAsB,OAAO;AAC9C,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,SAAS,SAAS;AACpB,cAAQ,GAAG,GAAG,IAAI,MAAM,CAAC,iCAAiC,GAAG,KAAK,SAAS,QAAS,CAAC,EAAE;AAAA,IACzF;AAGA,UAAM,mBAAmB,qBAAqB,OAAO;AACrD,UAAM,qBAAqB,mBACvB,0BAA0B,gBAAgB,IAC1C,oBAAI,IAAuF;AAI/F,gBAAY,IAAI;AAAA,MACd,MAAM;AAAA,MACN,OAAO,aACJ,OAAO,CAAC,SAAS,mBAAmB,IAAI,KAAK,EAAE,CAAC,EAChD,IAAI,CAAC,SAAS;AACb,cAAM,gBAAgB,mBAAmB,IAAI,KAAK,EAAE;AACpD,eAAO;AAAA,UACL,IAAI,KAAK;AAAA,UACT,MAAM,KAAK;AAAA,UACX,aAAa,KAAK;AAAA,UAClB,UAAU,KAAK;AAAA,UACf,iBAAiB,KAAK;AAAA,UACtB,iBAAiB,eAAe;AAAA,UAChC,gBAAgB,eAAe;AAAA,UAC/B,MAAM,KAAK;AAAA,UACX,cAAc,KAAK;AAAA,UACnB,gBAAgB,KAAK;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACL,CAAC;AAGD,eAAW,CAAC,KAAK,KAAK,KAAK,aAAa;AACtC,kBAAY,IAAI,EAAE,MAAM,iBAAiB,KAAK,MAAM,CAAC;AAAA,IACvD;AAEA,OAAG,GAAG,WAAW,CAAC,SAAS;AACzB,oBAAc,IAAI,KAAK,SAAS,CAAC;AAAA,IACnC,CAAC;AAED,OAAG,GAAG,SAAS,MAAM;AACnB,yBAAmB,KAAK,IAAI,GAAG,mBAAmB,CAAC;AACnD,0BAAoB,OAAO,EAAE;AAC7B,cAAQ,wBAAwB,gBAAgB,SAAS;AACzD,uBAAiB,EAAE;AAAA,IACrB,CAAC;AAED,OAAG,GAAG,SAAS,CAAC,UAAU;AACxB,eAAS,oBAAoB,MAAM,OAAO,EAAE;AAAA,IAC9C,CAAC;AAAA,EACH,CAAC;AAED,MAAI,GAAG,SAAS,CAAC,UAAU;AACzB,aAAS,iBAAiB,MAAM,OAAO,EAAE;AAAA,EAC3C,CAAC;AAED;AAAA,IACE,sCAAsC,GAAG,KAAK,kBAAkB,IAAI,EAAE,CAAC;AAAA,EACzE;AACA,UAAQ,sBAAsB;AAG9B,QAAM,IAAI,QAAc,CAACG,aAAY;AACnC,YAAQ,GAAG,UAAU,MAAM;AACzB,cAAQ,kBAAkB;AAC1B,UAAI,MAAM;AACV,mBAAa,MAAM;AACnB,MAAAA,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;;;AE35DA,SAAS,WAAAK,UAAS,WAAAC,UAAS,QAAAC,aAAY;AACvC;AAAA,EACE,cAAAC;AAAA,EAEA,gBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AACP;AAAA,EACE,qBAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,+BAAAC;AAAA,OAGK;AAsDP,SAASC,WAAU,MAAuB;AACxC,QAAM,IAAI,QAAQ,IAAI,IAAI;AAC1B,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM;AACxE;AAEA,SAASC,SAAQ,MAAc,QAAwB;AACrD,MAAI,KAAK,UAAU,OAAQ,QAAO;AAClC,SAAO,KAAK,MAAM,GAAG,MAAM,IAAI,gCAAsB,KAAK,MAAM,CAAC,MAAM;AACzE;AAEA,SAASC,cAAa,SAAiC;AACrD,SAAO,QAAQ,QAAQ,KAAK,KAAKF,WAAU,cAAc;AAC3D;AAEA,SAASG,kBAAiB,SAAiC;AACzD,SAAO,QAAQ,QAAQ,SAAS,KAAKH,WAAU,mBAAmB;AACpE;AAEA,SAASI,eAAc,SAAuC;AAC5D,QAAM,IAAI,QAAQ,aAAa,QAAQ,IAAI;AAC3C,MAAI,CAAC,EAAG,QAAO;AAEf,MAAI,MAAM,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE,YAAY,MAAM,OAAO;AACxE,WAAOC,SAAQ,QAAQ,IAAI,GAAG,SAAS;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAASC,UAAS,SAAkB,SAAiB,KAAqB;AACxE,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,QAAW;AACrB,YAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,EACjD,OAAO;AACL,QAAI;AACF,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,SAAS,GAAG;AAAA,IACtD,QAAQ;AACN,cAAQ,MAAM,GAAG,IAAI,gBAAgB,GAAG,OAAO;AAAA,IACjD;AAAA,EACF;AACF;AAEA,SAAS,0BAA0B,UAAiC;AAClE,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,YAAYC,MAAK,KAAK,WAAW,aAAa;AACpD,QAAIC,YAAW,SAAS,EAAG,QAAO;AAClC,UAAM,SAASC,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAUA,SAAS,uBAAuB,SAA6C;AAC3E,MAAI,CAACD,YAAW,OAAO,EAAG,QAAO,CAAC;AAClC,QAAM,UAAUE,aAAY,OAAO,EAChC,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC,EACjC,IAAI,CAAC,MAAMH,MAAK,SAAS,CAAC,CAAC;AAE9B,QAAM,MAAkC,CAAC;AACzC,aAAW,KAAK,SAAS;AACvB,QAAI;AACF,YAAM,OAAO,aAAkB,CAAC;AAChC,YAAM,SAAS,MAAM,QAAQ,MAAM,MAAM,IACrC,KAAK,SACL,MAAM,gBAAgB;AAC1B,UAAI,KAAK;AAAA,QACP,MAAM;AAAA,QACN,UACE,MAAM,YAAY,MAAM,kBAAkB,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AAAA,QAClE,WACE,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QACzD,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;AAAA,QACtD,YAAY,MAAM,QAAQ,MAAM,IAAI,OAAO,SAAS;AAAA,MACtD,CAAC;AAAA,IACH,QAAQ;AACN,UAAI,KAAK;AAAA,QACP,MAAM;AAAA,QACN,UAAU,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AAAA,MAClC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,KAAK,CAAC,GAAG,MAAM;AACjB,UAAM,KAAK,EAAE,aAAa;AAC1B,UAAM,KAAK,EAAE,aAAa;AAC1B,QAAI,OAAO,GAAI,QAAO,KAAK;AAC3B,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AAED,SAAO;AACT;AAEA,SAAS,kBAAkB,WAGzB;AACA,QAAM,QAAQI,cAAa,SAAS;AACpC,SAAO,EAAE,QAAQ,MAAM,SAAS,QAAQ,GAAG,WAAW,MAAM,WAAW;AACzE;AAEA,SAAS,aAAgB,UAAqB;AAC5C,QAAM,MAAMA,cAAa,UAAU,OAAO;AAC1C,SAAO,KAAK,MAAM,GAAG;AACvB;AAEA,SAAS,iBAAiB,QAA+B;AACvD,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SACE,OACG,IAAI,CAAC,MAAM;AACV,UAAM,MAAM,EAAE,YAAY;AAC1B,UAAM,MAAM,EAAE,YAAY;AAC1B,UAAM,QAAQ,EAAE,UAAU,KAAK,EAAE,OAAO,MAAM;AAC9C,WAAO,MAAM,GAAG,IAAI,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK;AAAA,EAC/C,CAAC,EACA,KAAK,IAAI,IAAI;AAEpB;AAEA,eAAsB,OAAO,SAAuC;AAClE,QAAM,eAAe,QAAQ,WAAW;AACxC,QAAM,MAAMT,cAAa,OAAO;AAChC,QAAM,UAAUC,kBAAiB,OAAO;AACxC,QAAM,UAAUC,eAAc,OAAO;AAErC,MAAI,CAAC,aAAc,OAAM,8BAA8B;AAEvD,MAAI;AACF,UAAM,cAAc,QAAQ,IAAI;AAGhC,QAAI,QAAQ,MAAM;AAChB,YAAM,QACH,QAAQ,iBACL,qBAAqB,QAAQ,gBAAgB,WAAW,IACxD,SAAS,0BAA0B,WAAW;AAEpD,UAAI,CAAC,MAAM;AACT,YAAI,cAAc;AAChB,oBAAU,EAAE,gBAAgB,MAAM,UAAU,CAAC,EAAE,CAAC;AAAA,QAClD,OAAO;AACL;AAAA,YACE;AAAA,UACF;AAAA,QACF;AACA,cAAM,cAAc;AACpB;AAAA,MACF;AAEA,YAAM,WAAW,uBAAuB,IAAI;AAC5C,UAAI,cAAc;AAChB,kBAAU,EAAE,gBAAgB,MAAM,SAAS,CAAC;AAAA,MAC9C,OAAO;AACL,gBAAQ,oBAAoB,GAAG,IAAI,IAAI,CAAC,EAAE;AAC1C,YAAI,SAAS,WAAW,GAAG;AACzB,kBAAQ,OAAO,MAAM,sBAAsB;AAAA,QAC7C,OAAO;AACL,kBAAQ,OAAO;AAAA,YACb,SACG,IAAI,CAAC,GAAG,QAAQ;AACf,oBAAM,QAAQ,EAAE,YACZ,IAAI,KAAK,EAAE,SAAS,EAAE,eAAe,IACrC;AACJ,oBAAM,QAAQ,EAAE,QAAQ,IAAI,GAAG,IAAI,EAAE,KAAK,CAAC,KAAK;AAChD,oBAAM,QACJ,OAAO,EAAE,eAAe,WACpB,IAAI,GAAG,IAAI,IAAI,EAAE,UAAU,UAAU,CAAC,KACtC;AACN,qBAAO,GAAG,QAAQ,IAAI,MAAM,GAAG,IAAI,EAAE,IAAI,GAAG,GAAG;AAAA,gBAC7C,WAAM,KAAK;AAAA,cACb,CAAC,GAAG,KAAK,GAAG,KAAK;AAAA,YACnB,CAAC,EACA,KAAK,IAAI,IAAI;AAAA,UAClB;AACA,kBAAQ,OAAO;AAAA,YACb,GAAG;AAAA,cACD;AAAA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM,cAAc;AACpB;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,QACtB,qBAAqB,QAAQ,OAAO,WAAW,IAC/C;AACJ,UAAM,cAAc,QAAQ,UACxB,qBAAqB,QAAQ,SAAS,WAAW,IACjD;AACJ,UAAM,mBAAmB,QAAQ,eAC7B,qBAAqB,QAAQ,cAAc,WAAW,IACtD;AAEJ,QAAI,CAAC,aAAa,CAAC,aAAa;AAC9B,UAAI,cAAc;AAChB,kBAAU,EAAE,OAAO,qBAAqB,QAAQ,CAAC,EAAE,CAAC;AAAA,MACtD,OAAO;AACL,iBAAS,8CAA8C;AAAA,MACzD;AACA,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,aAAa,CAACI,YAAW,SAAS,GAAG;AACvC,YAAM,IAAI,MAAM,oBAAoB,SAAS,EAAE;AAAA,IACjD;AACA,QAAI,eAAe,CAACA,YAAW,WAAW,GAAG;AAC3C,YAAM,IAAI,MAAM,sBAAsB,WAAW,EAAE;AAAA,IACrD;AACA,QAAI,oBAAoB,CAACA,YAAW,gBAAgB,GAAG;AACrD,YAAM,IAAI,MAAM,4BAA4B,gBAAgB,EAAE;AAAA,IAChE;AAGA,UAAM,UAAU,cACZ,aAOG,WAAW,IACd;AAEJ,UAAM,aACJ,QAAQ,UACP,OAAO,SAAS,UAAU,WAAW,QAAQ,QAAQ,YACrD,cAAc,SAAS,WAAW,MAAM;AAG3C,QAAI,WAAqC;AACzC,QAAI,QAAQ,cAAc;AACxB,iBAAW,KAAK,MAAM,QAAQ,YAAY;AAAA,IAC5C,WAAW,kBAAkB;AAC3B,iBAAW,aAAgC,gBAAgB;AAAA,IAC7D,WAAW,WAAW,MAAM,QAAQ,QAAQ,QAAQ,GAAG;AACrD,iBAAW,QAAQ;AAAA,IACrB;AAEA,QAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,QAAI,aAA4B;AAChC,QAAI,qBAAoC;AACxC,UAAM,aACH,aAAa,eAAe,oBAAoB,WAAc;AAEjE;AACE,YAAM,WAAW,MAAM,wBAAwB;AAAA,QAC7C;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,UAAU,YAAYC,SAAQ,SAAS,IAAI;AAAA,MAC7C,CAAC;AACD,mBAAa,SAAS;AACtB,2BAAqB,SAAS;AAAA,IAChC;AAEA,QAAI,sBAAsB,YAAY;AACpC,UAAI,CAAC;AACH,mBAAW,qBAAqB,GAAG,IAAI,kBAAkB,CAAC,EAAE;AAAA,IAChE,WAAW,CAAC,cAAc,CAAC,cAAc;AACvC,iBAAW,qBAAqB;AAChC;AAAA,QACE;AAAA,UACE,gBAAgB,QAAQ,cAAc,WAAW;AAAA,UACjD;AAAA,UACA;AAAA,UACA,GAAGG,kBAAiB,IAAI,CAAC,MAAM,YAAO,CAAC,EAAE;AAAA,UACzC;AAAA,UACA,UAAU,GAAG;AAAA,YACX;AAAA,UACF,CAAC,sBAAsB,GAAG,KAAK,gBAAgB,CAAC;AAAA,QAClD,EAAE,KAAK,IAAI;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,IAAAN,UAAS,KAAK,6BAA6B;AAAA,MACzC,WAAW,aAAa;AAAA,MACxB,aAAa,eAAe;AAAA,MAC5B,cAAc,oBAAoB;AAAA,MAClC,kBAAkB,SAAS;AAAA,MAC3B,OAAO;AAAA,MACP;AAAA,MACA,kBAAkB,aAAa,WAAW,SAAS;AAAA,IACrD,CAAC;AAGD,UAAM,cAAc,QAAQ,SAASO;AACrC,UAAM,cAAc,MAAM;AAC1B,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,oBAAoB,YAAY;AAChD,cAAMC,mBAAkB;AAAA,UACtB,OAAO;AAAA,UACP,SAAS,QAAQ;AAAA,QACnB,CAAC;AAAA,MACH,CAAC;AAAA,IACH,OAAO;AACL,YAAMA,mBAAkB,EAAE,OAAO,aAAa,SAAS,QAAQ,QAAQ,CAAC;AAAA,IAC1E;AACA,UAAM,YAAY,MAAM;AAGxB,UAAM,oBACJ,cACC,MAAM;AAEL,YAAM,iBACJ,OAAO,SAAS,mBAAmB,WAC/B,QAAQ,iBACR,OAAO,SAAS,aAAa,WAC7B,QAAQ,WACR;AACN,UAAI,CAAC,eAAgB,QAAO;AAC5B,YAAM,UAAU,cAAcL,SAAQ,WAAW,IAAI;AACrD,YAAM,MAAMJ,SAAQ,SAAS,cAAc;AAC3C,aAAO;AAAA,IACT,GAAG;AAEL,QAAI,CAAC,mBAAmB;AACtB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAACG,YAAW,iBAAiB,GAAG;AAClC,YAAM,IAAI,MAAM,oBAAoB,iBAAiB,EAAE;AAAA,IACzD;AAEA,UAAM,EAAE,QAAQ,UAAU,IAAI,kBAAkB,iBAAiB;AACjE,IAAAF,UAAS,KAAK,gBAAgB;AAAA,MAC5B,WAAW;AAAA,MACX;AAAA,MACA,cAAc,OAAO;AAAA,IACvB,CAAC;AAED,QAAI,WAAW,YAAY;AACzB,MAAAA,UAAS,KAAK,qBAAqB,UAAU;AAAA,IAC/C,WAAW,OAAO,YAAY;AAC5B,MAAAA,UAAS,KAAK,wBAAwBL,SAAQ,YAAY,GAAG,CAAC;AAAA,IAChE;AAGA,QAAI,SAKO;AAEX,UAAM,kBAAkB,MAAM;AAC9B,QAAI,eAA8B;AAClC,QAAI,kBAAiC;AACrC,QAAI,iBAAgC;AACpC,QAAI,gBAA+B;AACnC,QAAI,eAA8B;AAElC,QAAI,cAAc;AAChB,eAAS,MAAM,kBAAkB;AAAA,QAC/B,aAAa;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB,OAAO;AAAA,QACP,kBAAkB;AAAA,QAClB,WAAW,WAAW;AAAA,QACtB,2BAA2B;AAAA,QAC3B,mBAAmB;AAAA,UACjB,OAAO;AAAA,UACP,WAAW;AAAA,UACX,gBAAgB;AAAA,UAChB,mBAAmB,OAAO;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,UAAI,QAAQ,QAAQ;AAClB,YAAI,aAAa;AACjB,YAAI,iBAAiB;AACrB,YAAI,aAAa;AACjB,iBAAS,MAAM,kBAAkB;AAAA,UAC/B,aAAa;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,SAAS,QAAQ;AAAA,UACjB,OAAO;AAAA,UACP,kBAAkB;AAAA,UAClB,WAAW,WAAW;AAAA,UACtB,2BAA2B;AAAA,UAC3B,mBAAmB;AAAA,YACjB,OAAO;AAAA,YACP,WAAW;AAAA,YACX,gBAAgB;AAAA,YAChB,mBAAmB,OAAO;AAAA,UAC5B;AAAA,UACA,YAAY,CACV,YACA,eACA,OACA,kBACG;AACH,kBAAM,QAAQ,MAAM;AACpB,gBAAI,CAAC,iBAAiB,iBAAiB,OAAQ,gBAAe;AAC9D,gBAAI,eAAe;AACjB,kBAAI,CAAC,gBAAiB,mBAAkB;AACxC,+BAAiB;AAAA,YACnB;AACA,gBAAI,OAAO;AACT,kBAAI,CAAC,cAAe,iBAAgB;AACpC,6BAAe;AAAA,YACjB;AAEA,gBAAI,eAAe;AACjB,kBAAI,CAAC,gBAAgB;AACnB,iCAAiB;AACjB,wBAAQ,MAAM,GAAG,IAAI,qBAAqB,CAAC;AAC3C,wBAAQ,OAAO,MAAM,GAAG,IAAI,aAAa,CAAC;AAC1C,6BAAa;AAAA,cACf,WAAW,CAAC,YAAY;AACtB,wBAAQ,OAAO,MAAM,GAAG,IAAI,iBAAiB,CAAC;AAC9C,6BAAa;AAAA,cACf;AACA,sBAAQ,OAAO,MAAM,aAAa;AAClC;AAAA,YACF;AAGA,gBAAI,OAAO;AACT,kBAAI,CAAC,gBAAgB;AACnB,iCAAiB;AACjB,wBAAQ,MAAM,GAAG,IAAI,qBAAqB,CAAC;AAAA,cAC7C;AACA,kBAAI,YAAY;AACd,wBAAQ,OAAO,MAAM,GAAG,IAAI,eAAe,CAAC;AAC5C,6BAAa;AAAA,cACf;AAEA,sBAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,YACF;AAGA,kBAAM,QAAQ,cAAc,IAAI,KAAK;AACrC,gBAAI,CAAC,QAAQ,SAAS,WAAY;AAClC,yBAAa;AACb,oBAAQ,MAAM,GAAG,IAAI,UAAU,GAAG,IAAI;AAAA,UACxC;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,iBAAS,MAAM;AAAA,UACb;AAAA,UACA,OAAO,MAAM;AACX,mBAAO,MAAM,kBAAkB;AAAA,cAC7B,aAAa;AAAA,cACb;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,SAAS,QAAQ;AAAA,cACjB,OAAO;AAAA,cACP,kBAAkB;AAAA,cAClB,WAAW,WAAW;AAAA,cACtB,2BAA2B;AAAA,cAC3B,mBAAmB;AAAA,gBACjB,OAAO;AAAA,gBACP,WAAW;AAAA,gBACX,gBAAgB;AAAA,gBAChB,mBAAmB,OAAO;AAAA,cAC5B;AAAA,cACA,YAAY,CACV,YACA,eACA,OACA,kBACG;AACH,sBAAM,QAAQ,MAAM;AACpB,oBAAI,CAAC,iBAAiB,iBAAiB;AACrC,iCAAe;AACjB,oBAAI,eAAe;AACjB,sBAAI,CAAC,gBAAiB,mBAAkB;AACxC,mCAAiB;AAAA,gBACnB;AACA,oBAAI,OAAO;AACT,sBAAI,CAAC,cAAe,iBAAgB;AACpC,iCAAe;AAAA,gBACjB;AAEA,sBAAM,SAAS;AACf,sBAAM,cACJ,WAAW,SAAS,SAChB,WAAW,MAAM,GAAG,MAAM,IAAI,WAC9B;AACN,kBAAE,QAAQ,cAAc,GAAG,IAAI,eAAe,KAAK,CAAC,EAAE;AAAA,cACxD;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM;AAE5B,UAAM,SAAS,QAAQ,UAAU,CAAC;AAElC,QAAI,cAAc;AAChB,gBAAU;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,cAAc,QAAQ,gBAAgB;AAAA,QACtC,WAAW;AAAA,QACX,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE;AACtC,cAAQ,UAAU,GAAG,IAAI,WAAW,CAAC,EAAE;AACvC,cAAQ,OAAO,MAAM,iBAAiB,MAAM,CAAC;AAG7C,UAAI,QAAQ,OAAO,OAAO;AACxB,cAAM,SAAS,OAAO,YAAY,WAAW;AAC7C,cAAM,UAAU,OAAO,gBAAgB,eAAe;AACtD,cAAM,aAAa,OAAO,gBAAgB,WAAW;AACrD,cAAM,SAAS,eACX,OAAO,eAAe,eAAe,IACrC;AACJ,cAAM,aACJ,oBAAoB,iBAAiB,kBACjC;AAAA,WACG,iBAAiB,kBAAkB,iBAClC;AAAA,QACJ,IACA;AACN,cAAM,WACJ,kBAAkB,gBAAgB,iBAC9B,QAAQ,gBAAgB,iBAAiB,aAAa,IACtD;AAEN;AAAA,UACE;AAAA,YACE,mBAAmB,SAAS,MAAM,CAAC;AAAA,YACnC,wBAAwB,QAAQ,MAAM,CAAC;AAAA,YACvC,aAAa,QAAQ,UAAU,CAAC;AAAA,YAChC,eAAe,QAAQ,QAAQ,CAAC;AAAA,YAChC,cAAc,SAAS,OAAO,CAAC;AAAA,YAC/B,eAAe,SAAS,UAAU,CAAC;AAAA,YACnC,QAAQ,eACJ,GAAG,IAAI,uBAAuB,SAAS,OAAO,YAAY,CAAC,GAAG,IAC9D,GAAG,IAAI,0BAA0B;AAAA,UACvC,EAAE,KAAK,IAAI;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACF,gCAA0B;AAAA,QACxB,WAAW;AAAA,QACX,OAAO;AAAA,QACP;AAAA,QACA,SAAS,QAAQ,WAAW;AAAA,QAC5B,gBAAgB,QAAQ,gBAAgB;AAAA,QACxC,QAAQ,QAAQ,UAAU;AAAA,QAC1B,aAAa,QAAQ,eAAe;AAAA,QACpC,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB;AAAA,QACF;AAAA,MACF,CAAC;AACD,MAAAK,UAAS,KAAK,yCAAyC;AAAA,IACzD,SAAS,GAAG;AACV,MAAAA;AAAA,QACE;AAAA,QACA;AAAA,QACA,aAAa,QAAQ,EAAE,UAAU;AAAA,MACnC;AAAA,IACF;AAGA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,cAAc;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,SAAS,OAAO;AACd,QAAI,QAAQ,WAAW,QAAQ;AAC7B,gBAAU;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,QAAQ,CAAC;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL;AAAA,QACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACF;AACA,UAAM,cAAc;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc;AACtB;;;ACvqBA,SAAS,aAAAS,kBAAiB;AAQ1B,SAAS,cACP,OACsD;AAEtD,QAAM,UAAgC;AAAA,IACpC,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAEA,MAAI,QAAQ,KAAK,GAAG;AAClB,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AAGA,QAAM,QAAQ,MAAM,MAAM,eAAe;AACzC,MAAI,OAAO;AACT,WAAO,EAAE,GAAG,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,MAAM,CAAC,GAAG,EAAE,EAAE;AAAA,EAChE;AAEA,SAAO;AACT;AAGA,SAAS,iBAAiB,QAA0C;AAElE,QAAM,YAAsD;AAAA,IAC1D,cAAc,EAAE,GAAG,KAAK,GAAG,GAAG;AAAA,IAC9B,YAAY,EAAE,GAAG,IAAI,GAAG,GAAG;AAAA,IAC3B,aAAa,EAAE,GAAG,KAAK,GAAG,GAAG;AAAA,IAC7B,iBAAiB,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,IAClC,eAAe,EAAE,GAAG,IAAI,GAAG,IAAI;AAAA,IAC/B,gBAAgB,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EACnC;AACA,SAAO,UAAU,MAAM,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG;AAC9C;AAGA,SAAS,gBAAgB,OAGhB;AAEP,QAAM,QAAQ,MAAM,MAAM,4BAA4B;AACtD,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,QAAQ,MAAM,CAAC;AAAA,IACf,UAAU,MAAM,CAAC;AAAA,EACnB;AACF;AAGA,SAAS,iBAAiB,YAAqE;AAC7F,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,UAAU;AACpC,QAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAC1E,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,kBACb,MACA,KACA,OACkB;AAClB,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,MAAM,kBAAkB,IAAI;AAClC,UAAM,KAAK,IAAIC,WAAU,GAAG;AAC5B,QAAI,WAAW;AAEf,UAAM,UAAU,WAAW,MAAM;AAC/B,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,WAAG,MAAM;AACT,QAAAD,SAAQ,KAAK;AAAA,MACf;AAAA,IACF,GAAG,GAAI;AAEP,OAAG,GAAG,QAAQ,MAAM;AAClB,YAAM,UAAU,KAAK,UAAU,EAAE,MAAM,cAAc,KAAK,MAAM,CAAC;AACjE,SAAG,KAAK,OAAO;AAGf,iBAAW,MAAM;AACf,YAAI,CAAC,UAAU;AACb,qBAAW;AACX,uBAAa,OAAO;AACpB,aAAG,MAAM;AACT,UAAAA,SAAQ,IAAI;AAAA,QACd;AAAA,MACF,GAAG,GAAG;AAAA,IACR,CAAC;AAED,OAAG,GAAG,SAAS,MAAM;AACnB,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,qBAAa,OAAO;AACpB,QAAAA,SAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAe,sBACb,MACA,QACA,UACA,SAC+C;AAC/C,SAAO,IAAI,QAAQ,CAACA,aAAY;AAC9B,UAAM,MAAM,kBAAkB,IAAI;AAClC,UAAM,KAAK,IAAIC,WAAU,GAAG;AAC5B,QAAI,WAAW;AACf,UAAM,YAAY,OAAO,KAAK,IAAI,CAAC;AAEnC,UAAM,UAAU,WAAW,MAAM;AAC/B,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,WAAG,MAAM;AACT,QAAAD,SAAQ,EAAE,SAAS,OAAO,OAAO,oBAAoB,CAAC;AAAA,MACxD;AAAA,IACF,GAAG,GAAK;AAER,OAAG,GAAG,QAAQ,MAAM;AAClB,YAAM,UAAU,KAAK,UAAU;AAAA,QAC7B,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,SAAG,KAAK,OAAO;AAAA,IACjB,CAAC;AAED,OAAG,GAAG,WAAW,CAAC,SAAiB;AACjC,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC;AACtC,YAAI,IAAI,SAAS,wBAAwB,IAAI,cAAc,WAAW;AACpE,cAAI,CAAC,UAAU;AACb,uBAAW;AACX,yBAAa,OAAO;AACpB,eAAG,MAAM;AACT,YAAAA,SAAQ;AAAA,cACN,SAAS,IAAI;AAAA,cACb,OAAO,IAAI;AAAA,YACb,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAED,OAAG,GAAG,SAAS,MAAM;AACnB,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,qBAAa,OAAO;AACpB,QAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,mBAAmB,CAAC;AAAA,MACvD;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAe,UACb,KACA,OACA,MACA,UACe;AACf,UAAQ,KAAK;AAAA,IACX,KAAK,YAAY;AACf,YAAM,SAAS,cAAc,KAAK;AAClC,UAAI,CAAC,QAAQ;AACX;AAAA,UACE,2BAA2B,KAAK;AAAA;AAAA,QAElC;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,UAAI;AACJ,UAAI,YAAY,QAAQ;AACtB,mBAAW,iBAAiB,OAAO,MAAM;AACzC,gBAAQ,iBAAiB,OAAO,MAAM,aAAQ,SAAS,CAAC,KAAK,SAAS,CAAC,GAAG;AAAA,MAC5E,OAAO;AACL,mBAAW;AAAA,MACb;AAEA,YAAM,UAAU,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,SAAS;AACX;AAAA,UACE,kCAAkC,SAAS,CAAC,KAAK,SAAS,CAAC;AAAA,QAC7D;AAAA,MACF,OAAO;AACL;AAAA,UACE;AAAA,iBACoB,GAAG,KAAK,kBAAkB,CAAC;AAAA,QACjD;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS,gBAAgB,KAAK;AACpC,UAAI,CAAC,QAAQ;AACX;AAAA,UACE,wBAAwB,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAM/B;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAGA,YAAM,UAAU,iBAAiB,QAAQ;AACzC,UAAI,YAAY,CAAC,SAAS;AACxB;AAAA,UACE,yBAAyB,QAAQ;AAAA;AAAA,QAEnC;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA;AAAA,QACE,iBAAiB,OAAO,MAAM,QAAQ,OAAO,QAAQ,MAClD,UAAU,kBAAkB,KAAK,UAAU,OAAO,CAAC,KAAK;AAAA,MAC7D;AAEA,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,MACF;AAEA,UAAI,OAAO,SAAS;AAClB;AAAA,UACE,SAAS,OAAO,MAAM,YAAY,OAAO,QAAQ,MAC9C,UAAU,kBAAkB;AAAA,QACjC;AAAA,MACF,OAAO;AACL;AAAA,UACE,OAAO,SACL;AAAA,iBACoB,GAAG,KAAK,kBAAkB,CAAC;AAAA,QACnD;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA;AACE,eAAS,uBAAuB,GAAG,EAAE;AACrC,cAAQ,gCAAgC;AACxC,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAKA,eAAe,UAAU,KAAa,OAA8B;AAClE,UAAQ,KAAK;AAAA,IACX,KAAK;AACH;AAAA,QACE;AAAA;AAAA;AAAA,MAGF;AACA;AAAA,IAEF;AACE,eAAS,uBAAuB,GAAG,EAAE;AACrC,cAAQ,0BAA0B;AAClC,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAKA,eAAsBE,QACpB,QACA,KACA,OACA,UACA,UAAyB,CAAC,GACX;AACf,QAAM,OAAO,QAAQ,QAAQ;AAE7B,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,UAAI,CAAC,OAAO;AACV,iBAAS,gCAAgC,GAAG,EAAE;AAC9C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,UAAU,KAAK,OAAO,MAAM,QAAQ;AAC1C;AAAA,IAEF,KAAK;AACH,YAAM,UAAU,KAAK,IAAI;AACzB;AAAA,IAEF;AACE,eAAS,mBAAmB,MAAM,EAAE;AACpC,cAAQ,wDAAwD;AAChE,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;;;ACvWA,SAAS,WAAAC,gBAAe;;;ACAxB,SAAS,eAAe;AAExB,OAAOC,YAAW;AAClB,OAAO,SAAS;AAET,SAAS,eAAwB;AACtC,SAAO,IAAI,QAAQ,OAAO,EACvB,YAAY,+CAA+C,EAC3D,OAAO,WAAW,4BAA4B,EAC9C,OAAO,kBAAkB,6CAA6C,EACtE;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,KAAa,SAAmB,CAAC,GAAG,MAAM,GAAG;AAAA,IAC9C,CAAC;AAAA,EACH,EACC,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,YAAY;AACzB,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAE3D,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,QAAQ,WAAW;AAElC,QAAI;AACJ,QAAI,CAAC,QAAQ;AACX,gBAAU,IAAI,yBAAyB,EAAE,MAAM;AAAA,IACjD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,eAAe,aAAa;AAAA,QAC/C,OAAO,QAAQ;AAAA,QACf,OAAO,QAAQ;AAAA,QACf,SAAS,QAAQ;AAAA,QACjB,YAAY,CAAC,SAAS,SAAS,UAAU;AACvC,cAAI,SAAS;AACX,gBAAI,WAAW,OAAO;AACpB,sBAAQ,OAAO,GAAG,OAAO,KAAK,OAAO,IAAI,KAAK;AAAA,YAChD,OAAO;AACL,sBAAQ,OAAO;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAED,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,MAC7C,OAAO;AACL,iBAAS,QAAQA,OAAM,MAAM,gBAAgB,CAAC;AAC9C,gBAAQ,IAAI;AACZ,gBAAQ,IAAIA,OAAM,KAAK,mBAAmB,CAAC;AAC3C,gBAAQ,IAAI,qBAAqB,OAAO,KAAK,EAAE;AAC/C,gBAAQ,IAAI,qBAAqB,OAAO,QAAQ,EAAE;AAClD,gBAAQ,IAAI,qBAAqB,OAAO,OAAO,EAAE;AACjD,gBAAQ,IAAI,qBAAqB,OAAO,WAAW,EAAE;AACrD,gBAAQ,IAAI,sBAAsB,OAAO,WAAW,KAAM,QAAQ,CAAC,CAAC,GAAG;AAAA,MACzE;AAAA,IACF,SAAS,OAAO;AACd,UAAI,SAAS;AACX,gBAAQ,KAAKA,OAAM,IAAI,cAAc,CAAC;AAAA,MACxC;AACA,YAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;;;ACtEA,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,YAAW;AAGX,SAAS,cAAuB;AACrC,SAAO,IAAIF,SAAQ,MAAM,EACtB,YAAY,gDAAgD,EAC5D;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACC,OAAO,kBAAkB,mCAAmC,QAAQ,EACpE,OAAO,iBAAiB,mCAAmC,EAC3D,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,YAAY;AACzB,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAE3D,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,QAAQ,WAAW;AAElC,QAAI;AACF,YAAM,SAAS,MAAM,eAAe;AAAA,QAClC,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,QACtB,MAAM,QAAQ;AAAA,MAChB,CAAC;AAED,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;AAC/C;AAAA,MACF;AAEA,UAAI,OAAO,WAAW,GAAG;AACvB,gBAAQ,IAAIE,OAAM,MAAM,+BAA+B,CAAC;AACxD;AAAA,MACF;AAEA,cAAQ;AAAA,QACNA,OAAM;AAAA,UACJ,SAAS,OAAO,MAAM,mBAAmB,OAAO,SAAS,IAAI,MAAM,EAAE;AAAA;AAAA,QACvE;AAAA,MACF;AAEA,aAAO,QAAQ,CAAC,OAAO,QAAQ;AAC7B,cAAM,aAAa,KAAK,MAAM,MAAM,gBAAgB,GAAG;AACvD,gBAAQ;AAAA,UACNA,OAAM;AAAA,YACJ,mBAAmB,MAAM,CAAC,KAAK,UAAU,cAAc,MAAM,QAAQ,MAAM;AAAA,UAC7E;AAAA,QACF;AAEA,cAAM,QAAQ,QAAQ,CAAC,WAAW;AAChC,gBAAM,UAAUD,UAAS,aAAa,OAAO,QAAQ;AACrD,gBAAM,WAAW,GAAG,OAAO,IAAI,OAAO,SAAS,IAAI,OAAO,OAAO;AACjE,gBAAM,OAAO,OAAO,QAAQ;AAC5B,gBAAM,QACJ,OAAO,UAAU,IACb,KACAC,OAAM,IAAI,KAAK,KAAK,MAAM,OAAO,QAAQ,GAAG,CAAC,IAAI;AACvD,kBAAQ,IAAI,KAAKA,OAAM,KAAK,SAAS,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE;AAAA,QACpE,CAAC;AAED,gBAAQ;AAAA,UACNA,OAAM;AAAA,YACJ,kEAAkE,MAAM,IAAI;AAAA;AAAA,UAC9E;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;;;AClFA,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,YAAW;AAEX,SAAS,gBAAyB;AACvC,SAAO,IAAIF,SAAQ,QAAQ,EACxB,YAAY,kCAAkC,EAC9C,SAAS,WAAW,iCAAiC,EACrD,OAAO,iBAAiB,mCAAmC,QAAQ,EACnE,OAAO,mBAAmB,qCAAqC,UAAU,EACzE,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,OAAe,YAAY;AACxC,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,mBAAmB;AAE1D,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,QAAQ,WAAW;AAElC,QAAI;AACF,YAAM,UAAU,MAAM,cAAc,OAAO;AAAA,QACzC,MAAM;AAAA,QACN,KAAK,QAAQ;AAAA,QACb,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC;AAChD;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,GAAG;AACxB,gBAAQ,IAAIE,OAAM,OAAO,yBAAyB,CAAC;AACnD;AAAA,MACF;AAEA,cAAQ,IAAIA,OAAM,KAAK,SAAS,QAAQ,MAAM;AAAA,CAAsB,CAAC;AAErE,cAAQ,QAAQ,CAAC,QAAQ,QAAQ;AAC/B,cAAM,UAAUD,UAAS,aAAa,OAAO,QAAQ;AACrD,cAAM,WAAW,GAAG,OAAO,IAAI,OAAO,SAAS,IAAI,OAAO,OAAO;AACjE,cAAM,OAAO,OAAO,QAAQ;AAC5B,cAAM,QAAQ,KAAK,MAAM,OAAO,QAAQ,GAAG;AAC3C,cAAM,YAAY,OAAO,KAAK,OAAO,EAAE;AAEvC,gBAAQ;AAAA,UACN,GAAGC,OAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAIA,OAAM,KAAK,QAAQ,CAAC;AAAA,QACrD;AACA,gBAAQ;AAAA,UACN,MAAMA,OAAM,IAAI,SAAS,CAAC,IAAIA,OAAM,KAAK,IAAI,CAAC,IAAIA,OAAM,MAAM,IAAI,KAAK,YAAY,CAAC;AAAA,QACtF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;;;AC7DA,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,WAAU,WAAAC,UAAS,cAAAC,mBAAkB;AAC9C,OAAOC,YAAW;AAEX,SAAS,iBAA0B;AACxC,SAAO,IAAIJ,SAAQ,SAAS,EACzB,YAAY,0CAA0C,EACtD,SAAS,cAAc,6DAA6D,EACpF,OAAO,iBAAiB,mCAAmC,QAAQ,EACnE,OAAO,mBAAmB,qCAAqC,UAAU,EACzE,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,UAAkB,YAAY;AAC3C,UAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,mBAAmB;AAElE,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,QAAQ,WAAW;AAGlC,UAAM,WAAW,SAAS,YAAY,GAAG;AACzC,QAAI,aAAa,IAAI;AACnB,YAAM,UAAU;AAChB,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMI,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,WAAW,SAAS,MAAM,GAAG,QAAQ;AAC3C,UAAM,WAAW,SAAS,MAAM,WAAW,CAAC;AAC5C,UAAM,OAAO,SAAS,UAAU,EAAE;AAElC,QAAI,MAAM,IAAI,GAAG;AACf,YAAM,UAAU,wBAAwB,QAAQ;AAChD,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,WAAWD,YAAW,QAAQ,IAChC,WACAD,SAAQ,aAAa,QAAQ;AAEjC,QAAI;AACF,YAAM,UAAU,MAAM,sBAAsB;AAAA,QAC1C,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,KAAK,QAAQ;AAAA,QACb,WAAW,QAAQ,aAAa;AAAA,MAClC,CAAC;AAED,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC;AAChD;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,GAAG;AACxB,gBAAQ,IAAIE,OAAM,OAAO,wBAAwB,CAAC;AAClD;AAAA,MACF;AAEA,cAAQ;AAAA,QACNA,OAAM;AAAA,UACJ,SAAS,QAAQ,MAAM,8BAA8BH,UAAS,aAAa,QAAQ,CAAC,IAAI,IAAI;AAAA;AAAA,QAC9F;AAAA,MACF;AAEA,cAAQ,QAAQ,CAAC,QAAQ,QAAQ;AAC/B,cAAM,UAAUA,UAAS,aAAa,OAAO,QAAQ;AACrD,cAAM,cAAc,GAAG,OAAO,IAAI,OAAO,SAAS,IAAI,OAAO,OAAO;AACpE,cAAM,OAAO,OAAO,QAAQ;AAC5B,cAAM,QAAQ,KAAK,MAAM,OAAO,QAAQ,GAAG;AAC3C,cAAM,YAAY,OAAO,KAAK,OAAO,EAAE;AAEvC,gBAAQ;AAAA,UACN,GAAGG,OAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAIA,OAAM,KAAK,WAAW,CAAC;AAAA,QACxD;AACA,gBAAQ;AAAA,UACN,MAAMA,OAAM,IAAI,SAAS,CAAC,IAAIA,OAAM,KAAK,IAAI,CAAC,IAAIA,OAAM,MAAM,IAAI,KAAK,YAAY,CAAC;AAAA,QACtF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,UAAI,QAAQ;AACV,gBAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACzD,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,EAAE,CAAC;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;;;AJ3FO,SAAS,0BAAmC;AACjD,QAAM,aAAa,IAAIC,SAAQ,YAAY,EACxC,YAAY,mCAAmC;AAGlD,aAAW,WAAW,aAAa,CAAC;AACpC,aAAW,WAAW,YAAY,CAAC;AACnC,aAAW,WAAW,cAAc,CAAC;AACrC,aAAW,WAAW,eAAe,CAAC;AAEtC,SAAO;AACT;;;AdRA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,qBAAqB;;;AmBF9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,gBAAAC,eAAc,cAAAC,mBAAkB;AACzC,OAAOC,YAAW;;;ACRlB,OAAOC,gBAAe;AAqCf,IAAM,eAAN,MAAmB;AAAA,EAChB,KAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,oBAA0C;AAAA,EAC1C,kBAAoC,CAAC;AAAA,EACrC,eAAgC,CAAC;AAAA,EACjC,kBAAoC,CAAC;AAAA,EAE7C,YAAY,UAA+B,CAAC,GAAG;AAC7C,UAAM,OAAO,QAAQ,QAAQ;AAC7B,SAAK,MAAM,QAAQ,OAAO,kBAAkB,IAAI;AAChD,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,iBAAiB,QAAQ,kBAAkB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAyB;AAC7B,QAAI,KAAK,UAAW;AACpB,QAAI,KAAK,kBAAmB,QAAO,KAAK;AAExC,SAAK,oBAAoB,IAAI,QAAQ,CAACC,UAAS,WAAW;AACxD,YAAM,UAAU,WAAW,MAAM;AAC/B,eAAO,IAAI,MAAM,yBAAyB,KAAK,GAAG,EAAE,CAAC;AAAA,MACvD,GAAG,KAAK,cAAc;AAEtB,WAAK,KAAK,IAAID,WAAU,KAAK,GAAG;AAEhC,WAAK,GAAG,GAAG,QAAQ,MAAM;AACvB,qBAAa,OAAO;AACpB,aAAK,YAAY;AACjB,aAAK,IAAI,gBAAgB,KAAK,GAAG;AACjC,QAAAC,SAAQ;AAAA,MACV,CAAC;AAED,WAAK,GAAG,GAAG,WAAW,CAAC,SAAyB;AAC9C,YAAI;AACF,gBAAM,UAAU,KAAK,MAAM,KAAK,SAAS,CAAC;AAC1C,eAAK,IAAI,aAAa,QAAQ,IAAI;AAClC,eAAK,cAAc,OAAO;AAAA,QAC5B,SAAS,GAAG;AACV,kBAAQ,MAAM,4BAA4B,CAAC;AAAA,QAC7C;AAAA,MACF,CAAC;AAED,WAAK,GAAG,GAAG,SAAS,CAAC,QAAQ;AAC3B,qBAAa,OAAO;AACpB,YAAI,CAAC,KAAK,WAAW;AACnB,iBAAO,GAAG;AAAA,QACZ,OAAO;AACL,kBAAQ,MAAM,oBAAoB,GAAG;AAAA,QACvC;AAAA,MACF,CAAC;AAED,WAAK,GAAG,GAAG,SAAS,MAAM;AACxB,aAAK,YAAY;AACjB,aAAK,IAAI,cAAc;AAEvB,mBAAW,OAAO,KAAK,iBAAiB;AACtC,uBAAa,IAAI,OAAO;AACxB,cAAI,OAAO,IAAI,MAAM,cAAc,CAAC;AAAA,QACtC;AACA,aAAK,kBAAkB,CAAC;AAAA,MAC1B,CAAC;AAAA,IACH,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AACV,WAAK,YAAY;AACjB,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAAqC;AAC7C,SAAK,gBAAgB,KAAK,OAAO;AACjC,WAAO,MAAM;AACX,WAAK,kBAAkB,KAAK,gBAAgB,OAAO,CAAC,MAAM,MAAM,OAAO;AAAA,IACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,SAA8B;AACjC,QAAI,CAAC,KAAK,MAAM,CAAC,KAAK,WAAW;AAC/B,YAAM,IAAI,MAAM,eAAe;AAAA,IACjC;AACA,SAAK,IAAI,YAAY,QAAQ,IAAI;AACjC,SAAK,GAAG,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,QACE,WACA,UAAU,KACc;AAExB,UAAM,WAAW,KAAK,aAAa,KAAK,SAAS;AACjD,QAAI,UAAU;AACZ,WAAK,eAAe,KAAK,aAAa,OAAO,CAAC,MAAM,MAAM,QAAQ;AAClE,aAAO,QAAQ,QAAQ,QAAQ;AAAA,IACjC;AAEA,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,YAAM,YAAY,WAAW,MAAM;AACjC,aAAK,kBAAkB,KAAK,gBAAgB;AAAA,UAC1C,CAAC,MAAM,EAAE,YAAY;AAAA,QACvB;AACA,eAAO,IAAI,MAAM,gCAAgC,OAAO,KAAK,CAAC;AAAA,MAChE,GAAG,OAAO;AAEV,WAAK,gBAAgB,KAAK;AAAA,QACxB;AAAA,QACA,SAAAA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA4B;AAClC,WAAO,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBAAqB,UAAU,KAAqC;AACxE,UAAM,WAAW,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,gBAAgB;AAC1E,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AACA,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QAAQ,IAAI,SAAS;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAqB,UAAU,KAAqC;AACxE,UAAM,WAAW,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,gBAAgB;AAC1E,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AACA,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QAAQ,IAAI,SAAS;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,UAAkB,UAAU,KAAmC;AAC5E,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK,EAAE,MAAM,aAAa,UAAU,UAAU,CAAC;AACpD,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QACC,IAAI,SAAS,iBACZ,IAA0B,cAAc;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,UACA,SACA,UAAU,KACkB;AAC5B,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK,EAAE,MAAM,gBAAgB,UAAU,SAAS,UAAU,CAAC;AAChE,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QACC,IAAI,SAAS,iBACZ,IAA0B,cAAc;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,UAAU,KAAqC;AAC/D,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK,EAAE,MAAM,gBAAgB,UAAU,CAAC;AAC7C,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QACC,IAAI,SAAS,mBACZ,IAA4B,cAAc;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,QAMA,UAAU,MACoB;AAC9B,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,OAAO,OAAO;AAAA,MACd,WAAW,KAAK,IAAI;AAAA,MACpB,YAAY,OAAO;AAAA,MACnB,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO;AAAA,MACjB;AAAA,IACF,CAAC;AACD,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QACC,IAAI,SAAS,mBACZ,IAA4B,cAAc;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,UACA,UAAU,KACyC;AACnD,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK,EAAE,MAAM,gBAAgB,UAAU,UAAU,CAAC;AACvD,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,SACE,IAAI,SAAS,mBAAmB,IAAI,SAAS,oBAC5C,IAA4B,cAAc,aACzC,IAA2B,cAAc;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACJ,UAAU,KAC6C;AACvD,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK,EAAE,MAAM,oBAAoB,UAAU,CAAC;AACjD,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,SACE,IAAI,SAAS,qBAAqB,IAAI,SAAS,sBAC9C,IAA8B,cAAc,aAC3C,IAA6B,cAAc;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,QACA,UACA,SACA,UAAU,KACwB;AAClC,UAAM,YAAY,KAAK,kBAAkB;AACzC,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAQ,MAAM,KAAK;AAAA,MACjB,CAAC,QACC,IAAI,SAAS,wBACZ,IAAgC,cAAc;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,KAAa,OAAsB;AAC3C,SAAK,KAAK,EAAE,MAAM,cAAc,KAAK,MAAM,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,UAAwB;AACpC,SAAK,KAAK,EAAE,MAAM,kBAAkB,SAAS,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,UAAyB;AACvC,SAAK,KAAK,EAAE,MAAM,oBAAoB,SAAS,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,cAA+B;AAC7B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACpB,SAAK,eAAe,CAAC;AAAA,EACvB;AAAA,EAEQ,cAAc,SAA8B;AAElD,eAAW,WAAW,KAAK,iBAAiB;AAC1C,cAAQ,OAAO;AAAA,IACjB;AAGA,aAAS,IAAI,GAAG,IAAI,KAAK,gBAAgB,QAAQ,KAAK;AACpD,YAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,UAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,qBAAa,IAAI,OAAO;AACxB,aAAK,gBAAgB,OAAO,GAAG,CAAC;AAChC,YAAI,QAAQ,OAAO;AACnB;AAAA,MACF;AAAA,IACF;AAGA,SAAK,aAAa,KAAK,OAAO;AAAA,EAChC;AAAA,EAEQ,OAAO,MAAuB;AACpC,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,kBAAkB,GAAG,IAAI;AAAA,IACvC;AAAA,EACF;AACF;AAKA,eAAsB,mBACpB,UAA+B,CAAC,GACT;AACvB,QAAM,SAAS,IAAI,aAAa,OAAO;AACvC,QAAM,OAAO,QAAQ;AACrB,SAAO;AACT;;;ADtZA,SAAS,cAAc,KAAoB,MAAuB;AAChE,MAAI,MAAM;AACR,WAAO,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,EACpC;AAEA,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK,eAAe;AAClB,YAAM,QAAQ,CAAC,GAAGC,OAAM,KAAK,aAAa,CAAC,IAAI,IAAI,QAAQ,EAAE;AAC7D,UAAI,IAAI,OAAO,WAAW,GAAG;AAC3B,cAAM,KAAKA,OAAM,MAAM,mBAAmB,CAAC;AAAA,MAC7C,OAAO;AACL,mBAAW,SAAS,IAAI,QAAQ;AAC9B,gBAAM,MAAM,MAAM,SACd,GAAG,MAAM,IAAI,IAAI,MAAM,MAAM,KAC7B,GAAG,MAAM,IAAI;AACjB,gBAAM,OAAO,MAAM,SAASA,OAAM,IAAI,KAAK,MAAM,MAAM,GAAG,IAAI;AAC9D,gBAAM,KAAK,KAAKA,OAAM,OAAO,GAAG,CAAC,IAAI,MAAM,OAAO,GAAG,IAAI,EAAE;AAAA,QAC7D;AAAA,MACF;AACA,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAAA,IAEA,KAAK;AACH,UAAI,IAAI,WAAW;AACjB,eAAO,GAAGA,OAAM,KAAK,eAAe,CAAC,IAAIA,OAAM,MAAM,WAAW,CAAC,KAAK,IAAI,KAAK;AAAA,MACjF;AACA,aAAO,GAAGA,OAAM,KAAK,eAAe,CAAC,IAAIA,OAAM,IAAI,eAAe,CAAC;AAAA,IAErE,KAAK,iBAAiB;AACpB,YAAM,QAAQ;AAAA,QACZ,GAAGA,OAAM,KAAK,eAAe,CAAC,IAAI,IAAI,KAAK,KAAK,IAAI,YAAY;AAAA,MAClE;AACA,UAAI,IAAI,OAAO;AACb,cAAM,KAAKA,OAAM,IAAI,YAAY,IAAI,KAAK,EAAE,CAAC;AAAA,MAC/C,WAAW,IAAI,OAAO,WAAW,GAAG;AAClC,cAAM,KAAKA,OAAM,MAAM,mBAAmB,CAAC;AAAA,MAC7C,OAAO;AACL,mBAAW,SAAS,IAAI,QAAQ;AAC9B,gBAAM,WACJ,MAAM,aAAa,UACfA,OAAM,IAAI,OAAO,IACjB,MAAM,aAAa,YACjBA,OAAM,OAAO,MAAM,IACnBA,OAAM,KAAK,MAAM;AACzB,gBAAM,KAAK,KAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,MAAM,OAAO,EAAE;AAC/D,cAAI,MAAM,SAAS;AACjB,kBAAM,KAAKA,OAAM,IAAI,UAAU,MAAM,OAAO,EAAE,CAAC;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AACA,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAAA,IAEA,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,gBAAgB,CAAC;AAAA,aAAgB,IAAI,OAAO;AAAA,mBAAsB,IAAI,aAAa;AAAA,IAE1G,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,gBAAgB,CAAC,IAAI,IAAI,MAAM,MAAM;AAAA,IAE5D,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,eAAe,CAAC,IAAI,IAAI,QAAQ,KAAK,IAAI,UAAU;AAAA,IAE1E,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,cAAc,CAAC,IAAI,IAAI,QAAQ,KAAKA,OAAM,IAAI,IAAI,KAAK,CAAC;AAAA,IAE/E,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,iBAAiB,CAAC;AAAA,IAEzC,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,gBAAgB,CAAC,IAAIA,OAAM,IAAI,IAAI,KAAK,CAAC;AAAA,IAEhE,KAAK;AACH,UAAI,IAAI,SAAS;AACf,eAAO,GAAGA,OAAM,KAAK,oBAAoB,CAAC,IAAI,IAAI,MAAM,OAAO,IAAI,QAAQ;AAAA,MAC7E;AACA,aAAO,GAAGA,OAAM,KAAK,oBAAoB,CAAC,IAAI,IAAI,MAAM,IAAIA,OAAM,IAAI,QAAQ,CAAC,KAAK,IAAI,KAAK;AAAA,IAE/F,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,2BAA2B,CAAC;AAAA,IAEnD,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,8BAA8B,CAAC,IAAI,IAAI,OAAO;AAAA,IAErE,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,8BAA8B,CAAC,IAAI,IAAI,WAAW,cAAc,IAAI,QAAQ;AAAA,IAEnG,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,2BAA2B,CAAC,IAAIA,OAAM,IAAI,IAAI,KAAK,CAAC;AAAA,IAE3E,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,cAAc,CAAC,IAAI,IAAI,QAAQ;AAAA,IAEtD,KAAK;AACH,aAAO,GAAGA,OAAM,KAAK,eAAe,CAAC,IAAI,IAAI,GAAG,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC;AAAA,IAEjF;AACE,aAAO,GAAGA,OAAM,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,GAAG,CAAC;AAAA,EACzD;AACF;AAKA,eAAe,QAAQ,QAAsB,SAAuC;AAClF,QAAM,WAAW,MAAM,OAAO,UAAU;AACxC,QAAM,KAAK,SAAS,gBAAgB;AAAA,IAClC,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,IAChB,QAAQA,OAAM,MAAM,UAAU;AAAA,EAChC,CAAC;AAED,UAAQ,IAAIA,OAAM,KAAK,sBAAsB,CAAC;AAC9C,UAAQ,IAAI,uDAAuD;AAGnE,SAAO,UAAU,CAAC,QAAQ;AACxB,YAAQ,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,CAAC;AACnD,OAAG,OAAO;AAAA,EACZ,CAAC;AAGD,MAAI;AACF,UAAM,OAAO,qBAAqB,GAAI;AAAA,EACxC,QAAQ;AAAA,EAER;AAEA,KAAG,OAAO;AAEV,KAAG,GAAG,QAAQ,OAAO,SAAS;AAC5B,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,SAAS;AACZ,SAAG,OAAO;AACV;AAAA,IACF;AAEA,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,MAAM,KAAK;AAE1C,QAAI;AACF,cAAQ,KAAK;AAAA,QACX,KAAK;AACH,kBAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAkBrB;AACS;AAAA,QAEF,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,GAAG;AACZ,oBAAQ,IAAIA,OAAM,IAAI,yBAAyB,CAAC;AAAA,UAClD,OAAO;AACL,kBAAM,SAAS,MAAM,OAAO,SAAS,KAAK,CAAC,GAAG,QAAQ,OAAO;AAC7D,oBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAAA,UACjD;AACA;AAAA,QAEF,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG;AACxB,oBAAQ,IAAIA,OAAM,IAAI,sCAAsC,CAAC;AAAA,UAC/D,OAAO;AACL,kBAAM,SAAS,MAAM,OAAO,YAAY,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,QAAQ,OAAO;AACzE,oBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAAA,UACjD;AACA;AAAA,QAEF,KAAK,gBAAgB;AACnB,gBAAM,SAAS,MAAM,OAAO,YAAY,QAAQ,OAAO;AACvD,kBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAC/C;AAAA,QACF;AAAA,QAEA,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG;AACxB,oBAAQ,IAAIA,OAAM,IAAI,+DAA+D,CAAC;AAAA,UACxF,OAAO;AACL,kBAAM,eAAe,KAAK,CAAC;AAC3B,gBAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,sBAAQ,IAAID,OAAM,IAAI,4BAA4B,YAAY,EAAE,CAAC;AAAA,YACnE,OAAO;AACL,oBAAM,WAAW,KAAK,MAAME,cAAa,cAAc,OAAO,CAAC;AAC/D,oBAAM,SAKF,EAAE,OAAO,KAAK,CAAC,GAAG,SAAS;AAE/B,kBAAI,KAAK,CAAC,GAAG;AACX,oBAAID,YAAW,KAAK,CAAC,CAAC,GAAG;AAEvB,wBAAM,cAAcC,cAAa,KAAK,CAAC,CAAC;AACxC,yBAAO,aAAa,YAAY,SAAS,QAAQ;AAAA,gBACnD,OAAO;AACL,0BAAQ,IAAIF,OAAM,IAAI,8BAA8B,KAAK,CAAC,CAAC,EAAE,CAAC;AAC9D;AAAA,gBACF;AAAA,cACF;AAEA,oBAAM,SAAS,MAAM,OAAO,cAAc,QAAQ,QAAQ,OAAO;AACjE,sBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAAA,YACjD;AAAA,UACF;AACA;AAAA,QAEF,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,GAAG;AACZ,oBAAQ,IAAIA,OAAM,IAAI,4BAA4B,CAAC;AAAA,UACrD,OAAO;AACL,kBAAM,SAAS,MAAM,OAAO,YAAY,KAAK,CAAC,GAAG,QAAQ,OAAO;AAChE,oBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAAA,UACjD;AACA;AAAA,QAEF,KAAK,oBAAoB;AACvB,gBAAM,SAAS,MAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC3D,kBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAC/C;AAAA,QACF;AAAA,QAEA,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG;AACxB,oBAAQ,IAAIA,OAAM,IAAI,sDAAsD,CAAC;AAAA,UAC/E,OAAO;AACL,kBAAM,WAAW,KAAK,CAAC;AACvB,kBAAM,cAAc,KAAK,CAAC,IAAI,KAAK,MAAM,KAAK,CAAC,CAAC,IAAI;AACpD,kBAAM,SAAS,MAAM,OAAO,cAAc,KAAK,CAAC,GAAG,UAAU,aAAa,QAAQ,OAAO;AACzF,oBAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAAA,UACjD;AACA;AAAA,QAEF,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG;AACxB,oBAAQ,IAAIA,OAAM,IAAI,iCAAiC,CAAC;AAAA,UAC1D,OAAO;AACL,gBAAI,QAAiB,KAAK,CAAC;AAC3B,gBAAI;AACF,sBAAQ,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,YAC5B,QAAQ;AAAA,YAER;AACA,mBAAO,UAAU,KAAK,CAAC,GAAG,KAAK;AAC/B,oBAAQ,IAAIA,OAAM,MAAM,OAAO,KAAK,CAAC,CAAC,MAAM,KAAK,UAAU,KAAK,CAAC,EAAE,CAAC;AAAA,UACtE;AACA;AAAA,QAEF,KAAK;AACH,cAAI,CAAC,KAAK,CAAC,GAAG;AACZ,oBAAQ,IAAIA,OAAM,IAAI,yBAAyB,CAAC;AAAA,UAClD,OAAO;AACL,mBAAO,cAAc,KAAK,CAAC,CAAC;AAC5B,oBAAQ,IAAIA,OAAM,MAAM,iBAAiB,KAAK,CAAC,CAAC,EAAE,CAAC;AAAA,UACrD;AACA;AAAA,QAEF,KAAK;AACH,iBAAO,gBAAgB,KAAK,CAAC,CAAC;AAC9B,kBAAQ,IAAIA,OAAM,MAAM,KAAK,CAAC,IAAI,eAAe,KAAK,CAAC,CAAC,KAAK,uBAAuB,CAAC;AACrF;AAAA,QAEF,KAAK,YAAY;AACf,gBAAM,OAAO,OAAO,YAAY;AAChC,cAAI,KAAK,WAAW,GAAG;AACrB,oBAAQ,IAAIA,OAAM,IAAI,oBAAoB,CAAC;AAAA,UAC7C,OAAO;AACL,uBAAW,OAAO,MAAM;AACtB,sBAAQ,IAAI,cAAc,KAAK,QAAQ,IAAI,CAAC;AAAA,YAC9C;AAAA,UACF;AACA;AAAA,QACF;AAAA,QAEA,KAAK;AACH,iBAAO,cAAc;AACrB,kBAAQ,IAAIA,OAAM,MAAM,uBAAuB,CAAC;AAChD;AAAA,QAEF,KAAK;AACH,kBAAQ,OAAO,CAAC,QAAQ;AACxB,kBAAQ,IAAIA,OAAM,MAAM,eAAe,QAAQ,OAAO,YAAY,UAAU,EAAE,CAAC;AAC/E;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AACH,iBAAO,WAAW;AAClB,aAAG,MAAM;AACT,kBAAQ,KAAK,CAAC;AACd;AAAA,QAEF;AACE,kBAAQ,IAAIA,OAAM,IAAI,oBAAoB,GAAG,uCAAuC,CAAC;AAAA,MACzF;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,IAAIA,OAAM,IAAI,UAAW,IAAc,OAAO,EAAE,CAAC;AAAA,IAC3D;AAEA,OAAG,OAAO;AAAA,EACZ,CAAC;AAED,KAAG,GAAG,SAAS,MAAM;AACnB,WAAO,WAAW;AAClB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;AAKA,eAAe,UACb,QACA,SACA,QACe;AACf,UAAQ,IAAIA,OAAM,KAAK,6BAA6B,CAAC;AACrD,MAAI,QAAQ;AACV,YAAQ,IAAIA,OAAM,IAAI,WAAW,MAAM,EAAE,CAAC;AAAA,EAC5C;AACA,UAAQ,IAAIA,OAAM,IAAI,yBAAyB,CAAC;AAEhD,SAAO,UAAU,CAAC,QAAQ;AACxB,QAAI,UAAU,CAAC,IAAI,KAAK,SAAS,OAAO,QAAQ,KAAK,EAAE,CAAC,GAAG;AACzD;AAAA,IACF;AACA,YAAQ,IAAI,cAAc,KAAK,QAAQ,IAAI,CAAC;AAAA,EAC9C,CAAC;AAGD,QAAM,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC5B;AAKO,SAAS,sBAA+B;AAC7C,QAAM,MAAM,IAAIG,SAAQ,QAAQ,EAC7B,YAAY,wCAAwC,EACpD,OAAO,uBAAuB,sBAAsB,MAAM,EAC1D,OAAO,eAAe,wBAAwB,KAAK,EACnD,OAAO,cAAc,sBAAsB,KAAK,EAChD,OAAO,sBAAsB,mCAAmC,OAAO;AAG1E,MAAI,OAAO,OAAO,eAAe;AAC/B,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,WAAW,MAAM,EAAE;AAAA,MAClC,OAAO,WAAW;AAAA,MAClB,MAAM,WAAW;AAAA,MACjB,SAAS,SAAS,WAAW,SAAS,EAAE;AAAA,IAC1C;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,QAAQ,QAAQ,OAAO;AAAA,IAC/B,SAAS,KAAK;AACZ,cAAQ,MAAMH,OAAM,IAAI,sBAAuB,IAAc,OAAO,EAAE,CAAC;AACvE,cAAQ,MAAMA,OAAM,IAAI,oDAAoD,QAAQ,IAAI,EAAE,CAAC;AAC3F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGD,MACG,QAAQ,QAAQ,EAChB,YAAY,yCAAyC,EACrD,OAAO,0BAA0B,0DAA0D,EAC3F,OAAO,OAAO,YAAY,YAAY;AACrC,UAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACjD,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,cAAc,QAAQ,QAAQ,EAAE;AAAA,MAC/C,OAAO,cAAc,SAAS;AAAA,MAC9B,MAAM,cAAc,QAAQ;AAAA,MAC5B,SAAS,SAAS,cAAc,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,UAAU,QAAQ,SAAS,WAAW,MAAM;AAAA,IACpD,SAAS,KAAK;AACZ,cAAQ,MAAMA,OAAM,IAAI,sBAAuB,IAAc,OAAO,EAAE,CAAC;AACvE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,MACG,QAAQ,kBAAkB,EAC1B,YAAY,gCAAgC,EAC5C,OAAO,OAAO,UAAU,aAAa,YAAY;AAChD,UAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACjD,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,cAAc,QAAQ,QAAQ,EAAE;AAAA,MAC/C,OAAO,cAAc,SAAS;AAAA,MAC9B,MAAM,cAAc,QAAQ;AAAA,MAC5B,SAAS,SAAS,cAAc,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,OAAO,qBAAqB,GAAI,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACtD,YAAM,SAAS,MAAM,OAAO,SAAS,UAAU,QAAQ,OAAO;AAC9D,cAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAC/C,aAAO,WAAW;AAClB,cAAQ,KAAK,OAAO,OAAO,SAAS,IAAI,IAAI,CAAC;AAAA,IAC/C,SAAS,KAAK;AACZ,cAAQ,MAAMA,OAAM,IAAI,UAAW,IAAc,OAAO,EAAE,CAAC;AAC3D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,MACG,QAAQ,cAAc,EACtB,YAAY,uCAAuC,EACnD,OAAO,OAAO,aAAa,YAAY;AACtC,UAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACjD,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,cAAc,QAAQ,QAAQ,EAAE;AAAA,MAC/C,OAAO,cAAc,SAAS;AAAA,MAC9B,MAAM,cAAc,QAAQ;AAAA,MAC5B,SAAS,SAAS,cAAc,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,SAAS,MAAM,OAAO,YAAY,QAAQ,OAAO;AACvD,cAAQ,IAAI,cAAc,QAAQ,QAAQ,IAAI,CAAC;AAC/C,aAAO,WAAW;AAClB,cAAQ,KAAK,OAAO,YAAY,IAAI,CAAC;AAAA,IACvC,SAAS,KAAK;AACZ,cAAQ,MAAMA,OAAM,IAAI,UAAW,IAAc,OAAO,EAAE,CAAC;AAC3D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,MACG,QAAQ,qBAAqB,EAC7B,YAAY,8BAA8B,EAC1C,OAAO,OAAO,UAAU,aAAa,YAAY;AAChD,UAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACjD,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,cAAc,QAAQ,QAAQ,EAAE;AAAA,MAC/C,OAAO,cAAc,SAAS;AAAA,MAC9B,MAAM,cAAc,QAAQ;AAAA,MAC5B,SAAS,SAAS,cAAc,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,OAAO,qBAAqB,GAAI,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACtD,YAAM,SAAS,MAAM,OAAO,YAAY,UAAU,QAAQ,OAAO;AACjE,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,MAC7C,WAAW,OAAO,SAAS,iBAAiB;AAC1C,gBAAQ,IAAI,OAAO,OAAO;AAAA,MAC5B,OAAO;AACL,gBAAQ,MAAMA,OAAM,IAAI,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,MACnD;AACA,aAAO,WAAW;AAClB,cAAQ,KAAK,OAAO,SAAS,kBAAkB,IAAI,CAAC;AAAA,IACtD,SAAS,KAAK;AACZ,cAAQ,MAAMA,OAAM,IAAI,UAAW,IAAc,OAAO,EAAE,CAAC;AAC3D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,MACG,QAAQ,OAAO,EACf,YAAY,sBAAsB,EAClC,OAAO,OAAO,aAAa,YAAY;AACtC,UAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACjD,UAAM,UAAyB;AAAA,MAC7B,MAAM,SAAS,cAAc,QAAQ,QAAQ,EAAE;AAAA,MAC/C,OAAO,cAAc,SAAS;AAAA,MAC9B,MAAM,cAAc,QAAQ;AAAA,MAC5B,SAAS,SAAS,cAAc,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AACpF,YAAM,WAAW,MAAM,OAAO,qBAAqB,QAAQ,OAAO;AAElE,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,SAAS,OAAO,MAAM,CAAC,CAAC;AAAA,MACrD,OAAO;AACL,gBAAQ,IAAIA,OAAM,KAAK;AAAA,EAAK,SAAS,MAAM,MAAM;AAAA,CAAqB,CAAC;AACvE,mBAAW,QAAQ,SAAS,OAAO;AACjC,gBAAM,WACJ,KAAK,oBAAoB,UACrBA,OAAM,IAAI,OAAO,IACjB,KAAK,oBAAoB,SACvBA,OAAM,OAAO,MAAM,IACnBA,OAAM,IAAI,KAAK;AACvB,kBAAQ,IAAI,KAAKA,OAAM,KAAK,KAAK,EAAE,CAAC,KAAK,QAAQ,GAAG;AACpD,kBAAQ,IAAIA,OAAM,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;AAAA,QAClD;AAAA,MACF;AAEA,aAAO,WAAW;AAAA,IACpB,SAAS,KAAK;AACZ,cAAQ,MAAMA,OAAM,IAAI,UAAW,IAAc,OAAO,EAAE,CAAC;AAC3D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;AnBrhBA,SAAS,kBAAkB,UAAkB,UAAwB;AACnE,QAAM,MAAM,QAAQ,SAAS,QAAQ;AACrC,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QAAM,QAAQ,OAAO,SAAS,MAAM,CAAC,KAAK,IAAI,EAAE;AAChD,QAAM,QAAQ,OAAO,SAAS,MAAM,CAAC,KAAK,IAAI,EAAE;AAEhD,QAAM,mBACJ,OAAO,SAAS,KAAK,KACrB,OAAO,SAAS,KAAK,MACpB,QAAQ,YAAa,UAAU,YAAY,SAAS;AAEvD,MAAI,CAAC,kBAAkB;AAGrB,YAAQ;AAAA,MACN,8BAA8B,QAAQ,IAAI,QAAQ,+BAA+B,GAAG;AAAA,IACtF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAGA,kBAAkB,IAAI,EAAE;AAExB,IAAM,UAAU,IAAII,SAAQ;AAE5B,SAAS,gBAAwB;AAC/B,MAAI;AACF,UAAM,YAAYC,SAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,UAAM,UAAUC,MAAK,WAAW,MAAM,cAAc;AACpD,UAAM,MAAM,KAAK,MAAMC,cAAa,SAAS,OAAO,CAAC;AAGrD,WAAO,IAAI,WAAW;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,QACG,KAAK,QAAQ,EACb,YAAY,mCAAmC,EAC/C,QAAQ,cAAc,CAAC;AAG1B,QACG,QAAQ,SAAS,EACjB;AAAA,EACC;AACF,EACC,OAAO,2BAA2B,kCAAkC,EACpE,OAAO,wBAAwB,iCAAiC,EAChE,OAAO,sBAAsB,qCAAqC,EAClE,OAAO,wBAAwB,kCAAkC,EACjE,OAAO,4BAA4B,4BAA4B,EAC/D,OAAO,2BAA2B,qCAAqC,EACvE;AAAA,EAAO;AAAA,EAAwB;AAAA,EAAmC,CAAC,MAClE,SAAS,GAAG,EAAE;AAChB,EACC,OAAO,sBAAsB,oCAAoC,EACjE;AAAA,EACC;AAAA,EACA;AAAA,EACA,CAAC,GAAG,SAAgC,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAAA,EAC5D,CAAC;AACH,EACC,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,YAAY,qDAAqD,EACxE,OAAO,WAAW,+BAA+B,EACjD;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,OAAO,YAAY;AACzB,QAAM,QAAQ;AAAA,IACZ,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,IACpB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,eAAe,QAAQ;AAAA,IACvB,iBAAiB,QAAQ;AAAA,IACzB,SAAS,QAAQ;AAAA,IACjB,QAAQ,QAAQ;AAAA,IAChB,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,EACrB,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,MAAM,EACd,YAAY,qCAAqC,EACjD,OAAO,2BAA2B,2BAA2B,EAC7D,OAAO,2BAA2B,iCAAiC,EACnE,OAAO,2BAA2B,0BAA0B,EAC5D,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,WAAW,+BAA+B,EACjD;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,OAAO,YAAY;AACzB,QAAM,KAAK;AAAA,IACT,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,IACpB,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,EACrB,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,aAAa,EACrB,YAAY,yDAAyD,EACrE,OAAO,2BAA2B,iCAAiC,EACnE,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,YAAY;AACzB,QAAM,YAAY;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,6CAA6C,EACzD,OAAO,2BAA2B,8BAA8B,EAChE,OAAO,2BAA2B,iCAAiC,EACnE,OAAO,2BAA2B,0BAA0B,EAC5D,OAAO,SAAS,4BAA4B,EAC5C,OAAO,OAAO,YAAY;AACzB,QAAM,OAAO;AAAA,IACX,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,IACpB,KAAK,QAAQ;AAAA,EACf,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,MAAM,EACd,YAAY,+BAA+B,EAC3C,OAAO,WAAW,wCAAwC,EAC1D,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,OAAO,IAAI,MAAM,OAAO,uBAAuB;AACvD,QAAM,OAAO,EAAE,OAAO,QAAQ,MAAM,CAAC;AACvC,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,4CAA4C,EACxD,OAAO,aAAa,2CAA2C,EAC/D,OAAO,aAAa,0BAA0B,EAC9C,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,yBAAyB;AAC3D,QAAM,SAAS,EAAE,QAAQ,QAAQ,QAAQ,KAAK,QAAQ,IAAI,CAAC;AAC7D,CAAC;AAGH,QACG,QAAQ,OAAO,EACf,YAAY,iDAAiD,EAC7D,OAAO,uBAAuB,qBAAqB,MAAM,EACzD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM;AAAA,IACV,MAAM,SAAS,QAAQ,MAAM,EAAE;AAAA,EACjC,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,sEAAsE,EAClF,OAAO,UAAU,sDAAsD,EACvE;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,kBAAkB,sCAAsC,EAC/D;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,0BAA0B,sCAAsC,EACvE,OAAO,0BAA0B,8BAA8B,EAC/D,OAAO,mBAAmB,qCAAqC,EAC/D;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,kBAAkB,gCAAgC,MAAS,EAClE,OAAO,oBAAoB,mDAAmD,EAC9E,OAAO,YAAY,yDAAyD,EAC5E,OAAO,WAAW,+BAA+B,EACjD;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,OAAO,YAAY;AACzB,QAAM,OAAO;AAAA,IACX,MAAM,QAAQ;AAAA,IACd,gBAAgB,QAAQ;AAAA,IACxB,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,OAAO,QAAQ;AAAA,IACf,YAAY,QAAQ;AAAA,IACpB,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,EACrB,CAAC;AACH,CAAC;AAGH,QACG,QAAQ,QAAQ,EAChB,YAAY,yCAAyC,EACrD,SAAS,YAAY,oBAAoB,EACzC,SAAS,SAAS,mCAAmC,EACrD,SAAS,WAAW,+BAA+B,EACnD,SAAS,cAAc,qDAAqD,EAC5E,OAAO,uBAAuB,yBAAyB,MAAM,EAC7D,OAAO,OAAO,QAAQ,KAAK,OAAO,UAAU,YAAY;AACvD,QAAMC,QAAO,QAAQ,KAAK,OAAO,UAAU;AAAA,IACzC,MAAM,SAAS,QAAQ,MAAM,EAAE;AAAA,EACjC,CAAC;AACH,CAAC;AAGH,QAAQ,WAAW,wBAAwB,CAAC;AAI5C,QAAQ,WAAW,oBAAoB,CAAC;AAGxC,QACG,QAAQ,SAAS,EACjB,YAAY,kDAAkD,EAC9D,OAAO,WAAW,yCAAyC,EAC3D,OAAO,aAAa,0BAA0B,EAC9C,OAAO,aAAa,gDAAgD,EACpE,OAAO,eAAe,8BAA8B,EACpD,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,uBAAuB;AACxD,QAAM,QAAQ;AAAA,IACZ,OAAO,QAAQ;AAAA,IACf,KAAK,QAAQ;AAAA,IACb,QAAQ,QAAQ;AAAA,IAChB,MAAM,QAAQ;AAAA,EAChB,CAAC;AACH,CAAC;AAEH,QAAQ,MAAM;","names":["Command","resolve","existsSync","formatViolationsText","sanitizeIssues","findWorkspaceRoot","resolve","resolve","existsSync","sanitizeIssues","formatViolationsText","dirname","resolve","existsSync","mkdirSync","writeFileSync","ensureOllamaReady","readStyleGuide","findStyleGuidePath","findWorkspaceRoot","findUILintStyleGuideUpwards","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","existsSync","readStyleGuide","findUILintStyleGuideUpwards","dirname","findStyleGuidePath","findWorkspaceRoot","ensureOllamaReady","mkdirSync","writeFileSync","ensureOllamaReady","readStdin","resolve","result","ensureOllamaReady","dirname","resolve","createStyleSummary","readStyleGuide","findStyleGuidePath","ensureOllamaReady","readTailwindThemeTokens","findStyleGuidePath","readStyleGuide","dirname","resolve","readTailwindThemeTokens","ensureOllamaReady","createStyleSummary","existsSync","statSync","mkdirSync","writeFileSync","dirname","resolve","join","parse","findWorkspaceRoot","dirname","join","existsSync","statSync","mkdirSync","writeFileSync","ensureOllamaReady","findStyleGuidePath","findUILintStyleGuideUpwards","readStyleGuide","existsSync","statSync","readStyleGuide","findStyleGuidePath","findUILintStyleGuideUpwards","ensureOllamaReady","mkdirSync","dirname","writeFileSync","join","join","existsSync","parse","dirname","resolve","findWorkspaceRoot","statSync","mkdirSync","writeFileSync","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","readFileSync","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","ensureOllamaReady","WebSocket","resolve","WebSocket","config","Command","chalk","Command","relative","chalk","Command","relative","chalk","Command","relative","resolve","isAbsolute","chalk","Command","readFileSync","dirname","join","Command","readFileSync","existsSync","chalk","WebSocket","resolve","chalk","existsSync","readFileSync","Command","Command","dirname","join","readFileSync","config"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/scan.ts","../src/utils/input.ts","../src/utils/path-specifiers.ts","../src/utils/llm-client.ts","../src/utils/timing.ts","../src/utils/output.ts","../src/commands/analyze.ts","../src/commands/consistency.ts","../src/commands/update.ts","../src/commands/serve.ts","../src/utils/vision-run.ts","../src/commands/vision.ts","../src/commands/config.ts","../src/commands/duplicates/index.ts","../src/commands/duplicates/index-cmd.ts","../src/commands/duplicates/find.ts","../src/commands/duplicates/search.ts","../src/commands/duplicates/similar.ts","../src/commands/socket/index.ts","../src/commands/socket/client.ts"],"sourcesContent":["/**\n * UILint CLI - AI-powered UI consistency checking\n */\n\nimport { Command } from \"commander\";\nimport { scan } from \"./commands/scan.js\";\nimport { analyze } from \"./commands/analyze.js\";\nimport { consistency } from \"./commands/consistency.js\";\nimport { update } from \"./commands/update.js\";\nimport { serve } from \"./commands/serve.js\";\nimport { vision } from \"./commands/vision.js\";\nimport { config } from \"./commands/config.js\";\nimport { createDuplicatesCommand } from \"./commands/duplicates/index.js\";\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nfunction assertNodeVersion(minMajor: number, minMinor: number): void {\n const ver = process.versions.node || \"\";\n const parts = ver.split(\".\");\n const major = Number.parseInt(parts[0] || \"\", 10);\n const minor = Number.parseInt(parts[1] || \"\", 10);\n\n const meetsRequirement =\n Number.isFinite(major) &&\n Number.isFinite(minor) &&\n (major > minMajor || (major === minMajor && minor >= minMinor));\n\n if (!meetsRequirement) {\n // Keep this dependency-free and stdout/stderr friendly.\n // eslint-disable-next-line no-console\n console.error(\n `uilint requires Node.js >= ${minMajor}.${minMinor}.0. You are running Node.js ${ver}.`\n );\n process.exit(1);\n }\n}\n\n// Required by dependencies: chokidar, jsdom, readdirp, etc.\nassertNodeVersion(20, 19);\n\nconst program = new Command();\n\nfunction getCLIVersion(): string {\n try {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as {\n version?: string;\n };\n return pkg.version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nprogram\n .name(\"uilint\")\n .description(\"AI-powered UI consistency checker\")\n .version(getCLIVersion());\n\n// Analyze command\nprogram\n .command(\"analyze\")\n .description(\n \"Analyze a source file/snippet for style issues (data-loc aware)\"\n )\n .option(\"-f, --input-file <path>\", \"Path to a source file to analyze\")\n .option(\"--source-code <code>\", \"Source code to analyze (string)\")\n .option(\"--file-path <path>\", \"File path label shown in the prompt\")\n .option(\"--style-guide <text>\", \"Inline styleguide content to use\")\n .option(\"--styleguide-path <path>\", \"Path to a style guide file\")\n .option(\"--component-name <name>\", \"Component name for focused analysis\")\n .option(\"--component-line <n>\", \"Component line number (integer)\", (v) =>\n parseInt(v, 10)\n )\n .option(\"--include-children\", \"Scope: selected element + children\")\n .option(\n \"--data-loc <value>\",\n \"data-loc value (repeatable) in format path:line:column\",\n (v, prev: string[] | undefined) => (prev ? [...prev, v] : [v]),\n []\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--stream\", \"Stream progress while analyzing (text mode UI only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/source/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await analyze({\n inputFile: options.inputFile,\n sourceCode: options.sourceCode,\n filePath: options.filePath,\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n output: options.output,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Scan command\nprogram\n .command(\"scan\")\n .description(\"Scan HTML for UI consistency issues\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to scan\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/style summary/styleguide (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full LLM payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await scan({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n output: options.output,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Consistency command\nprogram\n .command(\"consistency\")\n .description(\"Analyze grouped DOM elements for visual inconsistencies\")\n .option(\"-j, --input-json <json>\", \"JSON input with GroupedSnapshot\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n await consistency({\n inputJson: options.inputJson,\n output: options.output,\n });\n });\n\n// Update command\nprogram\n .command(\"update\")\n .description(\"Update existing style guide with new styles\")\n .option(\"-f, --input-file <path>\", \"Path to HTML file to analyze\")\n .option(\"-j, --input-json <json>\", \"JSON input with html and styles\")\n .option(\"-s, --styleguide <path>\", \"Path to style guide file\")\n .option(\"--llm\", \"Use LLM to suggest updates\")\n .action(async (options) => {\n await update({\n inputFile: options.inputFile,\n inputJson: options.inputJson,\n styleguide: options.styleguide,\n llm: options.llm,\n });\n });\n\n// Init command\nprogram\n .command(\"init\")\n .description(\"Initialize UILint integration\")\n .option(\"--force\", \"Overwrite existing configuration files\")\n .option(\"--react\", \"Install React DevTool (non-interactive)\")\n .option(\"--eslint\", \"Install ESLint rules (non-interactive)\")\n .option(\"--genstyleguide\", \"Generate styleguide (non-interactive)\")\n .option(\"--skill\", \"Install Claude skill (non-interactive)\")\n .action(async (options) => {\n const { initUI } = await import(\"./commands/init-ui.js\");\n await initUI({\n force: options.force,\n react: options.react,\n eslint: options.eslint,\n genstyleguide: options.genstyleguide,\n skill: options.skill,\n });\n });\n\n// Remove command\nprogram\n .command(\"remove\")\n .description(\"Remove UILint components from your project\")\n .option(\"--dry-run\", \"Preview changes without removing anything\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(async (options) => {\n const { removeUI } = await import(\"./commands/remove-ui.js\");\n await removeUI({ dryRun: options.dryRun, yes: options.yes });\n });\n\n// Serve command - WebSocket server for UI overlay\nprogram\n .command(\"serve\")\n .description(\"Start WebSocket server for real-time UI linting\")\n .option(\"-p, --port <number>\", \"Port to listen on\", \"9234\")\n .action(async (options) => {\n await serve({\n port: parseInt(options.port, 10),\n });\n });\n\n// Vision command\nprogram\n .command(\"vision\")\n .description(\"Analyze a screenshot with Ollama vision models (requires a manifest)\")\n .option(\"--list\", \"List available .uilint/screenshots sidecars and exit\")\n .option(\n \"--screenshots-dir <path>\",\n \"Screenshots directory for --list (default: nearest .uilint/screenshots)\"\n )\n .option(\"--image <path>\", \"Path to a screenshot image (png/jpg)\")\n .option(\n \"--sidecar <path>\",\n \"Path to a .uilint/screenshots/*.json sidecar (contains manifest + metadata)\"\n )\n .option(\"--manifest-file <path>\", \"Path to a manifest JSON file (array)\")\n .option(\"--manifest-json <json>\", \"Inline manifest JSON (array)\")\n .option(\"--route <route>\", \"Optional route label (e.g., /todos)\")\n .option(\n \"-s, --styleguide <path>\",\n \"Path to style guide file OR project directory (falls back to upward search)\"\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .option(\"--model <name>\", \"Ollama vision model override\", undefined)\n .option(\"--base-url <url>\", \"Ollama base URL (default: http://localhost:11434)\")\n .option(\"--stream\", \"Stream model output/progress to stderr (text mode only)\")\n .option(\"--debug\", \"Enable debug logging (stderr)\")\n .option(\n \"--debug-full\",\n \"Print full prompt/styleguide and include base64 in dumps (can be very large)\"\n )\n .option(\n \"--debug-dump <path>\",\n \"Write full analysis payload dump to JSON file (or directory to auto-name)\"\n )\n .action(async (options) => {\n await vision({\n list: options.list,\n screenshotsDir: options.screenshotsDir,\n image: options.image,\n sidecar: options.sidecar,\n manifestFile: options.manifestFile,\n manifestJson: options.manifestJson,\n route: options.route,\n styleguide: options.styleguide,\n output: options.output,\n model: options.model,\n baseUrl: options.baseUrl,\n stream: options.stream,\n debug: options.debug,\n debugFull: options.debugFull,\n debugDump: options.debugDump,\n });\n });\n\n// Config command\nprogram\n .command(\"config\")\n .description(\"Get or set UILint configuration options\")\n .argument(\"<action>\", \"Action: set or get\")\n .argument(\"<key>\", \"Config key (e.g., position, rule)\")\n .argument(\"[value]\", \"Value to set (for set action)\")\n .argument(\"[extraArg]\", \"Extra argument (e.g., options JSON for rule config)\")\n .option(\"-p, --port <number>\", \"WebSocket server port\", \"9234\")\n .action(async (action, key, value, extraArg, options) => {\n await config(action, key, value, extraArg, {\n port: parseInt(options.port, 10),\n });\n });\n\n// Duplicates command group - semantic code duplicate detection\nprogram.addCommand(createDuplicatesCommand());\n\n// Socket command - CLI for interacting with socket server\nimport { createSocketCommand } from \"./commands/socket/index.js\";\nprogram.addCommand(createSocketCommand());\n\n// Upgrade command - update installed rules\nprogram\n .command(\"upgrade\")\n .description(\"Update installed ESLint rules to latest versions\")\n .option(\"--check\", \"Show available updates without applying\")\n .option(\"-y, --yes\", \"Auto-confirm all updates\")\n .option(\"--dry-run\", \"Show what would change without modifying files\")\n .option(\"--rule <id>\", \"Upgrade only a specific rule\")\n .action(async (options) => {\n const { upgrade } = await import(\"./commands/upgrade.js\");\n await upgrade({\n check: options.check,\n yes: options.yes,\n dryRun: options.dryRun,\n rule: options.rule,\n });\n });\n\nprogram.parse();\n","/**\n * Scan command - scans HTML for UI consistency issues\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, statSync, writeFileSync } from \"fs\";\nimport {\n createStyleSummary,\n buildAnalysisPrompt,\n buildSourceAnalysisPrompt,\n formatViolationsText,\n sanitizeIssues,\n ensureOllamaReady,\n readStyleGuide,\n readStyleGuideFromProject,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n STYLEGUIDE_PATHS,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport {\n getScanInput,\n type InputOptions,\n type ScanInput,\n} from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ScanOptions extends InputOptions {\n styleguide?: string;\n output?: \"text\" | \"json\";\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleSummary/styleGuide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: ScanOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: ScanOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: ScanOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nexport async function scan(options: ScanOptions): Promise<void> {\n // For JSON output, skip the fancy UI\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Scan for UI Issues\");\n }\n\n try {\n // Get input\n let snapshot: ScanInput;\n try {\n const normalizedOptions: ScanOptions = {\n ...options,\n inputFile: options.inputFile\n ? resolvePathSpecifier(options.inputFile, process.cwd())\n : options.inputFile,\n };\n if (isJsonOutput) {\n snapshot = await getScanInput(normalizedOptions);\n } else {\n snapshot = await withSpinner(\"Parsing input\", async () => {\n return await getScanInput(normalizedOptions);\n });\n }\n } catch {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n output: options.output,\n });\n\n if (snapshot.kind === \"dom\") {\n const dom = snapshot.snapshot;\n debugLog(dbg, \"Parsed snapshot (high-level)\", {\n elementCount: dom.elementCount,\n timestamp: dom.timestamp,\n htmlLength: dom.html.length,\n styles: {\n colors: dom.styles.colors.size,\n fontSizes: dom.styles.fontSizes.size,\n fontFamilies: dom.styles.fontFamilies.size,\n fontWeights: dom.styles.fontWeights.size,\n spacing: dom.styles.spacing.size,\n borderRadius: dom.styles.borderRadius.size,\n },\n });\n if (dbgFull) {\n debugLog(dbg, \"Snapshot HTML (full)\", dom.html);\n } else if (dbg) {\n debugLog(dbg, \"Snapshot HTML (preview)\", preview(dom.html, 800));\n }\n\n if (!isJsonOutput) {\n logInfo(`Scanning ${pc.cyan(String(dom.elementCount))} elements`);\n }\n } else {\n debugLog(dbg, \"Parsed source input (high-level)\", {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n length: snapshot.source.length,\n lines: snapshot.source.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source (full)\", snapshot.source);\n } else if (dbg) {\n debugLog(dbg, \"Source (preview)\", preview(snapshot.source, 1200));\n }\n\n if (!isJsonOutput) {\n logInfo(\n `Scanning ${pc.cyan(snapshot.extension || \"source\")} (${pc.cyan(\n String(snapshot.source.split(\"\\n\").length)\n )} lines)`\n );\n }\n }\n\n // Get style guide\n // --styleguide can be either:\n // 1. Direct path to a styleguide file (e.g., /path/to/.uilint/styleguide.md)\n // 2. Path to a project directory to search in\n // 3. Not provided - search from cwd\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const projectPath = process.cwd();\n\n if (options.styleguide) {\n const styleguideArg = resolvePathSpecifier(\n options.styleguide,\n projectPath\n );\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n // Direct path to styleguide file\n styleguideLocation = styleguideArg;\n styleGuide = await readStyleGuide(styleguideArg);\n } else if (stat.isDirectory()) {\n // Path to project directory - search within it\n styleguideLocation = findStyleGuidePath(styleguideArg);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n } else {\n if (!isJsonOutput) {\n logWarning(`Styleguide not found: ${styleguideArg}`);\n }\n }\n } else {\n // No --styleguide provided:\n // Prefer searching upward from the input file directory for `.uilint/styleguide.md`\n // (helps when running from repo root but scanning a nested app/package).\n const startPath =\n snapshot.kind === \"source\"\n ? snapshot.inputPath\n : snapshot.kind === \"dom\"\n ? snapshot.inputPath\n : undefined;\n if (startPath) {\n styleguideLocation = findUILintStyleGuideUpwards(dirname(startPath));\n }\n\n // Fallback: search from cwd\n styleguideLocation =\n styleguideLocation ?? findStyleGuidePath(projectPath);\n if (styleguideLocation) {\n styleGuide = await readStyleGuide(styleguideLocation);\n }\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n }\n } else if (!styleGuide) {\n if (!isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n }\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleguideArg: options.styleguide,\n styleguideLocation: styleguideLocation ?? null,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", styleGuide ?? \"\");\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide contents (preview)\", preview(styleGuide, 800));\n }\n\n // Create style summary\n const tailwindSearchDir =\n (snapshot.kind === \"source\" || snapshot.kind === \"dom\") &&\n snapshot.inputPath\n ? dirname(snapshot.inputPath)\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n const styleSummary =\n snapshot.kind === \"dom\"\n ? createStyleSummary(snapshot.snapshot.styles, {\n html: snapshot.snapshot.html,\n tailwindTheme,\n })\n : null;\n\n debugLog(dbg, \"Tailwind context\", {\n tailwindSearchDir,\n tailwindTheme: tailwindTheme\n ? {\n configPath: tailwindTheme.configPath,\n colors: tailwindTheme.colors.length,\n spacingKeys: tailwindTheme.spacingKeys.length,\n borderRadiusKeys: tailwindTheme.borderRadiusKeys.length,\n fontFamilyKeys: tailwindTheme.fontFamilyKeys.length,\n fontSizeKeys: tailwindTheme.fontSizeKeys.length,\n }\n : null,\n });\n\n debugLog(dbg, \"Style summary (stats)\", {\n length: styleSummary ? styleSummary.length : 0,\n lines: styleSummary ? styleSummary.split(\"\\n\").length : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Style summary (full)\", styleSummary ?? \"\");\n } else if (dbg && styleSummary) {\n debugLog(dbg, \"Style summary (preview)\", preview(styleSummary, 800));\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n // Call Ollama for analysis\n const client = await createLLMClient({});\n let result;\n\n // Build the exact prompt (this is what analyzeStyles() uses internally)\n const prompt =\n snapshot.kind === \"dom\"\n ? buildAnalysisPrompt(styleSummary ?? \"\", styleGuide)\n : buildSourceAnalysisPrompt(snapshot.source, styleGuide, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `scan-debug-${safeStamp}.json`);\n\n // If path looks like a directory (or a non-json file), ensure dir exists.\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n options: {\n inputFile: options.inputFile,\n inputJson: options.inputJson ? \"(provided)\" : undefined,\n styleguide: options.styleguide,\n styleguideLocation,\n output: options.output,\n model: client.getModel(),\n },\n snapshot: {\n kind: snapshot.kind,\n ...(snapshot.kind === \"dom\"\n ? {\n elementCount: snapshot.snapshot.elementCount,\n timestamp: snapshot.snapshot.timestamp,\n html: snapshot.snapshot.html,\n styles: {\n colors: [...snapshot.snapshot.styles.colors.entries()],\n fontSizes: [\n ...snapshot.snapshot.styles.fontSizes.entries(),\n ],\n fontFamilies: [\n ...snapshot.snapshot.styles.fontFamilies.entries(),\n ],\n fontWeights: [\n ...snapshot.snapshot.styles.fontWeights.entries(),\n ],\n spacing: [\n ...snapshot.snapshot.styles.spacing.entries(),\n ],\n borderRadius: [\n ...snapshot.snapshot.styles.borderRadius.entries(),\n ],\n },\n }\n : {\n inputPath: snapshot.inputPath,\n extension: snapshot.extension,\n source: snapshot.source,\n }),\n },\n styleGuide,\n styleSummary,\n prompt,\n tailwindTheme,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: !isJsonOutput,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n if (isJsonOutput) {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(styleSummary ?? \"\", styleGuide)\n : await client.analyzeSource(snapshot.source, styleGuide, undefined, {\n filePath: snapshot.inputPath,\n languageHint: snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n });\n } else {\n // Use streaming to show progress\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n const onProgress = (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ): void => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[scan] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n // Truncate line if too long for terminal\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n };\n\n try {\n result =\n snapshot.kind === \"dom\"\n ? await client.analyzeStyles(\n styleSummary ?? \"\",\n styleGuide,\n onProgress\n )\n : await client.analyzeSource(\n snapshot.source,\n styleGuide,\n onProgress,\n {\n filePath: snapshot.inputPath,\n languageHint:\n snapshot.extension.replace(/^\\./, \"\") || \"source\",\n extraContext: tailwindTheme\n ? `Tailwind theme tokens loaded from: ${tailwindTheme.configPath}\\n- colors: ${tailwindTheme.colors.length}\\n- spacingKeys: ${tailwindTheme.spacingKeys.length}\\n- borderRadiusKeys: ${tailwindTheme.borderRadiusKeys.length}\\n- fontFamilyKeys: ${tailwindTheme.fontFamilyKeys.length}\\n- fontSizeKeys: ${tailwindTheme.fontSizeKeys.length}`\n : \"\",\n }\n );\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (error) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw error;\n }\n }\n\n // Sanitize (enforce violations-only output)\n const issues = sanitizeIssues(result.issues);\n\n // Output results\n if (isJsonOutput) {\n printJSON({\n issues,\n analysisTime: result.analysisTime,\n elementCount:\n snapshot.kind === \"dom\" ? snapshot.snapshot.elementCount : 0,\n });\n } else {\n // Minimal output: list violations only, plus footer to consult the style guide.\n process.stdout.write(\n formatViolationsText(issues, { includeFooter: issues.length > 0 }) +\n \"\\n\"\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Scan failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Input handling utilities for CLI\n */\n\nimport { readFile } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { extname } from \"path\";\nimport {\n parseCLIInput,\n hasStdin,\n readStdin,\n type DOMSnapshot,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport interface InputOptions {\n inputFile?: string;\n inputJson?: string;\n}\n\nexport type ScanInput =\n | {\n kind: \"dom\";\n snapshot: DOMSnapshot;\n source: \"json\" | \"file\" | \"stdin\";\n inputPath?: string;\n }\n | {\n kind: \"source\";\n source: string;\n inputPath: string;\n extension: string;\n };\n\nfunction isHtmlLikeExtension(ext: string): boolean {\n return ext === \".html\" || ext === \".htm\";\n}\n\nfunction isJsonLikeExtension(ext: string): boolean {\n return ext === \".json\";\n}\n\n/**\n * Gets input from various sources: stdin, file, or JSON string\n */\nexport async function getInput(options: InputOptions): Promise<DOMSnapshot> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return parseCLIInput(options.inputJson);\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n return parseCLIInput(content);\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return parseCLIInput(content);\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets scan input:\n * - If input is a file and it's not HTML/JSON, treat it as raw source (TSX/JSX/etc).\n * - Otherwise, treat it as HTML/DOM input (including JSON-wrapped snapshots).\n */\nexport async function getScanInput(options: InputOptions): Promise<ScanInput> {\n // Priority: explicit JSON > explicit file > stdin\n if (options.inputJson) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(options.inputJson),\n source: \"json\",\n };\n }\n\n if (options.inputFile) {\n const filePath = resolvePathSpecifier(options.inputFile, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.inputFile}`);\n }\n const content = await readFile(filePath, \"utf-8\");\n const ext = extname(filePath).toLowerCase();\n\n if (isHtmlLikeExtension(ext) || isJsonLikeExtension(ext)) {\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"file\",\n inputPath: filePath,\n };\n }\n\n return {\n kind: \"source\",\n source: content,\n inputPath: filePath,\n extension: ext,\n };\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No input provided via stdin\");\n }\n return {\n kind: \"dom\",\n snapshot: parseCLIInput(content),\n source: \"stdin\",\n };\n }\n\n throw new Error(\n \"No input provided. Use --input-file, --input-json, or pipe content to stdin.\"\n );\n}\n\n/**\n * Gets code input from various sources\n */\nexport async function getCodeInput(options: {\n code?: string;\n file?: string;\n}): Promise<string> {\n if (options.code) {\n return options.code;\n }\n\n if (options.file) {\n const filePath = resolvePathSpecifier(options.file, process.cwd());\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${options.file}`);\n }\n return readFile(filePath, \"utf-8\");\n }\n\n if (hasStdin()) {\n const content = await readStdin();\n if (!content.trim()) {\n throw new Error(\"No code provided via stdin\");\n }\n return content;\n }\n\n throw new Error(\n \"No code provided. Use --code, provide a file, or pipe to stdin.\"\n );\n}\n\n/**\n * Validates that a path exists\n */\nexport function validatePath(path: string, description: string): void {\n if (!existsSync(path)) {\n throw new Error(`${description} not found: ${path}`);\n }\n}\n","/**\n * Path specifier utilities for CLI.\n *\n * We support \"workspace-relative\" specifiers using a leading \"@\", e.g.:\n * - @apps/test-app/app/page.tsx\n * - @apps/test-app/.uilint/styleguide.md\n *\n * This mirrors how some tools (and humans) refer to \"repo-relative\" paths.\n */\n\nimport { isAbsolute, resolve } from \"path\";\nimport { findWorkspaceRoot } from \"uilint-core/node\";\n\n/**\n * Resolve a user-provided path specifier into an absolute filesystem path.\n *\n * Rules:\n * - Absolute paths are left absolute (normalized with resolve()).\n * - \"@<path>\" is resolved relative to the workspace root (pnpm-workspace/.git).\n * - Everything else is resolved relative to cwd.\n */\nexport function resolvePathSpecifier(\n spec: string,\n cwd: string = process.cwd()\n): string {\n const raw = (spec ?? \"\").trim();\n if (!raw) return resolve(cwd, spec);\n\n if (raw.startsWith(\"@\")) {\n const workspaceRoot = findWorkspaceRoot(cwd);\n let rest = raw.slice(1);\n if (rest.startsWith(\"/\")) rest = rest.slice(1);\n // Note: resolve(workspaceRoot, rest) is safe even if rest contains \"..\";\n // callers that need a security boundary should validate separately.\n return resolve(workspaceRoot, rest);\n }\n\n if (isAbsolute(raw)) return resolve(raw);\n return resolve(cwd, raw);\n}\n","/**\n * LLM Client Factory with Optional Langfuse Instrumentation\n *\n * This module provides a centralized way to create OllamaClient instances\n * with optional Langfuse tracing enabled. Langfuse is only loaded if:\n * 1. LANGFUSE_ENABLED=1 (or true/yes)\n * 2. LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY are set\n */\n\nimport { config } from \"dotenv\";\nimport { join } from \"path\";\nimport {\n OllamaClient,\n type LLMInstrumentationCallbacks,\n type InstrumentationSpan,\n findWorkspaceRoot,\n} from \"uilint-core/node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { LangfuseSpanProcessor } from \"@langfuse/otel\";\nimport {\n startActiveObservation,\n startObservation,\n type LangfuseObservation,\n type LangfuseGeneration,\n} from \"@langfuse/tracing\";\n\n// Load .env.local from workspace root\nlet envLoaded = false;\nfunction loadEnvLocal(): void {\n if (envLoaded) return;\n envLoaded = true;\n\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n const envLocalPath = join(workspaceRoot, \".env.local\");\n\n // Load .env.local if it exists (dotenv will silently skip if file doesn't exist)\n config({ path: envLocalPath });\n}\n\n// Load environment variables immediately on module load\nloadEnvLocal();\n\n// Lazy-loaded instrumentation\nlet langfuseInitialized = false;\nlet langfuseInstrumentation: LLMInstrumentationCallbacks | undefined;\nlet sdkInstance: NodeSDK | undefined;\nlet spanProcessor: LangfuseSpanProcessor | undefined;\n\n/**\n * Checks if Langfuse is enabled via environment variable\n */\nfunction isLangfuseEnabled(): boolean {\n const enabled = process.env.LANGFUSE_ENABLED;\n if (!enabled) return false;\n return (\n enabled === \"1\" ||\n enabled.toLowerCase() === \"true\" ||\n enabled.toLowerCase() === \"yes\"\n );\n}\n\n/**\n * Initialize Langfuse if enabled. This is called automatically on first client creation,\n * but can also be called explicitly at app startup.\n */\nexport async function initializeLangfuseIfEnabled(): Promise<void> {\n if (langfuseInitialized) return;\n langfuseInitialized = true;\n\n if (!isLangfuseEnabled()) {\n return;\n }\n\n const publicKey = process.env.LANGFUSE_PUBLIC_KEY;\n const secretKey = process.env.LANGFUSE_SECRET_KEY;\n\n if (!publicKey || !secretKey) {\n console.error(\n \"[uilint] LANGFUSE_ENABLED=1 but missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY\"\n );\n return;\n }\n\n try {\n const baseUrl = process.env.LANGFUSE_BASE_URL || \"http://localhost:3333\";\n\n // Create the span processor with immediate export mode for CLI usage\n spanProcessor = new LangfuseSpanProcessor({\n publicKey,\n secretKey,\n baseUrl,\n // Use immediate mode to ensure spans are exported right away in CLI context\n exportMode: \"immediate\",\n });\n\n // Initialize OpenTelemetry with LangfuseSpanProcessor\n const sdk = new NodeSDK({\n spanProcessors: [spanProcessor],\n });\n\n sdk.start();\n sdkInstance = sdk;\n\n // Create instrumentation callbacks using @langfuse/tracing\n // Use startActiveObservation at top level to create the trace context\n langfuseInstrumentation = {\n onGenerationStart: ({\n name,\n model,\n prompt,\n metadata,\n }: {\n name: string;\n model: string;\n prompt: string;\n metadata?: Record<string, unknown>;\n }): InstrumentationSpan => {\n // We need to bridge the callback-based startActiveObservation with our\n // synchronous start / async end pattern. Use a promise to control when the trace ends.\n let resolveTrace: () => void;\n let generationRef: LangfuseGeneration | undefined;\n let traceRef: LangfuseObservation | undefined;\n let endData:\n | {\n output: string;\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n };\n }\n | undefined;\n\n // Start the active observation (trace) - this runs the callback immediately\n // but doesn't resolve until we call resolveTrace()\n const tracePromise = startActiveObservation(\n `uilint-${name}`,\n async (span) => {\n traceRef = span;\n span.update({\n input: { operation: name },\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n });\n\n // Create the generation as a child - startObservation within startActiveObservation\n // automatically nests under the active trace\n generationRef = startObservation(\n name,\n {\n model,\n input: prompt,\n metadata: {\n ...metadata,\n source: \"uilint\",\n },\n },\n { asType: \"generation\" }\n );\n\n // Wait for end() to be called before completing the trace\n await new Promise<void>((resolve) => {\n resolveTrace = resolve;\n });\n\n // Now process the end data\n if (endData && generationRef) {\n const usageDetails: Record<string, number> | undefined =\n endData.usage\n ? Object.fromEntries(\n Object.entries({\n input: endData.usage.promptTokens,\n output: endData.usage.completionTokens,\n total: endData.usage.totalTokens,\n }).filter(([, v]) => v !== undefined) as [\n string,\n number\n ][]\n )\n : undefined;\n\n // End the generation\n generationRef.update({\n output: endData.output,\n usageDetails:\n usageDetails && Object.keys(usageDetails).length > 0\n ? usageDetails\n : undefined,\n metadata: endData.usage?.error\n ? { ...metadata, error: endData.usage.error }\n : metadata,\n });\n generationRef.end();\n\n // Update the trace output\n span.update({\n output: endData.usage?.error\n ? `Error: ${endData.usage.error}`\n : \"completed\",\n });\n }\n // The trace automatically ends when the callback completes\n }\n );\n\n // Handle any errors from the trace promise\n tracePromise.catch((error) => {\n console.error(\"[uilint] Langfuse trace error:\", error);\n });\n\n return {\n end: (\n output: string,\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n error?: string;\n }\n ) => {\n // Store the end data and resolve the trace promise\n endData = { output, usage };\n if (resolveTrace) {\n resolveTrace();\n }\n },\n };\n },\n };\n\n console.error(`[uilint] Langfuse tracing enabled (${baseUrl})`);\n } catch (error) {\n console.error(\n \"[uilint] Failed to initialize Langfuse:\",\n error instanceof Error ? error.message : error\n );\n }\n}\n\n/**\n * Creates an OllamaClient with optional Langfuse instrumentation.\n * Automatically initializes Langfuse on first call if enabled.\n */\nexport async function createLLMClient(options: {\n model?: string;\n baseUrl?: string;\n timeout?: number;\n}): Promise<OllamaClient> {\n // Initialize Langfuse on first client creation\n await initializeLangfuseIfEnabled();\n\n return new OllamaClient({\n ...options,\n instrumentation: langfuseInstrumentation,\n });\n}\n\n/**\n * Flushes Langfuse traces. Call this before process exit to ensure all traces are sent.\n */\nexport async function flushLangfuse(): Promise<void> {\n // Force flush the span processor first to ensure all pending spans are sent\n if (spanProcessor) {\n try {\n await spanProcessor.forceFlush();\n } catch (error) {\n console.error(\n \"[uilint] Failed to flush Langfuse spans:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n\n // Then shutdown the SDK\n if (sdkInstance) {\n try {\n await sdkInstance.shutdown();\n } catch (error) {\n console.error(\n \"[uilint] Failed to shutdown OpenTelemetry SDK:\",\n error instanceof Error ? error.message : error\n );\n }\n }\n}\n\n/**\n * Returns true if Langfuse is currently initialized and active.\n */\nexport function isLangfuseActive(): boolean {\n return spanProcessor !== undefined;\n}\n\n// Register shutdown handler\nlet shutdownRegistered = false;\nfunction registerShutdownHandler(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n\n const cleanup = async () => {\n await flushLangfuse();\n };\n\n process.on(\"beforeExit\", cleanup);\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(130);\n });\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(143);\n });\n}\n\n// Auto-register on module load\nregisterShutdownHandler();\n","/**\n * High-precision timing helpers for CLI UX\n */\n\nexport function nsNow(): bigint {\n return process.hrtime.bigint();\n}\n\nexport function nsToMs(ns: bigint): number {\n return Number(ns) / 1_000_000;\n}\n\nexport function formatMs(ms: number): string {\n if (!Number.isFinite(ms)) return \"n/a\";\n if (ms < 1000) return `${ms.toFixed(ms < 10 ? 2 : ms < 100 ? 1 : 0)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${s.toFixed(s < 10 ? 2 : 1)}s`;\n const m = Math.floor(s / 60);\n const rem = s - m * 60;\n return `${m}m ${rem.toFixed(rem < 10 ? 1 : 0)}s`;\n}\n\nexport function maybeMs(ms: number | null | undefined): string {\n return ms == null ? \"n/a\" : formatMs(ms);\n}\n","/**\n * Output formatting utilities for CLI\n */\n\nimport chalk from \"chalk\";\nimport {\n formatViolationsText,\n sanitizeIssues,\n type UILintIssue,\n} from \"uilint-core\";\n\n/**\n * Formats UILint issues for console output\n */\nexport function formatIssues(issues: UILintIssue[]): string {\n const sanitized = sanitizeIssues(issues);\n const text = formatViolationsText(sanitized, {\n includeFooter: sanitized.length > 0,\n });\n // Preserve existing callers expecting a string; apply minimal coloring only.\n return sanitized.length === 0 ? chalk.green(text) : text;\n}\n\n/**\n * Prints JSON output\n */\nexport function printJSON(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * Prints an error message\n */\nexport function printError(message: string): void {\n console.error(chalk.red(`Error: ${message}`));\n}\n\n/**\n * Prints a success message\n */\nexport function printSuccess(message: string): void {\n console.log(chalk.green(`✓ ${message}`));\n}\n\n/**\n * Prints a warning message\n */\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n\n/**\n * Prints an info message\n */\nexport function printInfo(message: string): void {\n console.log(chalk.blue(`ℹ ${message}`));\n}\n\n/**\n * Prints a debug/path message (dimmed)\n */\nexport function printPath(label: string, path: string): void {\n console.log(chalk.gray(` ${label}: ${chalk.dim(path)}`));\n}\n\n/**\n * Prints a styled box for important messages\n */\nexport function printBox(\n title: string,\n lines: string[],\n style: \"warning\" | \"error\" | \"info\" = \"info\"\n): void {\n const colors = {\n warning: { border: chalk.yellow, title: chalk.yellow.bold, icon: \"⚠\" },\n error: { border: chalk.red, title: chalk.red.bold, icon: \"✖\" },\n info: { border: chalk.blue, title: chalk.blue.bold, icon: \"ℹ\" },\n };\n const { border, title: titleColor, icon } = colors[style];\n\n const maxLen = Math.max(title.length, ...lines.map((l) => l.length)) + 4;\n const horizontal = \"─\".repeat(maxLen);\n\n console.log();\n console.log(border(`╭${horizontal}╮`));\n console.log(border(`│ ${icon} ${titleColor(title.padEnd(maxLen - 3))}│`));\n console.log(border(`├${horizontal}┤`));\n lines.forEach((line) => {\n console.log(border(`│ ${chalk.gray(line.padEnd(maxLen - 1))}│`));\n });\n console.log(border(`╰${horizontal}╯`));\n console.log();\n}\n\n/**\n * Prints styleguide status information\n */\nexport function printStyleguideNotFound(\n searchedPaths: string[],\n projectPath: string\n): void {\n printBox(\n \"No styleguide found\",\n [\n `Searched in: ${projectPath}`,\n \"\",\n \"Looked for:\",\n ...searchedPaths.map((p) => ` • ${p}`),\n \"\",\n \"To create one, run:\",\n ` ${chalk.cyan(\"/genstyleguide\")} ${chalk.gray(\"(Cursor)\")}`,\n ],\n \"warning\"\n );\n}\n\n/**\n * Prints styleguide found confirmation\n */\nexport function printStyleguideFound(path: string): void {\n console.log(chalk.green(`📋 Using styleguide: ${chalk.dim(path)}`));\n}\n","/**\n * Analyze command - analyzes a source file/snippet for style issues (data-loc aware)\n */\n\nimport { dirname, resolve } from \"path\";\nimport { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n buildSourceScanPrompt,\n ensureOllamaReady,\n readStyleGuide,\n findStyleGuidePath,\n findWorkspaceRoot,\n findUILintStyleGuideUpwards,\n} from \"uilint-core/node\";\nimport { getCodeInput } from \"../utils/input.js\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n intro,\n withSpinner,\n createSpinner,\n note,\n logError,\n logWarning,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\ntype UILintScanIssue = {\n line?: number;\n message: string;\n dataLoc?: string;\n};\n\nexport interface AnalyzeOptions {\n // Input\n inputFile?: string;\n sourceCode?: string;\n\n // Styleguide\n styleGuide?: string;\n styleguidePath?: string;\n\n // Prompt context\n filePath?: string;\n componentName?: string;\n componentLine?: number;\n includeChildren?: boolean;\n dataLoc?: string[]; // repeatable\n\n // LLM\n stream?: boolean;\n\n // Output\n output?: \"text\" | \"json\";\n\n /**\n * Enable debug logging (stderr only; never pollutes JSON stdout).\n * Can also be enabled via UILINT_DEBUG=1\n */\n debug?: boolean;\n /**\n * Print full prompt/styleguide to stderr (can be very large).\n * Can also be enabled via UILINT_DEBUG_FULL=1\n */\n debugFull?: boolean;\n /**\n * Dump full LLM payload (prompt + inputs) to a JSON file.\n * Can also be set via UILINT_DEBUG_DUMP=/path/to/file-or-dir\n */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: AnalyzeOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: AnalyzeOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nasync function resolveStyleGuideForAnalyze(options: {\n styleGuide?: string;\n styleguidePath?: string;\n inputFile?: string;\n}): Promise<{ content: string | null; path: string | null }> {\n // 1) Inline (highest priority)\n if (options.styleGuide && typeof options.styleGuide === \"string\") {\n return { content: options.styleGuide, path: null };\n }\n\n // 2) Explicit path\n if (options.styleguidePath && typeof options.styleguidePath === \"string\") {\n const p = resolvePathSpecifier(options.styleguidePath, process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n return { content: null, path: null };\n }\n\n // 3) Env var pin\n const env = process.env.UILINT_STYLEGUIDE_PATH;\n if (env && env.trim()) {\n const p = resolvePathSpecifier(env.trim(), process.cwd());\n if (existsSync(p)) {\n return { content: await readStyleGuide(p), path: p };\n }\n }\n\n // 4) Smarter default: walk upward from the input file dir looking for `.uilint/styleguide.md`\n if (options.inputFile) {\n const absInput = resolvePathSpecifier(options.inputFile, process.cwd());\n const found = findUILintStyleGuideUpwards(dirname(absInput));\n if (found) return { content: await readStyleGuide(found), path: found };\n }\n\n // 5) Fallbacks: cwd, then workspace root (monorepo)\n const cwdPath = findStyleGuidePath(process.cwd());\n if (cwdPath) return { content: await readStyleGuide(cwdPath), path: cwdPath };\n\n const wsRoot = findWorkspaceRoot(process.cwd());\n const wsPath = findStyleGuidePath(wsRoot);\n if (wsPath) return { content: await readStyleGuide(wsPath), path: wsPath };\n\n return { content: null, path: null };\n}\n\nfunction formatScanIssuesText(issues: UILintScanIssue[]): string {\n if (issues.length === 0) return pc.green(\"No issues found.\");\n const lines = issues.map((i) => {\n const line = typeof i.line === \"number\" ? `Line ${i.line}: ` : \"\";\n const loc = i.dataLoc ? ` ${pc.dim(`(${i.dataLoc})`)}` : \"\";\n return `- ${line}${i.message}${loc}`;\n });\n return lines.join(\"\\n\");\n}\n\nexport async function analyze(options: AnalyzeOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) {\n intro(\"Analyze Source Code\");\n }\n\n try {\n debugLog(dbg, \"Input options\", {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n stream: options.stream,\n output: options.output,\n });\n\n // Input\n const sourceCode = await getCodeInput({\n code: options.sourceCode,\n file: options.inputFile\n ? resolvePathSpecifier(options.inputFile)\n : undefined,\n });\n\n debugLog(dbg, \"Source code (high-level)\", {\n length: sourceCode.length,\n lines: sourceCode.split(\"\\n\").length,\n });\n if (dbgFull) {\n debugLog(dbg, \"Source code (full)\", sourceCode);\n } else if (dbg) {\n debugLog(dbg, \"Source code (preview)\", preview(sourceCode, 800));\n }\n\n const resolvedStyle = await resolveStyleGuideForAnalyze({\n styleGuide: options.styleGuide,\n styleguidePath: options.styleguidePath,\n inputFile: options.inputFile,\n });\n\n debugLog(dbg, \"Styleguide resolved\", {\n styleGuideArg:\n options.styleguidePath ?? options.styleGuide ? \"(inline)\" : null,\n styleguideLocation: resolvedStyle.path,\n styleGuideLength: resolvedStyle.content\n ? resolvedStyle.content.length\n : 0,\n });\n if (dbgFull) {\n debugLog(dbg, \"Styleguide contents (full)\", resolvedStyle.content ?? \"\");\n } else if (dbg && resolvedStyle.content) {\n debugLog(\n dbg,\n \"Styleguide contents (preview)\",\n preview(resolvedStyle.content, 800)\n );\n }\n\n if (!resolvedStyle.content && !isJsonOutput) {\n logWarning(\"No styleguide found (analyzing without it)\");\n } else if (resolvedStyle.path && !isJsonOutput) {\n logSuccess(`Using styleguide: ${pc.dim(resolvedStyle.path)}`);\n }\n\n // Prepare Ollama\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n const prepEndNs = nsNow();\n\n const client = await createLLMClient({});\n\n const promptContext = {\n filePath:\n options.filePath ||\n (options.inputFile ? options.inputFile : undefined) ||\n \"component.tsx\",\n componentName: options.componentName,\n componentLine:\n typeof options.componentLine === \"number\"\n ? options.componentLine\n : undefined,\n includeChildren: options.includeChildren === true,\n dataLocs: Array.isArray(options.dataLoc) ? options.dataLoc : undefined,\n };\n\n const prompt = buildSourceScanPrompt(\n sourceCode,\n resolvedStyle.content,\n promptContext\n );\n\n debugLog(dbg, \"LLM request (high-level)\", {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n promptLength: prompt.length,\n promptLines: prompt.split(\"\\n\").length,\n });\n\n if (dbgFull) {\n debugLog(dbg, \"LLM prompt (full)\", prompt);\n } else if (dbg) {\n debugLog(dbg, \"LLM prompt (preview)\", preview(prompt, 1200));\n }\n\n // Debug dump\n if (dbgDump) {\n try {\n const now = new Date();\n const safeStamp = now.toISOString().replace(/[:.]/g, \"-\");\n const resolved = resolve(process.cwd(), dbgDump);\n const dumpFile =\n resolved.endsWith(\".json\") || resolved.endsWith(\".jsonl\")\n ? resolved\n : resolve(resolved, `analyze-debug-${safeStamp}.json`);\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: now.toISOString(),\n command: \"analyze\",\n options: {\n inputFile: options.inputFile,\n sourceCode: options.sourceCode ? \"(provided)\" : undefined,\n styleGuide: options.styleGuide ? \"(inline)\" : undefined,\n styleguidePath: options.styleguidePath,\n styleguideLocation: resolvedStyle.path,\n filePath: options.filePath,\n componentName: options.componentName,\n componentLine: options.componentLine,\n includeChildren: options.includeChildren,\n dataLoc: options.dataLoc,\n model: client.getModel(),\n stream: options.stream,\n output: options.output,\n },\n input: {\n sourceCode,\n sourceLines: sourceCode.split(\"\\n\").length,\n },\n styleGuide: resolvedStyle.content,\n promptContext,\n prompt,\n llmRequest: {\n baseUrl: \"http://localhost:11434\",\n model: client.getModel(),\n format: \"json\",\n stream: options.stream ?? false,\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n debugLog(dbg, `Wrote debug dump to ${dumpFile}`);\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write debug dump\",\n e instanceof Error ? e.message : e\n );\n }\n }\n\n let responseText = \"\";\n if (options.stream) {\n if (!isJsonOutput) {\n const s = createSpinner();\n s.start(\"Analyzing with LLM\");\n let thinkingStarted = false;\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n try {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!thinkingStarted) {\n thinkingStarted = true;\n s.stop(pc.dim(\"[analyze] streaming thinking:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n const maxLen = 60;\n const line =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(line || \"...\")}`);\n },\n });\n s.stop(pc.green(\"✓ \") + \"Analyzing with LLM\");\n\n if (process.stdout.isTTY) {\n const analysisEndNs = nsNow();\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n } catch (e) {\n s.stop(pc.red(\"✗ \") + \"Analyzing with LLM\");\n throw e;\n }\n } else {\n responseText = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: () => {\n // JSON mode: never write progress to stdout\n },\n });\n }\n } else {\n responseText = await client.complete(prompt, { json: true });\n }\n\n const parsed = JSON.parse(responseText) as { issues?: UILintScanIssue[] };\n const issues = Array.isArray(parsed.issues) ? parsed.issues : [];\n\n if (isJsonOutput) {\n printJSON({ issues });\n } else {\n process.stdout.write(formatScanIssuesText(issues) + \"\\n\");\n }\n\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analyze failed\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * Consistency command - analyzes grouped DOM elements for visual inconsistencies\n */\n\nimport { createInterface } from \"readline\";\nimport {\n parseGroupedSnapshot,\n analyzeConsistency,\n formatConsistencyViolations,\n countElements,\n hasAnalyzableGroups,\n type ConsistencyResult,\n} from \"uilint-core\";\nimport { ensureOllamaReady } from \"uilint-core/node\";\nimport {\n intro,\n withSpinner,\n logInfo,\n logError,\n logSuccess,\n logWarning,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface ConsistencyOptions {\n inputJson?: string;\n output?: \"text\" | \"json\";\n}\n\n/**\n * Reads JSON input from stdin\n */\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n const rl = createInterface({ input: process.stdin });\n rl.on(\"line\", (line) => {\n data += line;\n });\n rl.on(\"close\", () => {\n resolve(data);\n });\n });\n}\n\n/**\n * Main consistency analysis command\n */\nexport async function consistency(options: ConsistencyOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n\n if (!isJsonOutput) {\n intro(\"UI Consistency Analysis\");\n }\n\n try {\n // Get input\n let inputJson = options.inputJson;\n if (!inputJson) {\n // Check if stdin has data\n if (!process.stdin.isTTY) {\n inputJson = await readStdin();\n }\n }\n\n if (!inputJson) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", violations: [] });\n } else {\n logError(\"No input provided. Use --input-json or pipe JSON to stdin.\");\n }\n process.exit(1);\n }\n\n // Parse snapshot\n const snapshot = parseGroupedSnapshot(inputJson);\n if (!snapshot) {\n if (isJsonOutput) {\n printJSON({ error: \"Invalid JSON input\", violations: [] });\n } else {\n logError(\"Failed to parse input as GroupedSnapshot.\");\n }\n process.exit(1);\n }\n\n const elementCount = countElements(snapshot);\n\n if (!isJsonOutput) {\n logInfo(`Analyzing ${pc.cyan(String(elementCount))} elements`);\n }\n\n // Check if there are analyzable groups\n if (!hasAnalyzableGroups(snapshot)) {\n const result: ConsistencyResult = {\n violations: [],\n elementCount,\n analysisTime: 0,\n };\n\n if (isJsonOutput) {\n printJSON(result);\n } else {\n logWarning(\"No groups with 2+ elements to analyze.\");\n }\n return;\n }\n\n // Prepare Ollama\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n } else {\n await ensureOllamaReady();\n }\n\n // Analyze with core function\n let result: ConsistencyResult;\n if (isJsonOutput) {\n result = await analyzeConsistency(snapshot, {});\n } else {\n result = await withSpinner(\"Analyzing with LLM\", async () => {\n return await analyzeConsistency(snapshot, {});\n });\n }\n\n // Output results\n if (isJsonOutput) {\n printJSON(result);\n } else {\n console.log();\n console.log(formatConsistencyViolations(result.violations));\n\n if (result.violations.length > 0) {\n logInfo(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n } else {\n logSuccess(\n `Analysis completed in ${pc.dim(String(result.analysisTime) + \"ms\")}`\n );\n }\n }\n\n // Exit with error code if violations found\n if (result.violations.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (isJsonOutput) {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n violations: [],\n });\n } else {\n logError(error instanceof Error ? error.message : \"Analysis failed\");\n }\n process.exit(1);\n }\n}\n","/**\n * Update command - updates existing style guide with new styles\n */\n\nimport { dirname, resolve } from \"path\";\nimport {\n createStyleSummary,\n parseStyleGuide,\n mergeStyleGuides,\n styleGuideToMarkdown,\n} from \"uilint-core\";\nimport {\n readStyleGuide,\n writeStyleGuide,\n findStyleGuidePath,\n ensureOllamaReady,\n readTailwindThemeTokens,\n} from \"uilint-core/node\";\nimport { getInput, type InputOptions } from \"../utils/input.js\";\nimport { createLLMClient, flushLangfuse } from \"../utils/llm-client.js\";\nimport {\n intro,\n outro,\n withSpinner,\n note,\n logSuccess,\n logInfo,\n logError,\n pc,\n} from \"../utils/prompts.js\";\n\nexport interface UpdateOptions extends InputOptions {\n styleguide?: string;\n llm?: boolean;\n}\n\nexport async function update(options: UpdateOptions): Promise<void> {\n intro(\"Update Style Guide\");\n\n try {\n const projectPath = process.cwd();\n const styleGuidePath =\n options.styleguide || findStyleGuidePath(projectPath);\n\n if (!styleGuidePath) {\n logError(\"No style guide found\");\n note(\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} first (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n \"Tip\"\n );\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Using styleguide: ${pc.dim(styleGuidePath)}`);\n\n // Read existing style guide\n const existingContent = await readStyleGuide(styleGuidePath);\n const existingGuide = parseStyleGuide(existingContent);\n\n // Get input\n let snapshot;\n try {\n snapshot = await withSpinner(\"Analyzing project\", async () => {\n return await getInput(options);\n });\n } catch {\n logError(\"No input provided. Use --input-file or pipe HTML to stdin.\");\n await flushLangfuse();\n process.exit(1);\n }\n\n logInfo(`Found ${pc.cyan(String(snapshot.elementCount))} elements`);\n\n const tailwindSearchDir = options.inputFile\n ? dirname(resolve(projectPath, options.inputFile))\n : projectPath;\n const tailwindTheme = readTailwindThemeTokens(tailwindSearchDir);\n\n if (options.llm) {\n // Use LLM to suggest updates\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady();\n });\n\n const result = await withSpinner(\n \"Analyzing styles with LLM\",\n async () => {\n const client = await createLLMClient({});\n const styleSummary = createStyleSummary(snapshot.styles, {\n html: snapshot.html,\n tailwindTheme,\n });\n return await client.analyzeStyles(styleSummary, existingContent);\n }\n );\n\n if (result.issues.length > 0) {\n const suggestions = result.issues.map((issue) => {\n let line = `• ${issue.message}`;\n if (issue.suggestion) {\n line += `\\n ${pc.cyan(\"→\")} ${issue.suggestion}`;\n }\n return line;\n });\n\n note(\n suggestions.join(\"\\n\\n\"),\n `Found ${result.issues.length} suggestion(s)`\n );\n logInfo(\"Edit the styleguide manually to apply these changes.\");\n outro(\"Analysis complete\");\n } else {\n logSuccess(\"Style guide is up to date!\");\n outro(\"No changes needed\");\n }\n } else {\n // Parse new styles and merge\n const updatedContent = await withSpinner(\"Merging styles\", async () => {\n // Create a new guide from detected styles\n const mergedColors = new Map(snapshot.styles.colors);\n for (const m of (snapshot.html || \"\").matchAll(/#[A-Fa-f0-9]{6}\\b/g)) {\n const hex = (m[0] || \"\").toUpperCase();\n if (!hex) continue;\n mergedColors.set(hex, (mergedColors.get(hex) || 0) + 1);\n }\n\n const detectedColors = [...mergedColors.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([value], index) => ({\n name: `Color ${index + 1}`,\n value: value.toUpperCase(),\n usage: \"\",\n }));\n\n const detectedGuide = {\n colors: detectedColors,\n typography: [],\n spacing: [],\n components: [],\n };\n\n // Merge with existing\n const mergedGuide = mergeStyleGuides(existingGuide, detectedGuide);\n return styleGuideToMarkdown(mergedGuide);\n });\n\n // Check if there are any changes\n if (updatedContent === existingContent) {\n logSuccess(\"Style guide is already up to date!\");\n outro(\"No changes needed\");\n return;\n }\n\n // Write updated style guide\n await withSpinner(\"Writing styleguide\", async () => {\n await writeStyleGuide(styleGuidePath, updatedContent);\n });\n\n note(`Updated: ${pc.dim(styleGuidePath)}`, \"Success\");\n outro(\"Style guide updated!\");\n }\n } catch (error) {\n logError(error instanceof Error ? error.message : \"Update failed\");\n await flushLangfuse();\n process.exit(1);\n }\n\n // Flush before normal exit\n await flushLangfuse();\n}\n","/**\n * UILint WebSocket Server\n *\n * Provides real-time lint results for the UI overlay.\n *\n * Protocol:\n * - Client -> Server: { type: 'lint:file', filePath: string, requestId?: string }\n * - Client -> Server: { type: 'lint:element', filePath: string, dataLoc: string, requestId?: string }\n * - Client -> Server: { type: 'subscribe:file', filePath: string }\n * - Client -> Server: { type: 'cache:invalidate', filePath?: string }\n * - Client -> Server: { type: 'vision:analyze', route: string, timestamp: number, screenshot?: string, screenshotFile?: string, manifest: ElementManifest[], requestId?: string }\n * - Client -> Server: { type: 'vision:check', requestId?: string }\n * - Client -> Server: { type: 'config:set', key: string, value: any }\n * - Client -> Server: { type: 'rule:config:set', ruleId: string, severity: 'error'|'warn'|'off', options?: object, requestId?: string }\n * - Server -> Client: { type: 'lint:result', filePath: string, issues: Issue[], requestId?: string }\n * - Server -> Client: { type: 'lint:progress', filePath: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'file:changed', filePath: string }\n * - Server -> Client: { type: 'vision:result', route: string, issues: VisionIssue[], analysisTime: number, error?: string, requestId?: string }\n * - Server -> Client: { type: 'vision:progress', route: string, phase: string, requestId?: string }\n * - Server -> Client: { type: 'vision:status', available: boolean, model?: string, requestId?: string }\n * - Server -> Client: { type: 'config:update', key: string, value: any }\n * - Server -> Client: { type: 'rule:config:result', ruleId: string, severity: string, options?: object, success: boolean, error?: string, requestId?: string }\n * - Server -> Client: { type: 'rule:config:changed', ruleId: string, severity: string, options?: object }\n * - Server -> Client: { type: 'duplicates:indexing:start' }\n * - Server -> Client: { type: 'duplicates:indexing:progress', message: string, current?: number, total?: number }\n * - Server -> Client: { type: 'duplicates:indexing:complete', added: number, modified: number, deleted: number, totalChunks: number, duration: number }\n * - Server -> Client: { type: 'duplicates:indexing:error', error: string }\n * - Server -> Client: { type: 'coverage:setup:start' }\n * - Server -> Client: { type: 'coverage:setup:progress', message: string, phase: string }\n * - Server -> Client: { type: 'coverage:setup:complete', packageAdded: boolean, configModified: boolean, testsRan: boolean, coverageGenerated: boolean, duration: number, error?: string }\n * - Server -> Client: { type: 'coverage:setup:error', error: string }\n * - Client -> Server: { type: 'coverage:request', requestId?: string }\n * - Server -> Client: { type: 'coverage:result', coverage: object, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'coverage:error', error: string, requestId?: string }\n * - Client -> Server: { type: 'source:fetch', filePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:result', filePath: string, content: string, totalLines: number, relativePath: string, requestId?: string }\n * - Server -> Client: { type: 'source:error', filePath: string, error: string, requestId?: string }\n * - Client -> Server: { type: 'screenshot:save', dataUrl: string, route: string, timestamp: number, requestId?: string }\n * - Server -> Client: { type: 'screenshot:saved', filename: string, path: string, requestId?: string }\n * - Server -> Client: { type: 'screenshot:error', error: string, requestId?: string }\n */\n\nimport { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSync } from \"fs\";\nimport { createRequire } from \"module\";\nimport { dirname, resolve, relative, join, parse } from \"path\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { watch, type FSWatcher } from \"chokidar\";\nimport {\n findWorkspaceRoot,\n getVisionAnalyzer as getCoreVisionAnalyzer,\n} from \"uilint-core/node\";\nimport {\n detectNextAppRouter,\n findNextAppRouterProjects,\n} from \"../utils/next-detect.js\";\nimport {\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n logInfo,\n logSuccess,\n logWarning,\n logError,\n pc,\n} from \"../utils/prompts.js\";\nimport { ruleRegistry, type RuleOptionSchema } from \"uilint-eslint\";\nimport {\n findEslintConfigFile,\n updateRuleSeverityInConfig,\n updateRuleConfigInConfig,\n readRuleConfigsFromConfig,\n} from \"../utils/eslint-config-inject.js\";\nimport { detectCoverageSetup } from \"../utils/coverage-detect.js\";\nimport {\n prepareCoverage,\n needsCoveragePreparation,\n} from \"../utils/coverage-prepare.js\";\n\nexport interface ServeOptions {\n port?: number;\n}\n\nexport interface LintIssue {\n line: number;\n column?: number;\n message: string;\n ruleId?: string;\n dataLoc?: string;\n}\n\n// Message types\ninterface LintFileMessage {\n type: \"lint:file\";\n filePath: string;\n requestId?: string;\n}\n\ninterface LintElementMessage {\n type: \"lint:element\";\n filePath: string;\n dataLoc: string;\n requestId?: string;\n}\n\ninterface SubscribeFileMessage {\n type: \"subscribe:file\";\n filePath: string;\n}\n\ninterface CacheInvalidateMessage {\n type: \"cache:invalidate\";\n filePath?: string;\n}\n\ninterface VisionAnalyzeMessage {\n type: \"vision:analyze\";\n route: string;\n timestamp: number;\n screenshot?: string;\n /** Screenshot filename persisted under `.uilint/screenshots/` (e.g. uilint-...png) */\n screenshotFile?: string;\n manifest: ElementManifest[];\n requestId?: string;\n}\n\ninterface VisionCheckMessage {\n type: \"vision:check\";\n requestId?: string;\n}\n\ninterface ConfigSetMessage {\n type: \"config:set\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigSetMessage {\n type: \"rule:config:set\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n requestId?: string;\n}\n\ninterface SourceFetchMessage {\n type: \"source:fetch\";\n filePath: string;\n requestId?: string;\n}\n\ninterface ScreenshotSaveMessage {\n type: \"screenshot:save\";\n dataUrl: string;\n route: string;\n timestamp: number;\n requestId?: string;\n}\n\ntype ClientMessage =\n | LintFileMessage\n | LintElementMessage\n | SubscribeFileMessage\n | CacheInvalidateMessage\n | VisionAnalyzeMessage\n | VisionCheckMessage\n | ConfigSetMessage\n | RuleConfigSetMessage\n | CoverageRequestMessage\n | SourceFetchMessage\n | ScreenshotSaveMessage;\n\ninterface LintResultMessage {\n type: \"lint:result\";\n filePath: string;\n issues: LintIssue[];\n requestId?: string;\n}\n\ninterface LintProgressMessage {\n type: \"lint:progress\";\n filePath: string;\n phase: string;\n requestId?: string;\n}\n\ninterface FileChangedMessage {\n type: \"file:changed\";\n filePath: string;\n}\n\ninterface WorkspaceInfoMessage {\n type: \"workspace:info\";\n /**\n * Absolute path to the Next.js app project root (dir containing app/ or src/app/).\n * This is the base dir we should use to resolve `data-loc` relative file paths.\n */\n appRoot: string;\n workspaceRoot: string;\n serverCwd: string;\n}\n\ninterface WorkspaceCapabilitiesMessage {\n type: \"workspace:capabilities\";\n postToolUseHook: {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n };\n}\n\ninterface VisionResultMessage {\n type: \"vision:result\";\n route: string;\n issues: VisionIssue[];\n analysisTime: number;\n error?: string;\n requestId?: string;\n}\n\ninterface VisionProgressMessage {\n type: \"vision:progress\";\n route: string;\n phase: string;\n requestId?: string;\n}\n\ninterface VisionStatusMessage {\n type: \"vision:status\";\n available: boolean;\n model?: string;\n requestId?: string;\n}\n\ninterface RulesMetadataMessage {\n type: \"rules:metadata\";\n rules: Array<{\n id: string;\n name: string;\n description: string;\n category: \"static\" | \"semantic\";\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Current severity from ESLint config (may differ from default) */\n currentSeverity?: \"error\" | \"warn\" | \"off\";\n /** Current options from ESLint config */\n currentOptions?: Record<string, unknown>;\n docs?: string;\n optionSchema?: RuleOptionSchema;\n defaultOptions?: unknown[];\n }>;\n}\n\ninterface ConfigUpdateMessage {\n type: \"config:update\";\n key: string;\n value: unknown;\n}\n\ninterface RuleConfigResultMessage {\n type: \"rule:config:result\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n success: boolean;\n error?: string;\n requestId?: string;\n}\n\ninterface RuleConfigChangedMessage {\n type: \"rule:config:changed\";\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n options?: Record<string, unknown>;\n}\n\n// Duplicates indexing messages\ninterface DuplicatesIndexingStartMessage {\n type: \"duplicates:indexing:start\";\n}\n\ninterface DuplicatesIndexingProgressMessage {\n type: \"duplicates:indexing:progress\";\n message: string;\n current?: number;\n total?: number;\n}\n\ninterface DuplicatesIndexingCompleteMessage {\n type: \"duplicates:indexing:complete\";\n added: number;\n modified: number;\n deleted: number;\n totalChunks: number;\n duration: number;\n}\n\ninterface DuplicatesIndexingErrorMessage {\n type: \"duplicates:indexing:error\";\n error: string;\n}\n\n// Coverage heatmap messages\ninterface CoverageRequestMessage {\n type: \"coverage:request\";\n requestId?: string;\n}\n\ninterface CoverageResultMessage {\n type: \"coverage:result\";\n coverage: Record<string, unknown>;\n timestamp: number;\n requestId?: string;\n}\n\ninterface CoverageErrorMessage {\n type: \"coverage:error\";\n error: string;\n requestId?: string;\n}\n\n// Coverage setup messages (existing)\ninterface CoverageSetupStartMessage {\n type: \"coverage:setup:start\";\n}\n\ninterface CoverageSetupProgressMessage {\n type: \"coverage:setup:progress\";\n message: string;\n phase: string;\n}\n\ninterface CoverageSetupCompleteMessage {\n type: \"coverage:setup:complete\";\n packageAdded: boolean;\n configModified: boolean;\n testsRan: boolean;\n coverageGenerated: boolean;\n duration: number;\n error?: string;\n}\n\ninterface CoverageSetupErrorMessage {\n type: \"coverage:setup:error\";\n error: string;\n}\n\ninterface SourceResultMessage {\n type: \"source:result\";\n filePath: string;\n content: string;\n totalLines: number;\n relativePath: string;\n requestId?: string;\n}\n\ninterface SourceErrorMessage {\n type: \"source:error\";\n filePath: string;\n error: string;\n requestId?: string;\n}\n\ninterface ScreenshotSavedMessage {\n type: \"screenshot:saved\";\n filename: string;\n path: string;\n requestId?: string;\n}\n\ninterface ScreenshotErrorMessage {\n type: \"screenshot:error\";\n error: string;\n requestId?: string;\n}\n\ntype ServerMessage =\n | LintResultMessage\n | LintProgressMessage\n | FileChangedMessage\n | WorkspaceInfoMessage\n | WorkspaceCapabilitiesMessage\n | VisionResultMessage\n | VisionProgressMessage\n | VisionStatusMessage\n | RulesMetadataMessage\n | ConfigUpdateMessage\n | RuleConfigResultMessage\n | RuleConfigChangedMessage\n | DuplicatesIndexingStartMessage\n | DuplicatesIndexingProgressMessage\n | DuplicatesIndexingCompleteMessage\n | DuplicatesIndexingErrorMessage\n | CoverageResultMessage\n | CoverageErrorMessage\n | CoverageSetupStartMessage\n | CoverageSetupProgressMessage\n | CoverageSetupCompleteMessage\n | CoverageSetupErrorMessage\n | SourceResultMessage\n | SourceErrorMessage\n | ScreenshotSavedMessage\n | ScreenshotErrorMessage;\n\nfunction pickAppRoot(params: { cwd: string; workspaceRoot: string }): string {\n const { cwd, workspaceRoot } = params;\n\n // If started from a Next.js app root (app/ or src/app/ exists), use cwd.\n if (detectNextAppRouter(cwd)) return cwd;\n\n // Otherwise, try to discover Next apps from the workspace root.\n const matches = findNextAppRouterProjects(workspaceRoot, { maxDepth: 5 });\n if (matches.length === 0) return cwd;\n if (matches.length === 1) return matches[0]!.projectPath;\n\n // Prefer a project that contains the current cwd (common in monorepos).\n const containing = matches.find(\n (m) => cwd === m.projectPath || cwd.startsWith(m.projectPath + \"/\")\n );\n if (containing) return containing.projectPath;\n\n // Fallback: pick the first match deterministically.\n return matches[0]!.projectPath;\n}\n\n/**\n * Detect if a post-tool-use hook is configured for Claude or Cursor.\n * These hooks can automatically run ESLint when files are edited.\n */\nfunction detectPostToolUseHook(projectRoot: string): {\n enabled: boolean;\n provider: \"claude\" | \"cursor\" | null;\n} {\n // Check Claude settings.json for PostToolUse hooks\n const claudeSettingsPath = join(projectRoot, \".claude\", \"settings.json\");\n if (existsSync(claudeSettingsPath)) {\n try {\n const content = readFileSync(claudeSettingsPath, \"utf-8\");\n const settings = JSON.parse(content);\n const hooks = settings.hooks?.PostToolUse;\n if (Array.isArray(hooks)) {\n // Check if any hook matches Edit or Write tools\n const hasEditHook = hooks.some((h: { matcher?: string }) =>\n h.matcher?.includes(\"Edit\") || h.matcher?.includes(\"Write\")\n );\n if (hasEditHook) {\n return { enabled: true, provider: \"claude\" };\n }\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n // Check Cursor hooks.json\n const cursorHooksPath = join(projectRoot, \".cursor\", \"hooks.json\");\n if (existsSync(cursorHooksPath)) {\n try {\n const content = readFileSync(cursorHooksPath, \"utf-8\");\n const hooks = JSON.parse(content);\n if (hooks.hooks?.afterFileEdit?.length > 0) {\n return { enabled: true, provider: \"cursor\" };\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n\n return { enabled: false, provider: null };\n}\n\n// Simple in-memory cache\ninterface CacheEntry {\n issues: LintIssue[];\n mtimeMs: number;\n timestamp: number;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// ESLint instances cached per detected project root\nconst eslintInstances = new Map<string, unknown>();\n\n// Vision analyzer instance (lazy loaded)\ntype VisionIssue = {\n elementText: string;\n dataLoc?: string;\n message: string;\n category: string;\n severity: string;\n suggestion?: string;\n};\n\ntype ElementManifest = {\n id: string;\n text: string;\n dataLoc: string;\n rect: { x: number; y: number; width: number; height: number };\n tagName: string;\n role?: string;\n instanceCount?: number;\n};\n\nlet visionAnalyzer: ReturnType<typeof getCoreVisionAnalyzer> | null = null;\n\nfunction getVisionAnalyzerInstance(): ReturnType<typeof getCoreVisionAnalyzer> {\n if (!visionAnalyzer) {\n visionAnalyzer = getCoreVisionAnalyzer();\n }\n return visionAnalyzer;\n}\n\n// Default styleguide search root for vision analysis (set when `serve()` starts)\nlet serverAppRootForVision = process.cwd();\n\nfunction isValidScreenshotFilename(filename: string): boolean {\n // Only allow alphanumeric, hyphens, underscores, and dots; must end with a safe image extension.\n const validPattern = /^[a-zA-Z0-9_-]+\\.(png|jpeg|jpg)$/;\n return validPattern.test(filename) && !filename.includes(\"..\");\n}\n\n// Cache resolved paths for incoming filePath strings\nconst resolvedPathCache = new Map<string, string>();\n\n// File subscriptions: absolutePath -> Set of clients (and the original client filePath string)\nconst subscriptions = new Map<\n string,\n Set<{ ws: WebSocket; clientFilePath: string }>\n>();\n\n// File watcher\nlet fileWatcher: FSWatcher | null = null;\n\n// Basic client tracking for CLI feedback\nlet connectedClients = 0;\n\n// Local require (from uilint deps) for TSX parsing\nconst localRequire = createRequire(import.meta.url);\n\ntype JsxElementSpan = {\n start: number;\n end: number;\n dataLoc: string;\n};\n\nfunction buildLineStarts(code: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) starts.push(i + 1); // \\n\n }\n return starts;\n}\n\nfunction offsetFromLineCol(\n lineStarts: number[],\n line1: number,\n col0: number,\n codeLength: number\n): number {\n const lineIndex = Math.max(0, Math.min(lineStarts.length - 1, line1 - 1));\n const base = lineStarts[lineIndex] ?? 0;\n return Math.max(0, Math.min(codeLength, base + Math.max(0, col0)));\n}\n\nfunction buildJsxElementSpans(\n code: string,\n dataLocFile: string\n): JsxElementSpan[] {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { parse } = localRequire(\"@typescript-eslint/typescript-estree\") as {\n parse: (src: string, options: Record<string, unknown>) => any;\n };\n\n const ast = parse(code, {\n loc: true,\n range: true,\n jsx: true,\n comment: false,\n errorOnUnknownASTType: false,\n });\n\n const spans: JsxElementSpan[] = [];\n\n function walk(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Prefer mapping to JSXElement range so we can capture nested ownership precisely.\n if (node.type === \"JSXElement\") {\n const range = node.range as [number, number] | undefined;\n const opening = node.openingElement;\n const loc = opening?.loc?.start;\n if (\n range &&\n typeof range[0] === \"number\" &&\n typeof range[1] === \"number\" &&\n loc &&\n typeof loc.line === \"number\" &&\n typeof loc.column === \"number\"\n ) {\n const dataLoc = `${dataLocFile}:${loc.line}:${loc.column}`;\n spans.push({ start: range[0], end: range[1], dataLoc });\n }\n }\n\n for (const key of Object.keys(node)) {\n const child = (node as any)[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item);\n } else if (child && typeof child === \"object\") {\n walk(child);\n }\n }\n }\n\n walk(ast);\n\n // Keep spans small-first to make “smallest containing span” selection fast.\n spans.sort((a, b) => a.end - a.start - (b.end - b.start));\n return spans;\n}\n\nfunction mapMessageToDataLoc(params: {\n spans: JsxElementSpan[];\n lineStarts: number[];\n codeLength: number;\n messageLine1: number;\n messageCol1?: number;\n}): string | undefined {\n const col0 =\n typeof params.messageCol1 === \"number\"\n ? Math.max(0, params.messageCol1 - 1)\n : 0;\n const offset = offsetFromLineCol(\n params.lineStarts,\n params.messageLine1,\n col0,\n params.codeLength\n );\n\n // Pick the smallest JSXElement range that contains this offset.\n for (const s of params.spans) {\n if (s.start <= offset && offset < s.end) return s.dataLoc;\n }\n return undefined;\n}\n\n/**\n * Known ESLint config filenames (flat + legacy).\n */\nconst ESLINT_CONFIG_FILES = [\n // Flat config (ESLint v9+)\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n // Legacy config\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n];\n\n/**\n * Find a project root directory for ESLint by walking upward from a file dir.\n */\nfunction findESLintCwd(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n for (const cfg of ESLINT_CONFIG_FILES) {\n if (existsSync(join(dir, cfg))) return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\nfunction normalizePathSlashes(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\n/**\n * Match `jsx-loc-plugin` behavior:\n * - Use a stable, project-relative path when possible, otherwise absolute.\n */\nfunction normalizeDataLocFilePath(\n absoluteFilePath: string,\n projectCwd: string\n): string {\n const abs = normalizePathSlashes(resolve(absoluteFilePath));\n const cwd = normalizePathSlashes(resolve(projectCwd));\n if (abs === cwd || abs.startsWith(cwd + \"/\")) {\n return normalizePathSlashes(relative(cwd, abs));\n }\n return abs;\n}\n\nfunction resolveRequestedFilePath(filePath: string): string {\n // Absolute (POSIX) or Windows drive path\n if (filePath.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(filePath)) {\n return resolve(filePath);\n }\n\n const cached = resolvedPathCache.get(filePath);\n if (cached) return cached;\n\n const cwd = process.cwd();\n const fromCwd = resolve(cwd, filePath);\n if (existsSync(fromCwd)) {\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n }\n\n const wsRoot = findWorkspaceRoot(cwd);\n const fromWs = resolve(wsRoot, filePath);\n if (existsSync(fromWs)) {\n resolvedPathCache.set(filePath, fromWs);\n return fromWs;\n }\n\n // Monorepo helper: try common workspace folders (apps/*, packages/*)\n // Example: filePath=\"app/page.tsx\" -> apps/test-app/app/page.tsx\n for (const top of [\"apps\", \"packages\"]) {\n const base = join(wsRoot, top);\n if (!existsSync(base)) continue;\n try {\n const entries = readdirSync(base, { withFileTypes: true });\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const p = resolve(base, ent.name, filePath);\n if (existsSync(p)) {\n resolvedPathCache.set(filePath, p);\n return p;\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Cache deterministic fallback so repeated requests don't thrash\n resolvedPathCache.set(filePath, fromCwd);\n return fromCwd;\n}\n\nasync function getESLintForProject(projectCwd: string): Promise<any | null> {\n const cached = eslintInstances.get(projectCwd);\n if (cached) return cached as any;\n\n try {\n const req = createRequire(join(projectCwd, \"package.json\"));\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = req(\"eslint\");\n const ESLintCtor =\n mod?.ESLint ?? mod?.default?.ESLint ?? mod?.default ?? mod;\n if (!ESLintCtor) return null;\n\n const eslint = new ESLintCtor({ cwd: projectCwd });\n eslintInstances.set(projectCwd, eslint);\n return eslint;\n } catch {\n return null;\n }\n}\n\n/**\n * Lint a file and return issues\n */\nasync function lintFile(\n filePath: string,\n onProgress: (phase: string) => void\n): Promise<LintIssue[]> {\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Check if file exists\n if (!existsSync(absolutePath)) {\n onProgress(`File not found: ${pc.dim(absolutePath)}`);\n return [];\n }\n\n const mtimeMs = (() => {\n try {\n return statSync(absolutePath).mtimeMs;\n } catch {\n return 0;\n }\n })();\n\n // Check cache (mtime-based)\n const cached = cache.get(absolutePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n onProgress(\"Cache hit (unchanged)\");\n return cached.issues;\n }\n\n const fileDir = dirname(absolutePath);\n const projectCwd = findESLintCwd(fileDir);\n\n onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);\n\n const eslint = await getESLintForProject(projectCwd);\n if (!eslint) {\n logWarning(\n `ESLint not found in project. Install it in ${pc.dim(\n projectCwd\n )} to enable server-side linting.`\n );\n onProgress(\"ESLint not available (install eslint in this project)\");\n return [];\n }\n\n try {\n onProgress(\"Running ESLint...\");\n const results = await eslint.lintFiles([absolutePath]);\n const messages =\n Array.isArray(results) && results.length > 0\n ? results[0].messages || []\n : [];\n\n const dataLocFile = normalizeDataLocFilePath(absolutePath, projectCwd);\n let spans: JsxElementSpan[] = [];\n let lineStarts: number[] = [];\n let codeLength = 0;\n\n try {\n onProgress(\"Building JSX map...\");\n const code = readFileSync(absolutePath, \"utf-8\");\n codeLength = code.length;\n lineStarts = buildLineStarts(code);\n spans = buildJsxElementSpans(code, dataLocFile);\n onProgress(`JSX map: ${spans.length} element(s)`);\n } catch (e) {\n // If parsing fails, we still return ESLint messages (unmapped).\n onProgress(\"JSX map failed (falling back to unmapped issues)\");\n console.error(\"[uilint-serve] JSX map failed:\", e);\n spans = [];\n lineStarts = [];\n codeLength = 0;\n }\n\n const issues: LintIssue[] = messages\n .filter((m: any) => typeof m?.message === \"string\")\n .map((m: any) => {\n const line = typeof m.line === \"number\" ? m.line : 1;\n const column = typeof m.column === \"number\" ? m.column : undefined;\n const mappedDataLoc =\n spans.length > 0 && lineStarts.length > 0 && codeLength > 0\n ? mapMessageToDataLoc({\n spans,\n lineStarts,\n codeLength,\n messageLine1: line,\n messageCol1: column,\n })\n : undefined;\n return {\n line,\n column,\n message: m.message,\n ruleId: typeof m.ruleId === \"string\" ? m.ruleId : undefined,\n dataLoc: mappedDataLoc,\n } satisfies LintIssue;\n });\n\n const mappedCount = issues.filter((i) => Boolean(i.dataLoc)).length;\n if (issues.length > 0) {\n onProgress(\n `Mapped ${mappedCount}/${issues.length} issue(s) to JSX elements`\n );\n }\n\n cache.set(absolutePath, { issues, mtimeMs, timestamp: Date.now() });\n return issues;\n } catch (error) {\n console.error(\"[uilint-serve] ESLint failed:\", error);\n return [];\n }\n}\n\n/**\n * Send message to client\n */\nfunction sendMessage(ws: WebSocket, message: ServerMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n}\n\n/**\n * Handle incoming client message\n */\nasync function handleMessage(ws: WebSocket, data: string): Promise<void> {\n let message: ClientMessage;\n try {\n message = JSON.parse(data) as ClientMessage;\n } catch {\n return;\n }\n\n // Server-side tracing to confirm activity\n if (message.type === \"lint:file\" || message.type === \"lint:element\") {\n const fp = (message as any).filePath as string | undefined;\n const rid = (message as any).requestId as string | undefined;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(message.type)} ${pc.dim(fp ?? \"\")}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n } else if (message.type === \"subscribe:file\") {\n logInfo(`${pc.dim(\"[ws]\")} subscribe:file ${pc.dim(message.filePath)}`);\n } else if (message.type === \"cache:invalidate\") {\n logInfo(\n `${pc.dim(\"[ws]\")} cache:invalidate ${pc.dim(\n message.filePath ?? \"(all)\"\n )}`\n );\n } else if (message.type === \"vision:analyze\") {\n // Logged in handler for more detailed output\n } else if (message.type === \"vision:check\") {\n // Logged in handler\n } else if (message.type === \"config:set\") {\n // Logged in handler\n } else if (message.type === \"screenshot:save\") {\n const rid = (message as ScreenshotSaveMessage).requestId;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"screenshot:save\")} ${pc.dim(message.route)}${\n rid ? ` ${pc.dim(`(req ${rid})`)}` : \"\"\n }`\n );\n }\n\n switch (message.type) {\n case \"lint:file\": {\n const { filePath, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const resolved = resolveRequestedFilePath(filePath);\n if (!existsSync(resolved)) {\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n logWarning(\n [\n `${pc.dim(\"[ws]\")} File not found for request`,\n ` filePath: ${pc.dim(filePath)}`,\n ` resolved: ${pc.dim(resolved)}`,\n ` cwd: ${pc.dim(cwd)}`,\n ` wsRoot: ${pc.dim(wsRoot)}`,\n ` hint: In monorepos, ensure paths like ${pc.dim(\n \"app/page.tsx\"\n )} exist under ${pc.dim(\"apps/*/\")} or use absolute paths.`,\n ].join(\"\\n\")\n );\n }\n\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} lint:file done ${pc.dim(filePath)} → ${pc.bold(\n `${issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${issues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, { type: \"lint:result\", filePath, requestId, issues });\n break;\n }\n\n case \"lint:element\": {\n const { filePath, dataLoc, requestId } = message;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: \"Starting...\",\n });\n\n const startedAt = Date.now();\n const issues = await lintFile(filePath, (phase) => {\n sendMessage(ws, { type: \"lint:progress\", filePath, requestId, phase });\n });\n\n // Filter to only issues matching the dataLoc\n const filteredIssues = issues.filter(\n (issue) => issue.dataLoc === dataLoc\n );\n\n const elapsed = Date.now() - startedAt;\n sendMessage(ws, {\n type: \"lint:progress\",\n filePath,\n requestId,\n phase: `Done (${filteredIssues.length} issues, ${elapsed}ms)`,\n });\n sendMessage(ws, {\n type: \"lint:result\",\n filePath,\n requestId,\n issues: filteredIssues,\n });\n break;\n }\n\n case \"subscribe:file\": {\n const { filePath } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n // Add to subscriptions\n let subscribers = subscriptions.get(absolutePath);\n if (!subscribers) {\n subscribers = new Set();\n subscriptions.set(absolutePath, subscribers);\n\n // Start watching this file\n if (fileWatcher) {\n fileWatcher.add(absolutePath);\n }\n }\n subscribers.add({ ws, clientFilePath: filePath });\n break;\n }\n\n case \"cache:invalidate\": {\n const { filePath } = message;\n if (filePath) {\n const absolutePath = resolveRequestedFilePath(filePath);\n cache.delete(absolutePath);\n } else {\n cache.clear();\n }\n break;\n }\n\n case \"vision:analyze\": {\n const {\n route,\n timestamp,\n screenshot,\n screenshotFile,\n manifest,\n requestId,\n } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:analyze\")} ${pc.dim(route)}${\n requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"\n }`\n );\n\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase: \"Starting vision analysis...\",\n });\n\n const startedAt = Date.now();\n const analyzer = getVisionAnalyzerInstance();\n\n try {\n const screenshotBytes =\n typeof screenshot === \"string\" ? Buffer.byteLength(screenshot) : 0;\n const analyzerModel =\n typeof (analyzer as any).getModel === \"function\"\n ? ((analyzer as any).getModel() as string)\n : undefined;\n const analyzerBaseUrl =\n typeof (analyzer as any).getBaseUrl === \"function\"\n ? ((analyzer as any).getBaseUrl() as string)\n : undefined;\n logInfo(\n [\n `${pc.dim(\"[ws]\")} ${pc.dim(\"vision\")} details`,\n ` route: ${pc.dim(route)}`,\n ` requestId: ${pc.dim(requestId ?? \"(none)\")}`,\n ` manifest: ${pc.dim(String(manifest.length))} element(s)`,\n ` screenshot: ${pc.dim(\n screenshot ? `${Math.round(screenshotBytes / 1024)}kb` : \"none\"\n )}`,\n ` screenshotFile: ${pc.dim(screenshotFile ?? \"(none)\")}`,\n ` ollamaUrl: ${pc.dim(analyzerBaseUrl ?? \"(default)\")}`,\n ` visionModel: ${pc.dim(analyzerModel ?? \"(default)\")}`,\n ].join(\"\\n\")\n );\n\n if (!screenshot) {\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: \"No screenshot provided for vision analysis\",\n requestId,\n });\n break;\n }\n\n const result = await runVisionAnalysis({\n imageBase64: screenshot,\n manifest,\n projectPath: serverAppRootForVision,\n // In the overlay/server context, default to upward search from app root.\n baseUrl: analyzerBaseUrl,\n model: analyzerModel,\n analyzer: analyzer as any,\n onPhase: (phase) => {\n sendMessage(ws, {\n type: \"vision:progress\",\n route,\n requestId,\n phase,\n });\n },\n });\n\n // Write a markdown report alongside the saved screenshot (best-effort).\n if (typeof screenshotFile === \"string\" && screenshotFile.length > 0) {\n if (!isValidScreenshotFilename(screenshotFile)) {\n logWarning(\n `Skipping vision report write: invalid screenshotFile ${pc.dim(\n screenshotFile\n )}`\n );\n } else {\n const screenshotsDir = join(\n serverAppRootForVision,\n \".uilint\",\n \"screenshots\"\n );\n const imagePath = join(screenshotsDir, screenshotFile);\n try {\n if (!existsSync(imagePath)) {\n logWarning(\n `Skipping vision report write: screenshot file not found ${pc.dim(\n imagePath\n )}`\n );\n } else {\n const report = writeVisionMarkdownReport({\n imagePath,\n route,\n timestamp,\n visionModel: result.visionModel,\n baseUrl: result.baseUrl,\n analysisTimeMs: result.analysisTime,\n prompt: result.prompt ?? null,\n rawResponse: result.rawResponse ?? null,\n metadata: {\n screenshotFile: parse(imagePath).base,\n appRoot: serverAppRootForVision,\n manifestElements: manifest.length,\n requestId: requestId ?? null,\n },\n });\n logInfo(\n `${pc.dim(\"[ws]\")} wrote vision report ${pc.dim(\n report.outPath\n )}`\n );\n }\n } catch (e) {\n logWarning(\n `Failed to write vision report for ${pc.dim(screenshotFile)}: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n }\n }\n }\n\n const elapsed = Date.now() - startedAt;\n logInfo(\n `${pc.dim(\"[ws]\")} vision:analyze done ${pc.dim(route)} → ${pc.bold(\n `${result.issues.length}`\n )} issue(s) ${pc.dim(`(${elapsed}ms)`)}`\n );\n\n if (result.rawResponse) {\n logInfo(\n `${pc.dim(\"[ws]\")} vision rawResponse ${pc.dim(\n `${result.rawResponse.length} chars`\n )}`\n );\n }\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: result.issues,\n analysisTime: result.analysisTime,\n requestId,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? error.stack : undefined;\n logError(\n [\n `Vision analysis failed`,\n ` route: ${route}`,\n ` requestId: ${requestId ?? \"(none)\"}`,\n ` error: ${errorMessage}`,\n stack ? ` stack:\\n${stack}` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n );\n\n sendMessage(ws, {\n type: \"vision:result\",\n route,\n issues: [],\n analysisTime: Date.now() - startedAt,\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"vision:check\": {\n const { requestId } = message;\n logInfo(\n `${pc.dim(\"[ws]\")} ${pc.bold(\"vision:check\")}${requestId ? ` ${pc.dim(`(req ${requestId})`)}` : \"\"}`\n );\n\n try {\n const analyzer = getVisionAnalyzerInstance();\n const model =\n typeof (analyzer as any).getModel === \"function\"\n ? (analyzer as any).getModel()\n : undefined;\n\n sendMessage(ws, {\n type: \"vision:status\",\n available: true,\n model,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"vision:status\",\n available: false,\n requestId,\n });\n }\n break;\n }\n\n case \"config:set\": {\n const { key, value } = message;\n handleConfigSet(key, value);\n break;\n }\n\n case \"rule:config:set\": {\n const { ruleId, severity, options, requestId } = message;\n handleRuleConfigSet(ws, ruleId, severity, options, requestId);\n break;\n }\n\n case \"source:fetch\": {\n const { filePath, requestId } = message;\n const absolutePath = resolveRequestedFilePath(filePath);\n\n if (!existsSync(absolutePath)) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: \"File not found\",\n requestId,\n });\n break;\n }\n\n try {\n const content = readFileSync(absolutePath, \"utf-8\");\n const totalLines = content.split(\"\\n\").length;\n const relativePath = normalizeDataLocFilePath(absolutePath, serverAppRootForVision);\n\n sendMessage(ws, {\n type: \"source:result\",\n filePath,\n content,\n totalLines,\n relativePath,\n requestId,\n });\n } catch (error) {\n sendMessage(ws, {\n type: \"source:error\",\n filePath,\n error: error instanceof Error ? error.message : \"Failed to read file\",\n requestId,\n });\n }\n break;\n }\n\n case \"coverage:request\": {\n const { requestId } = message;\n try {\n const coveragePath = join(serverAppRootForVision, \"coverage\", \"coverage-final.json\");\n\n if (!existsSync(coveragePath)) {\n sendMessage(ws, {\n type: \"coverage:error\",\n error: \"Coverage data not found. Run tests with coverage first (e.g., `vitest run --coverage`)\",\n requestId,\n });\n break;\n }\n\n const coverageData = JSON.parse(readFileSync(coveragePath, \"utf-8\"));\n logInfo(`${pc.dim(\"[ws]\")} coverage:result ${pc.dim(`${Object.keys(coverageData).length} files`)}`);\n\n sendMessage(ws, {\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n requestId,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} coverage:error ${errorMessage}`);\n sendMessage(ws, {\n type: \"coverage:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n\n case \"screenshot:save\": {\n const { dataUrl, route, timestamp, requestId } = message;\n\n try {\n // Validate the dataUrl is a valid base64 PNG data URL\n if (!dataUrl || typeof dataUrl !== \"string\") {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a non-empty string\",\n requestId,\n });\n break;\n }\n\n const dataUrlPattern = /^data:image\\/png;base64,/;\n if (!dataUrlPattern.test(dataUrl)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: \"Invalid dataUrl: must be a base64 PNG data URL (data:image/png;base64,...)\",\n requestId,\n });\n break;\n }\n\n // Extract base64 data\n const base64Data = dataUrl.replace(dataUrlPattern, \"\");\n\n // Sanitize route for filename (replace / with -, remove special chars)\n const sanitizedRoute = route\n .replace(/^\\//, \"\") // Remove leading slash\n .replace(/\\//g, \"-\") // Replace slashes with dashes\n .replace(/[^a-zA-Z0-9_-]/g, \"_\") // Replace special chars with underscore\n || \"root\"; // Default to \"root\" for empty route\n\n // Generate filename\n const filename = `uilint-${timestamp}-${sanitizedRoute}.png`;\n\n // Validate generated filename\n if (!isValidScreenshotFilename(filename)) {\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: `Generated filename is invalid: ${filename}`,\n requestId,\n });\n break;\n }\n\n // Create screenshots directory if needed\n const screenshotsDir = join(serverAppRootForVision, \".uilint\", \"screenshots\");\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n // Write the image file\n const imagePath = join(screenshotsDir, filename);\n const imageBuffer = Buffer.from(base64Data, \"base64\");\n writeFileSync(imagePath, imageBuffer);\n\n // Write JSON sidecar with metadata\n const sidecarFilename = filename.replace(/\\.png$/, \".json\");\n const sidecarPath = join(screenshotsDir, sidecarFilename);\n const sidecarData = {\n route,\n timestamp,\n filename,\n savedAt: new Date().toISOString(),\n };\n writeFileSync(sidecarPath, JSON.stringify(sidecarData, null, 2));\n\n logInfo(\n `${pc.dim(\"[ws]\")} screenshot:saved ${pc.dim(filename)} ${pc.dim(\n `(${Math.round(imageBuffer.length / 1024)}kb)`\n )}`\n );\n\n // Send success response\n sendMessage(ws, {\n type: \"screenshot:saved\",\n filename,\n path: imagePath,\n requestId,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} screenshot:error ${errorMessage}`);\n sendMessage(ws, {\n type: \"screenshot:error\",\n error: errorMessage,\n requestId,\n });\n }\n break;\n }\n }\n}\n\n/**\n * Handle client disconnect\n */\nfunction handleDisconnect(ws: WebSocket): void {\n // Remove from all subscriptions\n for (const [filePath, subscribers] of subscriptions.entries()) {\n for (const entry of subscribers) {\n if (entry.ws === ws) {\n subscribers.delete(entry);\n }\n }\n if (subscribers.size === 0) {\n subscriptions.delete(filePath);\n // Stop watching if no subscribers\n if (fileWatcher) {\n fileWatcher.unwatch(filePath);\n }\n }\n }\n}\n\n/**\n * Handle file change\n */\nfunction handleFileChange(filePath: string): void {\n const subscribers = subscriptions.get(filePath);\n if (!subscribers || subscribers.size === 0) return;\n\n // Invalidate cache\n cache.delete(filePath);\n\n // Notify subscribers\n for (const { ws, clientFilePath } of subscribers) {\n sendMessage(ws, { type: \"file:changed\", filePath: clientFilePath });\n }\n}\n\n/**\n * Handle coverage-final.json file change - broadcast new coverage data to all clients\n */\nfunction handleCoverageFileChange(filePath: string): void {\n try {\n const coverageData = JSON.parse(readFileSync(filePath, \"utf-8\"));\n logInfo(`${pc.dim(\"[ws]\")} coverage:changed ${pc.dim(`${Object.keys(coverageData).length} files`)}`);\n\n broadcast({\n type: \"coverage:result\",\n coverage: coverageData,\n timestamp: Date.now(),\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logError(`${pc.dim(\"[ws]\")} Failed to read coverage data: ${errorMessage}`);\n broadcast({\n type: \"coverage:error\",\n error: `Failed to read coverage: ${errorMessage}`,\n });\n }\n}\n\n// In-memory config store (runtime only, for broadcasting to clients)\nconst configStore = new Map<string, unknown>();\n\n// Track connected clients for broadcasting\nlet connectedClientsSet = new Set<WebSocket>();\n\n/**\n * Broadcast config update to all connected clients\n */\nfunction broadcastConfigUpdate(key: string, value: unknown): void {\n const message: ConfigUpdateMessage = { type: \"config:update\", key, value };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Handle config:set message\n */\nfunction handleConfigSet(key: string, value: unknown): void {\n configStore.set(key, value);\n logInfo(`${pc.dim(\"[ws]\")} config:set ${pc.bold(key)} = ${pc.dim(JSON.stringify(value))}`);\n broadcastConfigUpdate(key, value);\n}\n\n/**\n * Broadcast rule config change to all connected clients\n */\nfunction broadcastRuleConfigChange(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): void {\n const message: RuleConfigChangedMessage = {\n type: \"rule:config:changed\",\n ruleId,\n severity,\n options,\n };\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n/**\n * Broadcast a message to all connected clients\n */\nfunction broadcast(message: ServerMessage): void {\n for (const ws of connectedClientsSet) {\n sendMessage(ws, message);\n }\n}\n\n// Duplicates indexing state\nlet isIndexing = false;\nlet reindexTimeout: NodeJS.Timeout | null = null;\nconst pendingIndexChanges = new Set<string>();\n\n/**\n * Build or update the duplicates index\n * Runs incrementally - very fast if no files changed\n */\nasync function buildDuplicatesIndex(appRoot: string): Promise<void> {\n if (isIndexing) {\n // Already indexing, skip\n return;\n }\n\n isIndexing = true;\n logInfo(`${pc.blue(\"Building duplicates index...\")}`);\n broadcast({ type: \"duplicates:indexing:start\" });\n\n try {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n const result = await indexDirectory(appRoot, {\n onProgress: (message, current, total) => {\n // Log to console\n if (current !== undefined && total !== undefined) {\n logInfo(` ${message} (${current}/${total})`);\n } else {\n logInfo(` ${message}`);\n }\n // Broadcast to connected clients\n broadcast({\n type: \"duplicates:indexing:progress\",\n message,\n current,\n total,\n });\n },\n });\n\n logSuccess(\n `${pc.green(\"Index complete:\")} ${result.totalChunks} chunks (${result.added} added, ${result.modified} modified, ${result.deleted} deleted) in ${(result.duration / 1000).toFixed(1)}s`\n );\n broadcast({\n type: \"duplicates:indexing:complete\",\n added: result.added,\n modified: result.modified,\n deleted: result.deleted,\n totalChunks: result.totalChunks,\n duration: result.duration,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logError(`Index failed: ${msg}`);\n broadcast({ type: \"duplicates:indexing:error\", error: msg });\n } finally {\n isIndexing = false;\n }\n}\n\n/**\n * Schedule a debounced re-index when source files change\n */\nfunction scheduleReindex(appRoot: string, filePath: string): void {\n // Only reindex for source files\n if (!/\\.(tsx?|jsx?)$/.test(filePath)) return;\n\n pendingIndexChanges.add(filePath);\n\n if (reindexTimeout) clearTimeout(reindexTimeout);\n reindexTimeout = setTimeout(async () => {\n const count = pendingIndexChanges.size;\n pendingIndexChanges.clear();\n logInfo(`${pc.dim(`[index] ${count} file(s) changed, updating index...`)}`);\n await buildDuplicatesIndex(appRoot);\n }, 2000); // 2 second debounce\n}\n\n// Coverage preparation state\nlet isPreparingCoverage = false;\n\n/**\n * Check if require-test-coverage rule is enabled in ESLint config\n */\nfunction isCoverageRuleEnabled(appRoot: string): boolean {\n const eslintConfigPath = findEslintConfigFile(appRoot);\n if (!eslintConfigPath) return false;\n\n const ruleConfigs = readRuleConfigsFromConfig(eslintConfigPath);\n const coverageConfig = ruleConfigs.get(\"require-test-coverage\");\n if (!coverageConfig) return false;\n\n // Rule is enabled if severity is not \"off\"\n return coverageConfig.severity !== \"off\";\n}\n\n/**\n * Prepare coverage data for require-test-coverage rule.\n * Runs only on startup:\n * - Installs @vitest/coverage-v8 if missing\n * - Adds coverage config to vitest.config.ts if missing\n * - Runs tests with coverage to generate coverage-final.json\n */\nasync function buildCoverageData(appRoot: string): Promise<void> {\n if (isPreparingCoverage) return;\n\n isPreparingCoverage = true;\n\n try {\n // Check if coverage rule is enabled\n if (!isCoverageRuleEnabled(appRoot)) {\n logInfo(`${pc.dim(\"Coverage rule not enabled, skipping preparation\")}`);\n return;\n }\n\n // Detect current setup\n const setup = detectCoverageSetup(appRoot);\n\n // Check if preparation needed\n if (!needsCoveragePreparation(setup)) {\n logInfo(`${pc.dim(\"Coverage data is up-to-date\")}`);\n return;\n }\n\n // Run preparation\n logInfo(`${pc.blue(\"Preparing coverage data...\")}`);\n broadcast({ type: \"coverage:setup:start\" });\n\n // Check environment variables for skipping\n const skipPackageInstall = process.env.UILINT_SKIP_COVERAGE_INSTALL === \"1\";\n const skipTests = process.env.UILINT_SKIP_COVERAGE_TESTS === \"1\";\n\n const result = await prepareCoverage({\n appRoot,\n skipPackageInstall,\n skipTests,\n onProgress: (message, phase) => {\n logInfo(` ${message}`);\n broadcast({ type: \"coverage:setup:progress\", message, phase });\n },\n });\n\n if (result.error) {\n // Continue with warning on test failures (don't block server startup)\n logWarning(`Coverage preparation completed with errors: ${result.error}`);\n } else {\n const parts = [];\n if (result.packageAdded) parts.push(\"package installed\");\n if (result.configModified) parts.push(\"config modified\");\n if (result.testsRan) parts.push(\"tests ran\");\n if (result.coverageGenerated) parts.push(\"coverage generated\");\n\n logSuccess(\n `${pc.green(\"Coverage prepared:\")} ${parts.join(\", \")} in ${(result.duration / 1000).toFixed(1)}s`\n );\n }\n\n broadcast({\n type: \"coverage:setup:complete\",\n ...result,\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logError(`Coverage preparation failed: ${msg}`);\n broadcast({ type: \"coverage:setup:error\", error: msg });\n } finally {\n isPreparingCoverage = false;\n }\n}\n\n/**\n * Handle rule:config:set message\n * Updates the ESLint config file and broadcasts the change to all clients\n */\nfunction handleRuleConfigSet(\n ws: WebSocket,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n requestId?: string\n): void {\n logInfo(\n `${pc.dim(\"[ws]\")} rule:config:set ${pc.bold(ruleId)} -> ${pc.dim(severity)}${\n options ? ` with options` : \"\"\n }`\n );\n\n // Find the ESLint config file\n const configPath = findEslintConfigFile(serverAppRootForVision);\n if (!configPath) {\n const error = `No ESLint config file found in ${serverAppRootForVision}`;\n logError(`${pc.dim(\"[ws]\")} ${error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error,\n requestId,\n });\n return;\n }\n\n // Update the config file\n let result;\n if (options && Object.keys(options).length > 0) {\n // Update severity AND options\n result = updateRuleConfigInConfig(configPath, ruleId, severity, options);\n } else {\n // Update severity only\n result = updateRuleSeverityInConfig(configPath, ruleId, severity);\n }\n\n if (result.success) {\n logSuccess(\n `${pc.dim(\"[ws]\")} Updated ${pc.bold(`uilint/${ruleId}`)} -> ${pc.dim(severity)}`\n );\n\n // Clear ESLint instance cache to pick up the new config\n eslintInstances.clear();\n cache.clear();\n\n // Send success response to requesting client\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: true,\n requestId,\n });\n\n // Broadcast change to all connected clients\n broadcastRuleConfigChange(ruleId, severity, options);\n } else {\n logError(`${pc.dim(\"[ws]\")} Failed to update rule: ${result.error}`);\n sendMessage(ws, {\n type: \"rule:config:result\",\n ruleId,\n severity,\n options,\n success: false,\n error: result.error,\n requestId,\n });\n }\n}\n\n/**\n * Start the WebSocket server\n */\nexport async function serve(options: ServeOptions): Promise<void> {\n const port = options.port || 9234;\n\n const cwd = process.cwd();\n const wsRoot = findWorkspaceRoot(cwd);\n const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });\n serverAppRootForVision = appRoot;\n logInfo(`Workspace root: ${pc.dim(wsRoot)}`);\n logInfo(`App root: ${pc.dim(appRoot)}`);\n logInfo(`Server cwd: ${pc.dim(cwd)}`);\n\n // Create file watcher\n fileWatcher = watch([], {\n persistent: true,\n ignoreInitial: true,\n });\n\n fileWatcher.on(\"change\", (path) => {\n const resolvedPath = resolve(path);\n\n // Check if coverage-final.json changed - broadcast to all clients\n if (resolvedPath.endsWith(\"coverage-final.json\")) {\n handleCoverageFileChange(resolvedPath);\n return;\n }\n\n handleFileChange(resolvedPath);\n // Also schedule re-indexing for duplicates detection\n scheduleReindex(appRoot, resolvedPath);\n });\n\n // Watch coverage-final.json for changes\n const coveragePath = join(appRoot, \"coverage\", \"coverage-final.json\");\n if (existsSync(coveragePath)) {\n fileWatcher.add(coveragePath);\n logInfo(`Watching coverage: ${pc.dim(coveragePath)}`);\n }\n\n // Create WebSocket server\n const wss = new WebSocketServer({ port });\n\n // Start building the duplicates index in the background\n // This runs incrementally - very fast if nothing changed\n buildDuplicatesIndex(appRoot).catch((err) => {\n logError(`Failed to build duplicates index: ${err.message}`);\n });\n\n // Prepare coverage data for require-test-coverage rule (startup only)\n // This installs packages, modifies config, and runs tests if needed\n buildCoverageData(appRoot).catch((err) => {\n // Don't block server startup on coverage failures\n logWarning(`Failed to prepare coverage: ${err.message}`);\n });\n\n wss.on(\"connection\", (ws) => {\n connectedClients += 1;\n connectedClientsSet.add(ws);\n logInfo(`Client connected (${connectedClients} total)`);\n\n // Send workspace info to client on connect\n sendMessage(ws, {\n type: \"workspace:info\",\n appRoot,\n workspaceRoot: wsRoot,\n serverCwd: cwd,\n });\n\n // Send workspace capabilities (hook availability, etc.)\n const hookInfo = detectPostToolUseHook(appRoot);\n sendMessage(ws, {\n type: \"workspace:capabilities\",\n postToolUseHook: hookInfo,\n });\n if (hookInfo.enabled) {\n logInfo(`${pc.dim(\"[ws]\")} Post-tool-use hook detected: ${pc.bold(hookInfo.provider!)}`);\n }\n\n // Read current rule configs from ESLint config file\n const eslintConfigPath = findEslintConfigFile(appRoot);\n const currentRuleConfigs = eslintConfigPath\n ? readRuleConfigsFromConfig(eslintConfigPath)\n : new Map<string, { severity: \"error\" | \"warn\" | \"off\"; options?: Record<string, unknown> }>();\n\n // Send installed rules metadata (only rules that exist in the ESLint config)\n // Include current severities from the ESLint config so UI reflects saved state\n sendMessage(ws, {\n type: \"rules:metadata\",\n rules: ruleRegistry\n .filter((rule) => currentRuleConfigs.has(rule.id))\n .map((rule) => {\n const currentConfig = currentRuleConfigs.get(rule.id);\n return {\n id: rule.id,\n name: rule.name,\n description: rule.description,\n category: rule.category,\n defaultSeverity: rule.defaultSeverity,\n currentSeverity: currentConfig?.severity,\n currentOptions: currentConfig?.options,\n docs: rule.docs,\n optionSchema: rule.optionSchema,\n defaultOptions: rule.defaultOptions,\n };\n }),\n });\n\n // Send current config state to new client\n for (const [key, value] of configStore) {\n sendMessage(ws, { type: \"config:update\", key, value });\n }\n\n ws.on(\"message\", (data) => {\n handleMessage(ws, data.toString());\n });\n\n ws.on(\"close\", () => {\n connectedClients = Math.max(0, connectedClients - 1);\n connectedClientsSet.delete(ws);\n logInfo(`Client disconnected (${connectedClients} total)`);\n handleDisconnect(ws);\n });\n\n ws.on(\"error\", (error) => {\n logError(`WebSocket error: ${error.message}`);\n });\n });\n\n wss.on(\"error\", (error) => {\n logError(`Server error: ${error.message}`);\n });\n\n logSuccess(\n `UILint WebSocket server running on ${pc.cyan(`ws://localhost:${port}`)}`\n );\n logInfo(\"Press Ctrl+C to stop\");\n\n // Keep the server running\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", () => {\n logInfo(\"Shutting down...\");\n wss.close();\n fileWatcher?.close();\n resolve();\n });\n });\n}\n","import { dirname, join, parse } from \"path\";\nimport { existsSync, statSync, mkdirSync, writeFileSync } from \"fs\";\nimport {\n ensureOllamaReady,\n findStyleGuidePath,\n findUILintStyleGuideUpwards,\n readStyleGuide,\n VisionAnalyzer,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n type VisionAnalysisResult,\n type StreamProgressCallback,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"./path-specifiers.js\";\n\nexport type ResolveVisionStyleGuideArgs = {\n /** Project root / cwd used to resolve relative path specifiers */\n projectPath: string;\n /** Path to style guide file OR project directory */\n styleguide?: string;\n /** A starting point for upward search (directory). Defaults to projectPath. */\n startDir?: string;\n};\n\nexport type ResolveVisionStyleGuideResult = {\n styleGuide: string | null;\n styleguideLocation: string | null;\n};\n\nexport async function resolveVisionStyleGuide(\n args: ResolveVisionStyleGuideArgs\n): Promise<ResolveVisionStyleGuideResult> {\n const projectPath = args.projectPath;\n const startDir = args.startDir ?? projectPath;\n\n if (args.styleguide) {\n const styleguideArg = resolvePathSpecifier(args.styleguide, projectPath);\n if (existsSync(styleguideArg)) {\n const stat = statSync(styleguideArg);\n if (stat.isFile()) {\n return {\n styleguideLocation: styleguideArg,\n styleGuide: await readStyleGuide(styleguideArg),\n };\n }\n if (stat.isDirectory()) {\n const found = findStyleGuidePath(styleguideArg);\n return {\n styleguideLocation: found,\n styleGuide: found ? await readStyleGuide(found) : null,\n };\n }\n }\n return { styleGuide: null, styleguideLocation: null };\n }\n\n const upwards = findUILintStyleGuideUpwards(startDir);\n const fallback = upwards ?? findStyleGuidePath(projectPath);\n return {\n styleguideLocation: fallback,\n styleGuide: fallback ? await readStyleGuide(fallback) : null,\n };\n}\n\nexport type RunVisionAnalysisArgs = {\n /** base64 image data (NO data: prefix) */\n imageBase64: string;\n manifest: ElementManifest[];\n /** Used to resolve styleguide arg and as default search root */\n projectPath: string;\n /** Path to style guide file OR directory; if omitted uses upward search */\n styleguide?: string;\n /** Directory for upward styleguide search; defaults to projectPath */\n styleguideStartDir?: string;\n /**\n * Override resolved styleguide content (lets callers do logging/notes based on resolution once).\n * If provided (even null), styleguide resolution is skipped.\n */\n styleGuide?: string | null;\n /**\n * Override resolved styleguide location (pairs with styleGuide override).\n * If provided, this is returned in the result.\n */\n styleguideLocation?: string | null;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /**\n * Optional analyzer instance (lets servers reuse a singleton and lets tests inject a mock).\n * If omitted, a new `VisionAnalyzer` is created with baseUrl+model.\n */\n analyzer?: Pick<VisionAnalyzer, \"analyzeScreenshot\">;\n /** Optional streaming progress callback passed into the analyzer */\n onProgress?: StreamProgressCallback;\n /** Optional coarse-grained phase callback (good for spinners / WS progress) */\n onPhase?: (phase: string) => void;\n /** When true, skip calling `ensureOllamaReady` (caller is responsible). */\n skipEnsureOllama?: boolean;\n /** Optional debug dump destination (file path or directory) */\n debugDump?: string;\n /** When true, include base64 image and full styleguide in debug dump */\n debugDumpIncludeSensitive?: boolean;\n /** Optional extra metadata to include in debug dumps */\n debugDumpMetadata?: Record<string, unknown>;\n};\n\nexport type RunVisionAnalysisResult = {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n styleguideLocation: string | null;\n visionModel: string;\n baseUrl: string;\n};\n\nconst ollamaReadyOnce = new Map<string, Promise<void>>();\n\nasync function ensureOllamaReadyCached(params: {\n model: string;\n baseUrl: string;\n}): Promise<void> {\n const key = `${params.baseUrl}::${params.model}`;\n const existing = ollamaReadyOnce.get(key);\n if (existing) return existing;\n\n const p = ensureOllamaReady({ model: params.model, baseUrl: params.baseUrl })\n .then(() => undefined)\n .catch((e) => {\n // If startup/pull fails, allow retry on next request.\n ollamaReadyOnce.delete(key);\n throw e;\n });\n ollamaReadyOnce.set(key, p);\n return p;\n}\n\nfunction writeVisionDebugDump(params: {\n dumpPath: string;\n now: Date;\n inputs: {\n imageBase64: string;\n manifest: ElementManifest[];\n styleguideLocation: string | null;\n styleGuide: string | null;\n };\n runtime: { visionModel: string; baseUrl: string };\n includeSensitive: boolean;\n metadata?: Record<string, unknown>;\n}): string {\n const resolvedDirOrFile = resolvePathSpecifier(\n params.dumpPath,\n process.cwd()\n );\n const safeStamp = params.now.toISOString().replace(/[:.]/g, \"-\");\n const dumpFile =\n resolvedDirOrFile.endsWith(\".json\") || resolvedDirOrFile.endsWith(\".jsonl\")\n ? resolvedDirOrFile\n : `${resolvedDirOrFile}/vision-debug-${safeStamp}.json`;\n\n mkdirSync(dirname(dumpFile), { recursive: true });\n writeFileSync(\n dumpFile,\n JSON.stringify(\n {\n version: 1,\n timestamp: params.now.toISOString(),\n runtime: params.runtime,\n metadata: params.metadata ?? null,\n inputs: {\n imageBase64: params.includeSensitive\n ? params.inputs.imageBase64\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n manifest: params.inputs.manifest,\n styleguideLocation: params.inputs.styleguideLocation,\n styleGuide: params.includeSensitive\n ? params.inputs.styleGuide\n : \"(omitted; set debugDumpIncludeSensitive=true)\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n\n return dumpFile;\n}\n\nexport async function runVisionAnalysis(\n args: RunVisionAnalysisArgs\n): Promise<RunVisionAnalysisResult> {\n const visionModel = args.model || UILINT_DEFAULT_VISION_MODEL;\n const baseUrl = args.baseUrl ?? \"http://localhost:11434\";\n\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n\n if (args.styleGuide !== undefined) {\n styleGuide = args.styleGuide;\n styleguideLocation = args.styleguideLocation ?? null;\n } else {\n args.onPhase?.(\"Resolving styleguide...\");\n const resolved = await resolveVisionStyleGuide({\n projectPath: args.projectPath,\n styleguide: args.styleguide,\n startDir: args.styleguideStartDir,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (!args.skipEnsureOllama) {\n args.onPhase?.(\"Preparing Ollama...\");\n await ensureOllamaReadyCached({ model: visionModel, baseUrl });\n }\n\n if (args.debugDump) {\n writeVisionDebugDump({\n dumpPath: args.debugDump,\n now: new Date(),\n runtime: { visionModel, baseUrl },\n inputs: {\n imageBase64: args.imageBase64,\n manifest: args.manifest,\n styleguideLocation,\n styleGuide,\n },\n includeSensitive: Boolean(args.debugDumpIncludeSensitive),\n metadata: args.debugDumpMetadata,\n });\n }\n\n const analyzer =\n args.analyzer ??\n new VisionAnalyzer({\n baseUrl: args.baseUrl,\n visionModel,\n });\n\n args.onPhase?.(`Analyzing ${args.manifest.length} elements...`);\n const result: VisionAnalysisResult = await analyzer.analyzeScreenshot(\n args.imageBase64,\n args.manifest,\n {\n styleGuide,\n onProgress: args.onProgress,\n }\n );\n\n args.onPhase?.(\n `Done (${result.issues.length} issues, ${result.analysisTime}ms)`\n );\n\n return {\n issues: result.issues,\n analysisTime: result.analysisTime,\n // Prompt is available in newer uilint-core versions; keep this resilient across versions.\n prompt: (result as any).prompt,\n rawResponse: result.rawResponse,\n styleguideLocation,\n visionModel,\n baseUrl,\n };\n}\n\nexport type WriteVisionMarkdownReportArgs = {\n /** Absolute path to the source image file */\n imagePath: string;\n /** Route label (optional; included in report) */\n route?: string;\n /** Unix ms timestamp (optional; included in report) */\n timestamp?: number;\n visionModel?: string;\n baseUrl?: string;\n analysisTimeMs?: number;\n prompt?: string | null;\n rawResponse?: string | null;\n /** Extra JSON-ish metadata to include */\n metadata?: Record<string, unknown>;\n /**\n * Optional output path; if omitted, writes alongside the image:\n * `<basename>.vision.md`\n */\n outPath?: string;\n};\n\nexport function writeVisionMarkdownReport(\n args: WriteVisionMarkdownReportArgs\n): {\n outPath: string;\n content: string;\n} {\n const p = parse(args.imagePath);\n const outPath = args.outPath ?? join(p.dir, `${p.name || p.base}.vision.md`);\n\n const lines: string[] = [];\n lines.push(`# UILint Vision Report`);\n lines.push(``);\n lines.push(`- Image: \\`${p.base}\\``);\n if (args.route) lines.push(`- Route: \\`${args.route}\\``);\n if (typeof args.timestamp === \"number\") {\n lines.push(`- Timestamp: \\`${new Date(args.timestamp).toISOString()}\\``);\n }\n if (args.visionModel) lines.push(`- Model: \\`${args.visionModel}\\``);\n if (args.baseUrl) lines.push(`- Ollama baseUrl: \\`${args.baseUrl}\\``);\n if (typeof args.analysisTimeMs === \"number\")\n lines.push(`- Analysis time: \\`${args.analysisTimeMs}ms\\``);\n lines.push(`- Generated: \\`${new Date().toISOString()}\\``);\n lines.push(``);\n\n if (args.metadata && Object.keys(args.metadata).length > 0) {\n lines.push(`## Metadata`);\n lines.push(``);\n lines.push(\"```json\");\n lines.push(JSON.stringify(args.metadata, null, 2));\n lines.push(\"```\");\n lines.push(``);\n }\n\n lines.push(`## Prompt`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.prompt ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n lines.push(`## Raw Response`);\n lines.push(``);\n lines.push(\"```text\");\n lines.push((args.rawResponse ?? \"\").trim());\n lines.push(\"```\");\n lines.push(``);\n\n const content = lines.join(\"\\n\");\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, \"utf-8\");\n return { outPath, content };\n}\n","/**\n * Vision command - analyze a screenshot with Ollama vision models\n *\n * Mirrors the \"scan\" command UX (debug flags, JSON/text output), but operates on images.\n */\n\nimport { dirname, resolve, join } from \"path\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from \"fs\";\nimport {\n ensureOllamaReady,\n STYLEGUIDE_PATHS,\n UILINT_DEFAULT_VISION_MODEL,\n type ElementManifest,\n type VisionIssue,\n} from \"uilint-core/node\";\nimport { resolvePathSpecifier } from \"../utils/path-specifiers.js\";\nimport { flushLangfuse } from \"../utils/llm-client.js\";\nimport { nsNow, nsToMs, formatMs, maybeMs } from \"../utils/timing.js\";\nimport {\n resolveVisionStyleGuide,\n runVisionAnalysis,\n writeVisionMarkdownReport,\n} from \"../utils/vision-run.js\";\nimport {\n intro,\n withSpinner,\n note,\n logInfo,\n logWarning,\n logError,\n logSuccess,\n pc,\n} from \"../utils/prompts.js\";\nimport { printJSON } from \"../utils/output.js\";\n\nexport interface VisionOptions {\n /** Path to a screenshot image (png/jpg). */\n image?: string;\n /** Path to a `.json` sidecar containing { manifest, ... } (as saved by the Next screenshot route). */\n sidecar?: string;\n /** Inline manifest JSON string (array). */\n manifestJson?: string;\n /** Path to a manifest JSON file (array). */\n manifestFile?: string;\n /** Explicit route label (used in output and debug dump). */\n route?: string;\n /** Path to style guide file or project dir (same semantics as scan.ts). */\n styleguide?: string;\n /** Output format */\n output?: \"text\" | \"json\";\n /** List available `.uilint/screenshots/*.json` sidecars and exit */\n list?: boolean;\n /** Optional screenshots directory to list from (default: nearest `.uilint/screenshots`) */\n screenshotsDir?: string;\n /** Stream model output/progress (text mode only; JSON output stays non-streaming) */\n stream?: boolean;\n /** Ollama base URL (default: http://localhost:11434) */\n baseUrl?: string;\n /** Vision model override (default: UILINT_DEFAULT_VISION_MODEL) */\n model?: string;\n /** Enable debug logging (stderr only; never pollutes JSON stdout). Can also be enabled via UILINT_DEBUG=1 */\n debug?: boolean;\n /** Print full prompt/styleguide (can be very large). Can also be enabled via UILINT_DEBUG_FULL=1 */\n debugFull?: boolean;\n /** Dump payload to file. Can also be set via UILINT_DEBUG_DUMP=/path */\n debugDump?: string;\n}\n\nfunction envTruthy(name: string): boolean {\n const v = process.env[name];\n if (!v) return false;\n return v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\";\n}\n\nfunction preview(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n…<truncated>…\\n\" + text.slice(-maxLen);\n}\n\nfunction debugEnabled(options: VisionOptions): boolean {\n return Boolean(options.debug) || envTruthy(\"UILINT_DEBUG\");\n}\n\nfunction debugFullEnabled(options: VisionOptions): boolean {\n return Boolean(options.debugFull) || envTruthy(\"UILINT_DEBUG_FULL\");\n}\n\nfunction debugDumpPath(options: VisionOptions): string | null {\n const v = options.debugDump ?? process.env.UILINT_DEBUG_DUMP;\n if (!v) return null;\n // Allow UILINT_DEBUG_DUMP=1 to mean \"use a sensible default\".\n if (v === \"1\" || v.toLowerCase() === \"true\" || v.toLowerCase() === \"yes\") {\n return resolve(process.cwd(), \".uilint\");\n }\n return v;\n}\n\nfunction debugLog(enabled: boolean, message: string, obj?: unknown): void {\n if (!enabled) return;\n if (obj === undefined) {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n } else {\n try {\n console.error(pc.dim(\"[uilint:debug]\"), message, obj);\n } catch {\n console.error(pc.dim(\"[uilint:debug]\"), message);\n }\n }\n}\n\nfunction findScreenshotsDirUpwards(startDir: string): string | null {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n const candidate = join(dir, \".uilint\", \"screenshots\");\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\ntype ScreenshotSidecarSummary = {\n path: string;\n filename: string;\n timestamp?: number;\n route?: string;\n issueCount?: number;\n};\n\nfunction listScreenshotSidecars(dirPath: string): ScreenshotSidecarSummary[] {\n if (!existsSync(dirPath)) return [];\n const entries = readdirSync(dirPath)\n .filter((f) => f.endsWith(\".json\"))\n .map((f) => join(dirPath, f));\n\n const out: ScreenshotSidecarSummary[] = [];\n for (const p of entries) {\n try {\n const json = loadJsonFile<any>(p);\n const issues = Array.isArray(json?.issues)\n ? json.issues\n : json?.analysisResult?.issues;\n out.push({\n path: p,\n filename:\n json?.filename || json?.screenshotFile || p.split(\"/\").pop() || p,\n timestamp:\n typeof json?.timestamp === \"number\" ? json.timestamp : undefined,\n route: typeof json?.route === \"string\" ? json.route : undefined,\n issueCount: Array.isArray(issues) ? issues.length : undefined,\n });\n } catch {\n out.push({\n path: p,\n filename: p.split(\"/\").pop() || p,\n });\n }\n }\n\n // Newest first (fallback to filename sort)\n out.sort((a, b) => {\n const at = a.timestamp ?? 0;\n const bt = b.timestamp ?? 0;\n if (at !== bt) return bt - at;\n return b.path.localeCompare(a.path);\n });\n\n return out;\n}\n\nfunction readImageAsBase64(imagePath: string): {\n base64: string;\n sizeBytes: number;\n} {\n const bytes = readFileSync(imagePath);\n return { base64: bytes.toString(\"base64\"), sizeBytes: bytes.byteLength };\n}\n\nfunction loadJsonFile<T>(filePath: string): T {\n const raw = readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nfunction formatIssuesText(issues: VisionIssue[]): string {\n if (issues.length === 0) return \"No vision issues found.\\n\";\n return (\n issues\n .map((i) => {\n const sev = i.severity || \"info\";\n const cat = i.category || \"other\";\n const where = i.dataLoc ? ` (${i.dataLoc})` : \"\";\n return `- [${sev}/${cat}] ${i.message}${where}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n}\n\nexport async function vision(options: VisionOptions): Promise<void> {\n const isJsonOutput = options.output === \"json\";\n const dbg = debugEnabled(options);\n const dbgFull = debugFullEnabled(options);\n const dbgDump = debugDumpPath(options);\n\n if (!isJsonOutput) intro(\"Vision (Screenshot) Analysis\");\n\n try {\n const projectPath = process.cwd();\n\n // List mode (no analysis)\n if (options.list) {\n const base =\n (options.screenshotsDir\n ? resolvePathSpecifier(options.screenshotsDir, projectPath)\n : null) || findScreenshotsDirUpwards(projectPath);\n\n if (!base) {\n if (isJsonOutput) {\n printJSON({ screenshotsDir: null, sidecars: [] });\n } else {\n logWarning(\n \"No `.uilint/screenshots` directory found (walked up from cwd).\"\n );\n }\n await flushLangfuse();\n return;\n }\n\n const sidecars = listScreenshotSidecars(base);\n if (isJsonOutput) {\n printJSON({ screenshotsDir: base, sidecars });\n } else {\n logInfo(`Screenshots dir: ${pc.dim(base)}`);\n if (sidecars.length === 0) {\n process.stdout.write(\"No sidecars found.\\n\");\n } else {\n process.stdout.write(\n sidecars\n .map((s, idx) => {\n const stamp = s.timestamp\n ? new Date(s.timestamp).toLocaleString()\n : \"(no timestamp)\";\n const route = s.route ? ` ${pc.dim(s.route)}` : \"\";\n const count =\n typeof s.issueCount === \"number\"\n ? ` ${pc.dim(`(${s.issueCount} issues)`)}`\n : \"\";\n return `${idx === 0 ? \"*\" : \"-\"} ${s.path}${pc.dim(\n ` — ${stamp}`\n )}${route}${count}`;\n })\n .join(\"\\n\") + \"\\n\"\n );\n process.stdout.write(\n pc.dim(\n `Tip: run \\`uilint vision --sidecar <path>\\` (the newest is marked with \"*\").\\n`\n )\n );\n }\n }\n await flushLangfuse();\n return;\n }\n\n // Resolve inputs\n const imagePath = options.image\n ? resolvePathSpecifier(options.image, projectPath)\n : undefined;\n const sidecarPath = options.sidecar\n ? resolvePathSpecifier(options.sidecar, projectPath)\n : undefined;\n const manifestFilePath = options.manifestFile\n ? resolvePathSpecifier(options.manifestFile, projectPath)\n : undefined;\n\n if (!imagePath && !sidecarPath) {\n if (isJsonOutput) {\n printJSON({ error: \"No input provided\", issues: [] });\n } else {\n logError(\"No input provided. Use --image or --sidecar.\");\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n if (imagePath && !existsSync(imagePath)) {\n throw new Error(`Image not found: ${imagePath}`);\n }\n if (sidecarPath && !existsSync(sidecarPath)) {\n throw new Error(`Sidecar not found: ${sidecarPath}`);\n }\n if (manifestFilePath && !existsSync(manifestFilePath)) {\n throw new Error(`Manifest file not found: ${manifestFilePath}`);\n }\n\n // Load sidecar if provided (supports the Next screenshot route payload)\n const sidecar = sidecarPath\n ? loadJsonFile<{\n filename?: string;\n screenshotFile?: string;\n route?: string;\n manifest?: unknown;\n analysisResult?: unknown;\n issues?: unknown;\n }>(sidecarPath)\n : null;\n\n const routeLabel =\n options.route ||\n (typeof sidecar?.route === \"string\" ? sidecar.route : undefined) ||\n (sidecarPath ? `(from ${sidecarPath})` : \"(unknown)\");\n\n // Manifest sources (priority: --manifest-json > --manifest-file > sidecar.manifest)\n let manifest: ElementManifest[] | null = null;\n if (options.manifestJson) {\n manifest = JSON.parse(options.manifestJson) as ElementManifest[];\n } else if (manifestFilePath) {\n manifest = loadJsonFile<ElementManifest[]>(manifestFilePath);\n } else if (sidecar && Array.isArray(sidecar.manifest)) {\n manifest = sidecar.manifest as ElementManifest[];\n }\n\n if (!manifest || manifest.length === 0) {\n throw new Error(\n \"No manifest provided. Supply --manifest-json, --manifest-file, or a sidecar JSON with a `manifest` array.\"\n );\n }\n\n // Styleguide resolution: same semantics as scan.ts (path/file/dir), with a good default start dir.\n let styleGuide: string | null = null;\n let styleguideLocation: string | null = null;\n const startPath =\n (imagePath ?? sidecarPath ?? manifestFilePath ?? undefined) || undefined;\n\n {\n const resolved = await resolveVisionStyleGuide({\n projectPath,\n styleguide: options.styleguide,\n startDir: startPath ? dirname(startPath) : projectPath,\n });\n styleGuide = resolved.styleGuide;\n styleguideLocation = resolved.styleguideLocation;\n }\n\n if (styleguideLocation && styleGuide) {\n if (!isJsonOutput)\n logSuccess(`Using styleguide: ${pc.dim(styleguideLocation)}`);\n } else if (!styleGuide && !isJsonOutput) {\n logWarning(\"No styleguide found\");\n note(\n [\n `Searched in: ${options.styleguide || projectPath}`,\n \"\",\n \"Looked for:\",\n ...STYLEGUIDE_PATHS.map((p) => ` • ${p}`),\n \"\",\n `Create ${pc.cyan(\n \".uilint/styleguide.md\"\n )} (recommended: run ${pc.cyan(\"/genstyleguide\")} in Cursor).`,\n ].join(\"\\n\"),\n \"Missing Styleguide\"\n );\n }\n\n debugLog(dbg, \"Vision input (high-level)\", {\n imagePath: imagePath ?? null,\n sidecarPath: sidecarPath ?? null,\n manifestFile: manifestFilePath ?? null,\n manifestElements: manifest.length,\n route: routeLabel,\n styleguideLocation,\n styleGuideLength: styleGuide ? styleGuide.length : 0,\n });\n\n // Prepare Ollama (ensure model exists & server up)\n const visionModel = options.model || UILINT_DEFAULT_VISION_MODEL;\n const prepStartNs = nsNow();\n if (!isJsonOutput) {\n await withSpinner(\"Preparing Ollama\", async () => {\n await ensureOllamaReady({\n model: visionModel,\n baseUrl: options.baseUrl,\n });\n });\n } else {\n await ensureOllamaReady({ model: visionModel, baseUrl: options.baseUrl });\n }\n const prepEndNs = nsNow();\n\n // Load screenshot bytes\n const resolvedImagePath =\n imagePath ||\n (() => {\n // If sidecar contains screenshotFile and is relative, resolve relative to the sidecar dir.\n const screenshotFile =\n typeof sidecar?.screenshotFile === \"string\"\n ? sidecar.screenshotFile\n : typeof sidecar?.filename === \"string\"\n ? sidecar.filename\n : undefined;\n if (!screenshotFile) return null;\n const baseDir = sidecarPath ? dirname(sidecarPath) : projectPath;\n const abs = resolve(baseDir, screenshotFile);\n return abs;\n })();\n\n if (!resolvedImagePath) {\n throw new Error(\n \"No image path could be resolved. Provide --image or a sidecar with `screenshotFile`/`filename`.\"\n );\n }\n if (!existsSync(resolvedImagePath)) {\n throw new Error(`Image not found: ${resolvedImagePath}`);\n }\n\n const { base64, sizeBytes } = readImageAsBase64(resolvedImagePath);\n debugLog(dbg, \"Image loaded\", {\n imagePath: resolvedImagePath,\n sizeBytes,\n base64Length: base64.length,\n });\n\n if (dbgFull && styleGuide) {\n debugLog(dbg, \"Styleguide (full)\", styleGuide);\n } else if (dbg && styleGuide) {\n debugLog(dbg, \"Styleguide (preview)\", preview(styleGuide, 800));\n }\n\n // Run analysis (optionally show streaming progress in text mode)\n let result: {\n issues: VisionIssue[];\n analysisTime: number;\n prompt?: string;\n rawResponse?: string;\n } | null = null;\n\n const analysisStartNs = nsNow();\n let firstTokenNs: bigint | null = null;\n let firstThinkingNs: bigint | null = null;\n let lastThinkingNs: bigint | null = null;\n let firstAnswerNs: bigint | null = null;\n let lastAnswerNs: bigint | null = null;\n\n if (isJsonOutput) {\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n });\n } else {\n if (options.stream) {\n let lastStatus = \"\";\n let printedAnyText = false;\n let inThinking = false;\n result = await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta)) firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n if (thinkingDelta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n process.stderr.write(pc.dim(\"Thinking:\\n\"));\n inThinking = true;\n } else if (!inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nThinking:\\n\"));\n inThinking = true;\n }\n process.stderr.write(thinkingDelta);\n return;\n }\n\n // If we got a text delta, stream it directly\n if (delta) {\n if (!printedAnyText) {\n printedAnyText = true;\n console.error(pc.dim(\"[vision] streaming:\"));\n }\n if (inThinking) {\n process.stderr.write(pc.dim(\"\\n\\nAnswer:\\n\"));\n inThinking = false;\n }\n // Stream raw text to stderr to avoid corrupting stdout.\n process.stderr.write(delta);\n return;\n }\n\n // Fallback to status output (latest line / heartbeats).\n const line = (latestLine || \"\").trim();\n if (!line || line === lastStatus) return;\n lastStatus = line;\n console.error(pc.dim(\"[vision]\"), line);\n },\n });\n } else {\n result = await withSpinner(\n \"Analyzing screenshot with vision model\",\n async (s) => {\n return await runVisionAnalysis({\n imageBase64: base64,\n manifest,\n projectPath,\n styleGuide,\n styleguideLocation,\n baseUrl: options.baseUrl,\n model: visionModel,\n skipEnsureOllama: true,\n debugDump: dbgDump ?? undefined,\n debugDumpIncludeSensitive: dbgFull,\n debugDumpMetadata: {\n route: routeLabel,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n imageBase64Length: base64.length,\n },\n onProgress: (\n latestLine: string,\n _fullResponse: string,\n delta?: string,\n thinkingDelta?: string\n ) => {\n const nowNs = nsNow();\n if (!firstTokenNs && (thinkingDelta || delta))\n firstTokenNs = nowNs;\n if (thinkingDelta) {\n if (!firstThinkingNs) firstThinkingNs = nowNs;\n lastThinkingNs = nowNs;\n }\n if (delta) {\n if (!firstAnswerNs) firstAnswerNs = nowNs;\n lastAnswerNs = nowNs;\n }\n\n const maxLen = 60;\n const displayLine =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n s.message(`Analyzing: ${pc.dim(displayLine || \"...\")}`);\n },\n });\n }\n );\n }\n }\n\n const analysisEndNs = nsNow();\n\n const issues = result?.issues ?? [];\n\n if (isJsonOutput) {\n printJSON({\n route: routeLabel,\n model: visionModel,\n issues,\n analysisTime: result?.analysisTime ?? 0,\n imagePath: resolvedImagePath,\n imageSizeBytes: sizeBytes,\n });\n } else {\n logInfo(`Route: ${pc.dim(routeLabel)}`);\n logInfo(`Model: ${pc.dim(visionModel)}`);\n process.stdout.write(formatIssuesText(issues));\n\n // Pretty timings (TTY-only so we don't clutter non-interactive usage)\n if (process.stdout.isTTY) {\n const prepMs = nsToMs(prepEndNs - prepStartNs);\n const totalMs = nsToMs(analysisEndNs - analysisStartNs);\n const endToEndMs = nsToMs(analysisEndNs - prepStartNs);\n const ttftMs = firstTokenNs\n ? nsToMs(firstTokenNs - analysisStartNs)\n : null;\n const thinkingMs =\n firstThinkingNs && (firstAnswerNs || lastThinkingNs)\n ? nsToMs(\n (firstAnswerNs ?? lastThinkingNs ?? analysisEndNs) -\n firstThinkingNs\n )\n : null;\n const outputMs =\n firstAnswerNs && (lastAnswerNs || analysisEndNs)\n ? nsToMs((lastAnswerNs ?? analysisEndNs) - firstAnswerNs)\n : null;\n\n note(\n [\n `Prepare Ollama: ${formatMs(prepMs)}`,\n `Time to first token: ${maybeMs(ttftMs)}`,\n `Thinking: ${maybeMs(thinkingMs)}`,\n `Outputting: ${maybeMs(outputMs)}`,\n `LLM total: ${formatMs(totalMs)}`,\n `End-to-end: ${formatMs(endToEndMs)}`,\n result?.analysisTime\n ? pc.dim(`(core analysisTime: ${formatMs(result.analysisTime)})`)\n : pc.dim(\"(core analysisTime: n/a)\"),\n ].join(\"\\n\"),\n \"Timings\"\n );\n }\n }\n\n // Write markdown report alongside the image (best-effort; never affects stdout JSON).\n try {\n writeVisionMarkdownReport({\n imagePath: resolvedImagePath,\n route: routeLabel,\n visionModel,\n baseUrl: options.baseUrl ?? \"http://localhost:11434\",\n analysisTimeMs: result?.analysisTime ?? 0,\n prompt: result?.prompt ?? null,\n rawResponse: result?.rawResponse ?? null,\n metadata: {\n imageSizeBytes: sizeBytes,\n styleguideLocation,\n },\n });\n debugLog(dbg, \"Wrote .vision.md report alongside image\");\n } catch (e) {\n debugLog(\n dbg,\n \"Failed to write .vision.md report\",\n e instanceof Error ? e.message : e\n );\n }\n\n // Exit with error code if issues found\n if (issues.length > 0) {\n await flushLangfuse();\n process.exit(1);\n }\n } catch (error) {\n if (options.output === \"json\") {\n printJSON({\n error: error instanceof Error ? error.message : \"Unknown error\",\n issues: [],\n });\n } else {\n logError(\n error instanceof Error ? error.message : \"Vision analysis failed\"\n );\n }\n await flushLangfuse();\n process.exit(1);\n }\n\n await flushLangfuse();\n}\n","/**\n * UILint Config Command\n *\n * Allows setting configuration options that are broadcast to connected clients.\n *\n * Usage:\n * uilint config set position <x,y> - Set floating icon position\n * uilint config set position top-center - Use preset position\n * uilint config get position - Get current position (from server)\n * uilint config set rule <ruleId>:<severity> [optionsJson] - Set rule config\n *\n * Examples:\n * uilint config set rule consistent-dark-mode:warn\n * uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'\n * uilint config set rule no-mixed-component-libraries:off\n */\n\nimport { WebSocket } from \"ws\";\nimport { logInfo, logSuccess, logError, pc } from \"../utils/prompts.js\";\n\nexport interface ConfigOptions {\n port?: number;\n}\n\n/** Parse position value from string */\nfunction parsePosition(\n value: string\n): { x: number; y: number } | { preset: string } | null {\n // Check for presets\n const presets: Record<string, true> = {\n \"top-center\": true,\n \"top-left\": true,\n \"top-right\": true,\n \"bottom-center\": true,\n \"bottom-left\": true,\n \"bottom-right\": true,\n };\n\n if (presets[value]) {\n return { preset: value };\n }\n\n // Try to parse as x,y coordinates\n const match = value.match(/^(\\d+),(\\d+)$/);\n if (match) {\n return { x: parseInt(match[1], 10), y: parseInt(match[2], 10) };\n }\n\n return null;\n}\n\n/** Convert preset to position (approximate, client will recalculate) */\nfunction presetToPosition(preset: string): { x: number; y: number } {\n // These are approximate defaults - the client can recalculate based on viewport\n const positions: Record<string, { x: number; y: number }> = {\n \"top-center\": { x: 500, y: 30 },\n \"top-left\": { x: 60, y: 30 },\n \"top-right\": { x: 940, y: 30 },\n \"bottom-center\": { x: 500, y: 700 },\n \"bottom-left\": { x: 60, y: 700 },\n \"bottom-right\": { x: 940, y: 700 },\n };\n return positions[preset] || { x: 500, y: 30 };\n}\n\n/** Parse rule configuration from value string */\nfunction parseRuleConfig(value: string): {\n ruleId: string;\n severity: \"error\" | \"warn\" | \"off\";\n} | null {\n // Format: <ruleId>:<severity>\n const match = value.match(/^([^:]+):(error|warn|off)$/);\n if (!match) {\n return null;\n }\n return {\n ruleId: match[1],\n severity: match[2] as \"error\" | \"warn\" | \"off\",\n };\n}\n\n/** Parse options JSON string */\nfunction parseOptionsJson(optionsStr: string | undefined): Record<string, unknown> | undefined {\n if (!optionsStr) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(optionsStr);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return undefined;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Send config message via WebSocket\n */\nasync function sendConfigMessage(\n port: number,\n key: string,\n value: unknown\n): Promise<boolean> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve(false);\n }\n }, 5000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({ type: \"config:set\", key, value });\n ws.send(message);\n\n // Give the server time to process and broadcast\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve(true);\n }\n }, 100);\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n}\n\n/**\n * Send rule config message via WebSocket and wait for result\n */\nasync function sendRuleConfigMessage(\n port: number,\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>\n): Promise<{ success: boolean; error?: string }> {\n return new Promise((resolve) => {\n const url = `ws://localhost:${port}`;\n const ws = new WebSocket(url);\n let resolved = false;\n const requestId = `cli-${Date.now()}`;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n ws.close();\n resolve({ success: false, error: \"Request timed out\" });\n }\n }, 10000);\n\n ws.on(\"open\", () => {\n const message = JSON.stringify({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n ws.send(message);\n });\n\n ws.on(\"message\", (data: Buffer) => {\n try {\n const msg = JSON.parse(data.toString());\n if (msg.type === \"rule:config:result\" && msg.requestId === requestId) {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n ws.close();\n resolve({\n success: msg.success,\n error: msg.error,\n });\n }\n }\n } catch {\n // Ignore parse errors\n }\n });\n\n ws.on(\"error\", () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve({ success: false, error: \"Connection error\" });\n }\n });\n });\n}\n\n/**\n * Handle config set command\n */\nasync function handleSet(\n key: string,\n value: string,\n port: number,\n extraArg?: string\n): Promise<void> {\n switch (key) {\n case \"position\": {\n const parsed = parsePosition(value);\n if (!parsed) {\n logError(\n `Invalid position value: ${value}\\n` +\n `Expected format: x,y (e.g., 100,50) or preset (top-center, top-left, etc.)`\n );\n process.exit(1);\n }\n\n let position: { x: number; y: number };\n if (\"preset\" in parsed) {\n position = presetToPosition(parsed.preset);\n logInfo(`Using preset \"${parsed.preset}\" → (${position.x}, ${position.y})`);\n } else {\n position = parsed;\n }\n\n const success = await sendConfigMessage(\n port,\n \"floatingIconPosition\",\n position\n );\n\n if (success) {\n logSuccess(\n `Set floating icon position to (${position.x}, ${position.y})`\n );\n } else {\n logError(\n `Failed to set position. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n case \"rule\": {\n const parsed = parseRuleConfig(value);\n if (!parsed) {\n logError(\n `Invalid rule config: ${value}\\n` +\n `Expected format: <ruleId>:<severity>\\n` +\n ` severity: error, warn, or off\\n\\n` +\n `Examples:\\n` +\n ` uilint config set rule consistent-dark-mode:warn\\n` +\n ` uilint config set rule no-prop-drilling-depth:error '{\"maxDepth\":3}'`\n );\n process.exit(1);\n }\n\n // Parse optional options JSON from extra argument\n const options = parseOptionsJson(extraArg);\n if (extraArg && !options) {\n logError(\n `Invalid options JSON: ${extraArg}\\n` +\n `Expected a valid JSON object, e.g., '{\"maxDepth\": 3}'`\n );\n process.exit(1);\n }\n\n logInfo(\n `Setting rule \"${parsed.ruleId}\" to ${parsed.severity}` +\n (options ? ` with options: ${JSON.stringify(options)}` : \"\")\n );\n\n const result = await sendRuleConfigMessage(\n port,\n parsed.ruleId,\n parsed.severity,\n options\n );\n\n if (result.success) {\n logSuccess(\n `Rule \"${parsed.ruleId}\" set to ${parsed.severity}` +\n (options ? ` with options` : \"\")\n );\n } else {\n logError(\n result.error ||\n `Failed to set rule config. Is the server running?\\n` +\n `Start it with: ${pc.bold(\"npx uilint serve\")}`\n );\n process.exit(1);\n }\n break;\n }\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position, rule`);\n process.exit(1);\n }\n}\n\n/**\n * Handle config get command\n */\nasync function handleGet(key: string, _port: number): Promise<void> {\n switch (key) {\n case \"position\":\n logInfo(\n `Position is stored in the browser's localStorage.\\n` +\n `To view it, check your browser's dev tools:\\n` +\n ` localStorage.getItem(\"uilint:floatingIconPosition\")`\n );\n break;\n\n default:\n logError(`Unknown config key: ${key}`);\n logInfo(`Available keys: position`);\n process.exit(1);\n }\n}\n\n/**\n * Config command entry point\n */\nexport async function config(\n action: string,\n key: string,\n value?: string,\n extraArg?: string,\n options: ConfigOptions = {}\n): Promise<void> {\n const port = options.port || 9234;\n\n switch (action) {\n case \"set\":\n if (!value) {\n logError(`Missing value for config set ${key}`);\n process.exit(1);\n }\n await handleSet(key, value, port, extraArg);\n break;\n\n case \"get\":\n await handleGet(key, port);\n break;\n\n default:\n logError(`Unknown action: ${action}`);\n logInfo(`Usage: uilint config <set|get> <key> [value] [options]`);\n process.exit(1);\n }\n}\n","/**\n * Duplicates command - semantic code duplicate detection\n */\n\nimport { Command } from \"commander\";\nimport { indexCommand } from \"./index-cmd.js\";\nimport { findCommand } from \"./find.js\";\nimport { searchCommand } from \"./search.js\";\nimport { similarCommand } from \"./similar.js\";\n\nexport function createDuplicatesCommand(): Command {\n const duplicates = new Command(\"duplicates\")\n .description(\"Semantic code duplicate detection\");\n\n // Add subcommands\n duplicates.addCommand(indexCommand());\n duplicates.addCommand(findCommand());\n duplicates.addCommand(searchCommand());\n duplicates.addCommand(similarCommand());\n\n return duplicates;\n}\n","/**\n * Index command - build or update the semantic duplicates index\n */\n\nimport { Command } from \"commander\";\nimport { resolve } from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\nexport function indexCommand(): Command {\n return new Command(\"index\")\n .description(\"Build or update the semantic duplicates index\")\n .option(\"--force\", \"Rebuild index from scratch\")\n .option(\"--model <name>\", \"Embedding model (default: nomic-embed-text)\")\n .option(\n \"--exclude <glob>\",\n \"Exclude patterns (repeatable)\",\n (val: string, prev: string[]) => [...prev, val],\n [] as string[]\n )\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { indexDirectory } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n let spinner: ReturnType<typeof ora> | undefined;\n if (!isJson) {\n spinner = ora(\"Initializing indexer...\").start();\n }\n\n try {\n const result = await indexDirectory(projectRoot, {\n force: options.force,\n model: options.model,\n exclude: options.exclude,\n onProgress: (message, current, total) => {\n if (spinner) {\n if (current && total) {\n spinner.text = `${message} (${current}/${total})`;\n } else {\n spinner.text = message;\n }\n }\n },\n });\n\n if (isJson) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n spinner?.succeed(chalk.green(\"Index complete\"));\n console.log();\n console.log(chalk.bold(\"Index Statistics:\"));\n console.log(` Files added: ${result.added}`);\n console.log(` Files modified: ${result.modified}`);\n console.log(` Files deleted: ${result.deleted}`);\n console.log(` Total chunks: ${result.totalChunks}`);\n console.log(` Duration: ${(result.duration / 1000).toFixed(2)}s`);\n }\n } catch (error) {\n if (spinner) {\n spinner.fail(chalk.red(\"Index failed\"));\n }\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Find command - find semantic duplicate groups\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\nimport type { ChunkKind } from \"uilint-duplicates\";\n\nexport function findCommand(): Command {\n return new Command(\"find\")\n .description(\"Find semantic duplicate groups in the codebase\")\n .option(\n \"--threshold <n>\",\n \"Similarity threshold 0-1 (default: 0.85)\",\n parseFloat\n )\n .option(\"--min-size <n>\", \"Minimum group size (default: 2)\", parseInt)\n .option(\"--kind <type>\", \"Filter: component, hook, function\")\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (options) => {\n const { findDuplicates } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const groups = await findDuplicates({\n path: projectRoot,\n threshold: options.threshold,\n minGroupSize: options.minSize,\n kind: options.kind as ChunkKind | undefined,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ groups }, null, 2));\n return;\n }\n\n if (groups.length === 0) {\n console.log(chalk.green(\"No semantic duplicates found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${groups.length} duplicate group${groups.length > 1 ? \"s\" : \"\"}:\\n`\n )\n );\n\n groups.forEach((group, idx) => {\n const similarity = Math.round(group.avgSimilarity * 100);\n console.log(\n chalk.yellow(\n `Duplicate Group ${idx + 1} (${similarity}% similar, ${group.members.length} occurrences):`\n )\n );\n\n group.members.forEach((member) => {\n const relPath = relative(projectRoot, member.filePath);\n const location = `${relPath}:${member.startLine}-${member.endLine}`;\n const name = member.name || \"(anonymous)\";\n const score =\n member.score === 1.0\n ? \"\"\n : chalk.dim(` (${Math.round(member.score * 100)}%)`);\n console.log(` ${chalk.cyan(location.padEnd(50))} ${name}${score}`);\n });\n\n console.log(\n chalk.dim(\n ` Suggestion: Consider extracting shared logic into a reusable ${group.kind}\\n`\n )\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Search command - semantic search for code\n */\n\nimport { Command } from \"commander\";\nimport { relative } from \"path\";\nimport chalk from \"chalk\";\n\nexport function searchCommand(): Command {\n return new Command(\"search\")\n .description(\"Semantic search for similar code\")\n .argument(\"<query>\", \"Search query (natural language)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.5)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (query: string, options) => {\n const { searchSimilar } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n try {\n const results = await searchSimilar(query, {\n path: projectRoot,\n top: options.top,\n threshold: options.threshold,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No matching code found.\"));\n return;\n }\n\n console.log(chalk.bold(`Found ${results.length} matching results:\\n`));\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const location = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(location)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Similar command - find code similar to a specific location\n */\n\nimport { Command } from \"commander\";\nimport { relative, resolve, isAbsolute } from \"path\";\nimport chalk from \"chalk\";\n\nexport function similarCommand(): Command {\n return new Command(\"similar\")\n .description(\"Find code similar to a specific location\")\n .argument(\"<location>\", \"File location in format file:line (e.g., src/Button.tsx:15)\")\n .option(\"-k, --top <n>\", \"Number of results (default: 10)\", parseInt)\n .option(\"--threshold <n>\", \"Minimum similarity (default: 0.7)\", parseFloat)\n .option(\"-o, --output <format>\", \"Output format: text or json\", \"text\")\n .action(async (location: string, options) => {\n const { findSimilarAtLocation } = await import(\"uilint-duplicates\");\n\n const projectRoot = process.cwd();\n const isJson = options.output === \"json\";\n\n // Parse location\n const colonIdx = location.lastIndexOf(\":\");\n if (colonIdx === -1) {\n const message = \"Invalid location format. Use file:line (e.g., src/Button.tsx:15)\";\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePart = location.slice(0, colonIdx);\n const linePart = location.slice(colonIdx + 1);\n const line = parseInt(linePart, 10);\n\n if (isNaN(line)) {\n const message = `Invalid line number: ${linePart}`;\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n\n const filePath = isAbsolute(filePart)\n ? filePart\n : resolve(projectRoot, filePart);\n\n try {\n const results = await findSimilarAtLocation({\n path: projectRoot,\n filePath,\n line,\n top: options.top,\n threshold: options.threshold ?? 0.7,\n });\n\n if (isJson) {\n console.log(JSON.stringify({ results }, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow(\"No similar code found.\"));\n return;\n }\n\n console.log(\n chalk.bold(\n `Found ${results.length} similar code locations to ${relative(projectRoot, filePath)}:${line}:\\n`\n )\n );\n\n results.forEach((result, idx) => {\n const relPath = relative(projectRoot, result.filePath);\n const locationStr = `${relPath}:${result.startLine}-${result.endLine}`;\n const name = result.name || \"(anonymous)\";\n const score = Math.round(result.score * 100);\n const kindLabel = result.kind.padEnd(10);\n\n console.log(\n `${chalk.dim(`${idx + 1}.`)} ${chalk.cyan(locationStr)}`\n );\n console.log(\n ` ${chalk.dim(kindLabel)} ${chalk.bold(name)} ${chalk.green(`(${score}% similar)`)}`\n );\n });\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n if (isJson) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(chalk.red(`Error: ${message}`));\n }\n process.exit(1);\n }\n });\n}\n","/**\n * Socket CLI Command\n *\n * Provides a CLI interface for interacting with the UILint socket server.\n * Useful for testing, debugging, and scripting.\n *\n * Usage:\n * uilint socket # Start interactive REPL\n * uilint socket lint:file <path> # Lint a file\n * uilint socket vision:check # Check vision availability\n * uilint socket listen # Listen for all messages\n */\n\nimport { Command } from \"commander\";\nimport { readFileSync, existsSync } from \"fs\";\nimport chalk from \"chalk\";\nimport { createSocketClient, SocketClient } from \"./client.js\";\nimport type { ServerMessage, ElementManifest } from \"./types.js\";\n\nexport interface SocketOptions {\n port: number;\n debug: boolean;\n json: boolean;\n timeout: number;\n}\n\n/**\n * Format a message for display\n */\nfunction formatMessage(msg: ServerMessage, json: boolean): string {\n if (json) {\n return JSON.stringify(msg, null, 2);\n }\n\n switch (msg.type) {\n case \"lint:result\": {\n const lines = [`${chalk.cyan(\"lint:result\")} ${msg.filePath}`];\n if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const loc = issue.column\n ? `${issue.line}:${issue.column}`\n : `${issue.line}`;\n const rule = issue.ruleId ? chalk.dim(` [${issue.ruleId}]`) : \"\";\n lines.push(` ${chalk.yellow(loc)} ${issue.message}${rule}`);\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"vision:status\":\n if (msg.available) {\n return `${chalk.cyan(\"vision:status\")} ${chalk.green(\"available\")} (${msg.model})`;\n }\n return `${chalk.cyan(\"vision:status\")} ${chalk.red(\"not available\")}`;\n\n case \"vision:result\": {\n const lines = [\n `${chalk.cyan(\"vision:result\")} ${msg.route} (${msg.analysisTime}ms)`,\n ];\n if (msg.error) {\n lines.push(chalk.red(` Error: ${msg.error}`));\n } else if (msg.issues.length === 0) {\n lines.push(chalk.green(\" No issues found\"));\n } else {\n for (const issue of msg.issues) {\n const severity =\n issue.severity === \"error\"\n ? chalk.red(\"error\")\n : issue.severity === \"warning\"\n ? chalk.yellow(\"warn\")\n : chalk.blue(\"info\");\n lines.push(` ${severity} [${issue.category}] ${issue.message}`);\n if (issue.dataLoc) {\n lines.push(chalk.dim(` at ${issue.dataLoc}`));\n }\n }\n }\n return lines.join(\"\\n\");\n }\n\n case \"workspace:info\":\n return `${chalk.cyan(\"workspace:info\")}\\n appRoot: ${msg.appRoot}\\n workspaceRoot: ${msg.workspaceRoot}`;\n\n case \"rules:metadata\":\n return `${chalk.cyan(\"rules:metadata\")} ${msg.rules.length} rules available`;\n\n case \"source:result\":\n return `${chalk.cyan(\"source:result\")} ${msg.filePath} (${msg.totalLines} lines)`;\n\n case \"source:error\":\n return `${chalk.cyan(\"source:error\")} ${msg.filePath}: ${chalk.red(msg.error)}`;\n\n case \"coverage:result\":\n return `${chalk.cyan(\"coverage:result\")} Coverage data received`;\n\n case \"coverage:error\":\n return `${chalk.cyan(\"coverage:error\")} ${chalk.red(msg.error)}`;\n\n case \"rule:config:result\":\n if (msg.success) {\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} -> ${msg.severity}`;\n }\n return `${chalk.cyan(\"rule:config:result\")} ${msg.ruleId} ${chalk.red(\"failed\")}: ${msg.error}`;\n\n case \"duplicates:indexing:start\":\n return `${chalk.cyan(\"duplicates:indexing:start\")}`;\n\n case \"duplicates:indexing:progress\":\n return `${chalk.cyan(\"duplicates:indexing:progress\")} ${msg.message}`;\n\n case \"duplicates:indexing:complete\":\n return `${chalk.cyan(\"duplicates:indexing:complete\")} ${msg.totalChunks} chunks in ${msg.duration}ms`;\n\n case \"duplicates:indexing:error\":\n return `${chalk.cyan(\"duplicates:indexing:error\")} ${chalk.red(msg.error)}`;\n\n case \"file:changed\":\n return `${chalk.cyan(\"file:changed\")} ${msg.filePath}`;\n\n case \"config:update\":\n return `${chalk.cyan(\"config:update\")} ${msg.key} = ${JSON.stringify(msg.value)}`;\n\n default:\n return `${chalk.cyan(msg.type)} ${JSON.stringify(msg)}`;\n }\n}\n\n/**\n * Run interactive REPL mode\n */\nasync function runRepl(client: SocketClient, options: SocketOptions): Promise<void> {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: chalk.green(\"uilint> \"),\n });\n\n console.log(chalk.bold(\"\\nUILint Socket REPL\"));\n console.log(\"Type 'help' for available commands, 'exit' to quit.\\n\");\n\n // Set up message handler\n client.onMessage((msg) => {\n console.log(\"\\n\" + formatMessage(msg, options.json));\n rl.prompt();\n });\n\n // Wait for initial messages\n try {\n await client.waitForWorkspaceInfo(2000);\n } catch {\n // Ignore timeout\n }\n\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) {\n rl.prompt();\n return;\n }\n\n const [cmd, ...args] = trimmed.split(/\\s+/);\n\n try {\n switch (cmd) {\n case \"help\":\n console.log(`\nAvailable commands:\n lint:file <path> Lint a file\n lint:element <path> <dataLoc> Lint a specific element\n vision:check Check if vision is available\n vision:analyze <route> <manifestFile> [screenshotFile]\n Run vision analysis\n source:fetch <path> Fetch source code\n coverage:request Request coverage data\n rule:config <ruleId> <severity> [optionsJson]\n Set rule configuration\n config:set <key> <value> Set a config value\n subscribe <path> Subscribe to file changes\n invalidate [path] Invalidate cache\n messages Show queued messages\n clear Clear message queue\n json Toggle JSON output\n exit Exit REPL\n`);\n break;\n\n case \"lint:file\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: lint:file <path>\"));\n } else {\n const result = await client.lintFile(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"lint:element\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: lint:element <path> <dataLoc>\"));\n } else {\n const result = await client.lintElement(args[0], args[1], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"vision:check\": {\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"vision:analyze\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: vision:analyze <route> <manifestFile> [screenshotFile]\"));\n } else {\n const manifestPath = args[1];\n if (!existsSync(manifestPath)) {\n console.log(chalk.red(`Manifest file not found: ${manifestPath}`));\n } else {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\")) as ElementManifest[];\n const params: {\n route: string;\n manifest: ElementManifest[];\n screenshotFile?: string;\n screenshot?: string;\n } = { route: args[0], manifest };\n\n if (args[2]) {\n if (existsSync(args[2])) {\n // Read as base64\n const imageBuffer = readFileSync(args[2]);\n params.screenshot = imageBuffer.toString(\"base64\");\n } else {\n console.log(chalk.red(`Screenshot file not found: ${args[2]}`));\n break;\n }\n }\n\n const result = await client.visionAnalyze(params, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n }\n break;\n\n case \"source:fetch\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: source:fetch <path>\"));\n } else {\n const result = await client.fetchSource(args[0], options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"coverage:request\": {\n const result = await client.requestCoverage(options.timeout);\n console.log(formatMessage(result, options.json));\n break;\n }\n\n case \"rule:config\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: rule:config <ruleId> <severity> [optionsJson]\"));\n } else {\n const severity = args[1] as \"error\" | \"warn\" | \"off\";\n const ruleOptions = args[2] ? JSON.parse(args[2]) : undefined;\n const result = await client.setRuleConfig(args[0], severity, ruleOptions, options.timeout);\n console.log(formatMessage(result, options.json));\n }\n break;\n\n case \"config:set\":\n if (!args[0] || !args[1]) {\n console.log(chalk.red(\"Usage: config:set <key> <value>\"));\n } else {\n let value: unknown = args[1];\n try {\n value = JSON.parse(args[1]);\n } catch {\n // Keep as string\n }\n client.setConfig(args[0], value);\n console.log(chalk.green(`Set ${args[0]} = ${JSON.stringify(value)}`));\n }\n break;\n\n case \"subscribe\":\n if (!args[0]) {\n console.log(chalk.red(\"Usage: subscribe <path>\"));\n } else {\n client.subscribeFile(args[0]);\n console.log(chalk.green(`Subscribed to ${args[0]}`));\n }\n break;\n\n case \"invalidate\":\n client.invalidateCache(args[0]);\n console.log(chalk.green(args[0] ? `Invalidated ${args[0]}` : \"Invalidated all cache\"));\n break;\n\n case \"messages\": {\n const msgs = client.getMessages();\n if (msgs.length === 0) {\n console.log(chalk.dim(\"No queued messages\"));\n } else {\n for (const msg of msgs) {\n console.log(formatMessage(msg, options.json));\n }\n }\n break;\n }\n\n case \"clear\":\n client.clearMessages();\n console.log(chalk.green(\"Message queue cleared\"));\n break;\n\n case \"json\":\n options.json = !options.json;\n console.log(chalk.green(`JSON output ${options.json ? \"enabled\" : \"disabled\"}`));\n break;\n\n case \"exit\":\n case \"quit\":\n client.disconnect();\n rl.close();\n process.exit(0);\n break;\n\n default:\n console.log(chalk.red(`Unknown command: ${cmd}. Type 'help' for available commands.`));\n }\n } catch (err) {\n console.log(chalk.red(`Error: ${(err as Error).message}`));\n }\n\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n client.disconnect();\n process.exit(0);\n });\n}\n\n/**\n * Run listen mode (print all messages)\n */\nasync function runListen(\n client: SocketClient,\n options: SocketOptions,\n filter?: string\n): Promise<void> {\n console.log(chalk.bold(\"\\nListening for messages...\"));\n if (filter) {\n console.log(chalk.dim(`Filter: ${filter}`));\n }\n console.log(chalk.dim(\"Press Ctrl+C to stop.\\n\"));\n\n client.onMessage((msg) => {\n if (filter && !msg.type.includes(filter.replace(\"*\", \"\"))) {\n return;\n }\n console.log(formatMessage(msg, options.json));\n });\n\n // Keep running\n await new Promise(() => {});\n}\n\n/**\n * Create the socket command\n */\nexport function createSocketCommand(): Command {\n const cmd = new Command(\"socket\")\n .description(\"Interact with the UILint socket server\")\n .option(\"-p, --port <number>\", \"Socket server port\", \"9234\")\n .option(\"-d, --debug\", \"Enable debug logging\", false)\n .option(\"-j, --json\", \"Output JSON format\", false)\n .option(\"-t, --timeout <ms>\", \"Request timeout in milliseconds\", \"30000\");\n\n // Default action: start REPL\n cmd.action(async (cmdOptions) => {\n const options: SocketOptions = {\n port: parseInt(cmdOptions.port, 10),\n debug: cmdOptions.debug,\n json: cmdOptions.json,\n timeout: parseInt(cmdOptions.timeout, 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runRepl(client, options);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n console.error(chalk.dim(`Make sure the server is running: uilint serve -p ${options.port}`));\n process.exit(1);\n }\n });\n\n // listen subcommand\n cmd\n .command(\"listen\")\n .description(\"Listen for all messages from the server\")\n .option(\"-f, --filter <pattern>\", \"Filter messages by type pattern (e.g., lint:*, vision:*)\")\n .action(async (subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await runListen(client, options, subOptions.filter);\n } catch (err) {\n console.error(chalk.red(`Failed to connect: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // lint:file subcommand\n cmd\n .command(\"lint:file <path>\")\n .description(\"Lint a file and output results\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"30000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.lintFile(filePath, options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.issues.length > 0 ? 1 : 0);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // vision:check subcommand\n cmd\n .command(\"vision:check\")\n .description(\"Check if vision analysis is available\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const result = await client.visionCheck(options.timeout);\n console.log(formatMessage(result, options.json));\n client.disconnect();\n process.exit(result.available ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // source:fetch subcommand\n cmd\n .command(\"source:fetch <path>\")\n .description(\"Fetch source code for a file\")\n .action(async (filePath, _subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n await client.waitForWorkspaceInfo(2000).catch(() => {});\n const result = await client.fetchSource(filePath, options.timeout);\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else if (result.type === \"source:result\") {\n console.log(result.content);\n } else {\n console.error(chalk.red(`Error: ${result.error}`));\n }\n client.disconnect();\n process.exit(result.type === \"source:result\" ? 0 : 1);\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n // rules subcommand\n cmd\n .command(\"rules\")\n .description(\"List available rules\")\n .action(async (_subOptions, command) => {\n const parentOptions = command.parent?.opts() || {};\n const options: SocketOptions = {\n port: parseInt(parentOptions.port || \"9234\", 10),\n debug: parentOptions.debug || false,\n json: parentOptions.json || false,\n timeout: parseInt(parentOptions.timeout || \"10000\", 10),\n };\n\n try {\n const client = await createSocketClient({ port: options.port, debug: options.debug });\n const metadata = await client.waitForRulesMetadata(options.timeout);\n\n if (options.json) {\n console.log(JSON.stringify(metadata.rules, null, 2));\n } else {\n console.log(chalk.bold(`\\n${metadata.rules.length} rules available:\\n`));\n for (const rule of metadata.rules) {\n const severity =\n rule.currentSeverity === \"error\"\n ? chalk.red(\"error\")\n : rule.currentSeverity === \"warn\"\n ? chalk.yellow(\"warn\")\n : chalk.dim(\"off\");\n console.log(` ${chalk.cyan(rule.id)} [${severity}]`);\n console.log(chalk.dim(` ${rule.description}`));\n }\n }\n\n client.disconnect();\n } catch (err) {\n console.error(chalk.red(`Error: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\n// Re-export types and client for programmatic use\nexport { SocketClient, createSocketClient } from \"./client.js\";\nexport { SocketTestHarness, createTestHarness } from \"./test-harness.js\";\nexport type * from \"./types.js\";\n","/**\n * Socket Client\n *\n * WebSocket client for communicating with the UILint socket server.\n * Provides request/response correlation and message handling.\n */\n\nimport WebSocket from \"ws\";\nimport type {\n ClientMessage,\n ServerMessage,\n LintResultMessage,\n VisionStatusMessage,\n VisionResultMessage,\n SourceResultMessage,\n SourceErrorMessage,\n CoverageResultMessage,\n CoverageErrorMessage,\n RuleConfigResultMessage,\n WorkspaceInfoMessage,\n RulesMetadataMessage,\n ElementManifest,\n} from \"./types.js\";\n\nexport interface SocketClientOptions {\n /** WebSocket URL (default: ws://localhost:9234) */\n url?: string;\n /** Port number (convenience, overrides url) */\n port?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Connection timeout in ms (default: 10000) */\n connectTimeout?: number;\n}\n\ntype MessageHandler = (message: ServerMessage) => void;\n\ninterface PendingRequest {\n predicate: (msg: ServerMessage) => boolean;\n resolve: (msg: ServerMessage) => void;\n reject: (err: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\nexport class SocketClient {\n private ws: WebSocket | null = null;\n private url: string;\n private debug: boolean;\n private connectTimeout: number;\n private connected = false;\n private connectionPromise: Promise<void> | null = null;\n private pendingRequests: PendingRequest[] = [];\n private messageQueue: ServerMessage[] = [];\n private messageHandlers: MessageHandler[] = [];\n\n constructor(options: SocketClientOptions = {}) {\n const port = options.port || 9234;\n this.url = options.url || `ws://localhost:${port}`;\n this.debug = options.debug || false;\n this.connectTimeout = options.connectTimeout || 10000;\n }\n\n /**\n * Connect to the socket server\n */\n async connect(): Promise<void> {\n if (this.connected) return;\n if (this.connectionPromise) return this.connectionPromise;\n\n this.connectionPromise = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Connection timeout to ${this.url}`));\n }, this.connectTimeout);\n\n this.ws = new WebSocket(this.url);\n\n this.ws.on(\"open\", () => {\n clearTimeout(timeout);\n this.connected = true;\n this.log(\"Connected to\", this.url);\n resolve();\n });\n\n this.ws.on(\"message\", (data: WebSocket.Data) => {\n try {\n const message = JSON.parse(data.toString()) as ServerMessage;\n this.log(\"Received:\", message.type);\n this.handleMessage(message);\n } catch (e) {\n console.error(\"Failed to parse message:\", e);\n }\n });\n\n this.ws.on(\"error\", (err) => {\n clearTimeout(timeout);\n if (!this.connected) {\n reject(err);\n } else {\n console.error(\"WebSocket error:\", err);\n }\n });\n\n this.ws.on(\"close\", () => {\n this.connected = false;\n this.log(\"Disconnected\");\n // Reject all pending requests\n for (const req of this.pendingRequests) {\n clearTimeout(req.timeout);\n req.reject(new Error(\"Disconnected\"));\n }\n this.pendingRequests = [];\n });\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n this.connected = false;\n this.connectionPromise = null;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Add a handler for all incoming messages\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.push(handler);\n return () => {\n this.messageHandlers = this.messageHandlers.filter((h) => h !== handler);\n };\n }\n\n /**\n * Send a raw message\n */\n send(message: ClientMessage): void {\n if (!this.ws || !this.connected) {\n throw new Error(\"Not connected\");\n }\n this.log(\"Sending:\", message.type);\n this.ws.send(JSON.stringify(message));\n }\n\n /**\n * Wait for a message matching the predicate\n */\n waitFor(\n predicate: (msg: ServerMessage) => boolean,\n timeout = 30000\n ): Promise<ServerMessage> {\n // Check existing messages first\n const existing = this.messageQueue.find(predicate);\n if (existing) {\n this.messageQueue = this.messageQueue.filter((m) => m !== existing);\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests = this.pendingRequests.filter(\n (r) => r.timeout !== timeoutId\n );\n reject(new Error(`Timeout waiting for message (${timeout}ms)`));\n }, timeout);\n\n this.pendingRequests.push({\n predicate,\n resolve,\n reject,\n timeout: timeoutId,\n });\n });\n }\n\n /**\n * Generate a unique request ID\n */\n private generateRequestId(): string {\n return `cli-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n // ==========================================================================\n // High-Level API Methods\n // ==========================================================================\n\n /**\n * Wait for workspace info (sent on connect)\n */\n async waitForWorkspaceInfo(timeout = 5000): Promise<WorkspaceInfoMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"workspace:info\");\n if (existing) {\n return existing as WorkspaceInfoMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"workspace:info\",\n timeout\n )) as WorkspaceInfoMessage;\n }\n\n /**\n * Wait for rules metadata (sent on connect)\n */\n async waitForRulesMetadata(timeout = 5000): Promise<RulesMetadataMessage> {\n const existing = this.messageQueue.find((m) => m.type === \"rules:metadata\");\n if (existing) {\n return existing as RulesMetadataMessage;\n }\n return (await this.waitFor(\n (msg) => msg.type === \"rules:metadata\",\n timeout\n )) as RulesMetadataMessage;\n }\n\n /**\n * Lint a file\n */\n async lintFile(filePath: string, timeout = 30000): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:file\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Lint a specific element\n */\n async lintElement(\n filePath: string,\n dataLoc: string,\n timeout = 30000\n ): Promise<LintResultMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"lint:element\", filePath, dataLoc, requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"lint:result\" &&\n (msg as LintResultMessage).requestId === requestId,\n timeout\n )) as LintResultMessage;\n }\n\n /**\n * Check if vision analysis is available\n */\n async visionCheck(timeout = 10000): Promise<VisionStatusMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"vision:check\", requestId });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:status\" &&\n (msg as VisionStatusMessage).requestId === requestId,\n timeout\n )) as VisionStatusMessage;\n }\n\n /**\n * Run vision analysis\n */\n async visionAnalyze(\n params: {\n route: string;\n manifest: ElementManifest[];\n screenshot?: string;\n screenshotFile?: string;\n },\n timeout = 120000\n ): Promise<VisionResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"vision:analyze\",\n route: params.route,\n timestamp: Date.now(),\n screenshot: params.screenshot,\n screenshotFile: params.screenshotFile,\n manifest: params.manifest,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"vision:result\" &&\n (msg as VisionResultMessage).requestId === requestId,\n timeout\n )) as VisionResultMessage;\n }\n\n /**\n * Fetch source code\n */\n async fetchSource(\n filePath: string,\n timeout = 10000\n ): Promise<SourceResultMessage | SourceErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"source:fetch\", filePath, requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"source:result\" || msg.type === \"source:error\") &&\n ((msg as SourceResultMessage).requestId === requestId ||\n (msg as SourceErrorMessage).requestId === requestId),\n timeout\n )) as SourceResultMessage | SourceErrorMessage;\n }\n\n /**\n * Request coverage data\n */\n async requestCoverage(\n timeout = 30000\n ): Promise<CoverageResultMessage | CoverageErrorMessage> {\n const requestId = this.generateRequestId();\n this.send({ type: \"coverage:request\", requestId });\n return (await this.waitFor(\n (msg) =>\n (msg.type === \"coverage:result\" || msg.type === \"coverage:error\") &&\n ((msg as CoverageResultMessage).requestId === requestId ||\n (msg as CoverageErrorMessage).requestId === requestId),\n timeout\n )) as CoverageResultMessage | CoverageErrorMessage;\n }\n\n /**\n * Set rule configuration\n */\n async setRuleConfig(\n ruleId: string,\n severity: \"error\" | \"warn\" | \"off\",\n options?: Record<string, unknown>,\n timeout = 10000\n ): Promise<RuleConfigResultMessage> {\n const requestId = this.generateRequestId();\n this.send({\n type: \"rule:config:set\",\n ruleId,\n severity,\n options,\n requestId,\n });\n return (await this.waitFor(\n (msg) =>\n msg.type === \"rule:config:result\" &&\n (msg as RuleConfigResultMessage).requestId === requestId,\n timeout\n )) as RuleConfigResultMessage;\n }\n\n /**\n * Set a configuration value\n */\n setConfig(key: string, value: unknown): void {\n this.send({ type: \"config:set\", key, value });\n }\n\n /**\n * Subscribe to file changes\n */\n subscribeFile(filePath: string): void {\n this.send({ type: \"subscribe:file\", filePath });\n }\n\n /**\n * Invalidate cache\n */\n invalidateCache(filePath?: string): void {\n this.send({ type: \"cache:invalidate\", filePath });\n }\n\n /**\n * Get all queued messages\n */\n getMessages(): ServerMessage[] {\n return [...this.messageQueue];\n }\n\n /**\n * Clear message queue\n */\n clearMessages(): void {\n this.messageQueue = [];\n }\n\n private handleMessage(message: ServerMessage): void {\n // Notify all handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n\n // Check if any pending request matches\n for (let i = 0; i < this.pendingRequests.length; i++) {\n const req = this.pendingRequests[i]!;\n if (req.predicate(message)) {\n clearTimeout(req.timeout);\n this.pendingRequests.splice(i, 1);\n req.resolve(message);\n return;\n }\n }\n\n // Otherwise queue it\n this.messageQueue.push(message);\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log(\"[SocketClient]\", ...args);\n }\n }\n}\n\n/**\n * Create a connected socket client\n */\nexport async function createSocketClient(\n options: SocketClientOptions = {}\n): Promise<SocketClient> {\n const client = new SocketClient(options);\n await client.connect();\n return client;\n}\n"],"mappings":"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","names":["Command","resolve","existsSync","formatViolationsText","sanitizeIssues","findWorkspaceRoot","resolve","resolve","existsSync","sanitizeIssues","formatViolationsText","dirname","resolve","existsSync","mkdirSync","writeFileSync","ensureOllamaReady","readStyleGuide","findStyleGuidePath","findWorkspaceRoot","findUILintStyleGuideUpwards","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","existsSync","readStyleGuide","findUILintStyleGuideUpwards","dirname","findStyleGuidePath","findWorkspaceRoot","ensureOllamaReady","mkdirSync","writeFileSync","ensureOllamaReady","readStdin","resolve","result","ensureOllamaReady","dirname","resolve","createStyleSummary","readStyleGuide","findStyleGuidePath","ensureOllamaReady","readTailwindThemeTokens","findStyleGuidePath","readStyleGuide","dirname","resolve","readTailwindThemeTokens","ensureOllamaReady","createStyleSummary","existsSync","statSync","mkdirSync","writeFileSync","dirname","resolve","join","parse","findWorkspaceRoot","dirname","join","existsSync","statSync","mkdirSync","writeFileSync","ensureOllamaReady","findStyleGuidePath","findUILintStyleGuideUpwards","readStyleGuide","existsSync","statSync","readStyleGuide","findStyleGuidePath","findUILintStyleGuideUpwards","ensureOllamaReady","mkdirSync","dirname","writeFileSync","join","join","existsSync","parse","dirname","resolve","findWorkspaceRoot","statSync","mkdirSync","writeFileSync","dirname","resolve","join","existsSync","readFileSync","readdirSync","ensureOllamaReady","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","envTruthy","preview","debugEnabled","debugFullEnabled","debugDumpPath","resolve","debugLog","join","existsSync","dirname","readdirSync","readFileSync","STYLEGUIDE_PATHS","UILINT_DEFAULT_VISION_MODEL","ensureOllamaReady","WebSocket","resolve","WebSocket","config","Command","chalk","Command","relative","chalk","Command","relative","chalk","Command","relative","resolve","isAbsolute","chalk","Command","readFileSync","dirname","join","Command","readFileSync","existsSync","chalk","WebSocket","resolve","chalk","existsSync","readFileSync","Command","Command","dirname","join","readFileSync","config"]}