@kakarot-ci/core 0.4.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
 
4
3
  // src/cli/index.ts
5
4
  import { readFileSync as readFileSync2 } from "fs";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/index.ts", "../../src/github/client.ts", "../../src/utils/logger.ts", "../../src/utils/config-loader.ts", "../../src/types/config.ts", "../../src/utils/diff-parser.ts", "../../src/utils/ast-analyzer.ts", "../../src/utils/test-target-extractor.ts", "../../src/llm/providers/base.ts", "../../src/llm/providers/openai.ts", "../../src/llm/providers/anthropic.ts", "../../src/llm/providers/google.ts", "../../src/llm/factory.ts", "../../src/llm/prompts/test-generation.ts", "../../src/llm/prompts/test-fix.ts", "../../src/llm/parser.ts", "../../src/llm/test-generator.ts", "../../src/utils/test-file-path.ts", "../../src/utils/package-manager-detector.ts", "../../src/utils/test-runner/jest-runner.ts", "../../src/utils/test-runner/vitest-runner.ts", "../../src/utils/test-runner/factory.ts", "../../src/utils/test-file-writer.ts", "../../src/utils/coverage-reader.ts", "../../src/llm/prompts/coverage-summary.ts", "../../src/core/orchestrator.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * CLI entry point for Kakarot CI\n * Parses CI environment variables and runs test generation\n */\n\nimport { readFileSync } from 'fs';\nimport { simpleGit } from 'simple-git';\nimport gitUrlParse from 'git-url-parse';\nimport { Command } from 'commander';\nimport { runPullRequest, type PullRequestContext } from '../core/orchestrator.js';\nimport { error, info, debug } from '../utils/logger.js';\nimport { loadConfig } from '../utils/config-loader.js';\nimport { findProjectRoot } from '../utils/config-loader.js';\n\ninterface GitHubEvent {\n pull_request?: {\n number: number;\n };\n number?: number;\n}\n\n/**\n * Parse GitHub repository string (format: \"owner/repo\")\n */\nfunction parseRepository(repo: string): { owner: string; repo: string } {\n const parts = repo.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid repository format: ${repo}. Expected \"owner/repo\"`);\n }\n return { owner: parts[0], repo: parts[1] };\n}\n\n/**\n * Detect repository from current git working directory\n */\nasync function detectGitRepository(projectRoot: string): Promise<{ owner: string; repo: string } | null> {\n try {\n const git = simpleGit(projectRoot);\n \n // Get the remote URL (prefer origin, fallback to first remote)\n let remoteUrl: string | null = null;\n \n try {\n remoteUrl = await git.getRemotes(true).then(remotes => {\n const origin = remotes.find(r => r.name === 'origin');\n return origin?.refs?.fetch || origin?.refs?.push || null;\n });\n \n if (!remoteUrl) {\n const remotes = await git.getRemotes(true);\n if (remotes.length > 0) {\n remoteUrl = remotes[0].refs?.fetch || remotes[0].refs?.push || null;\n }\n }\n } catch {\n return null;\n }\n \n if (!remoteUrl) {\n return null;\n }\n \n // Parse GitHub URL\n try {\n const parsed = gitUrlParse(remoteUrl);\n if (parsed.resource === 'github.com') {\n return {\n owner: parsed.owner,\n repo: parsed.name.replace(/\\.git$/, ''),\n };\n }\n } catch {\n // Not a GitHub URL or parse failed\n return null;\n }\n \n return null;\n } catch (err) {\n debug(`Failed to detect git repository: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n/**\n * Extract PR number from GitHub event JSON\n */\nfunction extractPRNumber(eventPath?: string): number | null {\n if (!eventPath) {\n return null;\n }\n\n try {\n const eventContent = readFileSync(eventPath, 'utf-8');\n const event: GitHubEvent = JSON.parse(eventContent);\n\n if (event.pull_request?.number) {\n return event.pull_request.number;\n }\n\n if (event.number) {\n return event.number;\n }\n\n return null;\n } catch (err) {\n error(`Failed to read GitHub event file: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n/**\n * Main CLI function\n */\nasync function main(): Promise<void> {\n const program = new Command();\n\n program\n .name('kakarot-ci')\n .description('AI-powered unit test generation for pull requests')\n .version('0.2.0')\n .option('--pr <number>', 'Pull request number')\n .option('--owner <string>', 'Repository owner')\n .option('--repo <string>', 'Repository name')\n .option('--token <string>', 'GitHub token (or use GITHUB_TOKEN env var)')\n .parse(process.argv);\n\n const options = program.opts();\n\n // Load config first to get defaults\n let config;\n try {\n config = await loadConfig();\n } catch (err) {\n // Config loading might fail if apiKey is missing, but we can continue\n config = null;\n }\n\n // Parse environment variables (with CLI args as highest priority, then config, then env)\n const githubRepository = process.env.GITHUB_REPOSITORY;\n const githubEventPath = process.env.GITHUB_EVENT_PATH;\n const githubToken = options.token || config?.githubToken || process.env.GITHUB_TOKEN;\n const prNumberEnv = process.env.PR_NUMBER;\n\n // Extract owner/repo from various sources (priority: CLI > env > config > git)\n let owner: string | undefined = options.owner;\n let repo: string | undefined = options.repo;\n\n // Try parsing from GITHUB_REPOSITORY if not provided via CLI\n if (!owner || !repo) {\n if (githubRepository) {\n try {\n const parsed = parseRepository(githubRepository);\n owner = owner || parsed.owner;\n repo = repo || parsed.repo;\n } catch (err) {\n if (!owner && !repo) {\n error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n }\n }\n }\n\n // Fallback to config defaults\n if (!owner || !repo) {\n owner = owner || config?.githubOwner;\n repo = repo || config?.githubRepo;\n }\n\n // Fallback to git repository detection\n if (!owner || !repo) {\n const projectRoot = await findProjectRoot();\n const gitRepo = await detectGitRepository(projectRoot);\n if (gitRepo) {\n owner = owner || gitRepo.owner;\n repo = repo || gitRepo.repo;\n debug(`Detected repository from git: ${owner}/${repo}`);\n }\n }\n\n // Validate required values\n if (!owner || !repo) {\n error('Repository owner and name are required.');\n error('Provide via:');\n error(' - Config file: githubOwner and githubRepo');\n error(' - CLI flags: --owner and --repo');\n error(' - Environment: GITHUB_REPOSITORY (format: \"owner/repo\")');\n error(' - Git remote: auto-detected from current repository');\n process.exit(1);\n }\n\n if (!githubToken) {\n error('GitHub token is required.');\n error('Provide via:');\n error(' - Config file: githubToken');\n error(' - CLI flag: --token');\n error(' - Environment: GITHUB_TOKEN');\n process.exit(1);\n }\n\n // Extract PR number from various sources\n let prNumber: number | null = null;\n\n // Priority: CLI arg > env var > GitHub event file\n if (options.pr) {\n prNumber = parseInt(String(options.pr), 10);\n if (isNaN(prNumber)) {\n error(`Invalid PR number: ${options.pr}`);\n process.exit(1);\n }\n } else if (prNumberEnv) {\n const parsed = parseInt(prNumberEnv, 10);\n if (!isNaN(parsed)) {\n prNumber = parsed;\n }\n } else if (githubEventPath) {\n prNumber = extractPRNumber(githubEventPath);\n }\n\n if (!prNumber) {\n error('Pull request number is required.');\n error('Provide via:');\n error(' - CLI flag: --pr <number>');\n error(' - Environment: PR_NUMBER');\n error(' - GitHub Actions: GITHUB_EVENT_PATH (auto-detected)');\n process.exit(1);\n }\n\n // Build context\n const context: PullRequestContext = {\n prNumber,\n owner,\n repo,\n githubToken,\n };\n\n info(`Starting Kakarot CI for PR #${prNumber} in ${owner}/${repo}`);\n\n try {\n const summary = await runPullRequest(context);\n\n // Exit with error code if there were failures\n if (summary.errors.length > 0 || summary.testsFailed > 0) {\n error(`Test generation completed with errors: ${summary.errors.length} error(s), ${summary.testsFailed} test(s) failed`);\n process.exit(1);\n }\n\n info(`Test generation completed successfully: ${summary.testsGenerated} test(s) generated`);\n process.exit(0);\n } catch (err) {\n error(`Fatal error: ${err instanceof Error ? err.message : String(err)}`);\n if (err instanceof Error && err.stack) {\n error(err.stack);\n }\n process.exit(1);\n }\n}\n\n// Run CLI\nmain().catch((err) => {\n error(`Unhandled error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n", "import { Octokit } from '@octokit/rest';\nimport type { PullRequest, PullRequestFile, FileContents, GitHubClientOptions, BatchCommitOptions } from '../types/github.js';\nimport { debug, error, warn } from '../utils/logger.js';\n\n/**\n * GitHub API client wrapper with retry and rate-limit handling\n */\nexport class GitHubClient {\n private octokit: Octokit;\n private owner: string;\n private repo: string;\n private maxRetries = 3;\n private retryDelay = 1000; // 1 second\n\n constructor(options: GitHubClientOptions) {\n this.owner = options.owner;\n this.repo = options.repo;\n this.octokit = new Octokit({\n auth: options.token,\n request: {\n retries: this.maxRetries,\n retryAfter: this.retryDelay / 1000,\n },\n });\n }\n\n /**\n * Retry wrapper with exponential backoff\n */\n private async withRetry<T>(\n fn: () => Promise<T>,\n operation: string,\n retries = this.maxRetries\n ): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n if (retries <= 0) {\n error(`${operation} failed after ${this.maxRetries} retries: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n\n const isRateLimit = err instanceof Error && err.message.includes('rate limit');\n const isServerError = err instanceof Error && (\n err.message.includes('500') ||\n err.message.includes('502') ||\n err.message.includes('503') ||\n err.message.includes('504')\n );\n\n if (isRateLimit || isServerError) {\n const delay = this.retryDelay * Math.pow(2, this.maxRetries - retries);\n warn(`${operation} failed, retrying in ${delay}ms... (${retries} retries left)`);\n await new Promise(resolve => setTimeout(resolve, delay));\n return this.withRetry(fn, operation, retries - 1);\n }\n\n throw err;\n }\n }\n\n /**\n * Get pull request details\n */\n async getPullRequest(prNumber: number): Promise<PullRequest> {\n return this.withRetry(async () => {\n debug(`Fetching PR #${prNumber}`);\n const response = await this.octokit.rest.pulls.get({\n owner: this.owner,\n repo: this.repo,\n pull_number: prNumber,\n });\n return response.data as PullRequest;\n }, `getPullRequest(${prNumber})`);\n }\n\n /**\n * List all files changed in a pull request with patches\n */\n async listPullRequestFiles(prNumber: number): Promise<PullRequestFile[]> {\n return this.withRetry(async () => {\n debug(`Fetching files for PR #${prNumber}`);\n const response = await this.octokit.rest.pulls.listFiles({\n owner: this.owner,\n repo: this.repo,\n pull_number: prNumber,\n });\n return response.data.map(file => ({\n filename: file.filename,\n status: file.status as PullRequestFile['status'],\n additions: file.additions,\n deletions: file.deletions,\n changes: file.changes,\n patch: file.patch || undefined,\n previous_filename: file.previous_filename || undefined,\n }));\n }, `listPullRequestFiles(${prNumber})`);\n }\n\n /**\n * Get file contents from a specific ref (branch, commit, etc.)\n */\n async getFileContents(ref: string, path: string): Promise<FileContents> {\n return this.withRetry(async () => {\n debug(`Fetching file contents: ${path}@${ref}`);\n const response = await this.octokit.rest.repos.getContent({\n owner: this.owner,\n repo: this.repo,\n path,\n ref,\n });\n\n if (Array.isArray(response.data)) {\n throw new Error(`Expected file but got directory: ${path}`);\n }\n\n const data = response.data as { content: string; encoding: string; sha: string; size: number };\n \n // Decode base64 content\n let content: string;\n if (data.encoding === 'base64') {\n content = Buffer.from(data.content, 'base64').toString('utf-8');\n } else {\n content = data.content;\n }\n\n return {\n content,\n encoding: data.encoding as 'base64' | 'utf-8',\n sha: data.sha,\n size: data.size,\n };\n }, `getFileContents(${ref}, ${path})`);\n }\n\n /**\n * Commit multiple files in a single commit using Git tree API\n */\n async commitFiles(options: BatchCommitOptions): Promise<string> {\n return this.withRetry(async () => {\n debug(`Committing ${options.files.length} file(s) to branch ${options.branch}`);\n\n // Get the base tree SHA\n const baseCommit = await this.octokit.rest.repos.getCommit({\n owner: this.owner,\n repo: this.repo,\n ref: options.baseSha,\n });\n const baseTreeSha = baseCommit.data.commit.tree.sha;\n\n // Create blobs for all files\n const blobPromises = options.files.map(async (file) => {\n const blobResponse = await this.octokit.rest.git.createBlob({\n owner: this.owner,\n repo: this.repo,\n content: Buffer.from(file.content, 'utf-8').toString('base64'),\n encoding: 'base64',\n });\n return {\n path: file.path,\n sha: blobResponse.data.sha,\n mode: '100644' as const,\n type: 'blob' as const,\n };\n });\n\n const treeItems = await Promise.all(blobPromises);\n\n // Create a new tree with the blobs\n const treeResponse = await this.octokit.rest.git.createTree({\n owner: this.owner,\n repo: this.repo,\n base_tree: baseTreeSha,\n tree: treeItems,\n });\n\n // Create the commit\n const commitResponse = await this.octokit.rest.git.createCommit({\n owner: this.owner,\n repo: this.repo,\n message: options.message,\n tree: treeResponse.data.sha,\n parents: [options.baseSha],\n });\n\n // Update the branch reference\n await this.octokit.rest.git.updateRef({\n owner: this.owner,\n repo: this.repo,\n ref: `heads/${options.branch}`,\n sha: commitResponse.data.sha,\n });\n\n return commitResponse.data.sha;\n }, `commitFiles(${options.files.length} files)`);\n }\n\n /**\n * Create a new branch from a base ref\n */\n async createBranch(branchName: string, baseRef: string): Promise<string> {\n return this.withRetry(async () => {\n debug(`Creating branch ${branchName} from ${baseRef}`);\n\n // Get the SHA of the base ref\n const baseRefResponse = await this.octokit.rest.git.getRef({\n owner: this.owner,\n repo: this.repo,\n ref: baseRef.startsWith('refs/') ? baseRef : `heads/${baseRef}`,\n });\n const baseSha = baseRefResponse.data.object.sha;\n\n // Create the new branch\n await this.octokit.rest.git.createRef({\n owner: this.owner,\n repo: this.repo,\n ref: `refs/heads/${branchName}`,\n sha: baseSha,\n });\n\n return baseSha;\n }, `createBranch(${branchName})`);\n }\n\n /**\n * Create a pull request\n */\n async createPullRequest(\n title: string,\n body: string,\n head: string,\n base: string\n ): Promise<PullRequest> {\n return this.withRetry(async () => {\n debug(`Creating PR: ${head} -> ${base}`);\n\n const response = await this.octokit.rest.pulls.create({\n owner: this.owner,\n repo: this.repo,\n title,\n body,\n head,\n base,\n });\n\n return response.data as PullRequest;\n }, `createPullRequest(${head} -> ${base})`);\n }\n\n /**\n * Post a comment on a pull request\n */\n async commentPR(prNumber: number, body: string): Promise<void> {\n await this.withRetry(async () => {\n debug(`Posting comment on PR #${prNumber}`);\n await this.octokit.rest.issues.createComment({\n owner: this.owner,\n repo: this.repo,\n issue_number: prNumber,\n body,\n });\n }, `commentPR(${prNumber})`);\n }\n\n /**\n * Check if a file exists in the repository\n */\n async fileExists(ref: string, path: string): Promise<boolean> {\n return this.withRetry(async () => {\n try {\n await this.octokit.rest.repos.getContent({\n owner: this.owner,\n repo: this.repo,\n path,\n ref,\n });\n return true;\n } catch (err) {\n if (err instanceof Error && err.message.includes('404')) {\n return false;\n }\n throw err;\n }\n }, `fileExists(${ref}, ${path})`);\n }\n\n /**\n * Get the current rate limit status\n */\n async getRateLimit(): Promise<{ remaining: number; reset: number }> {\n const response = await this.octokit.rest.rateLimit.get();\n return {\n remaining: response.data.rate.remaining,\n reset: response.data.rate.reset,\n };\n }\n}\n\n", "import type { KakarotConfig } from '../types/config.js';\n\nlet debugMode = false;\nlet jsonMode = false;\n\nexport function initLogger(config: Pick<KakarotConfig, 'debug'>): void {\n debugMode = config.debug ?? process.env.KAKAROT_DEBUG === 'true';\n jsonMode = process.env.KAKAROT_OUTPUT === 'json';\n}\n\n\nexport function info(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'info', message, ...args }));\n } else {\n console.log(`[kakarot-ci] ${message}`, ...args);\n }\n}\n\nexport function debug(message: string, ...args: unknown[]): void {\n if (debugMode) {\n if (jsonMode) {\n console.debug(JSON.stringify({ level: 'debug', message, ...args }));\n } else {\n console.debug(`[kakarot-ci:debug] ${message}`, ...args);\n }\n }\n}\n\nexport function warn(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.warn(JSON.stringify({ level: 'warn', message, ...args }));\n } else {\n console.warn(`[kakarot-ci] \u26A0 ${message}`, ...args);\n }\n}\n\nexport function error(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.error(JSON.stringify({ level: 'error', message, ...args }));\n } else {\n console.error(`[kakarot-ci] \u2717 ${message}`, ...args);\n }\n}\n\nexport function success(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'success', message, ...args }));\n } else {\n console.log(`[kakarot-ci] \u2713 ${message}`, ...args);\n }\n}\n\nexport function progress(step: number, total: number, message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'info', step, total, message, ...args }));\n } else {\n console.log(`[kakarot-ci] Step ${step}/${total}: ${message}`, ...args);\n }\n}\n", "import { cosmiconfig } from 'cosmiconfig';\nimport { findUp } from 'find-up';\nimport { KakarotConfigSchema, type KakarotConfig, type PartialKakarotConfig } from '../types/config.js';\nimport { error } from './logger.js';\n\n/**\n * Find the project root by locating package.json\n */\nexport async function findProjectRoot(startPath?: string): Promise<string> {\n const packageJsonPath = await findUp('package.json', {\n cwd: startPath ?? process.cwd(),\n });\n \n if (packageJsonPath) {\n const { dirname } = await import('path');\n return dirname(packageJsonPath);\n }\n \n return startPath ?? process.cwd();\n}\n\n/**\n * Load and validate Kakarot configuration\n */\nexport async function loadConfig(): Promise<KakarotConfig> {\n const explorer = cosmiconfig('kakarot', {\n searchPlaces: [\n 'kakarot.config.ts',\n 'kakarot.config.js',\n '.kakarot-ci.config.ts',\n '.kakarot-ci.config.js',\n '.kakarot-ci.config.json',\n 'package.json',\n ],\n loaders: {\n '.ts': async (filepath: string) => {\n // Dynamic import for TypeScript config file\n // Note: This requires the file to be transpiled or use tsx/ts-node in runtime\n try {\n const configModule = await import(filepath);\n return configModule.default || configModule.config || null;\n } catch (err) {\n error(`Failed to load TypeScript config: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n },\n },\n });\n\n try {\n const result = await explorer.search();\n \n let config: PartialKakarotConfig = {};\n \n if (result?.config) {\n config = result.config as PartialKakarotConfig;\n }\n \n // Also check package.json for kakarotCi field\n if (!result || result.filepath?.endsWith('package.json')) {\n const packageJsonPath = await findUp('package.json');\n if (packageJsonPath) {\n const { readFileSync } = await import('fs');\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { kakarotCi?: PartialKakarotConfig };\n if (pkg.kakarotCi) {\n config = { ...config, ...pkg.kakarotCi };\n }\n } catch {\n // Ignore package.json parse errors\n }\n }\n }\n \n // Merge environment variables\n if (!config.apiKey && process.env.KAKAROT_API_KEY) {\n config.apiKey = process.env.KAKAROT_API_KEY;\n }\n \n if (!config.githubToken && process.env.GITHUB_TOKEN) {\n config.githubToken = process.env.GITHUB_TOKEN;\n }\n \n return KakarotConfigSchema.parse(config);\n } catch (err) {\n if (err instanceof Error && err.message.includes('apiKey')) {\n error(\n 'Missing required apiKey. Provide it via:\\n' +\n ' - Config file (kakarot.config.ts, .kakarot-ci.config.js/json, or package.json)\\n' +\n ' - Environment variable: KAKAROT_API_KEY'\n );\n }\n throw err;\n }\n}\n", "import { z } from 'zod';\n\nexport const KakarotConfigSchema = z.object({\n apiKey: z.string(),\n githubToken: z.string().optional(),\n githubOwner: z.string().optional(),\n githubRepo: z.string().optional(),\n provider: z.enum(['openai', 'anthropic', 'google']).optional(),\n model: z.string().optional(),\n maxTokens: z.number().int().min(1).max(100000).optional(),\n temperature: z.number().min(0).max(2).optional(),\n fixTemperature: z.number().min(0).max(2).optional(),\n maxFixAttempts: z.number().int().min(0).max(5).default(3),\n framework: z.enum(['jest', 'vitest']),\n testLocation: z.enum(['separate', 'co-located']).default('separate'),\n testDirectory: z.string().default('__tests__'),\n testFilePattern: z.string().default('*.test.ts'),\n includePatterns: z.array(z.string()).default(['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']),\n excludePatterns: z.array(z.string()).default(['**/*.test.ts', '**/*.spec.ts', '**/*.test.js', '**/*.spec.js', '**/node_modules/**']),\n maxTestsPerPR: z.number().int().min(1).default(50),\n enableAutoCommit: z.boolean().default(true),\n commitStrategy: z.enum(['direct', 'branch-pr']).default('direct'),\n enablePRComments: z.boolean().default(true),\n debug: z.boolean().default(false),\n});\n\nexport type KakarotConfig = z.infer<typeof KakarotConfigSchema>;\n\nexport type PartialKakarotConfig = Partial<KakarotConfig>;\n\n", "import type { PullRequestFile } from '../types/github.js';\nimport type { FileDiff, DiffHunk } from '../types/diff.js';\nimport { debug } from './logger.js';\n\n/**\n * Parse unified diff format from GitHub patch\n */\nfunction parseUnifiedDiff(patch: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const lines = patch.split('\\n');\n \n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n \n // Match hunk header: @@ -oldStart,oldLines +newStart,newLines @@\n const hunkMatch = line.match(/^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/);\n if (hunkMatch) {\n const oldStart = parseInt(hunkMatch[1], 10);\n const oldLines = parseInt(hunkMatch[2] || '1', 10);\n const newStart = parseInt(hunkMatch[3], 10);\n const newLines = parseInt(hunkMatch[4] || '1', 10);\n \n const hunkLines: string[] = [];\n i++;\n \n // Collect lines until next hunk or end\n while (i < lines.length && !lines[i].startsWith('@@')) {\n hunkLines.push(lines[i]);\n i++;\n }\n \n hunks.push({\n oldStart,\n oldLines,\n newStart,\n newLines,\n lines: hunkLines,\n });\n } else {\n i++;\n }\n }\n \n return hunks;\n}\n\n/**\n * Convert diff hunks to changed line ranges\n * \n * Note: We're additions-first for test generation - we generate tests for new/modified code.\n * Deletions are tracked but primarily used for context. Merged ranges represent \"fuzzy zones\"\n * of change rather than exact line-by-line mappings, which helps with function-level detection.\n */\nfunction hunksToChangedRanges(hunks: DiffHunk[]): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n const ranges: Array<{ start: number; end: number; type: 'addition' | 'deletion' }> = [];\n \n for (const hunk of hunks) {\n let oldLine = hunk.oldStart;\n let newLine = hunk.newStart;\n \n for (const line of hunk.lines) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n // Addition - these are the lines we care about for test generation\n ranges.push({\n start: newLine,\n end: newLine,\n type: 'addition',\n });\n newLine++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n // Deletion - tracked for context, but additions are primary for test targets\n ranges.push({\n start: oldLine,\n end: oldLine,\n type: 'deletion',\n });\n oldLine++;\n } else if (!line.startsWith('\\\\')) {\n // Context line (unchanged)\n oldLine++;\n newLine++;\n }\n }\n }\n \n // Merge adjacent ranges (creates \"fuzzy zones\" of change)\n return mergeRanges(ranges);\n}\n\n/**\n * Merge adjacent or overlapping ranges\n * \n * Creates \"fuzzy zones\" of change - merged ranges represent approximate areas where\n * changes occurred, not exact line-by-line mappings. This helps with function-level\n * detection where we want to catch functions that are near changes.\n */\nfunction mergeRanges(\n ranges: Array<{ start: number; end: number; type: 'addition' | 'deletion' }>\n): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n if (ranges.length === 0) return [];\n \n const sorted = [...ranges].sort((a, b) => a.start - b.start);\n const merged: Array<{ start: number; end: number; type: 'addition' | 'deletion' }> = [];\n \n let current = sorted[0];\n \n for (let i = 1; i < sorted.length; i++) {\n const next = sorted[i];\n \n // If ranges overlap or are adjacent (within 2 lines), merge them\n if (next.start <= current.end + 2 && next.type === current.type) {\n current = {\n start: current.start,\n end: Math.max(current.end, next.end),\n type: current.type,\n };\n } else {\n merged.push(current);\n current = next;\n }\n }\n \n merged.push(current);\n return merged;\n}\n\n/**\n * Parse PR files into structured diff format\n */\nexport function parsePullRequestFiles(files: PullRequestFile[]): FileDiff[] {\n const diffs: FileDiff[] = [];\n \n for (const file of files) {\n // Filter TypeScript and JavaScript files\n if (!file.filename.match(/\\.(ts|tsx|js|jsx)$/)) {\n continue;\n }\n \n if (!file.patch) {\n // File was added or removed without patch\n diffs.push({\n filename: file.filename,\n status: file.status as FileDiff['status'],\n hunks: [],\n additions: file.additions,\n deletions: file.deletions,\n });\n continue;\n }\n \n const hunks = parseUnifiedDiff(file.patch);\n \n diffs.push({\n filename: file.filename,\n status: file.status as FileDiff['status'],\n hunks,\n additions: file.additions,\n deletions: file.deletions,\n });\n \n debug(`Parsed ${hunks.length} hunk(s) for ${file.filename}`);\n }\n \n return diffs;\n}\n\n/**\n * Get changed line ranges for a file diff\n * \n * For added files: Requires fileContent to determine line count. Returns ranges\n * covering the entire file (all lines are additions in new files).\n * \n * For removed files: Returns empty (nothing to test in deleted files).\n * \n * For modified files: Returns merged ranges representing fuzzy zones of change.\n * Note: Deletion ranges use OLD file line numbers and should only be used for\n * metadata/context, not for overlap detection in the new file.\n */\nexport function getChangedRanges(\n diff: FileDiff,\n fileContent?: string\n): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n if (diff.status === 'added') {\n if (!fileContent) {\n throw new Error('fileContent is required for added files to determine line count');\n }\n // For new files, entire file is changed (all lines are additions)\n const lineCount = fileContent.split('\\n').length;\n return [{ start: 1, end: lineCount, type: 'addition' }];\n }\n \n if (diff.status === 'removed') {\n // For removed files, return empty (nothing to test)\n return [];\n }\n \n return hunksToChangedRanges(diff.hunks);\n}\n\n", "import * as ts from 'typescript';\nimport type { ChangedRange, TestTarget } from '../types/diff.js';\nimport { debug } from './logger.js';\n\ninterface FunctionNode {\n name: string;\n type: 'function' | 'method' | 'arrow-function' | 'class-method';\n start: number;\n end: number;\n node: ts.Node;\n}\n\n/**\n * Extract functions/methods from TypeScript source code\n */\nfunction extractFunctions(sourceFile: ts.SourceFile): FunctionNode[] {\n const functions: FunctionNode[] = [];\n \n function visit(node: ts.Node) {\n // Function declarations (including export default)\n if (ts.isFunctionDeclaration(node)) {\n // Check if it's exported (export function foo() {} or export default function foo() {})\n const isExported = node.modifiers?.some(m => \n m.kind === ts.SyntaxKind.ExportKeyword || m.kind === ts.SyntaxKind.DefaultKeyword\n );\n \n if (node.name) {\n functions.push({\n name: node.name.text,\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n } else if (isExported) {\n // Anonymous export default function: export default function () {}\n functions.push({\n name: 'default',\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n }\n \n // Export default with function expressions: export default (function foo() {})\n // Note: FunctionDeclarations with export default are handled above via modifiers\n if (ts.isExportAssignment(node) && node.isExportEquals === false && ts.isFunctionExpression(node.expression)) {\n const func = node.expression;\n const name = func.name ? func.name.text : 'default';\n functions.push({\n name,\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n \n // Method declarations (class methods)\n if (ts.isMethodDeclaration(node) && node.name && ts.isIdentifier(node.name)) {\n functions.push({\n name: node.name.text,\n type: 'class-method',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n \n // Variable statements: const foo = function() {} or const foo = function bar() {}\n if (ts.isVariableStatement(node)) {\n for (const declaration of node.declarationList.declarations) {\n if (declaration.initializer) {\n // Arrow functions\n if (ts.isArrowFunction(declaration.initializer)) {\n if (ts.isIdentifier(declaration.name)) {\n functions.push({\n name: declaration.name.text,\n type: 'arrow-function',\n start: declaration.getStart(sourceFile),\n end: declaration.getEnd(),\n node: declaration,\n });\n }\n }\n // Named function expressions: const foo = function bar() {}\n else if (ts.isFunctionExpression(declaration.initializer)) {\n const funcExpr = declaration.initializer;\n // Use the function name if it has one, otherwise use the variable name\n const name = funcExpr.name\n ? funcExpr.name.text\n : ts.isIdentifier(declaration.name)\n ? declaration.name.text\n : 'anonymous';\n \n if (name !== 'anonymous') {\n functions.push({\n name,\n type: 'function',\n start: declaration.getStart(sourceFile),\n end: declaration.getEnd(),\n node: declaration,\n });\n }\n }\n }\n }\n }\n \n // Object method shorthand\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {\n if (ts.isFunctionExpression(node.initializer) || ts.isArrowFunction(node.initializer)) {\n functions.push({\n name: node.name.text,\n type: 'method',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n }\n \n ts.forEachChild(node, visit);\n }\n \n visit(sourceFile);\n return functions;\n}\n\n/**\n * Get line number from character position\n * \n * Note: For performance, consider caching line start positions if called\n * repeatedly on the same source. TypeScript's SourceFile.getLineAndCharacterOfPosition\n * could be used as an alternative.\n */\nfunction getLineNumber(source: string, position: number): number {\n return source.substring(0, position).split('\\n').length;\n}\n\n/**\n * Check if a function overlaps with changed ranges\n * \n * Note: Only uses 'addition' ranges for overlap detection. Deletion ranges\n * use OLD file line numbers and don't map to the new file, so they're\n * excluded from overlap checks (but kept in metadata).\n */\nfunction functionOverlapsChanges(\n func: FunctionNode,\n changedRanges: ChangedRange[],\n source: string\n): boolean {\n const funcStartLine = getLineNumber(source, func.start);\n const funcEndLine = getLineNumber(source, func.end);\n \n // Only check addition ranges - deletions use old file line numbers\n const additionRanges = changedRanges.filter(r => r.type === 'addition');\n \n for (const range of additionRanges) {\n // Check if changed range overlaps with function\n if (\n (range.start >= funcStartLine && range.start <= funcEndLine) ||\n (range.end >= funcStartLine && range.end <= funcEndLine) ||\n (range.start <= funcStartLine && range.end >= funcEndLine)\n ) {\n return true;\n }\n }\n \n return false;\n}\n\n/**\n * Extract code snippet for a function\n */\nfunction extractCodeSnippet(source: string, func: FunctionNode): string {\n return source.substring(func.start, func.end);\n}\n\n/**\n * Extract minimal context around a function (previous function + next few lines)\n */\nfunction extractContext(source: string, func: FunctionNode, allFunctions: FunctionNode[]): string {\n const funcStartLine = getLineNumber(source, func.start);\n const funcEndLine = getLineNumber(source, func.end);\n \n // Find previous function\n const previousFunc = allFunctions\n .filter(f => getLineNumber(source, f.end) < funcStartLine)\n .sort((a, b) => getLineNumber(source, b.end) - getLineNumber(source, a.end))[0];\n \n const contextStart = previousFunc\n ? getLineNumber(source, previousFunc.start)\n : Math.max(1, funcStartLine - 10);\n \n const lines = source.split('\\n');\n const contextLines = lines.slice(contextStart - 1, funcEndLine + 5);\n \n return contextLines.join('\\n');\n}\n\n/**\n * Detect existing test file for a source file by actually checking the repository\n */\nasync function detectTestFile(\n filePath: string,\n ref: string,\n githubClient: { fileExists: (ref: string, path: string) => Promise<boolean> },\n testDirectory: string\n): Promise<string | undefined> {\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n const baseName = filePath.substring(filePath.lastIndexOf('/') + 1).replace(/\\.(ts|tsx|js|jsx)$/, '');\n \n // Determine file extension and corresponding test patterns\n let ext: 'ts' | 'tsx' | 'js' | 'jsx';\n if (filePath.endsWith('.tsx')) ext = 'tsx';\n else if (filePath.endsWith('.jsx')) ext = 'jsx';\n else if (filePath.endsWith('.ts')) ext = 'ts';\n else ext = 'js';\n \n // Test file patterns to check (match source file type)\n const testPatterns = \n ext === 'tsx' ? [`.test.tsx`, `.spec.tsx`, `.test.ts`, `.spec.ts`] :\n ext === 'jsx' ? [`.test.jsx`, `.spec.jsx`, `.test.js`, `.spec.js`] :\n ext === 'ts' ? [`.test.ts`, `.spec.ts`] :\n [`.test.js`, `.spec.js`];\n \n // Locations to check (in order of preference, deduplicated)\n const locations = [\n // Co-located in same directory\n ...testPatterns.map(pattern => `${dir}/${baseName}${pattern}`),\n // Co-located __tests__ directory\n ...testPatterns.map(pattern => `${dir}/__tests__/${baseName}${pattern}`),\n // Test directory at root\n ...testPatterns.map(pattern => `${testDirectory}/${baseName}${pattern}`),\n // Nested test directory matching source structure\n ...testPatterns.map(pattern => `${testDirectory}${dir}/${baseName}${pattern}`),\n // __tests__ at root\n ...testPatterns.map(pattern => `__tests__/${baseName}${pattern}`),\n ];\n \n // Check each location to see if file actually exists\n for (const testPath of locations) {\n const exists = await githubClient.fileExists(ref, testPath);\n if (exists) {\n return testPath;\n }\n }\n \n return undefined;\n}\n\n/**\n * Analyze TypeScript file and extract test targets\n */\nexport async function analyzeFile(\n filePath: string,\n content: string,\n changedRanges: ChangedRange[],\n ref: string,\n githubClient: { fileExists: (ref: string, path: string) => Promise<boolean> },\n testDirectory: string\n): Promise<TestTarget[]> {\n const sourceFile = ts.createSourceFile(\n filePath,\n content,\n ts.ScriptTarget.Latest,\n true\n );\n \n const functions = extractFunctions(sourceFile);\n \n // Check for existing test file once per file (not per function)\n const existingTestFile = await detectTestFile(filePath, ref, githubClient, testDirectory);\n \n const targets: TestTarget[] = [];\n \n for (const func of functions) {\n if (functionOverlapsChanges(func, changedRanges, content)) {\n const startLine = getLineNumber(content, func.start);\n const endLine = getLineNumber(content, func.end);\n \n targets.push({\n filePath,\n functionName: func.name,\n functionType: func.type,\n startLine,\n endLine,\n code: extractCodeSnippet(content, func),\n context: extractContext(content, func, functions),\n existingTestFile,\n changedRanges: changedRanges.filter(\n r => r.start >= startLine && r.end <= endLine\n ),\n });\n \n debug(`Found test target: ${func.name} (${func.type}) in ${filePath}${existingTestFile ? ` - existing test: ${existingTestFile}` : ''}`);\n }\n }\n \n return targets;\n}\n\n", "import type { PullRequestFile } from '../types/github.js';\nimport type { KakarotConfig } from '../types/config.js';\nimport type { TestTarget } from '../types/diff.js';\nimport { GitHubClient } from '../github/client.js';\nimport { parsePullRequestFiles, getChangedRanges } from './diff-parser.js';\nimport { analyzeFile } from './ast-analyzer.js';\nimport { debug, info } from './logger.js';\n\n/**\n * Extract test targets from pull request files\n */\nexport async function extractTestTargets(\n files: PullRequestFile[],\n githubClient: GitHubClient,\n prHeadRef: string,\n config: Pick<KakarotConfig, 'testDirectory' | 'testFilePattern' | 'includePatterns' | 'excludePatterns'>\n): Promise<TestTarget[]> {\n info(`Analyzing ${files.length} file(s) for test targets`);\n \n // Parse diffs\n const diffs = parsePullRequestFiles(files);\n \n // Filter by include/exclude patterns\n const filteredDiffs = diffs.filter(diff => {\n // Check include patterns\n const matchesInclude = config.includePatterns.some(pattern => {\n const regex = new RegExp(pattern.replace(/\\*\\*/g, '.*').replace(/\\*/g, '[^/]*'));\n return regex.test(diff.filename);\n });\n \n if (!matchesInclude) return false;\n \n // Check exclude patterns\n const matchesExclude = config.excludePatterns.some(pattern => {\n const regex = new RegExp(pattern.replace(/\\*\\*/g, '.*').replace(/\\*/g, '[^/]*'));\n return regex.test(diff.filename);\n });\n \n return !matchesExclude;\n });\n \n debug(`Filtered to ${filteredDiffs.length} file(s) after pattern matching`);\n \n const targets: TestTarget[] = [];\n \n // Process each file\n for (const diff of filteredDiffs) {\n if (diff.status === 'removed') {\n // Skip removed files\n continue;\n }\n \n try {\n // Fetch file contents from PR head (the branch with changes)\n const fileContents = await githubClient.getFileContents(prHeadRef, diff.filename);\n \n // Get changed ranges (pass fileContent for added files)\n const changedRanges = getChangedRanges(diff, fileContents.content);\n \n if (changedRanges.length === 0) {\n // No changes detected, skip\n continue;\n }\n \n // Use the detected changed ranges (getChangedRanges now handles added files)\n const ranges = changedRanges.map(r => ({\n start: r.start,\n end: r.end,\n type: r.type as 'addition' | 'deletion',\n }));\n \n // Analyze AST and extract test targets (use head ref for test file detection)\n const fileTargets = await analyzeFile(\n diff.filename,\n fileContents.content,\n ranges,\n prHeadRef,\n githubClient,\n config.testDirectory\n );\n \n targets.push(...fileTargets);\n \n if (fileTargets.length > 0) {\n info(`Found ${fileTargets.length} test target(s) in ${diff.filename}`);\n }\n } catch (error) {\n debug(`Failed to analyze ${diff.filename}: ${error instanceof Error ? error.message : String(error)}`);\n // Continue with other files\n }\n }\n \n info(`Extracted ${targets.length} total test target(s)`);\n return targets;\n}\n\n", "/**\n * Base LLM provider interface and utilities\n */\n\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions, LLMProvider } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\nexport abstract class BaseLLMProvider implements LLMProvider {\n protected apiKey: string;\n protected model: string;\n protected defaultOptions: Required<LLMGenerateOptions>;\n\n constructor(apiKey: string, model: string, defaultOptions?: Partial<LLMGenerateOptions>) {\n this.apiKey = apiKey;\n this.model = model;\n this.defaultOptions = {\n temperature: defaultOptions?.temperature ?? 0.2,\n maxTokens: defaultOptions?.maxTokens ?? 4000,\n stopSequences: defaultOptions?.stopSequences ?? [],\n };\n }\n\n abstract generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse>;\n\n protected mergeOptions(options?: LLMGenerateOptions): Required<LLMGenerateOptions> {\n return {\n temperature: options?.temperature ?? this.defaultOptions.temperature,\n maxTokens: options?.maxTokens ?? this.defaultOptions.maxTokens,\n stopSequences: options?.stopSequences ?? this.defaultOptions.stopSequences,\n };\n }\n\n protected validateApiKey(): void {\n if (!this.apiKey || this.apiKey.trim().length === 0) {\n error('LLM API key is required but not provided');\n throw new Error('LLM API key is required');\n }\n }\n\n protected logUsage(usage: LLMResponse['usage'], operation: string): void {\n if (usage) {\n debug(\n `${operation} usage: ${usage.totalTokens ?? 'unknown'} tokens ` +\n `(prompt: ${usage.promptTokens ?? 'unknown'}, completion: ${usage.completionTokens ?? 'unknown'})`\n );\n }\n }\n}\n\n", "/**\n * OpenAI provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface OpenAIResponse {\n choices: Array<{\n message: {\n role: string;\n content: string;\n };\n finish_reason: string;\n }>;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nexport class OpenAIProvider extends BaseLLMProvider {\n private baseUrl = 'https://api.openai.com/v1';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n const requestBody = {\n model: this.model,\n messages: messages.map((msg) => ({\n role: msg.role,\n content: msg.content,\n })),\n temperature: mergedOptions.temperature,\n max_tokens: mergedOptions.maxTokens,\n ...(mergedOptions.stopSequences.length > 0 && { stop: mergedOptions.stopSequences }),\n };\n\n debug(`Calling OpenAI API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`OpenAI API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as OpenAIResponse;\n\n if (!data.choices || data.choices.length === 0) {\n error('OpenAI API returned no choices');\n throw new Error('OpenAI API returned no choices');\n }\n\n const content = data.choices[0]?.message?.content ?? '';\n const usage = data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined;\n\n this.logUsage(usage, 'OpenAI');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`OpenAI API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling OpenAI API');\n }\n }\n}\n\n", "/**\n * Anthropic (Claude) provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\ninterface AnthropicRequest {\n model: string;\n max_tokens: number;\n temperature: number;\n messages: AnthropicMessage[];\n system?: string;\n stop_sequences?: string[];\n}\n\ninterface AnthropicResponse {\n content: Array<{\n type: string;\n text: string;\n }>;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n };\n}\n\nexport class AnthropicProvider extends BaseLLMProvider {\n private baseUrl = 'https://api.anthropic.com/v1';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n // Anthropic requires system message to be separate\n const systemMessage = messages.find((m) => m.role === 'system')?.content ?? '';\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n\n const requestBody: AnthropicRequest = {\n model: this.model,\n max_tokens: mergedOptions.maxTokens,\n temperature: mergedOptions.temperature,\n messages: conversationMessages.map((msg) => ({\n role: msg.role === 'assistant' ? 'assistant' : 'user',\n content: msg.content,\n })),\n ...(systemMessage && { system: systemMessage }),\n ...(mergedOptions.stopSequences.length > 0 && { stop_sequences: mergedOptions.stopSequences }),\n };\n\n debug(`Calling Anthropic API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`Anthropic API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`Anthropic API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as AnthropicResponse;\n\n if (!data.content || data.content.length === 0) {\n error('Anthropic API returned no content');\n throw new Error('Anthropic API returned no content');\n }\n\n const content = data.content.map((c) => c.text).join('\\n');\n const usage = data.usage\n ? {\n promptTokens: data.usage.input_tokens,\n completionTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n }\n : undefined;\n\n this.logUsage(usage, 'Anthropic');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`Anthropic API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling Anthropic API');\n }\n }\n}\n\n", "/**\n * Google (Gemini) provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface GoogleContentPart {\n text: string;\n}\n\ninterface GoogleContent {\n role: 'user' | 'model';\n parts: GoogleContentPart[];\n}\n\ninterface GoogleGenerationConfig {\n temperature: number;\n maxOutputTokens: number;\n stopSequences?: string[];\n}\n\ninterface GoogleSystemInstruction {\n parts: GoogleContentPart[];\n}\n\ninterface GoogleRequest {\n contents: GoogleContent[];\n generationConfig: GoogleGenerationConfig;\n systemInstruction?: GoogleSystemInstruction;\n}\n\ninterface GoogleResponse {\n candidates: Array<{\n content: {\n parts: Array<{\n text: string;\n }>;\n };\n finishReason: string;\n }>;\n usageMetadata?: {\n promptTokenCount: number;\n candidatesTokenCount: number;\n totalTokenCount: number;\n };\n}\n\nexport class GoogleProvider extends BaseLLMProvider {\n private baseUrl = 'https://generativelanguage.googleapis.com/v1beta';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n // Google Gemini uses a different message format\n const systemInstruction = messages.find((m) => m.role === 'system')?.content;\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n\n const contents: GoogleContent[] = conversationMessages.map((msg) => ({\n role: (msg.role === 'assistant' ? 'model' : 'user') as 'user' | 'model',\n parts: [{ text: msg.content }],\n }));\n\n const generationConfig: GoogleGenerationConfig = {\n temperature: mergedOptions.temperature,\n maxOutputTokens: mergedOptions.maxTokens,\n ...(mergedOptions.stopSequences.length > 0 && { stopSequences: mergedOptions.stopSequences }),\n };\n\n const requestBody: GoogleRequest = {\n contents,\n generationConfig,\n ...(systemInstruction && { systemInstruction: { parts: [{ text: systemInstruction }] } }),\n };\n\n debug(`Calling Google API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/${this.model}:generateContent?key=${this.apiKey}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`Google API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`Google API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as GoogleResponse;\n\n if (!data.candidates || data.candidates.length === 0) {\n error('Google API returned no candidates');\n throw new Error('Google API returned no candidates');\n }\n\n const content = data.candidates[0]?.content?.parts?.map((p) => p.text).join('\\n') ?? '';\n const usage = data.usageMetadata\n ? {\n promptTokens: data.usageMetadata.promptTokenCount,\n completionTokens: data.usageMetadata.candidatesTokenCount,\n totalTokens: data.usageMetadata.totalTokenCount,\n }\n : undefined;\n\n this.logUsage(usage, 'Google');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`Google API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling Google API');\n }\n }\n}\n\n", "/**\n * LLM provider factory\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { LLMProvider } from '../types/llm.js';\nimport { OpenAIProvider } from './providers/openai.js';\nimport { AnthropicProvider } from './providers/anthropic.js';\nimport { GoogleProvider } from './providers/google.js';\nimport { error } from '../utils/logger.js';\n\n/**\n * Create an LLM provider based on configuration\n */\nexport function createLLMProvider(\n config: Pick<KakarotConfig, 'apiKey' | 'provider' | 'model' | 'maxTokens'>\n): LLMProvider {\n const provider = config.provider ?? 'openai';\n const model = config.model ?? getDefaultModel(provider);\n const defaultOptions = config.maxTokens ? { maxTokens: config.maxTokens } : undefined;\n\n switch (provider) {\n case 'openai':\n return new OpenAIProvider(config.apiKey, model, defaultOptions);\n case 'anthropic':\n return new AnthropicProvider(config.apiKey, model, defaultOptions);\n case 'google':\n return new GoogleProvider(config.apiKey, model, defaultOptions);\n default:\n error(`Unknown LLM provider: ${provider}`);\n throw new Error(`Unknown LLM provider: ${provider}`);\n }\n}\n\n/**\n * Get default model for a provider\n */\nfunction getDefaultModel(provider: 'openai' | 'anthropic' | 'google'): string {\n switch (provider) {\n case 'openai':\n return 'gpt-4-turbo-preview';\n case 'anthropic':\n return 'claude-3-5-sonnet-20241022';\n case 'google':\n return 'gemini-1.5-pro';\n default:\n return 'gpt-4-turbo-preview';\n }\n}\n\n", "/**\n * Test generation prompt builder\n */\n\nimport type { LLMMessage } from '../../types/llm.js';\nimport type { TestGenerationContext } from '../../types/llm.js';\n\nexport function buildTestGenerationPrompt(context: TestGenerationContext): LLMMessage[] {\n const { target, framework, existingTestFile, relatedFunctions } = context;\n\n const systemPrompt = buildSystemPrompt(framework);\n const userPrompt = buildUserPrompt(target, framework, existingTestFile, relatedFunctions);\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\nfunction buildSystemPrompt(framework: 'jest' | 'vitest'): string {\n const frameworkName = framework === 'jest' ? 'Jest' : 'Vitest';\n const importStatement = framework === 'jest' ? \"import { describe, it, expect } from 'jest';\" : \"import { describe, it, expect } from 'vitest';\";\n\n return `You are an expert ${frameworkName} test writer. Your task is to generate comprehensive unit tests for TypeScript/JavaScript functions.\n\nRequirements:\n1. Generate complete, runnable ${frameworkName} test code\n2. Use ${frameworkName} syntax and best practices\n3. Test edge cases, error conditions, and normal operation\n4. Use descriptive test names that explain what is being tested\n5. Include proper setup/teardown if needed\n6. Mock external dependencies appropriately\n7. Test both success and failure scenarios\n8. Follow the existing test file structure if one exists\n\nOutput format:\n- Return ONLY the test code, no explanations or markdown code blocks\n- The code should be ready to run in a ${frameworkName} environment\n- Include necessary imports at the top\n- Use proper TypeScript types if the source code uses TypeScript\n\n${frameworkName} example structure:\n${importStatement}\n\ndescribe('FunctionName', () => {\n it('should handle normal case', () => {\n // test implementation\n });\n\n it('should handle edge case', () => {\n // test implementation\n });\n});`;\n}\n\nfunction buildUserPrompt(\n target: TestGenerationContext['target'],\n framework: 'jest' | 'vitest',\n existingTestFile?: string,\n relatedFunctions?: Array<{ name: string; code: string }>\n): string {\n let prompt = `Generate ${framework} unit tests for the following function:\\n\\n`;\n\n prompt += `File: ${target.filePath}\\n`;\n prompt += `Function: ${target.functionName}\\n`;\n prompt += `Type: ${target.functionType}\\n\\n`;\n\n prompt += `Function code:\\n\\`\\`\\`typescript\\n${target.code}\\n\\`\\`\\`\\n\\n`;\n\n if (target.context) {\n prompt += `Context (surrounding code):\\n\\`\\`\\`typescript\\n${target.context}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (relatedFunctions && relatedFunctions.length > 0) {\n prompt += `Related functions (for context):\\n`;\n relatedFunctions.forEach((fn) => {\n prompt += `\\n${fn.name}:\\n\\`\\`\\`typescript\\n${fn.code}\\n\\`\\`\\`\\n`;\n });\n prompt += '\\n';\n }\n\n if (existingTestFile) {\n prompt += `Existing test file structure (follow this pattern):\\n\\`\\`\\`typescript\\n${existingTestFile}\\n\\`\\`\\`\\n\\n`;\n prompt += `Note: Add new tests to this file, maintaining the existing structure and style.\\n\\n`;\n }\n\n prompt += `Generate comprehensive unit tests for ${target.functionName}. Include:\\n`;\n prompt += `- Tests for normal operation with various inputs\\n`;\n prompt += `- Tests for edge cases (null, undefined, empty arrays, etc.)\\n`;\n prompt += `- Tests for error conditions if applicable\\n`;\n prompt += `- Tests for boundary conditions\\n`;\n prompt += `- Proper mocking of dependencies if needed\\n\\n`;\n\n prompt += `Return ONLY the test code, no explanations or markdown formatting.`;\n\n return prompt;\n}\n\n", "/**\n * Test fix prompt builder for fix loop\n */\n\nimport type { LLMMessage } from '../../types/llm.js';\nimport type { TestFixContext } from '../../types/llm.js';\n\nexport function buildTestFixPrompt(context: TestFixContext): LLMMessage[] {\n const { testCode, errorMessage, testOutput, originalCode, framework, attempt, maxAttempts } = context;\n\n const systemPrompt = buildSystemPrompt(framework, attempt, maxAttempts);\n const userPrompt = buildUserPrompt(testCode, errorMessage, testOutput, originalCode, framework, attempt);\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\nfunction buildSystemPrompt(framework: 'jest' | 'vitest', attempt: number, maxAttempts: number): string {\n const frameworkName = framework === 'jest' ? 'Jest' : 'Vitest';\n\n return `You are an expert ${frameworkName} test debugger. Your task is to fix failing unit tests.\n\nContext:\n- This is fix attempt ${attempt} of ${maxAttempts}\n- The test code failed to run or produced incorrect results\n- You need to analyze the error and fix the test code\n\nRequirements:\n1. Fix the test code to make it pass\n2. Maintain the original test intent\n3. Use proper ${frameworkName} syntax\n4. Ensure all imports and dependencies are correct\n5. Fix any syntax errors, type errors, or logical errors\n6. If the original code being tested has issues, note that but focus on fixing the test\n\nOutput format:\n- Return ONLY the fixed test code, no explanations or markdown code blocks\n- The code should be complete and runnable\n- Include all necessary imports`;\n}\n\nfunction buildUserPrompt(\n testCode: string,\n errorMessage: string,\n testOutput: string | undefined,\n originalCode: string,\n framework: 'jest' | 'vitest',\n attempt: number\n): string {\n let prompt = `The following ${framework} test is failing. Fix it:\\n\\n`;\n\n prompt += `Original function code:\\n\\`\\`\\`typescript\\n${originalCode}\\n\\`\\`\\`\\n\\n`;\n\n prompt += `Failing test code:\\n\\`\\`\\`typescript\\n${testCode}\\n\\`\\`\\`\\n\\n`;\n\n prompt += `Error message:\\n\\`\\`\\`\\n${errorMessage}\\n\\`\\`\\`\\n\\n`;\n\n if (testOutput) {\n prompt += `Test output:\\n\\`\\`\\`\\n${testOutput}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (attempt > 1) {\n prompt += `Note: This is fix attempt ${attempt}. Previous attempts failed. Please analyze the error more carefully.\\n\\n`;\n }\n\n prompt += `Fix the test code to resolve the error. Return ONLY the corrected test code, no explanations.`;\n\n return prompt;\n}\n\n", "/**\n * Parse LLM output to extract test code\n */\n\nimport { warn } from '../utils/logger.js';\n\n/**\n * Extract test code from LLM response\n * Handles markdown code blocks, plain code, and other formats\n */\nexport function parseTestCode(response: string): string {\n // Remove markdown code blocks if present\n let code = response.trim();\n\n // Check for markdown code blocks (```typescript, ```ts, ```javascript, ```js, or just ```)\n const codeBlockRegex = /^```(?:typescript|ts|javascript|js)?\\s*\\n([\\s\\S]*?)\\n```$/;\n const match = code.match(codeBlockRegex);\n\n if (match) {\n code = match[1].trim();\n } else {\n // Check for inline code blocks\n const inlineCodeRegex = /```([\\s\\S]*?)```/g;\n const inlineMatches = Array.from(code.matchAll(inlineCodeRegex));\n if (inlineMatches.length > 0) {\n // Use the largest code block\n code = inlineMatches.reduce((largest, match) => {\n return match[1].length > largest.length ? match[1] : largest;\n }, '');\n code = code.trim();\n }\n }\n\n // Remove any leading/trailing explanation text\n // Look for common patterns like \"Here's the test:\", \"Test code:\", etc.\n const explanationPatterns = [\n /^Here'?s?\\s+(?:the\\s+)?(?:test\\s+)?code:?\\s*/i,\n /^Test\\s+code:?\\s*/i,\n /^Generated\\s+test:?\\s*/i,\n /^Here\\s+is\\s+the\\s+test:?\\s*/i,\n ];\n\n for (const pattern of explanationPatterns) {\n if (pattern.test(code)) {\n code = code.replace(pattern, '').trim();\n // If there's still explanation after the code, try to extract just the code\n const codeBlockMatch = code.match(/```[\\s\\S]*?```/);\n if (codeBlockMatch) {\n code = codeBlockMatch[0];\n code = code.replace(/^```(?:typescript|ts|javascript|js)?\\s*\\n?/, '').replace(/\\n?```$/, '').trim();\n }\n }\n }\n\n // Final cleanup: remove any remaining markdown formatting\n code = code.replace(/^```[\\w]*\\n?/, '').replace(/\\n?```$/, '').trim();\n\n if (!code) {\n warn('Failed to extract test code from LLM response');\n return response; // Return original if we can't parse\n }\n\n return code;\n}\n\n/**\n * Validate that the parsed code looks like valid test code\n */\nexport function validateTestCodeStructure(code: string, framework: 'jest' | 'vitest'): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Check for basic test structure\n if (!code.includes('describe') && !code.includes('it(') && !code.includes('test(')) {\n errors.push('Missing test structure (describe/it/test)');\n }\n\n // Check for framework-specific imports\n if (framework === 'jest') {\n if (!code.includes(\"from 'jest'\") && !code.includes('from \"jest\"') && !code.includes('require(')) {\n // Jest might use global functions, so this is just a warning\n if (!code.includes('describe') && !code.includes('it') && !code.includes('test')) {\n errors.push('Missing Jest test functions');\n }\n }\n } else if (framework === 'vitest') {\n if (!code.includes(\"from 'vitest'\") && !code.includes('from \"vitest\"')) {\n errors.push('Missing Vitest import');\n }\n }\n\n // Check for basic syntax (has some code, not just whitespace)\n if (code.trim().length < 20) {\n errors.push('Test code appears too short or empty');\n }\n\n // Check for common test patterns\n if (!code.match(/(describe|it|test)\\s*\\(/)) {\n errors.push('Missing test function calls (describe/it/test)');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n", "/**\n * Main test generator that orchestrates LLM calls and parsing\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { TestGenerationContext, TestGenerationResult, TestFixContext } from '../types/llm.js';\nimport { createLLMProvider } from './factory.js';\nimport { buildTestGenerationPrompt } from './prompts/test-generation.js';\nimport { buildTestFixPrompt } from './prompts/test-fix.js';\nimport { parseTestCode, validateTestCodeStructure } from './parser.js';\nimport { info, warn, error, debug } from '../utils/logger.js';\n\nexport class TestGenerator {\n private provider: ReturnType<typeof createLLMProvider>;\n private config: Pick<KakarotConfig, 'maxFixAttempts' | 'temperature' | 'fixTemperature'>;\n\n constructor(\n config: Pick<\n KakarotConfig,\n 'apiKey' | 'provider' | 'model' | 'maxTokens' | 'maxFixAttempts' | 'temperature' | 'fixTemperature'\n >\n ) {\n this.provider = createLLMProvider(config);\n this.config = {\n maxFixAttempts: config.maxFixAttempts,\n temperature: config.temperature,\n fixTemperature: config.fixTemperature,\n };\n }\n\n /**\n * Generate test code for a test target\n */\n async generateTest(context: TestGenerationContext): Promise<TestGenerationResult> {\n const { target, framework } = context;\n\n info(`Generating ${framework} tests for ${target.functionName} in ${target.filePath}`);\n\n try {\n const messages = buildTestGenerationPrompt(context);\n debug(`Sending test generation request to LLM for ${target.functionName}`);\n\n const response = await this.provider.generate(messages, {\n temperature: this.config.temperature ?? 0.2, // Lower temperature for more consistent test generation\n maxTokens: 4000,\n });\n\n const testCode = parseTestCode(response.content);\n const validation = validateTestCodeStructure(testCode, framework);\n\n if (!validation.valid) {\n warn(`Test code validation warnings for ${target.functionName}: ${validation.errors.join(', ')}`);\n // Continue anyway, as some issues might be false positives\n }\n\n debug(`Successfully generated test code for ${target.functionName}`);\n\n return {\n testCode,\n explanation: response.content !== testCode ? 'Code extracted from LLM response' : undefined,\n usage: response.usage,\n };\n } catch (err) {\n error(`Failed to generate test for ${target.functionName}: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n\n /**\n * Fix a failing test by generating a corrected version\n */\n async fixTest(context: TestFixContext): Promise<TestGenerationResult> {\n const { framework, attempt } = context;\n\n info(`Fixing test (attempt ${attempt}/${this.config.maxFixAttempts})`);\n\n try {\n const messages = buildTestFixPrompt(context);\n debug(`Sending test fix request to LLM (attempt ${attempt})`);\n\n const response = await this.provider.generate(messages, {\n temperature: this.config.fixTemperature ?? 0.1, // Very low temperature for fix attempts\n maxTokens: 4000,\n });\n\n const fixedCode = parseTestCode(response.content);\n const validation = validateTestCodeStructure(fixedCode, framework);\n\n if (!validation.valid) {\n warn(`Fixed test code validation warnings: ${validation.errors.join(', ')}`);\n }\n\n debug(`Successfully generated fixed test code (attempt ${attempt})`);\n\n return {\n testCode: fixedCode,\n explanation: `Fixed test code (attempt ${attempt})`,\n usage: response.usage,\n };\n } catch (err) {\n error(`Failed to fix test (attempt ${attempt}): ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n\n /**\n * Generate a human-readable coverage summary\n */\n async generateCoverageSummary(messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>): Promise<string> {\n try {\n const response = await this.provider.generate(messages, {\n temperature: 0.3,\n maxTokens: 500,\n });\n return response.content;\n } catch (err) {\n error(`Failed to generate coverage summary: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import type { KakarotConfig } from '../types/config.js';\nimport type { TestTarget } from '../types/diff.js';\n\n/**\n * Determine the test file path for a test target based on configuration\n */\nexport function getTestFilePath(\n target: TestTarget,\n config: Pick<KakarotConfig, 'testLocation' | 'testDirectory' | 'testFilePattern'>\n): string {\n const sourcePath = target.filePath;\n const lastSlashIndex = sourcePath.lastIndexOf('/');\n const dir = lastSlashIndex >= 0 ? sourcePath.substring(0, lastSlashIndex) : '';\n const baseName = sourcePath.substring(lastSlashIndex + 1).replace(/\\.(ts|tsx|js|jsx)$/, '');\n \n // Determine file extension\n let ext: 'ts' | 'tsx' | 'js' | 'jsx';\n if (sourcePath.endsWith('.tsx')) ext = 'tsx';\n else if (sourcePath.endsWith('.jsx')) ext = 'jsx';\n else if (sourcePath.endsWith('.ts')) ext = 'ts';\n else ext = 'js';\n\n // Determine test file extension (prefer matching source type)\n const testExt = ext === 'tsx' || ext === 'ts' ? 'ts' : 'js';\n\n if (config.testLocation === 'co-located') {\n // Co-located: same directory as source file\n return dir ? `${dir}/${baseName}.test.${testExt}` : `${baseName}.test.${testExt}`;\n } else {\n // Separate: in test directory\n // Replace testFilePattern wildcard with actual filename\n const testFileName = config.testFilePattern.replace('*', baseName);\n return `${config.testDirectory}/${testFileName}`;\n }\n}\n\n", "import { existsSync } from 'fs';\nimport { join } from 'path';\n\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm';\n\n/**\n * Detect package manager from project files\n */\nexport function detectPackageManager(projectRoot: string): PackageManager {\n // Check for lock files (most reliable indicator)\n if (existsSync(join(projectRoot, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n \n if (existsSync(join(projectRoot, 'yarn.lock'))) {\n return 'yarn';\n }\n \n if (existsSync(join(projectRoot, 'package-lock.json'))) {\n return 'npm';\n }\n \n // Default to npm if no lock file found\n return 'npm';\n}\n\n", "import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { TestRunner, TestResult, TestRunOptions, TestFailure } from '../../types/test-runner.js';\nimport { debug, error } from '../logger.js';\n\nconst execAsync = promisify(exec);\n\ninterface JestTestResult {\n numPassedTests: number;\n numFailedTests: number;\n numTotalTests: number;\n testResults: Array<{\n name: string;\n status: 'passed' | 'failed';\n assertionResults: Array<{\n title: string;\n status: 'passed' | 'failed';\n failureMessages: string[];\n }>;\n }>;\n}\n\nexport class JestRunner implements TestRunner {\n async runTests(options: TestRunOptions): Promise<TestResult[]> {\n const { testFiles, packageManager, projectRoot, coverage } = options;\n \n debug(`Running Jest tests for ${testFiles.length} file(s)`);\n\n // Build Jest command\n const testFilesArg = testFiles.map(f => `\"${f}\"`).join(' ');\n const coverageFlag = coverage ? '--coverage --coverageReporters=json' : '--no-coverage';\n const cmd = `${packageManager} test -- --json ${coverageFlag} ${testFilesArg}`;\n\n try {\n const { stdout, stderr } = await execAsync(cmd, {\n cwd: projectRoot,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n\n if (stderr && !stderr.includes('PASS') && !stderr.includes('FAIL')) {\n debug(`Jest stderr: ${stderr}`);\n }\n\n const result = JSON.parse(stdout) as JestTestResult;\n\n return testFiles.map((testFile, index) => {\n const testResult = result.testResults[index] || result.testResults[0];\n const failures: TestFailure[] = [];\n\n if (testResult) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n const failureMessage = assertion.failureMessages[0];\n failures.push({\n testName: assertion.title,\n message: failureMessage,\n stack: failureMessage,\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0, // Jest JSON doesn't include duration per file\n failures,\n };\n });\n } catch (err: unknown) {\n // Jest returns non-zero exit code on failures, but stdout still contains JSON\n if (err && typeof err === 'object' && 'stdout' in err) {\n try {\n const result = JSON.parse(err.stdout as string) as JestTestResult;\n return testFiles.map((testFile) => {\n const failures: TestFailure[] = [];\n \n for (const testResult of result.testResults) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n failures.push({\n testName: assertion.title,\n message: assertion.failureMessages[0],\n stack: assertion.failureMessages[0],\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0,\n failures,\n };\n });\n } catch (parseErr) {\n error(`Failed to parse Jest output: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);\n throw err;\n }\n }\n \n error(`Jest test execution failed: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { TestRunner, TestResult, TestRunOptions, TestFailure } from '../../types/test-runner.js';\nimport { debug, error } from '../logger.js';\n\nconst execAsync = promisify(exec);\n\ninterface VitestTestResult {\n numPassedTests: number;\n numFailedTests: number;\n numTotalTests: number;\n testResults: Array<{\n name: string;\n status: 'passed' | 'failed';\n assertionResults: Array<{\n title: string;\n status: 'passed' | 'failed';\n failureMessages: string[];\n }>;\n }>;\n}\n\nexport class VitestRunner implements TestRunner {\n async runTests(options: TestRunOptions): Promise<TestResult[]> {\n const { testFiles, packageManager, projectRoot, coverage } = options;\n \n debug(`Running Vitest tests for ${testFiles.length} file(s)`);\n\n // Build Vitest command\n const testFilesArg = testFiles.map(f => `\"${f}\"`).join(' ');\n const coverageFlag = coverage ? '--coverage' : '';\n const cmd = `${packageManager} test -- --reporter=json ${coverageFlag} ${testFilesArg}`;\n\n try {\n const { stdout, stderr } = await execAsync(cmd, {\n cwd: projectRoot,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n\n if (stderr && !stderr.includes('PASS') && !stderr.includes('FAIL')) {\n debug(`Vitest stderr: ${stderr}`);\n }\n\n // Vitest JSON output is line-delimited, get the last line\n const lines = stdout.trim().split('\\n');\n const jsonLine = lines[lines.length - 1];\n \n if (!jsonLine || !jsonLine.startsWith('{')) {\n throw new Error('No valid JSON output from Vitest');\n }\n\n const result = JSON.parse(jsonLine) as VitestTestResult;\n\n return testFiles.map((testFile, index) => {\n const testResult = result.testResults[index] || result.testResults[0];\n const failures: TestFailure[] = [];\n\n if (testResult) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n const failureMessage = assertion.failureMessages[0];\n failures.push({\n testName: assertion.title,\n message: failureMessage,\n stack: failureMessage,\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0, // Vitest JSON doesn't include duration per file\n failures,\n };\n });\n } catch (err: unknown) {\n // Vitest returns non-zero exit code on failures, but stdout may still contain JSON\n if (err && typeof err === 'object' && 'stdout' in err) {\n try {\n const lines = (err.stdout as string).trim().split('\\n');\n const jsonLine = lines[lines.length - 1];\n \n if (jsonLine && jsonLine.startsWith('{')) {\n const result = JSON.parse(jsonLine) as VitestTestResult;\n return testFiles.map((testFile) => {\n const failures: TestFailure[] = [];\n \n for (const testResult of result.testResults) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n failures.push({\n testName: assertion.title,\n message: assertion.failureMessages[0],\n stack: assertion.failureMessages[0],\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0,\n failures,\n };\n });\n }\n } catch (parseErr) {\n error(`Failed to parse Vitest output: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);\n throw err;\n }\n }\n \n error(`Vitest test execution failed: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import type { TestRunner } from '../../types/test-runner.js';\nimport { JestRunner } from './jest-runner.js';\nimport { VitestRunner } from './vitest-runner.js';\n\n/**\n * Create a test runner for the specified framework\n */\nexport function createTestRunner(framework: 'jest' | 'vitest'): TestRunner {\n switch (framework) {\n case 'jest':\n return new JestRunner();\n case 'vitest':\n return new VitestRunner();\n default:\n throw new Error(`Unsupported test framework: ${framework}`);\n }\n}\n\n", "import { writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { debug } from './logger.js';\n\n/**\n * Write test files to disk in the project directory\n */\nexport function writeTestFiles(\n testFiles: Map<string, { content: string; targets: string[] }>,\n projectRoot: string\n): string[] {\n const writtenPaths: string[] = [];\n\n for (const [relativePath, fileData] of testFiles.entries()) {\n const fullPath = join(projectRoot, relativePath);\n const dir = dirname(fullPath);\n\n // Create directory if it doesn't exist\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n debug(`Created directory: ${dir}`);\n }\n\n // Write test file\n writeFileSync(fullPath, fileData.content, 'utf-8');\n writtenPaths.push(relativePath);\n debug(`Wrote test file: ${relativePath}`);\n }\n\n return writtenPaths;\n}\n\n", "import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport type { CoverageReport, FileCoverage } from '../types/coverage.js';\nimport { debug, warn } from './logger.js';\n\n/**\n * Jest coverage JSON structure\n */\ninterface JestCoverageData {\n [filePath: string]: {\n statements: { [key: string]: number };\n branches: { [key: string]: number };\n functions: { [key: string]: number };\n lines: { [key: string]: number };\n statementMap: Record<string, unknown>;\n fnMap: Record<string, unknown>;\n branchMap: Record<string, unknown>;\n };\n}\n\n/**\n * Vitest coverage JSON structure (similar to Jest)\n */\ninterface VitestCoverageData {\n [filePath: string]: {\n statements: { [key: string]: number };\n branches: { [key: string]: number };\n functions: { [key: string]: number };\n lines: { [key: string]: number };\n };\n}\n\n/**\n * Read and parse Jest coverage report\n */\nfunction parseJestCoverage(data: JestCoverageData): CoverageReport {\n const files: FileCoverage[] = [];\n let totalStatements = 0;\n let coveredStatements = 0;\n let totalBranches = 0;\n let coveredBranches = 0;\n let totalFunctions = 0;\n let coveredFunctions = 0;\n let totalLines = 0;\n let coveredLines = 0;\n\n for (const [filePath, coverage] of Object.entries(data)) {\n // Calculate metrics for this file\n const statementCounts = Object.values(coverage.statements);\n const branchCounts = Object.values(coverage.branches);\n const functionCounts = Object.values(coverage.functions);\n const lineCounts = Object.values(coverage.lines);\n\n const fileStatements = {\n total: statementCounts.length,\n covered: statementCounts.filter(c => c > 0).length,\n percentage: statementCounts.length > 0\n ? (statementCounts.filter(c => c > 0).length / statementCounts.length) * 100\n : 100,\n };\n\n const fileBranches = {\n total: branchCounts.length,\n covered: branchCounts.filter(c => c > 0).length,\n percentage: branchCounts.length > 0\n ? (branchCounts.filter(c => c > 0).length / branchCounts.length) * 100\n : 100,\n };\n\n const fileFunctions = {\n total: functionCounts.length,\n covered: functionCounts.filter(c => c > 0).length,\n percentage: functionCounts.length > 0\n ? (functionCounts.filter(c => c > 0).length / functionCounts.length) * 100\n : 100,\n };\n\n const fileLines = {\n total: lineCounts.length,\n covered: lineCounts.filter(c => c > 0).length,\n percentage: lineCounts.length > 0\n ? (lineCounts.filter(c => c > 0).length / lineCounts.length) * 100\n : 100,\n };\n\n files.push({\n path: filePath,\n metrics: {\n statements: fileStatements,\n branches: fileBranches,\n functions: fileFunctions,\n lines: fileLines,\n },\n });\n\n // Accumulate totals\n totalStatements += fileStatements.total;\n coveredStatements += fileStatements.covered;\n totalBranches += fileBranches.total;\n coveredBranches += fileBranches.covered;\n totalFunctions += fileFunctions.total;\n coveredFunctions += fileFunctions.covered;\n totalLines += fileLines.total;\n coveredLines += fileLines.covered;\n }\n\n return {\n total: {\n statements: {\n total: totalStatements,\n covered: coveredStatements,\n percentage: totalStatements > 0 ? (coveredStatements / totalStatements) * 100 : 100,\n },\n branches: {\n total: totalBranches,\n covered: coveredBranches,\n percentage: totalBranches > 0 ? (coveredBranches / totalBranches) * 100 : 100,\n },\n functions: {\n total: totalFunctions,\n covered: coveredFunctions,\n percentage: totalFunctions > 0 ? (coveredFunctions / totalFunctions) * 100 : 100,\n },\n lines: {\n total: totalLines,\n covered: coveredLines,\n percentage: totalLines > 0 ? (coveredLines / totalLines) * 100 : 100,\n },\n },\n files,\n };\n}\n\n/**\n * Read and parse Vitest coverage report (similar format to Jest)\n */\nfunction parseVitestCoverage(data: VitestCoverageData): CoverageReport {\n // Vitest uses the same structure as Jest\n return parseJestCoverage(data as JestCoverageData);\n}\n\n/**\n * Read coverage report from Jest/Vitest JSON output\n */\nexport function readCoverageReport(\n projectRoot: string,\n framework: 'jest' | 'vitest'\n): CoverageReport | null {\n // Jest and Vitest both output to coverage/coverage-final.json\n const coveragePath = join(projectRoot, 'coverage', 'coverage-final.json');\n\n if (!existsSync(coveragePath)) {\n debug(`Coverage file not found at ${coveragePath}`);\n return null;\n }\n\n try {\n const content = readFileSync(coveragePath, 'utf-8');\n const data = JSON.parse(content);\n\n if (framework === 'jest') {\n return parseJestCoverage(data as JestCoverageData);\n } else {\n return parseVitestCoverage(data as VitestCoverageData);\n }\n } catch (err) {\n warn(`Failed to read coverage report: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n", "import type { LLMMessage } from '../../types/llm.js';\nimport type { CoverageReport, CoverageDelta } from '../../types/coverage.js';\nimport type { TestResult } from '../../types/test-runner.js';\n\n/**\n * Build prompt for generating human-readable coverage summary\n */\nexport function buildCoverageSummaryPrompt(\n coverageReport: CoverageReport,\n testResults: TestResult[],\n functionsTested: string[],\n coverageDelta?: CoverageDelta\n): LLMMessage[] {\n const systemPrompt = `You are a technical writer specializing in test coverage reports. Your task is to generate a clear, concise, and actionable summary of test coverage metrics.\n\nRequirements:\n1. Use clear, professional language\n2. Highlight key metrics (lines, branches, functions, statements)\n3. Mention which functions were tested\n4. If coverage delta is provided, explain the change\n5. Provide actionable insights or recommendations\n6. Format as markdown suitable for GitHub PR comments\n7. Keep it concise (2-3 paragraphs max)`;\n\n const totalTests = testResults.reduce((sum, r) => sum + r.total, 0);\n const passedTests = testResults.reduce((sum, r) => sum + r.passed, 0);\n const failedTests = testResults.reduce((sum, r) => sum + r.failed, 0);\n\n const userPrompt = `Generate a human-readable test coverage summary with the following information:\n\n**Coverage Metrics:**\n- Lines: ${coverageReport.total.lines.percentage.toFixed(1)}% (${coverageReport.total.lines.covered}/${coverageReport.total.lines.total})\n- Branches: ${coverageReport.total.branches.percentage.toFixed(1)}% (${coverageReport.total.branches.covered}/${coverageReport.total.branches.total})\n- Functions: ${coverageReport.total.functions.percentage.toFixed(1)}% (${coverageReport.total.functions.covered}/${coverageReport.total.functions.total})\n- Statements: ${coverageReport.total.statements.percentage.toFixed(1)}% (${coverageReport.total.statements.covered}/${coverageReport.total.statements.total})\n\n**Test Results:**\n- Total tests: ${totalTests}\n- Passed: ${passedTests}\n- Failed: ${failedTests}\n\n**Functions Tested:**\n${functionsTested.length > 0 ? functionsTested.map(f => `- ${f}`).join('\\n') : 'None'}\n\n${coverageDelta ? `**Coverage Changes:**\n- Lines: ${coverageDelta.lines > 0 ? '+' : ''}${coverageDelta.lines.toFixed(1)}%\n- Branches: ${coverageDelta.branches > 0 ? '+' : ''}${coverageDelta.branches.toFixed(1)}%\n- Functions: ${coverageDelta.functions > 0 ? '+' : ''}${coverageDelta.functions.toFixed(1)}%\n- Statements: ${coverageDelta.statements > 0 ? '+' : ''}${coverageDelta.statements.toFixed(1)}%\n` : ''}\n\nGenerate a concise, professional summary that explains what was tested and the coverage achieved.`;\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\n", "/**\n * Main orchestration function for Kakarot CI\n * Processes pull requests and generates tests\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { PullRequest } from '../types/github.js';\nimport { GitHubClient } from '../github/client.js';\nimport { loadConfig } from '../utils/config-loader.js';\nimport { initLogger, info, error, warn, success, progress, debug } from '../utils/logger.js';\nimport { extractTestTargets } from '../utils/test-target-extractor.js';\nimport { TestGenerator } from '../llm/test-generator.js';\nimport { getTestFilePath } from '../utils/test-file-path.js';\nimport { detectPackageManager } from '../utils/package-manager-detector.js';\nimport { createTestRunner } from '../utils/test-runner/factory.js';\nimport { writeTestFiles } from '../utils/test-file-writer.js';\nimport { findProjectRoot } from '../utils/config-loader.js';\nimport { readCoverageReport } from '../utils/coverage-reader.js';\nimport { buildCoverageSummaryPrompt } from '../llm/prompts/coverage-summary.js';\nimport type { TestResult } from '../types/test-runner.js';\nimport type { CoverageReport } from '../types/coverage.js';\n\nexport interface PullRequestContext {\n prNumber: number;\n owner: string;\n repo: string;\n githubToken: string;\n}\n\nexport interface TestGenerationSummary {\n targetsProcessed: number;\n testsGenerated: number;\n testsFailed: number;\n testFiles: Array<{\n path: string;\n targets: string[];\n }>;\n errors: Array<{\n target: string;\n error: string;\n }>;\n coverageReport?: CoverageReport;\n testResults?: TestResult[];\n}\n\n/**\n * Main orchestration function to process a pull request and generate tests\n */\nexport async function runPullRequest(context: PullRequestContext): Promise<TestGenerationSummary> {\n // Load configuration\n const config = await loadConfig();\n \n // Initialize logger\n initLogger(config);\n \n info(`Processing PR #${context.prNumber} for ${context.owner}/${context.repo}`);\n\n // Initialize GitHub client\n const githubToken = context.githubToken || config.githubToken;\n if (!githubToken) {\n throw new Error('GitHub token is required. Provide it via config.githubToken or context.githubToken');\n }\n\n const githubClient = new GitHubClient({\n token: githubToken,\n owner: context.owner,\n repo: context.repo,\n });\n\n // Get PR details\n const pr = await githubClient.getPullRequest(context.prNumber);\n \n if (pr.state !== 'open') {\n warn(`PR #${context.prNumber} is ${pr.state}, skipping test generation`);\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n info(`PR: ${pr.title} (${pr.head.ref} -> ${pr.base.ref})`);\n\n // Get PR files\n const prFiles = await githubClient.listPullRequestFiles(context.prNumber);\n \n if (prFiles.length === 0) {\n info('No files changed in this PR');\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n info(`Found ${prFiles.length} file(s) changed in PR`);\n\n // Extract test targets\n const prHeadRef = pr.head.sha;\n const targets = await extractTestTargets(\n prFiles,\n githubClient,\n prHeadRef,\n config\n );\n\n if (targets.length === 0) {\n info('No test targets found in changed files');\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n // Limit targets based on config\n const limitedTargets = targets.slice(0, config.maxTestsPerPR);\n \n if (targets.length > limitedTargets.length) {\n warn(`Limiting to ${config.maxTestsPerPR} test targets (found ${targets.length})`);\n }\n\n info(`Found ${limitedTargets.length} test target(s)`);\n\n // Use configured test framework\n const framework = config.framework;\n info(`Using test framework: ${framework}`);\n\n // Initialize test generator\n const testGenerator = new TestGenerator({\n apiKey: config.apiKey,\n provider: config.provider,\n model: config.model,\n maxTokens: config.maxTokens,\n maxFixAttempts: config.maxFixAttempts,\n temperature: config.temperature,\n fixTemperature: config.fixTemperature,\n });\n\n // Generate tests for each target\n let testFiles = new Map<string, { content: string; targets: string[] }>();\n const errors: Array<{ target: string; error: string }> = [];\n let testsGenerated = 0;\n let testsFailed = 0;\n\n for (let i = 0; i < limitedTargets.length; i++) {\n const target = limitedTargets[i];\n progress(i + 1, limitedTargets.length, `Generating test for ${target.functionName}`);\n\n try {\n // Determine where the test file should be based on config\n const testFilePath = getTestFilePath(target, config);\n \n // Check if a test file exists at the config-determined path\n let existingTestFile: string | undefined;\n const testFileExists = await githubClient.fileExists(prHeadRef, testFilePath);\n \n if (testFileExists) {\n try {\n const fileContents = await githubClient.getFileContents(prHeadRef, testFilePath);\n existingTestFile = fileContents.content;\n debug(`Found existing test file at ${testFilePath}`);\n } catch (err) {\n debug(`Could not fetch existing test file ${testFilePath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n } else {\n debug(`No existing test file at ${testFilePath}, will create new file`);\n }\n\n // Generate test\n const result = await testGenerator.generateTest({\n target: {\n filePath: target.filePath,\n functionName: target.functionName,\n functionType: target.functionType,\n code: target.code,\n context: target.context,\n },\n framework,\n existingTestFile,\n });\n\n // Group tests by file path\n if (!testFiles.has(testFilePath)) {\n // Use existing test file content as base if it exists at this path\n const baseContent = existingTestFile || '';\n testFiles.set(testFilePath, { content: baseContent, targets: [] });\n }\n\n const fileData = testFiles.get(testFilePath)!;\n \n // Append test content (with separator if base content exists)\n if (fileData.content) {\n fileData.content += '\\n\\n' + result.testCode;\n } else {\n fileData.content = result.testCode;\n }\n \n fileData.targets.push(target.functionName);\n testsGenerated++;\n\n info(`\u2713 Generated test for ${target.functionName}`);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n error(`\u2717 Failed to generate test for ${target.functionName}: ${errorMessage}`);\n errors.push({\n target: `${target.filePath}:${target.functionName}`,\n error: errorMessage,\n });\n testsFailed++;\n }\n }\n\n // Write tests to disk and run them\n const projectRoot = await findProjectRoot();\n const packageManager = detectPackageManager(projectRoot);\n info(`Detected package manager: ${packageManager}`);\n\n if (testFiles.size > 0) {\n // Write test files to disk\n const writtenPaths = writeTestFiles(testFiles, projectRoot);\n info(`Wrote ${writtenPaths.length} test file(s) to disk`);\n\n // Run tests and fix failures\n const testRunner = createTestRunner(framework);\n const finalTestFiles = await runTestsAndFix(\n testRunner,\n testFiles,\n writtenPaths,\n framework,\n packageManager,\n projectRoot,\n testGenerator,\n config.maxFixAttempts\n );\n\n // Update testFiles with fixed versions\n testFiles = finalTestFiles;\n }\n\n // Initialize summary\n const summary: TestGenerationSummary = {\n targetsProcessed: limitedTargets.length,\n testsGenerated,\n testsFailed,\n testFiles: Array.from(testFiles.entries()).map(([path, data]) => ({\n path,\n targets: data.targets,\n })),\n errors,\n };\n\n // Run tests with coverage for final report (if tests were generated)\n if (testFiles.size > 0) {\n const testRunner = createTestRunner(framework);\n const writtenPaths = Array.from(testFiles.keys());\n \n info('Running tests with coverage...');\n const finalTestResults = await testRunner.runTests({\n testFiles: writtenPaths,\n framework,\n packageManager,\n projectRoot,\n coverage: true,\n });\n\n // Read coverage report\n const coverageReport = readCoverageReport(projectRoot, framework);\n if (coverageReport) {\n info(`Coverage collected: ${coverageReport.total.lines.percentage.toFixed(1)}% lines`);\n summary.coverageReport = coverageReport;\n summary.testResults = finalTestResults;\n } else {\n warn('Could not read coverage report');\n }\n }\n\n // Commit tests if enabled\n if (config.enableAutoCommit && testFiles.size > 0) {\n await commitTests(\n githubClient,\n pr,\n Array.from(testFiles.entries()).map(([path, data]) => ({\n path,\n content: data.content,\n })),\n config,\n summary\n );\n }\n\n // Post PR comment if enabled\n if (config.enablePRComments) {\n await postPRComment(githubClient, context.prNumber, summary, framework, testGenerator);\n }\n\n success(`Completed: ${testsGenerated} test(s) generated, ${testsFailed} failed`);\n\n return summary;\n}\n\n/**\n * Run tests and fix failures in a loop\n */\nasync function runTestsAndFix(\n testRunner: ReturnType<typeof createTestRunner>,\n testFiles: Map<string, { content: string; targets: string[] }>,\n testFilePaths: string[],\n framework: 'jest' | 'vitest',\n packageManager: 'npm' | 'yarn' | 'pnpm',\n projectRoot: string,\n testGenerator: TestGenerator,\n maxFixAttempts: number\n): Promise<Map<string, { content: string; targets: string[] }>> {\n const currentTestFiles = new Map(testFiles);\n let attempt = 0;\n\n while (attempt < maxFixAttempts) {\n info(`Running tests (attempt ${attempt + 1}/${maxFixAttempts})`);\n\n // Run tests\n const results = await testRunner.runTests({\n testFiles: testFilePaths,\n framework,\n packageManager,\n projectRoot,\n coverage: false,\n });\n\n // Check if all tests passed\n const allPassed = results.every(r => r.success);\n if (allPassed) {\n success(`All tests passed on attempt ${attempt + 1}`);\n return currentTestFiles;\n }\n\n // Find failing tests\n const failures: Array<{ testFile: string; result: TestResult }> = [];\n for (const result of results) {\n if (!result.success && result.failures.length > 0) {\n failures.push({ testFile: result.testFile, result });\n }\n }\n\n info(`Found ${failures.length} failing test file(s), attempting fixes...`);\n\n // Fix each failing test file\n let fixedAny = false;\n for (const { testFile, result } of failures) {\n const testFileContent = currentTestFiles.get(testFile)?.content;\n if (!testFileContent) {\n warn(`Could not find content for test file: ${testFile}`);\n continue;\n }\n\n // Get the original source code for context (we need to find which target this test file corresponds to)\n // For now, we'll use the first failure's context\n const firstFailure = result.failures[0];\n if (!firstFailure) continue;\n\n try {\n // Build fix context - we need the original function code\n // This is a simplified version - in practice, we'd need to map test files back to targets\n const fixedResult = await testGenerator.fixTest({\n testCode: testFileContent,\n errorMessage: firstFailure.message,\n testOutput: firstFailure.stack,\n originalCode: '', // We'd need to pass this from the target\n framework,\n attempt: attempt + 1,\n maxAttempts: maxFixAttempts,\n });\n\n // Update the test file content\n currentTestFiles.set(testFile, {\n content: fixedResult.testCode,\n targets: currentTestFiles.get(testFile)?.targets || [],\n });\n\n // Write updated file to disk\n const { writeFileSync } = await import('fs');\n const { join } = await import('path');\n writeFileSync(join(projectRoot, testFile), fixedResult.testCode, 'utf-8');\n\n fixedAny = true;\n info(`\u2713 Fixed test file: ${testFile}`);\n } catch (err) {\n error(`Failed to fix test file ${testFile}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (!fixedAny) {\n warn(`Could not fix any failing tests on attempt ${attempt + 1}`);\n break;\n }\n\n attempt++;\n }\n\n if (attempt >= maxFixAttempts) {\n warn(`Reached maximum fix attempts (${maxFixAttempts}), some tests may still be failing`);\n }\n\n return currentTestFiles;\n}\n\n/**\n * Commit generated tests to the repository\n */\nasync function commitTests(\n githubClient: GitHubClient,\n pr: PullRequest,\n testFiles: Array<{ path: string; content: string }>,\n config: KakarotConfig,\n summary: TestGenerationSummary\n): Promise<void> {\n info(`Committing ${testFiles.length} test file(s)`);\n\n try {\n if (config.commitStrategy === 'branch-pr') {\n // Create a new branch and PR\n const branchName = `kakarot-ci/tests-pr-${pr.number}`;\n const baseSha = await githubClient.createBranch(branchName, pr.head.ref);\n\n // Commit to the new branch\n await githubClient.commitFiles({\n files: testFiles.map(file => ({\n path: file.path,\n content: file.content,\n })),\n message: `test: add unit tests for PR #${pr.number}\\n\\nGenerated ${summary.testsGenerated} test(s) for ${summary.targetsProcessed} function(s)`,\n branch: branchName,\n baseSha,\n });\n\n // Create PR\n const testPR = await githubClient.createPullRequest(\n `test: Add unit tests for PR #${pr.number}`,\n `This PR contains automatically generated unit tests for PR #${pr.number}.\\n\\n` +\n `- ${summary.testsGenerated} test(s) generated\\n` +\n `- ${summary.targetsProcessed} function(s) tested\\n` +\n `- ${testFiles.length} test file(s) created/updated`,\n branchName,\n pr.head.ref\n );\n\n success(`Created PR #${testPR.number} with generated tests`);\n } else {\n // Direct commit to PR branch\n await githubClient.commitFiles({\n files: testFiles.map(file => ({\n path: file.path,\n content: file.content,\n })),\n message: `test: add unit tests\\n\\nGenerated ${summary.testsGenerated} test(s) for ${summary.targetsProcessed} function(s)`,\n branch: pr.head.ref,\n baseSha: pr.head.sha,\n });\n\n success(`Committed ${testFiles.length} test file(s) to ${pr.head.ref}`);\n }\n } catch (err) {\n error(`Failed to commit tests: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n}\n\n/**\n * Post a summary comment on the PR\n */\nasync function postPRComment(\n githubClient: GitHubClient,\n prNumber: number,\n summary: TestGenerationSummary,\n framework: 'jest' | 'vitest',\n testGenerator: TestGenerator\n): Promise<void> {\n let comment = `## \uD83E\uDDEA Kakarot CI Test Generation Summary\n\n**Framework:** ${framework}\n**Targets Processed:** ${summary.targetsProcessed}\n**Tests Generated:** ${summary.testsGenerated}\n**Failures:** ${summary.testsFailed}\n\n### Test Files\n${summary.testFiles.length > 0 \n ? summary.testFiles.map(f => `- \\`${f.path}\\` (${f.targets.length} test(s))`).join('\\n')\n : 'No test files generated'\n}\n\n${summary.errors.length > 0 \n ? `### Errors\\n${summary.errors.map(e => `- \\`${e.target}\\`: ${e.error}`).join('\\n')}`\n : ''\n}`;\n\n // Add coverage summary if available\n if (summary.coverageReport && summary.testResults) {\n try {\n // Collect all function names that were tested\n const functionsTested = summary.testFiles.flatMap(f => f.targets);\n \n // Generate human-readable coverage summary via LLM\n const messages = buildCoverageSummaryPrompt(\n summary.coverageReport,\n summary.testResults,\n functionsTested\n );\n\n const coverageSummary = await testGenerator.generateCoverageSummary(messages);\n comment += `\\n\\n## \uD83D\uDCCA Coverage Summary\\n\\n${coverageSummary}`;\n } catch (err) {\n warn(`Failed to generate coverage summary: ${err instanceof Error ? err.message : String(err)}`);\n \n // Fallback to basic coverage metrics\n const cov = summary.coverageReport.total;\n comment += `\\n\\n## \uD83D\uDCCA Coverage Summary\\n\\n` +\n `- **Lines:** ${cov.lines.percentage.toFixed(1)}% (${cov.lines.covered}/${cov.lines.total})\\n` +\n `- **Branches:** ${cov.branches.percentage.toFixed(1)}% (${cov.branches.covered}/${cov.branches.total})\\n` +\n `- **Functions:** ${cov.functions.percentage.toFixed(1)}% (${cov.functions.covered}/${cov.functions.total})\\n` +\n `- **Statements:** ${cov.statements.percentage.toFixed(1)}% (${cov.statements.covered}/${cov.statements.total})`;\n }\n }\n\n comment += `\\n\\n---\\n*Generated by [Kakarot CI](https://github.com/kakarot-ci)*`;\n\n try {\n await githubClient.commentPR(prNumber, comment);\n info('Posted PR comment with test generation summary');\n } catch (err) {\n warn(`Failed to post PR comment: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { readFileSync } from 'fs';\nimport { simpleGit } from 'simple-git';\nimport gitUrlParse from 'git-url-parse';\nimport { Command } from 'commander';\nimport { runPullRequest, type PullRequestContext } from '../core/orchestrator.js';\nimport { error, info, debug } from '../utils/logger.js';\nimport { loadConfig } from '../utils/config-loader.js';\nimport { findProjectRoot } from '../utils/config-loader.js';\n\ninterface GitHubEvent {\n pull_request?: {\n number: number;\n };\n number?: number;\n}\n\n/**\n * Parse GitHub repository string (format: \"owner/repo\")\n */\nfunction parseRepository(repo: string): { owner: string; repo: string } {\n const parts = repo.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid repository format: ${repo}. Expected \"owner/repo\"`);\n }\n return { owner: parts[0], repo: parts[1] };\n}\n\n/**\n * Detect repository from current git working directory\n */\nasync function detectGitRepository(projectRoot: string): Promise<{ owner: string; repo: string } | null> {\n try {\n const git = simpleGit(projectRoot);\n \n // Get the remote URL (prefer origin, fallback to first remote)\n let remoteUrl: string | null = null;\n \n try {\n remoteUrl = await git.getRemotes(true).then(remotes => {\n const origin = remotes.find(r => r.name === 'origin');\n return origin?.refs?.fetch || origin?.refs?.push || null;\n });\n \n if (!remoteUrl) {\n const remotes = await git.getRemotes(true);\n if (remotes.length > 0) {\n remoteUrl = remotes[0].refs?.fetch || remotes[0].refs?.push || null;\n }\n }\n } catch {\n return null;\n }\n \n if (!remoteUrl) {\n return null;\n }\n \n // Parse GitHub URL\n try {\n const parsed = gitUrlParse(remoteUrl);\n if (parsed.resource === 'github.com') {\n return {\n owner: parsed.owner,\n repo: parsed.name.replace(/\\.git$/, ''),\n };\n }\n } catch {\n // Not a GitHub URL or parse failed\n return null;\n }\n \n return null;\n } catch (err) {\n debug(`Failed to detect git repository: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n/**\n * Extract PR number from GitHub event JSON\n */\nfunction extractPRNumber(eventPath?: string): number | null {\n if (!eventPath) {\n return null;\n }\n\n try {\n const eventContent = readFileSync(eventPath, 'utf-8');\n const event: GitHubEvent = JSON.parse(eventContent);\n\n if (event.pull_request?.number) {\n return event.pull_request.number;\n }\n\n if (event.number) {\n return event.number;\n }\n\n return null;\n } catch (err) {\n error(`Failed to read GitHub event file: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n/**\n * Main CLI function\n */\nasync function main(): Promise<void> {\n const program = new Command();\n\n program\n .name('kakarot-ci')\n .description('AI-powered unit test generation for pull requests')\n .version('0.2.0')\n .option('--pr <number>', 'Pull request number')\n .option('--owner <string>', 'Repository owner')\n .option('--repo <string>', 'Repository name')\n .option('--token <string>', 'GitHub token (or use GITHUB_TOKEN env var)')\n .parse(process.argv);\n\n const options = program.opts();\n\n // Load config first to get defaults\n let config;\n try {\n config = await loadConfig();\n } catch (err) {\n // Config loading might fail if apiKey is missing, but we can continue\n config = null;\n }\n\n // Parse environment variables (with CLI args as highest priority, then config, then env)\n const githubRepository = process.env.GITHUB_REPOSITORY;\n const githubEventPath = process.env.GITHUB_EVENT_PATH;\n const githubToken = options.token || config?.githubToken || process.env.GITHUB_TOKEN;\n const prNumberEnv = process.env.PR_NUMBER;\n\n // Extract owner/repo from various sources (priority: CLI > env > config > git)\n let owner: string | undefined = options.owner;\n let repo: string | undefined = options.repo;\n\n // Try parsing from GITHUB_REPOSITORY if not provided via CLI\n if (!owner || !repo) {\n if (githubRepository) {\n try {\n const parsed = parseRepository(githubRepository);\n owner = owner || parsed.owner;\n repo = repo || parsed.repo;\n } catch (err) {\n if (!owner && !repo) {\n error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n }\n }\n }\n\n // Fallback to config defaults\n if (!owner || !repo) {\n owner = owner || config?.githubOwner;\n repo = repo || config?.githubRepo;\n }\n\n // Fallback to git repository detection\n if (!owner || !repo) {\n const projectRoot = await findProjectRoot();\n const gitRepo = await detectGitRepository(projectRoot);\n if (gitRepo) {\n owner = owner || gitRepo.owner;\n repo = repo || gitRepo.repo;\n debug(`Detected repository from git: ${owner}/${repo}`);\n }\n }\n\n // Validate required values\n if (!owner || !repo) {\n error('Repository owner and name are required.');\n error('Provide via:');\n error(' - Config file: githubOwner and githubRepo');\n error(' - CLI flags: --owner and --repo');\n error(' - Environment: GITHUB_REPOSITORY (format: \"owner/repo\")');\n error(' - Git remote: auto-detected from current repository');\n process.exit(1);\n }\n\n if (!githubToken) {\n error('GitHub token is required.');\n error('Provide via:');\n error(' - Config file: githubToken');\n error(' - CLI flag: --token');\n error(' - Environment: GITHUB_TOKEN');\n process.exit(1);\n }\n\n // Extract PR number from various sources\n let prNumber: number | null = null;\n\n // Priority: CLI arg > env var > GitHub event file\n if (options.pr) {\n prNumber = parseInt(String(options.pr), 10);\n if (isNaN(prNumber)) {\n error(`Invalid PR number: ${options.pr}`);\n process.exit(1);\n }\n } else if (prNumberEnv) {\n const parsed = parseInt(prNumberEnv, 10);\n if (!isNaN(parsed)) {\n prNumber = parsed;\n }\n } else if (githubEventPath) {\n prNumber = extractPRNumber(githubEventPath);\n }\n\n if (!prNumber) {\n error('Pull request number is required.');\n error('Provide via:');\n error(' - CLI flag: --pr <number>');\n error(' - Environment: PR_NUMBER');\n error(' - GitHub Actions: GITHUB_EVENT_PATH (auto-detected)');\n process.exit(1);\n }\n\n // Build context\n const context: PullRequestContext = {\n prNumber,\n owner,\n repo,\n githubToken,\n };\n\n info(`Starting Kakarot CI for PR #${prNumber} in ${owner}/${repo}`);\n\n try {\n const summary = await runPullRequest(context);\n\n // Exit with error code if there were failures\n if (summary.errors.length > 0 || summary.testsFailed > 0) {\n error(`Test generation completed with errors: ${summary.errors.length} error(s), ${summary.testsFailed} test(s) failed`);\n process.exit(1);\n }\n\n info(`Test generation completed successfully: ${summary.testsGenerated} test(s) generated`);\n process.exit(0);\n } catch (err) {\n error(`Fatal error: ${err instanceof Error ? err.message : String(err)}`);\n if (err instanceof Error && err.stack) {\n error(err.stack);\n }\n process.exit(1);\n }\n}\n\n// Run CLI\nmain().catch((err) => {\n error(`Unhandled error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n", "import { Octokit } from '@octokit/rest';\nimport type { PullRequest, PullRequestFile, FileContents, GitHubClientOptions, BatchCommitOptions } from '../types/github.js';\nimport { debug, error, warn } from '../utils/logger.js';\n\n/**\n * GitHub API client wrapper with retry and rate-limit handling\n */\nexport class GitHubClient {\n private octokit: Octokit;\n private owner: string;\n private repo: string;\n private maxRetries = 3;\n private retryDelay = 1000; // 1 second\n\n constructor(options: GitHubClientOptions) {\n this.owner = options.owner;\n this.repo = options.repo;\n this.octokit = new Octokit({\n auth: options.token,\n request: {\n retries: this.maxRetries,\n retryAfter: this.retryDelay / 1000,\n },\n });\n }\n\n /**\n * Retry wrapper with exponential backoff\n */\n private async withRetry<T>(\n fn: () => Promise<T>,\n operation: string,\n retries = this.maxRetries\n ): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n if (retries <= 0) {\n error(`${operation} failed after ${this.maxRetries} retries: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n\n const isRateLimit = err instanceof Error && err.message.includes('rate limit');\n const isServerError = err instanceof Error && (\n err.message.includes('500') ||\n err.message.includes('502') ||\n err.message.includes('503') ||\n err.message.includes('504')\n );\n\n if (isRateLimit || isServerError) {\n const delay = this.retryDelay * Math.pow(2, this.maxRetries - retries);\n warn(`${operation} failed, retrying in ${delay}ms... (${retries} retries left)`);\n await new Promise(resolve => setTimeout(resolve, delay));\n return this.withRetry(fn, operation, retries - 1);\n }\n\n throw err;\n }\n }\n\n /**\n * Get pull request details\n */\n async getPullRequest(prNumber: number): Promise<PullRequest> {\n return this.withRetry(async () => {\n debug(`Fetching PR #${prNumber}`);\n const response = await this.octokit.rest.pulls.get({\n owner: this.owner,\n repo: this.repo,\n pull_number: prNumber,\n });\n return response.data as PullRequest;\n }, `getPullRequest(${prNumber})`);\n }\n\n /**\n * List all files changed in a pull request with patches\n */\n async listPullRequestFiles(prNumber: number): Promise<PullRequestFile[]> {\n return this.withRetry(async () => {\n debug(`Fetching files for PR #${prNumber}`);\n const response = await this.octokit.rest.pulls.listFiles({\n owner: this.owner,\n repo: this.repo,\n pull_number: prNumber,\n });\n return response.data.map(file => ({\n filename: file.filename,\n status: file.status as PullRequestFile['status'],\n additions: file.additions,\n deletions: file.deletions,\n changes: file.changes,\n patch: file.patch || undefined,\n previous_filename: file.previous_filename || undefined,\n }));\n }, `listPullRequestFiles(${prNumber})`);\n }\n\n /**\n * Get file contents from a specific ref (branch, commit, etc.)\n */\n async getFileContents(ref: string, path: string): Promise<FileContents> {\n return this.withRetry(async () => {\n debug(`Fetching file contents: ${path}@${ref}`);\n const response = await this.octokit.rest.repos.getContent({\n owner: this.owner,\n repo: this.repo,\n path,\n ref,\n });\n\n if (Array.isArray(response.data)) {\n throw new Error(`Expected file but got directory: ${path}`);\n }\n\n const data = response.data as { content: string; encoding: string; sha: string; size: number };\n \n // Decode base64 content\n let content: string;\n if (data.encoding === 'base64') {\n content = Buffer.from(data.content, 'base64').toString('utf-8');\n } else {\n content = data.content;\n }\n\n return {\n content,\n encoding: data.encoding as 'base64' | 'utf-8',\n sha: data.sha,\n size: data.size,\n };\n }, `getFileContents(${ref}, ${path})`);\n }\n\n /**\n * Commit multiple files in a single commit using Git tree API\n */\n async commitFiles(options: BatchCommitOptions): Promise<string> {\n return this.withRetry(async () => {\n debug(`Committing ${options.files.length} file(s) to branch ${options.branch}`);\n\n // Get the base tree SHA\n const baseCommit = await this.octokit.rest.repos.getCommit({\n owner: this.owner,\n repo: this.repo,\n ref: options.baseSha,\n });\n const baseTreeSha = baseCommit.data.commit.tree.sha;\n\n // Create blobs for all files\n const blobPromises = options.files.map(async (file) => {\n const blobResponse = await this.octokit.rest.git.createBlob({\n owner: this.owner,\n repo: this.repo,\n content: Buffer.from(file.content, 'utf-8').toString('base64'),\n encoding: 'base64',\n });\n return {\n path: file.path,\n sha: blobResponse.data.sha,\n mode: '100644' as const,\n type: 'blob' as const,\n };\n });\n\n const treeItems = await Promise.all(blobPromises);\n\n // Create a new tree with the blobs\n const treeResponse = await this.octokit.rest.git.createTree({\n owner: this.owner,\n repo: this.repo,\n base_tree: baseTreeSha,\n tree: treeItems,\n });\n\n // Create the commit\n const commitResponse = await this.octokit.rest.git.createCommit({\n owner: this.owner,\n repo: this.repo,\n message: options.message,\n tree: treeResponse.data.sha,\n parents: [options.baseSha],\n });\n\n // Update the branch reference\n await this.octokit.rest.git.updateRef({\n owner: this.owner,\n repo: this.repo,\n ref: `heads/${options.branch}`,\n sha: commitResponse.data.sha,\n });\n\n return commitResponse.data.sha;\n }, `commitFiles(${options.files.length} files)`);\n }\n\n /**\n * Create a new branch from a base ref\n */\n async createBranch(branchName: string, baseRef: string): Promise<string> {\n return this.withRetry(async () => {\n debug(`Creating branch ${branchName} from ${baseRef}`);\n\n // Get the SHA of the base ref\n const baseRefResponse = await this.octokit.rest.git.getRef({\n owner: this.owner,\n repo: this.repo,\n ref: baseRef.startsWith('refs/') ? baseRef : `heads/${baseRef}`,\n });\n const baseSha = baseRefResponse.data.object.sha;\n\n // Create the new branch\n await this.octokit.rest.git.createRef({\n owner: this.owner,\n repo: this.repo,\n ref: `refs/heads/${branchName}`,\n sha: baseSha,\n });\n\n return baseSha;\n }, `createBranch(${branchName})`);\n }\n\n /**\n * Create a pull request\n */\n async createPullRequest(\n title: string,\n body: string,\n head: string,\n base: string\n ): Promise<PullRequest> {\n return this.withRetry(async () => {\n debug(`Creating PR: ${head} -> ${base}`);\n\n const response = await this.octokit.rest.pulls.create({\n owner: this.owner,\n repo: this.repo,\n title,\n body,\n head,\n base,\n });\n\n return response.data as PullRequest;\n }, `createPullRequest(${head} -> ${base})`);\n }\n\n /**\n * Post a comment on a pull request\n */\n async commentPR(prNumber: number, body: string): Promise<void> {\n await this.withRetry(async () => {\n debug(`Posting comment on PR #${prNumber}`);\n await this.octokit.rest.issues.createComment({\n owner: this.owner,\n repo: this.repo,\n issue_number: prNumber,\n body,\n });\n }, `commentPR(${prNumber})`);\n }\n\n /**\n * Check if a file exists in the repository\n */\n async fileExists(ref: string, path: string): Promise<boolean> {\n return this.withRetry(async () => {\n try {\n await this.octokit.rest.repos.getContent({\n owner: this.owner,\n repo: this.repo,\n path,\n ref,\n });\n return true;\n } catch (err) {\n if (err instanceof Error && err.message.includes('404')) {\n return false;\n }\n throw err;\n }\n }, `fileExists(${ref}, ${path})`);\n }\n\n /**\n * Get the current rate limit status\n */\n async getRateLimit(): Promise<{ remaining: number; reset: number }> {\n const response = await this.octokit.rest.rateLimit.get();\n return {\n remaining: response.data.rate.remaining,\n reset: response.data.rate.reset,\n };\n }\n}\n\n", "import type { KakarotConfig } from '../types/config.js';\n\nlet debugMode = false;\nlet jsonMode = false;\n\nexport function initLogger(config: Pick<KakarotConfig, 'debug'>): void {\n debugMode = config.debug ?? process.env.KAKAROT_DEBUG === 'true';\n jsonMode = process.env.KAKAROT_OUTPUT === 'json';\n}\n\n\nexport function info(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'info', message, ...args }));\n } else {\n console.log(`[kakarot-ci] ${message}`, ...args);\n }\n}\n\nexport function debug(message: string, ...args: unknown[]): void {\n if (debugMode) {\n if (jsonMode) {\n console.debug(JSON.stringify({ level: 'debug', message, ...args }));\n } else {\n console.debug(`[kakarot-ci:debug] ${message}`, ...args);\n }\n }\n}\n\nexport function warn(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.warn(JSON.stringify({ level: 'warn', message, ...args }));\n } else {\n console.warn(`[kakarot-ci] \u26A0 ${message}`, ...args);\n }\n}\n\nexport function error(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.error(JSON.stringify({ level: 'error', message, ...args }));\n } else {\n console.error(`[kakarot-ci] \u2717 ${message}`, ...args);\n }\n}\n\nexport function success(message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'success', message, ...args }));\n } else {\n console.log(`[kakarot-ci] \u2713 ${message}`, ...args);\n }\n}\n\nexport function progress(step: number, total: number, message: string, ...args: unknown[]): void {\n if (jsonMode) {\n console.log(JSON.stringify({ level: 'info', step, total, message, ...args }));\n } else {\n console.log(`[kakarot-ci] Step ${step}/${total}: ${message}`, ...args);\n }\n}\n", "import { cosmiconfig } from 'cosmiconfig';\nimport { findUp } from 'find-up';\nimport { KakarotConfigSchema, type KakarotConfig, type PartialKakarotConfig } from '../types/config.js';\nimport { error } from './logger.js';\n\n/**\n * Find the project root by locating package.json\n */\nexport async function findProjectRoot(startPath?: string): Promise<string> {\n const packageJsonPath = await findUp('package.json', {\n cwd: startPath ?? process.cwd(),\n });\n \n if (packageJsonPath) {\n const { dirname } = await import('path');\n return dirname(packageJsonPath);\n }\n \n return startPath ?? process.cwd();\n}\n\n/**\n * Load and validate Kakarot configuration\n */\nexport async function loadConfig(): Promise<KakarotConfig> {\n const explorer = cosmiconfig('kakarot', {\n searchPlaces: [\n 'kakarot.config.ts',\n 'kakarot.config.js',\n '.kakarot-ci.config.ts',\n '.kakarot-ci.config.js',\n '.kakarot-ci.config.json',\n 'package.json',\n ],\n loaders: {\n '.ts': async (filepath: string) => {\n // Dynamic import for TypeScript config file\n // Note: This requires the file to be transpiled or use tsx/ts-node in runtime\n try {\n const configModule = await import(filepath);\n return configModule.default || configModule.config || null;\n } catch (err) {\n error(`Failed to load TypeScript config: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n },\n },\n });\n\n try {\n const result = await explorer.search();\n \n let config: PartialKakarotConfig = {};\n \n if (result?.config) {\n config = result.config as PartialKakarotConfig;\n }\n \n // Also check package.json for kakarotCi field\n if (!result || result.filepath?.endsWith('package.json')) {\n const packageJsonPath = await findUp('package.json');\n if (packageJsonPath) {\n const { readFileSync } = await import('fs');\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { kakarotCi?: PartialKakarotConfig };\n if (pkg.kakarotCi) {\n config = { ...config, ...pkg.kakarotCi };\n }\n } catch {\n // Ignore package.json parse errors\n }\n }\n }\n \n // Merge environment variables\n if (!config.apiKey && process.env.KAKAROT_API_KEY) {\n config.apiKey = process.env.KAKAROT_API_KEY;\n }\n \n if (!config.githubToken && process.env.GITHUB_TOKEN) {\n config.githubToken = process.env.GITHUB_TOKEN;\n }\n \n return KakarotConfigSchema.parse(config);\n } catch (err) {\n if (err instanceof Error && err.message.includes('apiKey')) {\n error(\n 'Missing required apiKey. Provide it via:\\n' +\n ' - Config file (kakarot.config.ts, .kakarot-ci.config.js/json, or package.json)\\n' +\n ' - Environment variable: KAKAROT_API_KEY'\n );\n }\n throw err;\n }\n}\n", "import { z } from 'zod';\n\nexport const KakarotConfigSchema = z.object({\n apiKey: z.string(),\n githubToken: z.string().optional(),\n githubOwner: z.string().optional(),\n githubRepo: z.string().optional(),\n provider: z.enum(['openai', 'anthropic', 'google']).optional(),\n model: z.string().optional(),\n maxTokens: z.number().int().min(1).max(100000).optional(),\n temperature: z.number().min(0).max(2).optional(),\n fixTemperature: z.number().min(0).max(2).optional(),\n maxFixAttempts: z.number().int().min(0).max(5).default(3),\n framework: z.enum(['jest', 'vitest']),\n testLocation: z.enum(['separate', 'co-located']).default('separate'),\n testDirectory: z.string().default('__tests__'),\n testFilePattern: z.string().default('*.test.ts'),\n includePatterns: z.array(z.string()).default(['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']),\n excludePatterns: z.array(z.string()).default(['**/*.test.ts', '**/*.spec.ts', '**/*.test.js', '**/*.spec.js', '**/node_modules/**']),\n maxTestsPerPR: z.number().int().min(1).default(50),\n enableAutoCommit: z.boolean().default(true),\n commitStrategy: z.enum(['direct', 'branch-pr']).default('direct'),\n enablePRComments: z.boolean().default(true),\n debug: z.boolean().default(false),\n});\n\nexport type KakarotConfig = z.infer<typeof KakarotConfigSchema>;\n\nexport type PartialKakarotConfig = Partial<KakarotConfig>;\n\n", "import type { PullRequestFile } from '../types/github.js';\nimport type { FileDiff, DiffHunk } from '../types/diff.js';\nimport { debug } from './logger.js';\n\n/**\n * Parse unified diff format from GitHub patch\n */\nfunction parseUnifiedDiff(patch: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const lines = patch.split('\\n');\n \n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n \n // Match hunk header: @@ -oldStart,oldLines +newStart,newLines @@\n const hunkMatch = line.match(/^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/);\n if (hunkMatch) {\n const oldStart = parseInt(hunkMatch[1], 10);\n const oldLines = parseInt(hunkMatch[2] || '1', 10);\n const newStart = parseInt(hunkMatch[3], 10);\n const newLines = parseInt(hunkMatch[4] || '1', 10);\n \n const hunkLines: string[] = [];\n i++;\n \n // Collect lines until next hunk or end\n while (i < lines.length && !lines[i].startsWith('@@')) {\n hunkLines.push(lines[i]);\n i++;\n }\n \n hunks.push({\n oldStart,\n oldLines,\n newStart,\n newLines,\n lines: hunkLines,\n });\n } else {\n i++;\n }\n }\n \n return hunks;\n}\n\n/**\n * Convert diff hunks to changed line ranges\n * \n * Note: We're additions-first for test generation - we generate tests for new/modified code.\n * Deletions are tracked but primarily used for context. Merged ranges represent \"fuzzy zones\"\n * of change rather than exact line-by-line mappings, which helps with function-level detection.\n */\nfunction hunksToChangedRanges(hunks: DiffHunk[]): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n const ranges: Array<{ start: number; end: number; type: 'addition' | 'deletion' }> = [];\n \n for (const hunk of hunks) {\n let oldLine = hunk.oldStart;\n let newLine = hunk.newStart;\n \n for (const line of hunk.lines) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n // Addition - these are the lines we care about for test generation\n ranges.push({\n start: newLine,\n end: newLine,\n type: 'addition',\n });\n newLine++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n // Deletion - tracked for context, but additions are primary for test targets\n ranges.push({\n start: oldLine,\n end: oldLine,\n type: 'deletion',\n });\n oldLine++;\n } else if (!line.startsWith('\\\\')) {\n // Context line (unchanged)\n oldLine++;\n newLine++;\n }\n }\n }\n \n // Merge adjacent ranges (creates \"fuzzy zones\" of change)\n return mergeRanges(ranges);\n}\n\n/**\n * Merge adjacent or overlapping ranges\n * \n * Creates \"fuzzy zones\" of change - merged ranges represent approximate areas where\n * changes occurred, not exact line-by-line mappings. This helps with function-level\n * detection where we want to catch functions that are near changes.\n */\nfunction mergeRanges(\n ranges: Array<{ start: number; end: number; type: 'addition' | 'deletion' }>\n): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n if (ranges.length === 0) return [];\n \n const sorted = [...ranges].sort((a, b) => a.start - b.start);\n const merged: Array<{ start: number; end: number; type: 'addition' | 'deletion' }> = [];\n \n let current = sorted[0];\n \n for (let i = 1; i < sorted.length; i++) {\n const next = sorted[i];\n \n // If ranges overlap or are adjacent (within 2 lines), merge them\n if (next.start <= current.end + 2 && next.type === current.type) {\n current = {\n start: current.start,\n end: Math.max(current.end, next.end),\n type: current.type,\n };\n } else {\n merged.push(current);\n current = next;\n }\n }\n \n merged.push(current);\n return merged;\n}\n\n/**\n * Parse PR files into structured diff format\n */\nexport function parsePullRequestFiles(files: PullRequestFile[]): FileDiff[] {\n const diffs: FileDiff[] = [];\n \n for (const file of files) {\n // Filter TypeScript and JavaScript files\n if (!file.filename.match(/\\.(ts|tsx|js|jsx)$/)) {\n continue;\n }\n \n if (!file.patch) {\n // File was added or removed without patch\n diffs.push({\n filename: file.filename,\n status: file.status as FileDiff['status'],\n hunks: [],\n additions: file.additions,\n deletions: file.deletions,\n });\n continue;\n }\n \n const hunks = parseUnifiedDiff(file.patch);\n \n diffs.push({\n filename: file.filename,\n status: file.status as FileDiff['status'],\n hunks,\n additions: file.additions,\n deletions: file.deletions,\n });\n \n debug(`Parsed ${hunks.length} hunk(s) for ${file.filename}`);\n }\n \n return diffs;\n}\n\n/**\n * Get changed line ranges for a file diff\n * \n * For added files: Requires fileContent to determine line count. Returns ranges\n * covering the entire file (all lines are additions in new files).\n * \n * For removed files: Returns empty (nothing to test in deleted files).\n * \n * For modified files: Returns merged ranges representing fuzzy zones of change.\n * Note: Deletion ranges use OLD file line numbers and should only be used for\n * metadata/context, not for overlap detection in the new file.\n */\nexport function getChangedRanges(\n diff: FileDiff,\n fileContent?: string\n): Array<{ start: number; end: number; type: 'addition' | 'deletion' }> {\n if (diff.status === 'added') {\n if (!fileContent) {\n throw new Error('fileContent is required for added files to determine line count');\n }\n // For new files, entire file is changed (all lines are additions)\n const lineCount = fileContent.split('\\n').length;\n return [{ start: 1, end: lineCount, type: 'addition' }];\n }\n \n if (diff.status === 'removed') {\n // For removed files, return empty (nothing to test)\n return [];\n }\n \n return hunksToChangedRanges(diff.hunks);\n}\n\n", "import * as ts from 'typescript';\nimport type { ChangedRange, TestTarget } from '../types/diff.js';\nimport { debug } from './logger.js';\n\ninterface FunctionNode {\n name: string;\n type: 'function' | 'method' | 'arrow-function' | 'class-method';\n start: number;\n end: number;\n node: ts.Node;\n}\n\n/**\n * Extract functions/methods from TypeScript source code\n */\nfunction extractFunctions(sourceFile: ts.SourceFile): FunctionNode[] {\n const functions: FunctionNode[] = [];\n \n function visit(node: ts.Node) {\n // Function declarations (including export default)\n if (ts.isFunctionDeclaration(node)) {\n // Check if it's exported (export function foo() {} or export default function foo() {})\n const isExported = node.modifiers?.some(m => \n m.kind === ts.SyntaxKind.ExportKeyword || m.kind === ts.SyntaxKind.DefaultKeyword\n );\n \n if (node.name) {\n functions.push({\n name: node.name.text,\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n } else if (isExported) {\n // Anonymous export default function: export default function () {}\n functions.push({\n name: 'default',\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n }\n \n // Export default with function expressions: export default (function foo() {})\n // Note: FunctionDeclarations with export default are handled above via modifiers\n if (ts.isExportAssignment(node) && node.isExportEquals === false && ts.isFunctionExpression(node.expression)) {\n const func = node.expression;\n const name = func.name ? func.name.text : 'default';\n functions.push({\n name,\n type: 'function',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n \n // Method declarations (class methods)\n if (ts.isMethodDeclaration(node) && node.name && ts.isIdentifier(node.name)) {\n functions.push({\n name: node.name.text,\n type: 'class-method',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n \n // Variable statements: const foo = function() {} or const foo = function bar() {}\n if (ts.isVariableStatement(node)) {\n for (const declaration of node.declarationList.declarations) {\n if (declaration.initializer) {\n // Arrow functions\n if (ts.isArrowFunction(declaration.initializer)) {\n if (ts.isIdentifier(declaration.name)) {\n functions.push({\n name: declaration.name.text,\n type: 'arrow-function',\n start: declaration.getStart(sourceFile),\n end: declaration.getEnd(),\n node: declaration,\n });\n }\n }\n // Named function expressions: const foo = function bar() {}\n else if (ts.isFunctionExpression(declaration.initializer)) {\n const funcExpr = declaration.initializer;\n // Use the function name if it has one, otherwise use the variable name\n const name = funcExpr.name\n ? funcExpr.name.text\n : ts.isIdentifier(declaration.name)\n ? declaration.name.text\n : 'anonymous';\n \n if (name !== 'anonymous') {\n functions.push({\n name,\n type: 'function',\n start: declaration.getStart(sourceFile),\n end: declaration.getEnd(),\n node: declaration,\n });\n }\n }\n }\n }\n }\n \n // Object method shorthand\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {\n if (ts.isFunctionExpression(node.initializer) || ts.isArrowFunction(node.initializer)) {\n functions.push({\n name: node.name.text,\n type: 'method',\n start: node.getStart(sourceFile),\n end: node.getEnd(),\n node,\n });\n }\n }\n \n ts.forEachChild(node, visit);\n }\n \n visit(sourceFile);\n return functions;\n}\n\n/**\n * Get line number from character position\n * \n * Note: For performance, consider caching line start positions if called\n * repeatedly on the same source. TypeScript's SourceFile.getLineAndCharacterOfPosition\n * could be used as an alternative.\n */\nfunction getLineNumber(source: string, position: number): number {\n return source.substring(0, position).split('\\n').length;\n}\n\n/**\n * Check if a function overlaps with changed ranges\n * \n * Note: Only uses 'addition' ranges for overlap detection. Deletion ranges\n * use OLD file line numbers and don't map to the new file, so they're\n * excluded from overlap checks (but kept in metadata).\n */\nfunction functionOverlapsChanges(\n func: FunctionNode,\n changedRanges: ChangedRange[],\n source: string\n): boolean {\n const funcStartLine = getLineNumber(source, func.start);\n const funcEndLine = getLineNumber(source, func.end);\n \n // Only check addition ranges - deletions use old file line numbers\n const additionRanges = changedRanges.filter(r => r.type === 'addition');\n \n for (const range of additionRanges) {\n // Check if changed range overlaps with function\n if (\n (range.start >= funcStartLine && range.start <= funcEndLine) ||\n (range.end >= funcStartLine && range.end <= funcEndLine) ||\n (range.start <= funcStartLine && range.end >= funcEndLine)\n ) {\n return true;\n }\n }\n \n return false;\n}\n\n/**\n * Extract code snippet for a function\n */\nfunction extractCodeSnippet(source: string, func: FunctionNode): string {\n return source.substring(func.start, func.end);\n}\n\n/**\n * Extract minimal context around a function (previous function + next few lines)\n */\nfunction extractContext(source: string, func: FunctionNode, allFunctions: FunctionNode[]): string {\n const funcStartLine = getLineNumber(source, func.start);\n const funcEndLine = getLineNumber(source, func.end);\n \n // Find previous function\n const previousFunc = allFunctions\n .filter(f => getLineNumber(source, f.end) < funcStartLine)\n .sort((a, b) => getLineNumber(source, b.end) - getLineNumber(source, a.end))[0];\n \n const contextStart = previousFunc\n ? getLineNumber(source, previousFunc.start)\n : Math.max(1, funcStartLine - 10);\n \n const lines = source.split('\\n');\n const contextLines = lines.slice(contextStart - 1, funcEndLine + 5);\n \n return contextLines.join('\\n');\n}\n\n/**\n * Detect existing test file for a source file by actually checking the repository\n */\nasync function detectTestFile(\n filePath: string,\n ref: string,\n githubClient: { fileExists: (ref: string, path: string) => Promise<boolean> },\n testDirectory: string\n): Promise<string | undefined> {\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n const baseName = filePath.substring(filePath.lastIndexOf('/') + 1).replace(/\\.(ts|tsx|js|jsx)$/, '');\n \n // Determine file extension and corresponding test patterns\n let ext: 'ts' | 'tsx' | 'js' | 'jsx';\n if (filePath.endsWith('.tsx')) ext = 'tsx';\n else if (filePath.endsWith('.jsx')) ext = 'jsx';\n else if (filePath.endsWith('.ts')) ext = 'ts';\n else ext = 'js';\n \n // Test file patterns to check (match source file type)\n const testPatterns = \n ext === 'tsx' ? [`.test.tsx`, `.spec.tsx`, `.test.ts`, `.spec.ts`] :\n ext === 'jsx' ? [`.test.jsx`, `.spec.jsx`, `.test.js`, `.spec.js`] :\n ext === 'ts' ? [`.test.ts`, `.spec.ts`] :\n [`.test.js`, `.spec.js`];\n \n // Locations to check (in order of preference, deduplicated)\n const locations = [\n // Co-located in same directory\n ...testPatterns.map(pattern => `${dir}/${baseName}${pattern}`),\n // Co-located __tests__ directory\n ...testPatterns.map(pattern => `${dir}/__tests__/${baseName}${pattern}`),\n // Test directory at root\n ...testPatterns.map(pattern => `${testDirectory}/${baseName}${pattern}`),\n // Nested test directory matching source structure\n ...testPatterns.map(pattern => `${testDirectory}${dir}/${baseName}${pattern}`),\n // __tests__ at root\n ...testPatterns.map(pattern => `__tests__/${baseName}${pattern}`),\n ];\n \n // Check each location to see if file actually exists\n for (const testPath of locations) {\n const exists = await githubClient.fileExists(ref, testPath);\n if (exists) {\n return testPath;\n }\n }\n \n return undefined;\n}\n\n/**\n * Analyze TypeScript file and extract test targets\n */\nexport async function analyzeFile(\n filePath: string,\n content: string,\n changedRanges: ChangedRange[],\n ref: string,\n githubClient: { fileExists: (ref: string, path: string) => Promise<boolean> },\n testDirectory: string\n): Promise<TestTarget[]> {\n const sourceFile = ts.createSourceFile(\n filePath,\n content,\n ts.ScriptTarget.Latest,\n true\n );\n \n const functions = extractFunctions(sourceFile);\n \n // Check for existing test file once per file (not per function)\n const existingTestFile = await detectTestFile(filePath, ref, githubClient, testDirectory);\n \n const targets: TestTarget[] = [];\n \n for (const func of functions) {\n if (functionOverlapsChanges(func, changedRanges, content)) {\n const startLine = getLineNumber(content, func.start);\n const endLine = getLineNumber(content, func.end);\n \n targets.push({\n filePath,\n functionName: func.name,\n functionType: func.type,\n startLine,\n endLine,\n code: extractCodeSnippet(content, func),\n context: extractContext(content, func, functions),\n existingTestFile,\n changedRanges: changedRanges.filter(\n r => r.start >= startLine && r.end <= endLine\n ),\n });\n \n debug(`Found test target: ${func.name} (${func.type}) in ${filePath}${existingTestFile ? ` - existing test: ${existingTestFile}` : ''}`);\n }\n }\n \n return targets;\n}\n\n", "import type { PullRequestFile } from '../types/github.js';\nimport type { KakarotConfig } from '../types/config.js';\nimport type { TestTarget } from '../types/diff.js';\nimport { GitHubClient } from '../github/client.js';\nimport { parsePullRequestFiles, getChangedRanges } from './diff-parser.js';\nimport { analyzeFile } from './ast-analyzer.js';\nimport { debug, info } from './logger.js';\n\n/**\n * Extract test targets from pull request files\n */\nexport async function extractTestTargets(\n files: PullRequestFile[],\n githubClient: GitHubClient,\n prHeadRef: string,\n config: Pick<KakarotConfig, 'testDirectory' | 'testFilePattern' | 'includePatterns' | 'excludePatterns'>\n): Promise<TestTarget[]> {\n info(`Analyzing ${files.length} file(s) for test targets`);\n \n // Parse diffs\n const diffs = parsePullRequestFiles(files);\n \n // Filter by include/exclude patterns\n const filteredDiffs = diffs.filter(diff => {\n // Check include patterns\n const matchesInclude = config.includePatterns.some(pattern => {\n const regex = new RegExp(pattern.replace(/\\*\\*/g, '.*').replace(/\\*/g, '[^/]*'));\n return regex.test(diff.filename);\n });\n \n if (!matchesInclude) return false;\n \n // Check exclude patterns\n const matchesExclude = config.excludePatterns.some(pattern => {\n const regex = new RegExp(pattern.replace(/\\*\\*/g, '.*').replace(/\\*/g, '[^/]*'));\n return regex.test(diff.filename);\n });\n \n return !matchesExclude;\n });\n \n debug(`Filtered to ${filteredDiffs.length} file(s) after pattern matching`);\n \n const targets: TestTarget[] = [];\n \n // Process each file\n for (const diff of filteredDiffs) {\n if (diff.status === 'removed') {\n // Skip removed files\n continue;\n }\n \n try {\n // Fetch file contents from PR head (the branch with changes)\n const fileContents = await githubClient.getFileContents(prHeadRef, diff.filename);\n \n // Get changed ranges (pass fileContent for added files)\n const changedRanges = getChangedRanges(diff, fileContents.content);\n \n if (changedRanges.length === 0) {\n // No changes detected, skip\n continue;\n }\n \n // Use the detected changed ranges (getChangedRanges now handles added files)\n const ranges = changedRanges.map(r => ({\n start: r.start,\n end: r.end,\n type: r.type as 'addition' | 'deletion',\n }));\n \n // Analyze AST and extract test targets (use head ref for test file detection)\n const fileTargets = await analyzeFile(\n diff.filename,\n fileContents.content,\n ranges,\n prHeadRef,\n githubClient,\n config.testDirectory\n );\n \n targets.push(...fileTargets);\n \n if (fileTargets.length > 0) {\n info(`Found ${fileTargets.length} test target(s) in ${diff.filename}`);\n }\n } catch (error) {\n debug(`Failed to analyze ${diff.filename}: ${error instanceof Error ? error.message : String(error)}`);\n // Continue with other files\n }\n }\n \n info(`Extracted ${targets.length} total test target(s)`);\n return targets;\n}\n\n", "/**\n * Base LLM provider interface and utilities\n */\n\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions, LLMProvider } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\nexport abstract class BaseLLMProvider implements LLMProvider {\n protected apiKey: string;\n protected model: string;\n protected defaultOptions: Required<LLMGenerateOptions>;\n\n constructor(apiKey: string, model: string, defaultOptions?: Partial<LLMGenerateOptions>) {\n this.apiKey = apiKey;\n this.model = model;\n this.defaultOptions = {\n temperature: defaultOptions?.temperature ?? 0.2,\n maxTokens: defaultOptions?.maxTokens ?? 4000,\n stopSequences: defaultOptions?.stopSequences ?? [],\n };\n }\n\n abstract generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse>;\n\n protected mergeOptions(options?: LLMGenerateOptions): Required<LLMGenerateOptions> {\n return {\n temperature: options?.temperature ?? this.defaultOptions.temperature,\n maxTokens: options?.maxTokens ?? this.defaultOptions.maxTokens,\n stopSequences: options?.stopSequences ?? this.defaultOptions.stopSequences,\n };\n }\n\n protected validateApiKey(): void {\n if (!this.apiKey || this.apiKey.trim().length === 0) {\n error('LLM API key is required but not provided');\n throw new Error('LLM API key is required');\n }\n }\n\n protected logUsage(usage: LLMResponse['usage'], operation: string): void {\n if (usage) {\n debug(\n `${operation} usage: ${usage.totalTokens ?? 'unknown'} tokens ` +\n `(prompt: ${usage.promptTokens ?? 'unknown'}, completion: ${usage.completionTokens ?? 'unknown'})`\n );\n }\n }\n}\n\n", "/**\n * OpenAI provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface OpenAIResponse {\n choices: Array<{\n message: {\n role: string;\n content: string;\n };\n finish_reason: string;\n }>;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nexport class OpenAIProvider extends BaseLLMProvider {\n private baseUrl = 'https://api.openai.com/v1';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n const requestBody = {\n model: this.model,\n messages: messages.map((msg) => ({\n role: msg.role,\n content: msg.content,\n })),\n temperature: mergedOptions.temperature,\n max_tokens: mergedOptions.maxTokens,\n ...(mergedOptions.stopSequences.length > 0 && { stop: mergedOptions.stopSequences }),\n };\n\n debug(`Calling OpenAI API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`OpenAI API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as OpenAIResponse;\n\n if (!data.choices || data.choices.length === 0) {\n error('OpenAI API returned no choices');\n throw new Error('OpenAI API returned no choices');\n }\n\n const content = data.choices[0]?.message?.content ?? '';\n const usage = data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined;\n\n this.logUsage(usage, 'OpenAI');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`OpenAI API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling OpenAI API');\n }\n }\n}\n\n", "/**\n * Anthropic (Claude) provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\ninterface AnthropicRequest {\n model: string;\n max_tokens: number;\n temperature: number;\n messages: AnthropicMessage[];\n system?: string;\n stop_sequences?: string[];\n}\n\ninterface AnthropicResponse {\n content: Array<{\n type: string;\n text: string;\n }>;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n };\n}\n\nexport class AnthropicProvider extends BaseLLMProvider {\n private baseUrl = 'https://api.anthropic.com/v1';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n // Anthropic requires system message to be separate\n const systemMessage = messages.find((m) => m.role === 'system')?.content ?? '';\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n\n const requestBody: AnthropicRequest = {\n model: this.model,\n max_tokens: mergedOptions.maxTokens,\n temperature: mergedOptions.temperature,\n messages: conversationMessages.map((msg) => ({\n role: msg.role === 'assistant' ? 'assistant' : 'user',\n content: msg.content,\n })),\n ...(systemMessage && { system: systemMessage }),\n ...(mergedOptions.stopSequences.length > 0 && { stop_sequences: mergedOptions.stopSequences }),\n };\n\n debug(`Calling Anthropic API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`Anthropic API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`Anthropic API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as AnthropicResponse;\n\n if (!data.content || data.content.length === 0) {\n error('Anthropic API returned no content');\n throw new Error('Anthropic API returned no content');\n }\n\n const content = data.content.map((c) => c.text).join('\\n');\n const usage = data.usage\n ? {\n promptTokens: data.usage.input_tokens,\n completionTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n }\n : undefined;\n\n this.logUsage(usage, 'Anthropic');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`Anthropic API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling Anthropic API');\n }\n }\n}\n\n", "/**\n * Google (Gemini) provider implementation\n */\n\nimport { BaseLLMProvider } from './base.js';\nimport type { LLMMessage, LLMResponse, LLMGenerateOptions } from '../../types/llm.js';\nimport { error, debug } from '../../utils/logger.js';\n\ninterface GoogleContentPart {\n text: string;\n}\n\ninterface GoogleContent {\n role: 'user' | 'model';\n parts: GoogleContentPart[];\n}\n\ninterface GoogleGenerationConfig {\n temperature: number;\n maxOutputTokens: number;\n stopSequences?: string[];\n}\n\ninterface GoogleSystemInstruction {\n parts: GoogleContentPart[];\n}\n\ninterface GoogleRequest {\n contents: GoogleContent[];\n generationConfig: GoogleGenerationConfig;\n systemInstruction?: GoogleSystemInstruction;\n}\n\ninterface GoogleResponse {\n candidates: Array<{\n content: {\n parts: Array<{\n text: string;\n }>;\n };\n finishReason: string;\n }>;\n usageMetadata?: {\n promptTokenCount: number;\n candidatesTokenCount: number;\n totalTokenCount: number;\n };\n}\n\nexport class GoogleProvider extends BaseLLMProvider {\n private baseUrl = 'https://generativelanguage.googleapis.com/v1beta';\n\n async generate(messages: LLMMessage[], options?: LLMGenerateOptions): Promise<LLMResponse> {\n this.validateApiKey();\n const mergedOptions = this.mergeOptions(options);\n\n // Google Gemini uses a different message format\n const systemInstruction = messages.find((m) => m.role === 'system')?.content;\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n\n const contents: GoogleContent[] = conversationMessages.map((msg) => ({\n role: (msg.role === 'assistant' ? 'model' : 'user') as 'user' | 'model',\n parts: [{ text: msg.content }],\n }));\n\n const generationConfig: GoogleGenerationConfig = {\n temperature: mergedOptions.temperature,\n maxOutputTokens: mergedOptions.maxTokens,\n ...(mergedOptions.stopSequences.length > 0 && { stopSequences: mergedOptions.stopSequences }),\n };\n\n const requestBody: GoogleRequest = {\n contents,\n generationConfig,\n ...(systemInstruction && { systemInstruction: { parts: [{ text: systemInstruction }] } }),\n };\n\n debug(`Calling Google API with model: ${this.model}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/${this.model}:generateContent?key=${this.apiKey}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n error(`Google API error: ${response.status} ${response.statusText} - ${errorText}`);\n throw new Error(`Google API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as GoogleResponse;\n\n if (!data.candidates || data.candidates.length === 0) {\n error('Google API returned no candidates');\n throw new Error('Google API returned no candidates');\n }\n\n const content = data.candidates[0]?.content?.parts?.map((p) => p.text).join('\\n') ?? '';\n const usage = data.usageMetadata\n ? {\n promptTokens: data.usageMetadata.promptTokenCount,\n completionTokens: data.usageMetadata.candidatesTokenCount,\n totalTokens: data.usageMetadata.totalTokenCount,\n }\n : undefined;\n\n this.logUsage(usage, 'Google');\n\n return {\n content,\n usage,\n };\n } catch (err) {\n if (err instanceof Error) {\n error(`Google API request failed: ${err.message}`);\n throw err;\n }\n throw new Error('Unknown error calling Google API');\n }\n }\n}\n\n", "/**\n * LLM provider factory\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { LLMProvider } from '../types/llm.js';\nimport { OpenAIProvider } from './providers/openai.js';\nimport { AnthropicProvider } from './providers/anthropic.js';\nimport { GoogleProvider } from './providers/google.js';\nimport { error } from '../utils/logger.js';\n\n/**\n * Create an LLM provider based on configuration\n */\nexport function createLLMProvider(\n config: Pick<KakarotConfig, 'apiKey' | 'provider' | 'model' | 'maxTokens'>\n): LLMProvider {\n const provider = config.provider ?? 'openai';\n const model = config.model ?? getDefaultModel(provider);\n const defaultOptions = config.maxTokens ? { maxTokens: config.maxTokens } : undefined;\n\n switch (provider) {\n case 'openai':\n return new OpenAIProvider(config.apiKey, model, defaultOptions);\n case 'anthropic':\n return new AnthropicProvider(config.apiKey, model, defaultOptions);\n case 'google':\n return new GoogleProvider(config.apiKey, model, defaultOptions);\n default:\n error(`Unknown LLM provider: ${provider}`);\n throw new Error(`Unknown LLM provider: ${provider}`);\n }\n}\n\n/**\n * Get default model for a provider\n */\nfunction getDefaultModel(provider: 'openai' | 'anthropic' | 'google'): string {\n switch (provider) {\n case 'openai':\n return 'gpt-4-turbo-preview';\n case 'anthropic':\n return 'claude-3-5-sonnet-20241022';\n case 'google':\n return 'gemini-1.5-pro';\n default:\n return 'gpt-4-turbo-preview';\n }\n}\n\n", "/**\n * Test generation prompt builder\n */\n\nimport type { LLMMessage } from '../../types/llm.js';\nimport type { TestGenerationContext } from '../../types/llm.js';\n\nexport function buildTestGenerationPrompt(context: TestGenerationContext): LLMMessage[] {\n const { target, framework, existingTestFile, relatedFunctions } = context;\n\n const systemPrompt = buildSystemPrompt(framework);\n const userPrompt = buildUserPrompt(target, framework, existingTestFile, relatedFunctions);\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\nfunction buildSystemPrompt(framework: 'jest' | 'vitest'): string {\n const frameworkName = framework === 'jest' ? 'Jest' : 'Vitest';\n const importStatement = framework === 'jest' ? \"import { describe, it, expect } from 'jest';\" : \"import { describe, it, expect } from 'vitest';\";\n\n return `You are an expert ${frameworkName} test writer. Your task is to generate comprehensive unit tests for TypeScript/JavaScript functions.\n\nRequirements:\n1. Generate complete, runnable ${frameworkName} test code\n2. Use ${frameworkName} syntax and best practices\n3. Test edge cases, error conditions, and normal operation\n4. Use descriptive test names that explain what is being tested\n5. Include proper setup/teardown if needed\n6. Mock external dependencies appropriately\n7. Test both success and failure scenarios\n8. Follow the existing test file structure if one exists\n\nOutput format:\n- Return ONLY the test code, no explanations or markdown code blocks\n- The code should be ready to run in a ${frameworkName} environment\n- Include necessary imports at the top\n- Use proper TypeScript types if the source code uses TypeScript\n\n${frameworkName} example structure:\n${importStatement}\n\ndescribe('FunctionName', () => {\n it('should handle normal case', () => {\n // test implementation\n });\n\n it('should handle edge case', () => {\n // test implementation\n });\n});`;\n}\n\nfunction buildUserPrompt(\n target: TestGenerationContext['target'],\n framework: 'jest' | 'vitest',\n existingTestFile?: string,\n relatedFunctions?: Array<{ name: string; code: string }>\n): string {\n let prompt = `Generate ${framework} unit tests for the following function:\\n\\n`;\n\n prompt += `File: ${target.filePath}\\n`;\n prompt += `Function: ${target.functionName}\\n`;\n prompt += `Type: ${target.functionType}\\n\\n`;\n\n prompt += `Function code:\\n\\`\\`\\`typescript\\n${target.code}\\n\\`\\`\\`\\n\\n`;\n\n if (target.context) {\n prompt += `Context (surrounding code):\\n\\`\\`\\`typescript\\n${target.context}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (relatedFunctions && relatedFunctions.length > 0) {\n prompt += `Related functions (for context):\\n`;\n relatedFunctions.forEach((fn) => {\n prompt += `\\n${fn.name}:\\n\\`\\`\\`typescript\\n${fn.code}\\n\\`\\`\\`\\n`;\n });\n prompt += '\\n';\n }\n\n if (existingTestFile) {\n prompt += `Existing test file structure (follow this pattern):\\n\\`\\`\\`typescript\\n${existingTestFile}\\n\\`\\`\\`\\n\\n`;\n prompt += `Note: Add new tests to this file, maintaining the existing structure and style.\\n\\n`;\n }\n\n prompt += `Generate comprehensive unit tests for ${target.functionName}. Include:\\n`;\n prompt += `- Tests for normal operation with various inputs\\n`;\n prompt += `- Tests for edge cases (null, undefined, empty arrays, etc.)\\n`;\n prompt += `- Tests for error conditions if applicable\\n`;\n prompt += `- Tests for boundary conditions\\n`;\n prompt += `- Proper mocking of dependencies if needed\\n\\n`;\n\n prompt += `Return ONLY the test code, no explanations or markdown formatting.`;\n\n return prompt;\n}\n\n", "/**\n * Test fix prompt builder for fix loop\n */\n\nimport type { LLMMessage } from '../../types/llm.js';\nimport type { TestFixContext } from '../../types/llm.js';\n\nexport function buildTestFixPrompt(context: TestFixContext): LLMMessage[] {\n const { testCode, errorMessage, testOutput, originalCode, framework, attempt, maxAttempts } = context;\n\n const systemPrompt = buildSystemPrompt(framework, attempt, maxAttempts);\n const userPrompt = buildUserPrompt(testCode, errorMessage, testOutput, originalCode, framework, attempt);\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\nfunction buildSystemPrompt(framework: 'jest' | 'vitest', attempt: number, maxAttempts: number): string {\n const frameworkName = framework === 'jest' ? 'Jest' : 'Vitest';\n\n return `You are an expert ${frameworkName} test debugger. Your task is to fix failing unit tests.\n\nContext:\n- This is fix attempt ${attempt} of ${maxAttempts}\n- The test code failed to run or produced incorrect results\n- You need to analyze the error and fix the test code\n\nRequirements:\n1. Fix the test code to make it pass\n2. Maintain the original test intent\n3. Use proper ${frameworkName} syntax\n4. Ensure all imports and dependencies are correct\n5. Fix any syntax errors, type errors, or logical errors\n6. If the original code being tested has issues, note that but focus on fixing the test\n\nOutput format:\n- Return ONLY the fixed test code, no explanations or markdown code blocks\n- The code should be complete and runnable\n- Include all necessary imports`;\n}\n\nfunction buildUserPrompt(\n testCode: string,\n errorMessage: string,\n testOutput: string | undefined,\n originalCode: string,\n framework: 'jest' | 'vitest',\n attempt: number\n): string {\n let prompt = `The following ${framework} test is failing. Fix it:\\n\\n`;\n\n prompt += `Original function code:\\n\\`\\`\\`typescript\\n${originalCode}\\n\\`\\`\\`\\n\\n`;\n\n prompt += `Failing test code:\\n\\`\\`\\`typescript\\n${testCode}\\n\\`\\`\\`\\n\\n`;\n\n prompt += `Error message:\\n\\`\\`\\`\\n${errorMessage}\\n\\`\\`\\`\\n\\n`;\n\n if (testOutput) {\n prompt += `Test output:\\n\\`\\`\\`\\n${testOutput}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (attempt > 1) {\n prompt += `Note: This is fix attempt ${attempt}. Previous attempts failed. Please analyze the error more carefully.\\n\\n`;\n }\n\n prompt += `Fix the test code to resolve the error. Return ONLY the corrected test code, no explanations.`;\n\n return prompt;\n}\n\n", "/**\n * Parse LLM output to extract test code\n */\n\nimport { warn } from '../utils/logger.js';\n\n/**\n * Extract test code from LLM response\n * Handles markdown code blocks, plain code, and other formats\n */\nexport function parseTestCode(response: string): string {\n // Remove markdown code blocks if present\n let code = response.trim();\n\n // Check for markdown code blocks (```typescript, ```ts, ```javascript, ```js, or just ```)\n const codeBlockRegex = /^```(?:typescript|ts|javascript|js)?\\s*\\n([\\s\\S]*?)\\n```$/;\n const match = code.match(codeBlockRegex);\n\n if (match) {\n code = match[1].trim();\n } else {\n // Check for inline code blocks\n const inlineCodeRegex = /```([\\s\\S]*?)```/g;\n const inlineMatches = Array.from(code.matchAll(inlineCodeRegex));\n if (inlineMatches.length > 0) {\n // Use the largest code block\n code = inlineMatches.reduce((largest, match) => {\n return match[1].length > largest.length ? match[1] : largest;\n }, '');\n code = code.trim();\n }\n }\n\n // Remove any leading/trailing explanation text\n // Look for common patterns like \"Here's the test:\", \"Test code:\", etc.\n const explanationPatterns = [\n /^Here'?s?\\s+(?:the\\s+)?(?:test\\s+)?code:?\\s*/i,\n /^Test\\s+code:?\\s*/i,\n /^Generated\\s+test:?\\s*/i,\n /^Here\\s+is\\s+the\\s+test:?\\s*/i,\n ];\n\n for (const pattern of explanationPatterns) {\n if (pattern.test(code)) {\n code = code.replace(pattern, '').trim();\n // If there's still explanation after the code, try to extract just the code\n const codeBlockMatch = code.match(/```[\\s\\S]*?```/);\n if (codeBlockMatch) {\n code = codeBlockMatch[0];\n code = code.replace(/^```(?:typescript|ts|javascript|js)?\\s*\\n?/, '').replace(/\\n?```$/, '').trim();\n }\n }\n }\n\n // Final cleanup: remove any remaining markdown formatting\n code = code.replace(/^```[\\w]*\\n?/, '').replace(/\\n?```$/, '').trim();\n\n if (!code) {\n warn('Failed to extract test code from LLM response');\n return response; // Return original if we can't parse\n }\n\n return code;\n}\n\n/**\n * Validate that the parsed code looks like valid test code\n */\nexport function validateTestCodeStructure(code: string, framework: 'jest' | 'vitest'): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Check for basic test structure\n if (!code.includes('describe') && !code.includes('it(') && !code.includes('test(')) {\n errors.push('Missing test structure (describe/it/test)');\n }\n\n // Check for framework-specific imports\n if (framework === 'jest') {\n if (!code.includes(\"from 'jest'\") && !code.includes('from \"jest\"') && !code.includes('require(')) {\n // Jest might use global functions, so this is just a warning\n if (!code.includes('describe') && !code.includes('it') && !code.includes('test')) {\n errors.push('Missing Jest test functions');\n }\n }\n } else if (framework === 'vitest') {\n if (!code.includes(\"from 'vitest'\") && !code.includes('from \"vitest\"')) {\n errors.push('Missing Vitest import');\n }\n }\n\n // Check for basic syntax (has some code, not just whitespace)\n if (code.trim().length < 20) {\n errors.push('Test code appears too short or empty');\n }\n\n // Check for common test patterns\n if (!code.match(/(describe|it|test)\\s*\\(/)) {\n errors.push('Missing test function calls (describe/it/test)');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n", "/**\n * Main test generator that orchestrates LLM calls and parsing\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { TestGenerationContext, TestGenerationResult, TestFixContext } from '../types/llm.js';\nimport { createLLMProvider } from './factory.js';\nimport { buildTestGenerationPrompt } from './prompts/test-generation.js';\nimport { buildTestFixPrompt } from './prompts/test-fix.js';\nimport { parseTestCode, validateTestCodeStructure } from './parser.js';\nimport { info, warn, error, debug } from '../utils/logger.js';\n\nexport class TestGenerator {\n private provider: ReturnType<typeof createLLMProvider>;\n private config: Pick<KakarotConfig, 'maxFixAttempts' | 'temperature' | 'fixTemperature'>;\n\n constructor(\n config: Pick<\n KakarotConfig,\n 'apiKey' | 'provider' | 'model' | 'maxTokens' | 'maxFixAttempts' | 'temperature' | 'fixTemperature'\n >\n ) {\n this.provider = createLLMProvider(config);\n this.config = {\n maxFixAttempts: config.maxFixAttempts,\n temperature: config.temperature,\n fixTemperature: config.fixTemperature,\n };\n }\n\n /**\n * Generate test code for a test target\n */\n async generateTest(context: TestGenerationContext): Promise<TestGenerationResult> {\n const { target, framework } = context;\n\n info(`Generating ${framework} tests for ${target.functionName} in ${target.filePath}`);\n\n try {\n const messages = buildTestGenerationPrompt(context);\n debug(`Sending test generation request to LLM for ${target.functionName}`);\n\n const response = await this.provider.generate(messages, {\n temperature: this.config.temperature ?? 0.2, // Lower temperature for more consistent test generation\n maxTokens: 4000,\n });\n\n const testCode = parseTestCode(response.content);\n const validation = validateTestCodeStructure(testCode, framework);\n\n if (!validation.valid) {\n warn(`Test code validation warnings for ${target.functionName}: ${validation.errors.join(', ')}`);\n // Continue anyway, as some issues might be false positives\n }\n\n debug(`Successfully generated test code for ${target.functionName}`);\n\n return {\n testCode,\n explanation: response.content !== testCode ? 'Code extracted from LLM response' : undefined,\n usage: response.usage,\n };\n } catch (err) {\n error(`Failed to generate test for ${target.functionName}: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n\n /**\n * Fix a failing test by generating a corrected version\n */\n async fixTest(context: TestFixContext): Promise<TestGenerationResult> {\n const { framework, attempt } = context;\n\n info(`Fixing test (attempt ${attempt}/${this.config.maxFixAttempts})`);\n\n try {\n const messages = buildTestFixPrompt(context);\n debug(`Sending test fix request to LLM (attempt ${attempt})`);\n\n const response = await this.provider.generate(messages, {\n temperature: this.config.fixTemperature ?? 0.1, // Very low temperature for fix attempts\n maxTokens: 4000,\n });\n\n const fixedCode = parseTestCode(response.content);\n const validation = validateTestCodeStructure(fixedCode, framework);\n\n if (!validation.valid) {\n warn(`Fixed test code validation warnings: ${validation.errors.join(', ')}`);\n }\n\n debug(`Successfully generated fixed test code (attempt ${attempt})`);\n\n return {\n testCode: fixedCode,\n explanation: `Fixed test code (attempt ${attempt})`,\n usage: response.usage,\n };\n } catch (err) {\n error(`Failed to fix test (attempt ${attempt}): ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n\n /**\n * Generate a human-readable coverage summary\n */\n async generateCoverageSummary(messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>): Promise<string> {\n try {\n const response = await this.provider.generate(messages, {\n temperature: 0.3,\n maxTokens: 500,\n });\n return response.content;\n } catch (err) {\n error(`Failed to generate coverage summary: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import type { KakarotConfig } from '../types/config.js';\nimport type { TestTarget } from '../types/diff.js';\n\n/**\n * Determine the test file path for a test target based on configuration\n */\nexport function getTestFilePath(\n target: TestTarget,\n config: Pick<KakarotConfig, 'testLocation' | 'testDirectory' | 'testFilePattern'>\n): string {\n const sourcePath = target.filePath;\n const lastSlashIndex = sourcePath.lastIndexOf('/');\n const dir = lastSlashIndex >= 0 ? sourcePath.substring(0, lastSlashIndex) : '';\n const baseName = sourcePath.substring(lastSlashIndex + 1).replace(/\\.(ts|tsx|js|jsx)$/, '');\n \n // Determine file extension\n let ext: 'ts' | 'tsx' | 'js' | 'jsx';\n if (sourcePath.endsWith('.tsx')) ext = 'tsx';\n else if (sourcePath.endsWith('.jsx')) ext = 'jsx';\n else if (sourcePath.endsWith('.ts')) ext = 'ts';\n else ext = 'js';\n\n // Determine test file extension (prefer matching source type)\n const testExt = ext === 'tsx' || ext === 'ts' ? 'ts' : 'js';\n\n if (config.testLocation === 'co-located') {\n // Co-located: same directory as source file\n return dir ? `${dir}/${baseName}.test.${testExt}` : `${baseName}.test.${testExt}`;\n } else {\n // Separate: in test directory\n // Replace testFilePattern wildcard with actual filename\n const testFileName = config.testFilePattern.replace('*', baseName);\n return `${config.testDirectory}/${testFileName}`;\n }\n}\n\n", "import { existsSync } from 'fs';\nimport { join } from 'path';\n\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm';\n\n/**\n * Detect package manager from project files\n */\nexport function detectPackageManager(projectRoot: string): PackageManager {\n // Check for lock files (most reliable indicator)\n if (existsSync(join(projectRoot, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n \n if (existsSync(join(projectRoot, 'yarn.lock'))) {\n return 'yarn';\n }\n \n if (existsSync(join(projectRoot, 'package-lock.json'))) {\n return 'npm';\n }\n \n // Default to npm if no lock file found\n return 'npm';\n}\n\n", "import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { TestRunner, TestResult, TestRunOptions, TestFailure } from '../../types/test-runner.js';\nimport { debug, error } from '../logger.js';\n\nconst execAsync = promisify(exec);\n\ninterface JestTestResult {\n numPassedTests: number;\n numFailedTests: number;\n numTotalTests: number;\n testResults: Array<{\n name: string;\n status: 'passed' | 'failed';\n assertionResults: Array<{\n title: string;\n status: 'passed' | 'failed';\n failureMessages: string[];\n }>;\n }>;\n}\n\nexport class JestRunner implements TestRunner {\n async runTests(options: TestRunOptions): Promise<TestResult[]> {\n const { testFiles, packageManager, projectRoot, coverage } = options;\n \n debug(`Running Jest tests for ${testFiles.length} file(s)`);\n\n // Build Jest command\n const testFilesArg = testFiles.map(f => `\"${f}\"`).join(' ');\n const coverageFlag = coverage ? '--coverage --coverageReporters=json' : '--no-coverage';\n const cmd = `${packageManager} test -- --json ${coverageFlag} ${testFilesArg}`;\n\n try {\n const { stdout, stderr } = await execAsync(cmd, {\n cwd: projectRoot,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n\n if (stderr && !stderr.includes('PASS') && !stderr.includes('FAIL')) {\n debug(`Jest stderr: ${stderr}`);\n }\n\n const result = JSON.parse(stdout) as JestTestResult;\n\n return testFiles.map((testFile, index) => {\n const testResult = result.testResults[index] || result.testResults[0];\n const failures: TestFailure[] = [];\n\n if (testResult) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n const failureMessage = assertion.failureMessages[0];\n failures.push({\n testName: assertion.title,\n message: failureMessage,\n stack: failureMessage,\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0, // Jest JSON doesn't include duration per file\n failures,\n };\n });\n } catch (err: unknown) {\n // Jest returns non-zero exit code on failures, but stdout still contains JSON\n if (err && typeof err === 'object' && 'stdout' in err) {\n try {\n const result = JSON.parse(err.stdout as string) as JestTestResult;\n return testFiles.map((testFile) => {\n const failures: TestFailure[] = [];\n \n for (const testResult of result.testResults) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n failures.push({\n testName: assertion.title,\n message: assertion.failureMessages[0],\n stack: assertion.failureMessages[0],\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0,\n failures,\n };\n });\n } catch (parseErr) {\n error(`Failed to parse Jest output: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);\n throw err;\n }\n }\n \n error(`Jest test execution failed: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { TestRunner, TestResult, TestRunOptions, TestFailure } from '../../types/test-runner.js';\nimport { debug, error } from '../logger.js';\n\nconst execAsync = promisify(exec);\n\ninterface VitestTestResult {\n numPassedTests: number;\n numFailedTests: number;\n numTotalTests: number;\n testResults: Array<{\n name: string;\n status: 'passed' | 'failed';\n assertionResults: Array<{\n title: string;\n status: 'passed' | 'failed';\n failureMessages: string[];\n }>;\n }>;\n}\n\nexport class VitestRunner implements TestRunner {\n async runTests(options: TestRunOptions): Promise<TestResult[]> {\n const { testFiles, packageManager, projectRoot, coverage } = options;\n \n debug(`Running Vitest tests for ${testFiles.length} file(s)`);\n\n // Build Vitest command\n const testFilesArg = testFiles.map(f => `\"${f}\"`).join(' ');\n const coverageFlag = coverage ? '--coverage' : '';\n const cmd = `${packageManager} test -- --reporter=json ${coverageFlag} ${testFilesArg}`;\n\n try {\n const { stdout, stderr } = await execAsync(cmd, {\n cwd: projectRoot,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n });\n\n if (stderr && !stderr.includes('PASS') && !stderr.includes('FAIL')) {\n debug(`Vitest stderr: ${stderr}`);\n }\n\n // Vitest JSON output is line-delimited, get the last line\n const lines = stdout.trim().split('\\n');\n const jsonLine = lines[lines.length - 1];\n \n if (!jsonLine || !jsonLine.startsWith('{')) {\n throw new Error('No valid JSON output from Vitest');\n }\n\n const result = JSON.parse(jsonLine) as VitestTestResult;\n\n return testFiles.map((testFile, index) => {\n const testResult = result.testResults[index] || result.testResults[0];\n const failures: TestFailure[] = [];\n\n if (testResult) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n const failureMessage = assertion.failureMessages[0];\n failures.push({\n testName: assertion.title,\n message: failureMessage,\n stack: failureMessage,\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0, // Vitest JSON doesn't include duration per file\n failures,\n };\n });\n } catch (err: unknown) {\n // Vitest returns non-zero exit code on failures, but stdout may still contain JSON\n if (err && typeof err === 'object' && 'stdout' in err) {\n try {\n const lines = (err.stdout as string).trim().split('\\n');\n const jsonLine = lines[lines.length - 1];\n \n if (jsonLine && jsonLine.startsWith('{')) {\n const result = JSON.parse(jsonLine) as VitestTestResult;\n return testFiles.map((testFile) => {\n const failures: TestFailure[] = [];\n \n for (const testResult of result.testResults) {\n for (const assertion of testResult.assertionResults) {\n if (assertion.status === 'failed' && assertion.failureMessages.length > 0) {\n failures.push({\n testName: assertion.title,\n message: assertion.failureMessages[0],\n stack: assertion.failureMessages[0],\n });\n }\n }\n }\n\n return {\n success: result.numFailedTests === 0,\n testFile,\n passed: result.numPassedTests,\n failed: result.numFailedTests,\n total: result.numTotalTests,\n duration: 0,\n failures,\n };\n });\n }\n } catch (parseErr) {\n error(`Failed to parse Vitest output: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);\n throw err;\n }\n }\n \n error(`Vitest test execution failed: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n }\n}\n\n", "import type { TestRunner } from '../../types/test-runner.js';\nimport { JestRunner } from './jest-runner.js';\nimport { VitestRunner } from './vitest-runner.js';\n\n/**\n * Create a test runner for the specified framework\n */\nexport function createTestRunner(framework: 'jest' | 'vitest'): TestRunner {\n switch (framework) {\n case 'jest':\n return new JestRunner();\n case 'vitest':\n return new VitestRunner();\n default:\n throw new Error(`Unsupported test framework: ${framework}`);\n }\n}\n\n", "import { writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { debug } from './logger.js';\n\n/**\n * Write test files to disk in the project directory\n */\nexport function writeTestFiles(\n testFiles: Map<string, { content: string; targets: string[] }>,\n projectRoot: string\n): string[] {\n const writtenPaths: string[] = [];\n\n for (const [relativePath, fileData] of testFiles.entries()) {\n const fullPath = join(projectRoot, relativePath);\n const dir = dirname(fullPath);\n\n // Create directory if it doesn't exist\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n debug(`Created directory: ${dir}`);\n }\n\n // Write test file\n writeFileSync(fullPath, fileData.content, 'utf-8');\n writtenPaths.push(relativePath);\n debug(`Wrote test file: ${relativePath}`);\n }\n\n return writtenPaths;\n}\n\n", "import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport type { CoverageReport, FileCoverage } from '../types/coverage.js';\nimport { debug, warn } from './logger.js';\n\n/**\n * Jest coverage JSON structure\n */\ninterface JestCoverageData {\n [filePath: string]: {\n statements: { [key: string]: number };\n branches: { [key: string]: number };\n functions: { [key: string]: number };\n lines: { [key: string]: number };\n statementMap: Record<string, unknown>;\n fnMap: Record<string, unknown>;\n branchMap: Record<string, unknown>;\n };\n}\n\n/**\n * Vitest coverage JSON structure (similar to Jest)\n */\ninterface VitestCoverageData {\n [filePath: string]: {\n statements: { [key: string]: number };\n branches: { [key: string]: number };\n functions: { [key: string]: number };\n lines: { [key: string]: number };\n };\n}\n\n/**\n * Read and parse Jest coverage report\n */\nfunction parseJestCoverage(data: JestCoverageData): CoverageReport {\n const files: FileCoverage[] = [];\n let totalStatements = 0;\n let coveredStatements = 0;\n let totalBranches = 0;\n let coveredBranches = 0;\n let totalFunctions = 0;\n let coveredFunctions = 0;\n let totalLines = 0;\n let coveredLines = 0;\n\n for (const [filePath, coverage] of Object.entries(data)) {\n // Calculate metrics for this file\n const statementCounts = Object.values(coverage.statements);\n const branchCounts = Object.values(coverage.branches);\n const functionCounts = Object.values(coverage.functions);\n const lineCounts = Object.values(coverage.lines);\n\n const fileStatements = {\n total: statementCounts.length,\n covered: statementCounts.filter(c => c > 0).length,\n percentage: statementCounts.length > 0\n ? (statementCounts.filter(c => c > 0).length / statementCounts.length) * 100\n : 100,\n };\n\n const fileBranches = {\n total: branchCounts.length,\n covered: branchCounts.filter(c => c > 0).length,\n percentage: branchCounts.length > 0\n ? (branchCounts.filter(c => c > 0).length / branchCounts.length) * 100\n : 100,\n };\n\n const fileFunctions = {\n total: functionCounts.length,\n covered: functionCounts.filter(c => c > 0).length,\n percentage: functionCounts.length > 0\n ? (functionCounts.filter(c => c > 0).length / functionCounts.length) * 100\n : 100,\n };\n\n const fileLines = {\n total: lineCounts.length,\n covered: lineCounts.filter(c => c > 0).length,\n percentage: lineCounts.length > 0\n ? (lineCounts.filter(c => c > 0).length / lineCounts.length) * 100\n : 100,\n };\n\n files.push({\n path: filePath,\n metrics: {\n statements: fileStatements,\n branches: fileBranches,\n functions: fileFunctions,\n lines: fileLines,\n },\n });\n\n // Accumulate totals\n totalStatements += fileStatements.total;\n coveredStatements += fileStatements.covered;\n totalBranches += fileBranches.total;\n coveredBranches += fileBranches.covered;\n totalFunctions += fileFunctions.total;\n coveredFunctions += fileFunctions.covered;\n totalLines += fileLines.total;\n coveredLines += fileLines.covered;\n }\n\n return {\n total: {\n statements: {\n total: totalStatements,\n covered: coveredStatements,\n percentage: totalStatements > 0 ? (coveredStatements / totalStatements) * 100 : 100,\n },\n branches: {\n total: totalBranches,\n covered: coveredBranches,\n percentage: totalBranches > 0 ? (coveredBranches / totalBranches) * 100 : 100,\n },\n functions: {\n total: totalFunctions,\n covered: coveredFunctions,\n percentage: totalFunctions > 0 ? (coveredFunctions / totalFunctions) * 100 : 100,\n },\n lines: {\n total: totalLines,\n covered: coveredLines,\n percentage: totalLines > 0 ? (coveredLines / totalLines) * 100 : 100,\n },\n },\n files,\n };\n}\n\n/**\n * Read and parse Vitest coverage report (similar format to Jest)\n */\nfunction parseVitestCoverage(data: VitestCoverageData): CoverageReport {\n // Vitest uses the same structure as Jest\n return parseJestCoverage(data as JestCoverageData);\n}\n\n/**\n * Read coverage report from Jest/Vitest JSON output\n */\nexport function readCoverageReport(\n projectRoot: string,\n framework: 'jest' | 'vitest'\n): CoverageReport | null {\n // Jest and Vitest both output to coverage/coverage-final.json\n const coveragePath = join(projectRoot, 'coverage', 'coverage-final.json');\n\n if (!existsSync(coveragePath)) {\n debug(`Coverage file not found at ${coveragePath}`);\n return null;\n }\n\n try {\n const content = readFileSync(coveragePath, 'utf-8');\n const data = JSON.parse(content);\n\n if (framework === 'jest') {\n return parseJestCoverage(data as JestCoverageData);\n } else {\n return parseVitestCoverage(data as VitestCoverageData);\n }\n } catch (err) {\n warn(`Failed to read coverage report: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\n", "import type { LLMMessage } from '../../types/llm.js';\nimport type { CoverageReport, CoverageDelta } from '../../types/coverage.js';\nimport type { TestResult } from '../../types/test-runner.js';\n\n/**\n * Build prompt for generating human-readable coverage summary\n */\nexport function buildCoverageSummaryPrompt(\n coverageReport: CoverageReport,\n testResults: TestResult[],\n functionsTested: string[],\n coverageDelta?: CoverageDelta\n): LLMMessage[] {\n const systemPrompt = `You are a technical writer specializing in test coverage reports. Your task is to generate a clear, concise, and actionable summary of test coverage metrics.\n\nRequirements:\n1. Use clear, professional language\n2. Highlight key metrics (lines, branches, functions, statements)\n3. Mention which functions were tested\n4. If coverage delta is provided, explain the change\n5. Provide actionable insights or recommendations\n6. Format as markdown suitable for GitHub PR comments\n7. Keep it concise (2-3 paragraphs max)`;\n\n const totalTests = testResults.reduce((sum, r) => sum + r.total, 0);\n const passedTests = testResults.reduce((sum, r) => sum + r.passed, 0);\n const failedTests = testResults.reduce((sum, r) => sum + r.failed, 0);\n\n const userPrompt = `Generate a human-readable test coverage summary with the following information:\n\n**Coverage Metrics:**\n- Lines: ${coverageReport.total.lines.percentage.toFixed(1)}% (${coverageReport.total.lines.covered}/${coverageReport.total.lines.total})\n- Branches: ${coverageReport.total.branches.percentage.toFixed(1)}% (${coverageReport.total.branches.covered}/${coverageReport.total.branches.total})\n- Functions: ${coverageReport.total.functions.percentage.toFixed(1)}% (${coverageReport.total.functions.covered}/${coverageReport.total.functions.total})\n- Statements: ${coverageReport.total.statements.percentage.toFixed(1)}% (${coverageReport.total.statements.covered}/${coverageReport.total.statements.total})\n\n**Test Results:**\n- Total tests: ${totalTests}\n- Passed: ${passedTests}\n- Failed: ${failedTests}\n\n**Functions Tested:**\n${functionsTested.length > 0 ? functionsTested.map(f => `- ${f}`).join('\\n') : 'None'}\n\n${coverageDelta ? `**Coverage Changes:**\n- Lines: ${coverageDelta.lines > 0 ? '+' : ''}${coverageDelta.lines.toFixed(1)}%\n- Branches: ${coverageDelta.branches > 0 ? '+' : ''}${coverageDelta.branches.toFixed(1)}%\n- Functions: ${coverageDelta.functions > 0 ? '+' : ''}${coverageDelta.functions.toFixed(1)}%\n- Statements: ${coverageDelta.statements > 0 ? '+' : ''}${coverageDelta.statements.toFixed(1)}%\n` : ''}\n\nGenerate a concise, professional summary that explains what was tested and the coverage achieved.`;\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n}\n\n", "/**\n * Main orchestration function for Kakarot CI\n * Processes pull requests and generates tests\n */\n\nimport type { KakarotConfig } from '../types/config.js';\nimport type { PullRequest } from '../types/github.js';\nimport { GitHubClient } from '../github/client.js';\nimport { loadConfig } from '../utils/config-loader.js';\nimport { initLogger, info, error, warn, success, progress, debug } from '../utils/logger.js';\nimport { extractTestTargets } from '../utils/test-target-extractor.js';\nimport { TestGenerator } from '../llm/test-generator.js';\nimport { getTestFilePath } from '../utils/test-file-path.js';\nimport { detectPackageManager } from '../utils/package-manager-detector.js';\nimport { createTestRunner } from '../utils/test-runner/factory.js';\nimport { writeTestFiles } from '../utils/test-file-writer.js';\nimport { findProjectRoot } from '../utils/config-loader.js';\nimport { readCoverageReport } from '../utils/coverage-reader.js';\nimport { buildCoverageSummaryPrompt } from '../llm/prompts/coverage-summary.js';\nimport type { TestResult } from '../types/test-runner.js';\nimport type { CoverageReport } from '../types/coverage.js';\n\nexport interface PullRequestContext {\n prNumber: number;\n owner: string;\n repo: string;\n githubToken: string;\n}\n\nexport interface TestGenerationSummary {\n targetsProcessed: number;\n testsGenerated: number;\n testsFailed: number;\n testFiles: Array<{\n path: string;\n targets: string[];\n }>;\n errors: Array<{\n target: string;\n error: string;\n }>;\n coverageReport?: CoverageReport;\n testResults?: TestResult[];\n}\n\n/**\n * Main orchestration function to process a pull request and generate tests\n */\nexport async function runPullRequest(context: PullRequestContext): Promise<TestGenerationSummary> {\n // Load configuration\n const config = await loadConfig();\n \n // Initialize logger\n initLogger(config);\n \n info(`Processing PR #${context.prNumber} for ${context.owner}/${context.repo}`);\n\n // Initialize GitHub client\n const githubToken = context.githubToken || config.githubToken;\n if (!githubToken) {\n throw new Error('GitHub token is required. Provide it via config.githubToken or context.githubToken');\n }\n\n const githubClient = new GitHubClient({\n token: githubToken,\n owner: context.owner,\n repo: context.repo,\n });\n\n // Get PR details\n const pr = await githubClient.getPullRequest(context.prNumber);\n \n if (pr.state !== 'open') {\n warn(`PR #${context.prNumber} is ${pr.state}, skipping test generation`);\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n info(`PR: ${pr.title} (${pr.head.ref} -> ${pr.base.ref})`);\n\n // Get PR files\n const prFiles = await githubClient.listPullRequestFiles(context.prNumber);\n \n if (prFiles.length === 0) {\n info('No files changed in this PR');\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n info(`Found ${prFiles.length} file(s) changed in PR`);\n\n // Extract test targets\n const prHeadRef = pr.head.sha;\n const targets = await extractTestTargets(\n prFiles,\n githubClient,\n prHeadRef,\n config\n );\n\n if (targets.length === 0) {\n info('No test targets found in changed files');\n return {\n targetsProcessed: 0,\n testsGenerated: 0,\n testsFailed: 0,\n testFiles: [],\n errors: [],\n };\n }\n\n // Limit targets based on config\n const limitedTargets = targets.slice(0, config.maxTestsPerPR);\n \n if (targets.length > limitedTargets.length) {\n warn(`Limiting to ${config.maxTestsPerPR} test targets (found ${targets.length})`);\n }\n\n info(`Found ${limitedTargets.length} test target(s)`);\n\n // Use configured test framework\n const framework = config.framework;\n info(`Using test framework: ${framework}`);\n\n // Initialize test generator\n const testGenerator = new TestGenerator({\n apiKey: config.apiKey,\n provider: config.provider,\n model: config.model,\n maxTokens: config.maxTokens,\n maxFixAttempts: config.maxFixAttempts,\n temperature: config.temperature,\n fixTemperature: config.fixTemperature,\n });\n\n // Generate tests for each target\n let testFiles = new Map<string, { content: string; targets: string[] }>();\n const errors: Array<{ target: string; error: string }> = [];\n let testsGenerated = 0;\n let testsFailed = 0;\n\n for (let i = 0; i < limitedTargets.length; i++) {\n const target = limitedTargets[i];\n progress(i + 1, limitedTargets.length, `Generating test for ${target.functionName}`);\n\n try {\n // Determine where the test file should be based on config\n const testFilePath = getTestFilePath(target, config);\n \n // Check if a test file exists at the config-determined path\n let existingTestFile: string | undefined;\n const testFileExists = await githubClient.fileExists(prHeadRef, testFilePath);\n \n if (testFileExists) {\n try {\n const fileContents = await githubClient.getFileContents(prHeadRef, testFilePath);\n existingTestFile = fileContents.content;\n debug(`Found existing test file at ${testFilePath}`);\n } catch (err) {\n debug(`Could not fetch existing test file ${testFilePath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n } else {\n debug(`No existing test file at ${testFilePath}, will create new file`);\n }\n\n // Generate test\n const result = await testGenerator.generateTest({\n target: {\n filePath: target.filePath,\n functionName: target.functionName,\n functionType: target.functionType,\n code: target.code,\n context: target.context,\n },\n framework,\n existingTestFile,\n });\n\n // Group tests by file path\n if (!testFiles.has(testFilePath)) {\n // Use existing test file content as base if it exists at this path\n const baseContent = existingTestFile || '';\n testFiles.set(testFilePath, { content: baseContent, targets: [] });\n }\n\n const fileData = testFiles.get(testFilePath)!;\n \n // Append test content (with separator if base content exists)\n if (fileData.content) {\n fileData.content += '\\n\\n' + result.testCode;\n } else {\n fileData.content = result.testCode;\n }\n \n fileData.targets.push(target.functionName);\n testsGenerated++;\n\n info(`\u2713 Generated test for ${target.functionName}`);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n error(`\u2717 Failed to generate test for ${target.functionName}: ${errorMessage}`);\n errors.push({\n target: `${target.filePath}:${target.functionName}`,\n error: errorMessage,\n });\n testsFailed++;\n }\n }\n\n // Write tests to disk and run them\n const projectRoot = await findProjectRoot();\n const packageManager = detectPackageManager(projectRoot);\n info(`Detected package manager: ${packageManager}`);\n\n if (testFiles.size > 0) {\n // Write test files to disk\n const writtenPaths = writeTestFiles(testFiles, projectRoot);\n info(`Wrote ${writtenPaths.length} test file(s) to disk`);\n\n // Run tests and fix failures\n const testRunner = createTestRunner(framework);\n const finalTestFiles = await runTestsAndFix(\n testRunner,\n testFiles,\n writtenPaths,\n framework,\n packageManager,\n projectRoot,\n testGenerator,\n config.maxFixAttempts\n );\n\n // Update testFiles with fixed versions\n testFiles = finalTestFiles;\n }\n\n // Initialize summary\n const summary: TestGenerationSummary = {\n targetsProcessed: limitedTargets.length,\n testsGenerated,\n testsFailed,\n testFiles: Array.from(testFiles.entries()).map(([path, data]) => ({\n path,\n targets: data.targets,\n })),\n errors,\n };\n\n // Run tests with coverage for final report (if tests were generated)\n if (testFiles.size > 0) {\n const testRunner = createTestRunner(framework);\n const writtenPaths = Array.from(testFiles.keys());\n \n info('Running tests with coverage...');\n const finalTestResults = await testRunner.runTests({\n testFiles: writtenPaths,\n framework,\n packageManager,\n projectRoot,\n coverage: true,\n });\n\n // Read coverage report\n const coverageReport = readCoverageReport(projectRoot, framework);\n if (coverageReport) {\n info(`Coverage collected: ${coverageReport.total.lines.percentage.toFixed(1)}% lines`);\n summary.coverageReport = coverageReport;\n summary.testResults = finalTestResults;\n } else {\n warn('Could not read coverage report');\n }\n }\n\n // Commit tests if enabled\n if (config.enableAutoCommit && testFiles.size > 0) {\n await commitTests(\n githubClient,\n pr,\n Array.from(testFiles.entries()).map(([path, data]) => ({\n path,\n content: data.content,\n })),\n config,\n summary\n );\n }\n\n // Post PR comment if enabled\n if (config.enablePRComments) {\n await postPRComment(githubClient, context.prNumber, summary, framework, testGenerator);\n }\n\n success(`Completed: ${testsGenerated} test(s) generated, ${testsFailed} failed`);\n\n return summary;\n}\n\n/**\n * Run tests and fix failures in a loop\n */\nasync function runTestsAndFix(\n testRunner: ReturnType<typeof createTestRunner>,\n testFiles: Map<string, { content: string; targets: string[] }>,\n testFilePaths: string[],\n framework: 'jest' | 'vitest',\n packageManager: 'npm' | 'yarn' | 'pnpm',\n projectRoot: string,\n testGenerator: TestGenerator,\n maxFixAttempts: number\n): Promise<Map<string, { content: string; targets: string[] }>> {\n const currentTestFiles = new Map(testFiles);\n let attempt = 0;\n\n while (attempt < maxFixAttempts) {\n info(`Running tests (attempt ${attempt + 1}/${maxFixAttempts})`);\n\n // Run tests\n const results = await testRunner.runTests({\n testFiles: testFilePaths,\n framework,\n packageManager,\n projectRoot,\n coverage: false,\n });\n\n // Check if all tests passed\n const allPassed = results.every(r => r.success);\n if (allPassed) {\n success(`All tests passed on attempt ${attempt + 1}`);\n return currentTestFiles;\n }\n\n // Find failing tests\n const failures: Array<{ testFile: string; result: TestResult }> = [];\n for (const result of results) {\n if (!result.success && result.failures.length > 0) {\n failures.push({ testFile: result.testFile, result });\n }\n }\n\n info(`Found ${failures.length} failing test file(s), attempting fixes...`);\n\n // Fix each failing test file\n let fixedAny = false;\n for (const { testFile, result } of failures) {\n const testFileContent = currentTestFiles.get(testFile)?.content;\n if (!testFileContent) {\n warn(`Could not find content for test file: ${testFile}`);\n continue;\n }\n\n // Get the original source code for context (we need to find which target this test file corresponds to)\n // For now, we'll use the first failure's context\n const firstFailure = result.failures[0];\n if (!firstFailure) continue;\n\n try {\n // Build fix context - we need the original function code\n // This is a simplified version - in practice, we'd need to map test files back to targets\n const fixedResult = await testGenerator.fixTest({\n testCode: testFileContent,\n errorMessage: firstFailure.message,\n testOutput: firstFailure.stack,\n originalCode: '', // We'd need to pass this from the target\n framework,\n attempt: attempt + 1,\n maxAttempts: maxFixAttempts,\n });\n\n // Update the test file content\n currentTestFiles.set(testFile, {\n content: fixedResult.testCode,\n targets: currentTestFiles.get(testFile)?.targets || [],\n });\n\n // Write updated file to disk\n const { writeFileSync } = await import('fs');\n const { join } = await import('path');\n writeFileSync(join(projectRoot, testFile), fixedResult.testCode, 'utf-8');\n\n fixedAny = true;\n info(`\u2713 Fixed test file: ${testFile}`);\n } catch (err) {\n error(`Failed to fix test file ${testFile}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (!fixedAny) {\n warn(`Could not fix any failing tests on attempt ${attempt + 1}`);\n break;\n }\n\n attempt++;\n }\n\n if (attempt >= maxFixAttempts) {\n warn(`Reached maximum fix attempts (${maxFixAttempts}), some tests may still be failing`);\n }\n\n return currentTestFiles;\n}\n\n/**\n * Commit generated tests to the repository\n */\nasync function commitTests(\n githubClient: GitHubClient,\n pr: PullRequest,\n testFiles: Array<{ path: string; content: string }>,\n config: KakarotConfig,\n summary: TestGenerationSummary\n): Promise<void> {\n info(`Committing ${testFiles.length} test file(s)`);\n\n try {\n if (config.commitStrategy === 'branch-pr') {\n // Create a new branch and PR\n const branchName = `kakarot-ci/tests-pr-${pr.number}`;\n const baseSha = await githubClient.createBranch(branchName, pr.head.ref);\n\n // Commit to the new branch\n await githubClient.commitFiles({\n files: testFiles.map(file => ({\n path: file.path,\n content: file.content,\n })),\n message: `test: add unit tests for PR #${pr.number}\\n\\nGenerated ${summary.testsGenerated} test(s) for ${summary.targetsProcessed} function(s)`,\n branch: branchName,\n baseSha,\n });\n\n // Create PR\n const testPR = await githubClient.createPullRequest(\n `test: Add unit tests for PR #${pr.number}`,\n `This PR contains automatically generated unit tests for PR #${pr.number}.\\n\\n` +\n `- ${summary.testsGenerated} test(s) generated\\n` +\n `- ${summary.targetsProcessed} function(s) tested\\n` +\n `- ${testFiles.length} test file(s) created/updated`,\n branchName,\n pr.head.ref\n );\n\n success(`Created PR #${testPR.number} with generated tests`);\n } else {\n // Direct commit to PR branch\n await githubClient.commitFiles({\n files: testFiles.map(file => ({\n path: file.path,\n content: file.content,\n })),\n message: `test: add unit tests\\n\\nGenerated ${summary.testsGenerated} test(s) for ${summary.targetsProcessed} function(s)`,\n branch: pr.head.ref,\n baseSha: pr.head.sha,\n });\n\n success(`Committed ${testFiles.length} test file(s) to ${pr.head.ref}`);\n }\n } catch (err) {\n error(`Failed to commit tests: ${err instanceof Error ? err.message : String(err)}`);\n throw err;\n }\n}\n\n/**\n * Post a summary comment on the PR\n */\nasync function postPRComment(\n githubClient: GitHubClient,\n prNumber: number,\n summary: TestGenerationSummary,\n framework: 'jest' | 'vitest',\n testGenerator: TestGenerator\n): Promise<void> {\n let comment = `## \uD83E\uDDEA Kakarot CI Test Generation Summary\n\n**Framework:** ${framework}\n**Targets Processed:** ${summary.targetsProcessed}\n**Tests Generated:** ${summary.testsGenerated}\n**Failures:** ${summary.testsFailed}\n\n### Test Files\n${summary.testFiles.length > 0 \n ? summary.testFiles.map(f => `- \\`${f.path}\\` (${f.targets.length} test(s))`).join('\\n')\n : 'No test files generated'\n}\n\n${summary.errors.length > 0 \n ? `### Errors\\n${summary.errors.map(e => `- \\`${e.target}\\`: ${e.error}`).join('\\n')}`\n : ''\n}`;\n\n // Add coverage summary if available\n if (summary.coverageReport && summary.testResults) {\n try {\n // Collect all function names that were tested\n const functionsTested = summary.testFiles.flatMap(f => f.targets);\n \n // Generate human-readable coverage summary via LLM\n const messages = buildCoverageSummaryPrompt(\n summary.coverageReport,\n summary.testResults,\n functionsTested\n );\n\n const coverageSummary = await testGenerator.generateCoverageSummary(messages);\n comment += `\\n\\n## \uD83D\uDCCA Coverage Summary\\n\\n${coverageSummary}`;\n } catch (err) {\n warn(`Failed to generate coverage summary: ${err instanceof Error ? err.message : String(err)}`);\n \n // Fallback to basic coverage metrics\n const cov = summary.coverageReport.total;\n comment += `\\n\\n## \uD83D\uDCCA Coverage Summary\\n\\n` +\n `- **Lines:** ${cov.lines.percentage.toFixed(1)}% (${cov.lines.covered}/${cov.lines.total})\\n` +\n `- **Branches:** ${cov.branches.percentage.toFixed(1)}% (${cov.branches.covered}/${cov.branches.total})\\n` +\n `- **Functions:** ${cov.functions.percentage.toFixed(1)}% (${cov.functions.covered}/${cov.functions.total})\\n` +\n `- **Statements:** ${cov.statements.percentage.toFixed(1)}% (${cov.statements.covered}/${cov.statements.total})`;\n }\n }\n\n comment += `\\n\\n---\\n*Generated by [Kakarot CI](https://github.com/kakarot-ci)*`;\n\n try {\n await githubClient.commentPR(prNumber, comment);\n info('Posted PR comment with test generation summary');\n } catch (err) {\n warn(`Failed to post PR comment: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n"],
