{"version":3,"file":"index.cjs","sources":["../src/utils/ngram.ts","../src/utils/tokenization.ts","../src/metrics/bleu.ts","../src/utils/similarity.ts","../src/utils/tfidf.ts","../src/metrics/coherence.ts","../src/metrics/ter.ts","../src/telemetry.ts","../src/batch/concurrency-manager.ts","../src/batch/exporters/csv-exporter.ts","../src/batch/exporters/json-exporter.ts","../src/batch/parsers/csv-parser.ts","../src/batch/parsers/json-parser.ts","../src/batch/progress-tracker.ts","../src/batch/batch-evaluator.ts","../src/utils/template-engine.ts","../src/evaluators/evaluator.ts","../src/index.ts"],"sourcesContent":["export const generateNgrams = (tokens: string[], n: number): string[][] => {\n\tif (n <= 0 || tokens.length < n) {\n\t\treturn [];\n\t}\n\n\tconst ngrams: string[][] = [];\n\tfor (let i = 0; i <= tokens.length - n; i++) {\n\t\tngrams.push(tokens.slice(i, i + n));\n\t}\n\treturn ngrams;\n};\n\nexport const countNgrams = (ngrams: string[][]): Map<string, number> => {\n\tconst counts = new Map<string, number>();\n\n\tfor (const ngram of ngrams) {\n\t\tconst key = ngram.join(\" \");\n\t\tcounts.set(key, (counts.get(key) || 0) + 1);\n\t}\n\n\treturn counts;\n};\n\nexport const calculateNgramPrecision = (\n\tcandidateNgrams: string[][],\n\treferenceNgrams: string[][],\n): number => {\n\tif (candidateNgrams.length === 0) {\n\t\treturn 0;\n\t}\n\n\tconst candidateCounts = countNgrams(candidateNgrams);\n\tconst referenceCounts = countNgrams(referenceNgrams);\n\n\tlet clippedMatches = 0;\n\tlet totalCandidateNgrams = 0;\n\n\tfor (const [ngram, candidateCount] of candidateCounts) {\n\t\tconst referenceCount = referenceCounts.get(ngram) || 0;\n\t\tclippedMatches += Math.min(candidateCount, referenceCount);\n\t\ttotalCandidateNgrams += candidateCount;\n\t}\n\n\treturn totalCandidateNgrams > 0 ? clippedMatches / totalCandidateNgrams : 0;\n};\n","export const tokenizeWords = (text: string): string[] => {\n\treturn text\n\t\t.toLowerCase()\n\t\t.replace(/[.,!?;:()[\\]{}]/g, \" $& \")\n\t\t.split(/\\s+/)\n\t\t.filter((word) => word.length > 0);\n};\n\nexport const tokenizeSentences = (text: string): string[] => {\n\treturn text\n\t\t.split(/[.!?]+/)\n\t\t.map((s) => s.trim())\n\t\t.filter((s) => s.length > 0);\n};\n","import { calculateNgramPrecision, generateNgrams } from \"../utils/ngram.js\";\nimport { tokenizeWords } from \"../utils/tokenization.js\";\n\nexport interface BleuOptions {\n\tmaxNgramSize?: number;\n\tsmoothing?: number;\n}\n\nexport interface BleuResult {\n\tscore: number;\n\tprecisions: number[];\n\tbrevityPenalty: number;\n\tcandidateLength: number;\n\treferenceLength: number;\n}\n\nexport const calculateBleu = (\n\tcandidate: string,\n\treference: string,\n\toptions: BleuOptions = {},\n): BleuResult => {\n\tconst { maxNgramSize = 4, smoothing = 0 } = options;\n\n\tconst candidateTokens = tokenizeWords(candidate);\n\tconst referenceTokens = tokenizeWords(reference);\n\n\tconst candidateLength = candidateTokens.length;\n\tconst referenceLength = referenceTokens.length;\n\n\tconst precisions: number[] = [];\n\n\tfor (let n = 1; n <= maxNgramSize; n++) {\n\t\tconst candidateNgrams = generateNgrams(candidateTokens, n);\n\t\tconst referenceNgrams = generateNgrams(referenceTokens, n);\n\n\t\tconst precision = calculateNgramPrecision(candidateNgrams, referenceNgrams);\n\n\t\tconst smoothedPrecision = Math.max(precision, smoothing);\n\t\tprecisions.push(smoothedPrecision);\n\t}\n\n\tlet brevityPenalty = 1.0;\n\tif (candidateLength < referenceLength) {\n\t\tbrevityPenalty = Math.exp(1 - referenceLength / candidateLength);\n\t}\n\n\tlet logSum = 0;\n\tlet validPrecisions = 0;\n\n\tfor (const precision of precisions) {\n\t\tif (precision > 0) {\n\t\t\tlogSum += Math.log(precision);\n\t\t\tvalidPrecisions++;\n\t\t}\n\t}\n\n\tlet bleuScore = 0;\n\tif (validPrecisions > 0) {\n\t\tconst geometricMean = Math.exp(logSum / validPrecisions);\n\t\tbleuScore = brevityPenalty * geometricMean * 100;\n\t}\n\n\treturn {\n\t\tscore: Math.round(bleuScore * 100) / 100,\n\t\tprecisions: precisions.map((p) => Math.round(p * 10000) / 100),\n\t\tbrevityPenalty: Math.round(brevityPenalty * 10000) / 10000,\n\t\tcandidateLength,\n\t\treferenceLength,\n\t};\n};\n","export const cosineSimilarity = (\n\tvec1: Map<string, number>,\n\tvec2: Map<string, number>,\n): number => {\n\tconst allTerms = new Set([...vec1.keys(), ...vec2.keys()]);\n\n\tlet dotProduct = 0;\n\tlet magnitude1 = 0;\n\tlet magnitude2 = 0;\n\n\tfor (const term of allTerms) {\n\t\tconst val1 = vec1.get(term) || 0;\n\t\tconst val2 = vec2.get(term) || 0;\n\n\t\tdotProduct += val1 * val2;\n\t\tmagnitude1 += val1 * val1;\n\t\tmagnitude2 += val2 * val2;\n\t}\n\n\tmagnitude1 = Math.sqrt(magnitude1);\n\tmagnitude2 = Math.sqrt(magnitude2);\n\n\tif (magnitude1 === 0 || magnitude2 === 0) {\n\t\treturn 0;\n\t}\n\n\treturn dotProduct / (magnitude1 * magnitude2);\n};\n","export const calculateIDF = (\n\tsentenceTokens: string[][],\n): Map<string, number> => {\n\tconst totalSentences = sentenceTokens.length;\n\tconst documentFrequency = new Map<string, number>();\n\n\t// Count how many sentences each word appears in\n\tfor (const tokens of sentenceTokens) {\n\t\tconst uniqueTokens = new Set(tokens);\n\t\tfor (const token of uniqueTokens) {\n\t\t\tdocumentFrequency.set(token, (documentFrequency.get(token) || 0) + 1);\n\t\t}\n\t}\n\n\t// Calculate IDF: log((total_sentences + 1) / (sentences_containing_term + 1))\n\t// Add smoothing to avoid zero IDF values\n\tconst idf = new Map<string, number>();\n\tfor (const [term, df] of documentFrequency) {\n\t\tidf.set(term, Math.log((totalSentences + 1) / (df + 1)));\n\t}\n\n\treturn idf;\n};\n\nexport const calculateTFIDF = (\n\ttokens: string[],\n\tidf: Map<string, number>,\n): Map<string, number> => {\n\t// Calculate TF (term frequency)\n\tconst tf = new Map<string, number>();\n\tfor (const token of tokens) {\n\t\ttf.set(token, (tf.get(token) || 0) + 1);\n\t}\n\n\t// Multiply TF by IDF\n\tconst tfidf = new Map<string, number>();\n\tfor (const [term, termFreq] of tf) {\n\t\tconst idfValue = idf.get(term) || 0;\n\t\ttfidf.set(term, termFreq * idfValue);\n\t}\n\n\treturn tfidf;\n};\n","import { cosineSimilarity } from \"../utils/similarity.js\";\nimport { calculateIDF, calculateTFIDF } from \"../utils/tfidf.js\";\nimport { tokenizeSentences, tokenizeWords } from \"../utils/tokenization.js\";\n\nexport interface CoherenceOptions {\n\tminSentences?: number;\n}\n\nexport interface CoherenceResult {\n\tscore: number;\n\tsentenceCount: number;\n\tpairwiseSimilarities: number[];\n\taverageSimilarity: number;\n\tfeedback: string;\n}\n\nconst generateFeedback = (score: number, sentenceCount: number): string => {\n\tif (sentenceCount === 1) {\n\t\treturn \"Single sentence is inherently coherent\";\n\t}\n\n\tif (score >= 90) {\n\t\treturn \"Excellent coherence with very strong semantic connections and smooth flow\";\n\t}\n\tif (score >= 75) {\n\t\treturn \"Good coherence with strong connections and mostly smooth transitions\";\n\t}\n\tif (score >= 60) {\n\t\treturn \"Fair coherence with moderate topic continuity but some noticeable gaps\";\n\t}\n\tif (score >= 40) {\n\t\treturn \"Poor coherence with weak connections and frequent topic shifts\";\n\t}\n\treturn \"Very poor coherence with disconnected sentences and no clear topic continuity\";\n};\n\nexport const calculateCoherence = (\n\ttext: string,\n\toptions: CoherenceOptions = {},\n): CoherenceResult => {\n\tconst { minSentences = 2 } = options;\n\n\tconst sentences = tokenizeSentences(text);\n\n\tif (sentences.length < minSentences) {\n\t\treturn {\n\t\t\tscore: 100,\n\t\t\tsentenceCount: sentences.length,\n\t\t\tpairwiseSimilarities: [],\n\t\t\taverageSimilarity: 1.0,\n\t\t\tfeedback: generateFeedback(100, sentences.length),\n\t\t};\n\t}\n\n\tconst sentenceTokens = sentences.map((s) => tokenizeWords(s));\n\n\tconst idf = calculateIDF(sentenceTokens);\n\n\tconst tfidfVectors = sentenceTokens.map((tokens) =>\n\t\tcalculateTFIDF(tokens, idf),\n\t);\n\n\tconst similarities: number[] = [];\n\tfor (let i = 0; i < tfidfVectors.length - 1; i++) {\n\t\tconst sim = cosineSimilarity(tfidfVectors[i], tfidfVectors[i + 1]);\n\t\tsimilarities.push(sim);\n\t}\n\n\tconst avgSimilarity =\n\t\tsimilarities.length > 0\n\t\t\t? similarities.reduce((a, b) => a + b, 0) / similarities.length\n\t\t\t: 0;\n\tconst score = avgSimilarity * 100;\n\n\treturn {\n\t\tscore: Math.round(score * 100) / 100,\n\t\tsentenceCount: sentences.length,\n\t\tpairwiseSimilarities: similarities,\n\t\taverageSimilarity: avgSimilarity,\n\t\tfeedback: generateFeedback(score, sentences.length),\n\t};\n};\n","import { distance } from \"fastest-levenshtein\";\nimport { tokenizeWords } from \"../utils/tokenization.js\";\n\nexport interface TerOptions {\n\tnormalize?: boolean;\n}\n\nexport interface TerResult {\n\tscore: number;\n\trawTer: number;\n\teditCount: number;\n\tcandidateLength: number;\n\treferenceLength: number;\n\tfeedback: string;\n}\n\nexport const calculateTer = (\n\tcandidate: string,\n\treference: string,\n\toptions: TerOptions = {},\n): TerResult => {\n\tconst { normalize = true } = options;\n\n\tconst candidateTokens = tokenizeWords(candidate);\n\tconst referenceTokens = tokenizeWords(reference);\n\n\tconst candidateLength = candidateTokens.length;\n\tconst referenceLength = referenceTokens.length;\n\n\tconst editCount = distance(\n\t\tcandidateTokens.join(\" \"),\n\t\treferenceTokens.join(\" \"),\n\t);\n\n\tlet rawTer = 0;\n\tif (normalize && referenceLength > 0) {\n\t\trawTer = editCount / referenceLength;\n\t} else {\n\t\trawTer = editCount;\n\t}\n\n\tconst invertedScore = Math.max(0, 1 - rawTer) * 100;\n\n\tlet feedback = \"\";\n\tif (editCount === 0) {\n\t\tfeedback = \"Perfect match with reference translation\";\n\t} else if (rawTer < 0.2) {\n\t\tfeedback = `Excellent translation with only ${editCount} minor edit(s) needed`;\n\t} else if (rawTer < 0.4) {\n\t\tfeedback = `Good translation with ${editCount} edit(s) needed`;\n\t} else if (rawTer < 0.6) {\n\t\tfeedback = `Fair translation requiring ${editCount} edit(s)`;\n\t} else {\n\t\tfeedback = `Poor translation requiring ${editCount} edit(s) - significant revision needed`;\n\t}\n\n\tconst lengthDiff = Math.abs(candidateLength - referenceLength);\n\tif (lengthDiff > referenceLength * 0.2) {\n\t\tif (candidateLength > referenceLength) {\n\t\t\tfeedback += ` (translation is ${lengthDiff} words too long)`;\n\t\t} else {\n\t\t\tfeedback += ` (translation is ${lengthDiff} words too short)`;\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.round(invertedScore * 100) / 100,\n\t\trawTer: Math.round(rawTer * 10000) / 10000,\n\t\teditCount,\n\t\tcandidateLength,\n\t\treferenceLength,\n\t\tfeedback,\n\t};\n};\n","/**\n * OpenTelemetry instrumentation for eval-kit.\n *\n * Uses dynamic import so @opentelemetry/api is an optional peer dependency.\n * When the package is not installed or no SDK is configured, all tracing\n * operations are no-ops with zero overhead.\n */\n\ndeclare const __EVAL_KIT_VERSION__: string;\n\n// ---------- Type stubs (mirror the OTel API surface we use) ----------\n\ninterface SpanAttributes {\n\t[key: string]: string | number | boolean | undefined;\n}\n\n/**\n * Minimal span interface matching the subset of @opentelemetry/api Span we use.\n */\nexport interface EvalKitSpan {\n\tsetAttribute(key: string, value: string | number | boolean): void;\n\tsetStatus(status: { code: number; message?: string }): void;\n\trecordException(error: Error | string): void;\n\taddEvent(name: string, attributes?: SpanAttributes): void;\n\tend(): void;\n}\n\ninterface Tracer {\n\tstartActiveSpan<T>(\n\t\tname: string,\n\t\toptions: { attributes?: SpanAttributes },\n\t\tfn: (span: EvalKitSpan) => T,\n\t): T;\n}\n\n// ---------- No-op implementations ----------\n\nconst noopSpan: EvalKitSpan = {\n\tsetAttribute() {},\n\tsetStatus() {},\n\trecordException() {},\n\taddEvent() {},\n\tend() {},\n};\n\nconst noopTracer: Tracer = {\n\tstartActiveSpan<T>(\n\t\t_name: string,\n\t\t_options: { attributes?: SpanAttributes },\n\t\tfn: (span: EvalKitSpan) => T,\n\t): T {\n\t\treturn fn(noopSpan);\n\t},\n};\n\n// ---------- Global toggle ----------\n\nlet telemetryEnabled = false;\n\n/**\n * Enable or disable eval-kit's OpenTelemetry instrumentation globally.\n *\n * When disabled, all tracing functions return no-ops — identical to the\n * behaviour when `@opentelemetry/api` is not installed. This lets you\n * use OTel in your application without eval-kit emitting spans.\n *\n * Telemetry is **disabled** by default.\n */\nexport function enableTelemetry(enabled: boolean): void {\n\ttelemetryEnabled = enabled;\n}\n\n/**\n * Returns the current telemetry enabled state.\n */\nexport function isTelemetryEnabled(): boolean {\n\treturn telemetryEnabled;\n}\n\n// ---------- Lazy tracer resolution ----------\n\nlet resolvedTracer: Tracer | null = null;\nlet tracerPromise: Promise<Tracer> | null = null;\n\nfunction resolveTracer(): Promise<Tracer> {\n\tif (!tracerPromise) {\n\t\ttracerPromise = (async () => {\n\t\t\ttry {\n\t\t\t\tconst api = await import(\"@opentelemetry/api\");\n\t\t\t\tconst version =\n\t\t\t\t\ttypeof __EVAL_KIT_VERSION__ !== \"undefined\"\n\t\t\t\t\t\t? __EVAL_KIT_VERSION__\n\t\t\t\t\t\t: \"unknown\";\n\t\t\t\tconst tracer = api.trace.getTracer(\"eval-kit\", version);\n\t\t\t\t// Wrap the OTel tracer with an explicit adapter at the boundary\n\t\t\t\tconst wrapSpan = (\n\t\t\t\t\tspan: import(\"@opentelemetry/api\").Span,\n\t\t\t\t): EvalKitSpan => ({\n\t\t\t\t\tsetAttribute: (key, value) => span.setAttribute(key, value),\n\t\t\t\t\tsetStatus: (status) => span.setStatus(status),\n\t\t\t\t\trecordException: (error) => span.recordException(error),\n\t\t\t\t\taddEvent: (name, attributes) => span.addEvent(name, attributes),\n\t\t\t\t\tend: () => span.end(),\n\t\t\t\t});\n\n\t\t\t\tresolvedTracer = {\n\t\t\t\t\tstartActiveSpan<T>(\n\t\t\t\t\t\tname: string,\n\t\t\t\t\t\toptions: { attributes?: SpanAttributes },\n\t\t\t\t\t\tfn: (span: EvalKitSpan) => T,\n\t\t\t\t\t): T {\n\t\t\t\t\t\treturn tracer.startActiveSpan(name, options, (span) =>\n\t\t\t\t\t\t\tfn(wrapSpan(span)),\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\treturn resolvedTracer;\n\t\t\t} catch {\n\t\t\t\t// @opentelemetry/api not installed — use no-op\n\t\t\t\tresolvedTracer = noopTracer;\n\t\t\t\treturn noopTracer;\n\t\t\t}\n\t\t})();\n\t}\n\treturn tracerPromise;\n}\n\n// ---------- Status codes (match OTel SpanStatusCode) ----------\n\nexport const SpanStatusCode = {\n\tUNSET: 0,\n\tOK: 1,\n\tERROR: 2,\n} as const;\n\n// ---------- Public API ----------\n\n/**\n * Get the eval-kit tracer (async). Triggers resolution on first call.\n * Returns the no-op tracer when telemetry is disabled.\n */\nexport async function getTracer(): Promise<Tracer> {\n\tif (!telemetryEnabled) return noopTracer;\n\treturn resolveTracer();\n}\n\n/**\n * Get the cached tracer synchronously. Returns no-op if the tracer\n * hasn't been resolved yet (i.e., no prior withSpan/getTracer call)\n * or if telemetry is disabled.\n */\nexport function getCachedTracer(): Tracer {\n\tif (!telemetryEnabled) return noopTracer;\n\treturn resolvedTracer ?? noopTracer;\n}\n\nexport interface WithSpanOptions {\n\tattributes?: SpanAttributes;\n}\n\n/**\n * Wrap an async operation with an OpenTelemetry span.\n *\n * - Creates a child span under the current active span (if any)\n * - Sets initial attributes from options\n * - On success: sets status OK, ends span\n * - On error: records exception, sets status ERROR, ends span, re-throws\n * - The callback receives the span so it can add attributes/events during execution\n */\nexport async function withSpan<T>(\n\tname: string,\n\toptions: WithSpanOptions,\n\tfn: (span: EvalKitSpan) => Promise<T>,\n): Promise<T> {\n\tif (!telemetryEnabled) return fn(noopSpan);\n\n\tconst tracer = await resolveTracer();\n\treturn tracer.startActiveSpan(\n\t\tname,\n\t\t{ attributes: options.attributes },\n\t\tasync (span) => {\n\t\t\ttry {\n\t\t\t\tconst result = await fn(span);\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tspan.setStatus({\n\t\t\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t\tspan.recordException(error instanceof Error ? error : String(error));\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n\n/**\n * Reset the cached tracer. Only used in tests.\n */\nexport function _resetTracer(): void {\n\tresolvedTracer = null;\n\ttracerPromise = null;\n}\n","export interface ConcurrencyConfig {\n\treadonly maxConcurrency: number;\n\treadonly rateLimit?: {\n\t\treadonly maxRequestsPerMinute?: number;\n\t\treadonly maxRequestsPerHour?: number;\n\t};\n}\n\nexport class ConcurrencyManager {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly rateLimit?: ConcurrencyConfig[\"rateLimit\"];\n\tprivate activeCount = 0;\n\tprivate queue: Array<() => void> = [];\n\tprivate requestTimestamps: number[] = [];\n\tprivate readonly MAX_TIMESTAMP_AGE = 3600000; // 1 hour - cleanup threshold\n\n\tconstructor(config: ConcurrencyConfig) {\n\t\tthis.maxConcurrency = config.maxConcurrency;\n\t\tthis.rateLimit = config.rateLimit;\n\t}\n\n\t/**\n\t * Execute a task with concurrency control and rate limiting\n\t */\n\tasync run<T>(task: () => Promise<T>): Promise<T> {\n\t\t// Wait for available slot\n\t\tawait this.waitForSlot();\n\n\t\t// Check rate limit\n\t\tawait this.checkRateLimit();\n\n\t\tthis.activeCount++;\n\t\tthis.requestTimestamps.push(Date.now());\n\n\t\t// Periodically cleanup old timestamps to prevent memory leak\n\t\tthis.cleanupOldTimestamps();\n\n\t\ttry {\n\t\t\treturn await task();\n\t\t} finally {\n\t\t\tthis.activeCount--;\n\t\t\tthis.processQueue();\n\t\t}\n\t}\n\n\t/**\n\t * Wait for an available concurrency slot\n\t */\n\tprivate async waitForSlot(): Promise<void> {\n\t\tif (this.activeCount < this.maxConcurrency) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.queue.push(resolve);\n\t\t});\n\t}\n\n\t/**\n\t * Check and enforce rate limits\n\t */\n\tprivate async checkRateLimit(): Promise<void> {\n\t\tif (!this.rateLimit) return;\n\n\t\tconst now = Date.now();\n\n\t\t// Check per-minute limit\n\t\tif (this.rateLimit.maxRequestsPerMinute) {\n\t\t\tconst recentRequests = this.requestTimestamps.filter(\n\t\t\t\t(ts) => now - ts < 60000,\n\t\t\t);\n\n\t\t\tif (recentRequests.length >= this.rateLimit.maxRequestsPerMinute) {\n\t\t\t\tconst oldestRequest = Math.min(...recentRequests);\n\t\t\t\tconst waitTime = 60000 - (now - oldestRequest) + 100; // Add 100ms buffer\n\t\t\t\tawait this.sleep(waitTime);\n\t\t\t}\n\t\t}\n\n\t\t// Check per-hour limit\n\t\tif (this.rateLimit.maxRequestsPerHour) {\n\t\t\tconst recentRequests = this.requestTimestamps.filter(\n\t\t\t\t(ts) => now - ts < 3600000,\n\t\t\t);\n\n\t\t\tif (recentRequests.length >= this.rateLimit.maxRequestsPerHour) {\n\t\t\t\tconst oldestRequest = Math.min(...recentRequests);\n\t\t\t\tconst waitTime = 3600000 - (now - oldestRequest) + 100; // Add 100ms buffer\n\t\t\t\tawait this.sleep(waitTime);\n\t\t\t}\n\t\t}\n\n\t\t// Clean up old timestamps (keep only last hour)\n\t\tthis.requestTimestamps = this.requestTimestamps.filter(\n\t\t\t(ts) => now - ts < 3600000,\n\t\t);\n\t}\n\n\t/**\n\t * Process the next item in the queue\n\t * Checks capacity again after dequeuing to avoid race conditions\n\t */\n\tprivate processQueue(): void {\n\t\t// Check if we have capacity before dequeuing\n\t\tif (this.activeCount < this.maxConcurrency) {\n\t\t\tconst next = this.queue.shift();\n\t\t\t// Check capacity again after dequeuing to handle race conditions\n\t\t\tif (next) {\n\t\t\t\tif (this.activeCount < this.maxConcurrency) {\n\t\t\t\t\tnext();\n\t\t\t\t} else {\n\t\t\t\t\t// No capacity available, put it back at the front\n\t\t\t\t\tthis.queue.unshift(next);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sleep for specified milliseconds\n\t */\n\tprivate sleep(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n\n\t/**\n\t * Cleanup old timestamps to prevent memory leak\n\t * Removes timestamps older than MAX_TIMESTAMP_AGE\n\t */\n\tprivate cleanupOldTimestamps(): void {\n\t\t// Only cleanup if rate limiting is enabled and we have timestamps\n\t\tif (!this.rateLimit || this.requestTimestamps.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst cutoff = now - this.MAX_TIMESTAMP_AGE;\n\n\t\t// Keep only timestamps within the last hour\n\t\tthis.requestTimestamps = this.requestTimestamps.filter(\n\t\t\t(ts) => ts >= cutoff,\n\t\t);\n\t}\n\n\t/**\n\t * Get current active count\n\t */\n\tgetActiveCount(): number {\n\t\treturn this.activeCount;\n\t}\n\n\t/**\n\t * Get queue length\n\t */\n\tgetQueueLength(): number {\n\t\treturn this.queue.length;\n\t}\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { stringify } from \"csv-stringify/sync\";\nimport type { BatchEvaluationResult, BatchExportConfig } from \"../types.js\";\n\nconst STANDARD_INPUT_FIELDS = new Set([\n\t\"candidateText\",\n\t\"prompt\",\n\t\"referenceText\",\n\t\"sourceText\",\n\t\"contentType\",\n\t\"language\",\n\t\"id\",\n]);\n\nexport class CsvExporter {\n\tasync export(\n\t\tresults: BatchEvaluationResult[],\n\t\tconfig: BatchExportConfig,\n\t): Promise<void> {\n\t\tconst {\n\t\t\tdestination,\n\t\t\tcsvOptions = {},\n\t\t\tincludeFields,\n\t\t\texcludeFields,\n\t\t\tfilterCondition,\n\t\t} = config;\n\n\t\t// Filter results if condition provided\n\t\tconst filteredResults = filterCondition\n\t\t\t? results.filter(filterCondition)\n\t\t\t: results;\n\n\t\t// Flatten results for CSV\n\t\tconst flattenedRecords = filteredResults.map((result) =>\n\t\t\tthis.flattenResult(result, csvOptions.flattenResults ?? true),\n\t\t);\n\n\t\t// Apply field filtering\n\t\tconst finalRecords = this.applyFieldFilters(\n\t\t\tflattenedRecords,\n\t\t\tincludeFields,\n\t\t\texcludeFields,\n\t\t);\n\n\t\t// Generate CSV\n\t\tconst csv = stringify(finalRecords, {\n\t\t\theader: csvOptions.includeHeaders ?? true,\n\t\t\tdelimiter: csvOptions.delimiter ?? \",\",\n\t\t\tquoted: true,\n\t\t\tquoted_empty: true,\n\t\t\tquoted_string: true,\n\t\t});\n\n\t\t// Write to file\n\t\tawait writeFile(destination, csv, { encoding: \"utf-8\" });\n\t}\n\n\t/**\n\t * Flatten a BatchEvaluationResult into a flat object suitable for CSV\n\t */\n\tprivate flattenResult(\n\t\tresult: BatchEvaluationResult,\n\t\tshouldFlatten: boolean,\n\t): Record<string, unknown> {\n\t\tconst flat: Record<string, unknown> = {\n\t\t\trowId: result.rowId,\n\t\t\trowIndex: result.rowIndex,\n\t\t\ttimestamp: result.timestamp,\n\t\t\tdurationMs: result.durationMs,\n\t\t\tretryCount: result.retryCount,\n\t\t\terror: result.error ?? \"\",\n\t\t};\n\n\t\tthis.addStandardInputFields(flat, result.input);\n\t\tthis.addAdditionalInputFields(flat, result.input);\n\t\tthis.addEvaluatorResults(flat, result.results, shouldFlatten);\n\n\t\treturn flat;\n\t}\n\n\t/**\n\t * Add standard input fields to the flattened object\n\t */\n\tprivate addStandardInputFields(\n\t\tflat: Record<string, unknown>,\n\t\tinput: BatchEvaluationResult[\"input\"],\n\t): void {\n\t\tflat.candidateText = input.candidateText;\n\t\tif (input.prompt) flat.prompt = input.prompt;\n\t\tif (input.referenceText) flat.referenceText = input.referenceText;\n\t\tif (input.sourceText) flat.sourceText = input.sourceText;\n\t\tif (input.contentType) flat.contentType = input.contentType;\n\t\tif (input.language) flat.language = input.language;\n\t}\n\n\t/**\n\t * Add additional input fields to the flattened object\n\t */\n\tprivate addAdditionalInputFields(\n\t\tflat: Record<string, unknown>,\n\t\tinput: BatchEvaluationResult[\"input\"],\n\t): void {\n\t\tfor (const [key, value] of Object.entries(input)) {\n\t\t\tif (!STANDARD_INPUT_FIELDS.has(key)) {\n\t\t\t\tflat[`input_${key}`] = this.serializeValue(value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Add evaluator results to the flattened object\n\t */\n\tprivate addEvaluatorResults(\n\t\tflat: Record<string, unknown>,\n\t\tresults: BatchEvaluationResult[\"results\"],\n\t\tshouldFlatten: boolean,\n\t): void {\n\t\tif (!shouldFlatten) {\n\t\t\tflat.results = JSON.stringify(results);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst evalResult = results[i];\n\t\t\tconst prefix = results.length === 1 ? \"\" : `eval${i + 1}_`;\n\n\t\t\tflat[`${prefix}evaluatorName`] = evalResult.evaluatorName;\n\t\t\tflat[`${prefix}score`] = evalResult.score;\n\t\t\tflat[`${prefix}feedback`] = evalResult.feedback;\n\n\t\t\tthis.addProcessingStats(flat, evalResult, prefix);\n\n\t\t\tif (evalResult.error) {\n\t\t\t\tflat[`${prefix}error`] = evalResult.error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Add processing stats to the flattened object\n\t */\n\tprivate addProcessingStats(\n\t\tflat: Record<string, unknown>,\n\t\tevalResult: BatchEvaluationResult[\"results\"][number],\n\t\tprefix: string,\n\t): void {\n\t\tif (!evalResult.processingStats) {\n\t\t\treturn;\n\t\t}\n\n\t\tflat[`${prefix}executionTime`] = evalResult.processingStats.executionTime;\n\n\t\tif (evalResult.processingStats.tokenUsage) {\n\t\t\tflat[`${prefix}tokenUsage`] = JSON.stringify(\n\t\t\t\tevalResult.processingStats.tokenUsage,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Apply field filtering\n\t */\n\tprivate applyFieldFilters(\n\t\trecords: Record<string, unknown>[],\n\t\tincludeFields?: string[],\n\t\texcludeFields?: string[],\n\t): Record<string, unknown>[] {\n\t\tif (!includeFields && !excludeFields) {\n\t\t\treturn records;\n\t\t}\n\n\t\treturn records.map((record) => {\n\t\t\tconst filtered: Record<string, unknown> = {};\n\n\t\t\tfor (const [key, value] of Object.entries(record)) {\n\t\t\t\t// Include logic\n\t\t\t\tif (includeFields && !includeFields.includes(key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Exclude logic\n\t\t\t\tif (excludeFields?.includes(key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfiltered[key] = value;\n\t\t\t}\n\n\t\t\treturn filtered;\n\t\t});\n\t}\n\n\t/**\n\t * Serialize a value for CSV\n\t */\n\tprivate serializeValue(value: unknown): string {\n\t\tif (value === null || value === undefined) {\n\t\t\treturn \"\";\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\treturn String(value);\n\t\t}\n\t\t// For objects and arrays, serialize as JSON\n\t\treturn JSON.stringify(value);\n\t}\n}\n","import { writeFile } from \"node:fs/promises\";\nimport type { BatchEvaluationResult, BatchExportConfig } from \"../types.js\";\n\nexport class JsonExporter {\n\tasync export(\n\t\tresults: BatchEvaluationResult[],\n\t\tconfig: BatchExportConfig,\n\t): Promise<void> {\n\t\tconst {\n\t\t\tdestination,\n\t\t\tjsonOptions = {},\n\t\t\tincludeFields,\n\t\t\texcludeFields,\n\t\t\tfilterCondition,\n\t\t} = config;\n\n\t\t// Filter results if condition provided\n\t\tconst filteredResults = filterCondition\n\t\t\t? results.filter(filterCondition)\n\t\t\t: results;\n\n\t\t// Apply field filtering\n\t\tconst finalResults =\n\t\t\tincludeFields || excludeFields\n\t\t\t\t? filteredResults.map((result) =>\n\t\t\t\t\t\tthis.applyFieldFilters(result, includeFields, excludeFields),\n\t\t\t\t\t)\n\t\t\t\t: filteredResults;\n\n\t\t// Build output object\n\t\tconst output = jsonOptions.includeMetadata\n\t\t\t? {\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\texportedAt: new Date().toISOString(),\n\t\t\t\t\t\ttotalResults: finalResults.length,\n\t\t\t\t\t\tsuccessfulResults: finalResults.filter((r) => !r.error).length,\n\t\t\t\t\t\tfailedResults: finalResults.filter((r) => r.error).length,\n\t\t\t\t\t},\n\t\t\t\t\tresults: finalResults,\n\t\t\t\t}\n\t\t\t: finalResults;\n\n\t\t// Serialize to JSON\n\t\tconst json = JSON.stringify(\n\t\t\toutput,\n\t\t\tnull,\n\t\t\tjsonOptions.pretty ? 2 : undefined,\n\t\t);\n\n\t\t// Write to file\n\t\tawait writeFile(destination, json, { encoding: \"utf-8\" });\n\t}\n\n\t/**\n\t * Apply field filtering to a single result\n\t */\n\tprivate applyFieldFilters(\n\t\tresult: BatchEvaluationResult,\n\t\tincludeFields?: string[],\n\t\texcludeFields?: string[],\n\t): Partial<BatchEvaluationResult> {\n\t\tif (!includeFields && !excludeFields) {\n\t\t\treturn result;\n\t\t}\n\n\t\tconst filtered: Record<string, unknown> = {};\n\n\t\tfor (const [key, value] of Object.entries(result)) {\n\t\t\t// Include logic\n\t\t\tif (includeFields && !includeFields.includes(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Exclude logic\n\t\t\tif (excludeFields?.includes(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfiltered[key] = value;\n\t\t}\n\n\t\treturn filtered as Partial<BatchEvaluationResult>;\n\t}\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parse } from \"csv-parse/sync\";\nimport type { BatchInputFileConfig, BatchInputRow } from \"../types.js\";\n\nexport class CsvParser {\n\tasync parse(config: BatchInputFileConfig): Promise<BatchInputRow[]> {\n\t\tconst records = await this.parseRecordsFromFile(config);\n\t\treturn records.map((record, index) =>\n\t\t\tthis.mapRecordToRow(record, index, config.fieldMapping),\n\t\t);\n\t}\n\n\t/**\n\t * Read and parse CSV file into records\n\t */\n\tprivate async parseRecordsFromFile(\n\t\tconfig: BatchInputFileConfig,\n\t): Promise<Record<string, string>[]> {\n\t\tconst { filePath, csvOptions = {} } = config;\n\n\t\tconst encoding = csvOptions.encoding ?? \"utf-8\";\n\t\tconst content = await readFile(filePath, { encoding });\n\n\t\treturn parse(content, {\n\t\t\tdelimiter: csvOptions.delimiter ?? \",\",\n\t\t\tquote: csvOptions.quote ?? '\"',\n\t\t\tescape: csvOptions.escape ?? '\"',\n\t\t\tcolumns: csvOptions.headers ?? true,\n\t\t\tskip_empty_lines: csvOptions.skipEmptyLines ?? true,\n\t\t\ttrim: true,\n\t\t\tcast: false,\n\t\t}) as unknown as Record<string, string>[];\n\t}\n\n\t/**\n\t * Map a CSV record to a BatchInputRow\n\t */\n\tprivate mapRecordToRow(\n\t\trecord: Record<string, string>,\n\t\tindex: number,\n\t\tfieldMapping?: BatchInputFileConfig[\"fieldMapping\"],\n\t): BatchInputRow {\n\t\tconst candidateText = this.getField(\n\t\t\trecord,\n\t\t\tfieldMapping?.candidateText ?? \"candidateText\",\n\t\t);\n\n\t\tconst id = this.extractId(record, index, fieldMapping);\n\t\tconst referenceText = this.extractOptionalField(\n\t\t\trecord,\n\t\t\t\"referenceText\",\n\t\t\tfieldMapping?.referenceText,\n\t\t);\n\t\tconst sourceText = this.extractOptionalField(\n\t\t\trecord,\n\t\t\t\"sourceText\",\n\t\t\tfieldMapping?.sourceText,\n\t\t);\n\t\tconst contentType = this.extractOptionalField(\n\t\t\trecord,\n\t\t\t\"contentType\",\n\t\t\tfieldMapping?.contentType,\n\t\t);\n\t\tconst language = this.extractOptionalField(\n\t\t\trecord,\n\t\t\t\"language\",\n\t\t\tfieldMapping?.language,\n\t\t);\n\n\t\tconst row: BatchInputRow = {\n\t\t\tcandidateText,\n\t\t\tid,\n\t\t\t...(referenceText && { referenceText }),\n\t\t\t...(sourceText && { sourceText }),\n\t\t\t...(contentType && { contentType }),\n\t\t\t...(language && { language }),\n\t\t};\n\n\t\tthis.addAdditionalFields(row, record);\n\n\t\treturn row;\n\t}\n\n\t/**\n\t * Extract ID field with fallback logic\n\t */\n\tprivate extractId(\n\t\trecord: Record<string, string>,\n\t\tindex: number,\n\t\tfieldMapping?: BatchInputFileConfig[\"fieldMapping\"],\n\t): string {\n\t\tif (fieldMapping?.id) {\n\t\t\treturn this.getField(record, fieldMapping.id);\n\t\t}\n\t\treturn record.id || `row-${index}`;\n\t}\n\n\t/**\n\t * Extract optional field with mapping fallback\n\t */\n\tprivate extractOptionalField(\n\t\trecord: Record<string, string>,\n\t\tdefaultFieldName: string,\n\t\tmappedFieldName?: string,\n\t): string | undefined {\n\t\tif (mappedFieldName) {\n\t\t\treturn this.getOptionalField(record, mappedFieldName);\n\t\t}\n\t\treturn this.getOptionalField(record, defaultFieldName);\n\t}\n\n\t/**\n\t * Add any additional fields from the record to the row\n\t */\n\tprivate addAdditionalFields(\n\t\trow: BatchInputRow,\n\t\trecord: Record<string, string>,\n\t): void {\n\t\tfor (const [key, value] of Object.entries(record)) {\n\t\t\tif (!(key in row)) {\n\t\t\t\trow[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getField(record: Record<string, string>, fieldName: string): string {\n\t\tconst value = record[fieldName];\n\t\tif (!value) {\n\t\t\tthrow new Error(`Required field '${fieldName}' not found in CSV record`);\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate getOptionalField(\n\t\trecord: Record<string, string>,\n\t\tfieldName: string,\n\t): string | undefined {\n\t\tconst value = record[fieldName];\n\t\treturn value || undefined;\n\t}\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { BatchInputFileConfig, BatchInputRow } from \"../types.js\";\n\nexport class JsonParser {\n\tasync parse(config: BatchInputFileConfig): Promise<BatchInputRow[]> {\n\t\tconst data = await this.parseJsonFromFile(config);\n\t\tconst records = this.extractRecordsArray(data, config.jsonOptions);\n\t\tthis.validateRecords(records);\n\n\t\treturn (records as Record<string, unknown>[]).map((record, index) =>\n\t\t\tthis.mapRecordToRow(record, index, config.fieldMapping),\n\t\t);\n\t}\n\n\t/**\n\t * Read and parse JSON file\n\t */\n\tprivate async parseJsonFromFile(\n\t\tconfig: BatchInputFileConfig,\n\t): Promise<unknown> {\n\t\tconst { filePath, jsonOptions = {} } = config;\n\t\tconst encoding = jsonOptions.encoding ?? \"utf-8\";\n\t\tconst content = await readFile(filePath, { encoding });\n\n\t\ttry {\n\t\t\treturn JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse JSON file: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Extract array of records from data\n\t */\n\tprivate extractRecordsArray(\n\t\tdata: unknown,\n\t\tjsonOptions?: BatchInputFileConfig[\"jsonOptions\"],\n\t): unknown[] {\n\t\tif (jsonOptions?.arrayPath) {\n\t\t\treturn this.extractFromPath(data, jsonOptions.arrayPath);\n\t\t}\n\n\t\tif (Array.isArray(data)) {\n\t\t\treturn data;\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t\"JSON file must be an array or specify arrayPath to locate the array\",\n\t\t);\n\t}\n\n\t/**\n\t * Validate that all records are objects\n\t */\n\tprivate validateRecords(records: unknown[]): void {\n\t\tif (!records.every((r) => typeof r === \"object\" && r !== null)) {\n\t\t\tthrow new Error(\"All records in the array must be objects\");\n\t\t}\n\t}\n\n\t/**\n\t * Map a JSON record to a BatchInputRow\n\t */\n\tprivate mapRecordToRow(\n\t\trecord: Record<string, unknown>,\n\t\tindex: number,\n\t\tfieldMapping?: BatchInputFileConfig[\"fieldMapping\"],\n\t): BatchInputRow {\n\t\tconst candidateText = this.getField(\n\t\t\trecord,\n\t\t\tfieldMapping?.candidateText ?? \"candidateText\",\n\t\t);\n\n\t\tconst id = this.extractId(record, index, fieldMapping);\n\t\tconst referenceText = this.extractOptionalStringField(record, {\n\t\t\tdefaultFieldName: \"referenceText\",\n\t\t\tmappedFieldName: fieldMapping?.referenceText,\n\t\t});\n\t\tconst sourceText = this.extractOptionalStringField(record, {\n\t\t\tdefaultFieldName: \"sourceText\",\n\t\t\tmappedFieldName: fieldMapping?.sourceText,\n\t\t});\n\t\tconst contentType = this.extractOptionalStringField(record, {\n\t\t\tdefaultFieldName: \"contentType\",\n\t\t\tmappedFieldName: fieldMapping?.contentType,\n\t\t});\n\t\tconst language = this.extractOptionalStringField(record, {\n\t\t\tdefaultFieldName: \"language\",\n\t\t\tmappedFieldName: fieldMapping?.language,\n\t\t});\n\n\t\tconst row: BatchInputRow = {\n\t\t\tcandidateText,\n\t\t\tid,\n\t\t\t...(referenceText && { referenceText }),\n\t\t\t...(sourceText && { sourceText }),\n\t\t\t...(contentType && { contentType }),\n\t\t\t...(language && { language }),\n\t\t};\n\n\t\tthis.addAdditionalFields(row, record);\n\n\t\treturn row;\n\t}\n\n\t/**\n\t * Extract ID field with fallback logic\n\t */\n\tprivate extractId(\n\t\trecord: Record<string, unknown>,\n\t\tindex: number,\n\t\tfieldMapping?: BatchInputFileConfig[\"fieldMapping\"],\n\t): string {\n\t\tif (fieldMapping?.id) {\n\t\t\tconst value = this.getOptionalField(record, fieldMapping.id);\n\t\t\treturn value ? String(value) : `row-${index}`;\n\t\t}\n\t\treturn record.id ? String(record.id) : `row-${index}`;\n\t}\n\n\t/**\n\t * Extract optional string field with mapping fallback\n\t */\n\tprivate extractOptionalStringField(\n\t\trecord: Record<string, unknown>,\n\t\toptions: { defaultFieldName: string; mappedFieldName?: string },\n\t): string | undefined {\n\t\tconst fieldName = options.mappedFieldName ?? options.defaultFieldName;\n\t\tconst value = this.getOptionalField(record, fieldName);\n\t\treturn value ? String(value) : undefined;\n\t}\n\n\t/**\n\t * Add any additional fields from the record to the row\n\t */\n\tprivate addAdditionalFields(\n\t\trow: BatchInputRow,\n\t\trecord: Record<string, unknown>,\n\t): void {\n\t\tfor (const [key, value] of Object.entries(record)) {\n\t\t\tif (!(key in row)) {\n\t\t\t\trow[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate extractFromPath(data: unknown, path: string): unknown[] {\n\t\tconst parts = path.split(\".\");\n\t\tlet current: unknown = data;\n\n\t\tfor (const part of parts) {\n\t\t\tcurrent = this.accessProperty({\n\t\t\t\tobj: current,\n\t\t\t\tpropertyName: part,\n\t\t\t\tfullPath: path,\n\t\t\t});\n\t\t}\n\n\t\tthis.ensureIsArray(current, path);\n\t\treturn current as unknown[];\n\t}\n\n\t/**\n\t * Access a property on an object, with validation\n\t */\n\tprivate accessProperty(options: {\n\t\tobj: unknown;\n\t\tpropertyName: string;\n\t\tfullPath: string;\n\t}): unknown {\n\t\tconst { obj, propertyName, fullPath } = options;\n\n\t\tif (typeof obj !== \"object\" || obj === null) {\n\t\t\tthrow new Error(`Cannot access property '${propertyName}' on non-object`);\n\t\t}\n\n\t\tconst value = (obj as Record<string, unknown>)[propertyName];\n\t\tif (value === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Property '${propertyName}' not found in path '${fullPath}'`,\n\t\t\t);\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Ensure the value is an array\n\t */\n\tprivate ensureIsArray(value: unknown, path: string): void {\n\t\tif (!Array.isArray(value)) {\n\t\t\tthrow new Error(`Path '${path}' does not point to an array`);\n\t\t}\n\t}\n\n\tprivate getField(record: Record<string, unknown>, fieldName: string): string {\n\t\tconst value = record[fieldName];\n\t\tif (value === undefined || value === null) {\n\t\t\tthrow new Error(`Required field '${fieldName}' not found in JSON record`);\n\t\t}\n\t\treturn String(value);\n\t}\n\n\tprivate getOptionalField(\n\t\trecord: Record<string, unknown>,\n\t\tfieldName: string,\n\t): unknown {\n\t\treturn record[fieldName];\n\t}\n}\n","import type { ProgressEvent, ProgressEventType } from \"./types.js\";\n\nexport interface ProgressTrackerConfig {\n\treadonly totalRows: number;\n\treadonly emitInterval?: number; // milliseconds\n\treadonly onProgress?: (event: ProgressEvent) => void | Promise<void>;\n}\n\nexport class ProgressTracker {\n\tprivate readonly totalRows: number;\n\tprivate readonly emitInterval: number;\n\tprivate readonly onProgress?: (event: ProgressEvent) => void | Promise<void>;\n\n\tprivate processedRows = 0;\n\tprivate successfulRows = 0;\n\tprivate failedRows = 0;\n\tprivate processingTimes: number[] = [];\n\tprivate lastEmitTime = 0;\n\tprivate totalTokens = 0;\n\n\tconstructor(config: ProgressTrackerConfig) {\n\t\tthis.totalRows = config.totalRows;\n\t\tthis.emitInterval = config.emitInterval ?? 1000;\n\t\tthis.onProgress = config.onProgress;\n\t}\n\n\t/**\n\t * Start tracking progress\n\t */\n\tstart(): void {\n\t\tthis.emit(\"started\");\n\t}\n\n\t/**\n\t * Record a successful evaluation\n\t */\n\trecordSuccess(durationMs: number, tokensUsed?: number): void {\n\t\tthis.processedRows++;\n\t\tthis.successfulRows++;\n\t\tthis.processingTimes.push(durationMs);\n\t\tif (tokensUsed) {\n\t\t\tthis.totalTokens += tokensUsed;\n\t\t}\n\t\tthis.maybeEmit(\"progress\");\n\t}\n\n\t/**\n\t * Record a failed evaluation\n\t */\n\trecordFailure(durationMs: number): void {\n\t\tthis.processedRows++;\n\t\tthis.failedRows++;\n\t\tthis.processingTimes.push(durationMs);\n\t\tthis.maybeEmit(\"progress\");\n\t}\n\n\t/**\n\t * Record a retry attempt\n\t */\n\trecordRetry(error: string, retryCount: number): void {\n\t\tthis.emit(\"retry\", { currentError: error, retryCount });\n\t}\n\n\t/**\n\t * Mark completion\n\t */\n\tcomplete(): void {\n\t\tthis.emit(\"completed\");\n\t}\n\n\t/**\n\t * Pause tracking\n\t */\n\tpause(): void {\n\t\tthis.emit(\"paused\");\n\t}\n\n\t/**\n\t * Resume tracking\n\t */\n\tresume(): void {\n\t\tthis.emit(\"resumed\");\n\t}\n\n\t/**\n\t * Skip rows (for resuming from a specific index)\n\t * This marks rows as processed without actually processing them\n\t */\n\tskipRows(count: number): void {\n\t\tthis.processedRows += count;\n\t\tthis.successfulRows += count; // Assume skipped rows were successful in previous run\n\t}\n\n\t/**\n\t * Emit if interval has passed\n\t */\n\tprivate maybeEmit(\n\t\ttype: ProgressEventType,\n\t\textra?: Partial<ProgressEvent>,\n\t): void {\n\t\tconst now = Date.now();\n\t\tif (now - this.lastEmitTime >= this.emitInterval) {\n\t\t\tthis.emit(type, extra);\n\t\t\tthis.lastEmitTime = now;\n\t\t}\n\t}\n\n\t/**\n\t * Emit progress event\n\t */\n\tprivate emit(type: ProgressEventType, extra?: Partial<ProgressEvent>): void {\n\t\tif (!this.onProgress) return;\n\n\t\tconst avgProcessingTime =\n\t\t\tthis.processingTimes.length > 0\n\t\t\t\t? this.processingTimes.reduce((a, b) => a + b, 0) /\n\t\t\t\t\tthis.processingTimes.length\n\t\t\t\t: 0;\n\n\t\tconst remainingRows = this.totalRows - this.processedRows;\n\t\tconst estimatedTimeRemaining =\n\t\t\tremainingRows > 0 && avgProcessingTime > 0\n\t\t\t\t? remainingRows * avgProcessingTime\n\t\t\t\t: undefined;\n\n\t\t// Estimate cost (simplified - assumes ~1000 tokens per evaluation at $0.50 per 1M tokens)\n\t\tconst estimatedTokensRemaining = remainingRows * 1000;\n\t\tconst estimatedCostUSD = (this.totalTokens / 1_000_000) * 0.5;\n\n\t\tconst event: ProgressEvent = {\n\t\t\ttype,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttotalRows: this.totalRows,\n\t\t\tprocessedRows: this.processedRows,\n\t\t\tsuccessfulRows: this.successfulRows,\n\t\t\tfailedRows: this.failedRows,\n\t\t\tpercentComplete: (this.processedRows / this.totalRows) * 100,\n\t\t\taverageProcessingTime:\n\t\t\t\tavgProcessingTime > 0 ? avgProcessingTime : undefined,\n\t\t\testimatedTimeRemaining,\n\t\t\testimatedCostUSD,\n\t\t\testimatedTokensRemaining,\n\t\t\t...extra,\n\t\t};\n\n\t\t// Handle async onProgress\n\t\tconst result = this.onProgress(event);\n\t\tif (result instanceof Promise) {\n\t\t\tresult.catch((error) => {\n\t\t\t\tconsole.error(\"Error in progress callback:\", error);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get current progress without emitting\n\t */\n\tgetCurrentProgress(): ProgressEvent {\n\t\tconst avgProcessingTime =\n\t\t\tthis.processingTimes.length > 0\n\t\t\t\t? this.processingTimes.reduce((a, b) => a + b, 0) /\n\t\t\t\t\tthis.processingTimes.length\n\t\t\t\t: 0;\n\n\t\tconst remainingRows = this.totalRows - this.processedRows;\n\t\tconst estimatedTimeRemaining =\n\t\t\tremainingRows > 0 && avgProcessingTime > 0\n\t\t\t\t? remainingRows * avgProcessingTime\n\t\t\t\t: undefined;\n\n\t\tconst estimatedTokensRemaining = remainingRows * 1000;\n\t\tconst estimatedCostUSD = (this.totalTokens / 1_000_000) * 0.5;\n\n\t\treturn {\n\t\t\ttype: \"progress\",\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttotalRows: this.totalRows,\n\t\t\tprocessedRows: this.processedRows,\n\t\t\tsuccessfulRows: this.successfulRows,\n\t\t\tfailedRows: this.failedRows,\n\t\t\tpercentComplete: (this.processedRows / this.totalRows) * 100,\n\t\t\taverageProcessingTime:\n\t\t\t\tavgProcessingTime > 0 ? avgProcessingTime : undefined,\n\t\t\testimatedTimeRemaining,\n\t\t\testimatedCostUSD,\n\t\t\testimatedTokensRemaining,\n\t\t};\n\t}\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n\ttype EvalKitSpan,\n\tgetCachedTracer,\n\tSpanStatusCode,\n\twithSpan,\n} from \"../telemetry.js\";\nimport type { EvaluatorResult, IEvaluator } from \"../types/evaluator.js\";\nimport { ConcurrencyManager } from \"./concurrency-manager.js\";\nimport { CsvExporter } from \"./exporters/csv-exporter.js\";\nimport { JsonExporter } from \"./exporters/json-exporter.js\";\nimport { CsvParser } from \"./parsers/csv-parser.js\";\nimport { JsonParser } from \"./parsers/json-parser.js\";\nimport { ProgressTracker } from \"./progress-tracker.js\";\nimport type {\n\tBatchEvaluationResult,\n\tBatchEvaluatorConfig,\n\tBatchExportConfig,\n\tBatchInputConfig,\n\tBatchInputFileConfig,\n\tBatchInputRow,\n\tBatchResult,\n} from \"./types.js\";\n\nexport class BatchEvaluator {\n\tprivate readonly config: BatchEvaluatorConfig;\n\tprivate readonly evaluators: IEvaluator[];\n\tprivate readonly concurrencyManager: ConcurrencyManager;\n\tprivate progressTracker?: ProgressTracker;\n\tprivate batchId: string;\n\tprivate startTime: string;\n\tprivate results: BatchEvaluationResult[] = [];\n\tprivate processedRowIndices: Set<number> = new Set();\n\n\tconstructor(config: BatchEvaluatorConfig) {\n\t\tthis.config = config;\n\t\tthis.evaluators = [...config.evaluators];\n\t\tthis.batchId = randomUUID();\n\t\tthis.startTime = new Date().toISOString();\n\n\t\t// Initialize concurrency manager\n\t\tthis.concurrencyManager = new ConcurrencyManager({\n\t\t\tmaxConcurrency: config.concurrency ?? 5,\n\t\t\trateLimit: config.rateLimit,\n\t\t});\n\t}\n\n\t/**\n\t * Run batch evaluation on input data\n\t */\n\tasync evaluate(inputConfig: BatchInputConfig): Promise<BatchResult> {\n\t\treturn withSpan(\n\t\t\t\"eval-kit.batch.evaluate\",\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"eval_kit.batch.id\": this.batchId,\n\t\t\t\t\t\"eval_kit.batch.concurrency\": this.config.concurrency ?? 5,\n\t\t\t\t\t\"eval_kit.batch.execution_mode\":\n\t\t\t\t\t\tthis.config.evaluatorExecutionMode ?? \"parallel\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync (span) => {\n\t\t\t\t// Parse input\n\t\t\t\tconst allRows = await this.parseInput(inputConfig);\n\n\t\t\t\tspan.setAttribute(\"eval_kit.batch.total_rows\", allRows.length);\n\n\t\t\t\t// Handle startIndex for resuming from a specific position\n\t\t\t\tconst startIndex = inputConfig.startIndex ?? 0;\n\t\t\t\tconst rows = startIndex > 0 ? allRows.slice(startIndex) : allRows;\n\n\t\t\t\t// Mark rows before startIndex as already processed (for accurate progress tracking)\n\t\t\t\tfor (let i = 0; i < startIndex; i++) {\n\t\t\t\t\tthis.processedRowIndices.add(i);\n\t\t\t\t}\n\n\t\t\t\t// Initialize progress tracker (use total rows for accurate percentage)\n\t\t\t\tthis.progressTracker = new ProgressTracker({\n\t\t\t\t\ttotalRows: allRows.length,\n\t\t\t\t\temitInterval: this.config.progressInterval,\n\t\t\t\t\tonProgress: this.config.onProgress,\n\t\t\t\t});\n\t\t\t\tthis.progressTracker.start();\n\n\t\t\t\t// Fast-forward progress tracker for skipped rows\n\t\t\t\tif (startIndex > 0) {\n\t\t\t\t\tthis.progressTracker.skipRows(startIndex);\n\t\t\t\t}\n\n\t\t\t\t// Process rows with controlled concurrency\n\t\t\t\t// We batch into chunks to avoid creating all promises at once\n\t\t\t\tconst maxConcurrency = this.config.concurrency ?? 5;\n\t\t\t\tconst batchSize = maxConcurrency * 2; // Process in batches of 2x concurrency\n\n\t\t\t\tfor (let i = 0; i < rows.length; i += batchSize) {\n\t\t\t\t\tconst batch = rows.slice(i, i + batchSize);\n\t\t\t\t\tconst batchPromises = batch.map((row, batchIndex) =>\n\t\t\t\t\t\t// Adjust index to account for startIndex offset\n\t\t\t\t\t\tthis.processRow(row, startIndex + i + batchIndex),\n\t\t\t\t\t);\n\t\t\t\t\tawait Promise.all(batchPromises);\n\t\t\t\t}\n\n\t\t\t\t// Mark completion\n\t\t\t\tthis.progressTracker.complete();\n\n\t\t\t\t// Return results\n\t\t\t\tconst result = this.buildResult();\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\"eval_kit.batch.successful_rows\",\n\t\t\t\t\tresult.successfulRows,\n\t\t\t\t);\n\t\t\t\tspan.setAttribute(\"eval_kit.batch.failed_rows\", result.failedRows);\n\t\t\t\treturn result;\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Export results to a destination\n\t */\n\tasync export(exportConfig: BatchExportConfig): Promise<void> {\n\t\treturn withSpan(\n\t\t\t\"eval-kit.batch.export\",\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"eval_kit.export.format\": exportConfig.format,\n\t\t\t\t\t\"eval_kit.export.row_count\": this.results.length,\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst exporter = this.getExporter(exportConfig.format);\n\t\t\t\tawait exporter.export(this.results, exportConfig);\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Parse input - supports both file-based and in-memory data\n\t */\n\tprivate async parseInput(config: BatchInputConfig): Promise<BatchInputRow[]> {\n\t\t// In-memory data — no I/O, skip span\n\t\tif (\"data\" in config) {\n\t\t\treturn config.data;\n\t\t}\n\n\t\t// File-based config — actual I/O worth tracing\n\t\treturn withSpan(\n\t\t\t\"eval-kit.batch.parse_input\",\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"eval_kit.parse.input_format\": \"file\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync (span) => {\n\t\t\t\tconst fileConfig = config as BatchInputFileConfig;\n\t\t\t\tlet format = fileConfig.format;\n\n\t\t\t\t// Handle \"auto\" format detection\n\t\t\t\tif (!format || format === \"auto\") {\n\t\t\t\t\tformat = this.detectFormat(fileConfig.filePath);\n\t\t\t\t}\n\n\t\t\t\tconst parser = this.getParser(format);\n\t\t\t\tconst rows = await parser.parse(fileConfig);\n\n\t\t\t\tspan.setAttribute(\"eval_kit.parse.row_count\", rows.length);\n\t\t\t\treturn rows;\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Detect format from file extension\n\t */\n\tprivate detectFormat(filePath: string): \"csv\" | \"json\" {\n\t\tif (filePath.endsWith(\".csv\")) return \"csv\";\n\t\tif (filePath.endsWith(\".json\")) return \"json\";\n\t\tthrow new Error(\n\t\t\t`Cannot detect format from file extension: ${filePath}. Please specify format explicitly.`,\n\t\t);\n\t}\n\n\t/**\n\t * Get parser for format\n\t */\n\tprivate getParser(format: \"csv\" | \"json\"): CsvParser | JsonParser {\n\t\tswitch (format) {\n\t\t\tcase \"csv\":\n\t\t\t\treturn new CsvParser();\n\t\t\tcase \"json\":\n\t\t\t\treturn new JsonParser();\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported format: ${format}`);\n\t\t}\n\t}\n\n\t/**\n\t * Get exporter for format\n\t */\n\tprivate getExporter(format: \"csv\" | \"json\"): CsvExporter | JsonExporter {\n\t\tswitch (format) {\n\t\t\tcase \"csv\":\n\t\t\t\treturn new CsvExporter();\n\t\t\tcase \"json\":\n\t\t\t\treturn new JsonExporter();\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported export format: ${format}`);\n\t\t}\n\t}\n\n\t/**\n\t * Process a single row\n\t */\n\tprivate async processRow(row: BatchInputRow, index: number): Promise<void> {\n\t\t// Skip if already processed (resume scenario)\n\t\tif (this.processedRowIndices.has(index)) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.concurrencyManager.run(async () => {\n\t\t\tconst rowId = row.id ?? `row-${index}`;\n\t\t\tconst tracer = getCachedTracer();\n\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\t\"eval-kit.batch.process_row\",\n\t\t\t\t{\n\t\t\t\t\tattributes: { \"eval_kit.row.id\": rowId, \"eval_kit.row.index\": index },\n\t\t\t\t},\n\t\t\t\t(span: EvalKitSpan) => this.runRowWithSpan(row, index, span),\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async runRowWithSpan(\n\t\trow: BatchInputRow,\n\t\tindex: number,\n\t\tspan: EvalKitSpan,\n\t): Promise<void> {\n\t\tconst startTime = Date.now();\n\t\tlet spanError: string | undefined;\n\t\tconst inputData = { ...this.config.defaultInput, ...row };\n\t\tconst rowId = row.id ?? `row-${index}`;\n\n\t\ttry {\n\t\t\tawait this.executeRowWithRetry({\n\t\t\t\tinputData,\n\t\t\t\trow,\n\t\t\t\tindex,\n\t\t\t\trowId,\n\t\t\t\tspan,\n\t\t\t\tstartTime,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tspanError = error instanceof Error ? error.message : String(error);\n\t\t\tspan.recordException(error instanceof Error ? error : spanError);\n\t\t} finally {\n\t\t\tspan.setAttribute(\"eval_kit.row.duration_ms\", Date.now() - startTime);\n\t\t\tif (spanError) {\n\t\t\t\tspan.setAttribute(\"eval_kit.result.error\", spanError);\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR, message: spanError });\n\t\t\t} else {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t}\n\t\t\tspan.end();\n\t\t}\n\t}\n\n\tprivate async executeRowWithRetry(ctx: {\n\t\tinputData: BatchInputRow;\n\t\trow: BatchInputRow;\n\t\tindex: number;\n\t\trowId: string;\n\t\tspan: EvalKitSpan;\n\t\tstartTime: number;\n\t}): Promise<void> {\n\t\tlet retryCount = 0;\n\t\tconst maxRetries = this.config.retryConfig?.maxRetries ?? 3;\n\t\tlet lastError: unknown;\n\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\tawait this.executeRowEvaluation({ ...ctx, retryCount });\n\t\t\t\tctx.span.setAttribute(\"eval_kit.row.retry_count\", retryCount);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t\tconst errorCtx = {\n\t\t\t\t\terror,\n\t\t\t\t\tspan: ctx.span,\n\t\t\t\t\tstartTime: ctx.startTime,\n\t\t\t\t\tretryCount,\n\t\t\t\t\tmaxRetries,\n\t\t\t\t\trowId: ctx.rowId,\n\t\t\t\t\tindex: ctx.index,\n\t\t\t\t\trow: ctx.row,\n\t\t\t\t};\n\t\t\t\tconst shouldRetry = await this.handleRowError(errorCtx);\n\t\t\t\tif (!shouldRetry) {\n\t\t\t\t\tctx.span.setAttribute(\"eval_kit.row.retry_count\", retryCount);\n\t\t\t\t\tthrow lastError;\n\t\t\t\t}\n\t\t\t\tretryCount++;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async handleRowError(ctx: {\n\t\terror: unknown;\n\t\tspan: EvalKitSpan;\n\t\tstartTime: number;\n\t\tretryCount: number;\n\t\tmaxRetries: number;\n\t\trowId: string;\n\t\tindex: number;\n\t\trow: BatchInputRow;\n\t}): Promise<boolean> {\n\t\tconst errorMessage =\n\t\t\tctx.error instanceof Error ? ctx.error.message : String(ctx.error);\n\t\tconst shouldRetry = this.shouldRetry(\n\t\t\terrorMessage,\n\t\t\tctx.retryCount,\n\t\t\tctx.maxRetries,\n\t\t);\n\n\t\tif (shouldRetry) {\n\t\t\tconst nextAttempt = ctx.retryCount + 1;\n\t\t\tthis.progressTracker?.recordRetry(errorMessage, nextAttempt);\n\t\t\tconst delay = this.calculateRetryDelay(nextAttempt);\n\n\t\t\tctx.span.addEvent(\"retry\", {\n\t\t\t\t\"eval_kit.retry.attempt\": nextAttempt,\n\t\t\t\t\"eval_kit.retry.delay_ms\": delay,\n\t\t\t\t\"eval_kit.retry.error\": errorMessage,\n\t\t\t});\n\n\t\t\tawait this.sleep(delay);\n\t\t\treturn true;\n\t\t}\n\n\t\tconst durationMs = Date.now() - ctx.startTime;\n\t\tconst result: BatchEvaluationResult = {\n\t\t\trowId: ctx.rowId,\n\t\t\trowIndex: ctx.index,\n\t\t\tinput: ctx.row,\n\t\t\tresults: [],\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tdurationMs,\n\t\t\tretryCount: ctx.retryCount,\n\t\t\terror: errorMessage,\n\t\t};\n\n\t\tawait this.emitResult(result);\n\t\tthis.processedRowIndices.add(ctx.index);\n\t\tthis.progressTracker?.recordFailure(durationMs);\n\n\t\tif (this.config.stopOnError) {\n\t\t\tthrow new Error(\n\t\t\t\t`Stopping batch evaluation due to error: ${errorMessage}`,\n\t\t\t);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate calculateRetryDelay(attempt: number): number {\n\t\tconst baseDelay = this.config.retryConfig?.retryDelay ?? 1000;\n\t\treturn this.config.retryConfig?.exponentialBackoff\n\t\t\t? baseDelay * 2 ** (attempt - 1)\n\t\t\t: baseDelay;\n\t}\n\n\tprivate async emitResult(result: BatchEvaluationResult): Promise<void> {\n\t\tconst callbackResult = this.config.onResult?.(result);\n\t\tif (callbackResult instanceof Promise) {\n\t\t\tawait callbackResult;\n\t\t}\n\t\tthis.results.push(result);\n\t}\n\n\tprivate async executeRowEvaluation(ctx: {\n\t\tinputData: BatchInputRow;\n\t\tindex: number;\n\t\trowId: string;\n\t\tstartTime: number;\n\t\tretryCount: number;\n\t}): Promise<void> {\n\t\tconst evaluatorResults = await this.runEvaluators(ctx.inputData);\n\t\tconst durationMs = Date.now() - ctx.startTime;\n\t\tconst tokensUsed = evaluatorResults.reduce(\n\t\t\t(sum, r) => sum + (r.processingStats.tokenUsage?.totalTokens ?? 0),\n\t\t\t0,\n\t\t);\n\n\t\tconst result: BatchEvaluationResult = {\n\t\t\trowId: ctx.rowId,\n\t\t\trowIndex: ctx.index,\n\t\t\tinput: ctx.inputData,\n\t\t\tresults: evaluatorResults,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tdurationMs,\n\t\t\tretryCount: ctx.retryCount,\n\t\t};\n\n\t\tawait this.emitResult(result);\n\t\tthis.processedRowIndices.add(ctx.index);\n\t\tthis.progressTracker?.recordSuccess(durationMs, tokensUsed);\n\t}\n\n\t/**\n\t * Run all evaluators on a single row\n\t */\n\tprivate async runEvaluators(row: BatchInputRow): Promise<EvaluatorResult[]> {\n\t\treturn withSpan(\n\t\t\t\"eval-kit.batch.run_evaluators\",\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"eval_kit.evaluator_count\": this.evaluators.length,\n\t\t\t\t\t\"eval_kit.execution_mode\":\n\t\t\t\t\t\tthis.config.evaluatorExecutionMode ?? \"parallel\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst input = {\n\t\t\t\t\tcandidateText: row.candidateText,\n\t\t\t\t\tprompt: row.prompt,\n\t\t\t\t\treferenceText: row.referenceText,\n\t\t\t\t\tsourceText: row.sourceText,\n\t\t\t\t\tcontentType: row.contentType,\n\t\t\t\t\tlanguage: row.language,\n\t\t\t\t};\n\n\t\t\t\t// Apply timeout if configured\n\t\t\t\tconst timeout = this.config.timeout;\n\t\t\t\tconst evaluateWithTimeout = async (evaluator: IEvaluator) => {\n\t\t\t\t\tif (timeout) {\n\t\t\t\t\t\treturn Promise.race([\n\t\t\t\t\t\t\tevaluator.evaluate(input),\n\t\t\t\t\t\t\tthis.timeoutPromise(\n\t\t\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t\t\t`Evaluator ${evaluator.name} timed out after ${timeout}ms`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]);\n\t\t\t\t\t}\n\t\t\t\t\treturn evaluator.evaluate(input);\n\t\t\t\t};\n\n\t\t\t\t// Run evaluators in parallel or sequential mode\n\t\t\t\tif (this.config.evaluatorExecutionMode === \"sequential\") {\n\t\t\t\t\tconst results: EvaluatorResult[] = [];\n\t\t\t\t\tfor (const evaluator of this.evaluators) {\n\t\t\t\t\t\tconst result = await evaluateWithTimeout(evaluator);\n\t\t\t\t\t\tresults.push(result as EvaluatorResult);\n\t\t\t\t\t}\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t\t// Parallel mode (default)\n\t\t\t\tconst results = await Promise.all(\n\t\t\t\t\tthis.evaluators.map((evaluator) => evaluateWithTimeout(evaluator)),\n\t\t\t\t);\n\t\t\t\treturn results as EvaluatorResult[];\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Check if error should be retried\n\t * @param errorMessage The error message\n\t * @param currentAttempts Number of attempts made so far (0 = first attempt)\n\t * @param maxRetries Maximum number of retry attempts allowed\n\t * @returns true if should retry, false otherwise\n\t */\n\tprivate shouldRetry(\n\t\terrorMessage: string,\n\t\tcurrentAttempts: number,\n\t\tmaxRetries: number,\n\t): boolean {\n\t\t// If we've already made the maximum attempts, don't retry\n\t\t// currentAttempts starts at 0, so with maxRetries=3:\n\t\t// attempt 0 (first try), then retries at 1,2,3 = 4 total attempts\n\t\tif (currentAttempts >= maxRetries) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if error matches retry patterns\n\t\tconst retryOnErrors = this.config.retryConfig?.retryOnErrors;\n\t\tif (retryOnErrors && retryOnErrors.length > 0) {\n\t\t\treturn retryOnErrors.some((pattern) => errorMessage.includes(pattern));\n\t\t}\n\n\t\t// Default: retry on common transient errors\n\t\tconst transientErrors = [\n\t\t\t\"ECONNRESET\",\n\t\t\t\"ETIMEDOUT\",\n\t\t\t\"ENOTFOUND\",\n\t\t\t\"rate limit\",\n\t\t\t\"429\",\n\t\t\t\"503\",\n\t\t\t\"timeout\",\n\t\t];\n\t\treturn transientErrors.some((pattern) =>\n\t\t\terrorMessage.toLowerCase().includes(pattern.toLowerCase()),\n\t\t);\n\t}\n\n\t/**\n\t * Build final result\n\t */\n\tprivate buildResult(): BatchResult {\n\t\tconst endTime = new Date().toISOString();\n\t\tconst durationMs =\n\t\t\tnew Date(endTime).getTime() - new Date(this.startTime).getTime();\n\n\t\tconst successfulRows = this.results.filter((r) => !r.error).length;\n\t\tconst failedRows = this.results.filter((r) => r.error).length;\n\n\t\t// Calculate average processing time\n\t\tconst processingTimes = this.results.map((r) => r.durationMs);\n\t\tconst averageProcessingTime =\n\t\t\tprocessingTimes.length > 0\n\t\t\t\t? processingTimes.reduce((sum, t) => sum + t, 0) /\n\t\t\t\t\tprocessingTimes.length\n\t\t\t\t: 0;\n\n\t\t// Calculate total tokens\n\t\tconst totalTokensUsed = this.results.reduce(\n\t\t\t(sum, r) =>\n\t\t\t\tsum +\n\t\t\t\tr.results.reduce(\n\t\t\t\t\t(rSum, evalResult) =>\n\t\t\t\t\t\trSum + (evalResult.processingStats.tokenUsage?.totalTokens ?? 0),\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t0,\n\t\t);\n\n\t\treturn {\n\t\t\tbatchId: this.batchId,\n\t\t\tstartTime: this.startTime,\n\t\t\tendTime,\n\t\t\tdurationMs,\n\t\t\ttotalRows: this.results.length,\n\t\t\tsuccessfulRows,\n\t\t\tfailedRows,\n\t\t\tresults: this.results,\n\t\t\tsummary: {\n\t\t\t\taverageProcessingTime,\n\t\t\t\ttotalTokensUsed: totalTokensUsed > 0 ? totalTokensUsed : undefined,\n\t\t\t\terrorRate:\n\t\t\t\t\tthis.results.length > 0 ? failedRows / this.results.length : 0,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Create a timeout promise\n\t */\n\tprivate timeoutPromise<T>(ms: number, message: string): Promise<T> {\n\t\treturn new Promise((_, reject) => {\n\t\t\tsetTimeout(() => reject(new Error(message)), ms);\n\t\t});\n\t}\n\n\t/**\n\t * Sleep for specified milliseconds\n\t */\n\tprivate sleep(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n\n\t/**\n\t * Get current results (useful for streaming results)\n\t */\n\tgetCurrentResults(): BatchEvaluationResult[] {\n\t\treturn [...this.results];\n\t}\n}\n","export class TemplateRenderer {\n\trender(template: string, variables: Record<string, unknown>): string {\n\t\tlet result = template;\n\t\tresult = this.processConditionals(result, variables);\n\t\tresult = this.processVariables(result, variables);\n\t\treturn result.trim();\n\t}\n\n\tprivate processConditionals(\n\t\ttemplate: string,\n\t\tvariables: Record<string, unknown>,\n\t): string {\n\t\tconst conditionalRegex = /\\{\\{#if\\s+(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g;\n\n\t\treturn template.replace(conditionalRegex, (_, varName, content) => {\n\t\t\tconst value = variables[varName];\n\n\t\t\tconst isTruthy =\n\t\t\t\tvalue !== undefined &&\n\t\t\t\tvalue !== null &&\n\t\t\t\tvalue !== \"\" &&\n\t\t\t\tvalue !== false &&\n\t\t\t\t(typeof value !== \"object\" || Object.keys(value as object).length > 0);\n\n\t\t\treturn isTruthy ? content : \"\";\n\t\t});\n\t}\n\n\tprivate processVariables(\n\t\ttemplate: string,\n\t\tvariables: Record<string, unknown>,\n\t): string {\n\t\tconst variableRegex = /\\{\\{(\\w+)\\}\\}/g;\n\n\t\treturn template.replace(variableRegex, (_, varName) => {\n\t\t\tconst value = variables[varName];\n\n\t\t\tif (value === undefined || value === null) {\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\treturn this.stringify(value);\n\t\t});\n\t}\n\n\tprivate stringify(value: unknown): string {\n\t\tif (typeof value === \"string\") {\n\t\t\treturn value;\n\t\t}\n\n\t\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\treturn String(value);\n\t\t}\n\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\n\t\treturn String(value);\n\t}\n\n\tvalidate(template: string): string[] {\n\t\tconst errors: string[] = [];\n\n\t\tconst openIfs = (template.match(/\\{\\{#if\\s+\\w+\\}\\}/g) || []).length;\n\t\tconst closeIfs = (template.match(/\\{\\{\\/if\\}\\}/g) || []).length;\n\n\t\tif (openIfs !== closeIfs) {\n\t\t\terrors.push(\n\t\t\t\t`Mismatched conditional blocks: ${openIfs} opening {{#if}} but ${closeIfs} closing {{/if}}`,\n\t\t\t);\n\t\t}\n\n\t\tconst conditionalRegex = /\\{\\{#if\\s+\\w+\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g;\n\t\tconst matches = template.matchAll(conditionalRegex);\n\t\tfor (const match of matches) {\n\t\t\tconst content = match[1];\n\t\t\tif (content && /\\{\\{#if\\s+\\w+\\}\\}/.test(content)) {\n\t\t\t\terrors.push(\"Nested conditionals are not supported\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tconst unknownTags = template.match(/\\{\\{[#/](?!if|\\/if)[^}]*\\}\\}/g);\n\t\tif (unknownTags) {\n\t\t\terrors.push(`Unknown template tags: ${unknownTags.join(\", \")}`);\n\t\t}\n\n\t\treturn errors;\n\t}\n\n\textractVariables(template: string): string[] {\n\t\tconst variables = new Set<string>();\n\n\t\tconst conditionals = template.matchAll(/\\{\\{#if\\s+(\\w+)\\}\\}/g);\n\t\tfor (const match of conditionals) {\n\t\t\tvariables.add(match[1]);\n\t\t}\n\n\t\tconst substitutions = template.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n\t\tfor (const match of substitutions) {\n\t\t\tvariables.add(match[1]);\n\t\t}\n\n\t\treturn Array.from(variables);\n\t}\n\n\textractRequiredVariables(template: string): string[] {\n\t\tconst required = new Set<string>();\n\t\tconst optional = new Set<string>();\n\n\t\tconst conditionals = template.matchAll(\n\t\t\t/\\{\\{#if\\s+(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g,\n\t\t);\n\t\tfor (const match of conditionals) {\n\t\t\toptional.add(match[1]);\n\n\t\t\tconst innerVars = match[2]?.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n\t\t\tfor (const innerMatch of innerVars) {\n\t\t\t\toptional.add(innerMatch[1]);\n\t\t\t}\n\t\t}\n\n\t\tconst parts = template.split(/\\{\\{#if[\\s\\S]*?\\{\\{\\/if\\}\\}/g);\n\t\tfor (const part of parts) {\n\t\t\tconst substitutions = part.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n\t\t\tfor (const match of substitutions) {\n\t\t\t\tconst varName = match[1];\n\t\t\t\tif (!optional.has(varName)) {\n\t\t\t\t\trequired.add(varName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Array.from(required);\n\t}\n}\n","import { generateText, Output } from \"ai\";\nimport { z } from \"zod\";\nimport {\n\ttype EvalKitSpan,\n\tgetTracer,\n\tisTelemetryEnabled,\n\tSpanStatusCode,\n} from \"../telemetry.js\";\nimport type {\n\tEvaluationInput,\n\tEvaluatorConfig,\n\tEvaluatorResult,\n\tTokenUsage,\n} from \"../types/evaluator.js\";\nimport { TemplateRenderer } from \"../utils/template-engine.js\";\n\nfunction getNumber(value: unknown): number | undefined {\n\treturn typeof value === \"number\" ? value : undefined;\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn value && typeof value === \"object\"\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\nfunction hasNumberValue(value: Record<string, unknown>): boolean {\n\treturn Object.values(value).some((entry) => typeof entry === \"number\");\n}\n\nexport class Evaluator {\n\treadonly name: string;\n\treadonly timeout?: number;\n\n\tprivate readonly model: EvaluatorConfig[\"model\"];\n\tprivate readonly evaluationPrompt: string;\n\tprivate readonly scoreConfig: NonNullable<EvaluatorConfig[\"scoreConfig\"]>;\n\tprivate readonly modelSettings?: EvaluatorConfig[\"modelSettings\"];\n\tprivate readonly templateRenderer: TemplateRenderer;\n\n\tconstructor(config: EvaluatorConfig) {\n\t\tthis.name = config.name;\n\t\tthis.timeout = config.timeout;\n\n\t\tthis.model = config.model;\n\t\tthis.evaluationPrompt = config.evaluationPrompt;\n\t\tthis.scoreConfig = config.scoreConfig ?? {\n\t\t\ttype: \"numeric\",\n\t\t\tmin: 0,\n\t\t\tmax: 100,\n\t\t\tfloat: false,\n\t\t};\n\t\tthis.modelSettings = config.modelSettings;\n\n\t\tthis.templateRenderer = new TemplateRenderer();\n\n\t\tconst templateErrors = this.templateRenderer.validate(\n\t\t\tthis.evaluationPrompt,\n\t\t);\n\t\tif (templateErrors.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid evaluation prompt template: ${templateErrors.join(\"; \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync evaluate(input: EvaluationInput): Promise<EvaluatorResult> {\n\t\tconst tracer = await getTracer();\n\t\tconst modelId = (this.model as { modelId?: string }).modelId;\n\n\t\treturn tracer.startActiveSpan(\n\t\t\t\"eval-kit.evaluator.evaluate\",\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"eval_kit.evaluator.name\": this.name,\n\t\t\t\t\t\"eval_kit.model.id\": modelId ?? \"unknown\",\n\t\t\t\t\t\"eval_kit.score_config.type\": this.scoreConfig.type,\n\t\t\t\t\t\"eval_kit.input.candidate_text_length\": input.candidateText.length,\n\t\t\t\t},\n\t\t\t},\n\t\t\t(span: EvalKitSpan) => this.runEvaluation(input, modelId, span),\n\t\t);\n\t}\n\n\tprivate async runEvaluation(\n\t\tinput: EvaluationInput,\n\t\tmodelId: string | undefined,\n\t\tspan: EvalKitSpan,\n\t): Promise<EvaluatorResult> {\n\t\tconst startTime = Date.now();\n\t\tlet spanError: string | undefined;\n\t\tlet evaluatorResult: EvaluatorResult;\n\n\t\ttry {\n\t\t\tevaluatorResult = await this.executeEvaluation(input, modelId, span);\n\t\t} catch (error) {\n\t\t\tevaluatorResult = this.buildErrorResult(error, modelId, startTime);\n\t\t\tspanError = evaluatorResult.error;\n\t\t\tspan.recordException(\n\t\t\t\terror instanceof Error ? error : (spanError ?? String(error)),\n\t\t\t);\n\t\t} finally {\n\t\t\tspan.setAttribute(\n\t\t\t\t\"eval_kit.result.execution_time_ms\",\n\t\t\t\tDate.now() - startTime,\n\t\t\t);\n\t\t\tif (spanError) {\n\t\t\t\tspan.setAttribute(\"eval_kit.result.error\", spanError);\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR, message: spanError });\n\t\t\t} else {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t}\n\t\t\tspan.end();\n\t\t}\n\n\t\treturn evaluatorResult;\n\t}\n\n\tprivate buildErrorResult(\n\t\terror: unknown,\n\t\tmodelId: string | undefined,\n\t\tstartTime: number,\n\t): EvaluatorResult {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tconst errorDetails =\n\t\t\terror instanceof Error && \"cause\" in error\n\t\t\t\t? String(error.cause)\n\t\t\t\t: undefined;\n\t\tconst fullError = errorDetails\n\t\t\t? `${errorMessage} (${errorDetails})`\n\t\t\t: errorMessage;\n\n\t\treturn {\n\t\t\tevaluatorName: this.name,\n\t\t\tmodel: modelId,\n\t\t\tscore: 0,\n\t\t\tfeedback: `Evaluation failed: ${errorMessage}`,\n\t\t\tprocessingStats: { executionTime: Date.now() - startTime },\n\t\t\terror: fullError,\n\t\t};\n\t}\n\n\tprivate async executeEvaluation(\n\t\tinput: EvaluationInput,\n\t\tmodelId: string | undefined,\n\t\tspan: EvalKitSpan,\n\t): Promise<EvaluatorResult> {\n\t\tconst startTime = Date.now();\n\t\tconst prompt = this.buildPrompt(input);\n\t\tconst schema = this.createSchema();\n\n\t\tconst result = await generateText({\n\t\t\tmodel: this.model,\n\t\t\toutput: Output.object({ schema }),\n\t\t\tprompt,\n\t\t\ttemperature: this.modelSettings?.temperature,\n\t\t\tmaxOutputTokens: this.modelSettings?.maxOutputTokens,\n\t\t\ttopP: this.modelSettings?.topP,\n\t\t\ttopK: this.modelSettings?.topK,\n\t\t\tpresencePenalty: this.modelSettings?.presencePenalty,\n\t\t\tfrequencyPenalty: this.modelSettings?.frequencyPenalty,\n\t\t\tseed: this.modelSettings?.seed,\n\t\t\texperimental_telemetry: { isEnabled: isTelemetryEnabled() },\n\t\t});\n\n\t\tconst executionTime = Date.now() - startTime;\n\t\tconst tokenUsage = this.extractTokenUsage(result.usage);\n\n\t\tthis.setTokenAttributes(span, tokenUsage);\n\t\tspan.setAttribute(\"eval_kit.result.score\", result.output.score);\n\n\t\treturn {\n\t\t\tevaluatorName: this.name,\n\t\t\tmodel: modelId,\n\t\t\tscore: result.output.score,\n\t\t\tfeedback: result.output.feedback,\n\t\t\tprocessingStats: { executionTime, tokenUsage },\n\t\t};\n\t}\n\n\tprivate buildPrompt(input: EvaluationInput): string {\n\t\tconst variables = this.prepareVariables(input);\n\t\tconst scoreInstructions = this.formatScoreInstructions();\n\t\treturn `${this.templateRenderer.render(this.evaluationPrompt, variables)}\\n\\n${scoreInstructions}`;\n\t}\n\n\tprivate setTokenAttributes(\n\t\tspan: EvalKitSpan,\n\t\ttokenUsage: TokenUsage | undefined,\n\t): void {\n\t\tif (tokenUsage?.inputTokens !== undefined) {\n\t\t\tspan.setAttribute(\n\t\t\t\t\"eval_kit.result.token_usage.input\",\n\t\t\t\ttokenUsage.inputTokens,\n\t\t\t);\n\t\t}\n\t\tif (tokenUsage?.outputTokens !== undefined) {\n\t\t\tspan.setAttribute(\n\t\t\t\t\"eval_kit.result.token_usage.output\",\n\t\t\t\ttokenUsage.outputTokens,\n\t\t\t);\n\t\t}\n\t\tif (tokenUsage?.totalTokens !== undefined) {\n\t\t\tspan.setAttribute(\n\t\t\t\t\"eval_kit.result.token_usage.total\",\n\t\t\t\ttokenUsage.totalTokens,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate prepareVariables(input: EvaluationInput): Record<string, unknown> {\n\t\treturn {\n\t\t\tcandidateText: input.candidateText,\n\t\t\tprompt: input.prompt ?? \"\",\n\t\t\treferenceText: input.referenceText ?? \"\",\n\t\t\tsourceText: input.sourceText ?? \"\",\n\t\t\tname: this.name,\n\t\t\tcontentType: input.contentType ?? \"\",\n\t\t\tlanguage: input.language ?? \"\",\n\t\t};\n\t}\n\n\tprivate extractTokenUsage(usage: unknown): TokenUsage | undefined {\n\t\tif (!usage) return undefined;\n\t\tconst usageRecord = getRecord(usage);\n\t\tif (!usageRecord) return undefined;\n\n\t\tconst inputTokenDetails = this.extractInputTokenDetails(\n\t\t\tusageRecord.inputTokenDetails,\n\t\t);\n\t\tconst outputTokenDetails = this.extractOutputTokenDetails(\n\t\t\tusageRecord.outputTokenDetails,\n\t\t);\n\n\t\treturn {\n\t\t\tinputTokens: getNumber(usageRecord.inputTokens),\n\t\t\t...(inputTokenDetails ? { inputTokenDetails } : {}),\n\t\t\toutputTokens: getNumber(usageRecord.outputTokens),\n\t\t\t...(outputTokenDetails ? { outputTokenDetails } : {}),\n\t\t\ttotalTokens: getNumber(usageRecord.totalTokens),\n\t\t\treasoningTokens: getNumber(usageRecord.reasoningTokens),\n\t\t\tcachedInputTokens: getNumber(usageRecord.cachedInputTokens),\n\t\t};\n\t}\n\n\tprivate extractInputTokenDetails(\n\t\tdetails: unknown,\n\t): TokenUsage[\"inputTokenDetails\"] | undefined {\n\t\tconst detailRecord = getRecord(details);\n\t\tif (!detailRecord || !hasNumberValue(detailRecord)) return undefined;\n\n\t\treturn {\n\t\t\tnoCacheTokens: getNumber(detailRecord.noCacheTokens),\n\t\t\tcacheReadTokens: getNumber(detailRecord.cacheReadTokens),\n\t\t\tcacheWriteTokens: getNumber(detailRecord.cacheWriteTokens),\n\t\t};\n\t}\n\n\tprivate extractOutputTokenDetails(\n\t\tdetails: unknown,\n\t): TokenUsage[\"outputTokenDetails\"] | undefined {\n\t\tconst detailRecord = getRecord(details);\n\t\tif (!detailRecord || !hasNumberValue(detailRecord)) return undefined;\n\n\t\treturn {\n\t\t\ttextTokens: getNumber(detailRecord.textTokens),\n\t\t\treasoningTokens: getNumber(detailRecord.reasoningTokens),\n\t\t};\n\t}\n\n\tprivate createSchema(): z.ZodObject<{\n\t\tscore: z.ZodTypeAny;\n\t\tfeedback: z.ZodString;\n\t}> {\n\t\tif (this.scoreConfig.type === \"numeric\") {\n\t\t\tconst { min, max, float } = this.scoreConfig;\n\t\t\tlet scoreSchema: z.ZodNumber = z.number().min(min).max(max);\n\n\t\t\tif (float === false) {\n\t\t\t\tscoreSchema = scoreSchema.int();\n\t\t\t}\n\n\t\t\treturn z.object({\n\t\t\t\tscore: scoreSchema.describe(\n\t\t\t\t\t`Score from ${min} to ${max}${float === false ? \" (integer)\" : \"\"}`,\n\t\t\t\t),\n\t\t\t\tfeedback: z.string().describe(\"Detailed evaluation feedback\"),\n\t\t\t});\n\t\t}\n\n\t\treturn z.object({\n\t\t\tscore: z\n\t\t\t\t.enum(this.scoreConfig.categories as [string, ...string[]])\n\t\t\t\t.describe(\n\t\t\t\t\t`Score using one of: ${this.scoreConfig.categories.join(\", \")}`,\n\t\t\t\t),\n\t\t\tfeedback: z.string().describe(\"Detailed evaluation feedback\"),\n\t\t});\n\t}\n\n\tprivate formatScoreInstructions(): string {\n\t\tif (this.scoreConfig.type === \"numeric\") {\n\t\t\tconst { min, max, float } = this.scoreConfig;\n\t\t\tconst floatNote = float === false ? \" (integer)\" : \"\";\n\t\t\treturn `Provide a score from ${min} to ${max}${floatNote} where ${min} is worst and ${max} is best.`;\n\t\t}\n\n\t\tconst categories = this.scoreConfig.categories.join(\", \");\n\t\treturn `Provide a score using one of these categories (from worst to best): ${categories}`;\n\t}\n\n\tstatic create(\n\t\tname: string,\n\t\tmodel: EvaluatorConfig[\"model\"],\n\t\toptions?: {\n\t\t\tevaluationPrompt?: string;\n\t\t\tscoreConfig?: EvaluatorConfig[\"scoreConfig\"];\n\t\t\ttimeout?: number;\n\t\t\tmodelSettings?: EvaluatorConfig[\"modelSettings\"];\n\t\t\trequireReference?: boolean;\n\t\t},\n\t): Evaluator {\n\t\tconst useReference = options?.requireReference ?? false;\n\t\tconst referenceBlock = useReference\n\t\t\t? \"Reference: {{referenceText}}\"\n\t\t\t: \"{{#if referenceText}}Reference: {{referenceText}}{{/if}}\";\n\n\t\tconst defaultEvaluationPrompt = `Evaluate the {{name}} of the following text:\n\nText: {{candidateText}}\n${referenceBlock}\n\nProvide a detailed assessment.`;\n\n\t\treturn new Evaluator({\n\t\t\tname,\n\t\t\tmodel,\n\t\t\tevaluationPrompt: options?.evaluationPrompt ?? defaultEvaluationPrompt,\n\t\t\tscoreConfig: options?.scoreConfig,\n\t\t\ttimeout: options?.timeout,\n\t\t\tmodelSettings: options?.modelSettings,\n\t\t});\n\t}\n}\n","/**\n * eval-kit: TypeScript SDK for content evaluation\n *\n * A lightweight SDK for evaluating content quality.\n */\n\n// BERT score and perplexity use @huggingface/transformers which requires sharp.\n// Re-export types only; functions must be imported directly from submodules.\nexport type {\n\tBertScoreOptions,\n\tBertScoreResult,\n} from \"./metrics/bert-score.js\";\n// Metrics\nexport {\n\ttype BleuOptions,\n\ttype BleuResult,\n\tcalculateBleu,\n} from \"./metrics/bleu.js\";\nexport {\n\ttype CoherenceOptions,\n\ttype CoherenceResult,\n\tcalculateCoherence,\n} from \"./metrics/coherence.js\";\nexport type {\n\tPerplexityOptions,\n\tPerplexityResult,\n} from \"./metrics/perplexity.js\";\nexport {\n\tcalculateTer,\n\ttype TerOptions,\n\ttype TerResult,\n} from \"./metrics/ter.js\";\n\n// Lazy loaders for heavy metrics (avoid loading sharp at import time)\nexport async function loadBertScore() {\n\tconst mod = await import(\"./metrics/bert-score.js\");\n\treturn {\n\t\tcalculateBertScore: mod.calculateBertScore,\n\t\tclearBertCache: mod.clearBertCache,\n\t};\n}\n\nexport async function loadPerplexity() {\n\tconst mod = await import(\"./metrics/perplexity.js\");\n\treturn {\n\t\tcalculatePerplexity: mod.calculatePerplexity,\n\t\tclearPerplexityCache: mod.clearPerplexityCache,\n\t};\n}\n\n// Batch Evaluation\nexport { BatchEvaluator } from \"./batch/batch-evaluator.js\";\nexport type {\n\tBatchEvaluationResult,\n\tBatchEvaluatorConfig,\n\tBatchExportConfig,\n\tBatchInputConfig,\n\tBatchInputRow,\n\tBatchResult,\n\tProgressEvent,\n\tProgressEventType,\n} from \"./batch/types.js\";\n// Evaluator\nexport { Evaluator } from \"./evaluators/evaluator.js\";\n// Telemetry\nexport {\n\ttype EvalKitSpan,\n\tenableTelemetry,\n\tisTelemetryEnabled,\n\ttype WithSpanOptions,\n\twithSpan,\n} from \"./telemetry.js\";\nexport type {\n\tCategoricalScoreConfig,\n\tEvaluationInput,\n\tEvaluatorConfig,\n\tEvaluatorResult,\n\tIEvaluator,\n\tNumericScoreConfig,\n\tProcessingStats,\n\tScoreConfig,\n\tTemplateVariable,\n\tTokenUsage,\n} from \"./types/evaluator.js\";\nexport {\n\tcalculateNgramPrecision,\n\tcountNgrams,\n\tgenerateNgrams,\n} from \"./utils/ngram.js\";\nexport { cosineSimilarity } from \"./utils/similarity.js\";\n// Evaluator Utilities\nexport { TemplateRenderer } from \"./utils/template-engine.js\";\nexport { calculateIDF, calculateTFIDF } from \"./utils/tfidf.js\";\n// Utilities\nexport { tokenizeSentences, tokenizeWords } from \"./utils/tokenization.js\";\n"],"names":["distance","stringify","writeFile","readFile","parse","randomUUID","results","generateText","Output","z"],"mappings":"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"}