5
+ "mappings": ";;;AAAA,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,OAAO,iBAAiB;AACxB,SAAS,eAAe;;;ACHxB,SAAS,eAAe;;;ACExB,IAAI,YAAY;AAChB,IAAI,WAAW;AAER,SAAS,WAAW,QAA4C;AACrE,cAAY,OAAO,SAAS,QAAQ,IAAI,kBAAkB;AAC1D,aAAW,QAAQ,IAAI,mBAAmB;AAC5C;AAGO,SAAS,KAAK,YAAoB,MAAuB;AAC9D,MAAI,UAAU;AACZ,YAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,EACjE,OAAO;AACL,YAAQ,IAAI,gBAAgB,OAAO,IAAI,GAAG,IAAI;AAAA,EAChD;AACF;AAEO,SAAS,MAAM,YAAoB,MAAuB;AAC/D,MAAI,WAAW;AACb,QAAI,UAAU;AACZ,cAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,IACpE,OAAO;AACL,cAAQ,MAAM,sBAAsB,OAAO,IAAI,GAAG,IAAI;AAAA,IACxD;AAAA,EACF;AACF;AAEO,SAAS,KAAK,YAAoB,MAAuB;AAC9D,MAAI,UAAU;AACZ,YAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,QAAQ,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,EAClE,OAAO;AACL,YAAQ,KAAK,uBAAkB,OAAO,IAAI,GAAG,IAAI;AAAA,EACnD;AACF;AAEO,SAAS,MAAM,YAAoB,MAAuB;AAC/D,MAAI,UAAU;AACZ,YAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,EACpE,OAAO;AACL,YAAQ,MAAM,uBAAkB,OAAO,IAAI,GAAG,IAAI;AAAA,EACpD;AACF;AAEO,SAAS,QAAQ,YAAoB,MAAuB;AACjE,MAAI,UAAU;AACZ,YAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,WAAW,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,EACpE,OAAO;AACL,YAAQ,IAAI,uBAAkB,OAAO,IAAI,GAAG,IAAI;AAAA,EAClD;AACF;AAEO,SAAS,SAAS,MAAc,OAAe,YAAoB,MAAuB;AAC/F,MAAI,UAAU;AACZ,YAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,MAAM,OAAO,SAAS,GAAG,KAAK,CAAC,CAAC;AAAA,EAC9E,OAAO;AACL,YAAQ,IAAI,qBAAqB,IAAI,IAAI,KAAK,KAAK,OAAO,IAAI,GAAG,IAAI;AAAA,EACvE;AACF;;;ADpDO,IAAM,eAAN,MAAmB;AAAA;AAAA,EAOxB,YAAY,SAA8B;AAH1C,SAAQ,aAAa;AACrB,SAAQ,aAAa;AAGnB,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ;AACpB,SAAK,UAAU,IAAI,QAAQ;AAAA,MACzB,MAAM,QAAQ;AAAA,MACd,SAAS;AAAA,QACP,SAAS,KAAK;AAAA,QACd,YAAY,KAAK,aAAa;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,UACZ,IACA,WACA,UAAU,KAAK,YACH;AACZ,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,KAAK;AACZ,UAAI,WAAW,GAAG;AAChB,cAAM,GAAG,SAAS,iBAAiB,KAAK,UAAU,aAAa,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACjH,cAAM;AAAA,MACR;AAEA,YAAM,cAAc,eAAe,SAAS,IAAI,QAAQ,SAAS,YAAY;AAC7E,YAAM,gBAAgB,eAAe,UACnC,IAAI,QAAQ,SAAS,KAAK,KAC1B,IAAI,QAAQ,SAAS,KAAK,KAC1B,IAAI,QAAQ,SAAS,KAAK,KAC1B,IAAI,QAAQ,SAAS,KAAK;AAG5B,UAAI,eAAe,eAAe;AAChC,cAAM,QAAQ,KAAK,aAAa,KAAK,IAAI,GAAG,KAAK,aAAa,OAAO;AACrE,aAAK,GAAG,SAAS,wBAAwB,KAAK,UAAU,OAAO,gBAAgB;AAC/E,cAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,KAAK,CAAC;AACvD,eAAO,KAAK,UAAU,IAAI,WAAW,UAAU,CAAC;AAAA,MAClD;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,UAAwC;AAC3D,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,gBAAgB,QAAQ,EAAE;AAChC,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,MAAM,IAAI;AAAA,QACjD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,aAAa;AAAA,MACf,CAAC;AACD,aAAO,SAAS;AAAA,IAClB,GAAG,kBAAkB,QAAQ,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAqB,UAA8C;AACvE,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,0BAA0B,QAAQ,EAAE;AAC1C,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,MAAM,UAAU;AAAA,QACvD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,aAAa;AAAA,MACf,CAAC;AACD,aAAO,SAAS,KAAK,IAAI,WAAS;AAAA,QAChC,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,SAAS,KAAK;AAAA,QACd,OAAO,KAAK,SAAS;AAAA,QACrB,mBAAmB,KAAK,qBAAqB;AAAA,MAC/C,EAAE;AAAA,IACJ,GAAG,wBAAwB,QAAQ,GAAG;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,KAAa,MAAqC;AACtE,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,2BAA2B,IAAI,IAAI,GAAG,EAAE;AAC9C,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,MAAM,WAAW;AAAA,QACxD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,MAAM,QAAQ,SAAS,IAAI,GAAG;AAChC,cAAM,IAAI,MAAM,oCAAoC,IAAI,EAAE;AAAA,MAC5D;AAEA,YAAM,OAAO,SAAS;AAGtB,UAAI;AACJ,UAAI,KAAK,aAAa,UAAU;AAC9B,kBAAU,OAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,SAAS,OAAO;AAAA,MAChE,OAAO;AACL,kBAAU,KAAK;AAAA,MACjB;AAEA,aAAO;AAAA,QACL;AAAA,QACA,UAAU,KAAK;AAAA,QACf,KAAK,KAAK;AAAA,QACV,MAAM,KAAK;AAAA,MACb;AAAA,IACF,GAAG,mBAAmB,GAAG,KAAK,IAAI,GAAG;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAA8C;AAC9D,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,cAAc,QAAQ,MAAM,MAAM,sBAAsB,QAAQ,MAAM,EAAE;AAG9E,YAAM,aAAa,MAAM,KAAK,QAAQ,KAAK,MAAM,UAAU;AAAA,QACzD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,KAAK,QAAQ;AAAA,MACf,CAAC;AACD,YAAM,cAAc,WAAW,KAAK,OAAO,KAAK;AAGhD,YAAM,eAAe,QAAQ,MAAM,IAAI,OAAO,SAAS;AACrD,cAAM,eAAe,MAAM,KAAK,QAAQ,KAAK,IAAI,WAAW;AAAA,UAC1D,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,UACX,SAAS,OAAO,KAAK,KAAK,SAAS,OAAO,EAAE,SAAS,QAAQ;AAAA,UAC7D,UAAU;AAAA,QACZ,CAAC;AACD,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,KAAK,aAAa,KAAK;AAAA,UACvB,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAED,YAAM,YAAY,MAAM,QAAQ,IAAI,YAAY;AAGhD,YAAM,eAAe,MAAM,KAAK,QAAQ,KAAK,IAAI,WAAW;AAAA,QAC1D,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,WAAW;AAAA,QACX,MAAM;AAAA,MACR,CAAC;AAGD,YAAM,iBAAiB,MAAM,KAAK,QAAQ,KAAK,IAAI,aAAa;AAAA,QAC9D,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,SAAS,QAAQ;AAAA,QACjB,MAAM,aAAa,KAAK;AAAA,QACxB,SAAS,CAAC,QAAQ,OAAO;AAAA,MAC3B,CAAC;AAGD,YAAM,KAAK,QAAQ,KAAK,IAAI,UAAU;AAAA,QACpC,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,KAAK,SAAS,QAAQ,MAAM;AAAA,QAC5B,KAAK,eAAe,KAAK;AAAA,MAC3B,CAAC;AAED,aAAO,eAAe,KAAK;AAAA,IAC7B,GAAG,eAAe,QAAQ,MAAM,MAAM,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,YAAoB,SAAkC;AACvE,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,mBAAmB,UAAU,SAAS,OAAO,EAAE;AAGrD,YAAM,kBAAkB,MAAM,KAAK,QAAQ,KAAK,IAAI,OAAO;AAAA,QACzD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,KAAK,QAAQ,WAAW,OAAO,IAAI,UAAU,SAAS,OAAO;AAAA,MAC/D,CAAC;AACD,YAAM,UAAU,gBAAgB,KAAK,OAAO;AAG5C,YAAM,KAAK,QAAQ,KAAK,IAAI,UAAU;AAAA,QACpC,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,KAAK,cAAc,UAAU;AAAA,QAC7B,KAAK;AAAA,MACP,CAAC;AAED,aAAO;AAAA,IACT,GAAG,gBAAgB,UAAU,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBACJ,OACA,MACA,MACA,MACsB;AACtB,WAAO,KAAK,UAAU,YAAY;AAChC,YAAM,gBAAgB,IAAI,OAAO,IAAI,EAAE;AAEvC,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,MAAM,OAAO;AAAA,QACpD,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO,SAAS;AAAA,IAClB,GAAG,qBAAqB,IAAI,OAAO,IAAI,GAAG;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,UAAkB,MAA6B;AAC7D,UAAM,KAAK,UAAU,YAAY;AAC/B,YAAM,0BAA0B,QAAQ,EAAE;AAC1C,YAAM,KAAK,QAAQ,KAAK,OAAO,cAAc;AAAA,QAC3C,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,cAAc;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACH,GAAG,aAAa,QAAQ,GAAG;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,KAAa,MAAgC;AAC5D,WAAO,KAAK,UAAU,YAAY;AAChC,UAAI;AACF,cAAM,KAAK,QAAQ,KAAK,MAAM,WAAW;AAAA,UACvC,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,UACX;AAAA,UACA;AAAA,QACF,CAAC;AACD,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,YAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,KAAK,GAAG;AACvD,iBAAO;AAAA,QACT;AACA,cAAM;AAAA,MACR;AAAA,IACF,GAAG,cAAc,GAAG,KAAK,IAAI,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAA8D;AAClE,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,UAAU,IAAI;AACvD,WAAO;AAAA,MACL,WAAW,SAAS,KAAK,KAAK;AAAA,MAC9B,OAAO,SAAS,KAAK,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;;;AExSA,SAAS,mBAAmB;AAC5B,SAAS,cAAc;;;ACDvB,SAAS,SAAS;AAEX,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,QAAQ,EAAE,OAAO;AAAA,EACjB,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,KAAK,CAAC,UAAU,aAAa,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC7D,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAM,EAAE,SAAS;AAAA,EACxD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC/C,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClD,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxD,WAAW,EAAE,KAAK,CAAC,QAAQ,QAAQ,CAAC;AAAA,EACpC,cAAc,EAAE,KAAK,CAAC,YAAY,YAAY,CAAC,EAAE,QAAQ,UAAU;AAAA,EACnE,eAAe,EAAE,OAAO,EAAE,QAAQ,WAAW;AAAA,EAC7C,iBAAiB,EAAE,OAAO,EAAE,QAAQ,WAAW;AAAA,EAC/C,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,WAAW,YAAY,WAAW,UAAU,CAAC;AAAA,EAC3F,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,gBAAgB,gBAAgB,gBAAgB,gBAAgB,oBAAoB,CAAC;AAAA,EACnI,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE;AAAA,EACjD,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC1C,gBAAgB,EAAE,KAAK,CAAC,UAAU,WAAW,CAAC,EAAE,QAAQ,QAAQ;AAAA,EAChE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC1C,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAClC,CAAC;;;ADhBD,eAAsB,gBAAgB,WAAqC;AACzE,QAAM,kBAAkB,MAAM,OAAO,gBAAgB;AAAA,IACnD,KAAK,aAAa,QAAQ,IAAI;AAAA,EAChC,CAAC;AAED,MAAI,iBAAiB;AACnB,UAAM,EAAE,SAAAC,SAAQ,IAAI,MAAM,OAAO,MAAM;AACvC,WAAOA,SAAQ,eAAe;AAAA,EAChC;AAEA,SAAO,aAAa,QAAQ,IAAI;AAClC;AAKA,eAAsB,aAAqC;AACzD,QAAM,WAAW,YAAY,WAAW;AAAA,IACtC,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,OAAO,OAAO,aAAqB;AAGjC,YAAI;AACF,gBAAM,eAAe,MAAM,OAAO;AAClC,iBAAO,aAAa,WAAW,aAAa,UAAU;AAAA,QACxD,SAAS,KAAK;AACZ,gBAAM,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC7F,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI;AACF,UAAM,SAAS,MAAM,SAAS,OAAO;AAErC,QAAI,SAA+B,CAAC;AAEpC,QAAI,QAAQ,QAAQ;AAClB,eAAS,OAAO;AAAA,IAClB;AAGA,QAAI,CAAC,UAAU,OAAO,UAAU,SAAS,cAAc,GAAG;AACxD,YAAM,kBAAkB,MAAM,OAAO,cAAc;AACnD,UAAI,iBAAiB;AACnB,cAAM,EAAE,cAAAC,cAAa,IAAI,MAAM,OAAO,IAAI;AAC1C,YAAI;AACF,gBAAM,MAAM,KAAK,MAAMA,cAAa,iBAAiB,OAAO,CAAC;AAC7D,cAAI,IAAI,WAAW;AACjB,qBAAS,EAAE,GAAG,QAAQ,GAAG,IAAI,UAAU;AAAA,UACzC;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,OAAO,UAAU,QAAQ,IAAI,iBAAiB;AACjD,aAAO,SAAS,QAAQ,IAAI;AAAA,IAC9B;AAEA,QAAI,CAAC,OAAO,eAAe,QAAQ,IAAI,cAAc;AACnD,aAAO,cAAc,QAAQ,IAAI;AAAA,IACnC;AAEA,WAAO,oBAAoB,MAAM,MAAM;AAAA,EACzC,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,QAAQ,GAAG;AAC1D;AAAA,QACE;AAAA,MAGF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;;;AEvFA,SAAS,iBAAiB,OAA2B;AACnD,QAAM,QAAoB,CAAC;AAC3B,QAAM,QAAQ,MAAM,MAAM,IAAI;AAE9B,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,QAAQ;AACvB,UAAM,OAAO,MAAM,CAAC;AAGpB,UAAM,YAAY,KAAK,MAAM,6CAA6C;AAC1E,QAAI,WAAW;AACb,YAAM,WAAW,SAAS,UAAU,CAAC,GAAG,EAAE;AAC1C,YAAM,WAAW,SAAS,UAAU,CAAC,KAAK,KAAK,EAAE;AACjD,YAAM,WAAW,SAAS,UAAU,CAAC,GAAG,EAAE;AAC1C,YAAM,WAAW,SAAS,UAAU,CAAC,KAAK,KAAK,EAAE;AAEjD,YAAM,YAAsB,CAAC;AAC7B;AAGA,aAAO,IAAI,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,WAAW,IAAI,GAAG;AACrD,kBAAU,KAAK,MAAM,CAAC,CAAC;AACvB;AAAA,MACF;AAEA,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH,OAAO;AACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,qBAAqB,OAAyF;AACrH,QAAM,SAA+E,CAAC;AAEtF,aAAW,QAAQ,OAAO;AACxB,QAAI,UAAU,KAAK;AACnB,QAAI,UAAU,KAAK;AAEnB,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAAG;AAEnD,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,KAAK;AAAA,UACL,MAAM;AAAA,QACR,CAAC;AACD;AAAA,MACF,WAAW,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAAG;AAE1D,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,KAAK;AAAA,UACL,MAAM;AAAA,QACR,CAAC;AACD;AAAA,MACF,WAAW,CAAC,KAAK,WAAW,IAAI,GAAG;AAEjC;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO,YAAY,MAAM;AAC3B;AASA,SAAS,YACP,QACsE;AACtE,MAAI,OAAO,WAAW;AAAG,WAAO,CAAC;AAEjC,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3D,QAAM,SAA+E,CAAC;AAEtF,MAAI,UAAU,OAAO,CAAC;AAEtB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,OAAO,OAAO,CAAC;AAGrB,QAAI,KAAK,SAAS,QAAQ,MAAM,KAAK,KAAK,SAAS,QAAQ,MAAM;AAC/D,gBAAU;AAAA,QACR,OAAO,QAAQ;AAAA,QACf,KAAK,KAAK,IAAI,QAAQ,KAAK,KAAK,GAAG;AAAA,QACnC,MAAM,QAAQ;AAAA,MAChB;AAAA,IACF,OAAO;AACL,aAAO,KAAK,OAAO;AACnB,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,KAAK,OAAO;AACnB,SAAO;AACT;AAKO,SAAS,sBAAsB,OAAsC;AAC1E,QAAM,QAAoB,CAAC;AAE3B,aAAW,QAAQ,OAAO;AAExB,QAAI,CAAC,KAAK,SAAS,MAAM,oBAAoB,GAAG;AAC9C;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,OAAO;AAEf,YAAM,KAAK;AAAA,QACT,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,OAAO,CAAC;AAAA,QACR,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,MAClB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,QAAQ,iBAAiB,KAAK,KAAK;AAEzC,UAAM,KAAK;AAAA,MACT,UAAU,KAAK;AAAA,MACf,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,IAClB,CAAC;AAED,UAAM,UAAU,MAAM,MAAM,gBAAgB,KAAK,QAAQ,EAAE;AAAA,EAC7D;AAEA,SAAO;AACT;AAcO,SAAS,iBACd,MACA,aACsE;AACtE,MAAI,KAAK,WAAW,SAAS;AAC3B,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AAEA,UAAM,YAAY,YAAY,MAAM,IAAI,EAAE;AAC1C,WAAO,CAAC,EAAE,OAAO,GAAG,KAAK,WAAW,MAAM,WAAW,CAAC;AAAA,EACxD;AAEA,MAAI,KAAK,WAAW,WAAW;AAE7B,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,qBAAqB,KAAK,KAAK;AACxC;;;ACtMA,YAAY,QAAQ;AAepB,SAAS,iBAAiB,YAA2C;AACnE,QAAM,YAA4B,CAAC;AAEnC,WAAS,MAAM,MAAe;AAE5B,QAAO,yBAAsB,IAAI,GAAG;AAElC,YAAM,aAAa,KAAK,WAAW;AAAA,QAAK,OACtC,EAAE,SAAY,cAAW,iBAAiB,EAAE,SAAY,cAAW;AAAA,MACrE;AAEA,UAAI,KAAK,MAAM;AACb,kBAAU,KAAK;AAAA,UACb,MAAM,KAAK,KAAK;AAAA,UAChB,MAAM;AAAA,UACN,OAAO,KAAK,SAAS,UAAU;AAAA,UAC/B,KAAK,KAAK,OAAO;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH,WAAW,YAAY;AAErB,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO,KAAK,SAAS,UAAU;AAAA,UAC/B,KAAK,KAAK,OAAO;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAIA,QAAO,sBAAmB,IAAI,KAAK,KAAK,mBAAmB,SAAY,wBAAqB,KAAK,UAAU,GAAG;AAC5G,YAAM,OAAO,KAAK;AAClB,YAAM,OAAO,KAAK,OAAO,KAAK,KAAK,OAAO;AAC1C,gBAAU,KAAK;AAAA,QACb;AAAA,QACA,MAAM;AAAA,QACN,OAAO,KAAK,SAAS,UAAU;AAAA,QAC/B,KAAK,KAAK,OAAO;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAO,uBAAoB,IAAI,KAAK,KAAK,QAAW,gBAAa,KAAK,IAAI,GAAG;AAC3E,gBAAU,KAAK;AAAA,QACb,MAAM,KAAK,KAAK;AAAA,QAChB,MAAM;AAAA,QACN,OAAO,KAAK,SAAS,UAAU;AAAA,QAC/B,KAAK,KAAK,OAAO;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAO,uBAAoB,IAAI,GAAG;AAChC,iBAAW,eAAe,KAAK,gBAAgB,cAAc;AAC3D,YAAI,YAAY,aAAa;AAE3B,cAAO,mBAAgB,YAAY,WAAW,GAAG;AAC/C,gBAAO,gBAAa,YAAY,IAAI,GAAG;AACrC,wBAAU,KAAK;AAAA,gBACb,MAAM,YAAY,KAAK;AAAA,gBACvB,MAAM;AAAA,gBACN,OAAO,YAAY,SAAS,UAAU;AAAA,gBACtC,KAAK,YAAY,OAAO;AAAA,gBACxB,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF,WAEY,wBAAqB,YAAY,WAAW,GAAG;AACzD,kBAAM,WAAW,YAAY;AAE7B,kBAAM,OAAO,SAAS,OAClB,SAAS,KAAK,OACX,gBAAa,YAAY,IAAI,IAChC,YAAY,KAAK,OACjB;AAEJ,gBAAI,SAAS,aAAa;AACxB,wBAAU,KAAK;AAAA,gBACb;AAAA,gBACA,MAAM;AAAA,gBACN,OAAO,YAAY,SAAS,UAAU;AAAA,gBACtC,KAAK,YAAY,OAAO;AAAA,gBACxB,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAO,wBAAqB,IAAI,KAAQ,gBAAa,KAAK,IAAI,GAAG;AAC/D,UAAO,wBAAqB,KAAK,WAAW,KAAQ,mBAAgB,KAAK,WAAW,GAAG;AACrF,kBAAU,KAAK;AAAA,UACb,MAAM,KAAK,KAAK;AAAA,UAChB,MAAM;AAAA,UACN,OAAO,KAAK,SAAS,UAAU;AAAA,UAC/B,KAAK,KAAK,OAAO;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,IAAG,gBAAa,MAAM,KAAK;AAAA,EAC7B;AAEA,QAAM,UAAU;AAChB,SAAO;AACT;AASA,SAAS,cAAc,QAAgB,UAA0B;AAC/D,SAAO,OAAO,UAAU,GAAG,QAAQ,EAAE,MAAM,IAAI,EAAE;AACnD;AASA,SAAS,wBACP,MACA,eACA,QACS;AACT,QAAM,gBAAgB,cAAc,QAAQ,KAAK,KAAK;AACtD,QAAM,cAAc,cAAc,QAAQ,KAAK,GAAG;AAGlD,QAAM,iBAAiB,cAAc,OAAO,OAAK,EAAE,SAAS,UAAU;AAEtE,aAAW,SAAS,gBAAgB;AAElC,QACG,MAAM,SAAS,iBAAiB,MAAM,SAAS,eAC/C,MAAM,OAAO,iBAAiB,MAAM,OAAO,eAC3C,MAAM,SAAS,iBAAiB,MAAM,OAAO,aAC9C;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,QAAgB,MAA4B;AACtE,SAAO,OAAO,UAAU,KAAK,OAAO,KAAK,GAAG;AAC9C;AAKA,SAAS,eAAe,QAAgB,MAAoB,cAAsC;AAChG,QAAM,gBAAgB,cAAc,QAAQ,KAAK,KAAK;AACtD,QAAM,cAAc,cAAc,QAAQ,KAAK,GAAG;AAGlD,QAAM,eAAe,aAClB,OAAO,OAAK,cAAc,QAAQ,EAAE,GAAG,IAAI,aAAa,EACxD,KAAK,CAAC,GAAG,MAAM,cAAc,QAAQ,EAAE,GAAG,IAAI,cAAc,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;AAEhF,QAAM,eAAe,eACjB,cAAc,QAAQ,aAAa,KAAK,IACxC,KAAK,IAAI,GAAG,gBAAgB,EAAE;AAElC,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,QAAM,eAAe,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC;AAElE,SAAO,aAAa,KAAK,IAAI;AAC/B;AAKA,eAAe,eACb,UACA,KACA,cACA,eAC6B;AAC7B,QAAM,MAAM,SAAS,UAAU,GAAG,SAAS,YAAY,GAAG,CAAC;AAC3D,QAAM,WAAW,SAAS,UAAU,SAAS,YAAY,GAAG,IAAI,CAAC,EAAE,QAAQ,sBAAsB,EAAE;AAGnG,MAAI;AACJ,MAAI,SAAS,SAAS,MAAM;AAAG,UAAM;AAAA,WAC5B,SAAS,SAAS,MAAM;AAAG,UAAM;AAAA,WACjC,SAAS,SAAS,KAAK;AAAG,UAAM;AAAA;AACpC,UAAM;AAGX,QAAM,eACJ,QAAQ,QAAQ,CAAC,aAAa,aAAa,YAAY,UAAU,IACjE,QAAQ,QAAQ,CAAC,aAAa,aAAa,YAAY,UAAU,IACjE,QAAQ,OAAO,CAAC,YAAY,UAAU,IACtC,CAAC,YAAY,UAAU;AAGzB,QAAM,YAAY;AAAA;AAAA,IAEhB,GAAG,aAAa,IAAI,aAAW,GAAG,GAAG,IAAI,QAAQ,GAAG,OAAO,EAAE;AAAA;AAAA,IAE7D,GAAG,aAAa,IAAI,aAAW,GAAG,GAAG,cAAc,QAAQ,GAAG,OAAO,EAAE;AAAA;AAAA,IAEvE,GAAG,aAAa,IAAI,aAAW,GAAG,aAAa,IAAI,QAAQ,GAAG,OAAO,EAAE;AAAA;AAAA,IAEvE,GAAG,aAAa,IAAI,aAAW,GAAG,aAAa,GAAG,GAAG,IAAI,QAAQ,GAAG,OAAO,EAAE;AAAA;AAAA,IAE7E,GAAG,aAAa,IAAI,aAAW,aAAa,QAAQ,GAAG,OAAO,EAAE;AAAA,EAClE;AAGA,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS,MAAM,aAAa,WAAW,KAAK,QAAQ;AAC1D,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,YACpB,UACA,SACA,eACA,KACA,cACA,eACuB;AACvB,QAAM,aAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACG,gBAAa;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,YAAY,iBAAiB,UAAU;AAG7C,QAAM,mBAAmB,MAAM,eAAe,UAAU,KAAK,cAAc,aAAa;AAExF,QAAM,UAAwB,CAAC;AAE/B,aAAW,QAAQ,WAAW;AAC5B,QAAI,wBAAwB,MAAM,eAAe,OAAO,GAAG;AACzD,YAAM,YAAY,cAAc,SAAS,KAAK,KAAK;AACnD,YAAM,UAAU,cAAc,SAAS,KAAK,GAAG;AAE/C,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,cAAc,KAAK;AAAA,QACnB,cAAc,KAAK;AAAA,QACnB;AAAA,QACA;AAAA,QACA,MAAM,mBAAmB,SAAS,IAAI;AAAA,QACtC,SAAS,eAAe,SAAS,MAAM,SAAS;AAAA,QAChD;AAAA,QACA,eAAe,cAAc;AAAA,UAC3B,OAAK,EAAE,SAAS,aAAa,EAAE,OAAO;AAAA,QACxC;AAAA,MACF,CAAC;AAED,YAAM,sBAAsB,KAAK,IAAI,KAAK,KAAK,IAAI,QAAQ,QAAQ,GAAG,mBAAmB,qBAAqB,gBAAgB,KAAK,EAAE,EAAE;AAAA,IACzI;AAAA,EACF;AAEA,SAAO;AACT;;;ACpSA,eAAsB,mBACpB,OACA,cACA,WACA,QACuB;AACvB,OAAK,aAAa,MAAM,MAAM,2BAA2B;AAGzD,QAAM,QAAQ,sBAAsB,KAAK;AAGzC,QAAM,gBAAgB,MAAM,OAAO,UAAQ;AAEzC,UAAM,iBAAiB,OAAO,gBAAgB,KAAK,aAAW;AAC5D,YAAM,QAAQ,IAAI,OAAO,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC/E,aAAO,MAAM,KAAK,KAAK,QAAQ;AAAA,IACjC,CAAC;AAED,QAAI,CAAC;AAAgB,aAAO;AAG5B,UAAM,iBAAiB,OAAO,gBAAgB,KAAK,aAAW;AAC5D,YAAM,QAAQ,IAAI,OAAO,QAAQ,QAAQ,SAAS,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC/E,aAAO,MAAM,KAAK,KAAK,QAAQ;AAAA,IACjC,CAAC;AAED,WAAO,CAAC;AAAA,EACV,CAAC;AAED,QAAM,eAAe,cAAc,MAAM,iCAAiC;AAE1E,QAAM,UAAwB,CAAC;AAG/B,aAAW,QAAQ,eAAe;AAChC,QAAI,KAAK,WAAW,WAAW;AAE7B;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,eAAe,MAAM,aAAa,gBAAgB,WAAW,KAAK,QAAQ;AAGhF,YAAM,gBAAgB,iBAAiB,MAAM,aAAa,OAAO;AAEjE,UAAI,cAAc,WAAW,GAAG;AAE9B;AAAA,MACF;AAGA,YAAM,SAAS,cAAc,IAAI,QAAM;AAAA,QACrC,OAAO,EAAE;AAAA,QACT,KAAK,EAAE;AAAA,QACP,MAAM,EAAE;AAAA,MACV,EAAE;AAGF,YAAM,cAAc,MAAM;AAAA,QACxB,KAAK;AAAA,QACL,aAAa;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT;AAEA,cAAQ,KAAK,GAAG,WAAW;AAE3B,UAAI,YAAY,SAAS,GAAG;AAC1B,aAAK,SAAS,YAAY,MAAM,sBAAsB,KAAK,QAAQ,EAAE;AAAA,MACvE;AAAA,IACF,SAASC,QAAO;AACd,YAAM,qBAAqB,KAAK,QAAQ,KAAKA,kBAAiB,QAAQA,OAAM,UAAU,OAAOA,MAAK,CAAC,EAAE;AAAA,IAEvG;AAAA,EACF;AAEA,OAAK,aAAa,QAAQ,MAAM,uBAAuB;AACvD,SAAO;AACT;;;ACvFO,IAAe,kBAAf,MAAsD;AAAA,EAK3D,YAAY,QAAgB,OAAe,gBAA8C;AACvF,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,iBAAiB;AAAA,MACpB,aAAa,gBAAgB,eAAe;AAAA,MAC5C,WAAW,gBAAgB,aAAa;AAAA,MACxC,eAAe,gBAAgB,iBAAiB,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EAIU,aAAa,SAA4D;AACjF,WAAO;AAAA,MACL,aAAa,SAAS,eAAe,KAAK,eAAe;AAAA,MACzD,WAAW,SAAS,aAAa,KAAK,eAAe;AAAA,MACrD,eAAe,SAAS,iBAAiB,KAAK,eAAe;AAAA,IAC/D;AAAA,EACF;AAAA,EAEU,iBAAuB;AAC/B,QAAI,CAAC,KAAK,UAAU,KAAK,OAAO,KAAK,EAAE,WAAW,GAAG;AACnD,YAAM,0CAA0C;AAChD,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAAA,EACF;AAAA,EAEU,SAAS,OAA6B,WAAyB;AACvE,QAAI,OAAO;AACT;AAAA,QACE,GAAG,SAAS,WAAW,MAAM,eAAe,SAAS,oBACvC,MAAM,gBAAgB,SAAS,iBAAiB,MAAM,oBAAoB,SAAS;AAAA,MACnG;AAAA,IACF;AAAA,EACF;AACF;;;ACxBO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAA7C;AAAA;AACL,SAAQ,UAAU;AAAA;AAAA,EAElB,MAAM,SAAS,UAAwB,SAAoD;AACzF,SAAK,eAAe;AACpB,UAAM,gBAAgB,KAAK,aAAa,OAAO;AAE/C,UAAM,cAAc;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,UAAU,SAAS,IAAI,CAAC,SAAS;AAAA,QAC/B,MAAM,IAAI;AAAA,QACV,SAAS,IAAI;AAAA,MACf,EAAE;AAAA,MACF,aAAa,cAAc;AAAA,MAC3B,YAAY,cAAc;AAAA,MAC1B,GAAI,cAAc,cAAc,SAAS,KAAK,EAAE,MAAM,cAAc,cAAc;AAAA,IACpF;AAEA,UAAM,kCAAkC,KAAK,KAAK,EAAE;AAEpD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,QAC/D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,KAAK,MAAM;AAAA,QACtC;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS,EAAE;AAClF,cAAM,IAAI,MAAM,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAC/E;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,UAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC9C,cAAM,gCAAgC;AACtC,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAEA,YAAM,UAAU,KAAK,QAAQ,CAAC,GAAG,SAAS,WAAW;AACrD,YAAM,QAAQ,KAAK,QACf;AAAA,QACE,cAAc,KAAK,MAAM;AAAA,QACzB,kBAAkB,KAAK,MAAM;AAAA,QAC7B,aAAa,KAAK,MAAM;AAAA,MAC1B,IACA;AAEJ,WAAK,SAAS,OAAO,QAAQ;AAE7B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,OAAO;AACxB,cAAM,8BAA8B,IAAI,OAAO,EAAE;AACjD,cAAM;AAAA,MACR;AACA,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAAA,EACF;AACF;;;ACxDO,IAAM,oBAAN,cAAgC,gBAAgB;AAAA,EAAhD;AAAA;AACL,SAAQ,UAAU;AAAA;AAAA,EAElB,MAAM,SAAS,UAAwB,SAAoD;AACzF,SAAK,eAAe;AACpB,UAAM,gBAAgB,KAAK,aAAa,OAAO;AAG/C,UAAM,gBAAgB,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG,WAAW;AAC5E,UAAM,uBAAuB,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAEvE,UAAM,cAAgC;AAAA,MACpC,OAAO,KAAK;AAAA,MACZ,YAAY,cAAc;AAAA,MAC1B,aAAa,cAAc;AAAA,MAC3B,UAAU,qBAAqB,IAAI,CAAC,SAAS;AAAA,QAC3C,MAAM,IAAI,SAAS,cAAc,cAAc;AAAA,QAC/C,SAAS,IAAI;AAAA,MACf,EAAE;AAAA,MACF,GAAI,iBAAiB,EAAE,QAAQ,cAAc;AAAA,MAC7C,GAAI,cAAc,cAAc,SAAS,KAAK,EAAE,gBAAgB,cAAc,cAAc;AAAA,IAC9F;AAEA,UAAM,qCAAqC,KAAK,KAAK,EAAE;AAEvD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,aAAa;AAAA,QACvD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,aAAa,KAAK;AAAA,UAClB,qBAAqB;AAAA,QACvB;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS,EAAE;AACrF,cAAM,IAAI,MAAM,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAClF;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,UAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC9C,cAAM,mCAAmC;AACzC,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,YAAM,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACzD,YAAM,QAAQ,KAAK,QACf;AAAA,QACE,cAAc,KAAK,MAAM;AAAA,QACzB,kBAAkB,KAAK,MAAM;AAAA,QAC7B,aAAa,KAAK,MAAM,eAAe,KAAK,MAAM;AAAA,MACpD,IACA;AAEJ,WAAK,SAAS,OAAO,WAAW;AAEhC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,OAAO;AACxB,cAAM,iCAAiC,IAAI,OAAO,EAAE;AACpD,cAAM;AAAA,MACR;AACA,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAAA,EACF;AACF;;;ACxDO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAA7C;AAAA;AACL,SAAQ,UAAU;AAAA;AAAA,EAElB,MAAM,SAAS,UAAwB,SAAoD;AACzF,SAAK,eAAe;AACpB,UAAM,gBAAgB,KAAK,aAAa,OAAO;AAG/C,UAAM,oBAAoB,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG;AACrE,UAAM,uBAAuB,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAEvE,UAAM,WAA4B,qBAAqB,IAAI,CAAC,SAAS;AAAA,MACnE,MAAO,IAAI,SAAS,cAAc,UAAU;AAAA,MAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,QAAQ,CAAC;AAAA,IAC/B,EAAE;AAEF,UAAM,mBAA2C;AAAA,MAC/C,aAAa,cAAc;AAAA,MAC3B,iBAAiB,cAAc;AAAA,MAC/B,GAAI,cAAc,cAAc,SAAS,KAAK,EAAE,eAAe,cAAc,cAAc;AAAA,IAC7F;AAEA,UAAM,cAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA,GAAI,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM,kBAAkB,CAAC,EAAE,EAAE;AAAA,IACzF;AAEA,UAAM,kCAAkC,KAAK,KAAK,EAAE;AAEpD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,IAAI,KAAK,KAAK,wBAAwB,KAAK,MAAM,IAAI;AAAA,QAC/F,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS,EAAE;AAClF,cAAM,IAAI,MAAM,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAC/E;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,UAAI,CAAC,KAAK,cAAc,KAAK,WAAW,WAAW,GAAG;AACpD,cAAM,mCAAmC;AACzC,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,YAAM,UAAU,KAAK,WAAW,CAAC,GAAG,SAAS,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK;AACrF,YAAM,QAAQ,KAAK,gBACf;AAAA,QACE,cAAc,KAAK,cAAc;AAAA,QACjC,kBAAkB,KAAK,cAAc;AAAA,QACrC,aAAa,KAAK,cAAc;AAAA,MAClC,IACA;AAEJ,WAAK,SAAS,OAAO,QAAQ;AAE7B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,OAAO;AACxB,cAAM,8BAA8B,IAAI,OAAO,EAAE;AACjD,cAAM;AAAA,MACR;AACA,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAAA,EACF;AACF;;;AC9GO,SAAS,kBACd,QACa;AACb,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,QAAQ,OAAO,SAAS,gBAAgB,QAAQ;AACtD,QAAM,iBAAiB,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI;AAE5E,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,IAAI,eAAe,OAAO,QAAQ,OAAO,cAAc;AAAA,IAChE,KAAK;AACH,aAAO,IAAI,kBAAkB,OAAO,QAAQ,OAAO,cAAc;AAAA,IACnE,KAAK;AACH,aAAO,IAAI,eAAe,OAAO,QAAQ,OAAO,cAAc;AAAA,IAChE;AACE,YAAM,yBAAyB,QAAQ,EAAE;AACzC,YAAM,IAAI,MAAM,yBAAyB,QAAQ,EAAE;AAAA,EACvD;AACF;AAKA,SAAS,gBAAgB,UAAqD;AAC5E,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;ACzCO,SAAS,0BAA0B,SAA8C;AACtF,QAAM,EAAE,QAAQ,WAAW,kBAAkB,iBAAiB,IAAI;AAElE,QAAM,eAAe,kBAAkB,SAAS;AAChD,QAAM,aAAa,gBAAgB,QAAQ,WAAW,kBAAkB,gBAAgB;AAExF,SAAO;AAAA,IACL,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,IACxC,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,EACtC;AACF;AAEA,SAAS,kBAAkB,WAAsC;AAC/D,QAAM,gBAAgB,cAAc,SAAS,SAAS;AACtD,QAAM,kBAAkB,cAAc,SAAS,iDAAiD;AAEhG,SAAO,qBAAqB,aAAa;AAAA;AAAA;AAAA,iCAGV,aAAa;AAAA,SACrC,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAUmB,aAAa;AAAA;AAAA;AAAA;AAAA,EAIpD,aAAa;AAAA,EACb,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWjB;AAEA,SAAS,gBACP,QACA,WACA,kBACA,kBACQ;AACR,MAAI,SAAS,YAAY,SAAS;AAAA;AAAA;AAElC,YAAU,SAAS,OAAO,QAAQ;AAAA;AAClC,YAAU,aAAa,OAAO,YAAY;AAAA;AAC1C,YAAU,SAAS,OAAO,YAAY;AAAA;AAAA;AAEtC,YAAU;AAAA;AAAA,EAAqC,OAAO,IAAI;AAAA;AAAA;AAAA;AAE1D,MAAI,OAAO,SAAS;AAClB,cAAU;AAAA;AAAA,EAAkD,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA,EAC5E;AAEA,MAAI,oBAAoB,iBAAiB,SAAS,GAAG;AACnD,cAAU;AAAA;AACV,qBAAiB,QAAQ,CAAC,OAAO;AAC/B,gBAAU;AAAA,EAAK,GAAG,IAAI;AAAA;AAAA,EAAwB,GAAG,IAAI;AAAA;AAAA;AAAA,IACvD,CAAC;AACD,cAAU;AAAA,EACZ;AAEA,MAAI,kBAAkB;AACpB,cAAU;AAAA;AAAA,EAA0E,gBAAgB;AAAA;AAAA;AAAA;AACpG,cAAU;AAAA;AAAA;AAAA,EACZ;AAEA,YAAU,yCAAyC,OAAO,YAAY;AAAA;AACtE,YAAU;AAAA;AACV,YAAU;AAAA;AACV,YAAU;AAAA;AACV,YAAU;AAAA;AACV,YAAU;AAAA;AAAA;AAEV,YAAU;AAEV,SAAO;AACT;;;ACzFO,SAAS,mBAAmB,SAAuC;AACxE,QAAM,EAAE,UAAU,cAAc,YAAY,cAAc,WAAW,SAAS,YAAY,IAAI;AAE9F,QAAM,eAAeC,mBAAkB,WAAW,SAAS,WAAW;AACtE,QAAM,aAAaC,iBAAgB,UAAU,cAAc,YAAY,cAAc,WAAW,OAAO;AAEvG,SAAO;AAAA,IACL,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,IACxC,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,EACtC;AACF;AAEA,SAASD,mBAAkB,WAA8B,SAAiB,aAA6B;AACrG,QAAM,gBAAgB,cAAc,SAAS,SAAS;AAEtD,SAAO,qBAAqB,aAAa;AAAA;AAAA;AAAA,wBAGnB,OAAO,OAAO,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAOjC,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS7B;AAEA,SAASC,iBACP,UACA,cACA,YACA,cACA,WACA,SACQ;AACR,MAAI,SAAS,iBAAiB,SAAS;AAAA;AAAA;AAEvC,YAAU;AAAA;AAAA,EAA8C,YAAY;AAAA;AAAA;AAAA;AAEpE,YAAU;AAAA;AAAA,EAAyC,QAAQ;AAAA;AAAA;AAAA;AAE3D,YAAU;AAAA;AAAA,EAA2B,YAAY;AAAA;AAAA;AAAA;AAEjD,MAAI,YAAY;AACd,cAAU;AAAA;AAAA,EAAyB,UAAU;AAAA;AAAA;AAAA;AAAA,EAC/C;AAEA,MAAI,UAAU,GAAG;AACf,cAAU,6BAA6B,OAAO;AAAA;AAAA;AAAA,EAChD;AAEA,YAAU;AAEV,SAAO;AACT;;;AC5DO,SAAS,cAAc,UAA0B;AAEtD,MAAI,OAAO,SAAS,KAAK;AAGzB,QAAM,iBAAiB;AACvB,QAAM,QAAQ,KAAK,MAAM,cAAc;AAEvC,MAAI,OAAO;AACT,WAAO,MAAM,CAAC,EAAE,KAAK;AAAA,EACvB,OAAO;AAEL,UAAM,kBAAkB;AACxB,UAAM,gBAAgB,MAAM,KAAK,KAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,cAAc,SAAS,GAAG;AAE5B,aAAO,cAAc,OAAO,CAAC,SAASC,WAAU;AAC9C,eAAOA,OAAM,CAAC,EAAE,SAAS,QAAQ,SAASA,OAAM,CAAC,IAAI;AAAA,MACvD,GAAG,EAAE;AACL,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAIA,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,WAAW,qBAAqB;AACzC,QAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,aAAO,KAAK,QAAQ,SAAS,EAAE,EAAE,KAAK;AAEtC,YAAM,iBAAiB,KAAK,MAAM,gBAAgB;AAClD,UAAI,gBAAgB;AAClB,eAAO,eAAe,CAAC;AACvB,eAAO,KAAK,QAAQ,8CAA8C,EAAE,EAAE,QAAQ,WAAW,EAAE,EAAE,KAAK;AAAA,MACpG;AAAA,IACF;AAAA,EACF;AAGA,SAAO,KAAK,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,WAAW,EAAE,EAAE,KAAK;AAEpE,MAAI,CAAC,MAAM;AACT,SAAK,+CAA+C;AACpD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,0BAA0B,MAAc,WAGtD;AACA,QAAM,SAAmB,CAAC;AAG1B,MAAI,CAAC,KAAK,SAAS,UAAU,KAAK,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,SAAS,OAAO,GAAG;AAClF,WAAO,KAAK,2CAA2C;AAAA,EACzD;AAGA,MAAI,cAAc,QAAQ;AACxB,QAAI,CAAC,KAAK,SAAS,aAAa,KAAK,CAAC,KAAK,SAAS,aAAa,KAAK,CAAC,KAAK,SAAS,UAAU,GAAG;AAEhG,UAAI,CAAC,KAAK,SAAS,UAAU,KAAK,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,SAAS,MAAM,GAAG;AAChF,eAAO,KAAK,6BAA6B;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,WAAW,cAAc,UAAU;AACjC,QAAI,CAAC,KAAK,SAAS,eAAe,KAAK,CAAC,KAAK,SAAS,eAAe,GAAG;AACtE,aAAO,KAAK,uBAAuB;AAAA,IACrC;AAAA,EACF;AAGA,MAAI,KAAK,KAAK,EAAE,SAAS,IAAI;AAC3B,WAAO,KAAK,sCAAsC;AAAA,EACpD;AAGA,MAAI,CAAC,KAAK,MAAM,yBAAyB,GAAG;AAC1C,WAAO,KAAK,gDAAgD;AAAA,EAC9D;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,EACF;AACF;;;AC/FO,IAAM,gBAAN,MAAoB;AAAA,EAIzB,YACE,QAIA;AACA,SAAK,WAAW,kBAAkB,MAAM;AACxC,SAAK,SAAS;AAAA,MACZ,gBAAgB,OAAO;AAAA,MACvB,aAAa,OAAO;AAAA,MACpB,gBAAgB,OAAO;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAA+D;AAChF,UAAM,EAAE,QAAQ,UAAU,IAAI;AAE9B,SAAK,cAAc,SAAS,cAAc,OAAO,YAAY,OAAO,OAAO,QAAQ,EAAE;AAErF,QAAI;AACF,YAAM,WAAW,0BAA0B,OAAO;AAClD,YAAM,8CAA8C,OAAO,YAAY,EAAE;AAEzE,YAAM,WAAW,MAAM,KAAK,SAAS,SAAS,UAAU;AAAA,QACtD,aAAa,KAAK,OAAO,eAAe;AAAA;AAAA,QACxC,WAAW;AAAA,MACb,CAAC;AAED,YAAM,WAAW,cAAc,SAAS,OAAO;AAC/C,YAAM,aAAa,0BAA0B,UAAU,SAAS;AAEhE,UAAI,CAAC,WAAW,OAAO;AACrB,aAAK,qCAAqC,OAAO,YAAY,KAAK,WAAW,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,MAElG;AAEA,YAAM,wCAAwC,OAAO,YAAY,EAAE;AAEnE,aAAO;AAAA,QACL;AAAA,QACA,aAAa,SAAS,YAAY,WAAW,qCAAqC;AAAA,QAClF,OAAO,SAAS;AAAA,MAClB;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,+BAA+B,OAAO,YAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC/G,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,SAAwD;AACpE,UAAM,EAAE,WAAW,QAAQ,IAAI;AAE/B,SAAK,wBAAwB,OAAO,IAAI,KAAK,OAAO,cAAc,GAAG;AAErE,QAAI;AACF,YAAM,WAAW,mBAAmB,OAAO;AAC3C,YAAM,4CAA4C,OAAO,GAAG;AAE5D,YAAM,WAAW,MAAM,KAAK,SAAS,SAAS,UAAU;AAAA,QACtD,aAAa,KAAK,OAAO,kBAAkB;AAAA;AAAA,QAC3C,WAAW;AAAA,MACb,CAAC;AAED,YAAM,YAAY,cAAc,SAAS,OAAO;AAChD,YAAM,aAAa,0BAA0B,WAAW,SAAS;AAEjE,UAAI,CAAC,WAAW,OAAO;AACrB,aAAK,wCAAwC,WAAW,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,MAC7E;AAEA,YAAM,mDAAmD,OAAO,GAAG;AAEnE,aAAO;AAAA,QACL,UAAU;AAAA,QACV,aAAa,4BAA4B,OAAO;AAAA,QAChD,OAAO,SAAS;AAAA,MAClB;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,+BAA+B,OAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACpG,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,wBAAwB,UAA8F;AAC1H,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,SAAS,SAAS,UAAU;AAAA,QACtD,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AACD,aAAO,SAAS;AAAA,IAClB,SAAS,KAAK;AACZ,YAAM,wCAAwC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAChG,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AClHO,SAAS,gBACd,QACA,QACQ;AACR,QAAM,aAAa,OAAO;AAC1B,QAAM,iBAAiB,WAAW,YAAY,GAAG;AACjD,QAAM,MAAM,kBAAkB,IAAI,WAAW,UAAU,GAAG,cAAc,IAAI;AAC5E,QAAM,WAAW,WAAW,UAAU,iBAAiB,CAAC,EAAE,QAAQ,sBAAsB,EAAE;AAG1F,MAAI;AACJ,MAAI,WAAW,SAAS,MAAM;AAAG,UAAM;AAAA,WAC9B,WAAW,SAAS,MAAM;AAAG,UAAM;AAAA,WACnC,WAAW,SAAS,KAAK;AAAG,UAAM;AAAA;AACtC,UAAM;AAGX,QAAM,UAAU,QAAQ,SAAS,QAAQ,OAAO,OAAO;AAEvD,MAAI,OAAO,iBAAiB,cAAc;AAExC,WAAO,MAAM,GAAG,GAAG,IAAI,QAAQ,SAAS,OAAO,KAAK,GAAG,QAAQ,SAAS,OAAO;AAAA,EACjF,OAAO;AAGL,UAAM,eAAe,OAAO,gBAAgB,QAAQ,KAAK,QAAQ;AACjE,WAAO,GAAG,OAAO,aAAa,IAAI,YAAY;AAAA,EAChD;AACF;;;AClCA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAOd,SAAS,qBAAqB,aAAqC;AAExE,MAAI,WAAW,KAAK,aAAa,gBAAgB,CAAC,GAAG;AACnD,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,KAAK,aAAa,WAAW,CAAC,GAAG;AAC9C,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,KAAK,aAAa,mBAAmB,CAAC,GAAG;AACtD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;;;ACxBA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAI1B,IAAM,YAAY,UAAU,IAAI;AAiBzB,IAAM,aAAN,MAAuC;AAAA,EAC5C,MAAM,SAAS,SAAgD;AAC7D,UAAM,EAAE,WAAW,gBAAgB,aAAa,SAAS,IAAI;AAE7D,UAAM,0BAA0B,UAAU,MAAM,UAAU;AAG1D,UAAM,eAAe,UAAU,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG;AAC1D,UAAM,eAAe,WAAW,wCAAwC;AACxE,UAAM,MAAM,GAAG,cAAc,mBAAmB,YAAY,IAAI,YAAY;AAE5E,QAAI;AACF,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU,KAAK;AAAA,QAC9C,KAAK;AAAA,QACL,WAAW,KAAK,OAAO;AAAA;AAAA,MACzB,CAAC;AAED,UAAI,UAAU,CAAC,OAAO,SAAS,MAAM,KAAK,CAAC,OAAO,SAAS,MAAM,GAAG;AAClE,cAAM,gBAAgB,MAAM,EAAE;AAAA,MAChC;AAEA,YAAM,SAAS,KAAK,MAAM,MAAM;AAEhC,aAAO,UAAU,IAAI,CAAC,UAAU,UAAU;AACxC,cAAM,aAAa,OAAO,YAAY,KAAK,KAAK,OAAO,YAAY,CAAC;AACpE,cAAM,WAA0B,CAAC;AAEjC,YAAI,YAAY;AACd,qBAAW,aAAa,WAAW,kBAAkB;AACnD,gBAAI,UAAU,WAAW,YAAY,UAAU,gBAAgB,SAAS,GAAG;AACzE,oBAAM,iBAAiB,UAAU,gBAAgB,CAAC;AAClD,uBAAS,KAAK;AAAA,gBACZ,UAAU,UAAU;AAAA,gBACpB,SAAS;AAAA,gBACT,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,SAAS,OAAO,mBAAmB;AAAA,UACnC;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,OAAO,OAAO;AAAA,UACd,UAAU;AAAA;AAAA,UACV;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAc;AAErB,UAAI,OAAO,OAAO,QAAQ,YAAY,YAAY,KAAK;AACrD,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,IAAI,MAAgB;AAC9C,iBAAO,UAAU,IAAI,CAAC,aAAa;AACjC,kBAAM,WAA0B,CAAC;AAEjC,uBAAW,cAAc,OAAO,aAAa;AAC3C,yBAAW,aAAa,WAAW,kBAAkB;AACnD,oBAAI,UAAU,WAAW,YAAY,UAAU,gBAAgB,SAAS,GAAG;AACzE,2BAAS,KAAK;AAAA,oBACZ,UAAU,UAAU;AAAA,oBACpB,SAAS,UAAU,gBAAgB,CAAC;AAAA,oBACpC,OAAO,UAAU,gBAAgB,CAAC;AAAA,kBACpC,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,YACF;AAEA,mBAAO;AAAA,cACL,SAAS,OAAO,mBAAmB;AAAA,cACnC;AAAA,cACA,QAAQ,OAAO;AAAA,cACf,QAAQ,OAAO;AAAA,cACf,OAAO,OAAO;AAAA,cACd,UAAU;AAAA,cACV;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH,SAAS,UAAU;AACjB,gBAAM,gCAAgC,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ,CAAC,EAAE;AACvG,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACvF,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AChHA,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAI1B,IAAMC,aAAYC,WAAUC,KAAI;AAiBzB,IAAM,eAAN,MAAyC;AAAA,EAC9C,MAAM,SAAS,SAAgD;AAC7D,UAAM,EAAE,WAAW,gBAAgB,aAAa,SAAS,IAAI;AAE7D,UAAM,4BAA4B,UAAU,MAAM,UAAU;AAG5D,UAAM,eAAe,UAAU,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG;AAC1D,UAAM,eAAe,WAAW,eAAe;AAC/C,UAAM,MAAM,GAAG,cAAc,4BAA4B,YAAY,IAAI,YAAY;AAErF,QAAI;AACF,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAMF,WAAU,KAAK;AAAA,QAC9C,KAAK;AAAA,QACL,WAAW,KAAK,OAAO;AAAA;AAAA,MACzB,CAAC;AAED,UAAI,UAAU,CAAC,OAAO,SAAS,MAAM,KAAK,CAAC,OAAO,SAAS,MAAM,GAAG;AAClE,cAAM,kBAAkB,MAAM,EAAE;AAAA,MAClC;AAGA,YAAM,QAAQ,OAAO,KAAK,EAAE,MAAM,IAAI;AACtC,YAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AAEvC,UAAI,CAAC,YAAY,CAAC,SAAS,WAAW,GAAG,GAAG;AAC1C,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,YAAM,SAAS,KAAK,MAAM,QAAQ;AAElC,aAAO,UAAU,IAAI,CAAC,UAAU,UAAU;AACxC,cAAM,aAAa,OAAO,YAAY,KAAK,KAAK,OAAO,YAAY,CAAC;AACpE,cAAM,WAA0B,CAAC;AAEjC,YAAI,YAAY;AACd,qBAAW,aAAa,WAAW,kBAAkB;AACnD,gBAAI,UAAU,WAAW,YAAY,UAAU,gBAAgB,SAAS,GAAG;AACzE,oBAAM,iBAAiB,UAAU,gBAAgB,CAAC;AAClD,uBAAS,KAAK;AAAA,gBACZ,UAAU,UAAU;AAAA,gBACpB,SAAS;AAAA,gBACT,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,SAAS,OAAO,mBAAmB;AAAA,UACnC;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,OAAO,OAAO;AAAA,UACd,UAAU;AAAA;AAAA,UACV;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAc;AAErB,UAAI,OAAO,OAAO,QAAQ,YAAY,YAAY,KAAK;AACrD,YAAI;AACF,gBAAM,QAAS,IAAI,OAAkB,KAAK,EAAE,MAAM,IAAI;AACtD,gBAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AAEvC,cAAI,YAAY,SAAS,WAAW,GAAG,GAAG;AACxC,kBAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,mBAAO,UAAU,IAAI,CAAC,aAAa;AACjC,oBAAM,WAA0B,CAAC;AAEjC,yBAAW,cAAc,OAAO,aAAa;AAC3C,2BAAW,aAAa,WAAW,kBAAkB;AACnD,sBAAI,UAAU,WAAW,YAAY,UAAU,gBAAgB,SAAS,GAAG;AACzE,6BAAS,KAAK;AAAA,sBACZ,UAAU,UAAU;AAAA,sBACpB,SAAS,UAAU,gBAAgB,CAAC;AAAA,sBACpC,OAAO,UAAU,gBAAgB,CAAC;AAAA,oBACpC,CAAC;AAAA,kBACH;AAAA,gBACF;AAAA,cACF;AAEA,qBAAO;AAAA,gBACL,SAAS,OAAO,mBAAmB;AAAA,gBACnC;AAAA,gBACA,QAAQ,OAAO;AAAA,gBACf,QAAQ,OAAO;AAAA,gBACf,OAAO,OAAO;AAAA,gBACd,UAAU;AAAA,gBACV;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,SAAS,UAAU;AACjB,gBAAM,kCAAkC,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ,CAAC,EAAE;AACzG,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACzF,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACtHO,SAAS,iBAAiB,WAA0C;AACzE,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,IAAI,WAAW;AAAA,IACxB,KAAK;AACH,aAAO,IAAI,aAAa;AAAA,IAC1B;AACE,YAAM,IAAI,MAAM,+BAA+B,SAAS,EAAE;AAAA,EAC9D;AACF;;;AChBA,SAAS,eAAe,WAAW,cAAAG,mBAAkB;AACrD,SAAS,SAAS,QAAAC,aAAY;AAMvB,SAAS,eACd,WACA,aACU;AACV,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,cAAc,QAAQ,KAAK,UAAU,QAAQ,GAAG;AAC1D,UAAM,WAAWC,MAAK,aAAa,YAAY;AAC/C,UAAM,MAAM,QAAQ,QAAQ;AAG5B,QAAI,CAACC,YAAW,GAAG,GAAG;AACpB,gBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,YAAM,sBAAsB,GAAG,EAAE;AAAA,IACnC;AAGA,kBAAc,UAAU,SAAS,SAAS,OAAO;AACjD,iBAAa,KAAK,YAAY;AAC9B,UAAM,oBAAoB,YAAY,EAAE;AAAA,EAC1C;AAEA,SAAO;AACT;;;AC9BA,SAAS,cAAc,cAAAC,mBAAkB;AACzC,SAAS,QAAAC,aAAY;AAkCrB,SAAS,kBAAkB,MAAwC;AACjE,QAAM,QAAwB,CAAC;AAC/B,MAAI,kBAAkB;AACtB,MAAI,oBAAoB;AACxB,MAAI,gBAAgB;AACpB,MAAI,kBAAkB;AACtB,MAAI,iBAAiB;AACrB,MAAI,mBAAmB;AACvB,MAAI,aAAa;AACjB,MAAI,eAAe;AAEnB,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,IAAI,GAAG;AAEvD,UAAM,kBAAkB,OAAO,OAAO,SAAS,UAAU;AACzD,UAAM,eAAe,OAAO,OAAO,SAAS,QAAQ;AACpD,UAAM,iBAAiB,OAAO,OAAO,SAAS,SAAS;AACvD,UAAM,aAAa,OAAO,OAAO,SAAS,KAAK;AAE/C,UAAM,iBAAiB;AAAA,MACrB,OAAO,gBAAgB;AAAA,MACvB,SAAS,gBAAgB,OAAO,OAAK,IAAI,CAAC,EAAE;AAAA,MAC5C,YAAY,gBAAgB,SAAS,IAChC,gBAAgB,OAAO,OAAK,IAAI,CAAC,EAAE,SAAS,gBAAgB,SAAU,MACvE;AAAA,IACN;AAEA,UAAM,eAAe;AAAA,MACnB,OAAO,aAAa;AAAA,MACpB,SAAS,aAAa,OAAO,OAAK,IAAI,CAAC,EAAE;AAAA,MACzC,YAAY,aAAa,SAAS,IAC7B,aAAa,OAAO,OAAK,IAAI,CAAC,EAAE,SAAS,aAAa,SAAU,MACjE;AAAA,IACN;AAEA,UAAM,gBAAgB;AAAA,MACpB,OAAO,eAAe;AAAA,MACtB,SAAS,eAAe,OAAO,OAAK,IAAI,CAAC,EAAE;AAAA,MAC3C,YAAY,eAAe,SAAS,IAC/B,eAAe,OAAO,OAAK,IAAI,CAAC,EAAE,SAAS,eAAe,SAAU,MACrE;AAAA,IACN;AAEA,UAAM,YAAY;AAAA,MAChB,OAAO,WAAW;AAAA,MAClB,SAAS,WAAW,OAAO,OAAK,IAAI,CAAC,EAAE;AAAA,MACvC,YAAY,WAAW,SAAS,IAC3B,WAAW,OAAO,OAAK,IAAI,CAAC,EAAE,SAAS,WAAW,SAAU,MAC7D;AAAA,IACN;AAEA,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,WAAW;AAAA,QACX,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAGD,uBAAmB,eAAe;AAClC,yBAAqB,eAAe;AACpC,qBAAiB,aAAa;AAC9B,uBAAmB,aAAa;AAChC,sBAAkB,cAAc;AAChC,wBAAoB,cAAc;AAClC,kBAAc,UAAU;AACxB,oBAAgB,UAAU;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL,YAAY;AAAA,QACV,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,kBAAkB,IAAK,oBAAoB,kBAAmB,MAAM;AAAA,MAClF;AAAA,MACA,UAAU;AAAA,QACR,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,gBAAgB,IAAK,kBAAkB,gBAAiB,MAAM;AAAA,MAC5E;AAAA,MACA,WAAW;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,iBAAiB,IAAK,mBAAmB,iBAAkB,MAAM;AAAA,MAC/E;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,aAAa,IAAK,eAAe,aAAc,MAAM;AAAA,MACnE;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,oBAAoB,MAA0C;AAErE,SAAO,kBAAkB,IAAwB;AACnD;AAKO,SAAS,mBACd,aACA,WACuB;AAEvB,QAAM,eAAeC,MAAK,aAAa,YAAY,qBAAqB;AAExE,MAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,UAAM,8BAA8B,YAAY,EAAE;AAClD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,cAAc,OAAO;AAClD,UAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,QAAI,cAAc,QAAQ;AACxB,aAAO,kBAAkB,IAAwB;AAAA,IACnD,OAAO;AACL,aAAO,oBAAoB,IAA0B;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,SAAK,mCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC1F,WAAO;AAAA,EACT;AACF;;;AClKO,SAAS,2BACd,gBACA,aACA,iBACA,eACc;AACd,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWrB,QAAM,aAAa,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAClE,QAAM,cAAc,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACpE,QAAM,cAAc,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AAEpE,QAAM,aAAa;AAAA;AAAA;AAAA,WAGV,eAAe,MAAM,MAAM,WAAW,QAAQ,CAAC,CAAC,MAAM,eAAe,MAAM,MAAM,OAAO,IAAI,eAAe,MAAM,MAAM,KAAK;AAAA,cACzH,eAAe,MAAM,SAAS,WAAW,QAAQ,CAAC,CAAC,MAAM,eAAe,MAAM,SAAS,OAAO,IAAI,eAAe,MAAM,SAAS,KAAK;AAAA,eACpI,eAAe,MAAM,UAAU,WAAW,QAAQ,CAAC,CAAC,MAAM,eAAe,MAAM,UAAU,OAAO,IAAI,eAAe,MAAM,UAAU,KAAK;AAAA,gBACvI,eAAe,MAAM,WAAW,WAAW,QAAQ,CAAC,CAAC,MAAM,eAAe,MAAM,WAAW,OAAO,IAAI,eAAe,MAAM,WAAW,KAAK;AAAA;AAAA;AAAA,iBAG1I,UAAU;AAAA,YACf,WAAW;AAAA,YACX,WAAW;AAAA;AAAA;AAAA,EAGrB,gBAAgB,SAAS,IAAI,gBAAgB,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,IAAI,MAAM;AAAA;AAAA,EAEnF,gBAAgB;AAAA,WACP,cAAc,QAAQ,IAAI,MAAM,EAAE,GAAG,cAAc,MAAM,QAAQ,CAAC,CAAC;AAAA,cAChE,cAAc,WAAW,IAAI,MAAM,EAAE,GAAG,cAAc,SAAS,QAAQ,CAAC,CAAC;AAAA,eACxE,cAAc,YAAY,IAAI,MAAM,EAAE,GAAG,cAAc,UAAU,QAAQ,CAAC,CAAC;AAAA,gBAC1E,cAAc,aAAa,IAAI,MAAM,EAAE,GAAG,cAAc,WAAW,QAAQ,CAAC,CAAC;AAAA,IACzF,EAAE;AAAA;AAAA;AAIJ,SAAO;AAAA,IACL,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,IACxC,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,EACtC;AACF;;;ACTA,eAAsB,eAAe,SAA6D;AAEhG,QAAM,SAAS,MAAM,WAAW;AAGhC,aAAW,MAAM;AAEjB,OAAK,kBAAkB,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,IAAI,QAAQ,IAAI,EAAE;AAG9E,QAAM,cAAc,QAAQ,eAAe,OAAO;AAClD,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,oFAAoF;AAAA,EACtG;AAEA,QAAM,eAAe,IAAI,aAAa;AAAA,IACpC,OAAO;AAAA,IACP,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,EAChB,CAAC;AAGD,QAAM,KAAK,MAAM,aAAa,eAAe,QAAQ,QAAQ;AAE7D,MAAI,GAAG,UAAU,QAAQ;AACvB,SAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG,KAAK,4BAA4B;AACvE,WAAO;AAAA,MACL,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,WAAW,CAAC;AAAA,MACZ,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAEA,OAAK,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,GAAG;AAGzD,QAAM,UAAU,MAAM,aAAa,qBAAqB,QAAQ,QAAQ;AAExE,MAAI,QAAQ,WAAW,GAAG;AACxB,SAAK,6BAA6B;AAClC,WAAO;AAAA,MACL,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,WAAW,CAAC;AAAA,MACZ,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAEA,OAAK,SAAS,QAAQ,MAAM,wBAAwB;AAGpD,QAAM,YAAY,GAAG,KAAK;AAC1B,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,SAAK,wCAAwC;AAC7C,WAAO;AAAA,MACL,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,WAAW,CAAC;AAAA,MACZ,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAGA,QAAM,iBAAiB,QAAQ,MAAM,GAAG,OAAO,aAAa;AAE5D,MAAI,QAAQ,SAAS,eAAe,QAAQ;AAC1C,SAAK,eAAe,OAAO,aAAa,wBAAwB,QAAQ,MAAM,GAAG;AAAA,EACnF;AAEA,OAAK,SAAS,eAAe,MAAM,iBAAiB;AAGpD,QAAM,YAAY,OAAO;AACzB,OAAK,yBAAyB,SAAS,EAAE;AAGzC,QAAM,gBAAgB,IAAI,cAAc;AAAA,IACtC,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,gBAAgB,OAAO;AAAA,IACvB,aAAa,OAAO;AAAA,IACpB,gBAAgB,OAAO;AAAA,EACzB,CAAC;AAGD,MAAI,YAAY,oBAAI,IAAoD;AACxE,QAAM,SAAmD,CAAC;AAC1D,MAAI,iBAAiB;AACrB,MAAI,cAAc;AAElB,WAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,UAAM,SAAS,eAAe,CAAC;AAC/B,aAAS,IAAI,GAAG,eAAe,QAAQ,uBAAuB,OAAO,YAAY,EAAE;AAEnF,QAAI;AAEF,YAAM,eAAe,gBAAgB,QAAQ,MAAM;AAGnD,UAAI;AACJ,YAAM,iBAAiB,MAAM,aAAa,WAAW,WAAW,YAAY;AAE5E,UAAI,gBAAgB;AAClB,YAAI;AACF,gBAAM,eAAe,MAAM,aAAa,gBAAgB,WAAW,YAAY;AAC/E,6BAAmB,aAAa;AAChC,gBAAM,+BAA+B,YAAY,EAAE;AAAA,QACrD,SAAS,KAAK;AACZ,gBAAM,sCAAsC,YAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,QACjH;AAAA,MACF,OAAO;AACL,cAAM,4BAA4B,YAAY,wBAAwB;AAAA,MACxE;AAGA,YAAM,SAAS,MAAM,cAAc,aAAa;AAAA,QAC9C,QAAQ;AAAA,UACN,UAAU,OAAO;AAAA,UACjB,cAAc,OAAO;AAAA,UACrB,cAAc,OAAO;AAAA,UACrB,MAAM,OAAO;AAAA,UACb,SAAS,OAAO;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAGD,UAAI,CAAC,UAAU,IAAI,YAAY,GAAG;AAEhC,cAAM,cAAc,oBAAoB;AACxC,kBAAU,IAAI,cAAc,EAAE,SAAS,aAAa,SAAS,CAAC,EAAE,CAAC;AAAA,MACnE;AAEA,YAAM,WAAW,UAAU,IAAI,YAAY;AAG3C,UAAI,SAAS,SAAS;AACpB,iBAAS,WAAW,SAAS,OAAO;AAAA,MACtC,OAAO;AACL,iBAAS,UAAU,OAAO;AAAA,MAC5B;AAEA,eAAS,QAAQ,KAAK,OAAO,YAAY;AACzC;AAEA,WAAK,6BAAwB,OAAO,YAAY,EAAE;AAAA,IACpD,SAAS,KAAK;AACZ,YAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpE,YAAM,sCAAiC,OAAO,YAAY,KAAK,YAAY,EAAE;AAC7E,aAAO,KAAK;AAAA,QACV,QAAQ,GAAG,OAAO,QAAQ,IAAI,OAAO,YAAY;AAAA,QACjD,OAAO;AAAA,MACT,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,cAAc,MAAM,gBAAgB;AAC1C,QAAM,iBAAiB,qBAAqB,WAAW;AACvD,OAAK,6BAA6B,cAAc,EAAE;AAElD,MAAI,UAAU,OAAO,GAAG;AAEtB,UAAM,eAAe,eAAe,WAAW,WAAW;AAC1D,SAAK,SAAS,aAAa,MAAM,uBAAuB;AAGxD,UAAM,aAAa,iBAAiB,SAAS;AAC7C,UAAM,iBAAiB,MAAM;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAGA,gBAAY;AAAA,EACd;AAGA,QAAM,UAAiC;AAAA,IACrC,kBAAkB,eAAe;AAAA,IACjC;AAAA,IACA;AAAA,IACA,WAAW,MAAM,KAAK,UAAU,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO;AAAA,MAChE;AAAA,MACA,SAAS,KAAK;AAAA,IAChB,EAAE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,UAAU,OAAO,GAAG;AACtB,UAAM,aAAa,iBAAiB,SAAS;AAC7C,UAAM,eAAe,MAAM,KAAK,UAAU,KAAK,CAAC;AAEhD,SAAK,gCAAgC;AACrC,UAAM,mBAAmB,MAAM,WAAW,SAAS;AAAA,MACjD,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAGD,UAAM,iBAAiB,mBAAmB,aAAa,SAAS;AAChE,QAAI,gBAAgB;AAClB,WAAK,uBAAuB,eAAe,MAAM,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS;AACrF,cAAQ,iBAAiB;AACzB,cAAQ,cAAc;AAAA,IACxB,OAAO;AACL,WAAK,gCAAgC;AAAA,IACvC;AAAA,EACF;AAGA,MAAI,OAAO,oBAAoB,UAAU,OAAO,GAAG;AACjD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,MAAM,KAAK,UAAU,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO;AAAA,QACrD;AAAA,QACA,SAAS,KAAK;AAAA,MAChB,EAAE;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,kBAAkB;AAC3B,UAAM,cAAc,cAAc,QAAQ,UAAU,SAAS,WAAW,aAAa;AAAA,EACvF;AAEA,UAAQ,cAAc,cAAc,uBAAuB,WAAW,SAAS;AAE/E,SAAO;AACT;AAKA,eAAe,eACb,YACA,WACA,eACA,WACA,gBACA,aACA,eACA,gBAC8D;AAC9D,QAAM,mBAAmB,IAAI,IAAI,SAAS;AAC1C,MAAI,UAAU;AAEd,SAAO,UAAU,gBAAgB;AAC/B,SAAK,0BAA0B,UAAU,CAAC,IAAI,cAAc,GAAG;AAG/D,UAAM,UAAU,MAAM,WAAW,SAAS;AAAA,MACxC,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAGD,UAAM,YAAY,QAAQ,MAAM,OAAK,EAAE,OAAO;AAC9C,QAAI,WAAW;AACb,cAAQ,+BAA+B,UAAU,CAAC,EAAE;AACpD,aAAO;AAAA,IACT;AAGA,UAAM,WAA4D,CAAC;AACnE,eAAW,UAAU,SAAS;AAC5B,UAAI,CAAC,OAAO,WAAW,OAAO,SAAS,SAAS,GAAG;AACjD,iBAAS,KAAK,EAAE,UAAU,OAAO,UAAU,OAAO,CAAC;AAAA,MACrD;AAAA,IACF;AAEA,SAAK,SAAS,SAAS,MAAM,4CAA4C;AAGzE,QAAI,WAAW;AACf,eAAW,EAAE,UAAU,OAAO,KAAK,UAAU;AAC3C,YAAM,kBAAkB,iBAAiB,IAAI,QAAQ,GAAG;AACxD,UAAI,CAAC,iBAAiB;AACpB,aAAK,yCAAyC,QAAQ,EAAE;AACxD;AAAA,MACF;AAIA,YAAM,eAAe,OAAO,SAAS,CAAC;AACtC,UAAI,CAAC;AAAc;AAEnB,UAAI;AAGF,cAAM,cAAc,MAAM,cAAc,QAAQ;AAAA,UAC9C,UAAU;AAAA,UACV,cAAc,aAAa;AAAA,UAC3B,YAAY,aAAa;AAAA,UACzB,cAAc;AAAA;AAAA,UACd;AAAA,UACA,SAAS,UAAU;AAAA,UACnB,aAAa;AAAA,QACf,CAAC;AAGD,yBAAiB,IAAI,UAAU;AAAA,UAC7B,SAAS,YAAY;AAAA,UACrB,SAAS,iBAAiB,IAAI,QAAQ,GAAG,WAAW,CAAC;AAAA,QACvD,CAAC;AAGD,cAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,IAAI;AAC3C,cAAM,EAAE,MAAAC,MAAK,IAAI,MAAM,OAAO,MAAM;AACpC,QAAAD,eAAcC,MAAK,aAAa,QAAQ,GAAG,YAAY,UAAU,OAAO;AAExE,mBAAW;AACX,aAAK,2BAAsB,QAAQ,EAAE;AAAA,MACvC,SAAS,KAAK;AACZ,cAAM,2BAA2B,QAAQ,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MAClG;AAAA,IACF;AAEA,QAAI,CAAC,UAAU;AACb,WAAK,8CAA8C,UAAU,CAAC,EAAE;AAChE;AAAA,IACF;AAEA;AAAA,EACF;AAEA,MAAI,WAAW,gBAAgB;AAC7B,SAAK,iCAAiC,cAAc,oCAAoC;AAAA,EAC1F;AAEA,SAAO;AACT;AAKA,eAAe,YACb,cACA,IACA,WACA,QACA,SACe;AACf,OAAK,cAAc,UAAU,MAAM,eAAe;AAElD,MAAI;AACF,QAAI,OAAO,mBAAmB,aAAa;AAEzC,YAAM,aAAa,uBAAuB,GAAG,MAAM;AACnD,YAAM,UAAU,MAAM,aAAa,aAAa,YAAY,GAAG,KAAK,GAAG;AAGvE,YAAM,aAAa,YAAY;AAAA,QAC7B,OAAO,UAAU,IAAI,WAAS;AAAA,UAC5B,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,QAChB,EAAE;AAAA,QACF,SAAS,gCAAgC,GAAG,MAAM;AAAA;AAAA,YAAiB,QAAQ,cAAc,gBAAgB,QAAQ,gBAAgB;AAAA,QACjI,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAGD,YAAM,SAAS,MAAM,aAAa;AAAA,QAChC,gCAAgC,GAAG,MAAM;AAAA,QACzC,+DAA+D,GAAG,MAAM;AAAA;AAAA,IACnE,QAAQ,cAAc;AAAA,IACtB,QAAQ,gBAAgB;AAAA,IACxB,UAAU,MAAM;AAAA,QACrB;AAAA,QACA,GAAG,KAAK;AAAA,MACV;AAEA,cAAQ,eAAe,OAAO,MAAM,uBAAuB;AAAA,IAC7D,OAAO;AAEL,YAAM,aAAa,YAAY;AAAA,QAC7B,OAAO,UAAU,IAAI,WAAS;AAAA,UAC5B,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,QAChB,EAAE;AAAA,QACF,SAAS;AAAA;AAAA,YAAqC,QAAQ,cAAc,gBAAgB,QAAQ,gBAAgB;AAAA,QAC5G,QAAQ,GAAG,KAAK;AAAA,QAChB,SAAS,GAAG,KAAK;AAAA,MACnB,CAAC;AAED,cAAQ,aAAa,UAAU,MAAM,oBAAoB,GAAG,KAAK,GAAG,EAAE;AAAA,IACxE;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACnF,UAAM;AAAA,EACR;AACF;AAKA,eAAe,cACb,cACA,UACA,SACA,WACA,eACe;AACf,MAAI,UAAU;AAAA;AAAA,iBAEC,SAAS;AAAA,yBACD,QAAQ,gBAAgB;AAAA,uBAC1B,QAAQ,cAAc;AAAA,gBAC7B,QAAQ,WAAW;AAAA;AAAA;AAAA,EAGjC,QAAQ,UAAU,SAAS,IACzB,QAAQ,UAAU,IAAI,OAAK,OAAO,EAAE,IAAI,OAAO,EAAE,QAAQ,MAAM,WAAW,EAAE,KAAK,IAAI,IACrF,yBACJ;AAAA;AAAA,EAEE,QAAQ,OAAO,SAAS,IACtB;AAAA,EAAe,QAAQ,OAAO,IAAI,OAAK,OAAO,EAAE,MAAM,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI,CAAC,KAClF,EACJ;AAGE,MAAI,QAAQ,kBAAkB,QAAQ,aAAa;AACjD,QAAI;AAEF,YAAM,kBAAkB,QAAQ,UAAU,QAAQ,OAAK,EAAE,OAAO;AAGhE,YAAM,WAAW;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,MACF;AAEA,YAAM,kBAAkB,MAAM,cAAc,wBAAwB,QAAQ;AAC5E,iBAAW;AAAA;AAAA;AAAA;AAAA,EAAiC,eAAe;AAAA,IAC7D,SAAS,KAAK;AACZ,WAAK,wCAAwC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAG/F,YAAM,MAAM,QAAQ,eAAe;AACnC,iBAAW;AAAA;AAAA;AAAA;AAAA,eACO,IAAI,MAAM,WAAW,QAAQ,CAAC,CAAC,MAAM,IAAI,MAAM,OAAO,IAAI,IAAI,MAAM,KAAK;AAAA,kBACtE,IAAI,SAAS,WAAW,QAAQ,CAAC,CAAC,MAAM,IAAI,SAAS,OAAO,IAAI,IAAI,SAAS,KAAK;AAAA,mBACjF,IAAI,UAAU,WAAW,QAAQ,CAAC,CAAC,MAAM,IAAI,UAAU,OAAO,IAAI,IAAI,UAAU,KAAK;AAAA,oBACpF,IAAI,WAAW,WAAW,QAAQ,CAAC,CAAC,MAAM,IAAI,WAAW,OAAO,IAAI,IAAI,WAAW,KAAK;AAAA,IACjH;AAAA,EACF;AAEA,aAAW;AAAA;AAAA;AAAA;AAEX,MAAI;AACF,UAAM,aAAa,UAAU,UAAU,OAAO;AAC9C,SAAK,gDAAgD;AAAA,EACvD,SAAS,KAAK;AACZ,SAAK,8BAA8B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EACvF;AACF;;;AzBtgBA,SAAS,gBAAgB,MAA+C;AACtE,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI,MAAM,8BAA8B,IAAI,yBAAyB;AAAA,EAC7E;AACA,SAAO,EAAE,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE;AAC3C;AAKA,eAAe,oBAAoB,aAAsE;AACvG,MAAI;AACF,UAAM,MAAM,UAAU,WAAW;AAGjC,QAAI,YAA2B;AAE/B,QAAI;AACF,kBAAY,MAAM,IAAI,WAAW,IAAI,EAAE,KAAK,aAAW;AACrD,cAAM,SAAS,QAAQ,KAAK,OAAK,EAAE,SAAS,QAAQ;AACpD,eAAO,QAAQ,MAAM,SAAS,QAAQ,MAAM,QAAQ;AAAA,MACtD,CAAC;AAED,UAAI,CAAC,WAAW;AACd,cAAM,UAAU,MAAM,IAAI,WAAW,IAAI;AACzC,YAAI,QAAQ,SAAS,GAAG;AACtB,sBAAY,QAAQ,CAAC,EAAE,MAAM,SAAS,QAAQ,CAAC,EAAE,MAAM,QAAQ;AAAA,QACjE;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AAGA,QAAI;AACF,YAAM,SAAS,YAAY,SAAS;AACpC,UAAI,OAAO,aAAa,cAAc;AACpC,eAAO;AAAA,UACL,OAAO,OAAO;AAAA,UACd,MAAM,OAAO,KAAK,QAAQ,UAAU,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF,QAAQ;AAEN,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,oCAAoC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC5F,WAAO;AAAA,EACT;AACF;AAKA,SAAS,gBAAgB,WAAmC;AAC1D,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,eAAeC,cAAa,WAAW,OAAO;AACpD,UAAM,QAAqB,KAAK,MAAM,YAAY;AAElD,QAAI,MAAM,cAAc,QAAQ;AAC9B,aAAO,MAAM,aAAa;AAAA,IAC5B;AAEA,QAAI,MAAM,QAAQ;AAChB,aAAO,MAAM;AAAA,IACf;AAEA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC7F,WAAO;AAAA,EACT;AACF;AAKA,eAAe,OAAsB;AACnC,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,YAAY,EACjB,YAAY,mDAAmD,EAC/D,QAAQ,OAAO,EACf,OAAO,iBAAiB,qBAAqB,EAC7C,OAAO,oBAAoB,kBAAkB,EAC7C,OAAO,mBAAmB,iBAAiB,EAC3C,OAAO,oBAAoB,4CAA4C,EACvE,MAAM,QAAQ,IAAI;AAErB,QAAM,UAAU,QAAQ,KAAK;AAG7B,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAW;AAAA,EAC5B,SAAS,KAAK;AAEZ,aAAS;AAAA,EACX;AAGA,QAAM,mBAAmB,QAAQ,IAAI;AACrC,QAAM,kBAAkB,QAAQ,IAAI;AACpC,QAAM,cAAc,QAAQ,SAAS,QAAQ,eAAe,QAAQ,IAAI;AACxE,QAAM,cAAc,QAAQ,IAAI;AAGhC,MAAI,QAA4B,QAAQ;AACxC,MAAI,OAA2B,QAAQ;AAGvC,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,QAAI,kBAAkB;AACpB,UAAI;AACF,cAAM,SAAS,gBAAgB,gBAAgB;AAC/C,gBAAQ,SAAS,OAAO;AACxB,eAAO,QAAQ,OAAO;AAAA,MACxB,SAAS,KAAK;AACZ,YAAI,CAAC,SAAS,CAAC,MAAM;AACnB,gBAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AACtD,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,YAAQ,SAAS,QAAQ;AACzB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAGA,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,UAAM,cAAc,MAAM,gBAAgB;AAC1C,UAAM,UAAU,MAAM,oBAAoB,WAAW;AACrD,QAAI,SAAS;AACX,cAAQ,SAAS,QAAQ;AACzB,aAAO,QAAQ,QAAQ;AACvB,YAAM,iCAAiC,KAAK,IAAI,IAAI,EAAE;AAAA,IACxD;AAAA,EACF;AAGA,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,UAAM,yCAAyC;AAC/C,UAAM,cAAc;AACpB,UAAM,6CAA6C;AACnD,UAAM,mCAAmC;AACzC,UAAM,2DAA2D;AACjE,UAAM,uDAAuD;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,aAAa;AAChB,UAAM,2BAA2B;AACjC,UAAM,cAAc;AACpB,UAAM,8BAA8B;AACpC,UAAM,uBAAuB;AAC7B,UAAM,+BAA+B;AACrC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,WAA0B;AAG9B,MAAI,QAAQ,IAAI;AACd,eAAW,SAAS,OAAO,QAAQ,EAAE,GAAG,EAAE;AAC1C,QAAI,MAAM,QAAQ,GAAG;AACnB,YAAM,sBAAsB,QAAQ,EAAE,EAAE;AACxC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,WAAW,aAAa;AACtB,UAAM,SAAS,SAAS,aAAa,EAAE;AACvC,QAAI,CAAC,MAAM,MAAM,GAAG;AAClB,iBAAW;AAAA,IACb;AAAA,EACF,WAAW,iBAAiB;AAC1B,eAAW,gBAAgB,eAAe;AAAA,EAC5C;AAEA,MAAI,CAAC,UAAU;AACb,UAAM,kCAAkC;AACxC,UAAM,cAAc;AACpB,UAAM,6BAA6B;AACnC,UAAM,4BAA4B;AAClC,UAAM,uDAAuD;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAA8B;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,OAAK,+BAA+B,QAAQ,OAAO,KAAK,IAAI,IAAI,EAAE;AAElE,MAAI;AACF,UAAM,UAAU,MAAM,eAAe,OAAO;AAG5C,QAAI,QAAQ,OAAO,SAAS,KAAK,QAAQ,cAAc,GAAG;AACxD,YAAM,0CAA0C,QAAQ,OAAO,MAAM,cAAc,QAAQ,WAAW,iBAAiB;AACvH,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,SAAK,2CAA2C,QAAQ,cAAc,oBAAoB;AAC1F,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,KAAK;AACZ,UAAM,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACxE,QAAI,eAAe,SAAS,IAAI,OAAO;AACrC,YAAM,IAAI,KAAK;AAAA,IACjB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAGA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,QAAM,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAC5E,UAAQ,KAAK,CAAC;AAChB,CAAC;",
6
6
  "names": ["readFileSync", "dirname", "readFileSync", "error", "buildSystemPrompt", "buildUserPrompt", "match", "exec", "promisify", "execAsync", "promisify", "exec", "existsSync", "join", "join", "existsSync", "existsSync", "join", "join", "existsSync", "writeFileSync", "join", "readFileSync"]
7
7
  }
@@ -1,7 +1,2 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CLI entry point for Kakarot CI
4
- * Parses CI environment variables and runs test generation
5
- */
6
1
  export {};
7
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kakarot-ci/core",
3
- "version": "0.4.2",
3
+ "version": "0.5.1",
4
4
  "description": "Core package for Kakarot CI - AI-powered unit test generation for pull requests",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",