@agtlantis/eval 0.1.0 → 0.1.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/runner.ts","../src/multi-turn/types.ts","../src/core/errors.ts","../src/multi-turn/termination.ts","../src/utils/json.ts","../src/utils/condition-composites.ts","../src/multi-turn/conditions.ts","../src/multi-turn/runner.ts","../src/multi-turn/ai-user.ts","../src/utils/semaphore.ts","../src/core/constants.ts","../src/core/types.ts","../src/core/iteration.ts","../src/core/suite.ts","../src/index.ts","../src/judge/llm-judge.ts","../src/judge/prompts/default.ts","../src/judge/criteria/validate-schema.ts","../src/judge/criteria/index.ts","../src/reporter/markdown.ts","../src/reporter/json-reporter.ts","../src/reporter/cost-helpers.ts","../src/reporter/format-utils.ts","../src/reporter/markdown-reporter.ts","../src/reporter/console-reporter.ts","../src/reporter/composite-reporter.ts","../src/reporter/factory.ts","../src/reporter/runner.ts","../src/reporter/cycle-json.ts","../src/reporter/cycle-console.ts","../src/reporter/cycle-markdown.ts","../src/improver/utils.ts","../src/improver/llm-improver.ts","../src/improver/prompts/default.ts","../src/testing/mock-agent.ts","../src/cli/config/types.ts","../src/cli/config/loader.ts","../src/cli/config/schema.ts","../src/improvement-cycle/types.ts","../src/improvement-cycle/conditions.ts","../src/improvement-cycle/runner.ts","../src/improvement-cycle/history.ts","../src/core/test-case-collection.ts"],"sourcesContent":["import { resolveFileSourcesInInput } from '@agtlantis/core';\n\nimport type { Judge } from '@/judge/types';\nimport {\n type MultiTurnTestResult,\n executeMultiTurnTestCase,\n isMultiTurnTestCase,\n} from '@/multi-turn';\nimport { createSemaphore } from '@/utils/semaphore';\n\nimport { ZERO_TOKEN_USAGE } from './constants';\nimport { EvalError, EvalErrorCode } from './errors';\nimport type {\n EvalAgent,\n EvalTestResult,\n EvalTokenUsage,\n MetricsResult,\n MultiTurnResult,\n SingleTurnResult,\n TestCase,\n TestResult,\n TestResultWithVerdict,\n} from './types';\n\n/**\n * Options for running test cases.\n */\nexport interface RunOptions {\n /** Maximum number of concurrent test case executions. Defaults to 1 (sequential). */\n concurrency?: number;\n\n /** Stop execution after the first test failure. Defaults to false. */\n stopOnFirstFailure?: boolean;\n\n /** AbortSignal for cancelling execution */\n signal?: AbortSignal;\n\n /**\n * Number of times to run each test case. Defaults to 1.\n * When > 1, results include iteration statistics (mean, stdDev, passRate).\n */\n iterations?: number;\n}\n\n/**\n * Context required for executing a single test case.\n * @internal\n */\nexport interface ExecuteContext<TInput, TOutput> {\n agent: EvalAgent<TInput, TOutput>;\n judge: Judge;\n agentDescription: string;\n}\n\n/**\n * Executes a single test case and returns the result with verdict.\n *\n * Flow:\n * 1. Execute agent with test input\n * 2. Measure execution latency\n * 3. Collect token usage from agent metadata\n * 4. Evaluate output using Judge\n * 5. Return combined result with verdicts\n *\n * @example\n * ```typescript\n * const result = await executeTestCase(\n * { id: 'test-1', input: { query: 'Hello' } },\n * { agent: myAgent, judge: myJudge, agentDescription: 'A friendly bot' }\n * )\n *\n * console.log(result.passed) // true/false\n * console.log(result.overallScore) // 0-100\n * console.log(result.verdicts) // Verdict[]\n * ```\n */\nexport async function executeTestCase<TInput, TOutput>(\n testCase: TestCase<TInput>,\n context: ExecuteContext<TInput, TOutput>,\n signal?: AbortSignal\n): Promise<SingleTurnResult<TInput, TOutput>> {\n const { agent, judge, agentDescription } = context;\n\n if (signal?.aborted) {\n throw new EvalError('Test execution aborted', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, reason: 'aborted' },\n });\n }\n\n let resolvedInput: TInput;\n try {\n resolvedInput = await resolveFileSourcesInInput(testCase.input, {\n basePath: process.cwd(),\n });\n } catch (e) {\n const error = EvalError.from(e, EvalErrorCode.FILE_READ_ERROR, {\n testCaseId: testCase.id,\n agentName: agent.config.name,\n });\n return createFailedResult(testCase, error);\n }\n\n const startTime = performance.now();\n let output: TOutput;\n let tokenUsage: EvalTokenUsage = ZERO_TOKEN_USAGE;\n let error: Error | undefined;\n\n try {\n const agentResult = await agent.execute(resolvedInput);\n output = agentResult.result;\n if (agentResult.metadata?.tokenUsage) {\n tokenUsage = agentResult.metadata.tokenUsage;\n }\n } catch (e) {\n error = EvalError.from(e, EvalErrorCode.AGENT_EXECUTION_ERROR, {\n testCaseId: testCase.id,\n agentName: agent.config.name,\n });\n output = undefined as TOutput;\n }\n\n const latencyMs = performance.now() - startTime;\n\n const metrics: MetricsResult = { latencyMs, tokenUsage };\n const testResult: TestResult<TInput, TOutput> = { testCase, output, metrics, error };\n\n if (error) {\n return {\n kind: 'single-turn',\n ...testResult,\n verdicts: [],\n overallScore: 0,\n passed: false,\n judgeMetadata: undefined,\n };\n }\n\n if (signal?.aborted) {\n throw new EvalError('Test execution aborted before evaluation', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, reason: 'aborted' },\n });\n }\n\n const judgeResult = await judge.evaluate({\n input: testCase.input,\n output,\n agentDescription,\n files: testCase.files,\n });\n\n return {\n kind: 'single-turn',\n ...testResult,\n verdicts: judgeResult.verdicts,\n overallScore: judgeResult.overallScore,\n passed: judgeResult.passed,\n judgeMetadata: judgeResult.metadata,\n };\n}\n\nfunction createFailedResult<TInput, TOutput>(\n testCase: TestCase<TInput>,\n error: Error\n): SingleTurnResult<TInput, TOutput> {\n return {\n kind: 'single-turn',\n testCase,\n output: undefined as TOutput,\n metrics: { latencyMs: 0, tokenUsage: ZERO_TOKEN_USAGE },\n error,\n verdicts: [],\n overallScore: 0,\n passed: false,\n judgeMetadata: undefined,\n };\n}\n\n/**\n * Converts a MultiTurnTestResult to MultiTurnResult format.\n * This allows multi-turn results to flow through the same aggregation pipeline\n * as single-turn results while preserving multi-turn specific data.\n *\n * @internal\n */\nfunction toMultiTurnResult<TInput, TOutput>(\n result: MultiTurnTestResult<TInput, TOutput>\n): MultiTurnResult<TInput, TOutput> {\n return {\n kind: 'multi-turn',\n testCase: result.testCase,\n output: result.output as TOutput,\n metrics: result.metrics,\n verdicts: result.verdicts,\n overallScore: result.overallScore,\n passed: result.passed,\n judgeMetadata: result.judgeMetadata,\n conversationHistory: result.conversationHistory,\n totalTurns: result.totalTurns,\n terminationReason: result.termination.reason,\n termination: result.termination,\n };\n}\n\n/**\n * Runs multiple test cases with configurable concurrency.\n *\n * Features:\n * - Parallel execution with concurrency limit\n * - Stop on first failure option\n * - AbortSignal support for cancellation\n *\n * @example\n * ```typescript\n * const results = await runWithConcurrency(\n * testCases,\n * { agent: myAgent, judge: myJudge, agentDescription: 'Test agent' },\n * { concurrency: 5, stopOnFirstFailure: false }\n * )\n *\n * console.log(`Passed: ${results.filter(r => r.passed).length}`)\n * console.log(`Failed: ${results.filter(r => !r.passed).length}`)\n * ```\n */\nexport async function runWithConcurrency<TInput, TOutput>(\n testCases: TestCase<TInput>[],\n context: ExecuteContext<TInput, TOutput>,\n options: RunOptions = {}\n): Promise<EvalTestResult<TInput, TOutput>[]> {\n const { concurrency = 1, stopOnFirstFailure = false, signal } = options;\n\n if (concurrency < 1) {\n throw new EvalError('Concurrency must be at least 1', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { concurrency },\n });\n }\n\n if (testCases.length === 0) {\n return [];\n }\n\n const semaphore = createSemaphore(concurrency);\n const results: EvalTestResult<TInput, TOutput>[] = [];\n let shouldStop = false;\n let firstError: Error | undefined;\n const internalAbort = new AbortController();\n\n const propagateExternalAbort = () => {\n shouldStop = true;\n internalAbort.abort();\n };\n signal?.addEventListener('abort', propagateExternalAbort);\n\n if (signal?.aborted) {\n shouldStop = true;\n }\n\n try {\n const executeOne = async (testCase: TestCase<TInput>, index: number): Promise<void> => {\n if (shouldStop) return;\n\n await semaphore.acquire();\n\n try {\n if (shouldStop) return;\n\n const result = await executeTestCaseByType(testCase, context, internalAbort.signal);\n results[index] = result;\n\n if (stopOnFirstFailure && !result.passed) {\n shouldStop = true;\n internalAbort.abort();\n }\n } catch (e) {\n if (!firstError && !isAbortError(e)) {\n firstError = e instanceof Error ? e : new Error(String(e));\n }\n shouldStop = true;\n internalAbort.abort();\n } finally {\n semaphore.release();\n }\n };\n\n const promises = testCases.map((tc, i) => executeOne(tc, i));\n await Promise.allSettled(promises);\n\n if (firstError) {\n throw firstError;\n }\n\n return results.filter((r): r is EvalTestResult<TInput, TOutput> => r !== undefined);\n } finally {\n signal?.removeEventListener('abort', propagateExternalAbort);\n }\n}\n\nfunction isAbortError(e: unknown): boolean {\n return (\n (e instanceof DOMException && e.name === 'AbortError') ||\n (e instanceof EvalError && e.context?.reason === 'aborted')\n );\n}\n\nasync function executeTestCaseByType<TInput, TOutput>(\n testCase: TestCase<TInput>,\n context: ExecuteContext<TInput, TOutput>,\n signal: AbortSignal\n): Promise<EvalTestResult<TInput, TOutput>> {\n if (isMultiTurnTestCase<TInput, TOutput>(testCase)) {\n const multiTurnResult = await executeMultiTurnTestCase(testCase, context, { signal });\n return toMultiTurnResult(multiTurnResult);\n }\n return executeTestCase(testCase, context, signal);\n}\n","import type { AgentMetadata, TestCase, TestResultWithVerdict } from '@/core/types'\n\nexport type TerminationCondition<TInput = unknown, TOutput = unknown> =\n | MaxTurnsCondition\n | FieldSetCondition\n | FieldValueCondition\n | CustomCondition<TInput, TOutput>\n\nexport interface MaxTurnsCondition {\n type: 'maxTurns'\n /** Safety limit - terminates after this many turns */\n count: number\n}\n\nexport interface FieldsCondition {\n /** Dot notation for nested access (e.g., \"result.recommendation\") */\n fieldPath: string\n}\n\nexport interface FieldSetCondition extends FieldsCondition {\n type: 'fieldSet'\n}\n\nexport interface FieldValueCondition extends FieldsCondition {\n type: 'fieldValue'\n expectedValue: unknown\n}\n\nexport interface CustomCondition<TInput = unknown, TOutput = unknown> {\n type: 'custom'\n /** Sync or async check function (e.g., for LLM-based conditions) */\n check: (\n context: ConversationContext<TInput, TOutput>\n ) => boolean | Promise<boolean>\n /** For debugging/logging */\n description?: string\n}\n\nexport type TerminationType = 'condition' | 'maxTurns' | 'error' | 'exhausted'\n\nexport interface ContinueResult {\n terminated: false\n reason: string\n terminationType?: never\n matchedCondition?: never\n}\n\nexport interface TerminatedResult {\n terminated: true\n terminationType: TerminationType\n matchedCondition?: TerminationCondition<unknown, unknown>\n reason: string\n}\n\nexport type TerminationCheckResult = ContinueResult | TerminatedResult\n\nexport interface ConversationContext<TInput, TOutput = unknown> {\n currentTurn: number\n history: Array<{\n turn: number\n input: TInput\n output: TOutput | undefined\n metadata?: AgentMetadata\n }>\n lastOutput?: TOutput\n}\n\nexport interface FollowUpInput<TInput, TOutput = unknown> {\n /**\n * Input for this follow-up turn.\n * Can be static, dynamic (sync), or async (for AI-generated inputs via aiUser()).\n */\n input:\n | TInput\n | ((context: ConversationContext<TInput, TOutput>) => TInput)\n | ((context: ConversationContext<TInput, TOutput>) => Promise<TInput>)\n\n /** For debugging/reports */\n description?: string\n\n /**\n * Repeat count (default: 1).\n * Use Infinity to repeat until termination (must be last followUpInput).\n */\n turns?: number\n}\n\nexport interface MultiTurnTestCase<TInput, TOutput = unknown>\n extends TestCase<TInput> {\n multiTurn: {\n /** Inputs for 2nd turn onwards (first turn uses TestCase.input) */\n followUpInputs?: FollowUpInput<TInput, TOutput>[]\n\n /** Any condition triggers termination (OR logic) */\n terminateWhen: TerminationCondition<TInput, TOutput>[]\n\n /** Safety limit (default: 10). Uses min of this and any maxTurns condition. */\n maxTurns?: number\n\n /** Pass/fail when condition met (default: 'pass') */\n onConditionMet?: 'pass' | 'fail'\n\n /** Pass/fail when maxTurns reached (default: 'fail') */\n onMaxTurnsReached?: 'pass' | 'fail'\n }\n}\n\nexport interface MultiTurnTestResult<TInput, TOutput>\n extends Omit<TestResultWithVerdict<TInput, TOutput>, 'output'> {\n output: TOutput | undefined\n conversationHistory: Array<{\n turn: number\n input: TInput\n output: TOutput | undefined\n metadata?: AgentMetadata\n }>\n termination: TerminationCheckResult\n totalTurns: number\n}\n\nexport function isMaxTurnsCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is MaxTurnsCondition {\n return condition.type === 'maxTurns'\n}\n\nexport function isFieldSetCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is FieldSetCondition {\n return condition.type === 'fieldSet'\n}\n\nexport function isFieldValueCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is FieldValueCondition {\n return condition.type === 'fieldValue'\n}\n\nexport function isCustomCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is CustomCondition<TInput, TOutput> {\n return condition.type === 'custom'\n}\n\nexport function isMultiTurnTestCase<TInput, TOutput = unknown>(\n testCase: TestCase<TInput>\n): testCase is MultiTurnTestCase<TInput, TOutput> {\n return 'multiTurn' in testCase\n}\n\nexport function isTerminated(\n result: TerminationCheckResult\n): result is TerminatedResult {\n return result.terminated === true\n}\n","/**\n * Error codes for agent-eval operations\n */\nexport enum EvalErrorCode {\n // LLM errors\n LLM_API_ERROR = 'LLM_API_ERROR',\n LLM_RATE_LIMIT = 'LLM_RATE_LIMIT',\n LLM_TIMEOUT = 'LLM_TIMEOUT',\n\n // Parsing errors\n JSON_PARSE_ERROR = 'JSON_PARSE_ERROR',\n VERDICT_PARSE_ERROR = 'VERDICT_PARSE_ERROR',\n TEMPLATE_COMPILE_ERROR = 'TEMPLATE_COMPILE_ERROR',\n\n // Agent errors\n AGENT_EXECUTION_ERROR = 'AGENT_EXECUTION_ERROR',\n\n // Configuration errors\n INVALID_CONFIG = 'INVALID_CONFIG',\n MISSING_API_KEY = 'MISSING_API_KEY',\n\n // Prompt Repository errors\n PROMPT_NOT_FOUND = 'PROMPT_NOT_FOUND',\n PROMPT_INVALID_FORMAT = 'PROMPT_INVALID_FORMAT',\n PROMPT_WRITE_ERROR = 'PROMPT_WRITE_ERROR',\n PROMPT_READ_ERROR = 'PROMPT_READ_ERROR',\n\n // Suggestion apply errors\n SUGGESTION_APPLY_ERROR = 'SUGGESTION_APPLY_ERROR',\n\n // Schema validation errors\n SCHEMA_VALIDATION_ERROR = 'SCHEMA_VALIDATION_ERROR',\n SCHEMA_GENERATION_ERROR = 'SCHEMA_GENERATION_ERROR',\n\n // File context errors (Phase 5.3)\n FILE_READ_ERROR = 'FILE_READ_ERROR',\n FILE_WRITE_ERROR = 'FILE_WRITE_ERROR',\n FILE_TOO_LARGE = 'FILE_TOO_LARGE',\n\n // Concurrency errors\n CONCURRENT_MODIFICATION = 'CONCURRENT_MODIFICATION',\n\n // General errors\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\nexport interface EvalErrorOptions {\n code: EvalErrorCode\n cause?: Error\n context?: Record<string, unknown>\n}\n\n/**\n * Custom error class for agent-eval operations.\n * Provides structured error information including error code and optional context.\n */\nexport class EvalError extends Error {\n readonly code: EvalErrorCode\n readonly cause?: Error\n readonly context?: Record<string, unknown>\n\n constructor(message: string, options: EvalErrorOptions) {\n super(message)\n this.name = 'EvalError'\n this.code = options.code\n this.cause = options.cause\n this.context = options.context\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EvalError)\n }\n }\n\n /**\n * Creates an EvalError from an unknown error with a specific code.\n */\n static from(error: unknown, code: EvalErrorCode, context?: Record<string, unknown>): EvalError {\n if (error instanceof EvalError) {\n return error\n }\n\n const cause = error instanceof Error ? error : new Error(String(error))\n return new EvalError(cause.message, { code, cause, context })\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n cause: this.cause?.message,\n }\n }\n}\n","import type {\n ConversationContext,\n CustomCondition,\n FieldSetCondition,\n FieldValueCondition,\n MaxTurnsCondition,\n TerminationCheckResult,\n TerminationCondition,\n} from './types'\nimport {\n isCustomCondition,\n isFieldSetCondition,\n isFieldValueCondition,\n isMaxTurnsCondition,\n} from './types'\nimport { EvalError, EvalErrorCode } from '@/core/errors'\n\n/** Access a nested field value using dot notation (e.g., \"result.recommendation\"). */\nexport function getFieldValue(obj: unknown, fieldPath: string): unknown {\n if (obj === null || obj === undefined) {\n return undefined\n }\n\n const parts = fieldPath.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) {\n return undefined\n }\n\n if (typeof current !== 'object') {\n return undefined\n }\n\n current = (current as Record<string, unknown>)[part]\n }\n\n return current\n}\n\nfunction isSet(value: unknown): boolean {\n return value !== null && value !== undefined\n}\n\nfunction checkMaxTurns<TInput, TOutput>(\n condition: MaxTurnsCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const shouldTerminate = context.currentTurn >= condition.count\n\n if (shouldTerminate) {\n return {\n terminated: true,\n terminationType: 'maxTurns',\n matchedCondition: condition,\n reason: `Maximum turns reached (${condition.count})`,\n }\n }\n\n return {\n terminated: false,\n reason: `Turn ${context.currentTurn} of ${condition.count}`,\n }\n}\n\nfunction checkFieldSet<TInput, TOutput>(\n condition: FieldSetCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const fieldValue = getFieldValue(context.lastOutput, condition.fieldPath)\n const fieldIsSet = isSet(fieldValue)\n\n if (fieldIsSet) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition,\n reason: `Field \"${condition.fieldPath}\" is set (value: ${JSON.stringify(fieldValue)})`,\n }\n }\n\n return {\n terminated: false,\n reason: `Field \"${condition.fieldPath}\" is not set`,\n }\n}\n\nfunction checkFieldValue<TInput, TOutput>(\n condition: FieldValueCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const fieldValue = getFieldValue(context.lastOutput, condition.fieldPath)\n const matches = fieldValue === condition.expectedValue\n\n if (matches) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition,\n reason: `Field \"${condition.fieldPath}\" equals expected value`,\n }\n }\n\n return {\n terminated: false,\n reason: `Field \"${condition.fieldPath}\" does not equal expected value (got: ${JSON.stringify(fieldValue)})`,\n }\n}\n\nasync function checkCustom<TInput, TOutput>(\n condition: CustomCondition<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n const description = condition.description ?? 'Custom condition'\n\n try {\n const shouldTerminate = await condition.check(context)\n\n if (shouldTerminate) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition as TerminationCondition<unknown, unknown>,\n reason: `${description} met`,\n }\n }\n\n return {\n terminated: false,\n reason: `${description} not met`,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n terminated: false,\n reason: `${description} failed: ${errorMessage}`,\n }\n }\n}\n\nexport async function checkCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n if (isMaxTurnsCondition(condition)) {\n return checkMaxTurns(condition, context)\n }\n\n if (isFieldValueCondition(condition)) {\n return checkFieldValue(condition, context)\n }\n\n if (isFieldSetCondition(condition)) {\n return checkFieldSet(condition, context)\n }\n\n if (isCustomCondition(condition)) {\n return checkCustom(condition, context)\n }\n\n const _exhaustive: never = condition\n throw new EvalError(`Unknown condition type: ${JSON.stringify(_exhaustive)}`, {\n code: EvalErrorCode.UNKNOWN_ERROR,\n context: { condition: _exhaustive },\n })\n}\n\n/** Check all termination conditions (OR relationship). Returns on first termination. */\nexport async function checkTermination<TInput, TOutput>(\n conditions: TerminationCondition<TInput, TOutput>[],\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n if (conditions.length === 0) {\n return {\n terminated: false,\n reason: 'No termination conditions specified',\n }\n }\n\n for (const condition of conditions) {\n const result = await checkCondition(condition, context)\n if (result.terminated) {\n return result\n }\n }\n\n return {\n terminated: false,\n reason: 'No termination conditions met',\n }\n}\n","/**\n * Extracts JSON from LLM response, handling markdown code blocks.\n *\n * Supports:\n * - Raw JSON: `{\"key\": \"value\"}`\n * - Markdown code block: ```json\\n{...}\\n```\n * - Code block without annotation: ```\\n{...}\\n```\n * - JSON embedded in text: \"Here is my answer: {...} Hope this helps\"\n *\n * @example\n * ```typescript\n * const json = extractJson('```json\\n{\"foo\": \"bar\"}\\n```')\n * console.log(json) // '{\"foo\": \"bar\"}'\n * ```\n */\nexport function extractJson(content: string): string {\n const markdownCodeBlockMatch = content.match(/```(?:json)?\\s*([\\s\\S]*?)```/)\n if (markdownCodeBlockMatch) {\n return markdownCodeBlockMatch[1].trim()\n }\n\n const jsonObjectMatch = content.match(/\\{[\\s\\S]*\\}/)\n if (jsonObjectMatch) {\n return jsonObjectMatch[0]\n }\n\n return content.trim()\n}\n\n/**\n * Truncates a string to a maximum length with ellipsis.\n * Only adds \"...\" if the string was actually truncated.\n *\n * @example\n * ```typescript\n * truncate('hello', 10) // 'hello'\n * truncate('hello world', 5) // 'hello...'\n * ```\n */\nexport function truncate(str: string | undefined | null, maxLength: number): string {\n if (!str) {\n return ''\n }\n if (str.length <= maxLength) {\n return str\n }\n return str.slice(0, maxLength) + '...'\n}\n","/**\n * Shared Condition Composite Helpers\n *\n * These helper functions provide the core logic for AND/OR/NOT condition composites.\n * Domain-specific modules (multi-turn, improvement-cycle) use these helpers while\n * maintaining their own type definitions.\n *\n * @example\n * ```typescript\n * // In multi-turn/conditions.ts\n * import { createAndCheck } from '@/utils/condition-composites'\n *\n * export function and<TInput, TOutput>(\n * ...conditions: TerminationCondition<TInput, TOutput>[]\n * ): CustomCondition<TInput, TOutput> {\n * return {\n * type: 'custom',\n * check: createAndCheck(conditions, checkCondition),\n * description: `and(${conditions.map(c => c.type).join(', ')})`,\n * }\n * }\n * ```\n */\n\n/**\n * Result type expected from condition check functions.\n * Both multi-turn and improvement-cycle use this shape.\n */\nexport interface ConditionCheckResult {\n terminated: boolean\n}\n\n/**\n * Type for condition check functions.\n * The check function receives a condition and context, returns a result.\n */\nexport type ConditionCheckFn<TCondition, TContext> = (\n condition: TCondition,\n context: TContext\n) => ConditionCheckResult | Promise<ConditionCheckResult>\n\n/**\n * Create an AND check function.\n *\n * Returns a function that evaluates all conditions and returns true only if ALL terminate.\n * Short-circuits on first non-terminating condition.\n *\n * @param conditions - Array of conditions to check\n * @param checkFn - Function to check a single condition\n * @returns Async function that returns true if all conditions terminate\n */\nexport function createAndCheck<TCondition, TContext>(\n conditions: TCondition[],\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n for (const condition of conditions) {\n const result = await checkFn(condition, context)\n if (!result.terminated) {\n return false\n }\n }\n return true\n }\n}\n\n/**\n * Create an OR check function.\n *\n * Returns a function that evaluates conditions and returns true if ANY terminates.\n * Short-circuits on first terminating condition.\n *\n * @param conditions - Array of conditions to check\n * @param checkFn - Function to check a single condition\n * @returns Async function that returns true if any condition terminates\n */\nexport function createOrCheck<TCondition, TContext>(\n conditions: TCondition[],\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n for (const condition of conditions) {\n const result = await checkFn(condition, context)\n if (result.terminated) {\n return true\n }\n }\n return false\n }\n}\n\n/**\n * Create a NOT check function.\n *\n * Returns a function that inverts the result of a single condition check.\n *\n * @param condition - The condition to invert\n * @param checkFn - Function to check the condition\n * @returns Async function that returns true if condition does NOT terminate\n */\nexport function createNotCheck<TCondition, TContext>(\n condition: TCondition,\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n const result = await checkFn(condition, context)\n return !result.terminated\n }\n}\n\n/**\n * Format a description for composite conditions.\n *\n * @param type - Composite type ('and', 'or', 'not')\n * @param conditions - Conditions being composed\n * @returns Formatted description string\n */\nexport function formatCompositeDescription<TCondition extends { type: string }>(\n type: 'and' | 'or',\n conditions: TCondition[]\n): string {\n if (conditions.length === 0) {\n return `${type}() - empty, never terminates`\n }\n return `${type}(${conditions.map((c) => c.type).join(', ')})`\n}\n","import type { Provider } from '@agtlantis/core';\nimport { truncate } from '@/utils/json';\nimport { checkCondition } from './termination';\nimport type { ConversationContext, CustomCondition, TerminationCondition } from './types';\n\nimport {\n createAndCheck,\n createOrCheck,\n createNotCheck,\n formatCompositeDescription,\n} from '../utils/condition-composites';\n\nexport interface NaturalLanguageConditionOptions {\n /** Provider to use for evaluation */\n provider: Provider;\n /** Prompt describing the termination criteria (e.g., \"Has the user's question been fully answered?\") */\n prompt: string;\n /** Optional system prompt override */\n systemPrompt?: string;\n}\n\n/** LLM-based termination condition. Asks the LLM to evaluate the termination criteria. */\nexport function naturalLanguage<TInput = unknown, TOutput = unknown>(\n options: NaturalLanguageConditionOptions\n): CustomCondition<TInput, TOutput> {\n const { provider, prompt, systemPrompt } = options;\n\n const defaultSystemPrompt = `You are an assistant that evaluates whether a conversation should terminate.\nAnalyze the conversation history and determine if the specified condition is met.\nRespond with ONLY \"yes\" or \"no\" - nothing else.`;\n\n return {\n type: 'custom',\n check: async (context: ConversationContext<TInput, TOutput>) => {\n const historyText = context.history\n .map(\n (h) =>\n `Turn ${h.turn}:\\nInput: ${JSON.stringify(h.input)}\\nOutput: ${JSON.stringify(h.output)}`\n )\n .join('\\n\\n');\n\n const userPrompt = `## Termination Condition\n${prompt}\n\n## Conversation History\n${historyText || '(No history yet)'}\n\n## Current Turn\nTurn: ${context.currentTurn}\nLast Output: ${JSON.stringify(context.lastOutput)}\n\nShould the conversation terminate based on the condition above? Answer \"yes\" or \"no\" only.`;\n\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages: [\n { role: 'system', content: systemPrompt ?? defaultSystemPrompt },\n { role: 'user', content: userPrompt },\n ],\n });\n return result.text;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n const responseText = executionResult.value;\n const answer = responseText.toLowerCase().trim();\n return answer === 'yes' || answer.startsWith('yes');\n },\n description: `NL: ${truncate(prompt, 50)}`,\n };\n}\n\n/** Terminates when ALL sub-conditions are met (AND logic). */\nexport function and<TInput = unknown, TOutput = unknown>(\n ...conditions: TerminationCondition<TInput, TOutput>[]\n): CustomCondition<TInput, TOutput> {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('and', []),\n };\n }\n\n return {\n type: 'custom',\n check: createAndCheck(conditions, checkCondition),\n description: formatCompositeDescription('and', conditions),\n };\n}\n\n/** Terminates when ANY sub-condition is met (OR logic). Useful for nested composites. */\nexport function or<TInput = unknown, TOutput = unknown>(\n ...conditions: TerminationCondition<TInput, TOutput>[]\n): CustomCondition<TInput, TOutput> {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('or', []),\n };\n }\n\n return {\n type: 'custom',\n check: createOrCheck(conditions, checkCondition),\n description: formatCompositeDescription('or', conditions),\n };\n}\n\n/** Inverts another condition (NOT logic). */\nexport function not<TInput = unknown, TOutput = unknown>(\n condition: TerminationCondition<TInput, TOutput>\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: createNotCheck(condition, checkCondition),\n description: `not(${condition.type})`,\n };\n}\n\n/** Terminates after a specified number of turns. Convenience wrapper for use in composites. */\nexport function afterTurns<TInput = unknown, TOutput = unknown>(\n count: number\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: (context) => context.currentTurn >= count,\n description: `afterTurns(${count})`,\n };\n}\n\n/** Terminates when a field matches a specific value. Convenience wrapper for composites. */\nexport function fieldEquals<TInput = unknown, TOutput = unknown>(\n fieldPath: string,\n expectedValue: unknown\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: async (context) => {\n const result = await checkCondition(\n { type: 'fieldValue', fieldPath, expectedValue },\n context\n );\n return result.terminated;\n },\n description: `fieldEquals(${fieldPath}, ${JSON.stringify(expectedValue)})`,\n };\n}\n\n/** Terminates when a field is set (not null/undefined). Convenience wrapper for composites. */\nexport function fieldIsSet<TInput = unknown, TOutput = unknown>(\n fieldPath: string\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: async (context) => {\n const result = await checkCondition({ type: 'fieldSet', fieldPath }, context);\n return result.terminated;\n },\n description: `fieldIsSet(${fieldPath})`,\n };\n}\n","import { resolveFileSourcesInInput } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentMetadata, EvalAgent, EvalTokenUsage, MetricsResult } from '@/core/types';\nimport type { Judge } from '@/judge/types';\n\nimport { checkTermination } from './termination';\nimport type {\n ConversationContext,\n FollowUpInput,\n MultiTurnTestCase,\n MultiTurnTestResult,\n TerminationCheckResult,\n TerminationCondition,\n} from './types';\nimport { isTerminated } from './types';\n\nexport interface MultiTurnExecuteContext<TInput, TOutput> {\n agent: EvalAgent<TInput, TOutput>;\n judge: Judge;\n agentDescription: string;\n}\n\nexport interface MultiTurnExecuteOptions {\n signal?: AbortSignal;\n}\n\nconst DEFAULT_MAX_TURNS = 10;\nconst DEFAULT_ON_CONDITION_MET: 'pass' | 'fail' = 'pass';\nconst DEFAULT_ON_MAX_TURNS_REACHED: 'pass' | 'fail' = 'fail';\n\nfunction aggregateTokenUsage(usages: EvalTokenUsage[]): EvalTokenUsage {\n return usages.reduce(\n (acc, usage) => ({\n inputTokens: acc.inputTokens + usage.inputTokens,\n outputTokens: acc.outputTokens + usage.outputTokens,\n totalTokens: acc.totalTokens + usage.totalTokens,\n }),\n { inputTokens: 0, outputTokens: 0, totalTokens: 0 }\n );\n}\n\nfunction getEffectiveMaxTurns<TInput, TOutput>(\n conditions: TerminationCondition<TInput, TOutput>[],\n safetyLimit: number\n): number {\n const maxTurnsCondition = conditions.find((c) => c.type === 'maxTurns');\n if (maxTurnsCondition && maxTurnsCondition.type === 'maxTurns') {\n return Math.min(maxTurnsCondition.count, safetyLimit);\n }\n return safetyLimit;\n}\n\nasync function resolveInput<TInput, TOutput>(\n followUpInput: FollowUpInput<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TInput> {\n const inputValue = followUpInput.input;\n if (typeof inputValue === 'function') {\n const result = (\n inputValue as (ctx: ConversationContext<TInput, TOutput>) => TInput | Promise<TInput>\n )(context);\n return result instanceof Promise ? await result : result;\n }\n return inputValue as TInput;\n}\n\nfunction buildContext<TInput, TOutput>(\n currentTurn: number,\n history: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }>\n): ConversationContext<TInput, TOutput> {\n return {\n currentTurn,\n history,\n lastOutput: history.length > 0 ? history[history.length - 1].output : undefined,\n };\n}\n\nfunction getFollowUpInput<TInput, TOutput>(\n followUpInputs: FollowUpInput<TInput, TOutput>[],\n followUpIndex: number\n): FollowUpInput<TInput, TOutput> | null {\n let currentIndex = 0;\n\n for (const followUp of followUpInputs) {\n const repeatCount = followUp.turns ?? 1;\n\n if (!Number.isFinite(repeatCount) && followUpIndex >= currentIndex) {\n return followUp;\n }\n\n if (followUpIndex < currentIndex + repeatCount) {\n return followUp;\n }\n\n currentIndex += repeatCount;\n }\n\n return null;\n}\n\nfunction validateFollowUpInputs<TInput, TOutput>(\n followUpInputs: FollowUpInput<TInput, TOutput>[]\n): void {\n for (let i = 0; i < followUpInputs.length; i++) {\n const followUp = followUpInputs[i];\n\n if (followUp.turns === undefined) {\n continue;\n }\n\n if (typeof followUp.turns !== 'number' || followUp.turns < 1) {\n throw new EvalError('turns must be a positive number or Infinity', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: {\n description: followUp.description,\n turns: followUp.turns,\n },\n });\n }\n\n if (!Number.isFinite(followUp.turns) && i < followUpInputs.length - 1) {\n throw new EvalError(\n 'turns: Infinity must be the last followUpInput (subsequent items would be unreachable)',\n {\n code: EvalErrorCode.INVALID_CONFIG,\n context: {\n description: followUp.description,\n position: i,\n totalItems: followUpInputs.length,\n },\n }\n );\n }\n }\n}\n\ntype GetTurnInputResult<TInput> = { type: 'success'; input: TInput } | { type: 'exhausted' };\n\nasync function getTurnInput<TInput, TOutput>(\n turn: number,\n testCaseInput: TInput,\n followUpInputs: FollowUpInput<TInput, TOutput>[],\n conversationHistory: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }>\n): Promise<GetTurnInputResult<TInput>> {\n if (turn === 1) {\n return { type: 'success', input: testCaseInput };\n }\n\n const followUpIndex = turn - 2;\n const followUp = getFollowUpInput(followUpInputs, followUpIndex);\n\n if (!followUp) {\n return { type: 'exhausted' };\n }\n\n const ctx = buildContext(turn, conversationHistory);\n const input = await resolveInput(followUp, ctx);\n return { type: 'success', input };\n}\n\ninterface TurnExecutionResult<TOutput> {\n output: TOutput | undefined;\n metadata: AgentMetadata | undefined;\n latencyMs: number;\n error?: Error;\n}\n\nfunction isFileResolutionError<TOutput>(\n result: TurnExecutionResult<TOutput> | { type: 'fileResolutionError'; reason: string }\n): result is { type: 'fileResolutionError'; reason: string } {\n return 'type' in result && result.type === 'fileResolutionError';\n}\n\nasync function executeSingleTurn<TInput, TOutput>(\n input: TInput,\n agent: EvalAgent<TInput, TOutput>,\n testCaseId: string,\n turn: number\n): Promise<TurnExecutionResult<TOutput> | { type: 'fileResolutionError'; reason: string }> {\n let resolvedInput: TInput;\n try {\n resolvedInput = await resolveFileSourcesInInput(input, {\n basePath: process.cwd(),\n });\n } catch (e) {\n return {\n type: 'fileResolutionError',\n reason: `FileSource resolution failed on turn ${turn}: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n\n const startTime = performance.now();\n let output: TOutput | undefined;\n let metadata: AgentMetadata | undefined;\n let error: Error | undefined;\n\n try {\n const agentResult = await agent.execute(resolvedInput);\n output = agentResult.result;\n metadata = agentResult.metadata;\n } catch (e) {\n error = EvalError.from(e, EvalErrorCode.AGENT_EXECUTION_ERROR, {\n testCaseId,\n turn,\n agentName: agent.config.name,\n });\n }\n\n const latencyMs = performance.now() - startTime;\n return { output, metadata, latencyMs, error };\n}\n\nfunction determinePassFromTermination(\n termination: TerminationCheckResult,\n onConditionMet: 'pass' | 'fail',\n onMaxTurnsReached: 'pass' | 'fail'\n): boolean {\n if (!isTerminated(termination)) {\n return true;\n }\n\n switch (termination.terminationType) {\n case 'error':\n case 'exhausted':\n return false;\n case 'maxTurns':\n return onMaxTurnsReached === 'pass';\n case 'condition':\n return onConditionMet === 'pass';\n default:\n return true;\n }\n}\n\nexport async function executeMultiTurnTestCase<TInput, TOutput>(\n testCase: MultiTurnTestCase<TInput, TOutput>,\n context: MultiTurnExecuteContext<TInput, TOutput>,\n options?: MultiTurnExecuteOptions\n): Promise<MultiTurnTestResult<TInput, TOutput>> {\n const { agent, judge, agentDescription } = context;\n const { multiTurn } = testCase;\n const signal = options?.signal;\n\n const maxTurns = getEffectiveMaxTurns(\n multiTurn.terminateWhen,\n multiTurn.maxTurns ?? DEFAULT_MAX_TURNS\n );\n const onConditionMet = multiTurn.onConditionMet ?? DEFAULT_ON_CONDITION_MET;\n const onMaxTurnsReached = multiTurn.onMaxTurnsReached ?? DEFAULT_ON_MAX_TURNS_REACHED;\n const followUpInputs = multiTurn.followUpInputs ?? [];\n\n validateFollowUpInputs(followUpInputs);\n\n const conversationHistory: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }> = [];\n const tokenUsages: EvalTokenUsage[] = [];\n let totalLatencyMs = 0;\n let termination: TerminationCheckResult = {\n terminated: false,\n reason: 'Execution not started',\n };\n\n for (let turn = 1; turn <= maxTurns; turn++) {\n if (signal?.aborted) {\n throw new EvalError('Multi-turn test execution aborted', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, turn, reason: 'aborted' },\n });\n }\n\n const inputResult = await getTurnInput(\n turn,\n testCase.input,\n followUpInputs,\n conversationHistory\n );\n if (inputResult.type === 'exhausted') {\n termination = {\n terminated: true,\n terminationType: 'exhausted',\n reason: 'All follow-up inputs exhausted',\n };\n break;\n }\n const input = inputResult.input;\n\n const turnResult = await executeSingleTurn(input, agent, testCase.id ?? 'unknown', turn);\n if (isFileResolutionError(turnResult)) {\n termination = {\n terminated: true,\n terminationType: 'error',\n reason: turnResult.reason,\n };\n break;\n }\n\n const {\n output: agentOutput,\n metadata: agentMetadata,\n latencyMs,\n error: agentError,\n } = turnResult;\n totalLatencyMs += latencyMs;\n\n const turnUsage = agentMetadata?.tokenUsage ?? {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n tokenUsages.push(turnUsage);\n\n conversationHistory.push({\n turn,\n input,\n output: agentOutput,\n metadata: agentMetadata,\n });\n\n if (agentError) {\n termination = {\n terminated: true,\n terminationType: 'error',\n reason: `Agent execution failed on turn ${turn}: ${agentError.message}`,\n };\n break;\n }\n\n const ctx = buildContext(turn, conversationHistory);\n termination = await checkTermination(multiTurn.terminateWhen, ctx);\n\n if (termination.terminated) {\n break;\n }\n\n if (turn >= maxTurns) {\n termination = {\n terminated: true,\n terminationType: 'maxTurns',\n matchedCondition: { type: 'maxTurns', count: maxTurns },\n reason: `Maximum turns reached (${maxTurns})`,\n };\n break;\n }\n }\n\n const aggregatedTokenUsage = aggregateTokenUsage(tokenUsages);\n const metrics: MetricsResult = {\n latencyMs: totalLatencyMs,\n tokenUsage: aggregatedTokenUsage,\n };\n\n const lastTurn = conversationHistory[conversationHistory.length - 1];\n const finalOutput = lastTurn?.output;\n\n const judgeResult = await judge.evaluate({\n input: testCase.input,\n output: finalOutput,\n agentDescription,\n files: testCase.files,\n });\n\n const passedTermination = determinePassFromTermination(\n termination,\n onConditionMet,\n onMaxTurnsReached\n );\n const passed = passedTermination && judgeResult.passed;\n\n return {\n testCase,\n output: finalOutput,\n metrics,\n verdicts: judgeResult.verdicts,\n overallScore: judgeResult.overallScore,\n passed,\n judgeMetadata: judgeResult.metadata,\n conversationHistory,\n termination,\n totalTurns: conversationHistory.length,\n };\n}\n","import type { Provider } from '@agtlantis/core';\nimport type { ConversationContext } from './types';\n\nexport interface AIUserOptions<TInput, TOutput> {\n /** Provider for generating user responses */\n provider: Provider;\n\n /** System prompt (string or function for dynamic personas). Uses default if not provided. */\n systemPrompt?: string | ((context: ConversationContext<TInput, TOutput>) => string);\n\n /** Custom history formatter. Default: JSON-based \"User: {input}\\nAssistant: {output}\" format. */\n formatHistory?: (context: ConversationContext<TInput, TOutput>) => string;\n\n /** Convert LLM text response to TInput. Has access to full context for structured input building. */\n buildInput: (llmResponse: string, context: ConversationContext<TInput, TOutput>) => TInput;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are simulating a realistic user in a conversation with an AI assistant.\n\n## Your Role\nGenerate natural, context-appropriate user messages based on the conversation history.\n\n## Guidelines\n\n1. **Stay in Character**: Respond as a real user would - with natural language, occasional typos, or casual phrasing when appropriate.\n\n2. **Be Goal-Oriented**: Users have objectives. Pursue them logically based on the conversation context:\n - If the assistant asks a question, provide a reasonable answer\n - If clarification is needed, ask for it naturally\n - If a task is progressing, guide it toward completion\n\n3. **React Appropriately**: Respond to what the assistant says:\n - Acknowledge when the assistant is helpful\n - Express confusion if the response is unclear\n - Correct misunderstandings if they occur\n\n4. **Keep It Realistic**: Real users:\n - Don't always provide perfect information upfront\n - May change their mind or add requirements\n - Sometimes need time to think or decide\n\n## Output Format\nRespond with ONLY the user's message. No additional formatting, explanation, or meta-commentary.`;\n\n/**\n * Creates an async function that generates user inputs using an LLM for multi-turn testing.\n *\n * @example\n * ```typescript\n * aiUser({\n * provider: openai,\n * systemPrompt: 'You are a friendly customer.',\n * buildInput: (response, ctx) => ({ message: response }),\n * })\n * ```\n */\nexport function aiUser<TInput, TOutput>(\n options: AIUserOptions<TInput, TOutput>\n): (context: ConversationContext<TInput, TOutput>) => Promise<TInput> {\n const { provider, systemPrompt, formatHistory, buildInput } = options;\n\n const defaultFormatHistory = (ctx: ConversationContext<TInput, TOutput>): string =>\n ctx.history\n .map(\n (h, i) =>\n `[Turn ${i + 1}]\\nUser: ${JSON.stringify(h.input)}\\nAssistant: ${JSON.stringify(h.output)}`\n )\n .join('\\n\\n');\n\n return async (context: ConversationContext<TInput, TOutput>): Promise<TInput> => {\n const historyText = (formatHistory ?? defaultFormatHistory)(context);\n\n const resolvedSystemPrompt =\n typeof systemPrompt === 'function'\n ? systemPrompt(context)\n : (systemPrompt ?? DEFAULT_SYSTEM_PROMPT);\n\n const userPrompt = historyText\n ? `## Conversation History\\n${historyText}\\n\\n## Your Task\\nGenerate the next user message based on the conversation above:`\n : `## Your Task\\nThis is the start of a new conversation. Generate an appropriate opening message from the user:`;\n\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages: [\n { role: 'system', content: resolvedSystemPrompt },\n { role: 'user', content: userPrompt },\n ],\n });\n return result.text;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n const responseText = executionResult.value;\n return buildInput(responseText, context);\n };\n}\n","/**\n * A simple semaphore for limiting concurrent operations.\n *\n * @example\n * ```typescript\n * const semaphore = createSemaphore(3) // Allow 3 concurrent operations\n *\n * async function doWork(id: number) {\n * await semaphore.acquire()\n * try {\n * console.log(`Starting work ${id}`)\n * await someAsyncOperation()\n * } finally {\n * semaphore.release()\n * }\n * }\n *\n * // Launch 10 tasks, but only 3 run at a time\n * await Promise.all(Array.from({ length: 10 }, (_, i) => doWork(i)))\n * ```\n */\nexport interface Semaphore {\n /**\n * Acquires a slot from the semaphore.\n * If no slots are available, waits until one is released.\n */\n acquire(): Promise<void>\n\n /**\n * Releases a slot back to the semaphore.\n * Must be called after acquire() completes, typically in a finally block.\n */\n release(): void\n}\n\n/**\n * Creates a semaphore with the specified concurrency limit.\n *\n * @param limit - Maximum number of concurrent operations allowed\n * @returns A Semaphore instance\n */\nexport function createSemaphore(limit: number): Semaphore {\n let running = 0\n const waiting: Array<() => void> = []\n\n return {\n async acquire(): Promise<void> {\n if (running < limit) {\n running++\n return\n }\n return new Promise<void>((resolve) => {\n waiting.push(resolve)\n })\n },\n\n release(): void {\n running--\n const next = waiting.shift()\n if (next) {\n running++\n next()\n }\n },\n }\n}\n","/**\n * Evaluation Constants\n *\n * Centralized constants used across the evaluation system.\n * Eliminates magic numbers and provides semantic names.\n */\n\n/**\n * Score-related constants.\n */\nexport const SCORE = {\n /** Minimum possible score */\n MIN: 0,\n /** Maximum possible score */\n MAX: 100,\n /** Default threshold for passing evaluation */\n DEFAULT_PASS_THRESHOLD: 70,\n /** Threshold for majority-based pass determination (50%) */\n MAJORITY_PASS_THRESHOLD: 0.5,\n} as const\n\n/**\n * Default configuration values.\n */\nexport const DEFAULTS = {\n /** Default maximum turns for multi-turn conversations */\n MAX_TURNS: 10,\n /** Default concurrency for parallel execution */\n CONCURRENCY: 1,\n} as const\n\n\n/**\n * Zero token usage - used for error cases or initialization.\n */\nexport const ZERO_TOKEN_USAGE = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n} as const\n\n/**\n * Type for score values (0-100).\n */\nexport type Score = number\n","/**\n * Simplified token usage type for eval package.\n *\n * This is a subset of AI SDK's LanguageModelUsage that only includes\n * the properties eval actually tracks. The cost-helpers module handles\n * conversion when calling @agtlantis/core's pricing calculator.\n *\n * @example\n * ```typescript\n * const usage: EvalTokenUsage = {\n * inputTokens: 100,\n * outputTokens: 50,\n * totalTokens: 150,\n * }\n * ```\n */\nexport interface EvalTokenUsage {\n /** Number of input (prompt) tokens */\n inputTokens: number;\n /** Number of output (completion) tokens */\n outputTokens: number;\n /** Total tokens (input + output) */\n totalTokens: number;\n}\n\n/**\n * Simplified agent configuration for evaluation.\n * Only requires fields needed for eval purposes.\n *\n * For agents from `ai-agents` package with full AgentConfig,\n * use `toEvalAgent()` adapter to convert them.\n */\nexport interface EvalAgentConfig {\n /** Agent name for identification */\n name: string;\n /** Agent description (used by Judge for context) */\n description?: string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Agent prompt template.\n */\nexport interface AgentPrompt<TInput> {\n /** Prompt unique ID for version tracking */\n id: string;\n /** Version string (e.g., \"1.0.0\") */\n version: string;\n /** System prompt */\n system: string;\n /** User template string (for serialization/history) */\n userTemplate?: string;\n /** User prompt builder function */\n renderUserPrompt: (input: TInput) => string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Base metadata type shared by all LLM-using components (Agent, Judge, Improver).\n * Provides consistent structure for tracking token usage and model information.\n *\n * @example\n * ```typescript\n * const metadata: ComponentMetadata = {\n * tokenUsage: { inputTokens: 100, outputTokens: 50, totalTokens: 150 },\n * model: 'gpt-4o',\n * }\n * ```\n */\nexport interface ComponentMetadata {\n /** Token usage from the LLM call (AI SDK LanguageModelUsage format) */\n tokenUsage?: EvalTokenUsage;\n /** Model identifier used for the LLM call */\n model?: string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Agent execution result metadata.\n * Extends ComponentMetadata with agent-specific fields.\n */\nexport interface AgentMetadata extends ComponentMetadata {\n /** Prompt version used for execution */\n promptVersion?: string;\n /** Execution duration in milliseconds */\n duration?: number;\n}\n\n/**\n * Judge evaluation metadata.\n * Tracks token usage and model for cost calculation.\n */\nexport interface JudgeMetadata extends ComponentMetadata {}\n\n/**\n * Improver analysis metadata.\n * Tracks token usage and model for cost calculation.\n */\nexport interface ImproverMetadata extends ComponentMetadata {}\n\n/**\n * Agent execution result.\n */\nexport interface AgentResult<TOutput> {\n result: TOutput;\n metadata?: AgentMetadata;\n}\n\n/**\n * Simplified Agent interface for evaluation.\n *\n * @example\n * ```typescript\n * // Direct implementation\n * const myAgent: EvalAgent<string, string> = {\n * config: { name: 'MyAgent', description: 'A simple agent' },\n * prompt: { id: 'prompt-1', version: '1.0.0', system: '...', renderUserPrompt: (input) => input },\n * execute: async (input) => ({ result: `Processed: ${input}` })\n * }\n *\n * // Or adapt from full ai-agents Agent\n * const evalAgent = toEvalAgent(fullAgent)\n * ```\n */\nexport interface EvalAgent<TInput, TOutput> {\n readonly config: EvalAgentConfig;\n readonly prompt: AgentPrompt<TInput>;\n execute(input: TInput, options?: unknown): Promise<AgentResult<TOutput>>;\n}\n\n/**\n * Full AgentConfig interface (compatible with ai-agents package).\n * Used for type-safe adaptation.\n */\nexport interface FullAgentConfig {\n name: string;\n role: 'generator' | 'analyzer' | 'validator' | 'enhancer';\n streaming: 'required' | 'optional' | 'none';\n execution: 'batch' | 'realtime';\n conversation?: 'single-turn' | 'multi-turn';\n description?: string;\n [key: string]: unknown;\n}\n\n/**\n * Full Agent interface (compatible with ai-agents package).\n * Used for type-safe adaptation.\n */\nexport interface FullAgent<TInput, TOutput> {\n readonly config: FullAgentConfig;\n readonly prompt: AgentPrompt<TInput>;\n execute(\n input: TInput,\n options?: unknown\n ): Promise<{\n result: TOutput;\n metadata: {\n duration: number;\n promptVersion: string;\n tokenUsage?: EvalTokenUsage;\n model?: string;\n retryCount?: number;\n traceId?: string;\n [key: string]: unknown;\n };\n }>;\n}\n\n/**\n * Adapts a full Agent (from ai-agents) to EvalAgent for evaluation.\n * Extracts only the fields needed for evaluation.\n *\n * @example\n * ```typescript\n * import { scenarioGenerator } from './agents/mce'\n *\n * const evalAgent = toEvalAgent(scenarioGenerator)\n * const suite = createEvalSuite({ agent: evalAgent, ... })\n * ```\n */\nexport function toEvalAgent<TInput, TOutput>(\n agent: FullAgent<TInput, TOutput>\n): EvalAgent<TInput, TOutput> {\n return {\n config: {\n name: agent.config.name,\n description: agent.config.description,\n },\n prompt: agent.prompt,\n execute: async (input, options) => {\n const result = await agent.execute(input, options);\n return {\n result: result.result,\n metadata: result.metadata,\n };\n },\n };\n}\n\n/**\n * Metadata for file content.\n */\nexport interface FileContentMetadata {\n /** File size in bytes */\n size?: number;\n /** Full resolved path (for loaded files) */\n fullPath?: string;\n /** Whether the content was created inline (not from disk) */\n inline?: boolean;\n /** Additional custom metadata */\n [key: string]: unknown;\n}\n\nexport interface FileContent {\n /** File path (relative or absolute) - used as identifier */\n path: string;\n /** File content as string (text files only for Phase 5.3) */\n content: string;\n /** Optional MIME type hint (defaults to 'text/plain') */\n mediaType?: string;\n /** Optional encoding (defaults to 'utf-8') */\n encoding?: BufferEncoding;\n /** Optional metadata (e.g., original size, full path, etc.) */\n metadata?: FileContentMetadata;\n}\n\nexport interface TestCase<TInput> {\n id?: string;\n input: TInput;\n tags?: string[];\n description?: string;\n expectedOutput?: unknown; // Optional reference for checking\n /**\n * Optional file context for agent and judge (Phase 5.3).\n * Files are passed to Judge for evaluation context.\n * For Agent access, include files in the input type directly.\n *\n * @deprecated Use FileSource in input directly for flexible file handling\n */\n files?: FileContent[];\n}\n\nexport interface MetricsResult {\n latencyMs: number;\n tokenUsage: EvalTokenUsage;\n}\n\nexport interface Criterion {\n id: string;\n name: string;\n description: string;\n weight?: number;\n}\n\n/**\n * Zod error issue - minimal type compatible with ZodError.errors.\n * Using `readonly` and rest index to be compatible with Zod's discriminated union.\n */\nexport type ZodIssue = {\n readonly code: string;\n readonly path: readonly (string | number)[];\n readonly message: string;\n};\n\n/**\n * Result of programmatic schema validation.\n */\nexport interface SchemaValidationResult {\n /** Whether the output matches the schema */\n valid: boolean;\n /** Validation errors if invalid (Zod issue format) */\n errors?: readonly ZodIssue[];\n /** Human-readable error summary */\n errorSummary?: string;\n}\n\n/**\n * Validator function type for programmatic validation.\n * Returns validation result with binary pass/fail outcome.\n */\nexport type ValidatorFn = (output: unknown) => SchemaValidationResult;\n\n/**\n * Extended criterion with optional programmatic validator.\n * Validators run before LLM evaluation with binary scoring (0 or 100).\n *\n * @example\n * ```typescript\n * import { z } from 'zod'\n * import { schema } from '@agtlantis/eval'\n *\n * const criterion = schema({\n * schema: z.object({ name: z.string() }),\n * weight: 2,\n * })\n * ```\n */\nexport interface ValidatorCriterion extends Criterion {\n /**\n * Optional programmatic validator.\n * If provided and fails, score is automatically 0.\n * If provided and passes, score is automatically 100.\n */\n validator?: ValidatorFn;\n}\n\nexport interface Verdict {\n criterionId: string;\n score: number; // 0-100\n reasoning: string;\n passed: boolean;\n}\n\nexport interface TestResult<TInput, TOutput> {\n testCase: TestCase<TInput>;\n output: TOutput;\n metrics: MetricsResult;\n error?: Error;\n}\n\nexport interface TestResultWithVerdict<TInput, TOutput> extends TestResult<TInput, TOutput> {\n verdicts: Verdict[];\n overallScore: number;\n passed: boolean;\n /** Judge metadata for cost tracking */\n judgeMetadata?: JudgeMetadata;\n}\n\n/**\n * Statistics from running the same test multiple times.\n * Used to measure consistency and reliability of LLM-based agents.\n */\nexport interface IterationStats {\n /** Total number of iterations run */\n iterations: number;\n /** Score from each iteration */\n scores: number[];\n /** Average score across all iterations */\n mean: number;\n /** Standard deviation (lower = more consistent) */\n stdDev: number;\n /** Lowest score achieved */\n min: number;\n /** Highest score achieved */\n max: number;\n /** Pass rate as decimal (0-1, e.g., 0.67 = 67%) */\n passRate: number;\n /** Number of iterations that passed */\n passCount: number;\n}\n\n/**\n * Extended iteration statistics for multi-turn tests.\n * Includes turn-count metrics and termination type distribution.\n *\n * @example\n * ```typescript\n * if (hasMultiTurnIterationData(result)) {\n * console.log(`Average turns: ${result.multiTurnIterationStats.avgTurns}`)\n * console.log(`Termination types: ${JSON.stringify(result.multiTurnIterationStats.terminationCounts)}`)\n * }\n * ```\n */\nexport interface MultiTurnIterationStats extends IterationStats {\n /** Average number of turns across all iterations */\n avgTurns: number;\n /** Minimum turns in any iteration */\n minTurns: number;\n /** Maximum turns in any iteration */\n maxTurns: number;\n /** Distribution of termination types across iterations (e.g., { condition: 2, maxTurns: 1 }) */\n terminationCounts: Record<string, number>;\n}\n\n/**\n * Discriminator for eval result types.\n * Used for exhaustive pattern matching on result variants.\n */\nexport type EvalResultKind =\n | 'single-turn'\n | 'single-turn-iterated'\n | 'multi-turn'\n | 'multi-turn-iterated';\n\n/**\n * Properties present when test ran with multiple iterations.\n * Extracted as a separate interface for composition.\n */\nexport interface IterationData<TInput, TOutput> {\n /** Aggregated statistics across all iterations */\n iterationStats: IterationStats;\n /** Individual results from each iteration */\n iterationResults: TestResultWithVerdict<TInput, TOutput>[];\n}\n\n/**\n * Single conversation entry in multi-turn tests.\n */\nexport interface ConversationEntry<TInput, TOutput> {\n /** Turn number (1-based) */\n turn: number;\n /** Input provided for this turn */\n input: TInput;\n /** Output from agent (undefined if execution failed) */\n output: TOutput | undefined;\n /** Agent execution metadata */\n metadata?: AgentMetadata;\n}\n\n/**\n * Termination info for multi-turn tests.\n * Compatible with TerminationCheckResult from multi-turn module.\n */\nexport interface TerminationInfo {\n /** Whether the conversation terminated */\n terminated: boolean;\n /** Human-readable reason for termination */\n reason: string;\n /** Type of termination (condition, maxTurns, error, exhausted) */\n terminationType?: string;\n /** The condition that caused termination (if applicable) */\n matchedCondition?: unknown;\n}\n\n/**\n * Properties present for multi-turn test results.\n * Extracted as a separate interface for composition.\n */\nexport interface MultiTurnData<TInput, TOutput> {\n /** Full conversation history */\n conversationHistory: ConversationEntry<TInput, TOutput>[];\n /** Total turns executed */\n totalTurns: number;\n /** Human-readable termination reason */\n terminationReason: string;\n /** Full termination check result */\n termination: TerminationInfo;\n}\n\n/**\n * Single-turn test result with single iteration (base case).\n * No iteration stats, no multi-turn data.\n */\nexport interface SingleTurnResult<TInput, TOutput> extends TestResultWithVerdict<TInput, TOutput> {\n readonly kind: 'single-turn';\n}\n\n/**\n * Single-turn test result with multiple iterations.\n * Has iteration stats but no multi-turn data.\n */\nexport interface SingleTurnIteratedResult<TInput, TOutput>\n extends TestResultWithVerdict<TInput, TOutput>, IterationData<TInput, TOutput> {\n readonly kind: 'single-turn-iterated';\n}\n\n/**\n * Multi-turn test result with single iteration.\n * Has multi-turn data but no iteration stats.\n */\nexport interface MultiTurnResult<TInput, TOutput>\n extends TestResultWithVerdict<TInput, TOutput>, MultiTurnData<TInput, TOutput> {\n readonly kind: 'multi-turn';\n}\n\n/**\n * Multi-turn test result with multiple iterations.\n * Has both multi-turn data and iteration stats.\n */\nexport interface MultiTurnIteratedResult<TInput, TOutput>\n extends\n TestResultWithVerdict<TInput, TOutput>,\n IterationData<TInput, TOutput>,\n MultiTurnData<TInput, TOutput> {\n readonly kind: 'multi-turn-iterated';\n /** Multi-turn specific iteration statistics */\n multiTurnIterationStats: MultiTurnIterationStats;\n}\n\n/**\n * Unified eval result type - discriminated union of all result kinds.\n *\n * Use pattern matching on `kind` for exhaustive handling:\n * @example\n * ```typescript\n * switch (result.kind) {\n * case 'single-turn':\n * // No iteration stats, no multi-turn data\n * break\n * case 'single-turn-iterated':\n * console.log(result.iterationStats.mean) // Type-safe\n * break\n * case 'multi-turn':\n * console.log(result.conversationHistory) // Type-safe\n * break\n * case 'multi-turn-iterated':\n * console.log(result.multiTurnIterationStats.avgTurns) // Type-safe\n * break\n * }\n * ```\n */\nexport type EvalTestResult<TInput, TOutput> =\n | SingleTurnResult<TInput, TOutput>\n | SingleTurnIteratedResult<TInput, TOutput>\n | MultiTurnResult<TInput, TOutput>\n | MultiTurnIteratedResult<TInput, TOutput>;\n\n/**\n * Check if result is from a single-turn test (either iterated or not).\n *\n * @example\n * ```typescript\n * if (isSingleTurnResult(result)) {\n * // result is SingleTurnResult | SingleTurnIteratedResult\n * console.log('Single turn test')\n * }\n * ```\n */\nexport function isSingleTurnResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is SingleTurnResult<TInput, TOutput> | SingleTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'single-turn' || result.kind === 'single-turn-iterated';\n}\n\n/**\n * Check if result is from a multi-turn test (either iterated or not).\n *\n * @example\n * ```typescript\n * if (isMultiTurnResult(result)) {\n * // result is MultiTurnResult | MultiTurnIteratedResult\n * console.log(`Turns: ${result.totalTurns}`) // Type-safe\n * for (const entry of result.conversationHistory) { // Type-safe\n * console.log(`Turn ${entry.turn}: ${entry.input}`)\n * }\n * }\n * ```\n */\nexport function isMultiTurnResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'multi-turn' || result.kind === 'multi-turn-iterated';\n}\n\n/**\n * Check if result has iteration data (multiple iterations ran).\n *\n * @example\n * ```typescript\n * if (isIteratedResult(result)) {\n * // result is SingleTurnIteratedResult | MultiTurnIteratedResult\n * console.log(`Mean score: ${result.iterationStats.mean}`) // Type-safe\n * console.log(`Pass rate: ${result.iterationStats.passRate}`) // Type-safe\n * }\n * ```\n */\nexport function isIteratedResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'single-turn-iterated' || result.kind === 'multi-turn-iterated';\n}\n","/**\n * Iteration statistics utilities for repeated test execution.\n *\n * These functions aggregate results from running the same test multiple times,\n * providing statistical metrics like mean, standard deviation, and pass rate.\n */\n\nimport type {\n EvalTestResult,\n IterationStats,\n MultiTurnIteratedResult,\n MultiTurnResult,\n MultiTurnIterationStats,\n SingleTurnIteratedResult,\n SingleTurnResult,\n TestResultWithVerdict,\n} from './types.js'\nimport { isMultiTurnResult } from './types.js'\nimport { EvalError, EvalErrorCode } from './errors'\nimport { SCORE } from './constants'\n\n/**\n * Calculate iteration statistics from multiple test results.\n *\n * @param results - Results from running the same test multiple times\n * @returns Aggregated statistics including mean, stdDev, and passRate\n *\n * @example\n * ```typescript\n * const stats = calculateIterationStats([\n * { overallScore: 85, passed: true, ... },\n * { overallScore: 90, passed: true, ... },\n * { overallScore: 80, passed: true, ... },\n * ])\n * // stats.mean = 85\n * // stats.stdDev ≈ 4.08\n * // stats.passRate = 1.0\n * ```\n */\nexport function calculateIterationStats(\n results: TestResultWithVerdict<unknown, unknown>[]\n): IterationStats {\n if (results.length === 0) {\n return {\n iterations: 0,\n scores: [],\n mean: 0,\n stdDev: 0,\n min: 0,\n max: 0,\n passRate: 0,\n passCount: 0,\n }\n }\n\n const scores = results.map((r) => r.overallScore)\n const passCount = results.filter((r) => r.passed).length\n\n const mean = scores.reduce((sum, s) => sum + s, 0) / scores.length\n\n // Population standard deviation (not sample)\n const variance =\n scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length\n const stdDev = Math.sqrt(variance)\n\n return {\n iterations: results.length,\n scores,\n mean,\n stdDev,\n min: Math.min(...scores),\n max: Math.max(...scores),\n passRate: passCount / results.length,\n passCount,\n }\n}\n\n/**\n * Calculate multi-turn specific iteration statistics.\n *\n * Extends base iteration stats with turn counts and termination type distribution.\n * Used when aggregating multiple iterations of multi-turn tests.\n *\n * @param results - Results from running the same multi-turn test multiple times\n * @returns Extended statistics including avgTurns, min/max turns, and terminationCounts\n *\n * @example\n * ```typescript\n * const stats = calculateMultiTurnIterationStats(results)\n * // stats.avgTurns = 4.2\n * // stats.minTurns = 3\n * // stats.maxTurns = 6\n * // stats.terminationCounts = { condition: 2, maxTurns: 1 }\n * ```\n */\nexport function calculateMultiTurnIterationStats<TInput, TOutput>(\n results: (MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[]\n): MultiTurnIterationStats {\n const baseStats = calculateIterationStats(results)\n\n // Extract turns from results (all multi-turn results have totalTurns)\n const turns = results.map((r) => r.totalTurns)\n\n // Count termination types from termination.terminationType\n const terminationCounts: Record<string, number> = {}\n for (const r of results) {\n const type = r.termination.terminationType\n if (type) {\n terminationCounts[type] = (terminationCounts[type] || 0) + 1\n }\n }\n\n return {\n ...baseStats,\n avgTurns: turns.length > 0 ? turns.reduce((a, b) => a + b, 0) / turns.length : 0,\n minTurns: turns.length > 0 ? Math.min(...turns) : 0,\n maxTurns: turns.length > 0 ? Math.max(...turns) : 0,\n terminationCounts,\n }\n}\n\n/**\n * Select the result closest to the mean score.\n * Used to pick a \"representative\" result for displaying verdicts/reasoning.\n *\n * The function preserves the full type of the input array, so if you pass\n * `TestResultWithIteration[]`, you get back `TestResultWithIteration`.\n *\n * @param results - Array of results to choose from (must not be empty)\n * @param mean - The mean score to compare against\n * @returns The result with overallScore closest to mean\n * @throws Error if results array is empty\n */\nexport function selectRepresentativeResult<\n TInput,\n TOutput,\n T extends TestResultWithVerdict<TInput, TOutput> = TestResultWithVerdict<TInput, TOutput>,\n>(results: T[], mean: number): T {\n if (results.length === 0) {\n throw new EvalError('Cannot select representative result from empty array', {\n code: EvalErrorCode.UNKNOWN_ERROR,\n })\n }\n\n return results.reduce((closest, current) => {\n const closestDiff = Math.abs(closest.overallScore - mean)\n const currentDiff = Math.abs(current.overallScore - mean)\n return currentDiff < closestDiff ? current : closest\n })\n}\n\n/**\n * Aggregate results from multiple iteration runs into iterated result types.\n *\n * Takes N arrays of results (one per iteration) and groups them by test case,\n * calculating iteration statistics for each test case.\n *\n * For multi-turn tests, returns MultiTurnIteratedResult with multi-turn specific\n * statistics like average turns, min/max turns, and termination type distribution.\n *\n * For single-turn tests, returns SingleTurnIteratedResult with base iteration stats.\n *\n * @param allIterationResults - Array of arrays: outer = iterations, inner = test cases\n * @returns Aggregated results with iteration statistics\n *\n * @example\n * ```typescript\n * // 3 iterations, 2 test cases each\n * const allResults = [\n * [testCase1_iter1, testCase2_iter1], // iteration 1\n * [testCase1_iter2, testCase2_iter2], // iteration 2\n * [testCase1_iter3, testCase2_iter3], // iteration 3\n * ]\n *\n * const aggregated = aggregateIterationResults(allResults)\n * // aggregated[0] = testCase1 with stats from iter1, iter2, iter3\n * // aggregated[1] = testCase2 with stats from iter1, iter2, iter3\n *\n * // For multi-turn tests:\n * // aggregated[0].kind === 'multi-turn-iterated'\n * // aggregated[0].multiTurnIterationStats = { avgTurns, minTurns, maxTurns, terminationCounts }\n * ```\n */\nexport function aggregateIterationResults<TInput, TOutput>(\n allIterationResults: EvalTestResult<TInput, TOutput>[][]\n): (SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[] {\n if (allIterationResults.length === 0) {\n return []\n }\n\n const testCount = allIterationResults[0].length\n const aggregated: (SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[] = []\n\n for (let i = 0; i < testCount; i++) {\n const resultsForTestCase = allIterationResults.map((iteration) => iteration[i])\n const stats = calculateIterationStats(resultsForTestCase)\n const representative = selectRepresentativeResult(resultsForTestCase, stats.mean)\n const isMultiTurn = resultsForTestCase.some((r) => isMultiTurnResult(r))\n const passedByMajority = stats.passRate >= SCORE.MAJORITY_PASS_THRESHOLD\n\n if (isMultiTurn) {\n const multiTurnResults = resultsForTestCase.filter(\n (r): r is MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> =>\n isMultiTurnResult(r)\n )\n const multiTurnRep = representative as MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>\n\n const aggregatedResult: MultiTurnIteratedResult<TInput, TOutput> = {\n kind: 'multi-turn-iterated',\n testCase: multiTurnRep.testCase,\n output: multiTurnRep.output,\n metrics: multiTurnRep.metrics,\n verdicts: multiTurnRep.verdicts,\n error: multiTurnRep.error,\n overallScore: stats.mean,\n passed: passedByMajority,\n iterationStats: stats,\n iterationResults: resultsForTestCase,\n conversationHistory: multiTurnRep.conversationHistory,\n totalTurns: multiTurnRep.totalTurns,\n terminationReason: multiTurnRep.terminationReason,\n termination: multiTurnRep.termination,\n multiTurnIterationStats: calculateMultiTurnIterationStats(multiTurnResults),\n }\n aggregated.push(aggregatedResult)\n } else {\n const aggregatedResult: SingleTurnIteratedResult<TInput, TOutput> = {\n kind: 'single-turn-iterated',\n testCase: representative.testCase,\n output: representative.output,\n metrics: representative.metrics,\n verdicts: representative.verdicts,\n error: representative.error,\n overallScore: stats.mean,\n passed: passedByMajority,\n iterationStats: stats,\n iterationResults: resultsForTestCase,\n }\n aggregated.push(aggregatedResult)\n }\n }\n\n return aggregated\n}\n\ntype IteratedResult<TInput, TOutput> = SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>\n\nfunction filterIteratedResults<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): IteratedResult<TInput, TOutput>[] {\n return results.filter(\n (r): r is IteratedResult<TInput, TOutput> =>\n r.kind === 'single-turn-iterated' || r.kind === 'multi-turn-iterated'\n )\n}\n\nfunction averageIterationStat<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[],\n selector: (stats: IterationStats) => number\n): number | undefined {\n const iteratedResults = filterIteratedResults(results)\n if (iteratedResults.length === 0) {\n return undefined\n }\n const total = iteratedResults.reduce((sum, r) => sum + selector(r.iterationStats), 0)\n return total / iteratedResults.length\n}\n\n/**\n * Calculate average standard deviation across multiple test results.\n * Used for report summary.\n *\n * @param results - Eval results (only iterated results have stats)\n * @returns Average stdDev across all iterated tests, or undefined if no iteration data\n */\nexport function calculateAvgStdDev<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): number | undefined {\n return averageIterationStat(results, (stats) => stats.stdDev)\n}\n\n/**\n * Calculate average pass rate across multiple test results.\n * Used for report summary.\n *\n * @param results - Eval results (only iterated results have stats)\n * @returns Average passRate across all iterated tests, or undefined if no iteration data\n */\nexport function calculateAvgPassRate<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): number | undefined {\n return averageIterationStat(results, (stats) => stats.passRate)\n}\n","import type {\n EvalAgent,\n EvalTestResult,\n TestCase,\n TestResultWithVerdict,\n} from './types'\nimport type { Judge } from '@/judge/types'\nimport type { Improver, AggregatedMetrics, Suggestion } from '@/improver/types'\nimport type { EvalReport, ReportSummary } from '@/reporter/types'\nimport { runWithConcurrency, type RunOptions } from './runner'\nimport {\n aggregateIterationResults,\n calculateAvgPassRate,\n calculateAvgStdDev,\n} from './iteration'\nimport { EvalError, EvalErrorCode } from './errors'\n\nexport type { RunOptions } from './runner'\n\n/**\n * Configuration for creating an EvalSuite.\n *\n * @example\n * ```typescript\n * const suite = createEvalSuite({\n * agent: myAgent,\n * judge: myJudge,\n * agentDescription: 'Recommends career paths based on student profiles',\n * })\n * ```\n */\nexport interface EvalSuiteConfig<TInput, TOutput> {\n /** The agent to evaluate */\n agent: EvalAgent<TInput, TOutput>\n\n /** Human-readable description of what the agent does (used by Judge) */\n agentDescription?: string\n\n /** Judge instance for evaluating agent outputs */\n judge: Judge\n\n /** Improver instance for generating prompt improvement suggestions (optional) */\n improver?: Improver\n}\n\n/**\n * Evaluation suite for running test cases against an agent.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases, { concurrency: 3 })\n * console.log(reportToMarkdown(report))\n *\n * // Test with a different agent\n * const newReport = await suite.withAgent(improvedAgent).run(testCases)\n * ```\n */\nexport interface EvalSuite<TInput, TOutput> {\n /**\n * Run test cases and generate an evaluation report.\n *\n * @param testCases - Test cases to run\n * @param options - Run options (concurrency, stopOnFirstFailure, signal)\n * @returns Evaluation report with results, summary, and suggestions\n */\n run(\n testCases: TestCase<TInput>[],\n options?: RunOptions\n ): Promise<EvalReport<TInput, TOutput>>\n\n /**\n * Create a new suite with a different agent.\n * Useful for A/B testing or testing prompt improvements.\n *\n * @param agent - New agent to use\n * @returns New EvalSuite instance with the updated agent\n */\n withAgent(agent: EvalAgent<TInput, TOutput>): EvalSuite<TInput, TOutput>\n}\n\n/**\n * Calculate aggregated metrics from test results.\n * @internal\n *\n * Cost calculation is done via post-processing utilities (Phase 11).\n * Use calculateReportCosts() or addCostsToResults() from pricing module.\n */\nfunction calculateAggregatedMetrics<TInput, TOutput>(\n results: TestResultWithVerdict<TInput, TOutput>[]\n): AggregatedMetrics {\n if (results.length === 0) {\n return { avgLatencyMs: 0, totalTokens: 0 }\n }\n\n const totalLatencyMs = sumBy(results, (r) => r.metrics.latencyMs)\n const totalTokens = sumBy(results, (r) => r.metrics.tokenUsage.totalTokens)\n\n return {\n avgLatencyMs: totalLatencyMs / results.length,\n totalTokens,\n }\n}\n\nfunction sumBy<T>(items: T[], selector: (item: T) => number): number {\n return items.reduce((sum, item) => sum + selector(item), 0)\n}\n\n/** @internal */\nfunction calculateSummary<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[],\n iterations?: number\n): ReportSummary {\n const metrics = calculateAggregatedMetrics(results)\n const passedCount = results.filter((r) => r.passed).length\n const failedCount = results.length - passedCount\n const avgScore = results.length > 0\n ? sumBy(results, (r) => r.overallScore) / results.length\n : 0\n\n const summary: ReportSummary = {\n totalTests: results.length,\n passed: passedCount,\n failed: failedCount,\n avgScore,\n metrics,\n }\n\n const hasMultipleIterations = iterations && iterations > 1\n if (hasMultipleIterations) {\n summary.iterations = iterations\n summary.avgStdDev = calculateAvgStdDev(results)\n summary.avgPassRate = calculateAvgPassRate(results)\n }\n\n return summary\n}\n\n/**\n * Create an evaluation suite for testing an agent.\n *\n * The suite orchestrates test execution, evaluation, and optional\n * prompt improvement suggestions.\n *\n * @example\n * ```typescript\n * const suite = createEvalSuite({\n * agent: scenarioGenerator,\n * agentDescription: 'Recommends majors based on student profiles',\n * judge: createJudge({\n * llm: openaiClient,\n * prompt: defaultJudgePrompt,\n * criteria: [accuracy(), relevance()],\n * }),\n * })\n *\n * const report = await suite.run(testCases, { concurrency: 3 })\n * ```\n */\nexport function createEvalSuite<TInput, TOutput>(\n config: EvalSuiteConfig<TInput, TOutput>\n): EvalSuite<TInput, TOutput> {\n const { agent, agentDescription, judge, improver } = config\n const description = agentDescription ?? agent.config.description ?? agent.config.name\n\n const suite: EvalSuite<TInput, TOutput> = {\n async run(\n testCases: TestCase<TInput>[],\n options?: RunOptions\n ): Promise<EvalReport<TInput, TOutput>> {\n const iterations = options?.iterations ?? 1\n validateIterations(iterations)\n\n const executeContext = { agent, judge, agentDescription: description }\n const results = iterations <= 1\n ? await runWithConcurrency<TInput, TOutput>(testCases, executeContext, options)\n : await runMultipleIterations(testCases, executeContext, options, iterations)\n\n const summary = calculateSummary(results, iterations > 1 ? iterations : undefined)\n const suggestions = improver\n ? (await improver.improve(agent.prompt, results)).suggestions\n : []\n\n return {\n summary,\n results,\n suggestions,\n generatedAt: new Date(),\n promptVersion: agent.prompt.version,\n }\n },\n\n withAgent(newAgent: EvalAgent<TInput, TOutput>): EvalSuite<TInput, TOutput> {\n return createEvalSuite({\n ...config,\n agent: newAgent,\n agentDescription: undefined,\n })\n },\n }\n\n return suite\n}\n\nfunction validateIterations(iterations: number): void {\n if (iterations < 1 || !Number.isInteger(iterations)) {\n throw new EvalError(\n `Invalid iterations value: ${iterations}. Must be a positive integer.`,\n { code: EvalErrorCode.INVALID_CONFIG, context: { iterations } }\n )\n }\n}\n\nasync function runMultipleIterations<TInput, TOutput>(\n testCases: TestCase<TInput>[],\n executeContext: { agent: EvalAgent<TInput, TOutput>; judge: Judge; agentDescription: string },\n options: RunOptions | undefined,\n iterations: number\n): Promise<EvalTestResult<TInput, TOutput>[]> {\n const allIterationResults: EvalTestResult<TInput, TOutput>[][] = []\n\n for (let i = 0; i < iterations; i++) {\n const iterationResults = await runWithConcurrency<TInput, TOutput>(\n testCases,\n executeContext,\n { ...options, iterations: undefined }\n )\n allIterationResults.push(iterationResults)\n }\n\n return aggregateIterationResults(allIterationResults)\n}\n","/**\n * agent-eval - LLM-as-Judge based AI Agent testing library\n *\n * @example\n * ```typescript\n * import {\n * createEvalSuite,\n * createJudge,\n * createOpenAIClient,\n * accuracy,\n * relevance,\n * } from 'agent-eval'\n *\n * const openai = createOpenAIClient({\n * apiKey: process.env.OPENAI_API_KEY,\n * defaultModel: 'gpt-5-nano',\n * reasoningEffort: 'minimal',\n * })\n *\n * const judge = createJudge({\n * llm: openai,\n * criteria: [accuracy(), relevance()],\n * })\n *\n * const suite = createEvalSuite({\n * agent: myAgent,\n * judge,\n * agentDescription: 'Recommends careers based on student profiles',\n * })\n *\n * const report = await suite.run(testCases, { concurrency: 3 })\n * console.log(report.summary)\n * ```\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Suite - Main Entry Point\n// ============================================================================\n\nexport {\n createEvalSuite,\n type EvalSuiteConfig,\n type EvalSuite,\n type RunOptions,\n} from '@/core/suite';\n\n// ============================================================================\n// Runner - Low-level Execution\n// ============================================================================\n\nexport { executeTestCase, runWithConcurrency, type ExecuteContext } from '@/core/runner';\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\nexport type {\n // Token usage\n EvalTokenUsage,\n // Agent types\n EvalAgent,\n EvalAgentConfig,\n AgentPrompt,\n AgentResult,\n AgentMetadata,\n // Component metadata types (Phase 10)\n ComponentMetadata,\n JudgeMetadata,\n ImproverMetadata,\n // Test types\n TestCase,\n TestResult,\n TestResultWithVerdict,\n MetricsResult,\n // Iteration types (Phase 6.2)\n IterationStats,\n IterationData,\n // Multi-turn iteration types (Phase 7.2)\n MultiTurnIterationStats,\n // Eval result types (Discriminated Union)\n EvalResultKind,\n EvalTestResult,\n SingleTurnResult,\n SingleTurnIteratedResult,\n MultiTurnResult,\n MultiTurnIteratedResult,\n ConversationEntry,\n TerminationInfo,\n MultiTurnData,\n // Evaluation types\n Verdict,\n Criterion,\n // Schema validation types (Phase 6.3)\n SchemaValidationResult,\n ValidatorFn,\n ValidatorCriterion,\n ZodIssue,\n // File context types (Phase 5.3)\n FileContent,\n FileContentMetadata,\n} from '@/core/types';\n\nexport {\n toEvalAgent,\n // Type guards for EvalTestResult\n isSingleTurnResult,\n isMultiTurnResult,\n isIteratedResult,\n} from '@/core/types';\n\n// ============================================================================\n// FileSource (Embedded Files in Input)\n// ============================================================================\n\nexport {\n // Resolver\n resolveFileSource,\n resolveFileSourcesInInput,\n // Scanner\n scanForFileSources,\n // Display info\n getFileSourceDisplayInfo,\n getFileSourcesDisplayInfo,\n // Utilities\n inferMediaType,\n // Type guards\n isFileSource,\n isFileSourcePath,\n isFileSourceData,\n isFileSourceBase64,\n isFileSourceUrl,\n // Types\n type FileSource,\n type FileSourcePath,\n type FileSourceData,\n type FileSourceBase64,\n type FileSourceUrl,\n type FoundFileSource,\n type FileSourceDisplayInfo,\n type ResolveOptions,\n} from '@agtlantis/core';\n\n// ============================================================================\n// Iteration Utilities (Phase 6.2, 7.2)\n// ============================================================================\n\nexport {\n calculateIterationStats,\n calculateMultiTurnIterationStats,\n selectRepresentativeResult,\n aggregateIterationResults,\n calculateAvgStdDev,\n calculateAvgPassRate,\n} from '@/core/iteration';\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nexport { EvalError, EvalErrorCode, type EvalErrorOptions } from '@/core/errors';\n\n// ============================================================================\n// Judge\n// ============================================================================\n\nexport {\n createJudge,\n // Criteria\n accuracy,\n consistency,\n relevance,\n schema,\n type CriterionOptions,\n type SchemaOptions,\n // Types\n type Judge,\n type JudgeConfig,\n type JudgeContext,\n type JudgePrompt,\n // Context-based API types (Phase 5.3)\n type EvalContext,\n type JudgeResult,\n} from '@/judge/index';\n\n// ============================================================================\n// Reporter\n// ============================================================================\n\nexport type {\n EvalReport,\n ReportSummary,\n ReportMarkdownOptions,\n ReportComparison,\n} from '@/reporter/types';\n\nexport { reportToMarkdown, saveReportMarkdown, compareReports } from '@/reporter/markdown';\n\n// Reporter classes\nexport {\n JsonReporter,\n MarkdownReporter,\n ConsoleReporter,\n CompositeReporter,\n type MarkdownReporterOptions,\n} from '@/reporter';\n\n// Reporter factory functions\nexport {\n createJsonReporter,\n createMarkdownReporter,\n createConsoleReporter,\n createCompositeReporter,\n createDefaultReporter,\n} from '@/reporter';\n\n// Report runner (convenience wrapper)\nexport { createReportRunner, type ReportRunnerOptions } from '@/reporter';\n\n// Reporter types\nexport type {\n Reporter,\n FileReporterOptions,\n ConsoleReporterOptions,\n LogVerbosity,\n} from '@/reporter';\n\n// ImprovementCycleResult helpers\nexport {\n saveCycleJson,\n logCycle,\n cycleToMarkdown,\n saveCycleMarkdown,\n type SaveCycleJsonOptions,\n type LogCycleOptions,\n type CycleMarkdownOptions,\n} from '@/reporter';\n\n// ============================================================================\n// Improver\n// ============================================================================\n\nexport {\n createImprover,\n // Utility functions\n suggestionDiff,\n suggestionPreview,\n suggestionSummary,\n applyPromptSuggestions,\n bumpVersion,\n // Types\n type Suggestion,\n type AggregatedMetrics,\n type Improver,\n type ImproverConfig,\n type ImproverPrompt,\n type ImproverContext,\n type ApplyPromptSuggestionsOptions,\n type ApplySuggestionsResult,\n // Phase 10 - ImproveResult with metadata\n type ImproveResult,\n} from '@/improver/index';\n\n// ============================================================================\n// Testing Utilities\n// ============================================================================\n\n// Re-export core testing mock utilities\nexport { mock, MockProvider } from '@agtlantis/core/testing';\nexport type { MockCall } from '@agtlantis/core/testing';\n\n// Agent/Judge/Improver mocks\nexport {\n createMockAgent,\n createMockJudge,\n createMockImprover,\n type MockAgentConfig,\n type MockJudgeConfig,\n type MockImproverConfig,\n} from '@/testing/mock-agent';\n\n// ============================================================================\n// Prompt (from @agtlantis/core)\n// ============================================================================\n\nexport {\n compileTemplate,\n createFilePromptRepository,\n type FilePromptRepositoryOptions,\n type FileSystem,\n type PromptTemplate,\n type PromptRepository,\n} from '@agtlantis/core';\n\n// ============================================================================\n// Multi-turn Testing\n// ============================================================================\n\n// Types\nexport type {\n ConversationContext,\n FieldsCondition,\n FieldSetCondition,\n FieldValueCondition,\n ContinueResult,\n CustomCondition,\n FollowUpInput,\n MaxTurnsCondition,\n MultiTurnTestCase,\n MultiTurnTestResult,\n NaturalLanguageConditionOptions,\n TerminatedResult,\n TerminationCheckResult,\n TerminationCondition,\n MultiTurnExecuteContext,\n MultiTurnExecuteOptions,\n} from '@/multi-turn/index';\n\n// Type guards\nexport {\n isCustomCondition,\n isFieldSetCondition,\n isFieldValueCondition,\n isMaxTurnsCondition,\n isMultiTurnTestCase,\n isTerminated,\n} from '@/multi-turn/index';\n\n// Termination utilities\nexport { checkCondition, checkTermination, getFieldValue } from '@/multi-turn/index';\n\n// Condition factory functions\nexport {\n afterTurns,\n and,\n fieldEquals,\n fieldIsSet,\n naturalLanguage,\n not,\n or,\n} from '@/multi-turn/index';\n\n// Runner\nexport { executeMultiTurnTestCase } from '@/multi-turn/index';\n\n// AI User\nexport { aiUser, type AIUserOptions } from '@/multi-turn/index';\n\n// ============================================================================\n// Cost Calculation (re-export from reporter/cost-helpers)\n// ============================================================================\n\nexport {\n calculateResultCost,\n calculateReportCosts,\n addCostsToResults,\n type CostBreakdown,\n type CostSummary,\n type MetricsWithCost,\n type TestResultWithCost,\n type EvalPricingConfig,\n} from '@/reporter/cost-helpers';\n\n// Re-export core pricing utilities for convenience\nexport {\n calculateCostFromUsage,\n OPENAI_PRICING,\n GOOGLE_PRICING,\n ANTHROPIC_PRICING,\n DEFAULT_PRICING_CONFIG,\n type PricingConfig,\n type ModelPricing,\n type CostResult,\n} from '@agtlantis/core';\n\n// ============================================================================\n// CLI Configuration\n// ============================================================================\n\nexport {\n defineConfig,\n type EvalConfig,\n type LLMConfig,\n type CLIJudgeConfig,\n type CLIImproverConfig,\n type OutputConfig,\n type RunConfig,\n type CLITestCase,\n type CLISingleTurnTestCase,\n type CLIMultiTurnTestCase,\n} from '@/cli/config/types';\n\nexport { discoverEvalFiles, type DiscoverOptions } from '@/cli/config/loader';\n\n// ============================================================================\n// Improvement Cycle (Automated Prompt Refinement)\n// ============================================================================\n\n// Types\nexport type {\n // Termination conditions\n TargetScoreCondition,\n MaxRoundsCondition,\n NoImprovementCondition,\n MaxCostCondition,\n CustomCycleCondition,\n CycleTerminationCondition,\n // Context and results\n CycleContext,\n CycleContinueResult,\n CycleTerminatedResult,\n CycleTerminationResult,\n // Round types\n RoundYield,\n RoundDecision,\n RoundCost,\n RoundResult,\n // Serialization\n SerializedPrompt,\n SerializedRoundResult,\n // History and config\n ImprovementHistory,\n HistoryConfig,\n ImprovementCycleConfig,\n ImprovementCycleOptions,\n ImprovementCycleResult,\n HistoryStorage,\n ImprovementSession,\n SessionConfig,\n} from '@/improvement-cycle';\n\n// Type guards\nexport {\n isTargetScoreCondition,\n isMaxRoundsCondition,\n isNoImprovementCondition,\n isMaxCostCondition,\n isCustomCycleCondition,\n isCycleTerminated,\n} from '@/improvement-cycle';\n\n// Condition utilities\nexport { checkCycleCondition, checkCycleTermination } from '@/improvement-cycle';\n\n// Condition factory functions\nexport {\n targetScore,\n maxRounds,\n noImprovement,\n maxCost,\n customCondition,\n // Composite conditions\n and as cycleAnd,\n or as cycleOr,\n not as cycleNot,\n} from '@/improvement-cycle';\n\n// Runner\nexport { runImprovementCycle, runImprovementCycleAuto } from '@/improvement-cycle';\n\n// History/Persistence\nexport {\n createSession,\n resumeSession,\n loadHistory,\n saveHistory,\n serializePrompt,\n deserializePrompt,\n defaultHistoryStorage,\n} from '@/improvement-cycle';\n\n// ============================================================================\n// Test Case Utilities\n// ============================================================================\n\nexport {\n TestCaseCollection,\n testCase,\n testCases,\n type RandomOptions,\n} from '@/core/test-case-collection';\n","import { type LanguageModelUsage, type ModelMessage, Output } from 'ai';\nimport { z } from 'zod';\n\nimport { SCORE } from '@/core/constants.js';\nimport { EvalError, EvalErrorCode } from '@/core/errors.js';\nimport type {\n Criterion,\n EvalTokenUsage,\n JudgeMetadata,\n ValidatorCriterion,\n Verdict,\n} from '@/core/types.js';\n\nimport { defaultJudgePrompt } from './prompts/default.js';\nimport type { EvalContext, Judge, JudgeConfig, JudgeContext, JudgeResult } from './types.js';\n\nfunction toEvalTokenUsage(usage: LanguageModelUsage): EvalTokenUsage {\n return {\n inputTokens: usage.inputTokens ?? 0,\n outputTokens: usage.outputTokens ?? 0,\n totalTokens: usage.totalTokens ?? 0,\n };\n}\n\nfunction hasValidator(criterion: Criterion): criterion is ValidatorCriterion {\n return (\n 'validator' in criterion &&\n typeof (criterion as ValidatorCriterion).validator === 'function'\n );\n}\n\nconst JudgeResponseSchema = z.object({\n verdicts: z.array(\n z.object({\n criterionId: z.string(),\n score: z.number().min(SCORE.MIN).max(SCORE.MAX),\n reasoning: z.string(),\n passed: z.boolean().optional(),\n })\n ),\n});\n\ntype JudgeResponse = z.infer<typeof JudgeResponseSchema>;\n\nfunction validateAllCriteriaHaveVerdicts(\n verdicts: JudgeResponse['verdicts'],\n criteriaIds: string[]\n): void {\n const providedIds = new Set(verdicts.map((v) => v.criterionId));\n const missingIds = criteriaIds.filter((id) => !providedIds.has(id));\n\n if (missingIds.length > 0) {\n throw new EvalError('Judge response missing verdicts for some criteria', {\n code: EvalErrorCode.VERDICT_PARSE_ERROR,\n context: { missingCriteriaIds: missingIds, providedIds: [...providedIds] },\n });\n }\n}\n\nfunction calculateOverallScore(verdicts: Verdict[], criteriaWeights: Map<string, number>): number {\n let totalWeight = 0;\n let weightedSum = 0;\n\n for (const verdict of verdicts) {\n const weight = criteriaWeights.get(verdict.criterionId) ?? 1;\n weightedSum += verdict.score * weight;\n totalWeight += weight;\n }\n\n if (totalWeight === 0) {\n return 0;\n }\n\n return Math.round((weightedSum / totalWeight) * 100) / 100;\n}\n\nfunction runValidatorCriteria(validatorCriteria: ValidatorCriterion[], output: unknown): Verdict[] {\n return validatorCriteria.map((criterion) => {\n const result = criterion.validator!(output);\n\n if (result.valid) {\n return {\n criterionId: criterion.id,\n score: 100,\n reasoning: `${criterion.name} 통과`,\n passed: true,\n };\n }\n\n return {\n criterionId: criterion.id,\n score: 0,\n reasoning: `${criterion.name} 실패:\\n${result.errorSummary ?? '유효성 검증 오류'}`,\n passed: false,\n };\n });\n}\n\nasync function runLLMEvaluation(\n provider: JudgeConfig['provider'],\n prompt: NonNullable<JudgeConfig['prompt']>,\n context: JudgeContext,\n llmCriteriaIds: string[],\n passThreshold: number\n): Promise<{ verdicts: Verdict[]; usage?: LanguageModelUsage }> {\n const messages: ModelMessage[] = [\n { role: 'system', content: prompt.system },\n { role: 'user', content: prompt.renderUserPrompt(context) },\n ];\n\n let response: JudgeResponse;\n let usage: LanguageModelUsage | undefined;\n\n try {\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages,\n output: Output.object({ schema: JudgeResponseSchema }),\n });\n return result.output!;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n response = executionResult.value;\n usage = executionResult.summary.totalLLMUsage;\n } catch (cause) {\n throw EvalError.from(cause, EvalErrorCode.LLM_API_ERROR, {\n promptId: prompt.id,\n promptVersion: prompt.version,\n });\n }\n\n validateAllCriteriaHaveVerdicts(response.verdicts, llmCriteriaIds);\n\n const verdicts: Verdict[] = response.verdicts.map((v) => ({\n criterionId: v.criterionId,\n score: v.score,\n reasoning: v.reasoning,\n passed: v.passed ?? v.score >= passThreshold,\n }));\n\n return { verdicts, usage };\n}\n\n/**\n * Creates an LLM-as-Judge evaluator.\n *\n * @example\n * ```typescript\n * import { createJudge, defaultJudgePrompt, accuracy, consistency } from 'agent-eval'\n * import { createGoogleProvider } from '@agtlantis/core'\n *\n * const provider = createGoogleProvider({ apiKey }).withDefaultModel('gemini-2.5-flash')\n *\n * const judge = createJudge({\n * provider,\n * prompt: defaultJudgePrompt,\n * criteria: [accuracy(), consistency()],\n * passThreshold: 70,\n * })\n *\n * const result = await judge.evaluate({\n * input: { query: 'What is 2+2?' },\n * output: { answer: '4' },\n * agentDescription: 'A math tutor agent',\n * files: [{ path: 'reference.md', content: '...' }],\n * })\n *\n * console.log(result.overallScore) // e.g., 85\n * console.log(result.passed) // true\n * ```\n */\nexport function createJudge(config: JudgeConfig): Judge {\n const {\n provider,\n prompt = defaultJudgePrompt,\n criteria,\n passThreshold = SCORE.DEFAULT_PASS_THRESHOLD,\n model,\n } = config;\n\n const validatorCriteria: ValidatorCriterion[] = [];\n const llmCriteria: Criterion[] = [];\n const criteriaWeights = new Map<string, number>();\n const llmCriteriaIds: string[] = [];\n\n for (const c of criteria) {\n criteriaWeights.set(c.id, c.weight ?? 1);\n\n if (hasValidator(c)) {\n validatorCriteria.push(c);\n } else {\n llmCriteria.push(c);\n llmCriteriaIds.push(c.id);\n }\n }\n\n return {\n async evaluate(evalContext: EvalContext): Promise<JudgeResult> {\n const { input, output, agentDescription, files } = evalContext;\n\n const validatorVerdicts = runValidatorCriteria(validatorCriteria, output);\n\n let llmVerdicts: Verdict[] = [];\n let llmUsage: LanguageModelUsage | undefined;\n\n if (llmCriteria.length > 0) {\n const context: JudgeContext = {\n agentDescription,\n input,\n output,\n criteria: llmCriteria,\n files,\n };\n\n const llmResult = await runLLMEvaluation(\n provider,\n prompt,\n context,\n llmCriteriaIds,\n passThreshold\n );\n llmVerdicts = llmResult.verdicts;\n llmUsage = llmResult.usage;\n }\n\n const allVerdicts: Verdict[] = [...validatorVerdicts, ...llmVerdicts];\n const overallScore = calculateOverallScore(allVerdicts, criteriaWeights);\n const passed = overallScore >= passThreshold;\n\n const metadata: JudgeMetadata | undefined = llmUsage\n ? { tokenUsage: toEvalTokenUsage(llmUsage), model }\n : undefined;\n\n return {\n verdicts: allVerdicts,\n overallScore,\n passed,\n metadata,\n };\n },\n };\n}\n","import type { JudgeContext, JudgePrompt } from '../types';\n\nexport const defaultJudgePrompt: JudgePrompt = {\n id: 'default-judge',\n version: '2.0.0',\n\n system: `You are an expert evaluator specializing in assessing AI Agent outputs.\n\nYour role is to fairly and thoroughly evaluate the agent's output against the provided criteria.\n\n## Evaluation Principles\n\n1. **Scoring**: Assign a score between 0-100 for each criterion\n - 90-100: Exceptional - Exceeds expectations with no significant issues\n - 70-89: Good - Meets expectations with minor issues\n - 50-69: Acceptable - Partially meets expectations, notable issues present\n - 30-49: Poor - Falls short of expectations, significant issues\n - 0-29: Failing - Does not meet minimum requirements\n\n2. **Reasoning**: Always provide specific, evidence-based reasoning\n - Quote or reference specific parts of the output\n - Explain both strengths and weaknesses\n - Be constructive and actionable in feedback\n\n3. **Objectivity**: Evaluate based solely on the criteria provided\n - Avoid personal preferences or unstated requirements\n - Consider the agent's intended purpose and context\n - Weight severity of issues proportionally\n\n## Response Format\n\nYou MUST respond with valid JSON only. No additional text or explanation outside the JSON structure.\n\n{\n \"verdicts\": [\n {\n \"criterionId\": \"criterion-id\",\n \"score\": 0-100,\n \"reasoning\": \"Detailed explanation with specific evidence from the output\",\n \"passed\": true/false\n }\n ]\n}`,\n\n renderUserPrompt: (ctx: JudgeContext): string => {\n const fileSection = buildFileSection(ctx.files);\n\n return `\n## Agent Under Evaluation\n${ctx.agentDescription}\n\n## Input Provided to Agent\n\\`\\`\\`json\n${JSON.stringify(ctx.input, null, 2)}\n\\`\\`\\`\n${fileSection}\n## Agent Output\n\\`\\`\\`json\n${JSON.stringify(ctx.output, null, 2)}\n\\`\\`\\`\n\n## Evaluation Criteria\n${ctx.criteria.map((c) => `- **${c.name}** (id: ${c.id}, weight: ${c.weight ?? 1}): ${c.description}`).join('\\n')}\n\nPlease evaluate the agent's output against each criterion listed above.`.trim();\n },\n};\n\nfunction buildFileSection(files: JudgeContext['files']): string {\n if (!files || files.length === 0) {\n return '';\n }\n\n return `\n## Reference Files\n${files.map((f) => `### ${f.path}\\n\\`\\`\\`\\n${f.content}\\n\\`\\`\\``).join('\\n\\n')}\n`;\n}\n","import { z, ZodError } from 'zod'\nimport type { ValidatorCriterion, SchemaValidationResult } from '@/core/types.js'\nimport type { CriterionOptions } from './index.js'\n\nexport interface SchemaOptions<T> extends CriterionOptions {\n schema: z.ZodType<T>\n /** Use unique IDs when using multiple validators */\n id?: string\n name?: string\n description?: string\n}\n\nfunction formatZodErrors(error: ZodError): string {\n return error.errors\n .map((e) => {\n const path = e.path.length > 0 ? `${e.path.join('.')}: ` : ''\n return `- ${path}${e.message}`\n })\n .join('\\n')\n}\n\n/**\n * Creates a schema validation criterion using Zod.\n *\n * Performs PROGRAMMATIC validation (not LLM-based).\n * Scoring is binary: 100 if validation passes, 0 if it fails.\n *\n * @example\n * ```typescript\n * import { z } from 'zod'\n * import { schema, createJudge, accuracy, defaultJudgePrompt } from '@agtlantis/eval'\n *\n * const RecipeSchema = z.object({\n * name: z.string(),\n * ingredients: z.array(z.object({\n * name: z.string(),\n * amount: z.string(),\n * })),\n * steps: z.array(z.string()).min(1),\n * })\n *\n * const judge = createJudge({\n * llm: openaiClient,\n * prompt: defaultJudgePrompt,\n * criteria: [\n * schema({ schema: RecipeSchema, weight: 2 }),\n * accuracy(),\n * ],\n * })\n * ```\n */\nexport function schema<T>(options: SchemaOptions<T>): ValidatorCriterion {\n const { schema, id, weight, name, description } = options\n\n return {\n id: id ?? 'schema-validation',\n name: name ?? '스키마 유효성',\n description:\n description ??\n '출력이 지정된 스키마(Zod)를 준수하는지 프로그래밍 방식으로 검증합니다.',\n weight,\n validator: (output: unknown): SchemaValidationResult => {\n const result = schema.safeParse(output)\n\n if (result.success) {\n return { valid: true }\n }\n\n return {\n valid: false,\n errors: result.error.errors,\n errorSummary: formatZodErrors(result.error),\n }\n },\n }\n}\n","import type { Criterion } from '@/core/types.js'\n\nexport { schema, type SchemaOptions } from './validate-schema.js'\n\nexport interface CriterionOptions {\n weight?: number\n}\n\n/**\n * Evaluates whether the agent's output is factually accurate\n * and free from errors or hallucinations.\n */\nexport function accuracy(options?: CriterionOptions): Criterion {\n return {\n id: 'accuracy',\n name: 'Accuracy',\n description:\n 'Evaluates whether the output is factually correct, free from errors, and avoids hallucinations. Check for incorrect facts, made-up information, or misrepresentation of the input data.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output is internally consistent\n * and doesn't contradict itself or the provided context.\n */\nexport function consistency(options?: CriterionOptions): Criterion {\n return {\n id: 'consistency',\n name: 'Consistency',\n description:\n 'Evaluates whether the output is internally coherent and logically consistent. Check for self-contradictions, conflicting statements, or logical inconsistencies within the response.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output is relevant to the input\n * and addresses the user's needs appropriately.\n */\nexport function relevance(options?: CriterionOptions): Criterion {\n return {\n id: 'relevance',\n name: 'Relevance',\n description:\n 'Evaluates whether the output directly addresses the input and fulfills the user intent. Check for off-topic content, missing key requirements, or responses that fail to answer the actual question.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output shows clear step-by-step reasoning\n * or explanation of the solution process.\n */\nexport function stepByStep(options?: CriterionOptions): Criterion {\n return {\n id: 'step-by-step',\n name: 'Step-by-Step Reasoning',\n description:\n 'Evaluates whether the output demonstrates clear, structured reasoning with explicit steps. ' +\n 'Check for: numbered steps or clear progression, explanation of the thought process, ' +\n 'intermediate results shown before the final answer. ' +\n 'Penalize outputs that jump directly to the answer without showing work.',\n weight: options?.weight,\n }\n}\n","import { writeFile } from 'node:fs/promises';\n\nimport { getFileSourcesDisplayInfo } from '@agtlantis/core';\n\nimport { truncate } from '@/utils/json';\n\nimport type { EvalReport, ReportComparison, ReportMarkdownOptions } from './types';\n\nconst PASS_ICON = '✅';\nconst FAIL_ICON = '❌';\n\nconst PRIORITY_ORDER: Record<string, number> = { high: 0, medium: 1, low: 2 };\n\n/**\n * Converts an evaluation report to Markdown format.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases)\n * const markdown = reportToMarkdown(report)\n * console.log(markdown)\n * ```\n */\nexport function reportToMarkdown<TInput, TOutput>(\n report: EvalReport<TInput, TOutput>,\n options: ReportMarkdownOptions = {}\n): string {\n const {\n expandPassedTests = false,\n includeRawOutput = false,\n outputPreviewLength = 200,\n } = options;\n\n const { summary, results, suggestions, generatedAt, promptVersion } = report;\n const passRate =\n summary.totalTests > 0 ? ((summary.passed / summary.totalTests) * 100).toFixed(1) : '0.0';\n\n const lines: string[] = [];\n\n lines.push('# Evaluation Report');\n lines.push('');\n lines.push(`> Generated: ${generatedAt.toISOString()}`);\n lines.push(`> Prompt Version: ${promptVersion}`);\n lines.push('');\n\n lines.push('## Summary');\n lines.push('');\n lines.push(`| Metric | Value |`);\n lines.push(`|--------|-------|`);\n lines.push(`| Total Tests | ${summary.totalTests} |`);\n if (summary.iterations && summary.iterations > 1) {\n lines.push(`| **Iterations** | **${summary.iterations}** |`);\n }\n lines.push(`| Passed | ${summary.passed} (${passRate}%) |`);\n lines.push(`| Failed | ${summary.failed} |`);\n if (summary.avgStdDev !== undefined) {\n lines.push(\n `| Average Score | ${summary.avgScore.toFixed(1)} ± ${summary.avgStdDev.toFixed(1)} |`\n );\n } else {\n lines.push(`| Average Score | ${summary.avgScore.toFixed(1)} |`);\n }\n if (summary.avgPassRate !== undefined) {\n lines.push(`| Avg Pass Rate | ${(summary.avgPassRate * 100).toFixed(1)}% |`);\n }\n lines.push(`| Avg Latency | ${summary.metrics.avgLatencyMs.toFixed(0)}ms |`);\n lines.push(`| Total Tokens | ${summary.metrics.totalTokens} |`);\n if (summary.costSummary?.total !== undefined) {\n lines.push(`| Est. Cost | $${summary.costSummary.total.toFixed(4)} |`);\n }\n lines.push('');\n\n const failedResults = results.filter((r) => !r.passed);\n if (failedResults.length > 0) {\n lines.push(`## ${FAIL_ICON} Failed Tests`);\n lines.push('');\n for (const result of failedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n }\n\n const passedResults = results.filter((r) => r.passed);\n if (passedResults.length > 0) {\n lines.push(`## ${PASS_ICON} Passed Tests`);\n lines.push('');\n if (expandPassedTests) {\n for (const result of passedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n } else {\n lines.push('<details>');\n lines.push('<summary>Click to expand passed tests</summary>');\n lines.push('');\n for (const result of passedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n lines.push('</details>');\n lines.push('');\n }\n }\n\n if (suggestions.length > 0) {\n lines.push('## 💡 Improvement Suggestions');\n lines.push('');\n const sortedSuggestions = [...suggestions].sort(\n (a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]\n );\n\n for (const suggestion of sortedSuggestions) {\n lines.push(formatSuggestion(suggestion));\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Saves an evaluation report as a Markdown file.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases)\n * await saveReportMarkdown(report, './reports/eval-2024-01.md')\n * ```\n */\nexport async function saveReportMarkdown<TInput, TOutput>(\n report: EvalReport<TInput, TOutput>,\n path: string,\n options?: ReportMarkdownOptions\n): Promise<void> {\n const markdown = reportToMarkdown(report, options);\n await writeFile(path, markdown, 'utf-8');\n}\n\nfunction jsonCodeBlock(value: unknown, maxLength?: number): string[] {\n const json = JSON.stringify(value, null, 2);\n const content = maxLength !== undefined ? truncate(json, maxLength) : json;\n return ['```json', content, '```'];\n}\n\nfunction passFailIcon(passed: boolean): string {\n return passed ? PASS_ICON : FAIL_ICON;\n}\n\ninterface TestResultForFormat<TInput, TOutput> {\n testCase: { id?: string; input: TInput; description?: string };\n output: TOutput;\n overallScore: number;\n passed: boolean;\n verdicts: Array<{ criterionId: string; score: number; reasoning: string; passed: boolean }>;\n iterationStats?: {\n iterations: number;\n scores: number[];\n mean: number;\n stdDev: number;\n min: number;\n max: number;\n passRate: number;\n passCount: number;\n };\n iterationResults?: Array<{\n overallScore: number;\n passed: boolean;\n metrics: { latencyMs: number };\n }>;\n conversationHistory?: Array<{ turn: number; input: TInput; output: TOutput | undefined }>;\n totalTurns?: number;\n terminationReason?: string;\n multiTurnIterationStats?: {\n avgTurns: number;\n minTurns: number;\n maxTurns: number;\n terminationCounts: Record<string, number>;\n };\n}\n\nfunction formatTestResult<TInput, TOutput>(\n result: TestResultForFormat<TInput, TOutput>,\n previewLength: number,\n includeRaw: boolean\n): string {\n const lines: string[] = [];\n const testId = result.testCase.id ?? 'unnamed';\n\n const scoreDisplay = result.iterationStats\n ? `${result.overallScore.toFixed(1)} ± ${result.iterationStats.stdDev.toFixed(1)}`\n : result.overallScore.toFixed(1);\n lines.push(`### ${testId} (Score: ${scoreDisplay})`);\n lines.push('');\n\n if (result.testCase.description) {\n lines.push(`> ${result.testCase.description}`);\n lines.push('');\n }\n\n const fileDisplayInfos = getFileSourcesDisplayInfo(result.testCase.input);\n if (fileDisplayInfos.length > 0) {\n lines.push('**Files:**');\n for (const info of fileDisplayInfos) {\n const namePrefix = info.filename ? `${info.filename} - ` : '';\n lines.push(`- ${namePrefix}${info.source}: ${info.description} (${info.mediaType})`);\n }\n lines.push('');\n }\n\n if (result.totalTurns !== undefined) {\n lines.push(\n `**Multi-turn:** ${result.totalTurns} turns | Termination: ${result.terminationReason ?? 'unknown'}`\n );\n lines.push('');\n }\n\n if (result.multiTurnIterationStats) {\n lines.push(...formatMultiTurnIterationStats(result.multiTurnIterationStats));\n }\n\n if (result.iterationStats && result.iterationResults) {\n lines.push(...formatIterationResults(result.iterationStats, result.iterationResults));\n }\n\n if (result.conversationHistory && result.conversationHistory.length > 0) {\n lines.push(...formatConversationHistory(result.conversationHistory, previewLength));\n } else {\n lines.push(\n ...formatSingleTurnInputOutput(result.testCase.input, result.output, previewLength)\n );\n }\n\n lines.push('**Verdicts:**');\n for (const verdict of result.verdicts) {\n lines.push(\n `- ${passFailIcon(verdict.passed)} **${verdict.criterionId}**: ${verdict.score} - ${verdict.reasoning}`\n );\n }\n lines.push('');\n\n if (includeRaw) {\n lines.push('<details>');\n lines.push('<summary>Raw Output</summary>');\n lines.push('');\n lines.push(...jsonCodeBlock(result.output));\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiTurnIterationStats(\n stats: NonNullable<TestResultForFormat<unknown, unknown>['multiTurnIterationStats']>\n): string[] {\n const terminationSummary =\n Object.entries(stats.terminationCounts)\n .map(([type, count]) => `${type}: ${count}`)\n .join(', ') || 'none';\n\n return [\n '**Multi-turn Iteration Statistics:**',\n '',\n '| Metric | Value |',\n '|--------|-------|',\n `| Avg Turns | ${stats.avgTurns.toFixed(1)} |`,\n `| Min/Max Turns | ${stats.minTurns} / ${stats.maxTurns} |`,\n `| Termination Distribution | ${terminationSummary} |`,\n '',\n ];\n}\n\nfunction formatIterationResults(\n stats: NonNullable<TestResultForFormat<unknown, unknown>['iterationStats']>,\n results: NonNullable<TestResultForFormat<unknown, unknown>['iterationResults']>\n): string[] {\n const lines: string[] = [\n '**Iteration Results:**',\n '',\n '| # | Score | Passed | Latency |',\n '|---|-------|--------|---------|',\n ];\n\n results.forEach((iter, idx) => {\n lines.push(\n `| ${idx + 1} | ${iter.overallScore.toFixed(1)} | ${passFailIcon(iter.passed)} | ${iter.metrics.latencyMs.toFixed(0)}ms |`\n );\n });\n\n lines.push('');\n lines.push(\n `**Stats:** ${stats.mean.toFixed(1)} ± ${stats.stdDev.toFixed(1)} (min: ${stats.min.toFixed(0)}, max: ${stats.max.toFixed(0)}, pass rate: ${(stats.passRate * 100).toFixed(0)}%)`\n );\n lines.push('');\n\n return lines;\n}\n\nfunction formatConversationHistory<TInput, TOutput>(\n history: Array<{ turn: number; input: TInput; output: TOutput | undefined }>,\n previewLength: number\n): string[] {\n const lines: string[] = ['**Conversation History:**', ''];\n\n for (const turn of history) {\n lines.push('<details>');\n lines.push(`<summary>Turn ${turn.turn}</summary>`);\n lines.push('');\n lines.push('**Input:**');\n lines.push(...jsonCodeBlock(turn.input, previewLength));\n lines.push('');\n lines.push('**Output:**');\n lines.push(...jsonCodeBlock(turn.output, previewLength));\n lines.push('</details>');\n lines.push('');\n }\n\n return lines;\n}\n\nfunction formatSingleTurnInputOutput<TInput, TOutput>(\n input: TInput,\n output: TOutput,\n previewLength: number\n): string[] {\n return [\n '**Input:**',\n ...jsonCodeBlock(input, previewLength),\n '',\n '**Output:**',\n ...jsonCodeBlock(output, previewLength),\n '',\n ];\n}\n\nfunction formatSuggestion(suggestion: {\n type: string;\n priority: string;\n currentValue: string;\n suggestedValue: string;\n reasoning: string;\n expectedImprovement: string;\n}): string {\n const lines: string[] = [];\n const priorityIcon = { high: '🔴', medium: '🟡', low: '🟢' }[suggestion.priority] ?? '⚪';\n\n lines.push(`### ${priorityIcon} [${suggestion.priority.toUpperCase()}] ${suggestion.type}`);\n lines.push('');\n lines.push(`**Reasoning:** ${suggestion.reasoning}`);\n lines.push('');\n lines.push(`**Expected Improvement:** ${suggestion.expectedImprovement}`);\n lines.push('');\n lines.push('**Diff:**');\n lines.push('```diff');\n lines.push(`- ${suggestion.currentValue.split('\\n').join('\\n- ')}`);\n lines.push(`+ ${suggestion.suggestedValue.split('\\n').join('\\n+ ')}`);\n lines.push('```');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Compares two evaluation reports and returns the differences.\n * Useful for tracking improvements across prompt versions.\n *\n * @example\n * ```typescript\n * const beforeReport = await suite.run(testCases)\n * // ... apply improvements ...\n * const afterReport = await suite.withAgent(improvedAgent).run(testCases)\n *\n * const comparison = compareReports(beforeReport, afterReport)\n * console.log(`Score improved by ${comparison.scoreDelta} points`)\n * console.log(`Tests improved: ${comparison.improved.join(', ')}`)\n * console.log(`Tests regressed: ${comparison.regressed.join(', ')}`)\n * ```\n */\nexport function compareReports<TInput, TOutput>(\n before: EvalReport<TInput, TOutput>,\n after: EvalReport<TInput, TOutput>\n): ReportComparison {\n const scoreDelta = after.summary.avgScore - before.summary.avgScore;\n\n const beforePassRate =\n before.summary.totalTests > 0 ? before.summary.passed / before.summary.totalTests : 0;\n const afterPassRate =\n after.summary.totalTests > 0 ? after.summary.passed / after.summary.totalTests : 0;\n const passRateDelta = afterPassRate - beforePassRate;\n\n const metricsDelta = {\n latencyMs: after.summary.metrics.avgLatencyMs - before.summary.metrics.avgLatencyMs,\n tokenUsage: after.summary.metrics.totalTokens - before.summary.metrics.totalTokens,\n };\n\n const beforeScores = buildScoreMap(before.results);\n const afterScores = buildScoreMap(after.results);\n\n const improved: string[] = [];\n const regressed: string[] = [];\n\n for (const [id, afterScore] of afterScores) {\n const beforeScore = beforeScores.get(id);\n if (beforeScore === undefined) continue;\n if (afterScore > beforeScore) {\n improved.push(id);\n } else if (afterScore < beforeScore) {\n regressed.push(id);\n }\n }\n\n const removed = [...beforeScores.keys()].filter((id) => !afterScores.has(id));\n\n return {\n scoreDelta,\n passRateDelta,\n metricsDelta,\n improved,\n regressed,\n removed,\n };\n}\n\nfunction buildScoreMap<TInput, TOutput>(\n results: Array<{ testCase: { id?: string }; overallScore: number }>\n): Map<string, number> {\n const scoreMap = new Map<string, number>();\n for (const result of results) {\n scoreMap.set(result.testCase.id ?? 'unnamed', result.overallScore);\n }\n return scoreMap;\n}\n","import { writeFileSync } from 'node:fs'\nimport type { Reporter, FileReporterOptions, EvalReport } from './types'\nimport { calculateReportCosts, type CostSummary, type EvalPricingConfig } from './cost-helpers'\nimport { buildOutputPath } from './format-utils'\n\ninterface SerializedReport<TInput, TOutput> {\n summary: EvalReport<TInput, TOutput>['summary']\n results: EvalReport<TInput, TOutput>['results']\n suggestions: EvalReport<TInput, TOutput>['suggestions']\n generatedAt: string\n promptVersion: string\n costs?: CostSummary\n}\n\n/**\n * Reporter that saves EvalReport as JSON.\n *\n * @example\n * ```typescript\n * const reporter = new JsonReporter({ outputDir: './reports' })\n * reporter.save(report, 'my-test') // -> ./reports/my-test-1736691234567.json\n *\n * // Without timestamp\n * const fixedReporter = new JsonReporter({\n * outputDir: './reports',\n * addTimestamp: false,\n * })\n * fixedReporter.save(report, 'round-1') // -> ./reports/round-1.json\n * ```\n */\nexport class JsonReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly outputDir: string\n private readonly pricing?: EvalPricingConfig\n private readonly addTimestamp: boolean\n\n constructor(options: FileReporterOptions) {\n this.outputDir = options.outputDir\n this.pricing = options.pricing\n this.addTimestamp = options.addTimestamp ?? true\n }\n\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const filepath = buildOutputPath(this.outputDir, name, 'json', this.addTimestamp)\n\n const costs = this.pricing\n ? calculateReportCosts(report, this.pricing)\n : undefined\n\n const output: SerializedReport<TInput, TOutput> = {\n summary: report.summary,\n results: report.results,\n suggestions: report.suggestions,\n generatedAt: report.generatedAt.toISOString(),\n promptVersion: report.promptVersion,\n ...(costs && { costs }),\n }\n\n writeFileSync(filepath, JSON.stringify(output, null, 2))\n return filepath\n }\n}\n","import type { EvalTokenUsage } from '@/core/types'\nimport {\n calculateCostFromUsage,\n type ProviderType,\n type ProviderPricing,\n} from '@agtlantis/core'\nimport type { LanguageModelUsage } from 'ai'\n\nfunction toLanguageModelUsage(usage: EvalTokenUsage): LanguageModelUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n } as LanguageModelUsage\n}\n\n/** Cost breakdown by component (Agent, Judge, Improver) */\nexport interface CostBreakdown {\n agent?: number\n judge?: number\n improver?: number\n total?: number\n}\n\n/** Cost summary aggregated across all test results */\nexport interface CostSummary {\n total: number\n byComponent: {\n agent: number\n judge: number\n improver?: number\n }\n}\n\nexport interface MetricsWithCost {\n latencyMs: number\n tokenUsage: EvalTokenUsage\n costBreakdown: CostBreakdown\n}\n\n/** Test result with cost breakdown, returned by addCostsToResults() */\nexport interface TestResultWithCost<TInput, TOutput> {\n testCase: {\n id?: string\n input: TInput\n tags?: string[]\n description?: string\n expectedOutput?: unknown\n }\n output: TOutput\n metrics: MetricsWithCost\n error?: Error\n verdicts: Array<{\n criterionId: string\n score: number\n reasoning: string\n passed: boolean\n }>\n overallScore: number\n passed: boolean\n}\n\n/** Pricing configuration for eval */\nexport interface EvalPricingConfig {\n /** Provider-specific pricing overrides. Key is provider name (e.g., 'google', 'openai'), value is model pricing. */\n providerPricing?: Partial<Record<ProviderType, ProviderPricing>>\n}\n\n/** Maps eval's provider names to core's provider names (eval uses 'gemini', core uses 'google') */\nconst PROVIDER_MAPPING: Record<string, ProviderType> = {\n gemini: 'google',\n openai: 'openai',\n anthropic: 'anthropic',\n google: 'google',\n}\n\nfunction detectProvider(model: string | undefined): ProviderType {\n if (!model) return 'google' // default\n\n if (model.startsWith('gpt-') || model.startsWith('o1') || model.startsWith('o3')) {\n return 'openai'\n }\n if (model.startsWith('gemini-')) {\n return 'google'\n }\n if (model.startsWith('claude-')) {\n return 'anthropic'\n }\n\n return 'google'\n}\n\nfunction normalizeProvider(provider: string | undefined): ProviderType {\n if (!provider) return 'google'\n return PROVIDER_MAPPING[provider] ?? provider\n}\n\n/** Minimal result interface compatible with TestResultWithVerdict and TestResultWithIteration */\ninterface ResultForCostCalculation<TInput, TOutput> {\n testCase: {\n id?: string\n input: TInput\n tags?: string[]\n description?: string\n expectedOutput?: unknown\n }\n output: TOutput\n metrics: {\n latencyMs: number\n tokenUsage: EvalTokenUsage\n }\n error?: Error\n verdicts: Array<{\n criterionId: string\n score: number\n reasoning: string\n passed: boolean\n }>\n overallScore: number\n passed: boolean\n agentMetadata?: {\n tokenUsage?: EvalTokenUsage\n model?: string\n provider?: string\n }\n judgeMetadata?: {\n tokenUsage?: EvalTokenUsage\n model?: string\n provider?: string\n }\n}\n\ninterface ReportForCostCalculation<TInput, TOutput> {\n results: ResultForCostCalculation<TInput, TOutput>[]\n}\n\nfunction calculateComponentCost(\n tokenUsage: EvalTokenUsage | undefined,\n model: string | undefined,\n provider: string | undefined,\n config?: EvalPricingConfig\n): number | undefined {\n if (!tokenUsage) return undefined\n\n const normalizedProvider = provider\n ? normalizeProvider(provider)\n : detectProvider(model)\n\n // Get the pricing for this specific provider from the config\n const providerPricing = config?.providerPricing?.[normalizedProvider]\n\n const result = calculateCostFromUsage(\n toLanguageModelUsage(tokenUsage),\n model ?? 'unknown',\n normalizedProvider,\n providerPricing\n )\n\n return result.total\n}\n\nfunction buildCostBreakdown(costs: {\n agent?: number\n judge?: number\n improver?: number\n}): CostBreakdown {\n const total =\n (costs.agent ?? 0) + (costs.judge ?? 0) + (costs.improver ?? 0)\n\n return {\n ...costs,\n total: total > 0 ? total : undefined,\n }\n}\n\nexport function calculateResultCost<TInput, TOutput>(\n result: ResultForCostCalculation<TInput, TOutput>,\n config?: EvalPricingConfig\n): CostBreakdown {\n const agentCost = calculateComponentCost(\n result.metrics.tokenUsage,\n result.agentMetadata?.model,\n result.agentMetadata?.provider,\n config\n )\n\n const judgeCost = result.judgeMetadata?.tokenUsage\n ? calculateComponentCost(\n result.judgeMetadata.tokenUsage,\n result.judgeMetadata.model,\n result.judgeMetadata.provider,\n config\n )\n : undefined\n\n return buildCostBreakdown({\n agent: agentCost,\n judge: judgeCost,\n })\n}\n\nexport function calculateReportCosts<TInput, TOutput>(\n report: ReportForCostCalculation<TInput, TOutput>,\n config?: EvalPricingConfig\n): CostSummary {\n let totalAgent = 0\n let totalJudge = 0\n\n for (const result of report.results) {\n const breakdown = calculateResultCost(result, config)\n totalAgent += breakdown.agent ?? 0\n totalJudge += breakdown.judge ?? 0\n }\n\n return {\n total: totalAgent + totalJudge,\n byComponent: {\n agent: totalAgent,\n judge: totalJudge,\n },\n }\n}\n\n/** Add cost breakdown to each result. Returns new array (does not mutate original). */\nexport function addCostsToResults<TInput, TOutput>(\n results: ResultForCostCalculation<TInput, TOutput>[],\n config?: EvalPricingConfig\n): TestResultWithCost<TInput, TOutput>[] {\n return results.map((result) => {\n const costBreakdown = calculateResultCost(result, config)\n\n const metricsWithCost: MetricsWithCost = {\n latencyMs: result.metrics.latencyMs,\n tokenUsage: result.metrics.tokenUsage,\n costBreakdown,\n }\n\n return {\n testCase: result.testCase,\n output: result.output,\n metrics: metricsWithCost,\n error: result.error,\n verdicts: result.verdicts,\n overallScore: result.overallScore,\n passed: result.passed,\n }\n })\n}\n","import { mkdirSync } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * Formats a score delta for display with consistent sign prefix.\n *\n * @example\n * formatScoreDelta(5.2) // \"+5.2\"\n * formatScoreDelta(-3.1) // \"-3.1\"\n * formatScoreDelta(0) // \"+0.0\"\n * formatScoreDelta(null) // \"-\"\n */\nexport function formatScoreDelta(delta: number | null): string {\n if (delta === null) {\n return '-'\n }\n const sign = delta >= 0 ? '+' : ''\n return `${sign}${delta.toFixed(1)}`\n}\n\n/**\n * Builds the output file path, creating the output directory if it doesn't exist.\n * Used by file-based reporters for consistent path handling.\n */\nexport function buildOutputPath(\n outputDir: string,\n name: string,\n extension: string,\n addTimestamp: boolean\n): string {\n mkdirSync(outputDir, { recursive: true })\n const filename = addTimestamp\n ? `${name}-${Date.now()}.${extension}`\n : `${name}.${extension}`\n return path.join(outputDir, filename)\n}\n\n/** Converts a Date to ISO string, handling both Date objects and already-serialized strings */\nexport function toISOStringIfDate(value: Date | string): string {\n return value instanceof Date ? value.toISOString() : value\n}\n","import { writeFileSync } from 'node:fs'\nimport type { Reporter, FileReporterOptions, EvalReport, ReportMarkdownOptions } from './types'\nimport { reportToMarkdown } from './markdown'\nimport { buildOutputPath } from './format-utils'\n\nexport interface MarkdownReporterOptions extends FileReporterOptions {\n /** Markdown generation options */\n markdown?: ReportMarkdownOptions\n}\n\n/**\n * Reporter that saves EvalReport as Markdown.\n *\n * @example\n * ```typescript\n * const reporter = new MarkdownReporter({ outputDir: './reports' })\n * reporter.save(report, 'my-test') // -> ./reports/my-test-1736691234567.md\n *\n * // With expanded passed tests\n * const detailedReporter = new MarkdownReporter({\n * outputDir: './reports',\n * markdown: { expandPassedTests: true },\n * })\n * ```\n */\nexport class MarkdownReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly outputDir: string\n private readonly addTimestamp: boolean\n private readonly markdownOptions: ReportMarkdownOptions\n\n constructor(options: MarkdownReporterOptions) {\n this.outputDir = options.outputDir\n this.addTimestamp = options.addTimestamp ?? true\n this.markdownOptions = options.markdown ?? {}\n }\n\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const filepath = buildOutputPath(this.outputDir, name, 'md', this.addTimestamp)\n const markdown = reportToMarkdown(report, this.markdownOptions)\n writeFileSync(filepath, markdown)\n return filepath\n }\n}\n","import type { Reporter, ConsoleReporterOptions, EvalReport, LogVerbosity } from './types'\nimport { calculateReportCosts, type EvalPricingConfig } from './cost-helpers'\nimport { truncate } from '@/utils/json'\n\n/**\n * Reporter that logs EvalReport to console.\n *\n * @example\n * ```typescript\n * const reporter = new ConsoleReporter({ verbosity: 'detailed' })\n * reporter.log(report) // Logs to console\n *\n * // With cost display\n * const costReporter = new ConsoleReporter({\n * verbosity: 'summary',\n * pricing: GOOGLE_PRICING,\n * })\n * ```\n */\nexport class ConsoleReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly verbosity: LogVerbosity\n private readonly pricing?: EvalPricingConfig\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.verbosity = options.verbosity ?? 'summary'\n this.pricing = options.pricing\n }\n\n log(report: EvalReport<TInput, TOutput>): void {\n const { summary } = report\n const passRate = summary.totalTests > 0 ? summary.passed / summary.totalTests : 0\n\n console.log(`\\n📊 Eval Report: ${summary.totalTests} tests`)\n console.log(` Score: ${summary.avgScore.toFixed(1)} | Pass Rate: ${(passRate * 100).toFixed(0)}%`)\n\n if (this.verbosity === 'summary') {\n this.logCostIfAvailable(report)\n return\n }\n\n console.log('')\n for (const result of report.results) {\n const testId = result.testCase.id || 'unknown'\n const status = result.passed ? '✓' : '✗'\n console.log(` ${status} [${testId}] Score: ${result.overallScore.toFixed(1)}`)\n\n if (this.verbosity === 'full') {\n console.log(` Input: ${truncate(JSON.stringify(result.testCase.input), 80)}`)\n console.log(` Output: ${truncate(String(result.output), 80)}`)\n }\n }\n\n this.logCostIfAvailable(report)\n }\n\n private logCostIfAvailable(report: EvalReport<TInput, TOutput>): void {\n if (this.pricing) {\n const costs = calculateReportCosts(report, this.pricing)\n console.log(`\\n 💰 Cost: $${costs.total.toFixed(4)}`)\n }\n }\n}\n","import type { Reporter, EvalReport } from './types'\n\n/**\n * Combines multiple reporters to save/log to multiple outputs.\n *\n * @example\n * ```typescript\n * const reporter = new CompositeReporter([\n * new JsonReporter({ outputDir: './reports' }),\n * new ConsoleReporter({ verbosity: 'detailed' }),\n * ])\n * reporter.save(report, 'my-test') // JSON 저장 + 콘솔 출력\n * ```\n */\nexport class CompositeReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n constructor(private readonly reporters: Reporter<TInput, TOutput>[]) {}\n\n /**\n * Saves to all reporters that support saving.\n * Returns the first successful file path (usually JsonReporter).\n */\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const errors: Array<{ reporter: string; error: Error }> = []\n let firstPath: string | undefined\n\n for (const reporter of this.reporters) {\n // Skip reporters that don't support save\n if (!reporter.save) {\n reporter.log?.(report)\n continue\n }\n\n try {\n const savedPath = reporter.save(report, name)\n if (!firstPath) firstPath = savedPath\n } catch (error) {\n errors.push({\n reporter: reporter.constructor.name,\n error: error as Error,\n })\n }\n\n // Log regardless of save success/failure - user should see output even if save fails\n reporter.log?.(report)\n }\n\n if (!firstPath) {\n const details = errors.length > 0\n ? errors.map(e => `${e.reporter}: ${e.error.message}`).join(', ')\n : 'No reporters support save()'\n throw new Error(`No reporter saved successfully. ${details}`)\n }\n\n return firstPath\n }\n\n log(report: EvalReport<TInput, TOutput>): void {\n for (const reporter of this.reporters) {\n reporter.log?.(report)\n }\n }\n}\n","import { JsonReporter } from './json-reporter'\nimport { MarkdownReporter, type MarkdownReporterOptions } from './markdown-reporter'\nimport { ConsoleReporter } from './console-reporter'\nimport { CompositeReporter } from './composite-reporter'\nimport type { FileReporterOptions, ConsoleReporterOptions, Reporter, LogVerbosity } from './types'\nimport type { EvalPricingConfig } from './cost-helpers'\n\n/**\n * Create a JSON reporter.\n *\n * @example\n * ```typescript\n * const reporter = createJsonReporter('./reports')\n * reporter.save(report, 'my-test') // → ./reports/my-test-1736691234567.json\n * ```\n */\nexport function createJsonReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: Omit<FileReporterOptions, 'outputDir'>,\n): JsonReporter<TInput, TOutput> {\n return new JsonReporter({ outputDir, ...options })\n}\n\n/**\n * Create a Markdown reporter.\n *\n * @example\n * ```typescript\n * const reporter = createMarkdownReporter('./reports')\n * reporter.save(report, 'my-test') // → ./reports/my-test-1736691234567.md\n * ```\n */\nexport function createMarkdownReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: Omit<MarkdownReporterOptions, 'outputDir'>,\n): MarkdownReporter<TInput, TOutput> {\n return new MarkdownReporter({ outputDir, ...options })\n}\n\n/**\n * Create a console reporter.\n *\n * @example\n * ```typescript\n * const reporter = createConsoleReporter({ verbosity: 'detailed' })\n * reporter.log(report) // Logs to console\n * ```\n */\nexport function createConsoleReporter<TInput = unknown, TOutput = unknown>(\n options?: ConsoleReporterOptions,\n): ConsoleReporter<TInput, TOutput> {\n return new ConsoleReporter(options)\n}\n\n/**\n * Create a composite reporter from multiple reporters.\n *\n * @example\n * ```typescript\n * const reporter = createCompositeReporter([\n * createJsonReporter('./reports'),\n * createConsoleReporter({ verbosity: 'summary' }),\n * ])\n * ```\n */\nexport function createCompositeReporter<TInput = unknown, TOutput = unknown>(\n reporters: Reporter<TInput, TOutput>[],\n): CompositeReporter<TInput, TOutput> {\n return new CompositeReporter(reporters)\n}\n\n/**\n * Convenience: Create JSON + Console reporter combo.\n *\n * @example\n * ```typescript\n * const reporter = createDefaultReporter('./reports', {\n * pricing: GOOGLE_PRICING,\n * verbosity: 'summary',\n * })\n * reporter.save(report, 'my-test') // JSON 저장 + 콘솔 출력\n * ```\n */\nexport function createDefaultReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: {\n pricing?: EvalPricingConfig\n verbosity?: LogVerbosity\n addTimestamp?: boolean\n },\n): CompositeReporter<TInput, TOutput> {\n return new CompositeReporter([\n new JsonReporter({\n outputDir,\n pricing: options?.pricing,\n addTimestamp: options?.addTimestamp,\n }),\n new ConsoleReporter({\n verbosity: options?.verbosity,\n pricing: options?.pricing,\n }),\n ])\n}\n","import type { EvalSuite } from '@/core/suite'\nimport type { TestCase } from '@/core/types'\nimport type { EvalReport, LogVerbosity } from './types'\nimport type { EvalPricingConfig } from './cost-helpers'\nimport { JsonReporter } from './json-reporter'\nimport { ConsoleReporter } from './console-reporter'\n\n/**\n * Options for creating a report runner.\n */\nexport interface ReportRunnerOptions {\n /** Directory where reports will be saved */\n outputDir: string\n /** Pricing config for cost calculation */\n pricing?: EvalPricingConfig\n /** Verbosity level for console output (false to disable logging) */\n verbosity?: LogVerbosity | false\n}\n\n\n/**\n * Result returned by the report runner.\n */\nexport interface ReportRunnerResult<TInput, TOutput> {\n /** The generated evaluation report */\n report: EvalReport<TInput, TOutput>\n /** Path where the report was saved */\n savedPath: string\n}\n\n/**\n * Creates a runner that automatically logs and saves reports.\n *\n * @param options - Runner configuration\n * @returns A function that runs the suite and handles reporting\n *\n * @example\n * ```typescript\n * import { createReportRunner, GOOGLE_PRICING } from '@agtlantis/eval'\n *\n * const run = createReportRunner({\n * outputDir: './reports',\n * pricing: GOOGLE_PRICING,\n * verbosity: 'detailed',\n * })\n *\n * const { report, savedPath } = await run(suite, testCases, 'my-evaluation')\n * // Logs to console and saves to ./reports/my-evaluation-{timestamp}.json\n * console.log(`Saved to: ${savedPath}`)\n * ```\n */\nexport function createReportRunner(options: ReportRunnerOptions) {\n const { outputDir, pricing, verbosity } = options\n\n const jsonReporter = new JsonReporter({ outputDir, pricing })\n const consoleReporter = verbosity !== false\n ? new ConsoleReporter({ verbosity: verbosity || 'summary', pricing })\n : null\n\n return async <TInput, TOutput>(\n suite: EvalSuite<TInput, TOutput>,\n testCases: TestCase<TInput>[],\n name: string,\n ): Promise<ReportRunnerResult<TInput, TOutput>> => {\n const report = await suite.run(testCases)\n\n consoleReporter?.log(report)\n const savedPath = jsonReporter.save(report, name)\n\n return { report, savedPath }\n }\n}\n","import { writeFileSync, mkdirSync } from 'node:fs'\nimport path from 'node:path'\nimport type { ImprovementCycleResult } from '@/improvement-cycle/types'\nimport { toISOStringIfDate } from './format-utils'\n\n/**\n * Options for saving an ImprovementCycleResult as JSON.\n *\n * Supports two modes:\n * - **Auto mode**: Provide `outputDir` and `name` to create a timestamped subdirectory\n * - **Explicit mode**: Provide `directory` to use an existing directory directly\n */\nexport interface SaveCycleJsonOptions {\n /** Base output directory (creates {name}-{timestamp}/ subdirectory) */\n outputDir?: string\n /** Cycle name (used for folder name with timestamp) */\n name?: string\n /** Use this exact directory path (no timestamp suffix added) */\n directory?: string\n /** Whether to save individual round reports (default: true) */\n saveRounds?: boolean\n}\n\n/**\n * Saves an ImprovementCycleResult to JSON files.\n *\n * Creates a directory containing:\n * - `cycle-summary.json`: Structured cycle summary\n * - `round-{n}-report.json`: Individual round reports (if saveRounds=true)\n *\n * @example Auto mode (creates timestamped directory)\n * ```typescript\n * const dir = saveCycleJson(result, {\n * outputDir: './reports',\n * name: 'my-agent',\n * })\n * // -> ./reports/my-agent-1736691234567/\n * ```\n *\n * @example Explicit mode (uses existing directory)\n * ```typescript\n * const dir = saveCycleJson(result, {\n * directory: './reports/my-existing-dir',\n * })\n * // -> ./reports/my-existing-dir/\n * ```\n */\nexport function saveCycleJson<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: SaveCycleJsonOptions,\n): string {\n const { outputDir, name, directory, saveRounds = true } = options\n\n const cycleDir = resolveCycleDirectory(outputDir, name, directory)\n mkdirSync(cycleDir, { recursive: true })\n\n saveCycleSummary(cycleDir, result)\n\n if (saveRounds) {\n saveRoundReports(cycleDir, result.rounds)\n }\n\n return cycleDir\n}\n\nfunction resolveCycleDirectory(\n outputDir: string | undefined,\n name: string | undefined,\n directory: string | undefined\n): string {\n if (directory) {\n return directory\n }\n if (outputDir && name) {\n return path.join(outputDir, `${name}-${Date.now()}`)\n }\n throw new Error('saveCycleJson requires either \"directory\" or both \"outputDir\" and \"name\"')\n}\n\nfunction saveCycleSummary<TInput, TOutput>(\n cycleDir: string,\n result: ImprovementCycleResult<TInput, TOutput>\n): void {\n const summaryPath = path.join(cycleDir, 'cycle-summary.json')\n const summary = {\n rounds: result.rounds.map((round) => ({\n round: round.round,\n completedAt: toISOStringIfDate(round.completedAt),\n score: round.report.summary.avgScore,\n scoreDelta: round.scoreDelta,\n cost: round.cost,\n suggestionsGenerated: round.suggestionsGenerated.length,\n suggestionsApproved: round.suggestionsApproved.length,\n promptVersionAfter: round.promptVersionAfter,\n })),\n terminationReason: result.terminationReason,\n totalCost: result.totalCost,\n roundCount: result.rounds.length,\n initialScore: result.rounds[0]?.report.summary.avgScore ?? null,\n finalScore: result.rounds[result.rounds.length - 1]?.report.summary.avgScore ?? null,\n }\n writeFileSync(summaryPath, JSON.stringify(summary, null, 2))\n}\n\nfunction saveRoundReports<TInput, TOutput>(\n cycleDir: string,\n rounds: ImprovementCycleResult<TInput, TOutput>['rounds']\n): void {\n for (const round of rounds) {\n const roundPath = path.join(cycleDir, `round-${round.round}-report.json`)\n const roundData = {\n round: round.round,\n completedAt: toISOStringIfDate(round.completedAt),\n report: {\n ...round.report,\n generatedAt: toISOStringIfDate(round.report.generatedAt),\n },\n suggestionsGenerated: round.suggestionsGenerated,\n suggestionsApproved: round.suggestionsApproved,\n promptSnapshot: round.promptSnapshot,\n cost: round.cost,\n scoreDelta: round.scoreDelta,\n }\n writeFileSync(roundPath, JSON.stringify(roundData, null, 2))\n }\n}\n","import type { ImprovementCycleResult } from '@/improvement-cycle/types'\nimport type { LogVerbosity } from './types'\nimport { ConsoleReporter } from './console-reporter'\nimport { formatScoreDelta } from './format-utils'\n\n/**\n * Options for logging an ImprovementCycleResult to console.\n */\nexport interface LogCycleOptions {\n /** Verbosity level for per-round details */\n verbosity?: LogVerbosity\n /** Show per-round details (default: false, summary only) */\n showRounds?: boolean\n}\n\n/**\n * Logs an ImprovementCycleResult to the console.\n *\n * Shows cycle summary including round count, termination reason, total cost,\n * and score progression. Optionally shows per-round details.\n *\n * @param result - The improvement cycle result to log\n * @param options - Logging options\n *\n * @example\n * ```typescript\n * import { logCycle } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * logCycle(result, { verbosity: 'detailed', showRounds: true })\n * ```\n */\nexport function logCycle<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: LogCycleOptions = {},\n): void {\n const { verbosity = 'summary', showRounds = false } = options\n\n console.log('\\n🔄 Improvement Cycle Complete')\n console.log(` Rounds: ${result.rounds.length}`)\n console.log(` Termination: ${result.terminationReason}`)\n console.log(` Total Cost: $${result.totalCost.toFixed(4)}`)\n\n if (result.rounds.length > 0) {\n const firstScore = result.rounds[0].report.summary.avgScore\n const lastScore = result.rounds[result.rounds.length - 1].report.summary.avgScore\n const delta = lastScore - firstScore\n console.log(` Score: ${firstScore.toFixed(1)} -> ${lastScore.toFixed(1)} (${formatScoreDelta(delta)})`)\n }\n\n if (showRounds) {\n const consoleReporter = new ConsoleReporter({ verbosity })\n for (const round of result.rounds) {\n console.log(`\\n -- Round ${round.round} --`)\n consoleReporter.log(round.report)\n }\n }\n}\n","import { writeFileSync } from 'node:fs';\n\nimport type { ImprovementCycleResult } from '@/improvement-cycle/types';\n\nimport { formatScoreDelta } from './format-utils';\nimport { reportToMarkdown } from './markdown';\n\n/**\n * Options for generating cycle markdown.\n */\nexport interface CycleMarkdownOptions {\n /** Include full per-round details (default: true) */\n includeRoundDetails?: boolean;\n /** Show prompt evolution - initial vs final (default: false) */\n showPromptEvolution?: boolean;\n}\n\n/**\n * Converts an ImprovementCycleResult to markdown.\n *\n * Generates a comprehensive report including:\n * - Summary table (rounds, termination, cost, scores)\n * - Score progression table\n * - Per-round details (optional)\n * - Prompt evolution (optional)\n *\n * @param result - The improvement cycle result\n * @param options - Markdown generation options\n * @returns Markdown string\n *\n * @example\n * ```typescript\n * import { cycleToMarkdown } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * const markdown = cycleToMarkdown(result, {\n * includeRoundDetails: true,\n * showPromptEvolution: true,\n * })\n * ```\n */\nexport function cycleToMarkdown<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: CycleMarkdownOptions = {}\n): string {\n const { includeRoundDetails = true, showPromptEvolution = false } = options;\n const lines: string[] = [];\n\n // Header\n lines.push('# Improvement Cycle Report');\n lines.push('');\n\n // Summary\n lines.push('## Summary');\n lines.push('');\n lines.push('| Metric | Value |');\n lines.push('|--------|-------|');\n lines.push(`| Rounds | ${result.rounds.length} |`);\n lines.push(`| Termination | ${result.terminationReason} |`);\n lines.push(`| Total Cost | $${result.totalCost.toFixed(4)} |`);\n\n if (result.rounds.length > 0) {\n const first = result.rounds[0].report.summary.avgScore;\n const last = result.rounds[result.rounds.length - 1].report.summary.avgScore;\n lines.push(`| Initial Score | ${first.toFixed(1)} |`);\n lines.push(`| Final Score | ${last.toFixed(1)} |`);\n lines.push(`| Improvement | ${formatScoreDelta(last - first)} |`);\n }\n lines.push('');\n\n // Score progression table\n lines.push('## Score Progression');\n lines.push('');\n lines.push('| Round | Score | Delta | Cost |');\n lines.push('|-------|-------|-------|------|');\n for (const round of result.rounds) {\n const delta = formatScoreDelta(round.scoreDelta);\n lines.push(\n `| ${round.round} | ${round.report.summary.avgScore.toFixed(1)} | ${delta} | $${round.cost.total.toFixed(4)} |`\n );\n }\n lines.push('');\n\n // Per-round details\n if (includeRoundDetails) {\n lines.push('## Round Details');\n lines.push('');\n for (const round of result.rounds) {\n lines.push(`### Round ${round.round}`);\n lines.push('');\n lines.push(reportToMarkdown(round.report));\n lines.push('');\n }\n }\n\n // Prompt evolution\n if (showPromptEvolution && result.rounds.length > 0) {\n lines.push('## Prompt Evolution');\n lines.push('');\n lines.push('### Initial Prompt');\n lines.push('');\n lines.push('```');\n lines.push(result.rounds[0].promptSnapshot.userTemplate);\n lines.push('```');\n lines.push('');\n lines.push('### Final Prompt');\n lines.push('');\n lines.push('```');\n // Use the final prompt's userTemplate if available, otherwise try to call renderUserPrompt\n const finalPrompt = result.finalPrompt;\n if ('userTemplate' in finalPrompt && typeof finalPrompt.userTemplate === 'string') {\n lines.push(finalPrompt.userTemplate);\n } else {\n lines.push('[Compiled prompt - template not available]');\n }\n lines.push('```');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Saves an ImprovementCycleResult as markdown.\n *\n * @param result - The improvement cycle result\n * @param filePath - Path to save the markdown file\n * @param options - Markdown generation options\n *\n * @example\n * ```typescript\n * import { saveCycleMarkdown } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * saveCycleMarkdown(result, './reports/cycle-report.md', {\n * includeRoundDetails: true,\n * })\n * ```\n */\nexport function saveCycleMarkdown<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n filePath: string,\n options?: CycleMarkdownOptions\n): void {\n const markdown = cycleToMarkdown(result, options);\n writeFileSync(filePath, markdown);\n}\n","import { compileTemplate } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt } from '@/core/types';\nimport { truncate } from '@/utils/json';\n\nimport type { Suggestion } from './types';\n\n/**\n * Generates a unified diff string for a suggestion.\n *\n * @example\n * ```typescript\n * const diff = suggestionDiff(suggestion)\n * console.log(diff)\n * // - Old value here\n * // + New value here\n * ```\n */\nexport function suggestionDiff(suggestion: Suggestion): string {\n const oldLines = suggestion.currentValue.split('\\n');\n const newLines = suggestion.suggestedValue.split('\\n');\n\n const lines: string[] = [];\n lines.push(`--- ${suggestion.type} (current)`);\n lines.push(`+++ ${suggestion.type} (suggested)`);\n lines.push('');\n\n for (const line of oldLines) {\n lines.push(`- ${line}`);\n }\n for (const line of newLines) {\n lines.push(`+ ${line}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Generates a preview of what the suggestion would look like when applied.\n *\n * @example\n * ```typescript\n * const preview = suggestionPreview(suggestion)\n * console.log(preview)\n * ```\n */\nexport function suggestionPreview(suggestion: Suggestion): string {\n const lines: string[] = [];\n\n lines.push(`=== Suggestion Preview ===`);\n lines.push(`Type: ${suggestion.type}`);\n lines.push(`Priority: ${suggestion.priority}`);\n lines.push(``);\n lines.push(`Reasoning: ${suggestion.reasoning}`);\n lines.push(``);\n lines.push(`Expected Improvement: ${suggestion.expectedImprovement}`);\n lines.push(``);\n lines.push(`--- Current Value ---`);\n lines.push(suggestion.currentValue);\n lines.push(``);\n lines.push(`--- Suggested Value ---`);\n lines.push(suggestion.suggestedValue);\n\n return lines.join('\\n');\n}\n\n/**\n * Formats a suggestion as a compact summary string.\n *\n * @example\n * ```typescript\n * console.log(suggestionSummary(suggestion))\n * // [HIGH] system_prompt: Improve clarity in instructions\n * ```\n */\nexport function suggestionSummary(suggestion: Suggestion): string {\n const priorityTag = `[${suggestion.priority.toUpperCase()}]`;\n return `${priorityTag} ${suggestion.type}: ${truncate(suggestion.reasoning, 60)}`;\n}\n\n/**\n * Safely replaces the first occurrence of a search string with a replacement string.\n * Uses a function replacement to avoid special pattern interpretation ($&, $1, etc.)\n * that JavaScript's String.replace() performs.\n *\n * @internal\n */\nfunction safeReplace(str: string, search: string, replacement: string): string {\n return str.replace(search, () => replacement);\n}\n\n/**\n * Options for applying suggestions to a prompt.\n */\nexport interface ApplyPromptSuggestionsOptions {\n /**\n * Version bump type for semver.\n * - 'major': 1.0.0 → 2.0.0 (breaking changes)\n * - 'minor': 1.0.0 → 1.1.0 (new features)\n * - 'patch': 1.0.0 → 1.0.1 (bug fixes)\n */\n bumpVersion?: 'major' | 'minor' | 'patch';\n}\n\n/**\n * Result of applying suggestions to a prompt.\n */\nexport interface ApplySuggestionsResult<TInput, TOutput = unknown> {\n /** The updated prompt with suggestions applied */\n prompt: AgentPrompt<TInput>;\n /** Number of suggestions that were successfully applied */\n appliedCount: number;\n /** Suggestions that could not be applied (currentValue not found) */\n skipped: Array<{ suggestion: Suggestion; reason: string }>;\n}\n\n/**\n * Bumps a semver version string.\n *\n * @example\n * ```typescript\n * bumpVersion('1.0.0', 'major') // '2.0.0'\n * bumpVersion('1.0.0', 'minor') // '1.1.0'\n * bumpVersion('1.0.0', 'patch') // '1.0.1'\n * bumpVersion('1.2.3', 'minor') // '1.3.0'\n * ```\n */\nexport function bumpVersion(version: string, bump: 'major' | 'minor' | 'patch'): string {\n const parts = version.split('.').map((n) => parseInt(n, 10));\n\n // Handle invalid version formats\n if (parts.length !== 3 || parts.some(isNaN)) {\n throw new EvalError(\n `Invalid version format: \"${version}\". Expected semver format (x.y.z)`,\n {\n code: EvalErrorCode.SUGGESTION_APPLY_ERROR,\n context: { version, expectedFormat: 'x.y.z' },\n }\n );\n }\n\n const [major, minor, patch] = parts;\n\n switch (bump) {\n case 'major':\n return `${major + 1}.0.0`;\n case 'minor':\n return `${major}.${minor + 1}.0`;\n case 'patch':\n return `${major}.${minor}.${patch + 1}`;\n }\n}\n\n/**\n * Applies approved suggestions to an AgentPrompt and returns a new prompt.\n *\n * This function:\n * - Only applies suggestions where `approved === true`\n * - For `system_prompt`: replaces `currentValue` in `prompt.system`\n * - For `user_prompt`: requires `prompt.userTemplate` field, updates it and regenerates `renderUserPrompt`\n * - For `parameters`: applies to custom fields in the prompt\n * - Optionally bumps the version (major/minor/patch)\n *\n * **Important behaviors:**\n * - Only the **first occurrence** of `currentValue` is replaced (not all occurrences)\n * - Special characters like `$&`, `$1` in `suggestedValue` are preserved as-is (no regex interpretation)\n *\n * @example\n * ```typescript\n * // Apply approved suggestions with minor version bump\n * const result = applyPromptSuggestions(\n * currentPrompt,\n * suggestions.filter(s => s.approved),\n * { bumpVersion: 'minor' }\n * )\n *\n * console.log(result.prompt.version) // '1.1.0'\n * console.log(`Applied ${result.appliedCount} suggestions`)\n *\n * if (result.skipped.length > 0) {\n * console.warn('Skipped suggestions:', result.skipped)\n * }\n * ```\n *\n * @throws {EvalError} with code SUGGESTION_APPLY_ERROR if:\n * - A `user_prompt` suggestion is applied but prompt lacks `userTemplate` field\n * - Version format is invalid when bumpVersion is specified\n */\nexport function applyPromptSuggestions<TInput, TOutput = unknown>(\n currentPrompt: AgentPrompt<TInput>,\n suggestions: Suggestion[],\n options?: ApplyPromptSuggestionsOptions\n): ApplySuggestionsResult<TInput, TOutput> {\n const approvedSuggestions = suggestions.filter((s) => s.approved);\n\n if (approvedSuggestions.length === 0) {\n return {\n prompt: currentPrompt,\n appliedCount: 0,\n skipped: [],\n };\n }\n\n let newPrompt: AgentPrompt<TInput> = { ...currentPrompt };\n let appliedCount = 0;\n const skipped: Array<{ suggestion: Suggestion; reason: string }> = [];\n\n for (const suggestion of approvedSuggestions) {\n const applyResult = applySingleSuggestion(newPrompt, suggestion);\n\n if (applyResult.success) {\n newPrompt = applyResult.prompt;\n appliedCount++;\n } else {\n skipped.push({ suggestion, reason: applyResult.reason });\n }\n }\n\n if (options?.bumpVersion && appliedCount > 0) {\n newPrompt = {\n ...newPrompt,\n version: bumpVersion(currentPrompt.version, options.bumpVersion),\n };\n }\n\n return {\n prompt: newPrompt,\n appliedCount,\n skipped,\n };\n}\n\n/** Fields that are part of the core AgentPrompt interface and should not be modified by 'parameters' suggestions */\nconst AGENT_PROMPT_CORE_FIELDS = [\n 'id',\n 'version',\n 'system',\n 'renderUserPrompt',\n 'userTemplate',\n] as const;\n\nfunction applySingleSuggestion<TInput, TOutput>(\n prompt: AgentPrompt<TInput>,\n suggestion: Suggestion\n): { success: true; prompt: AgentPrompt<TInput> } | { success: false; reason: string } {\n switch (suggestion.type) {\n case 'system_prompt': {\n if (!prompt.system.includes(suggestion.currentValue)) {\n return {\n success: false,\n reason: `currentValue not found in system prompt: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n return {\n success: true,\n prompt: {\n ...prompt,\n system: safeReplace(\n prompt.system,\n suggestion.currentValue,\n suggestion.suggestedValue\n ),\n },\n };\n }\n\n case 'user_prompt': {\n const userTemplate = prompt.userTemplate as string | undefined;\n\n if (typeof userTemplate !== 'string') {\n throw new EvalError(\n `Cannot apply user_prompt suggestion: prompt does not have a userTemplate field. ` +\n `The renderUserPrompt is a function and cannot be modified directly.`,\n {\n code: EvalErrorCode.SUGGESTION_APPLY_ERROR,\n context: {\n suggestionType: suggestion.type,\n hasUserTemplate: 'userTemplate' in prompt,\n },\n }\n );\n }\n\n if (!userTemplate.includes(suggestion.currentValue)) {\n return {\n success: false,\n reason: `currentValue not found in userTemplate: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n\n const newTemplate = safeReplace(\n userTemplate,\n suggestion.currentValue,\n suggestion.suggestedValue\n );\n\n return {\n success: true,\n prompt: {\n ...prompt,\n userTemplate: newTemplate,\n renderUserPrompt: compileTemplate<TInput>(newTemplate, prompt.id),\n },\n };\n }\n\n case 'parameters': {\n const updatedPrompt = { ...prompt };\n let found = false;\n\n for (const [key, value] of Object.entries(updatedPrompt)) {\n if (\n AGENT_PROMPT_CORE_FIELDS.includes(\n key as (typeof AGENT_PROMPT_CORE_FIELDS)[number]\n )\n ) {\n continue;\n }\n\n if (typeof value === 'string' && value.includes(suggestion.currentValue)) {\n (updatedPrompt as Record<string, unknown>)[key] = safeReplace(\n value,\n suggestion.currentValue,\n suggestion.suggestedValue\n );\n found = true;\n break;\n }\n }\n\n if (!found) {\n return {\n success: false,\n reason: `currentValue not found in any parameter field: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n\n return {\n success: true,\n prompt: updatedPrompt,\n };\n }\n\n default: {\n const _exhaustive: never = suggestion.type;\n return {\n success: false,\n reason: `Unknown suggestion type: ${suggestion.type}`,\n };\n }\n }\n}\n","import { type LanguageModelUsage, type ModelMessage, Output } from 'ai';\nimport { z } from 'zod';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt, EvalTestResult, EvalTokenUsage, ImproverMetadata } from '@/core/types';\n\nimport { defaultImproverPrompt } from './prompts/default';\nimport type {\n AggregatedMetrics,\n ImproveResult,\n Improver,\n ImproverConfig,\n ImproverContext,\n Suggestion,\n} from './types';\n\nfunction toEvalTokenUsage(usage: LanguageModelUsage): EvalTokenUsage {\n return {\n inputTokens: usage.inputTokens ?? 0,\n outputTokens: usage.outputTokens ?? 0,\n totalTokens: usage.totalTokens ?? 0,\n };\n}\n\nconst ImproverResponseSchema = z.object({\n suggestions: z.array(\n z.object({\n type: z.enum(['system_prompt', 'user_prompt', 'parameters']),\n priority: z.enum(['high', 'medium', 'low']),\n currentValue: z.string(),\n suggestedValue: z.string(),\n reasoning: z.string(),\n expectedImprovement: z.string(),\n })\n ),\n});\n\ntype ImproverResponse = z.infer<typeof ImproverResponseSchema>;\n\nfunction aggregateMetrics(results: EvalTestResult<unknown, unknown>[]): AggregatedMetrics {\n if (results.length === 0) {\n return {\n avgLatencyMs: 0,\n totalTokens: 0,\n };\n }\n\n let totalLatency = 0;\n let totalTokens = 0;\n\n for (const result of results) {\n totalLatency += result.metrics.latencyMs;\n totalTokens += result.metrics.tokenUsage.totalTokens;\n }\n\n return {\n avgLatencyMs: Math.round(totalLatency / results.length),\n totalTokens,\n };\n}\n\n/**\n * Creates an LLM-based prompt improver.\n *\n * Analyzes test results and suggests improvements to the agent's prompt,\n * focusing on low-scoring criteria with actionable suggestions.\n *\n * @example\n * ```typescript\n * import { createImprover, defaultImproverPrompt } from '@agtlantis/eval'\n * import { createGoogleProvider } from '@agtlantis/core'\n *\n * const provider = createGoogleProvider({ apiKey }).withDefaultModel('gemini-2.5-flash')\n *\n * const improver = createImprover({\n * provider,\n * prompt: defaultImproverPrompt,\n * })\n *\n * const { suggestions } = await improver.improve(agent.prompt, evaluatedResults)\n *\n * for (const suggestion of suggestions) {\n * console.log(suggestionDiff(suggestion))\n * suggestion.approved = true\n * }\n *\n * const newPrompt = applyPromptSuggestions(agent.prompt, suggestions)\n * ```\n */\nexport function createImprover(config: ImproverConfig): Improver {\n const { provider, prompt = defaultImproverPrompt, model } = config;\n\n return {\n async improve(\n agentPrompt: AgentPrompt<any>,\n results: EvalTestResult<any, any>[]\n ): Promise<ImproveResult> {\n const context: ImproverContext = {\n agentPrompt,\n evaluatedResults: results,\n aggregatedMetrics: aggregateMetrics(results),\n };\n\n const messages: ModelMessage[] = [\n { role: 'system', content: prompt.system },\n { role: 'user', content: prompt.renderUserPrompt(context) },\n ];\n\n let response: ImproverResponse;\n let llmUsage: LanguageModelUsage | undefined;\n\n try {\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages,\n output: Output.object({ schema: ImproverResponseSchema }),\n });\n return result.output!;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n response = executionResult.value;\n llmUsage = executionResult.summary.totalLLMUsage;\n } catch (cause) {\n throw EvalError.from(cause, EvalErrorCode.LLM_API_ERROR, {\n promptId: prompt.id,\n promptVersion: prompt.version,\n });\n }\n\n const suggestions: Suggestion[] = response.suggestions.map((s) => ({\n ...s,\n approved: undefined,\n modified: undefined,\n }));\n\n const metadata: ImproverMetadata | undefined = llmUsage\n ? { tokenUsage: toEvalTokenUsage(llmUsage), model }\n : undefined;\n\n return { suggestions, metadata };\n },\n };\n}\n","import { truncate } from '@/utils/json';\n\nimport type { ImproverContext, ImproverPrompt } from '../types';\n\nexport const defaultImproverPrompt: ImproverPrompt = {\n id: 'default-improver',\n version: '2.0.0',\n\n system: `You are an expert prompt engineer specializing in optimizing AI Agent prompts.\n\nYour role is to analyze test results and evaluation feedback to propose targeted improvements.\n\n## Improvement Principles\n\n1. **Focus on Impact**: Prioritize changes that address the lowest-scoring criteria\n - Target specific failure patterns, not general improvements\n - One well-crafted change is better than many superficial ones\n\n2. **Be Specific and Actionable**: Provide concrete changes, not vague suggestions\n - Show exact text to add, modify, or remove\n - Explain the mechanism by which the change will help\n\n3. **Consider Trade-offs**: Evaluate side effects of each change\n - Will this fix break other test cases?\n - Does it increase prompt length/cost significantly?\n - Could it introduce new failure modes?\n\n4. **Maintain Prompt Quality**: Preserve clarity and structure\n - Keep prompts readable and maintainable\n - Avoid over-engineering or excessive constraints\n - Ensure changes align with the agent's core purpose\n\n## Suggestion Priority Levels\n- **high**: Critical issues causing test failures, should be addressed immediately\n- **medium**: Issues affecting quality scores, recommended for next iteration\n- **low**: Minor optimizations, nice-to-have improvements\n\n## Response Format\n\nYou MUST respond with valid JSON only. No additional text outside the JSON structure.\n\n{\n \"suggestions\": [\n {\n \"type\": \"system_prompt\" | \"user_prompt\" | \"parameters\",\n \"priority\": \"high\" | \"medium\" | \"low\",\n \"currentValue\": \"The specific text or value being changed\",\n \"suggestedValue\": \"The proposed replacement text or value\",\n \"reasoning\": \"Why this change addresses the identified issue\",\n \"expectedImprovement\": \"Predicted impact on scores and behavior\"\n }\n ]\n}`,\n\n renderUserPrompt: (ctx: ImproverContext): string => {\n const failedDetails = buildFailedCaseDetails(ctx.evaluatedResults);\n\n return `\n## Current Agent Prompt\n\n### System Prompt\n\\`\\`\\`\n${ctx.agentPrompt.system}\n\\`\\`\\`\n\n## Test Results Summary\n- Total tests: ${ctx.evaluatedResults.length}\n- Passed: ${ctx.evaluatedResults.filter((r) => r.passed).length}\n- Failed: ${ctx.evaluatedResults.filter((r) => !r.passed).length}\n\n## Performance Metrics\n- Average latency: ${ctx.aggregatedMetrics.avgLatencyMs}ms\n- Total tokens used: ${ctx.aggregatedMetrics.totalTokens}\n\n## Failed/Low-Score Cases Details\n${failedDetails}\n\nBased on the above results, please propose specific prompt improvements.`.trim();\n },\n};\n\nfunction buildFailedCaseDetails(results: ImproverContext['evaluatedResults']): string {\n const failedOrLowScore = results.filter((r) => !r.passed || r.overallScore < 70);\n\n if (failedOrLowScore.length === 0) {\n return '(None - all tests passed with acceptable scores)';\n }\n\n return failedOrLowScore\n .map(\n (r) => `\n### ${r.testCase.id ?? 'unnamed'} (Score: ${r.overallScore})\n**Input:** ${truncate(JSON.stringify(r.testCase.input), 200)}\n**Output:** ${truncate(JSON.stringify(r.output), 200)}\n**Evaluation:**\n${r.verdicts.map((v) => `- ${v.criterionId}: ${v.score}/100 - ${v.reasoning}`).join('\\n')}`\n )\n .join('\\n');\n}\n","import type {\n AgentPrompt,\n EvalAgent,\n EvalTokenUsage,\n TestResultWithVerdict,\n Verdict,\n} from '@/core/types';\nimport type { ImproveResult, Improver, Suggestion } from '@/improver/types';\nimport type { EvalContext, Judge, JudgeResult } from '@/judge/types';\n\n/**\n * Configuration for creating a mock agent.\n */\nexport interface MockAgentConfig<TInput, TOutput> {\n /** Name for the mock agent */\n name?: string;\n\n /** Description for the mock agent */\n description?: string;\n\n /** Response to return from execute() */\n response?: TOutput;\n\n /** Token usage to include in metadata */\n tokenUsage?: EvalTokenUsage;\n\n /** Delay in ms before returning response */\n delay?: number;\n\n /** If true, throw an error instead of returning response */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom execute function for more control */\n executeFn?: (\n input: TInput\n ) => Promise<{ result: TOutput; metadata?: { tokenUsage?: EvalTokenUsage } }>;\n}\n\n/**\n * Creates a mock agent for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const agent = createMockAgent<{ query: string }, { answer: string }>({\n * response: { answer: 'Hello!' },\n * })\n *\n * // With delay and token usage\n * const agent = createMockAgent({\n * response: { answer: 'Response' },\n * delay: 100,\n * tokenUsage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n * })\n *\n * // Error testing\n * const agent = createMockAgent({\n * shouldError: true,\n * errorMessage: 'Agent failed',\n * })\n * ```\n */\nexport function createMockAgent<TInput, TOutput>(\n config: MockAgentConfig<TInput, TOutput> = {}\n): EvalAgent<TInput, TOutput> {\n const {\n name = 'MockAgent',\n description = 'A mock agent for testing',\n response = {} as TOutput,\n tokenUsage = { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n delay = 0,\n shouldError = false,\n errorMessage = 'Mock agent execution failed',\n executeFn,\n } = config;\n\n return {\n config: { name, description },\n prompt: {\n id: 'mock-prompt',\n version: '1.0.0',\n system: 'You are a mock agent',\n renderUserPrompt: (input: TInput) => JSON.stringify(input),\n },\n execute: async (input: TInput) => {\n if (executeFn) {\n return executeFn(input);\n }\n\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return {\n result: response,\n metadata: { tokenUsage },\n };\n },\n };\n}\n\n/**\n * Configuration for creating a mock judge.\n */\nexport interface MockJudgeConfig {\n /** Overall score to return (0-100) */\n score?: number;\n\n /** Whether the evaluation passed */\n passed?: boolean;\n\n /** Verdicts to return */\n verdicts?: Verdict[];\n\n /** Metadata to return (for cost tracking tests) */\n metadata?: JudgeResult['metadata'];\n\n /** If true, throw an error instead of returning result */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom evaluate function for more control */\n evaluateFn?: (context: EvalContext) => Promise<JudgeResult>;\n}\n\n/**\n * Creates a mock judge for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage - passing test\n * const judge = createMockJudge({\n * score: 85,\n * passed: true,\n * })\n *\n * // Custom verdicts\n * const judge = createMockJudge({\n * verdicts: [\n * { criterionId: 'accuracy', score: 90, reasoning: 'Good', passed: true },\n * { criterionId: 'clarity', score: 80, reasoning: 'Clear', passed: true },\n * ],\n * score: 85,\n * passed: true,\n * })\n *\n * // Failing test\n * const judge = createMockJudge({\n * score: 40,\n * passed: false,\n * })\n *\n * // Error testing\n * const judge = createMockJudge({\n * shouldError: true,\n * errorMessage: 'Judge failed to evaluate',\n * })\n * ```\n */\nexport function createMockJudge(config: MockJudgeConfig = {}): Judge {\n const {\n score = 80,\n passed = true,\n verdicts = [\n { criterionId: 'default', score: 80, reasoning: 'Default verdict', passed: true },\n ],\n metadata,\n shouldError = false,\n errorMessage = 'Mock judge evaluation failed',\n evaluateFn,\n } = config;\n\n return {\n evaluate: async (context: EvalContext) => {\n if (evaluateFn) {\n return evaluateFn(context);\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return {\n verdicts,\n overallScore: score,\n passed,\n metadata,\n };\n },\n };\n}\n\n/**\n * Configuration for creating a mock improver.\n */\nexport interface MockImproverConfig {\n /** Suggestions to return */\n suggestions?: Suggestion[];\n\n /** If true, throw an error instead of returning suggestions */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom improve function for more control */\n improveFn?: (\n agentPrompt: AgentPrompt<any>,\n results: TestResultWithVerdict<any, any>[]\n ) => Promise<ImproveResult>;\n}\n\n/**\n * Creates a mock improver for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const improver = createMockImprover({\n * suggestions: [\n * {\n * type: 'system_prompt',\n * priority: 'high',\n * currentValue: 'Old prompt',\n * suggestedValue: 'New prompt',\n * reasoning: 'Better clarity',\n * expectedImprovement: '10% improvement',\n * },\n * ],\n * })\n *\n * // Empty suggestions\n * const improver = createMockImprover({ suggestions: [] })\n *\n * // Error testing\n * const improver = createMockImprover({\n * shouldError: true,\n * errorMessage: 'Improver failed',\n * })\n * ```\n */\nexport function createMockImprover(config: MockImproverConfig = {}): Improver {\n const {\n suggestions = [],\n shouldError = false,\n errorMessage = 'Mock improver failed',\n improveFn,\n } = config;\n\n return {\n improve: async (agentPrompt, results) => {\n if (improveFn) {\n return improveFn(agentPrompt, results);\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return { suggestions };\n },\n };\n}\n","/**\n * CLI Configuration Types\n *\n * Defines the configuration schema for `agent-eval.config.ts` files.\n * Use `defineConfig()` helper for type inference and IDE autocompletion.\n */\n\nimport type {\n EvalAgent,\n TestCase,\n Criterion,\n ValidatorCriterion,\n FileContent,\n} from '@/core/types'\nimport type { JudgePrompt } from '@/judge/types'\nimport type { ImproverPrompt } from '@/improver/types'\nimport type { EvalPricingConfig } from '@/reporter/cost-helpers'\nimport type {\n MultiTurnTestCase,\n TerminationCondition,\n FollowUpInput,\n} from '@/multi-turn/types'\n\n/**\n * LLM provider configuration.\n * API keys fall back to OPENAI_API_KEY or GOOGLE_API_KEY env vars.\n */\nexport interface LLMConfig {\n /** LLM provider */\n provider: 'openai' | 'gemini'\n /** API key (optional - falls back to environment variable) */\n apiKey?: string\n /** Default model to use */\n defaultModel?: string\n /**\n * OpenAI reasoning effort (o1/o3 models only)\n * @see https://platform.openai.com/docs/guides/reasoning\n */\n reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high'\n /**\n * Default response format\n * @see https://platform.openai.com/docs/guides/structured-outputs\n */\n defaultResponseFormat?: { type: 'json_object' | 'text' }\n}\n\nexport interface CLIJudgeConfig {\n /**\n * LLM configuration for judge.\n * If not specified, uses the main `llm` config.\n */\n llm?: LLMConfig\n /**\n * Evaluation criteria.\n * Use built-in criteria factories like `accuracy()`, `relevance()`,\n * or define custom criteria objects.\n */\n criteria: Array<Criterion | ValidatorCriterion>\n /**\n * Score threshold for passing (0-100).\n * @default 70\n */\n passThreshold?: number\n /**\n * Custom judge prompt.\n * If not specified, uses the default judge prompt.\n */\n prompt?: JudgePrompt\n}\n\nexport interface CLIImproverConfig {\n /**\n * LLM configuration for improver.\n * If not specified, uses the main `llm` config.\n */\n llm?: LLMConfig\n /**\n * Custom improver prompt.\n * If not specified, uses the default improver prompt.\n */\n prompt?: ImproverPrompt\n}\n\nexport interface OutputConfig {\n /**\n * Directory for report output.\n * @default './reports'\n */\n dir?: string\n /**\n * Custom filename pattern.\n * Supports `{timestamp}` placeholder.\n * @default 'eval-{timestamp}.md'\n */\n filename?: string\n /**\n * Include verbose details in console output.\n * @default false\n */\n verbose?: boolean\n}\n\nexport interface RunConfig {\n /**\n * Number of concurrent test executions.\n * @default 1\n */\n concurrency?: number\n /**\n * Number of iterations per test case (for statistical analysis).\n * @default 1\n */\n iterations?: number\n /**\n * Stop execution on first test failure.\n * @default false\n */\n stopOnFirstFailure?: boolean\n}\n\nexport interface CLISingleTurnTestCase<TInput> extends TestCase<TInput> {\n /** Test case must NOT have multiTurn field */\n multiTurn?: never\n}\n\nexport interface CLIMultiTurnTestCase<TInput, TOutput = unknown>\n extends TestCase<TInput> {\n /** Multi-turn configuration */\n multiTurn: {\n /**\n * Inputs for 2nd turn onwards.\n * First turn uses `input` field.\n */\n followUpInputs?: FollowUpInput<TInput, TOutput>[]\n /**\n * Termination conditions (OR relationship).\n * Any one triggers termination.\n */\n terminateWhen: TerminationCondition<TInput, TOutput>[]\n /**\n * Safety limit: maximum turns.\n * @default 10\n */\n maxTurns?: number\n /**\n * Outcome when termination condition is met.\n * @default 'pass'\n */\n onConditionMet?: 'pass' | 'fail'\n /**\n * Outcome when maxTurns is reached.\n * @default 'fail'\n */\n onMaxTurnsReached?: 'pass' | 'fail'\n }\n}\n\nexport type CLITestCase<TInput, TOutput = unknown> =\n | CLISingleTurnTestCase<TInput>\n | CLIMultiTurnTestCase<TInput, TOutput>\n\n/**\n * Main evaluation configuration for CLI.\n * @typeParam TInput - Agent input type\n * @typeParam TOutput - Agent output type\n */\nexport interface EvalConfig<TInput = unknown, TOutput = unknown> {\n /**\n * Human-readable name for this evaluation.\n */\n name?: string\n\n /**\n * Description of what the agent does.\n * Used by Judge for evaluation context.\n */\n agentDescription?: string\n\n /**\n * The agent to evaluate.\n */\n agent: EvalAgent<TInput, TOutput>\n\n /**\n * LLM configuration (shared by Judge and Improver unless overridden).\n */\n llm: LLMConfig\n\n /**\n * Judge configuration for evaluating agent outputs.\n */\n judge: CLIJudgeConfig\n\n /**\n * Improver configuration for prompt improvement suggestions.\n * Optional - if not specified, no improvements are generated.\n */\n improver?: CLIImproverConfig\n\n /**\n * Test cases to run (inline TypeScript definition).\n * Can mix single-turn and multi-turn test cases.\n *\n * Either `testCases` or `include` must be provided.\n * - Use `testCases` for inline TypeScript test case definitions\n * - Use `include` for YAML-based test case files\n */\n testCases?: CLITestCase<TInput, TOutput>[]\n\n /**\n * Output configuration for reports.\n */\n output?: OutputConfig\n\n /**\n * Run configuration for test execution.\n */\n run?: RunConfig\n\n /**\n * Pricing configuration for cost calculation.\n * If provided, cost breakdown will be included in test metrics.\n *\n * @example\n * ```typescript\n * pricing: {\n * openai: { 'gpt-4o': { inputPricePerMillion: 2.5, outputPricePerMillion: 10 } },\n * fallback: { inputPricePerMillion: 1.0, outputPricePerMillion: 3.0 },\n * }\n * ```\n */\n pricing?: EvalPricingConfig\n\n /**\n * Glob patterns to discover YAML eval files.\n * Required when using YAML-based test cases instead of inline testCases.\n *\n * @example\n * ```typescript\n * include: ['evals/booking/*.eval.yaml']\n * ```\n */\n include?: string[]\n\n /**\n * Agent registry for YAML file references.\n * YAML files reference agents by name (e.g., `agent: booking-agent`).\n *\n * @example\n * ```typescript\n * agents: {\n * 'booking-agent': bookingAgent,\n * 'qa-agent': qaAgent,\n * }\n * ```\n */\n agents?: Record<string, EvalAgent<unknown, unknown>>\n}\n\n/** Identity function for type inference and IDE autocompletion. */\nexport function defineConfig<TInput = unknown, TOutput = unknown>(\n config: EvalConfig<TInput, TOutput>\n): EvalConfig<TInput, TOutput> {\n return config\n}\n\nexport function isMultiTurnConfig<TInput, TOutput>(\n testCase: CLITestCase<TInput, TOutput>\n): testCase is CLIMultiTurnTestCase<TInput, TOutput> {\n return 'multiTurn' in testCase && testCase.multiTurn !== undefined\n}\n","import { existsSync } from 'node:fs'\nimport { resolve, extname } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { bundleRequire } from 'bundle-require'\nimport fg from 'fast-glob'\nimport { validateConfig, type ValidatedEvalConfig } from './schema.js'\nimport type { EvalConfig } from './types.js'\n\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly code: ConfigErrorCode,\n public readonly context?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'ConfigError'\n }\n}\n\nexport type ConfigErrorCode =\n | 'CONFIG_NOT_FOUND'\n | 'CONFIG_LOAD_ERROR'\n | 'CONFIG_NO_DEFAULT_EXPORT'\n | 'CONFIG_VALIDATION_ERROR'\n | 'CONFIG_NO_INCLUDE_PATTERN'\n\nexport const DEFAULT_CONFIG_FILE = 'agent-eval.config.ts'\n\nexport const SUPPORTED_EXTENSIONS = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs']\n\nexport function resolveConfigPath(\n configPath: string = DEFAULT_CONFIG_FILE,\n cwd: string = process.cwd()\n): string {\n return resolve(cwd, configPath)\n}\n\nexport async function loadConfig(configPath: string): Promise<EvalConfig> {\n const absolutePath = resolve(process.cwd(), configPath)\n\n if (!existsSync(absolutePath)) {\n throw new ConfigError(\n `Config file not found: ${configPath}\\n\\n` +\n `Create an ${DEFAULT_CONFIG_FILE} file or specify a path:\\n` +\n ` npx agent-eval run ./path/to/config.ts`,\n 'CONFIG_NOT_FOUND',\n { path: absolutePath }\n )\n }\n\n const ext = extname(absolutePath).toLowerCase()\n if (!SUPPORTED_EXTENSIONS.includes(ext)) {\n throw new ConfigError(\n `Unsupported config file extension: ${ext}\\n` +\n `Supported extensions: ${SUPPORTED_EXTENSIONS.join(', ')}`,\n 'CONFIG_LOAD_ERROR',\n { path: absolutePath, extension: ext }\n )\n }\n\n let mod: { default?: EvalConfig } | EvalConfig\n\n try {\n if (ext === '.ts' || ext === '.mts' || ext === '.cts') {\n const result = await bundleRequire({\n filepath: absolutePath,\n format: 'esm',\n esbuildOptions: { sourcemap: 'inline' },\n })\n mod = result.mod\n } else {\n const fileUrl = pathToFileURL(absolutePath).href\n mod = await import(fileUrl)\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ConfigError(\n `Failed to load config file: ${configPath}\\n\\n` +\n `Error: ${message}\\n\\n` +\n `Make sure the file is valid TypeScript/JavaScript and has no syntax errors.`,\n 'CONFIG_LOAD_ERROR',\n { path: absolutePath, originalError: message }\n )\n }\n\n const config = 'default' in mod ? mod.default : mod\n\n if (!config || typeof config !== 'object') {\n throw new ConfigError(\n `Config file must export a default configuration object.\\n\\n` +\n `Example:\\n` +\n ` import { defineConfig } from '@agtlantis/eval'\\n` +\n ` export default defineConfig({ ... })`,\n 'CONFIG_NO_DEFAULT_EXPORT',\n { path: absolutePath }\n )\n }\n\n try {\n validateConfig(config)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ConfigError(\n message,\n 'CONFIG_VALIDATION_ERROR',\n { path: absolutePath }\n )\n }\n\n return config as EvalConfig\n}\n\nexport async function loadConfigWithDefaults(\n configPath?: string,\n cwd?: string\n): Promise<EvalConfig> {\n const resolvedPath = resolveConfigPath(configPath, cwd)\n return loadConfig(resolvedPath)\n}\n\nexport interface DiscoverOptions {\n /** Override config include patterns (CLI --include) */\n include?: string[]\n /** Base directory for glob patterns (defaults to process.cwd()) */\n cwd?: string\n /** Ignore patterns (default excludes node_modules) */\n ignore?: string[]\n}\n\n/** Discover YAML eval files matching glob patterns. CLI patterns override config. */\nexport async function discoverEvalFiles(\n config: Pick<EvalConfig, 'include'>,\n options: DiscoverOptions = {}\n): Promise<string[]> {\n const patterns = options.include ?? config.include\n\n if (!patterns || patterns.length === 0) {\n throw new ConfigError(\n 'No include patterns specified.\\n\\n' +\n 'Add an include field to your config:\\n' +\n \" include: ['evals/**/*.eval.yaml']\\n\\n\" +\n 'Or use the --include CLI option:\\n' +\n ' npx agent-eval --include \"evals/**/*.eval.yaml\"',\n 'CONFIG_NO_INCLUDE_PATTERN'\n )\n }\n\n const cwd = options.cwd ?? process.cwd()\n const ignore = options.ignore ?? ['**/node_modules/**']\n\n const files = await fg(patterns, {\n absolute: true,\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n followSymbolicLinks: false,\n unique: true,\n suppressErrors: false,\n })\n\n return files.sort()\n}\n","import { z } from 'zod';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai', 'gemini'], {\n errorMap: () => ({\n message: \"provider must be 'openai' or 'gemini'\",\n }),\n }),\n apiKey: z.string().optional(),\n defaultModel: z.string().optional(),\n reasoningEffort: z.enum(['minimal', 'low', 'medium', 'high']).optional(),\n defaultResponseFormat: z\n .object({\n type: z.enum(['json_object', 'text']),\n })\n .optional(),\n});\n\nexport const criterionSchema = z.object({\n id: z.string().min(1, 'Criterion id is required'),\n name: z.string().min(1, 'Criterion name is required'),\n description: z.string().min(1, 'Criterion description is required'),\n weight: z.number().positive().optional(),\n validator: z.function().optional(),\n});\n\nexport const judgeConfigSchema = z.object({\n llm: llmConfigSchema.optional(),\n criteria: z.array(criterionSchema).min(1, 'At least one criterion is required'),\n passThreshold: z.number().min(0).max(100).optional(),\n prompt: z.any().optional(),\n});\n\nexport const improverConfigSchema = z\n .object({\n llm: llmConfigSchema.optional(),\n prompt: z.any().optional(),\n })\n .optional();\n\nexport const outputConfigSchema = z\n .object({\n dir: z.string().optional(),\n filename: z.string().optional(),\n verbose: z.boolean().optional(),\n })\n .optional();\n\nexport const runConfigSchema = z\n .object({\n concurrency: z.number().int().positive().optional(),\n iterations: z.number().int().positive().optional(),\n stopOnFirstFailure: z.boolean().optional(),\n })\n .optional();\n\nconst maxTurnsConditionSchema = z.object({\n type: z.literal('maxTurns'),\n count: z.number().int().positive(),\n});\n\nconst fieldSetConditionSchema = z.object({\n type: z.literal('fieldSet'),\n fieldPath: z.string().min(1),\n});\n\nconst fieldValueConditionSchema = z.object({\n type: z.literal('fieldValue'),\n fieldPath: z.string().min(1),\n expectedValue: z.unknown(),\n});\n\nconst customConditionSchema = z.object({\n type: z.literal('custom'),\n check: z.function(),\n description: z.string().optional(),\n});\n\nexport const terminationConditionSchema = z.union([\n maxTurnsConditionSchema,\n fieldSetConditionSchema,\n fieldValueConditionSchema,\n customConditionSchema,\n]);\n\nexport const followUpInputSchema = z.object({\n input: z.unknown(),\n description: z.string().optional(),\n turns: z.number().optional(),\n});\n\nexport const multiTurnConfigSchema = z.object({\n followUpInputs: z.array(followUpInputSchema).optional(),\n terminateWhen: z\n .array(terminationConditionSchema)\n .min(1, 'At least one termination condition is required'),\n maxTurns: z.number().int().positive().optional(),\n onConditionMet: z.enum(['pass', 'fail']).optional(),\n onMaxTurnsReached: z.enum(['pass', 'fail']).optional(),\n});\n\nexport const testCaseSchema = z.object({\n id: z.string().optional(),\n input: z.unknown(),\n tags: z.array(z.string()).optional(),\n description: z.string().optional(),\n expectedOutput: z.unknown().optional(),\n files: z.array(z.any()).optional(),\n multiTurn: multiTurnConfigSchema.optional(),\n});\n\nexport const agentSchema = z.object({\n config: z.object({\n name: z.string(),\n description: z.string().optional(),\n }),\n prompt: z.object({\n id: z.string(),\n version: z.string(),\n system: z.string(),\n renderUserPrompt: z.function(),\n }),\n execute: z.function(),\n});\n\nexport const evalConfigSchema = z\n .object({\n name: z.string().optional(),\n agentDescription: z.string().optional(),\n agent: agentSchema,\n llm: llmConfigSchema,\n judge: judgeConfigSchema,\n improver: improverConfigSchema,\n testCases: z.array(testCaseSchema).optional(),\n output: outputConfigSchema,\n run: runConfigSchema,\n include: z\n .array(z.string().min(1, 'Include pattern cannot be empty'))\n .min(1, 'Include array must have at least one pattern')\n .optional(),\n agents: z.record(z.string(), agentSchema).optional(),\n })\n .refine(\n (data) => {\n const hasTestCases = (data.testCases?.length ?? 0) > 0;\n const hasInclude = (data.include?.length ?? 0) > 0;\n return hasTestCases || hasInclude;\n },\n {\n message:\n 'Either testCases or include must be provided. ' +\n 'Use testCases for inline TypeScript tests, or include for YAML file discovery.',\n path: ['testCases'],\n }\n );\n\nexport type ValidatedLLMConfig = z.infer<typeof llmConfigSchema>;\nexport type ValidatedJudgeConfig = z.infer<typeof judgeConfigSchema>;\nexport type ValidatedImproverConfig = z.infer<typeof improverConfigSchema>;\nexport type ValidatedOutputConfig = z.infer<typeof outputConfigSchema>;\nexport type ValidatedRunConfig = z.infer<typeof runConfigSchema>;\nexport type ValidatedTestCase = z.infer<typeof testCaseSchema>;\nexport type ValidatedEvalConfig = z.infer<typeof evalConfigSchema>;\n\nexport function validateConfig(config: unknown): ValidatedEvalConfig {\n const result = evalConfigSchema.safeParse(config);\n\n if (!result.success) {\n const errors = result.error.issues\n .map((issue) => {\n const path = issue.path.join('.');\n return path ? ` - ${path}: ${issue.message}` : ` - ${issue.message}`;\n })\n .join('\\n');\n\n throw new EvalError(`Invalid configuration:\\n${errors}`, {\n code: EvalErrorCode.INVALID_CONFIG,\n });\n }\n\n return result.data;\n}\n\nexport function validateConfigPartial(config: unknown): {\n success: boolean;\n errors?: string[];\n} {\n const result = evalConfigSchema.safeParse(config);\n\n if (result.success) {\n return { success: true };\n }\n\n return {\n success: false,\n errors: result.error.issues.map((issue) => {\n const path = issue.path.join('.');\n return path ? `${path}: ${issue.message}` : issue.message;\n }),\n };\n}\n","import type { AgentPrompt, EvalAgent, TestCase } from '@/core/types';\nimport type { Improver, Suggestion } from '@/improver/types';\nimport type { Judge } from '@/judge/types';\nimport type { EvalPricingConfig } from '@/reporter/cost-helpers';\nimport type { EvalReport } from '@/reporter/types';\n\nimport type { ImprovementSession } from './history';\n\n/** Terminate when average score reaches threshold */\nexport interface TargetScoreCondition {\n type: 'targetScore';\n /** Score threshold (0-100) */\n threshold: number;\n}\n\n/** Terminate after N rounds */\nexport interface MaxRoundsCondition {\n type: 'maxRounds';\n /** Maximum number of improvement rounds */\n count: number;\n}\n\n/** Terminate when score doesn't improve for N consecutive rounds */\nexport interface NoImprovementCondition {\n type: 'noImprovement';\n /** Number of consecutive rounds without improvement */\n consecutiveRounds: number;\n /** Minimum score delta to count as improvement (default: 0) */\n minDelta?: number;\n}\n\n/** Terminate when total cost exceeds budget */\nexport interface MaxCostCondition {\n type: 'maxCost';\n /** Maximum cost in USD */\n maxUSD: number;\n}\n\n/** Custom condition with user-defined check function */\nexport interface CustomCycleCondition {\n type: 'custom';\n /** Function to check if termination condition is met */\n check: (ctx: CycleContext) => boolean | Promise<boolean>;\n /** Human-readable description (for debugging/logging) */\n description?: string;\n}\n\n/** Discriminated union of termination conditions. Uses OR semantics - first match triggers. */\nexport type CycleTerminationCondition =\n | TargetScoreCondition\n | MaxRoundsCondition\n | NoImprovementCondition\n | MaxCostCondition\n | CustomCycleCondition;\n\n/** Context available to termination condition checks */\nexport interface CycleContext {\n /** Current round number (1-indexed) */\n currentRound: number;\n /** Average score from the latest round */\n latestScore: number;\n /** Score history from all previous rounds */\n previousScores: number[];\n /** Total accumulated cost in USD */\n totalCost: number;\n /** Full history of completed rounds */\n history: RoundResult[];\n}\n\n/** Result when cycle should continue (no termination) */\nexport interface CycleContinueResult {\n terminated: false;\n reason: string;\n /** Not present when not terminated (for type safety with discriminated union) */\n matchedCondition?: never;\n}\n\n/** Result when cycle should terminate */\nexport interface CycleTerminatedResult {\n terminated: true;\n matchedCondition: CycleTerminationCondition;\n reason: string;\n}\n\nexport type CycleTerminationResult = CycleContinueResult | CycleTerminatedResult;\n\n/**\n * Data yielded after each improvement round for Human-in-the-Loop (HITL) control.\n * The AsyncGenerator yields this after each round, allowing inspection and decision.\n */\nexport interface RoundYield {\n /** Result of the completed round */\n roundResult: RoundResult;\n /** Current cycle context */\n context: CycleContext;\n /** Suggestions awaiting approval */\n pendingSuggestions: Suggestion[];\n /** Termination check result (use isCycleTerminated() to check if terminated) */\n terminationCheck: CycleTerminationResult;\n}\n\n/** Decision from the caller after reviewing a round */\nexport interface RoundDecision {\n /** Action to take */\n action: 'continue' | 'stop' | 'rollback';\n /** Target round for rollback (required if action is 'rollback') */\n rollbackToRound?: number;\n /** Suggestions approved by user (optional override) */\n approvedSuggestions?: Suggestion[];\n}\n\n/** Cost breakdown for a single round */\nexport interface RoundCost {\n /** Agent LLM cost in USD */\n agent: number;\n /** Judge LLM cost in USD */\n judge: number;\n /** Improver LLM cost in USD */\n improver: number;\n /** Total cost in USD */\n total: number;\n}\n\n/** Result of a single improvement round */\nexport interface RoundResult {\n /** Round number (1-indexed) */\n round: number;\n /** When this round completed */\n completedAt: Date;\n /** Full evaluation report */\n report: EvalReport<unknown, unknown>;\n /** All suggestions generated by improver */\n suggestionsGenerated: Suggestion[];\n /** Suggestions that were approved/applied */\n suggestionsApproved: Suggestion[];\n /** Prompt snapshot at start of this round (for rollback) */\n promptSnapshot: SerializedPrompt;\n /** Prompt version after applying suggestions */\n promptVersionAfter: string;\n /** Cost breakdown for this round */\n cost: RoundCost;\n /** Score change from previous round (null for first round) */\n scoreDelta: number | null;\n}\n\n/**\n * Serialized prompt for JSON storage.\n * Note: renderUserPrompt cannot be serialized; use compileTemplate(userTemplate) to reconstruct.\n */\nexport interface SerializedPrompt {\n /** Prompt unique ID */\n id: string;\n /** Version string (e.g., \"1.0.0\") */\n version: string;\n /** System prompt */\n system: string;\n /** User prompt template (Mustache format) */\n userTemplate: string;\n /** Additional custom fields from AgentPrompt */\n customFields?: Record<string, unknown>;\n}\n\n/** Serialized round result for JSON storage */\nexport interface SerializedRoundResult {\n /** Round number (1-indexed) */\n round: number;\n /** Completion timestamp (ISO 8601) */\n completedAt: string;\n /** Average score from this round */\n avgScore: number;\n /** Number of passed tests */\n passed: number;\n /** Number of failed tests */\n failed: number;\n /** Total number of tests */\n totalTests: number;\n /** All suggestions generated */\n suggestionsGenerated: Suggestion[];\n /** Suggestions that were approved/applied */\n suggestionsApproved: Suggestion[];\n /** Prompt snapshot at start of this round */\n promptSnapshot: SerializedPrompt;\n /** Prompt version after applying suggestions */\n promptVersionAfter: string;\n /** Cost breakdown */\n cost: RoundCost;\n /** Score change from previous round */\n scoreDelta: number | null;\n}\n\n/**\n * Improvement cycle history (JSON file schema v1.1.0).\n * Includes promptSnapshot per round for rollback support.\n */\nexport interface ImprovementHistory {\n /** Schema version for migration compatibility */\n schemaVersion: '1.1.0';\n /** Unique session identifier */\n sessionId: string;\n /** Session start timestamp (ISO 8601) */\n startedAt: string;\n /** Session completion timestamp (ISO 8601, if completed) */\n completedAt?: string;\n /** Initial prompt before any improvements */\n initialPrompt: SerializedPrompt;\n /** Current/latest prompt */\n currentPrompt: SerializedPrompt;\n /** All completed rounds */\n rounds: SerializedRoundResult[];\n /** Reason for termination (if completed) */\n terminationReason?: string;\n /** Total accumulated cost in USD */\n totalCost: number;\n}\n\n/** History persistence configuration */\nexport interface HistoryConfig {\n /** Path to save history JSON */\n path: string;\n /** Auto-save after each round (default: true) */\n autoSave?: boolean;\n}\n\n/** Configuration for running an improvement cycle */\nexport interface ImprovementCycleConfig<TInput, TOutput> {\n /** Factory function to create agent with given prompt */\n createAgent: (prompt: AgentPrompt<TInput>) => EvalAgent<TInput, TOutput>;\n /** Starting prompt for improvements */\n initialPrompt: AgentPrompt<TInput>;\n /** Test cases to evaluate against */\n testCases: TestCase<TInput>[];\n /** Judge for evaluation */\n judge: Judge;\n /** Improver for generating suggestions */\n improver: Improver;\n /** Termination conditions (OR semantics) */\n terminateWhen: CycleTerminationCondition[];\n /** Optional configuration */\n options?: ImprovementCycleOptions;\n}\n\n/** Optional configuration for improvement cycle */\nexport interface ImprovementCycleOptions {\n /** Options passed to eval suite run */\n runOptions?: { concurrency?: number; iterations?: number };\n /** How to bump version on each improvement */\n versionBump?: 'major' | 'minor' | 'patch';\n /** Pricing configuration for cost calculation */\n pricingConfig?: EvalPricingConfig;\n /** History persistence settings */\n history?: HistoryConfig;\n /** Description for agent (passed to judge) */\n agentDescription?: string;\n /** Existing session to resume (preserves session ID and accumulated state) */\n session?: ImprovementSession;\n}\n\n/** Final result of an improvement cycle */\nexport interface ImprovementCycleResult<TInput, TOutput> {\n /** Final improved prompt */\n finalPrompt: AgentPrompt<TInput>;\n /** All completed rounds */\n rounds: RoundResult[];\n /** Reason for termination */\n terminationReason: string;\n /** Total cost in USD */\n totalCost: number;\n /** Saved history (if persistence was enabled) */\n history?: ImprovementHistory;\n}\n\nexport function isTargetScoreCondition(\n condition: CycleTerminationCondition\n): condition is TargetScoreCondition {\n return condition.type === 'targetScore';\n}\n\nexport function isMaxRoundsCondition(\n condition: CycleTerminationCondition\n): condition is MaxRoundsCondition {\n return condition.type === 'maxRounds';\n}\n\nexport function isNoImprovementCondition(\n condition: CycleTerminationCondition\n): condition is NoImprovementCondition {\n return condition.type === 'noImprovement';\n}\n\nexport function isMaxCostCondition(\n condition: CycleTerminationCondition\n): condition is MaxCostCondition {\n return condition.type === 'maxCost';\n}\n\nexport function isCustomCycleCondition(\n condition: CycleTerminationCondition\n): condition is CustomCycleCondition {\n return condition.type === 'custom';\n}\n\nexport function isCycleTerminated(result: CycleTerminationResult): result is CycleTerminatedResult {\n return result.terminated === true;\n}\n","import type {\n CycleContext,\n CycleTerminationCondition,\n CycleTerminationResult,\n TargetScoreCondition,\n MaxRoundsCondition,\n NoImprovementCondition,\n MaxCostCondition,\n CustomCycleCondition,\n} from './types'\nimport {\n isTargetScoreCondition,\n isMaxRoundsCondition,\n isNoImprovementCondition,\n isMaxCostCondition,\n isCustomCycleCondition,\n} from './types'\nimport { EvalError, EvalErrorCode } from '@/core/errors'\nimport {\n createAndCheck,\n createOrCheck,\n createNotCheck,\n formatCompositeDescription,\n} from '../utils/condition-composites'\n\n/** Terminates when the average score reaches or exceeds threshold. */\nexport function targetScore(threshold: number): TargetScoreCondition {\n if (!Number.isFinite(threshold)) {\n throw new EvalError('threshold must be a finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { threshold },\n })\n }\n if (threshold < 0 || threshold > 100) {\n throw new EvalError('threshold must be between 0 and 100', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { threshold },\n })\n }\n return { type: 'targetScore', threshold }\n}\n\n/** Terminates after completing the specified number of rounds. */\nexport function maxRounds(count: number): MaxRoundsCondition {\n if (!Number.isInteger(count) || count < 1) {\n throw new EvalError('count must be a positive integer', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { count },\n })\n }\n return { type: 'maxRounds', count }\n}\n\n/** Terminates when score hasn't improved for N consecutive rounds. */\nexport function noImprovement(\n consecutiveRounds: number,\n minDelta?: number\n): NoImprovementCondition {\n if (!Number.isInteger(consecutiveRounds) || consecutiveRounds < 1) {\n throw new EvalError('consecutiveRounds must be a positive integer', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { consecutiveRounds },\n })\n }\n if (minDelta !== undefined && (!Number.isFinite(minDelta) || minDelta < 0)) {\n throw new EvalError('minDelta must be a non-negative finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { minDelta },\n })\n }\n return {\n type: 'noImprovement',\n consecutiveRounds,\n ...(minDelta !== undefined && { minDelta }),\n }\n}\n\n/** Terminates when total accumulated cost reaches or exceeds the budget. */\nexport function maxCost(maxUSD: number): MaxCostCondition {\n if (!Number.isFinite(maxUSD) || maxUSD <= 0) {\n throw new EvalError('maxUSD must be a positive finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { maxUSD },\n })\n }\n return { type: 'maxCost', maxUSD }\n}\n\n/** Custom termination condition with arbitrary logic. Supports async checks. */\nexport function customCondition(\n check: (ctx: CycleContext) => boolean | Promise<boolean>,\n description?: string\n): CustomCycleCondition {\n return {\n type: 'custom',\n check,\n ...(description !== undefined && { description }),\n }\n}\n\n/** All conditions must be met for termination. Short-circuits on first false. */\nexport function and(\n ...conditions: CycleTerminationCondition[]\n): CustomCycleCondition {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('and', []),\n }\n }\n\n return {\n type: 'custom',\n check: createAndCheck(conditions, checkCycleCondition),\n description: formatCompositeDescription('and', conditions),\n }\n}\n\n/** Any condition being met causes termination. Short-circuits on first true. */\nexport function or(\n ...conditions: CycleTerminationCondition[]\n): CustomCycleCondition {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('or', []),\n }\n }\n\n return {\n type: 'custom',\n check: createOrCheck(conditions, checkCycleCondition),\n description: formatCompositeDescription('or', conditions),\n }\n}\n\n/** Invert a condition's result. Terminates when inner condition does NOT terminate. */\nexport function not(\n condition: CycleTerminationCondition\n): CustomCycleCondition {\n return {\n type: 'custom',\n check: createNotCheck(condition, checkCycleCondition),\n description: `not(${condition.type})`,\n }\n}\n\nfunction checkTargetScore(\n condition: TargetScoreCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.latestScore >= condition.threshold) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Target score ${condition.threshold} reached (current: ${ctx.latestScore})`,\n }\n }\n return {\n terminated: false,\n reason: `Score ${ctx.latestScore} below target ${condition.threshold}`,\n }\n}\n\nfunction checkMaxRounds(\n condition: MaxRoundsCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.currentRound >= condition.count) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Maximum rounds reached (${condition.count})`,\n }\n }\n return {\n terminated: false,\n reason: `Round ${ctx.currentRound} of ${condition.count}`,\n }\n}\n\n/**\n * Counts consecutive rounds without improvement from most recent to oldest.\n * Breaks on null delta (first round) or on improvement (scoreDelta > minDelta).\n */\nfunction checkNoImprovement(\n condition: NoImprovementCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n const { consecutiveRounds, minDelta = 0 } = condition\n const { history } = ctx\n\n let noImprovementCount = 0\n\n for (let i = history.length - 1; i >= 0; i--) {\n const round = history[i]\n\n if (round.scoreDelta === null) break\n if (round.scoreDelta <= minDelta) {\n noImprovementCount++\n } else {\n break\n }\n }\n\n if (noImprovementCount >= consecutiveRounds) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `No improvement for ${noImprovementCount} consecutive round${noImprovementCount === 1 ? '' : 's'}`,\n }\n }\n\n const roundWord = noImprovementCount === 1 ? 'round' : 'rounds'\n return {\n terminated: false,\n reason: `${noImprovementCount} ${roundWord} without improvement (need ${consecutiveRounds})`,\n }\n}\n\nfunction checkMaxCost(\n condition: MaxCostCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.totalCost >= condition.maxUSD) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Cost limit exceeded ($${ctx.totalCost.toFixed(2)} >= $${condition.maxUSD.toFixed(2)})`,\n }\n }\n return {\n terminated: false,\n reason: `Cost $${ctx.totalCost.toFixed(2)} under limit $${condition.maxUSD.toFixed(2)}`,\n }\n}\n\nasync function checkCustomCondition(\n condition: CustomCycleCondition,\n ctx: CycleContext\n): Promise<CycleTerminationResult> {\n const description = condition.description ?? 'Custom condition'\n\n try {\n const shouldTerminate = await condition.check(ctx)\n\n if (shouldTerminate) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `${description} met`,\n }\n }\n return {\n terminated: false,\n reason: `${description} not met`,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n terminated: false,\n reason: `${description} check failed: ${message}`,\n }\n }\n}\n\n/** Dispatches to the appropriate check function based on condition type. */\nexport async function checkCycleCondition(\n condition: CycleTerminationCondition,\n context: CycleContext\n): Promise<CycleTerminationResult> {\n if (isTargetScoreCondition(condition)) {\n return checkTargetScore(condition, context)\n }\n if (isMaxRoundsCondition(condition)) {\n return checkMaxRounds(condition, context)\n }\n if (isNoImprovementCondition(condition)) {\n return checkNoImprovement(condition, context)\n }\n if (isMaxCostCondition(condition)) {\n return checkMaxCost(condition, context)\n }\n if (isCustomCycleCondition(condition)) {\n return checkCustomCondition(condition, context)\n }\n\n // Exhaustive check - TypeScript will error if we miss a case\n const _exhaustive: never = condition\n throw new EvalError(`Unknown condition type: ${JSON.stringify(_exhaustive)}`, {\n code: EvalErrorCode.UNKNOWN_ERROR,\n context: { condition: _exhaustive },\n })\n}\n\n/** Check all conditions with OR semantics - first match wins. */\nexport async function checkCycleTermination(\n conditions: CycleTerminationCondition[],\n context: CycleContext\n): Promise<CycleTerminationResult> {\n if (conditions.length === 0) {\n return {\n terminated: false,\n reason: 'No termination conditions specified',\n }\n }\n\n for (const condition of conditions) {\n const result = await checkCycleCondition(condition, context)\n if (result.terminated) {\n return result // First match wins (OR semantics)\n }\n }\n\n return {\n terminated: false,\n reason: 'No termination conditions met',\n }\n}\n","import type { LanguageModelUsage } from 'ai'\nimport { calculateCostFromUsage } from '@agtlantis/core'\nimport { createEvalSuite } from '@/core/suite'\nimport { applyPromptSuggestions } from '@/improver/utils'\nimport { calculateReportCosts, type EvalPricingConfig } from '@/reporter/cost-helpers'\nimport type { EvalAgent, AgentPrompt, EvalTokenUsage } from '@/core/types'\nimport type { EvalReport } from '@/reporter/types'\nimport type { Suggestion, ImproveResult } from '@/improver/types'\n\nimport { createSession, serializePrompt, deserializePrompt } from './history'\nimport type { ImprovementSession, SessionConfig } from './history'\nimport { checkCycleTermination } from './conditions'\nimport type {\n ImprovementCycleConfig,\n ImprovementCycleResult,\n RoundYield,\n RoundDecision,\n RoundResult,\n RoundCost,\n CycleContext,\n SerializedPrompt,\n} from './types'\n\ninterface CycleState<TInput, TOutput> {\n currentPrompt: AgentPrompt<TInput>\n currentRound: number\n previousScores: number[]\n totalCost: number\n completedRounds: RoundResult[]\n}\n\n/** Initialize cycle state, resuming from existing session if provided. */\nfunction initializeCycleState<TInput, TOutput>(\n initialPrompt: AgentPrompt<TInput>,\n existingSession: ImprovementSession | undefined\n): CycleState<TInput, TOutput> {\n const resumeFromRound = existingSession ? existingSession.history.rounds.length : 0\n return {\n currentPrompt: initialPrompt,\n currentRound: resumeFromRound,\n previousScores: existingSession\n ? existingSession.history.rounds.map((r) => r.avgScore)\n : [],\n totalCost: existingSession ? existingSession.history.totalCost : 0,\n completedRounds: [],\n }\n}\n\n/** Returns null for the first round (no previous score to compare). */\nfunction calculateScoreDelta(currentScore: number, previousScores: number[]): number | null {\n if (previousScores.length === 0) {\n return null\n }\n const previousScore = previousScores[previousScores.length - 1]\n return currentScore - previousScore\n}\n\nfunction buildCycleContext<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n currentScore: number\n): CycleContext {\n return {\n currentRound: state.currentRound,\n latestScore: currentScore,\n previousScores: [...state.previousScores],\n totalCost: state.totalCost,\n history: state.completedRounds,\n }\n}\n\nfunction createRoundResult<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n report: EvalReport<TInput, TOutput>,\n improveResult: ImproveResult,\n cost: RoundCost,\n scoreDelta: number | null,\n promptSnapshot: SerializedPrompt\n): RoundResult {\n return {\n round: state.currentRound,\n report: report as EvalReport<unknown, unknown>,\n completedAt: new Date(),\n suggestionsGenerated: improveResult.suggestions,\n suggestionsApproved: [], // Will be updated after decision\n promptSnapshot,\n promptVersionAfter: state.currentPrompt.version,\n cost,\n scoreDelta,\n }\n}\n\nasync function handleStopDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n session: ImprovementSession,\n roundResult: RoundResult,\n promptSnapshot: SerializedPrompt,\n terminatedByCondition: boolean,\n conditionReason: string | undefined\n): Promise<ImprovementCycleResult<TInput, TOutput>> {\n const reason = terminatedByCondition ? conditionReason! : 'User requested stop'\n\n session.addRound(roundResult, promptSnapshot)\n session.complete(reason)\n await session.flush()\n state.completedRounds.push(roundResult)\n\n return {\n rounds: state.completedRounds,\n finalPrompt: deserializePrompt(session.history.currentPrompt),\n terminationReason: reason,\n totalCost: state.totalCost,\n history: session.history,\n }\n}\n\n/** Throws if target round is invalid. */\nfunction handleRollbackDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n rollbackToRound: number\n): void {\n const targetRoundIndex = rollbackToRound - 1\n if (targetRoundIndex < 0 || targetRoundIndex >= state.completedRounds.length) {\n throw new Error(`Cannot rollback to round ${rollbackToRound}: round not found`)\n }\n\n const targetRound = state.completedRounds[targetRoundIndex]\n state.currentPrompt = deserializePrompt(targetRound.promptSnapshot)\n state.previousScores = state.previousScores.slice(0, rollbackToRound - 1)\n}\n\nfunction handleContinueDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n session: ImprovementSession,\n roundResult: RoundResult,\n approvedSuggestions: Suggestion[],\n versionBump: 'major' | 'minor' | 'patch'\n): RoundResult {\n const updatedRoundResult: RoundResult = {\n ...roundResult,\n suggestionsApproved: approvedSuggestions,\n }\n\n if (approvedSuggestions.length > 0) {\n const applyResult = applyPromptSuggestions(state.currentPrompt, approvedSuggestions, {\n bumpVersion: versionBump,\n })\n state.currentPrompt = applyResult.prompt\n updatedRoundResult.promptVersionAfter = state.currentPrompt.version\n }\n\n const updatedPromptSnapshot = serializePrompt(state.currentPrompt)\n session.addRound(updatedRoundResult, updatedPromptSnapshot)\n state.completedRounds.push(updatedRoundResult)\n\n return updatedRoundResult\n}\n\ninterface RoundExecutionResult<TInput, TOutput> {\n report: EvalReport<TInput, TOutput>\n improveResult: ImproveResult\n cost: RoundCost\n}\n\nasync function executeRound<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>,\n state: CycleState<TInput, TOutput>,\n pricingConfig: EvalPricingConfig | undefined\n): Promise<RoundExecutionResult<TInput, TOutput>> {\n const { createAgent, judge, improver, testCases, options = {} } = config\n const agent = createAgent(state.currentPrompt)\n\n // Improver is called separately (not via suite) to capture full ImproveResult\n // with metadata, enabling accurate cost calculation via tokenUsage\n const suite = createEvalSuite({\n agent,\n judge,\n agentDescription: options.agentDescription,\n })\n const report = await suite.run(testCases, options.runOptions)\n\n const improveResult: ImproveResult = improver\n ? await improver.improve(state.currentPrompt, report.results)\n : { suggestions: [] }\n\n const cost = calculateRoundCost(report, improveResult, pricingConfig)\n\n return { report, improveResult, cost }\n}\n\nfunction detectProviderForImprover(model: string | undefined): string {\n if (!model) return 'anthropic' // improver typically uses Claude\n\n if (model.startsWith('claude-')) return 'anthropic'\n if (model.startsWith('gpt-') || model.startsWith('o1') || model.startsWith('o3')) return 'openai'\n if (model.startsWith('gemini-')) return 'google'\n\n return 'anthropic'\n}\n\nfunction toLanguageModelUsage(usage: EvalTokenUsage): LanguageModelUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n } as LanguageModelUsage\n}\n\nfunction calculateImproverCost(\n improveResult: ImproveResult,\n pricingConfig?: EvalPricingConfig\n): number {\n const usage = improveResult.metadata?.tokenUsage as EvalTokenUsage | undefined\n if (!usage) return 0\n\n const model = improveResult.metadata?.model ?? 'unknown'\n const provider = detectProviderForImprover(model)\n\n // Get the pricing for this specific provider\n const providerPricing = pricingConfig?.providerPricing?.[provider]\n\n const result = calculateCostFromUsage(\n toLanguageModelUsage(usage),\n model,\n provider,\n providerPricing\n )\n\n return result.total\n}\n\nfunction calculateRoundCost(\n report: EvalReport<unknown, unknown>,\n improveResult: ImproveResult,\n pricingConfig?: EvalPricingConfig\n): RoundCost {\n const reportCosts = pricingConfig\n ? calculateReportCosts(report, pricingConfig)\n : { total: 0, byComponent: { agent: 0, judge: 0 } }\n\n const improverCost = calculateImproverCost(improveResult, pricingConfig)\n\n return {\n agent: reportCosts.byComponent.agent ?? 0,\n judge: reportCosts.byComponent.judge ?? 0,\n improver: improverCost,\n total: reportCosts.total + improverCost,\n }\n}\n\n/**\n * Run an improvement cycle as an AsyncGenerator for Human-in-the-Loop control.\n * Yields after each round for decision-making (continue, stop, or rollback).\n */\nexport async function* runImprovementCycle<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>\n): AsyncGenerator<RoundYield, ImprovementCycleResult<TInput, TOutput>, RoundDecision | undefined> {\n const { initialPrompt, terminateWhen = [], options = {} } = config\n const { pricingConfig, versionBump = 'patch', history: historyConfig, session: existingSession } = options\n\n const session: ImprovementSession = existingSession ?? createSession(\n initialPrompt,\n historyConfig ? { path: historyConfig.path, autoSave: historyConfig.autoSave } : undefined\n )\n const state = initializeCycleState(initialPrompt, existingSession)\n\n try {\n while (true) {\n state.currentRound++\n\n const { report, improveResult, cost } = await executeRound(config, state, pricingConfig)\n state.totalCost += cost.total\n\n const currentScore = report.summary.avgScore\n const scoreDelta = calculateScoreDelta(currentScore, state.previousScores)\n const promptSnapshot = serializePrompt(state.currentPrompt)\n const roundResult = createRoundResult(state, report, improveResult, cost, scoreDelta, promptSnapshot)\n const context = buildCycleContext(state, currentScore)\n\n state.previousScores.push(currentScore)\n\n const terminationCheck = await checkCycleTermination(terminateWhen, context)\n const pendingSuggestions: Suggestion[] = improveResult.suggestions.map((s) => ({\n ...s,\n approved: false,\n }))\n\n const roundYield: RoundYield = {\n roundResult,\n pendingSuggestions,\n terminationCheck,\n context,\n }\n\n const decision: RoundDecision | undefined = yield roundYield\n\n if (!decision || decision.action === 'stop') {\n return await handleStopDecision(\n state,\n session,\n roundResult,\n promptSnapshot,\n terminationCheck.terminated,\n terminationCheck.reason\n )\n }\n\n if (decision.action === 'rollback' && decision.rollbackToRound !== undefined) {\n handleRollbackDecision(state, decision.rollbackToRound)\n continue\n }\n\n handleContinueDecision(\n state,\n session,\n roundResult,\n decision.approvedSuggestions ?? [],\n versionBump\n )\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n session.complete(`Error: ${errorMessage}`)\n throw error\n }\n}\n\n/**\n * Run improvement cycle with automatic approval of all suggestions.\n * Continues until a termination condition is met.\n */\nexport async function runImprovementCycleAuto<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>\n): Promise<ImprovementCycleResult<TInput, TOutput>> {\n const cycle = runImprovementCycle(config)\n\n let iteratorResult = await cycle.next()\n\n while (!iteratorResult.done) {\n const roundYield = iteratorResult.value\n let decision: RoundDecision\n\n if (roundYield.terminationCheck.terminated) {\n decision = { action: 'stop' }\n } else {\n const approvedSuggestions = roundYield.pendingSuggestions.map((s) => ({\n ...s,\n approved: true,\n }))\n decision = { action: 'continue', approvedSuggestions }\n }\n\n iteratorResult = await cycle.next(decision)\n }\n\n return iteratorResult.value\n}\n","import crypto from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport { compileTemplate } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt } from '@/core/types';\n\nimport type {\n ImprovementHistory,\n RoundResult,\n SerializedPrompt,\n SerializedRoundResult,\n} from './types';\n\n/** Storage abstraction for testability - allows injecting mock storage */\nexport interface HistoryStorage {\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, content: string) => Promise<void>;\n exists: (path: string) => boolean;\n mkdir: (path: string, options?: { recursive?: boolean }) => Promise<string | undefined | void>;\n}\n\nexport const defaultHistoryStorage: HistoryStorage = {\n readFile: (path) => readFile(path, 'utf-8'),\n writeFile: (path, content) => writeFile(path, content, 'utf-8'),\n exists: existsSync,\n mkdir: (path, options) => mkdir(path, options),\n};\n\nexport interface ImprovementSession {\n readonly sessionId: string;\n readonly history: Readonly<ImprovementHistory>;\n readonly canSave: boolean;\n addRound(roundResult: RoundResult, updatedPrompt: SerializedPrompt): void;\n complete(terminationReason: string): void;\n save(): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface SessionConfig {\n path?: string;\n autoSave?: boolean;\n storage?: HistoryStorage;\n onAutoSaveError?: (error: Error) => void;\n}\n\nexport function hasUserTemplate(\n prompt: AgentPrompt<unknown>\n): prompt is AgentPrompt<unknown> & { userTemplate: string } {\n return typeof (prompt as { userTemplate?: unknown }).userTemplate === 'string';\n}\n\n/** @throws EvalError with PROMPT_INVALID_FORMAT if userTemplate is missing */\nexport function serializePrompt<TInput>(prompt: AgentPrompt<TInput>): SerializedPrompt {\n const p = prompt as AgentPrompt<unknown>;\n if (!hasUserTemplate(p)) {\n throw new EvalError('Cannot serialize prompt: userTemplate field is required', {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId: p.id },\n });\n }\n\n const { id, version, system, userTemplate, renderUserPrompt, ...rest } =\n p as AgentPrompt<unknown> & {\n userTemplate: string;\n };\n const customFields =\n Object.keys(rest).length > 0 ? (rest as Record<string, unknown>) : undefined;\n\n return {\n id,\n version,\n system,\n userTemplate,\n ...(customFields && { customFields }),\n };\n}\n\nfunction validateDeserializedPrompt(\n obj: Record<string, unknown>,\n promptId: string\n): asserts obj is Record<string, unknown> & {\n id: string;\n version: string;\n system: string;\n userTemplate: string;\n renderUserPrompt: (input: unknown) => string;\n} {\n const requiredStrings = ['id', 'version', 'system', 'userTemplate'] as const;\n for (const field of requiredStrings) {\n if (typeof obj[field] !== 'string') {\n throw new EvalError(`Invalid deserialized prompt: ${field} must be a string`, {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId, field, actual: typeof obj[field] },\n });\n }\n }\n\n if (typeof obj.renderUserPrompt !== 'function') {\n throw new EvalError('Invalid deserialized prompt: renderUserPrompt must be a function', {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId, actual: typeof obj.renderUserPrompt },\n });\n }\n}\n\n/** Reconstructs renderUserPrompt using compileTemplate. */\nexport function deserializePrompt<TInput>(serialized: SerializedPrompt): AgentPrompt<TInput> {\n const { id, version, system, userTemplate, customFields } = serialized;\n\n let renderUserPrompt: (input: TInput) => string;\n try {\n renderUserPrompt = compileTemplate<TInput>(userTemplate, id);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new EvalError(`Failed to compile userTemplate: ${message}`, {\n code: EvalErrorCode.TEMPLATE_COMPILE_ERROR,\n context: { promptId: id, userTemplate },\n });\n }\n\n // Spread customFields first, then core fields to prevent override attacks\n const result = {\n ...customFields,\n id,\n version,\n system,\n userTemplate,\n renderUserPrompt,\n };\n\n validateDeserializedPrompt(result, id);\n return result as AgentPrompt<TInput>;\n}\n\nfunction serializeRoundResult(result: RoundResult): SerializedRoundResult {\n const { summary } = result.report;\n\n return {\n round: result.round,\n completedAt: result.completedAt.toISOString(),\n avgScore: summary.avgScore,\n passed: summary.passed,\n failed: summary.failed,\n totalTests: summary.totalTests,\n suggestionsGenerated: result.suggestionsGenerated,\n suggestionsApproved: result.suggestionsApproved,\n promptSnapshot: result.promptSnapshot,\n promptVersionAfter: result.promptVersionAfter,\n cost: result.cost,\n scoreDelta: result.scoreDelta,\n };\n}\n\nfunction validateHistorySchema(data: unknown): asserts data is ImprovementHistory {\n if (typeof data !== 'object' || data === null) {\n throw new EvalError('Invalid history: not an object', {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n });\n }\n\n const h = data as Record<string, unknown>;\n\n if (h.schemaVersion !== '1.1.0') {\n throw new EvalError(`Unsupported schema version: ${String(h.schemaVersion)}`, {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n context: { schemaVersion: h.schemaVersion },\n });\n }\n\n const requiredFields = [\n 'sessionId',\n 'startedAt',\n 'initialPrompt',\n 'currentPrompt',\n 'rounds',\n 'totalCost',\n ];\n for (const field of requiredFields) {\n if (!(field in h)) {\n throw new EvalError(`Invalid history: missing field \"${field}\"`, {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n context: { missingField: field },\n });\n }\n }\n}\n\nclass ImprovementSessionImpl implements ImprovementSession {\n private _history: ImprovementHistory;\n private _isUpdating = false;\n private _savePromise: Promise<void> = Promise.resolve();\n private readonly config: Required<Pick<SessionConfig, 'autoSave'>> & SessionConfig;\n\n constructor(history: ImprovementHistory, config: SessionConfig = {}) {\n this._history = history;\n this.config = {\n autoSave: config.autoSave ?? false,\n ...config,\n };\n }\n\n get sessionId(): string {\n return this._history.sessionId;\n }\n\n get history(): Readonly<ImprovementHistory> {\n return this._history;\n }\n\n get canSave(): boolean {\n return this.config.path !== undefined;\n }\n\n addRound(roundResult: RoundResult, updatedPrompt: SerializedPrompt): void {\n if (this._isUpdating) {\n throw new EvalError('Session is being updated', {\n code: EvalErrorCode.CONCURRENT_MODIFICATION,\n context: { sessionId: this.sessionId },\n });\n }\n\n if (this._history.completedAt) {\n throw new EvalError('Cannot add round to completed session', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { sessionId: this.sessionId },\n });\n }\n\n this._isUpdating = true;\n try {\n const serializedRound = serializeRoundResult(roundResult);\n\n this._history = {\n ...this._history,\n currentPrompt: updatedPrompt,\n rounds: [...this._history.rounds, serializedRound],\n totalCost: this._history.totalCost + roundResult.cost.total,\n };\n\n if (this.config.autoSave && this.canSave) {\n this.save().catch((err) => this.handleAutoSaveError(err));\n }\n } finally {\n this._isUpdating = false;\n }\n }\n\n complete(terminationReason: string): void {\n this._history = {\n ...this._history,\n completedAt: new Date().toISOString(),\n terminationReason,\n };\n\n if (this.config.autoSave && this.canSave) {\n this.save().catch((err) => this.handleAutoSaveError(err));\n }\n }\n\n private handleAutoSaveError(error: unknown): void {\n const err = error instanceof Error ? error : new Error(String(error));\n if (this.config.onAutoSaveError) {\n this.config.onAutoSaveError(err);\n } else {\n console.error('Auto-save failed:', err);\n }\n }\n\n async save(): Promise<void> {\n if (!this.config.path) {\n throw new EvalError('Cannot save: no path configured', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { sessionId: this.sessionId },\n });\n }\n\n // Serialize saves to prevent race conditions from back-to-back autoSave triggers\n this._savePromise = this._savePromise.then(async () => {\n await saveHistory(this._history, this.config.path!, this.config.storage);\n });\n return this._savePromise;\n }\n\n async flush(): Promise<void> {\n return this._savePromise;\n }\n}\n\n/** @throws EvalError with PROMPT_INVALID_FORMAT if prompt lacks userTemplate */\nexport function createSession<TInput>(\n initialPrompt: AgentPrompt<TInput>,\n config?: SessionConfig\n): ImprovementSession {\n const serializedPrompt = serializePrompt(initialPrompt);\n\n const history: ImprovementHistory = {\n schemaVersion: '1.1.0',\n sessionId: crypto.randomUUID(),\n startedAt: new Date().toISOString(),\n initialPrompt: serializedPrompt,\n currentPrompt: serializedPrompt,\n rounds: [],\n totalCost: 0,\n };\n\n return new ImprovementSessionImpl(history, config);\n}\n\n/** Resume from a history file. Clears completion status to allow adding new rounds. */\nexport async function resumeSession(\n path: string,\n config?: Omit<SessionConfig, 'path'>\n): Promise<ImprovementSession> {\n const history = await loadHistory(path, config?.storage);\n\n const reopenedHistory: ImprovementHistory = {\n ...history,\n completedAt: undefined,\n terminationReason: undefined,\n };\n\n return new ImprovementSessionImpl(reopenedHistory, { ...config, path });\n}\n\n/** Save history to JSON file. Creates parent directories if needed. */\nexport async function saveHistory(\n history: ImprovementHistory,\n path: string,\n storage: HistoryStorage = defaultHistoryStorage\n): Promise<void> {\n try {\n const dir = dirname(path);\n if (dir && dir !== '.' && dir !== '/' && !storage.exists(dir)) {\n await storage.mkdir(dir, { recursive: true });\n }\n await storage.writeFile(path, JSON.stringify(history, null, 2));\n } catch (error) {\n if (error instanceof EvalError) throw error;\n throw EvalError.from(error, EvalErrorCode.FILE_WRITE_ERROR, { path });\n }\n}\n\nexport async function loadHistory(\n path: string,\n storage: HistoryStorage = defaultHistoryStorage\n): Promise<ImprovementHistory> {\n try {\n if (!storage.exists(path)) {\n throw new EvalError(`History file not found: ${path}`, {\n code: EvalErrorCode.FILE_READ_ERROR,\n context: { path },\n });\n }\n\n const content = await storage.readFile(path);\n const history = JSON.parse(content) as unknown;\n validateHistorySchema(history);\n\n return history;\n } catch (error) {\n if (error instanceof EvalError) throw error;\n throw EvalError.from(error, EvalErrorCode.FILE_READ_ERROR, { path });\n }\n}\n","import type { TestCase } from './types'\n\n/**\n * Options for random selection.\n */\nexport interface RandomOptions {\n /** Seed for reproducible random selection */\n seed?: number\n}\n\n/**\n * Immutable collection for managing and selecting test cases.\n * Provides fluent API for filtering, sampling, and accessing test cases.\n *\n * ## Immutability\n * - All selection methods (`filter`, `first`, `random`, etc.) return **new collections**\n * - Chaining creates intermediate collections without modifying the original\n * - Internal array is frozen with `Object.freeze()` to prevent accidental mutation\n * - `toArray()` returns a **mutable copy** for consumer convenience\n *\n * @example\n * ```typescript\n * import { TestCaseCollection, createEvalSuite } from '@agtlantis/eval'\n *\n * const cases = TestCaseCollection.from([\n * { id: 'basic', input: { query: 'Hello' } },\n * { id: 'complex', input: { query: 'Explain quantum computing' } },\n * { id: 'edge', input: { query: '' } },\n * ])\n *\n * // Development: quick feedback\n * await suite.run(cases.minimal().toArray())\n *\n * // CI: full coverage\n * await suite.run(cases.all().toArray())\n *\n * // Debugging specific case\n * await suite.run(cases.byIds(['edge']).toArray())\n *\n * // Chaining: filter then sample\n * const filtered = cases.filter(tc => tc.tags?.includes('fast')).random(3).toArray()\n * ```\n */\nexport class TestCaseCollection<TInput> {\n private readonly cases: ReadonlyArray<TestCase<TInput>>\n\n private constructor(cases: TestCase<TInput>[]) {\n this.cases = Object.freeze([...cases])\n }\n\n // ============================================================================\n // Static Factories\n // ============================================================================\n\n /**\n * Create a collection from an array of test cases.\n */\n static from<T>(cases: TestCase<T>[]): TestCaseCollection<T> {\n return new TestCaseCollection(cases)\n }\n\n /**\n * Create an empty collection.\n */\n static empty<T>(): TestCaseCollection<T> {\n return new TestCaseCollection<T>([])\n }\n\n // ============================================================================\n // Properties\n // ============================================================================\n\n /**\n * Number of test cases in the collection.\n */\n get length(): number {\n return this.cases.length\n }\n\n /**\n * Whether the collection is empty.\n */\n get isEmpty(): boolean {\n return this.cases.length === 0\n }\n\n // ============================================================================\n // Selection Methods (return new TestCaseCollection - chainable)\n // ============================================================================\n\n /**\n * Returns all test cases.\n * Returns `this` since the collection is immutable (frozen array).\n * Useful as explicit starting point in chains.\n */\n all(): TestCaseCollection<TInput> {\n return this\n }\n\n /**\n * Returns the first N test cases (default: 1).\n * Useful for cost-controlled testing during development.\n */\n minimal(count: number = 1): TestCaseCollection<TInput> {\n return this.first(count)\n }\n\n /**\n * Returns the first N test cases.\n */\n first(count: number): TestCaseCollection<TInput> {\n if (count <= 0) {\n return TestCaseCollection.empty()\n }\n return new TestCaseCollection([...this.cases.slice(0, count)])\n }\n\n /**\n * Returns the last N test cases (default: 1).\n * Preserves original order (earlier cases first).\n */\n last(count: number = 1): TestCaseCollection<TInput> {\n if (count <= 0) {\n return TestCaseCollection.empty()\n }\n const startIndex = Math.max(0, this.cases.length - count)\n return new TestCaseCollection([...this.cases.slice(startIndex)])\n }\n\n /**\n * Returns N random test cases.\n *\n * @param count - Number of cases to select\n * @param options - Optional seed for reproducibility\n *\n * @example\n * ```typescript\n * // Different each time\n * collection.random(5)\n *\n * // Same result with same seed\n * collection.random(5, { seed: 42 })\n * ```\n */\n random(count: number, options?: RandomOptions): TestCaseCollection<TInput> {\n if (count <= 0 || this.cases.length === 0) {\n return TestCaseCollection.empty()\n }\n\n const actualCount = Math.min(count, this.cases.length)\n const indices = [...Array(this.cases.length).keys()]\n\n const rng =\n options?.seed !== undefined ? createSeededRng(options.seed) : Math.random\n\n // Fisher-Yates shuffle\n for (let i = indices.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1))\n ;[indices[i], indices[j]] = [indices[j], indices[i]]\n }\n\n const selected = indices.slice(0, actualCount).map((i) => this.cases[i])\n return new TestCaseCollection([...selected])\n }\n\n /**\n * Filter test cases by predicate.\n */\n filter(\n predicate: (testCase: TestCase<TInput>) => boolean,\n ): TestCaseCollection<TInput> {\n return new TestCaseCollection([...this.cases.filter(predicate)])\n }\n\n /**\n * Find test case by ID.\n * Returns collection with single case or empty collection.\n */\n byId(id: string): TestCaseCollection<TInput> {\n const found = this.cases.find((tc) => tc.id === id)\n return found\n ? new TestCaseCollection([found])\n : TestCaseCollection.empty<TInput>()\n }\n\n /**\n * Find test cases by multiple IDs.\n * Preserves order of provided IDs (first occurrence).\n * Skips non-existent IDs. Duplicate IDs in input are deduplicated.\n *\n * @example\n * ```typescript\n * collection.byIds(['a', 'b', 'a']) // returns [case-a, case-b] (deduplicated)\n * collection.byIds(['b', 'a']) // returns [case-b, case-a] (order preserved)\n * ```\n */\n byIds(ids: string[]): TestCaseCollection<TInput> {\n const uniqueIds = [...new Set(ids)]\n const idSet = new Set(uniqueIds)\n const idToCase = new Map<string, TestCase<TInput>>()\n\n for (const tc of this.cases) {\n if (tc.id && idSet.has(tc.id) && !idToCase.has(tc.id)) {\n idToCase.set(tc.id, tc)\n }\n }\n\n const result = uniqueIds\n .map((id) => idToCase.get(id))\n .filter((tc): tc is TestCase<TInput> => tc !== undefined)\n\n return new TestCaseCollection(result)\n }\n\n // ============================================================================\n // Access Methods\n // ============================================================================\n\n /**\n * Get test case by ID.\n * Returns undefined if not found.\n */\n get(id: string): TestCase<TInput> | undefined {\n return this.cases.find((tc) => tc.id === id)\n }\n\n /**\n * Get test case by index.\n * Supports negative indices (e.g., -1 for last item).\n * Returns undefined if index is out of bounds.\n */\n at(index: number): TestCase<TInput> | undefined {\n const normalizedIndex = index < 0 ? this.cases.length + index : index\n if (normalizedIndex < 0 || normalizedIndex >= this.cases.length) {\n return undefined\n }\n return this.cases[normalizedIndex]\n }\n\n // ============================================================================\n // Conversion Methods\n // ============================================================================\n\n /**\n * Convert to array.\n * Returns a mutable copy of the internal array.\n */\n toArray(): TestCase<TInput>[] {\n return [...this.cases]\n }\n\n // ============================================================================\n // Iterator Support\n // ============================================================================\n\n /**\n * Iterator support for for...of loops and spread operator.\n */\n [Symbol.iterator](): Iterator<TestCase<TInput>> {\n return this.cases[Symbol.iterator]()\n }\n}\n\nlet autoIdCounter = 0\n\n/**\n * Create a single test case with auto-generated ID if not provided.\n *\n * Auto-generated IDs use a global counter: `test-1`, `test-2`, etc.\n *\n * @param input - The test case input data\n * @param id - Optional custom ID (uses auto-generated if omitted)\n * @returns A TestCase object\n *\n * @example\n * ```typescript\n * const case1 = testCase({ name: 'Alice' }) // id: 'test-1'\n * const case2 = testCase({ name: 'Bob' }) // id: 'test-2'\n * const case3 = testCase({ name: 'Charlie' }, 'custom-id') // id: 'custom-id'\n * ```\n *\n * @remarks\n * The global counter increments on every call. For deterministic IDs,\n * provide an explicit ID or use `testCases()` with a prefix.\n */\nexport function testCase<TInput>(input: TInput, id?: string): TestCase<TInput> {\n return {\n id: id ?? `test-${++autoIdCounter}`,\n input,\n }\n}\n\n/**\n * Create multiple test cases from inputs.\n * Auto-generates IDs with optional prefix.\n *\n * @example\n * ```typescript\n * const cases = testCases([{ name: 'Alice' }, { name: 'Bob' }], 'greet')\n * // Results in: [{ id: 'greet-0', input: {...} }, { id: 'greet-1', input: {...} }]\n * ```\n */\nexport function testCases<TInput>(\n inputs: TInput[],\n prefix: string = 'case',\n): TestCase<TInput>[] {\n return inputs.map((input, index) => ({\n id: `${prefix}-${index}`,\n input,\n }))\n}\n\n/**\n * Simple seeded random number generator (mulberry32 algorithm).\n * Provides reproducible pseudo-random sequences for test case selection.\n *\n * **Algorithm**: Mulberry32 - fast, good distribution, 32-bit state\n * **Period**: ~2^32 unique outputs per seed\n * **Use case**: Test case shuffling (not suitable for cryptographic purposes)\n *\n * @see https://github.com/bryc/code/blob/master/jshash/PRNGs.md\n * @internal\n */\nfunction createSeededRng(seed: number): () => number {\n let state = seed\n return () => {\n state = (state + 0x6d2b79f5) | 0\n let t = Math.imul(state ^ (state >>> 15), state | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n"],"mappings":"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","names":["resolveFileSourcesInInput","testCase","EvalErrorCode","fieldIsSet","testCase","resolve","testCase","resolveFileSourcesInInput","error","testCases","testCases","resolveFileSourcesInInput","getFileSourcesDisplayInfo","path","schema","path","writeFileSync","writeFileSync","testCases","writeFileSync","mkdirSync","path","mkdirSync","path","writeFileSync","writeFileSync","writeFileSync","Output","z","toEvalTokenUsage","z","Output","resolve","compileTemplate","calculateCostFromUsage","z","z","and","or","not","calculateCostFromUsage","existsSync","writeFile","compileTemplate","path","writeFile","existsSync","compileTemplate","testCases","toLanguageModelUsage","calculateCostFromUsage"]}
1
+ {"version":3,"sources":["../src/core/runner.ts","../src/multi-turn/types.ts","../src/core/errors.ts","../src/multi-turn/termination.ts","../src/utils/json.ts","../src/utils/condition-composites.ts","../src/multi-turn/conditions.ts","../src/multi-turn/runner.ts","../src/multi-turn/ai-user.ts","../src/utils/semaphore.ts","../src/core/constants.ts","../src/core/types.ts","../src/core/iteration.ts","../src/core/suite.ts","../src/index.ts","../src/judge/llm-judge.ts","../src/judge/prompts/default.ts","../src/judge/criteria/validate-schema.ts","../src/judge/criteria/index.ts","../src/reporter/markdown.ts","../src/reporter/json-reporter.ts","../src/reporter/cost-helpers.ts","../src/reporter/format-utils.ts","../src/reporter/markdown-reporter.ts","../src/reporter/console-reporter.ts","../src/reporter/composite-reporter.ts","../src/reporter/factory.ts","../src/reporter/runner.ts","../src/reporter/cycle-json.ts","../src/reporter/cycle-console.ts","../src/reporter/cycle-markdown.ts","../src/improver/utils.ts","../src/improver/llm-improver.ts","../src/improver/prompts/default.ts","../src/testing/mock-agent.ts","../src/cli/config/types.ts","../src/cli/config/loader.ts","../src/cli/config/schema.ts","../src/improvement-cycle/types.ts","../src/improvement-cycle/conditions.ts","../src/improvement-cycle/runner.ts","../src/improvement-cycle/history.ts","../src/core/test-case-collection.ts"],"sourcesContent":["import { resolveFileSourcesInInput } from '@agtlantis/core';\n\nimport type { Judge } from '@/judge/types';\nimport {\n type MultiTurnTestResult,\n executeMultiTurnTestCase,\n isMultiTurnTestCase,\n} from '@/multi-turn';\nimport { createSemaphore } from '@/utils/semaphore';\n\nimport { ZERO_TOKEN_USAGE } from './constants';\nimport { EvalError, EvalErrorCode } from './errors';\nimport type {\n EvalAgent,\n EvalTestResult,\n EvalTokenUsage,\n MetricsResult,\n MultiTurnResult,\n SingleTurnResult,\n TestCase,\n TestResult,\n TestResultWithVerdict,\n} from './types';\n\n/**\n * Options for running test cases.\n */\nexport interface RunOptions {\n /** Maximum number of concurrent test case executions. Defaults to 1 (sequential). */\n concurrency?: number;\n\n /** Stop execution after the first test failure. Defaults to false. */\n stopOnFirstFailure?: boolean;\n\n /** AbortSignal for cancelling execution */\n signal?: AbortSignal;\n\n /**\n * Number of times to run each test case. Defaults to 1.\n * When > 1, results include iteration statistics (mean, stdDev, passRate).\n */\n iterations?: number;\n}\n\n/**\n * Context required for executing a single test case.\n * @internal\n */\nexport interface ExecuteContext<TInput, TOutput> {\n agent: EvalAgent<TInput, TOutput>;\n judge: Judge;\n agentDescription: string;\n}\n\n/**\n * Executes a single test case and returns the result with verdict.\n *\n * Flow:\n * 1. Execute agent with test input\n * 2. Measure execution latency\n * 3. Collect token usage from agent metadata\n * 4. Evaluate output using Judge\n * 5. Return combined result with verdicts\n *\n * @example\n * ```typescript\n * const result = await executeTestCase(\n * { id: 'test-1', input: { query: 'Hello' } },\n * { agent: myAgent, judge: myJudge, agentDescription: 'A friendly bot' }\n * )\n *\n * console.log(result.passed) // true/false\n * console.log(result.overallScore) // 0-100\n * console.log(result.verdicts) // Verdict[]\n * ```\n */\nexport async function executeTestCase<TInput, TOutput>(\n testCase: TestCase<TInput>,\n context: ExecuteContext<TInput, TOutput>,\n signal?: AbortSignal\n): Promise<SingleTurnResult<TInput, TOutput>> {\n const { agent, judge, agentDescription } = context;\n\n if (signal?.aborted) {\n throw new EvalError('Test execution aborted', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, reason: 'aborted' },\n });\n }\n\n let resolvedInput: TInput;\n try {\n resolvedInput = await resolveFileSourcesInInput(testCase.input, {\n basePath: process.cwd(),\n });\n } catch (e) {\n const error = EvalError.from(e, EvalErrorCode.FILE_READ_ERROR, {\n testCaseId: testCase.id,\n agentName: agent.config.name,\n });\n return createFailedResult(testCase, error);\n }\n\n const startTime = performance.now();\n let output: TOutput;\n let tokenUsage: EvalTokenUsage = ZERO_TOKEN_USAGE;\n let error: Error | undefined;\n\n try {\n const agentResult = await agent.execute(resolvedInput);\n output = agentResult.result;\n if (agentResult.metadata?.tokenUsage) {\n tokenUsage = agentResult.metadata.tokenUsage;\n }\n } catch (e) {\n error = EvalError.from(e, EvalErrorCode.AGENT_EXECUTION_ERROR, {\n testCaseId: testCase.id,\n agentName: agent.config.name,\n });\n output = undefined as TOutput;\n }\n\n const latencyMs = performance.now() - startTime;\n\n const metrics: MetricsResult = { latencyMs, tokenUsage };\n const testResult: TestResult<TInput, TOutput> = { testCase, output, metrics, error };\n\n if (error) {\n return {\n kind: 'single-turn',\n ...testResult,\n verdicts: [],\n overallScore: 0,\n passed: false,\n judgeMetadata: undefined,\n };\n }\n\n if (signal?.aborted) {\n throw new EvalError('Test execution aborted before evaluation', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, reason: 'aborted' },\n });\n }\n\n const judgeResult = await judge.evaluate({\n input: testCase.input,\n output,\n agentDescription,\n files: testCase.files,\n });\n\n return {\n kind: 'single-turn',\n ...testResult,\n verdicts: judgeResult.verdicts,\n overallScore: judgeResult.overallScore,\n passed: judgeResult.passed,\n judgeMetadata: judgeResult.metadata,\n };\n}\n\nfunction createFailedResult<TInput, TOutput>(\n testCase: TestCase<TInput>,\n error: Error\n): SingleTurnResult<TInput, TOutput> {\n return {\n kind: 'single-turn',\n testCase,\n output: undefined as TOutput,\n metrics: { latencyMs: 0, tokenUsage: ZERO_TOKEN_USAGE },\n error,\n verdicts: [],\n overallScore: 0,\n passed: false,\n judgeMetadata: undefined,\n };\n}\n\n/**\n * Converts a MultiTurnTestResult to MultiTurnResult format.\n * This allows multi-turn results to flow through the same aggregation pipeline\n * as single-turn results while preserving multi-turn specific data.\n *\n * @internal\n */\nfunction toMultiTurnResult<TInput, TOutput>(\n result: MultiTurnTestResult<TInput, TOutput>\n): MultiTurnResult<TInput, TOutput> {\n return {\n kind: 'multi-turn',\n testCase: result.testCase,\n output: result.output as TOutput,\n metrics: result.metrics,\n verdicts: result.verdicts,\n overallScore: result.overallScore,\n passed: result.passed,\n judgeMetadata: result.judgeMetadata,\n conversationHistory: result.conversationHistory,\n totalTurns: result.totalTurns,\n terminationReason: result.termination.reason,\n termination: result.termination,\n };\n}\n\n/**\n * Runs multiple test cases with configurable concurrency.\n *\n * Features:\n * - Parallel execution with concurrency limit\n * - Stop on first failure option\n * - AbortSignal support for cancellation\n *\n * @example\n * ```typescript\n * const results = await runWithConcurrency(\n * testCases,\n * { agent: myAgent, judge: myJudge, agentDescription: 'Test agent' },\n * { concurrency: 5, stopOnFirstFailure: false }\n * )\n *\n * console.log(`Passed: ${results.filter(r => r.passed).length}`)\n * console.log(`Failed: ${results.filter(r => !r.passed).length}`)\n * ```\n */\nexport async function runWithConcurrency<TInput, TOutput>(\n testCases: TestCase<TInput>[],\n context: ExecuteContext<TInput, TOutput>,\n options: RunOptions = {}\n): Promise<EvalTestResult<TInput, TOutput>[]> {\n const { concurrency = 1, stopOnFirstFailure = false, signal } = options;\n\n if (concurrency < 1) {\n throw new EvalError('Concurrency must be at least 1', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { concurrency },\n });\n }\n\n if (testCases.length === 0) {\n return [];\n }\n\n const semaphore = createSemaphore(concurrency);\n const results: EvalTestResult<TInput, TOutput>[] = [];\n let shouldStop = false;\n let firstError: Error | undefined;\n const internalAbort = new AbortController();\n\n const propagateExternalAbort = () => {\n shouldStop = true;\n internalAbort.abort();\n };\n signal?.addEventListener('abort', propagateExternalAbort);\n\n if (signal?.aborted) {\n shouldStop = true;\n }\n\n try {\n const executeOne = async (testCase: TestCase<TInput>, index: number): Promise<void> => {\n if (shouldStop) return;\n\n await semaphore.acquire();\n\n try {\n if (shouldStop) return;\n\n const result = await executeTestCaseByType(testCase, context, internalAbort.signal);\n results[index] = result;\n\n if (stopOnFirstFailure && !result.passed) {\n shouldStop = true;\n internalAbort.abort();\n }\n } catch (e) {\n if (!firstError && !isAbortError(e)) {\n firstError = e instanceof Error ? e : new Error(String(e));\n }\n shouldStop = true;\n internalAbort.abort();\n } finally {\n semaphore.release();\n }\n };\n\n const promises = testCases.map((tc, i) => executeOne(tc, i));\n await Promise.allSettled(promises);\n\n if (firstError) {\n throw firstError;\n }\n\n return results.filter((r): r is EvalTestResult<TInput, TOutput> => r !== undefined);\n } finally {\n signal?.removeEventListener('abort', propagateExternalAbort);\n }\n}\n\nfunction isAbortError(e: unknown): boolean {\n return (\n (e instanceof DOMException && e.name === 'AbortError') ||\n (e instanceof EvalError && e.context?.reason === 'aborted')\n );\n}\n\nasync function executeTestCaseByType<TInput, TOutput>(\n testCase: TestCase<TInput>,\n context: ExecuteContext<TInput, TOutput>,\n signal: AbortSignal\n): Promise<EvalTestResult<TInput, TOutput>> {\n if (isMultiTurnTestCase<TInput, TOutput>(testCase)) {\n const multiTurnResult = await executeMultiTurnTestCase(testCase, context, { signal });\n return toMultiTurnResult(multiTurnResult);\n }\n return executeTestCase(testCase, context, signal);\n}\n","import type { AgentMetadata, TestCase, TestResultWithVerdict } from '@/core/types'\n\nexport type TerminationCondition<TInput = unknown, TOutput = unknown> =\n | MaxTurnsCondition\n | FieldSetCondition\n | FieldValueCondition\n | CustomCondition<TInput, TOutput>\n\nexport interface MaxTurnsCondition {\n type: 'maxTurns'\n /** Safety limit - terminates after this many turns */\n count: number\n}\n\nexport interface FieldsCondition {\n /** Dot notation for nested access (e.g., \"result.recommendation\") */\n fieldPath: string\n}\n\nexport interface FieldSetCondition extends FieldsCondition {\n type: 'fieldSet'\n}\n\nexport interface FieldValueCondition extends FieldsCondition {\n type: 'fieldValue'\n expectedValue: unknown\n}\n\nexport interface CustomCondition<TInput = unknown, TOutput = unknown> {\n type: 'custom'\n /** Sync or async check function (e.g., for LLM-based conditions) */\n check: (\n context: ConversationContext<TInput, TOutput>\n ) => boolean | Promise<boolean>\n /** For debugging/logging */\n description?: string\n}\n\nexport type TerminationType = 'condition' | 'maxTurns' | 'error' | 'exhausted'\n\nexport interface ContinueResult {\n terminated: false\n reason: string\n terminationType?: never\n matchedCondition?: never\n}\n\nexport interface TerminatedResult {\n terminated: true\n terminationType: TerminationType\n matchedCondition?: TerminationCondition<unknown, unknown>\n reason: string\n}\n\nexport type TerminationCheckResult = ContinueResult | TerminatedResult\n\nexport interface ConversationContext<TInput, TOutput = unknown> {\n currentTurn: number\n history: Array<{\n turn: number\n input: TInput\n output: TOutput | undefined\n metadata?: AgentMetadata\n }>\n lastOutput?: TOutput\n}\n\nexport interface FollowUpInput<TInput, TOutput = unknown> {\n /**\n * Input for this follow-up turn.\n * Can be static, dynamic (sync), or async (for AI-generated inputs via aiUser()).\n */\n input:\n | TInput\n | ((context: ConversationContext<TInput, TOutput>) => TInput)\n | ((context: ConversationContext<TInput, TOutput>) => Promise<TInput>)\n\n /** For debugging/reports */\n description?: string\n\n /**\n * Repeat count (default: 1).\n * Use Infinity to repeat until termination (must be last followUpInput).\n */\n turns?: number\n}\n\nexport interface MultiTurnTestCase<TInput, TOutput = unknown>\n extends TestCase<TInput> {\n multiTurn: {\n /** Inputs for 2nd turn onwards (first turn uses TestCase.input) */\n followUpInputs?: FollowUpInput<TInput, TOutput>[]\n\n /** Any condition triggers termination (OR logic) */\n terminateWhen: TerminationCondition<TInput, TOutput>[]\n\n /** Safety limit (default: 10). Uses min of this and any maxTurns condition. */\n maxTurns?: number\n\n /** Pass/fail when condition met (default: 'pass') */\n onConditionMet?: 'pass' | 'fail'\n\n /** Pass/fail when maxTurns reached (default: 'fail') */\n onMaxTurnsReached?: 'pass' | 'fail'\n }\n}\n\nexport interface MultiTurnTestResult<TInput, TOutput>\n extends Omit<TestResultWithVerdict<TInput, TOutput>, 'output'> {\n output: TOutput | undefined\n conversationHistory: Array<{\n turn: number\n input: TInput\n output: TOutput | undefined\n metadata?: AgentMetadata\n }>\n termination: TerminationCheckResult\n totalTurns: number\n}\n\nexport function isMaxTurnsCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is MaxTurnsCondition {\n return condition.type === 'maxTurns'\n}\n\nexport function isFieldSetCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is FieldSetCondition {\n return condition.type === 'fieldSet'\n}\n\nexport function isFieldValueCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is FieldValueCondition {\n return condition.type === 'fieldValue'\n}\n\nexport function isCustomCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>\n): condition is CustomCondition<TInput, TOutput> {\n return condition.type === 'custom'\n}\n\nexport function isMultiTurnTestCase<TInput, TOutput = unknown>(\n testCase: TestCase<TInput>\n): testCase is MultiTurnTestCase<TInput, TOutput> {\n return 'multiTurn' in testCase\n}\n\nexport function isTerminated(\n result: TerminationCheckResult\n): result is TerminatedResult {\n return result.terminated === true\n}\n","/**\n * Error codes for agent-eval operations\n */\nexport enum EvalErrorCode {\n // LLM errors\n LLM_API_ERROR = 'LLM_API_ERROR',\n LLM_RATE_LIMIT = 'LLM_RATE_LIMIT',\n LLM_TIMEOUT = 'LLM_TIMEOUT',\n\n // Parsing errors\n JSON_PARSE_ERROR = 'JSON_PARSE_ERROR',\n VERDICT_PARSE_ERROR = 'VERDICT_PARSE_ERROR',\n TEMPLATE_COMPILE_ERROR = 'TEMPLATE_COMPILE_ERROR',\n\n // Agent errors\n AGENT_EXECUTION_ERROR = 'AGENT_EXECUTION_ERROR',\n\n // Configuration errors\n INVALID_CONFIG = 'INVALID_CONFIG',\n MISSING_API_KEY = 'MISSING_API_KEY',\n\n // Prompt Repository errors\n PROMPT_NOT_FOUND = 'PROMPT_NOT_FOUND',\n PROMPT_INVALID_FORMAT = 'PROMPT_INVALID_FORMAT',\n PROMPT_WRITE_ERROR = 'PROMPT_WRITE_ERROR',\n PROMPT_READ_ERROR = 'PROMPT_READ_ERROR',\n\n // Suggestion apply errors\n SUGGESTION_APPLY_ERROR = 'SUGGESTION_APPLY_ERROR',\n\n // Schema validation errors\n SCHEMA_VALIDATION_ERROR = 'SCHEMA_VALIDATION_ERROR',\n SCHEMA_GENERATION_ERROR = 'SCHEMA_GENERATION_ERROR',\n\n // File context errors (Phase 5.3)\n FILE_READ_ERROR = 'FILE_READ_ERROR',\n FILE_WRITE_ERROR = 'FILE_WRITE_ERROR',\n FILE_TOO_LARGE = 'FILE_TOO_LARGE',\n\n // Concurrency errors\n CONCURRENT_MODIFICATION = 'CONCURRENT_MODIFICATION',\n\n // General errors\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\nexport interface EvalErrorOptions {\n code: EvalErrorCode\n cause?: Error\n context?: Record<string, unknown>\n}\n\n/**\n * Custom error class for agent-eval operations.\n * Provides structured error information including error code and optional context.\n */\nexport class EvalError extends Error {\n readonly code: EvalErrorCode\n readonly cause?: Error\n readonly context?: Record<string, unknown>\n\n constructor(message: string, options: EvalErrorOptions) {\n super(message)\n this.name = 'EvalError'\n this.code = options.code\n this.cause = options.cause\n this.context = options.context\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EvalError)\n }\n }\n\n /**\n * Creates an EvalError from an unknown error with a specific code.\n */\n static from(error: unknown, code: EvalErrorCode, context?: Record<string, unknown>): EvalError {\n if (error instanceof EvalError) {\n return error\n }\n\n const cause = error instanceof Error ? error : new Error(String(error))\n return new EvalError(cause.message, { code, cause, context })\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n cause: this.cause?.message,\n }\n }\n}\n","import type {\n ConversationContext,\n CustomCondition,\n FieldSetCondition,\n FieldValueCondition,\n MaxTurnsCondition,\n TerminationCheckResult,\n TerminationCondition,\n} from './types'\nimport {\n isCustomCondition,\n isFieldSetCondition,\n isFieldValueCondition,\n isMaxTurnsCondition,\n} from './types'\nimport { EvalError, EvalErrorCode } from '@/core/errors'\n\n/** Access a nested field value using dot notation (e.g., \"result.recommendation\"). */\nexport function getFieldValue(obj: unknown, fieldPath: string): unknown {\n if (obj === null || obj === undefined) {\n return undefined\n }\n\n const parts = fieldPath.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) {\n return undefined\n }\n\n if (typeof current !== 'object') {\n return undefined\n }\n\n current = (current as Record<string, unknown>)[part]\n }\n\n return current\n}\n\nfunction isSet(value: unknown): boolean {\n return value !== null && value !== undefined\n}\n\nfunction checkMaxTurns<TInput, TOutput>(\n condition: MaxTurnsCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const shouldTerminate = context.currentTurn >= condition.count\n\n if (shouldTerminate) {\n return {\n terminated: true,\n terminationType: 'maxTurns',\n matchedCondition: condition,\n reason: `Maximum turns reached (${condition.count})`,\n }\n }\n\n return {\n terminated: false,\n reason: `Turn ${context.currentTurn} of ${condition.count}`,\n }\n}\n\nfunction checkFieldSet<TInput, TOutput>(\n condition: FieldSetCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const fieldValue = getFieldValue(context.lastOutput, condition.fieldPath)\n const fieldIsSet = isSet(fieldValue)\n\n if (fieldIsSet) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition,\n reason: `Field \"${condition.fieldPath}\" is set (value: ${JSON.stringify(fieldValue)})`,\n }\n }\n\n return {\n terminated: false,\n reason: `Field \"${condition.fieldPath}\" is not set`,\n }\n}\n\nfunction checkFieldValue<TInput, TOutput>(\n condition: FieldValueCondition,\n context: ConversationContext<TInput, TOutput>\n): TerminationCheckResult {\n const fieldValue = getFieldValue(context.lastOutput, condition.fieldPath)\n const matches = fieldValue === condition.expectedValue\n\n if (matches) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition,\n reason: `Field \"${condition.fieldPath}\" equals expected value`,\n }\n }\n\n return {\n terminated: false,\n reason: `Field \"${condition.fieldPath}\" does not equal expected value (got: ${JSON.stringify(fieldValue)})`,\n }\n}\n\nasync function checkCustom<TInput, TOutput>(\n condition: CustomCondition<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n const description = condition.description ?? 'Custom condition'\n\n try {\n const shouldTerminate = await condition.check(context)\n\n if (shouldTerminate) {\n return {\n terminated: true,\n terminationType: 'condition',\n matchedCondition: condition as TerminationCondition<unknown, unknown>,\n reason: `${description} met`,\n }\n }\n\n return {\n terminated: false,\n reason: `${description} not met`,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n terminated: false,\n reason: `${description} failed: ${errorMessage}`,\n }\n }\n}\n\nexport async function checkCondition<TInput, TOutput>(\n condition: TerminationCondition<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n if (isMaxTurnsCondition(condition)) {\n return checkMaxTurns(condition, context)\n }\n\n if (isFieldValueCondition(condition)) {\n return checkFieldValue(condition, context)\n }\n\n if (isFieldSetCondition(condition)) {\n return checkFieldSet(condition, context)\n }\n\n if (isCustomCondition(condition)) {\n return checkCustom(condition, context)\n }\n\n const _exhaustive: never = condition\n throw new EvalError(`Unknown condition type: ${JSON.stringify(_exhaustive)}`, {\n code: EvalErrorCode.UNKNOWN_ERROR,\n context: { condition: _exhaustive },\n })\n}\n\n/** Check all termination conditions (OR relationship). Returns on first termination. */\nexport async function checkTermination<TInput, TOutput>(\n conditions: TerminationCondition<TInput, TOutput>[],\n context: ConversationContext<TInput, TOutput>\n): Promise<TerminationCheckResult> {\n if (conditions.length === 0) {\n return {\n terminated: false,\n reason: 'No termination conditions specified',\n }\n }\n\n for (const condition of conditions) {\n const result = await checkCondition(condition, context)\n if (result.terminated) {\n return result\n }\n }\n\n return {\n terminated: false,\n reason: 'No termination conditions met',\n }\n}\n","/**\n * Extracts JSON from LLM response, handling markdown code blocks.\n *\n * Supports:\n * - Raw JSON: `{\"key\": \"value\"}`\n * - Markdown code block: ```json\\n{...}\\n```\n * - Code block without annotation: ```\\n{...}\\n```\n * - JSON embedded in text: \"Here is my answer: {...} Hope this helps\"\n *\n * @example\n * ```typescript\n * const json = extractJson('```json\\n{\"foo\": \"bar\"}\\n```')\n * console.log(json) // '{\"foo\": \"bar\"}'\n * ```\n */\nexport function extractJson(content: string): string {\n const markdownCodeBlockMatch = content.match(/```(?:json)?\\s*([\\s\\S]*?)```/)\n if (markdownCodeBlockMatch) {\n return markdownCodeBlockMatch[1].trim()\n }\n\n const jsonObjectMatch = content.match(/\\{[\\s\\S]*\\}/)\n if (jsonObjectMatch) {\n return jsonObjectMatch[0]\n }\n\n return content.trim()\n}\n\n/**\n * Truncates a string to a maximum length with ellipsis.\n * Only adds \"...\" if the string was actually truncated.\n *\n * @example\n * ```typescript\n * truncate('hello', 10) // 'hello'\n * truncate('hello world', 5) // 'hello...'\n * ```\n */\nexport function truncate(str: string | undefined | null, maxLength: number): string {\n if (!str) {\n return ''\n }\n if (str.length <= maxLength) {\n return str\n }\n return str.slice(0, maxLength) + '...'\n}\n","/**\n * Shared Condition Composite Helpers\n *\n * These helper functions provide the core logic for AND/OR/NOT condition composites.\n * Domain-specific modules (multi-turn, improvement-cycle) use these helpers while\n * maintaining their own type definitions.\n *\n * @example\n * ```typescript\n * // In multi-turn/conditions.ts\n * import { createAndCheck } from '@/utils/condition-composites'\n *\n * export function and<TInput, TOutput>(\n * ...conditions: TerminationCondition<TInput, TOutput>[]\n * ): CustomCondition<TInput, TOutput> {\n * return {\n * type: 'custom',\n * check: createAndCheck(conditions, checkCondition),\n * description: `and(${conditions.map(c => c.type).join(', ')})`,\n * }\n * }\n * ```\n */\n\n/**\n * Result type expected from condition check functions.\n * Both multi-turn and improvement-cycle use this shape.\n */\nexport interface ConditionCheckResult {\n terminated: boolean\n}\n\n/**\n * Type for condition check functions.\n * The check function receives a condition and context, returns a result.\n */\nexport type ConditionCheckFn<TCondition, TContext> = (\n condition: TCondition,\n context: TContext\n) => ConditionCheckResult | Promise<ConditionCheckResult>\n\n/**\n * Create an AND check function.\n *\n * Returns a function that evaluates all conditions and returns true only if ALL terminate.\n * Short-circuits on first non-terminating condition.\n *\n * @param conditions - Array of conditions to check\n * @param checkFn - Function to check a single condition\n * @returns Async function that returns true if all conditions terminate\n */\nexport function createAndCheck<TCondition, TContext>(\n conditions: TCondition[],\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n for (const condition of conditions) {\n const result = await checkFn(condition, context)\n if (!result.terminated) {\n return false\n }\n }\n return true\n }\n}\n\n/**\n * Create an OR check function.\n *\n * Returns a function that evaluates conditions and returns true if ANY terminates.\n * Short-circuits on first terminating condition.\n *\n * @param conditions - Array of conditions to check\n * @param checkFn - Function to check a single condition\n * @returns Async function that returns true if any condition terminates\n */\nexport function createOrCheck<TCondition, TContext>(\n conditions: TCondition[],\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n for (const condition of conditions) {\n const result = await checkFn(condition, context)\n if (result.terminated) {\n return true\n }\n }\n return false\n }\n}\n\n/**\n * Create a NOT check function.\n *\n * Returns a function that inverts the result of a single condition check.\n *\n * @param condition - The condition to invert\n * @param checkFn - Function to check the condition\n * @returns Async function that returns true if condition does NOT terminate\n */\nexport function createNotCheck<TCondition, TContext>(\n condition: TCondition,\n checkFn: ConditionCheckFn<TCondition, TContext>\n): (context: TContext) => Promise<boolean> {\n return async (context: TContext) => {\n const result = await checkFn(condition, context)\n return !result.terminated\n }\n}\n\n/**\n * Format a description for composite conditions.\n *\n * @param type - Composite type ('and', 'or', 'not')\n * @param conditions - Conditions being composed\n * @returns Formatted description string\n */\nexport function formatCompositeDescription<TCondition extends { type: string }>(\n type: 'and' | 'or',\n conditions: TCondition[]\n): string {\n if (conditions.length === 0) {\n return `${type}() - empty, never terminates`\n }\n return `${type}(${conditions.map((c) => c.type).join(', ')})`\n}\n","import type { Provider } from '@agtlantis/core';\nimport { truncate } from '@/utils/json';\nimport { checkCondition } from './termination';\nimport type { ConversationContext, CustomCondition, TerminationCondition } from './types';\n\nimport {\n createAndCheck,\n createOrCheck,\n createNotCheck,\n formatCompositeDescription,\n} from '../utils/condition-composites';\n\nexport interface NaturalLanguageConditionOptions {\n /** Provider to use for evaluation */\n provider: Provider;\n /** Prompt describing the termination criteria (e.g., \"Has the user's question been fully answered?\") */\n prompt: string;\n /** Optional system prompt override */\n systemPrompt?: string;\n}\n\n/** LLM-based termination condition. Asks the LLM to evaluate the termination criteria. */\nexport function naturalLanguage<TInput = unknown, TOutput = unknown>(\n options: NaturalLanguageConditionOptions\n): CustomCondition<TInput, TOutput> {\n const { provider, prompt, systemPrompt } = options;\n\n const defaultSystemPrompt = `You are an assistant that evaluates whether a conversation should terminate.\nAnalyze the conversation history and determine if the specified condition is met.\nRespond with ONLY \"yes\" or \"no\" - nothing else.`;\n\n return {\n type: 'custom',\n check: async (context: ConversationContext<TInput, TOutput>) => {\n const historyText = context.history\n .map(\n (h) =>\n `Turn ${h.turn}:\\nInput: ${JSON.stringify(h.input)}\\nOutput: ${JSON.stringify(h.output)}`\n )\n .join('\\n\\n');\n\n const userPrompt = `## Termination Condition\n${prompt}\n\n## Conversation History\n${historyText || '(No history yet)'}\n\n## Current Turn\nTurn: ${context.currentTurn}\nLast Output: ${JSON.stringify(context.lastOutput)}\n\nShould the conversation terminate based on the condition above? Answer \"yes\" or \"no\" only.`;\n\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages: [\n { role: 'system', content: systemPrompt ?? defaultSystemPrompt },\n { role: 'user', content: userPrompt },\n ],\n });\n return result.text;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n const responseText = executionResult.value;\n const answer = responseText.toLowerCase().trim();\n return answer === 'yes' || answer.startsWith('yes');\n },\n description: `NL: ${truncate(prompt, 50)}`,\n };\n}\n\n/** Terminates when ALL sub-conditions are met (AND logic). */\nexport function and<TInput = unknown, TOutput = unknown>(\n ...conditions: TerminationCondition<TInput, TOutput>[]\n): CustomCondition<TInput, TOutput> {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('and', []),\n };\n }\n\n return {\n type: 'custom',\n check: createAndCheck(conditions, checkCondition),\n description: formatCompositeDescription('and', conditions),\n };\n}\n\n/** Terminates when ANY sub-condition is met (OR logic). Useful for nested composites. */\nexport function or<TInput = unknown, TOutput = unknown>(\n ...conditions: TerminationCondition<TInput, TOutput>[]\n): CustomCondition<TInput, TOutput> {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('or', []),\n };\n }\n\n return {\n type: 'custom',\n check: createOrCheck(conditions, checkCondition),\n description: formatCompositeDescription('or', conditions),\n };\n}\n\n/** Inverts another condition (NOT logic). */\nexport function not<TInput = unknown, TOutput = unknown>(\n condition: TerminationCondition<TInput, TOutput>\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: createNotCheck(condition, checkCondition),\n description: `not(${condition.type})`,\n };\n}\n\n/** Terminates after a specified number of turns. Convenience wrapper for use in composites. */\nexport function afterTurns<TInput = unknown, TOutput = unknown>(\n count: number\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: (context) => context.currentTurn >= count,\n description: `afterTurns(${count})`,\n };\n}\n\n/** Terminates when a field matches a specific value. Convenience wrapper for composites. */\nexport function fieldEquals<TInput = unknown, TOutput = unknown>(\n fieldPath: string,\n expectedValue: unknown\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: async (context) => {\n const result = await checkCondition(\n { type: 'fieldValue', fieldPath, expectedValue },\n context\n );\n return result.terminated;\n },\n description: `fieldEquals(${fieldPath}, ${JSON.stringify(expectedValue)})`,\n };\n}\n\n/** Terminates when a field is set (not null/undefined). Convenience wrapper for composites. */\nexport function fieldIsSet<TInput = unknown, TOutput = unknown>(\n fieldPath: string\n): CustomCondition<TInput, TOutput> {\n return {\n type: 'custom',\n check: async (context) => {\n const result = await checkCondition({ type: 'fieldSet', fieldPath }, context);\n return result.terminated;\n },\n description: `fieldIsSet(${fieldPath})`,\n };\n}\n","import { resolveFileSourcesInInput } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentMetadata, EvalAgent, EvalTokenUsage, MetricsResult } from '@/core/types';\nimport type { Judge } from '@/judge/types';\n\nimport { checkTermination } from './termination';\nimport type {\n ConversationContext,\n FollowUpInput,\n MultiTurnTestCase,\n MultiTurnTestResult,\n TerminationCheckResult,\n TerminationCondition,\n} from './types';\nimport { isTerminated } from './types';\n\nexport interface MultiTurnExecuteContext<TInput, TOutput> {\n agent: EvalAgent<TInput, TOutput>;\n judge: Judge;\n agentDescription: string;\n}\n\nexport interface MultiTurnExecuteOptions {\n signal?: AbortSignal;\n}\n\nconst DEFAULT_MAX_TURNS = 10;\nconst DEFAULT_ON_CONDITION_MET: 'pass' | 'fail' = 'pass';\nconst DEFAULT_ON_MAX_TURNS_REACHED: 'pass' | 'fail' = 'fail';\n\nfunction aggregateTokenUsage(usages: EvalTokenUsage[]): EvalTokenUsage {\n return usages.reduce(\n (acc, usage) => ({\n inputTokens: acc.inputTokens + usage.inputTokens,\n outputTokens: acc.outputTokens + usage.outputTokens,\n totalTokens: acc.totalTokens + usage.totalTokens,\n }),\n { inputTokens: 0, outputTokens: 0, totalTokens: 0 }\n );\n}\n\nfunction getEffectiveMaxTurns<TInput, TOutput>(\n conditions: TerminationCondition<TInput, TOutput>[],\n safetyLimit: number\n): number {\n const maxTurnsCondition = conditions.find((c) => c.type === 'maxTurns');\n if (maxTurnsCondition && maxTurnsCondition.type === 'maxTurns') {\n return Math.min(maxTurnsCondition.count, safetyLimit);\n }\n return safetyLimit;\n}\n\nasync function resolveInput<TInput, TOutput>(\n followUpInput: FollowUpInput<TInput, TOutput>,\n context: ConversationContext<TInput, TOutput>\n): Promise<TInput> {\n const inputValue = followUpInput.input;\n if (typeof inputValue === 'function') {\n const result = (\n inputValue as (ctx: ConversationContext<TInput, TOutput>) => TInput | Promise<TInput>\n )(context);\n return result instanceof Promise ? await result : result;\n }\n return inputValue as TInput;\n}\n\nfunction buildContext<TInput, TOutput>(\n currentTurn: number,\n history: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }>\n): ConversationContext<TInput, TOutput> {\n return {\n currentTurn,\n history,\n lastOutput: history.length > 0 ? history[history.length - 1].output : undefined,\n };\n}\n\nfunction getFollowUpInput<TInput, TOutput>(\n followUpInputs: FollowUpInput<TInput, TOutput>[],\n followUpIndex: number\n): FollowUpInput<TInput, TOutput> | null {\n let currentIndex = 0;\n\n for (const followUp of followUpInputs) {\n const repeatCount = followUp.turns ?? 1;\n\n if (!Number.isFinite(repeatCount) && followUpIndex >= currentIndex) {\n return followUp;\n }\n\n if (followUpIndex < currentIndex + repeatCount) {\n return followUp;\n }\n\n currentIndex += repeatCount;\n }\n\n return null;\n}\n\nfunction validateFollowUpInputs<TInput, TOutput>(\n followUpInputs: FollowUpInput<TInput, TOutput>[]\n): void {\n for (let i = 0; i < followUpInputs.length; i++) {\n const followUp = followUpInputs[i];\n\n if (followUp.turns === undefined) {\n continue;\n }\n\n if (typeof followUp.turns !== 'number' || followUp.turns < 1) {\n throw new EvalError('turns must be a positive number or Infinity', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: {\n description: followUp.description,\n turns: followUp.turns,\n },\n });\n }\n\n if (!Number.isFinite(followUp.turns) && i < followUpInputs.length - 1) {\n throw new EvalError(\n 'turns: Infinity must be the last followUpInput (subsequent items would be unreachable)',\n {\n code: EvalErrorCode.INVALID_CONFIG,\n context: {\n description: followUp.description,\n position: i,\n totalItems: followUpInputs.length,\n },\n }\n );\n }\n }\n}\n\ntype GetTurnInputResult<TInput> = { type: 'success'; input: TInput } | { type: 'exhausted' };\n\nasync function getTurnInput<TInput, TOutput>(\n turn: number,\n testCaseInput: TInput,\n followUpInputs: FollowUpInput<TInput, TOutput>[],\n conversationHistory: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }>\n): Promise<GetTurnInputResult<TInput>> {\n if (turn === 1) {\n return { type: 'success', input: testCaseInput };\n }\n\n const followUpIndex = turn - 2;\n const followUp = getFollowUpInput(followUpInputs, followUpIndex);\n\n if (!followUp) {\n return { type: 'exhausted' };\n }\n\n const ctx = buildContext(turn, conversationHistory);\n const input = await resolveInput(followUp, ctx);\n return { type: 'success', input };\n}\n\ninterface TurnExecutionResult<TOutput> {\n output: TOutput | undefined;\n metadata: AgentMetadata | undefined;\n latencyMs: number;\n error?: Error;\n}\n\nfunction isFileResolutionError<TOutput>(\n result: TurnExecutionResult<TOutput> | { type: 'fileResolutionError'; reason: string }\n): result is { type: 'fileResolutionError'; reason: string } {\n return 'type' in result && result.type === 'fileResolutionError';\n}\n\nasync function executeSingleTurn<TInput, TOutput>(\n input: TInput,\n agent: EvalAgent<TInput, TOutput>,\n testCaseId: string,\n turn: number\n): Promise<TurnExecutionResult<TOutput> | { type: 'fileResolutionError'; reason: string }> {\n let resolvedInput: TInput;\n try {\n resolvedInput = await resolveFileSourcesInInput(input, {\n basePath: process.cwd(),\n });\n } catch (e) {\n return {\n type: 'fileResolutionError',\n reason: `FileSource resolution failed on turn ${turn}: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n\n const startTime = performance.now();\n let output: TOutput | undefined;\n let metadata: AgentMetadata | undefined;\n let error: Error | undefined;\n\n try {\n const agentResult = await agent.execute(resolvedInput);\n output = agentResult.result;\n metadata = agentResult.metadata;\n } catch (e) {\n error = EvalError.from(e, EvalErrorCode.AGENT_EXECUTION_ERROR, {\n testCaseId,\n turn,\n agentName: agent.config.name,\n });\n }\n\n const latencyMs = performance.now() - startTime;\n return { output, metadata, latencyMs, error };\n}\n\nfunction determinePassFromTermination(\n termination: TerminationCheckResult,\n onConditionMet: 'pass' | 'fail',\n onMaxTurnsReached: 'pass' | 'fail'\n): boolean {\n if (!isTerminated(termination)) {\n return true;\n }\n\n switch (termination.terminationType) {\n case 'error':\n case 'exhausted':\n return false;\n case 'maxTurns':\n return onMaxTurnsReached === 'pass';\n case 'condition':\n return onConditionMet === 'pass';\n default:\n return true;\n }\n}\n\nexport async function executeMultiTurnTestCase<TInput, TOutput>(\n testCase: MultiTurnTestCase<TInput, TOutput>,\n context: MultiTurnExecuteContext<TInput, TOutput>,\n options?: MultiTurnExecuteOptions\n): Promise<MultiTurnTestResult<TInput, TOutput>> {\n const { agent, judge, agentDescription } = context;\n const { multiTurn } = testCase;\n const signal = options?.signal;\n\n const maxTurns = getEffectiveMaxTurns(\n multiTurn.terminateWhen,\n multiTurn.maxTurns ?? DEFAULT_MAX_TURNS\n );\n const onConditionMet = multiTurn.onConditionMet ?? DEFAULT_ON_CONDITION_MET;\n const onMaxTurnsReached = multiTurn.onMaxTurnsReached ?? DEFAULT_ON_MAX_TURNS_REACHED;\n const followUpInputs = multiTurn.followUpInputs ?? [];\n\n validateFollowUpInputs(followUpInputs);\n\n const conversationHistory: Array<{\n turn: number;\n input: TInput;\n output: TOutput | undefined;\n metadata?: AgentMetadata;\n }> = [];\n const tokenUsages: EvalTokenUsage[] = [];\n let totalLatencyMs = 0;\n let termination: TerminationCheckResult = {\n terminated: false,\n reason: 'Execution not started',\n };\n\n for (let turn = 1; turn <= maxTurns; turn++) {\n if (signal?.aborted) {\n throw new EvalError('Multi-turn test execution aborted', {\n code: EvalErrorCode.AGENT_EXECUTION_ERROR,\n context: { testCaseId: testCase.id, turn, reason: 'aborted' },\n });\n }\n\n const inputResult = await getTurnInput(\n turn,\n testCase.input,\n followUpInputs,\n conversationHistory\n );\n if (inputResult.type === 'exhausted') {\n termination = {\n terminated: true,\n terminationType: 'exhausted',\n reason: 'All follow-up inputs exhausted',\n };\n break;\n }\n const input = inputResult.input;\n\n const turnResult = await executeSingleTurn(input, agent, testCase.id ?? 'unknown', turn);\n if (isFileResolutionError(turnResult)) {\n termination = {\n terminated: true,\n terminationType: 'error',\n reason: turnResult.reason,\n };\n break;\n }\n\n const {\n output: agentOutput,\n metadata: agentMetadata,\n latencyMs,\n error: agentError,\n } = turnResult;\n totalLatencyMs += latencyMs;\n\n const turnUsage = agentMetadata?.tokenUsage ?? {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n tokenUsages.push(turnUsage);\n\n conversationHistory.push({\n turn,\n input,\n output: agentOutput,\n metadata: agentMetadata,\n });\n\n if (agentError) {\n termination = {\n terminated: true,\n terminationType: 'error',\n reason: `Agent execution failed on turn ${turn}: ${agentError.message}`,\n };\n break;\n }\n\n const ctx = buildContext(turn, conversationHistory);\n termination = await checkTermination(multiTurn.terminateWhen, ctx);\n\n if (termination.terminated) {\n break;\n }\n\n if (turn >= maxTurns) {\n termination = {\n terminated: true,\n terminationType: 'maxTurns',\n matchedCondition: { type: 'maxTurns', count: maxTurns },\n reason: `Maximum turns reached (${maxTurns})`,\n };\n break;\n }\n }\n\n const aggregatedTokenUsage = aggregateTokenUsage(tokenUsages);\n const metrics: MetricsResult = {\n latencyMs: totalLatencyMs,\n tokenUsage: aggregatedTokenUsage,\n };\n\n const lastTurn = conversationHistory[conversationHistory.length - 1];\n const finalOutput = lastTurn?.output;\n\n const judgeResult = await judge.evaluate({\n input: testCase.input,\n output: finalOutput,\n agentDescription,\n files: testCase.files,\n });\n\n const passedTermination = determinePassFromTermination(\n termination,\n onConditionMet,\n onMaxTurnsReached\n );\n const passed = passedTermination && judgeResult.passed;\n\n return {\n testCase,\n output: finalOutput,\n metrics,\n verdicts: judgeResult.verdicts,\n overallScore: judgeResult.overallScore,\n passed,\n judgeMetadata: judgeResult.metadata,\n conversationHistory,\n termination,\n totalTurns: conversationHistory.length,\n };\n}\n","import type { Provider } from '@agtlantis/core';\nimport type { ConversationContext } from './types';\n\nexport interface AIUserOptions<TInput, TOutput> {\n /** Provider for generating user responses */\n provider: Provider;\n\n /** System prompt (string or function for dynamic personas). Uses default if not provided. */\n systemPrompt?: string | ((context: ConversationContext<TInput, TOutput>) => string);\n\n /** Custom history formatter. Default: JSON-based \"User: {input}\\nAssistant: {output}\" format. */\n formatHistory?: (context: ConversationContext<TInput, TOutput>) => string;\n\n /** Convert LLM text response to TInput. Has access to full context for structured input building. */\n buildInput: (llmResponse: string, context: ConversationContext<TInput, TOutput>) => TInput;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are simulating a realistic user in a conversation with an AI assistant.\n\n## Your Role\nGenerate natural, context-appropriate user messages based on the conversation history.\n\n## Guidelines\n\n1. **Stay in Character**: Respond as a real user would - with natural language, occasional typos, or casual phrasing when appropriate.\n\n2. **Be Goal-Oriented**: Users have objectives. Pursue them logically based on the conversation context:\n - If the assistant asks a question, provide a reasonable answer\n - If clarification is needed, ask for it naturally\n - If a task is progressing, guide it toward completion\n\n3. **React Appropriately**: Respond to what the assistant says:\n - Acknowledge when the assistant is helpful\n - Express confusion if the response is unclear\n - Correct misunderstandings if they occur\n\n4. **Keep It Realistic**: Real users:\n - Don't always provide perfect information upfront\n - May change their mind or add requirements\n - Sometimes need time to think or decide\n\n## Output Format\nRespond with ONLY the user's message. No additional formatting, explanation, or meta-commentary.`;\n\n/**\n * Creates an async function that generates user inputs using an LLM for multi-turn testing.\n *\n * @example\n * ```typescript\n * aiUser({\n * provider: openai,\n * systemPrompt: 'You are a friendly customer.',\n * buildInput: (response, ctx) => ({ message: response }),\n * })\n * ```\n */\nexport function aiUser<TInput, TOutput>(\n options: AIUserOptions<TInput, TOutput>\n): (context: ConversationContext<TInput, TOutput>) => Promise<TInput> {\n const { provider, systemPrompt, formatHistory, buildInput } = options;\n\n const defaultFormatHistory = (ctx: ConversationContext<TInput, TOutput>): string =>\n ctx.history\n .map(\n (h, i) =>\n `[Turn ${i + 1}]\\nUser: ${JSON.stringify(h.input)}\\nAssistant: ${JSON.stringify(h.output)}`\n )\n .join('\\n\\n');\n\n return async (context: ConversationContext<TInput, TOutput>): Promise<TInput> => {\n const historyText = (formatHistory ?? defaultFormatHistory)(context);\n\n const resolvedSystemPrompt =\n typeof systemPrompt === 'function'\n ? systemPrompt(context)\n : (systemPrompt ?? DEFAULT_SYSTEM_PROMPT);\n\n const userPrompt = historyText\n ? `## Conversation History\\n${historyText}\\n\\n## Your Task\\nGenerate the next user message based on the conversation above:`\n : `## Your Task\\nThis is the start of a new conversation. Generate an appropriate opening message from the user:`;\n\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages: [\n { role: 'system', content: resolvedSystemPrompt },\n { role: 'user', content: userPrompt },\n ],\n });\n return result.text;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n const responseText = executionResult.value;\n return buildInput(responseText, context);\n };\n}\n","/**\n * A simple semaphore for limiting concurrent operations.\n *\n * @example\n * ```typescript\n * const semaphore = createSemaphore(3) // Allow 3 concurrent operations\n *\n * async function doWork(id: number) {\n * await semaphore.acquire()\n * try {\n * console.log(`Starting work ${id}`)\n * await someAsyncOperation()\n * } finally {\n * semaphore.release()\n * }\n * }\n *\n * // Launch 10 tasks, but only 3 run at a time\n * await Promise.all(Array.from({ length: 10 }, (_, i) => doWork(i)))\n * ```\n */\nexport interface Semaphore {\n /**\n * Acquires a slot from the semaphore.\n * If no slots are available, waits until one is released.\n */\n acquire(): Promise<void>\n\n /**\n * Releases a slot back to the semaphore.\n * Must be called after acquire() completes, typically in a finally block.\n */\n release(): void\n}\n\n/**\n * Creates a semaphore with the specified concurrency limit.\n *\n * @param limit - Maximum number of concurrent operations allowed\n * @returns A Semaphore instance\n */\nexport function createSemaphore(limit: number): Semaphore {\n let running = 0\n const waiting: Array<() => void> = []\n\n return {\n async acquire(): Promise<void> {\n if (running < limit) {\n running++\n return\n }\n return new Promise<void>((resolve) => {\n waiting.push(resolve)\n })\n },\n\n release(): void {\n running--\n const next = waiting.shift()\n if (next) {\n running++\n next()\n }\n },\n }\n}\n","/**\n * Evaluation Constants\n *\n * Centralized constants used across the evaluation system.\n * Eliminates magic numbers and provides semantic names.\n */\n\n/**\n * Score-related constants.\n */\nexport const SCORE = {\n /** Minimum possible score */\n MIN: 0,\n /** Maximum possible score */\n MAX: 100,\n /** Default threshold for passing evaluation */\n DEFAULT_PASS_THRESHOLD: 70,\n /** Threshold for majority-based pass determination (50%) */\n MAJORITY_PASS_THRESHOLD: 0.5,\n} as const\n\n/**\n * Default configuration values.\n */\nexport const DEFAULTS = {\n /** Default maximum turns for multi-turn conversations */\n MAX_TURNS: 10,\n /** Default concurrency for parallel execution */\n CONCURRENCY: 1,\n} as const\n\n\n/**\n * Zero token usage - used for error cases or initialization.\n */\nexport const ZERO_TOKEN_USAGE = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n} as const\n\n/**\n * Type for score values (0-100).\n */\nexport type Score = number\n","/**\n * Simplified token usage type for eval package.\n *\n * This is a subset of AI SDK's LanguageModelUsage that only includes\n * the properties eval actually tracks. The cost-helpers module handles\n * conversion when calling @agtlantis/core's pricing calculator.\n *\n * @example\n * ```typescript\n * const usage: EvalTokenUsage = {\n * inputTokens: 100,\n * outputTokens: 50,\n * totalTokens: 150,\n * }\n * ```\n */\nexport interface EvalTokenUsage {\n /** Number of input (prompt) tokens */\n inputTokens: number;\n /** Number of output (completion) tokens */\n outputTokens: number;\n /** Total tokens (input + output) */\n totalTokens: number;\n}\n\n/**\n * Simplified agent configuration for evaluation.\n * Only requires fields needed for eval purposes.\n *\n * For agents from `ai-agents` package with full AgentConfig,\n * use `toEvalAgent()` adapter to convert them.\n */\nexport interface EvalAgentConfig {\n /** Agent name for identification */\n name: string;\n /** Agent description (used by Judge for context) */\n description?: string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Agent prompt template.\n */\nexport interface AgentPrompt<TInput> {\n /** Prompt unique ID for version tracking */\n id: string;\n /** Version string (e.g., \"1.0.0\") */\n version: string;\n /** System prompt */\n system: string;\n /** User template string (for serialization/history) */\n userTemplate?: string;\n /** User prompt builder function */\n renderUserPrompt: (input: TInput) => string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Base metadata type shared by all LLM-using components (Agent, Judge, Improver).\n * Provides consistent structure for tracking token usage and model information.\n *\n * @example\n * ```typescript\n * const metadata: ComponentMetadata = {\n * tokenUsage: { inputTokens: 100, outputTokens: 50, totalTokens: 150 },\n * model: 'gpt-4o',\n * }\n * ```\n */\nexport interface ComponentMetadata {\n /** Token usage from the LLM call (AI SDK LanguageModelUsage format) */\n tokenUsage?: EvalTokenUsage;\n /** Model identifier used for the LLM call */\n model?: string;\n /** Additional custom fields */\n [key: string]: unknown;\n}\n\n/**\n * Agent execution result metadata.\n * Extends ComponentMetadata with agent-specific fields.\n */\nexport interface AgentMetadata extends ComponentMetadata {\n /** Prompt version used for execution */\n promptVersion?: string;\n /** Execution duration in milliseconds */\n duration?: number;\n}\n\n/**\n * Judge evaluation metadata.\n * Tracks token usage and model for cost calculation.\n */\nexport interface JudgeMetadata extends ComponentMetadata {}\n\n/**\n * Improver analysis metadata.\n * Tracks token usage and model for cost calculation.\n */\nexport interface ImproverMetadata extends ComponentMetadata {}\n\n/**\n * Agent execution result.\n */\nexport interface AgentResult<TOutput> {\n result: TOutput;\n metadata?: AgentMetadata;\n}\n\n/**\n * Simplified Agent interface for evaluation.\n *\n * @example\n * ```typescript\n * // Direct implementation\n * const myAgent: EvalAgent<string, string> = {\n * config: { name: 'MyAgent', description: 'A simple agent' },\n * prompt: { id: 'prompt-1', version: '1.0.0', system: '...', renderUserPrompt: (input) => input },\n * execute: async (input) => ({ result: `Processed: ${input}` })\n * }\n *\n * // Or adapt from full ai-agents Agent\n * const evalAgent = toEvalAgent(fullAgent)\n * ```\n */\nexport interface EvalAgent<TInput, TOutput> {\n readonly config: EvalAgentConfig;\n readonly prompt: AgentPrompt<TInput>;\n execute(input: TInput, options?: unknown): Promise<AgentResult<TOutput>>;\n}\n\n/**\n * Full AgentConfig interface (compatible with ai-agents package).\n * Used for type-safe adaptation.\n */\nexport interface FullAgentConfig {\n name: string;\n role: 'generator' | 'analyzer' | 'validator' | 'enhancer';\n streaming: 'required' | 'optional' | 'none';\n execution: 'batch' | 'realtime';\n conversation?: 'single-turn' | 'multi-turn';\n description?: string;\n [key: string]: unknown;\n}\n\n/**\n * Full Agent interface (compatible with ai-agents package).\n * Used for type-safe adaptation.\n */\nexport interface FullAgent<TInput, TOutput> {\n readonly config: FullAgentConfig;\n readonly prompt: AgentPrompt<TInput>;\n execute(\n input: TInput,\n options?: unknown\n ): Promise<{\n result: TOutput;\n metadata: {\n duration: number;\n promptVersion: string;\n tokenUsage?: EvalTokenUsage;\n model?: string;\n retryCount?: number;\n traceId?: string;\n [key: string]: unknown;\n };\n }>;\n}\n\n/**\n * Adapts a full Agent (from ai-agents) to EvalAgent for evaluation.\n * Extracts only the fields needed for evaluation.\n *\n * @example\n * ```typescript\n * import { scenarioGenerator } from './agents/mce'\n *\n * const evalAgent = toEvalAgent(scenarioGenerator)\n * const suite = createEvalSuite({ agent: evalAgent, ... })\n * ```\n */\nexport function toEvalAgent<TInput, TOutput>(\n agent: FullAgent<TInput, TOutput>\n): EvalAgent<TInput, TOutput> {\n return {\n config: {\n name: agent.config.name,\n description: agent.config.description,\n },\n prompt: agent.prompt,\n execute: async (input, options) => {\n const result = await agent.execute(input, options);\n return {\n result: result.result,\n metadata: result.metadata,\n };\n },\n };\n}\n\n/**\n * Metadata for file content.\n */\nexport interface FileContentMetadata {\n /** File size in bytes */\n size?: number;\n /** Full resolved path (for loaded files) */\n fullPath?: string;\n /** Whether the content was created inline (not from disk) */\n inline?: boolean;\n /** Additional custom metadata */\n [key: string]: unknown;\n}\n\nexport interface FileContent {\n /** File path (relative or absolute) - used as identifier */\n path: string;\n /** File content as string (text files only for Phase 5.3) */\n content: string;\n /** Optional MIME type hint (defaults to 'text/plain') */\n mediaType?: string;\n /** Optional encoding (defaults to 'utf-8') */\n encoding?: BufferEncoding;\n /** Optional metadata (e.g., original size, full path, etc.) */\n metadata?: FileContentMetadata;\n}\n\nexport interface TestCase<TInput> {\n id?: string;\n input: TInput;\n tags?: string[];\n description?: string;\n expectedOutput?: unknown; // Optional reference for checking\n /**\n * Optional file context for agent and judge (Phase 5.3).\n * Files are passed to Judge for evaluation context.\n * For Agent access, include files in the input type directly.\n *\n * @deprecated Use FileSource in input directly for flexible file handling\n */\n files?: FileContent[];\n}\n\nexport interface MetricsResult {\n latencyMs: number;\n tokenUsage: EvalTokenUsage;\n}\n\nexport interface Criterion {\n id: string;\n name: string;\n description: string;\n weight?: number;\n}\n\n/**\n * Zod error issue - minimal type compatible with ZodError.errors.\n * Using `readonly` and rest index to be compatible with Zod's discriminated union.\n */\nexport type ZodIssue = {\n readonly code: string;\n readonly path: readonly PropertyKey[];\n readonly message: string;\n};\n\n/**\n * Result of programmatic schema validation.\n */\nexport interface SchemaValidationResult {\n /** Whether the output matches the schema */\n valid: boolean;\n /** Validation errors if invalid (Zod issue format) */\n errors?: readonly ZodIssue[];\n /** Human-readable error summary */\n errorSummary?: string;\n}\n\n/**\n * Validator function type for programmatic validation.\n * Returns validation result with binary pass/fail outcome.\n */\nexport type ValidatorFn = (output: unknown) => SchemaValidationResult;\n\n/**\n * Extended criterion with optional programmatic validator.\n * Validators run before LLM evaluation with binary scoring (0 or 100).\n *\n * @example\n * ```typescript\n * import { z } from 'zod'\n * import { schema } from '@agtlantis/eval'\n *\n * const criterion = schema({\n * schema: z.object({ name: z.string() }),\n * weight: 2,\n * })\n * ```\n */\nexport interface ValidatorCriterion extends Criterion {\n /**\n * Optional programmatic validator.\n * If provided and fails, score is automatically 0.\n * If provided and passes, score is automatically 100.\n */\n validator?: ValidatorFn;\n}\n\nexport interface Verdict {\n criterionId: string;\n score: number; // 0-100\n reasoning: string;\n passed: boolean;\n}\n\nexport interface TestResult<TInput, TOutput> {\n testCase: TestCase<TInput>;\n output: TOutput;\n metrics: MetricsResult;\n error?: Error;\n}\n\nexport interface TestResultWithVerdict<TInput, TOutput> extends TestResult<TInput, TOutput> {\n verdicts: Verdict[];\n overallScore: number;\n passed: boolean;\n /** Judge metadata for cost tracking */\n judgeMetadata?: JudgeMetadata;\n}\n\n/**\n * Statistics from running the same test multiple times.\n * Used to measure consistency and reliability of LLM-based agents.\n */\nexport interface IterationStats {\n /** Total number of iterations run */\n iterations: number;\n /** Score from each iteration */\n scores: number[];\n /** Average score across all iterations */\n mean: number;\n /** Standard deviation (lower = more consistent) */\n stdDev: number;\n /** Lowest score achieved */\n min: number;\n /** Highest score achieved */\n max: number;\n /** Pass rate as decimal (0-1, e.g., 0.67 = 67%) */\n passRate: number;\n /** Number of iterations that passed */\n passCount: number;\n}\n\n/**\n * Extended iteration statistics for multi-turn tests.\n * Includes turn-count metrics and termination type distribution.\n *\n * @example\n * ```typescript\n * if (hasMultiTurnIterationData(result)) {\n * console.log(`Average turns: ${result.multiTurnIterationStats.avgTurns}`)\n * console.log(`Termination types: ${JSON.stringify(result.multiTurnIterationStats.terminationCounts)}`)\n * }\n * ```\n */\nexport interface MultiTurnIterationStats extends IterationStats {\n /** Average number of turns across all iterations */\n avgTurns: number;\n /** Minimum turns in any iteration */\n minTurns: number;\n /** Maximum turns in any iteration */\n maxTurns: number;\n /** Distribution of termination types across iterations (e.g., { condition: 2, maxTurns: 1 }) */\n terminationCounts: Record<string, number>;\n}\n\n/**\n * Discriminator for eval result types.\n * Used for exhaustive pattern matching on result variants.\n */\nexport type EvalResultKind =\n | 'single-turn'\n | 'single-turn-iterated'\n | 'multi-turn'\n | 'multi-turn-iterated';\n\n/**\n * Properties present when test ran with multiple iterations.\n * Extracted as a separate interface for composition.\n */\nexport interface IterationData<TInput, TOutput> {\n /** Aggregated statistics across all iterations */\n iterationStats: IterationStats;\n /** Individual results from each iteration */\n iterationResults: TestResultWithVerdict<TInput, TOutput>[];\n}\n\n/**\n * Single conversation entry in multi-turn tests.\n */\nexport interface ConversationEntry<TInput, TOutput> {\n /** Turn number (1-based) */\n turn: number;\n /** Input provided for this turn */\n input: TInput;\n /** Output from agent (undefined if execution failed) */\n output: TOutput | undefined;\n /** Agent execution metadata */\n metadata?: AgentMetadata;\n}\n\n/**\n * Termination info for multi-turn tests.\n * Compatible with TerminationCheckResult from multi-turn module.\n */\nexport interface TerminationInfo {\n /** Whether the conversation terminated */\n terminated: boolean;\n /** Human-readable reason for termination */\n reason: string;\n /** Type of termination (condition, maxTurns, error, exhausted) */\n terminationType?: string;\n /** The condition that caused termination (if applicable) */\n matchedCondition?: unknown;\n}\n\n/**\n * Properties present for multi-turn test results.\n * Extracted as a separate interface for composition.\n */\nexport interface MultiTurnData<TInput, TOutput> {\n /** Full conversation history */\n conversationHistory: ConversationEntry<TInput, TOutput>[];\n /** Total turns executed */\n totalTurns: number;\n /** Human-readable termination reason */\n terminationReason: string;\n /** Full termination check result */\n termination: TerminationInfo;\n}\n\n/**\n * Single-turn test result with single iteration (base case).\n * No iteration stats, no multi-turn data.\n */\nexport interface SingleTurnResult<TInput, TOutput> extends TestResultWithVerdict<TInput, TOutput> {\n readonly kind: 'single-turn';\n}\n\n/**\n * Single-turn test result with multiple iterations.\n * Has iteration stats but no multi-turn data.\n */\nexport interface SingleTurnIteratedResult<TInput, TOutput>\n extends TestResultWithVerdict<TInput, TOutput>, IterationData<TInput, TOutput> {\n readonly kind: 'single-turn-iterated';\n}\n\n/**\n * Multi-turn test result with single iteration.\n * Has multi-turn data but no iteration stats.\n */\nexport interface MultiTurnResult<TInput, TOutput>\n extends TestResultWithVerdict<TInput, TOutput>, MultiTurnData<TInput, TOutput> {\n readonly kind: 'multi-turn';\n}\n\n/**\n * Multi-turn test result with multiple iterations.\n * Has both multi-turn data and iteration stats.\n */\nexport interface MultiTurnIteratedResult<TInput, TOutput>\n extends\n TestResultWithVerdict<TInput, TOutput>,\n IterationData<TInput, TOutput>,\n MultiTurnData<TInput, TOutput> {\n readonly kind: 'multi-turn-iterated';\n /** Multi-turn specific iteration statistics */\n multiTurnIterationStats: MultiTurnIterationStats;\n}\n\n/**\n * Unified eval result type - discriminated union of all result kinds.\n *\n * Use pattern matching on `kind` for exhaustive handling:\n * @example\n * ```typescript\n * switch (result.kind) {\n * case 'single-turn':\n * // No iteration stats, no multi-turn data\n * break\n * case 'single-turn-iterated':\n * console.log(result.iterationStats.mean) // Type-safe\n * break\n * case 'multi-turn':\n * console.log(result.conversationHistory) // Type-safe\n * break\n * case 'multi-turn-iterated':\n * console.log(result.multiTurnIterationStats.avgTurns) // Type-safe\n * break\n * }\n * ```\n */\nexport type EvalTestResult<TInput, TOutput> =\n | SingleTurnResult<TInput, TOutput>\n | SingleTurnIteratedResult<TInput, TOutput>\n | MultiTurnResult<TInput, TOutput>\n | MultiTurnIteratedResult<TInput, TOutput>;\n\n/**\n * Check if result is from a single-turn test (either iterated or not).\n *\n * @example\n * ```typescript\n * if (isSingleTurnResult(result)) {\n * // result is SingleTurnResult | SingleTurnIteratedResult\n * console.log('Single turn test')\n * }\n * ```\n */\nexport function isSingleTurnResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is SingleTurnResult<TInput, TOutput> | SingleTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'single-turn' || result.kind === 'single-turn-iterated';\n}\n\n/**\n * Check if result is from a multi-turn test (either iterated or not).\n *\n * @example\n * ```typescript\n * if (isMultiTurnResult(result)) {\n * // result is MultiTurnResult | MultiTurnIteratedResult\n * console.log(`Turns: ${result.totalTurns}`) // Type-safe\n * for (const entry of result.conversationHistory) { // Type-safe\n * console.log(`Turn ${entry.turn}: ${entry.input}`)\n * }\n * }\n * ```\n */\nexport function isMultiTurnResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'multi-turn' || result.kind === 'multi-turn-iterated';\n}\n\n/**\n * Check if result has iteration data (multiple iterations ran).\n *\n * @example\n * ```typescript\n * if (isIteratedResult(result)) {\n * // result is SingleTurnIteratedResult | MultiTurnIteratedResult\n * console.log(`Mean score: ${result.iterationStats.mean}`) // Type-safe\n * console.log(`Pass rate: ${result.iterationStats.passRate}`) // Type-safe\n * }\n * ```\n */\nexport function isIteratedResult<TInput, TOutput>(\n result: EvalTestResult<TInput, TOutput>\n): result is SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> {\n return result.kind === 'single-turn-iterated' || result.kind === 'multi-turn-iterated';\n}\n","/**\n * Iteration statistics utilities for repeated test execution.\n *\n * These functions aggregate results from running the same test multiple times,\n * providing statistical metrics like mean, standard deviation, and pass rate.\n */\n\nimport type {\n EvalTestResult,\n IterationStats,\n MultiTurnIteratedResult,\n MultiTurnResult,\n MultiTurnIterationStats,\n SingleTurnIteratedResult,\n SingleTurnResult,\n TestResultWithVerdict,\n} from './types.js'\nimport { isMultiTurnResult } from './types.js'\nimport { EvalError, EvalErrorCode } from './errors'\nimport { SCORE } from './constants'\n\n/**\n * Calculate iteration statistics from multiple test results.\n *\n * @param results - Results from running the same test multiple times\n * @returns Aggregated statistics including mean, stdDev, and passRate\n *\n * @example\n * ```typescript\n * const stats = calculateIterationStats([\n * { overallScore: 85, passed: true, ... },\n * { overallScore: 90, passed: true, ... },\n * { overallScore: 80, passed: true, ... },\n * ])\n * // stats.mean = 85\n * // stats.stdDev ≈ 4.08\n * // stats.passRate = 1.0\n * ```\n */\nexport function calculateIterationStats(\n results: TestResultWithVerdict<unknown, unknown>[]\n): IterationStats {\n if (results.length === 0) {\n return {\n iterations: 0,\n scores: [],\n mean: 0,\n stdDev: 0,\n min: 0,\n max: 0,\n passRate: 0,\n passCount: 0,\n }\n }\n\n const scores = results.map((r) => r.overallScore)\n const passCount = results.filter((r) => r.passed).length\n\n const mean = scores.reduce((sum, s) => sum + s, 0) / scores.length\n\n // Population standard deviation (not sample)\n const variance =\n scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length\n const stdDev = Math.sqrt(variance)\n\n return {\n iterations: results.length,\n scores,\n mean,\n stdDev,\n min: Math.min(...scores),\n max: Math.max(...scores),\n passRate: passCount / results.length,\n passCount,\n }\n}\n\n/**\n * Calculate multi-turn specific iteration statistics.\n *\n * Extends base iteration stats with turn counts and termination type distribution.\n * Used when aggregating multiple iterations of multi-turn tests.\n *\n * @param results - Results from running the same multi-turn test multiple times\n * @returns Extended statistics including avgTurns, min/max turns, and terminationCounts\n *\n * @example\n * ```typescript\n * const stats = calculateMultiTurnIterationStats(results)\n * // stats.avgTurns = 4.2\n * // stats.minTurns = 3\n * // stats.maxTurns = 6\n * // stats.terminationCounts = { condition: 2, maxTurns: 1 }\n * ```\n */\nexport function calculateMultiTurnIterationStats<TInput, TOutput>(\n results: (MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[]\n): MultiTurnIterationStats {\n const baseStats = calculateIterationStats(results)\n\n // Extract turns from results (all multi-turn results have totalTurns)\n const turns = results.map((r) => r.totalTurns)\n\n // Count termination types from termination.terminationType\n const terminationCounts: Record<string, number> = {}\n for (const r of results) {\n const type = r.termination.terminationType\n if (type) {\n terminationCounts[type] = (terminationCounts[type] || 0) + 1\n }\n }\n\n return {\n ...baseStats,\n avgTurns: turns.length > 0 ? turns.reduce((a, b) => a + b, 0) / turns.length : 0,\n minTurns: turns.length > 0 ? Math.min(...turns) : 0,\n maxTurns: turns.length > 0 ? Math.max(...turns) : 0,\n terminationCounts,\n }\n}\n\n/**\n * Select the result closest to the mean score.\n * Used to pick a \"representative\" result for displaying verdicts/reasoning.\n *\n * The function preserves the full type of the input array, so if you pass\n * `TestResultWithIteration[]`, you get back `TestResultWithIteration`.\n *\n * @param results - Array of results to choose from (must not be empty)\n * @param mean - The mean score to compare against\n * @returns The result with overallScore closest to mean\n * @throws Error if results array is empty\n */\nexport function selectRepresentativeResult<\n TInput,\n TOutput,\n T extends TestResultWithVerdict<TInput, TOutput> = TestResultWithVerdict<TInput, TOutput>,\n>(results: T[], mean: number): T {\n if (results.length === 0) {\n throw new EvalError('Cannot select representative result from empty array', {\n code: EvalErrorCode.UNKNOWN_ERROR,\n })\n }\n\n return results.reduce((closest, current) => {\n const closestDiff = Math.abs(closest.overallScore - mean)\n const currentDiff = Math.abs(current.overallScore - mean)\n return currentDiff < closestDiff ? current : closest\n })\n}\n\n/**\n * Aggregate results from multiple iteration runs into iterated result types.\n *\n * Takes N arrays of results (one per iteration) and groups them by test case,\n * calculating iteration statistics for each test case.\n *\n * For multi-turn tests, returns MultiTurnIteratedResult with multi-turn specific\n * statistics like average turns, min/max turns, and termination type distribution.\n *\n * For single-turn tests, returns SingleTurnIteratedResult with base iteration stats.\n *\n * @param allIterationResults - Array of arrays: outer = iterations, inner = test cases\n * @returns Aggregated results with iteration statistics\n *\n * @example\n * ```typescript\n * // 3 iterations, 2 test cases each\n * const allResults = [\n * [testCase1_iter1, testCase2_iter1], // iteration 1\n * [testCase1_iter2, testCase2_iter2], // iteration 2\n * [testCase1_iter3, testCase2_iter3], // iteration 3\n * ]\n *\n * const aggregated = aggregateIterationResults(allResults)\n * // aggregated[0] = testCase1 with stats from iter1, iter2, iter3\n * // aggregated[1] = testCase2 with stats from iter1, iter2, iter3\n *\n * // For multi-turn tests:\n * // aggregated[0].kind === 'multi-turn-iterated'\n * // aggregated[0].multiTurnIterationStats = { avgTurns, minTurns, maxTurns, terminationCounts }\n * ```\n */\nexport function aggregateIterationResults<TInput, TOutput>(\n allIterationResults: EvalTestResult<TInput, TOutput>[][]\n): (SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[] {\n if (allIterationResults.length === 0) {\n return []\n }\n\n const testCount = allIterationResults[0].length\n const aggregated: (SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>)[] = []\n\n for (let i = 0; i < testCount; i++) {\n const resultsForTestCase = allIterationResults.map((iteration) => iteration[i])\n const stats = calculateIterationStats(resultsForTestCase)\n const representative = selectRepresentativeResult(resultsForTestCase, stats.mean)\n const isMultiTurn = resultsForTestCase.some((r) => isMultiTurnResult(r))\n const passedByMajority = stats.passRate >= SCORE.MAJORITY_PASS_THRESHOLD\n\n if (isMultiTurn) {\n const multiTurnResults = resultsForTestCase.filter(\n (r): r is MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput> =>\n isMultiTurnResult(r)\n )\n const multiTurnRep = representative as MultiTurnResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>\n\n const aggregatedResult: MultiTurnIteratedResult<TInput, TOutput> = {\n kind: 'multi-turn-iterated',\n testCase: multiTurnRep.testCase,\n output: multiTurnRep.output,\n metrics: multiTurnRep.metrics,\n verdicts: multiTurnRep.verdicts,\n error: multiTurnRep.error,\n overallScore: stats.mean,\n passed: passedByMajority,\n iterationStats: stats,\n iterationResults: resultsForTestCase,\n conversationHistory: multiTurnRep.conversationHistory,\n totalTurns: multiTurnRep.totalTurns,\n terminationReason: multiTurnRep.terminationReason,\n termination: multiTurnRep.termination,\n multiTurnIterationStats: calculateMultiTurnIterationStats(multiTurnResults),\n }\n aggregated.push(aggregatedResult)\n } else {\n const aggregatedResult: SingleTurnIteratedResult<TInput, TOutput> = {\n kind: 'single-turn-iterated',\n testCase: representative.testCase,\n output: representative.output,\n metrics: representative.metrics,\n verdicts: representative.verdicts,\n error: representative.error,\n overallScore: stats.mean,\n passed: passedByMajority,\n iterationStats: stats,\n iterationResults: resultsForTestCase,\n }\n aggregated.push(aggregatedResult)\n }\n }\n\n return aggregated\n}\n\ntype IteratedResult<TInput, TOutput> = SingleTurnIteratedResult<TInput, TOutput> | MultiTurnIteratedResult<TInput, TOutput>\n\nfunction filterIteratedResults<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): IteratedResult<TInput, TOutput>[] {\n return results.filter(\n (r): r is IteratedResult<TInput, TOutput> =>\n r.kind === 'single-turn-iterated' || r.kind === 'multi-turn-iterated'\n )\n}\n\nfunction averageIterationStat<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[],\n selector: (stats: IterationStats) => number\n): number | undefined {\n const iteratedResults = filterIteratedResults(results)\n if (iteratedResults.length === 0) {\n return undefined\n }\n const total = iteratedResults.reduce((sum, r) => sum + selector(r.iterationStats), 0)\n return total / iteratedResults.length\n}\n\n/**\n * Calculate average standard deviation across multiple test results.\n * Used for report summary.\n *\n * @param results - Eval results (only iterated results have stats)\n * @returns Average stdDev across all iterated tests, or undefined if no iteration data\n */\nexport function calculateAvgStdDev<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): number | undefined {\n return averageIterationStat(results, (stats) => stats.stdDev)\n}\n\n/**\n * Calculate average pass rate across multiple test results.\n * Used for report summary.\n *\n * @param results - Eval results (only iterated results have stats)\n * @returns Average passRate across all iterated tests, or undefined if no iteration data\n */\nexport function calculateAvgPassRate<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[]\n): number | undefined {\n return averageIterationStat(results, (stats) => stats.passRate)\n}\n","import type {\n EvalAgent,\n EvalTestResult,\n TestCase,\n TestResultWithVerdict,\n} from './types'\nimport type { Judge } from '@/judge/types'\nimport type { Improver, AggregatedMetrics, Suggestion } from '@/improver/types'\nimport type { EvalReport, ReportSummary } from '@/reporter/types'\nimport { runWithConcurrency, type RunOptions } from './runner'\nimport {\n aggregateIterationResults,\n calculateAvgPassRate,\n calculateAvgStdDev,\n} from './iteration'\nimport { EvalError, EvalErrorCode } from './errors'\n\nexport type { RunOptions } from './runner'\n\n/**\n * Configuration for creating an EvalSuite.\n *\n * @example\n * ```typescript\n * const suite = createEvalSuite({\n * agent: myAgent,\n * judge: myJudge,\n * agentDescription: 'Recommends career paths based on student profiles',\n * })\n * ```\n */\nexport interface EvalSuiteConfig<TInput, TOutput> {\n /** The agent to evaluate */\n agent: EvalAgent<TInput, TOutput>\n\n /** Human-readable description of what the agent does (used by Judge) */\n agentDescription?: string\n\n /** Judge instance for evaluating agent outputs */\n judge: Judge\n\n /** Improver instance for generating prompt improvement suggestions (optional) */\n improver?: Improver\n}\n\n/**\n * Evaluation suite for running test cases against an agent.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases, { concurrency: 3 })\n * console.log(reportToMarkdown(report))\n *\n * // Test with a different agent\n * const newReport = await suite.withAgent(improvedAgent).run(testCases)\n * ```\n */\nexport interface EvalSuite<TInput, TOutput> {\n /**\n * Run test cases and generate an evaluation report.\n *\n * @param testCases - Test cases to run\n * @param options - Run options (concurrency, stopOnFirstFailure, signal)\n * @returns Evaluation report with results, summary, and suggestions\n */\n run(\n testCases: TestCase<TInput>[],\n options?: RunOptions\n ): Promise<EvalReport<TInput, TOutput>>\n\n /**\n * Create a new suite with a different agent.\n * Useful for A/B testing or testing prompt improvements.\n *\n * @param agent - New agent to use\n * @returns New EvalSuite instance with the updated agent\n */\n withAgent(agent: EvalAgent<TInput, TOutput>): EvalSuite<TInput, TOutput>\n}\n\n/**\n * Calculate aggregated metrics from test results.\n * @internal\n *\n * Cost calculation is done via post-processing utilities (Phase 11).\n * Use calculateReportCosts() or addCostsToResults() from pricing module.\n */\nfunction calculateAggregatedMetrics<TInput, TOutput>(\n results: TestResultWithVerdict<TInput, TOutput>[]\n): AggregatedMetrics {\n if (results.length === 0) {\n return { avgLatencyMs: 0, totalTokens: 0 }\n }\n\n const totalLatencyMs = sumBy(results, (r) => r.metrics.latencyMs)\n const totalTokens = sumBy(results, (r) => r.metrics.tokenUsage.totalTokens)\n\n return {\n avgLatencyMs: totalLatencyMs / results.length,\n totalTokens,\n }\n}\n\nfunction sumBy<T>(items: T[], selector: (item: T) => number): number {\n return items.reduce((sum, item) => sum + selector(item), 0)\n}\n\n/** @internal */\nfunction calculateSummary<TInput, TOutput>(\n results: EvalTestResult<TInput, TOutput>[],\n iterations?: number\n): ReportSummary {\n const metrics = calculateAggregatedMetrics(results)\n const passedCount = results.filter((r) => r.passed).length\n const failedCount = results.length - passedCount\n const avgScore = results.length > 0\n ? sumBy(results, (r) => r.overallScore) / results.length\n : 0\n\n const summary: ReportSummary = {\n totalTests: results.length,\n passed: passedCount,\n failed: failedCount,\n avgScore,\n metrics,\n }\n\n const hasMultipleIterations = iterations && iterations > 1\n if (hasMultipleIterations) {\n summary.iterations = iterations\n summary.avgStdDev = calculateAvgStdDev(results)\n summary.avgPassRate = calculateAvgPassRate(results)\n }\n\n return summary\n}\n\n/**\n * Create an evaluation suite for testing an agent.\n *\n * The suite orchestrates test execution, evaluation, and optional\n * prompt improvement suggestions.\n *\n * @example\n * ```typescript\n * const suite = createEvalSuite({\n * agent: scenarioGenerator,\n * agentDescription: 'Recommends majors based on student profiles',\n * judge: createJudge({\n * llm: openaiClient,\n * prompt: defaultJudgePrompt,\n * criteria: [accuracy(), relevance()],\n * }),\n * })\n *\n * const report = await suite.run(testCases, { concurrency: 3 })\n * ```\n */\nexport function createEvalSuite<TInput, TOutput>(\n config: EvalSuiteConfig<TInput, TOutput>\n): EvalSuite<TInput, TOutput> {\n const { agent, agentDescription, judge, improver } = config\n const description = agentDescription ?? agent.config.description ?? agent.config.name\n\n const suite: EvalSuite<TInput, TOutput> = {\n async run(\n testCases: TestCase<TInput>[],\n options?: RunOptions\n ): Promise<EvalReport<TInput, TOutput>> {\n const iterations = options?.iterations ?? 1\n validateIterations(iterations)\n\n const executeContext = { agent, judge, agentDescription: description }\n const results = iterations <= 1\n ? await runWithConcurrency<TInput, TOutput>(testCases, executeContext, options)\n : await runMultipleIterations(testCases, executeContext, options, iterations)\n\n const summary = calculateSummary(results, iterations > 1 ? iterations : undefined)\n const suggestions = improver\n ? (await improver.improve(agent.prompt, results)).suggestions\n : []\n\n return {\n summary,\n results,\n suggestions,\n generatedAt: new Date(),\n promptVersion: agent.prompt.version,\n }\n },\n\n withAgent(newAgent: EvalAgent<TInput, TOutput>): EvalSuite<TInput, TOutput> {\n return createEvalSuite({\n ...config,\n agent: newAgent,\n agentDescription: undefined,\n })\n },\n }\n\n return suite\n}\n\nfunction validateIterations(iterations: number): void {\n if (iterations < 1 || !Number.isInteger(iterations)) {\n throw new EvalError(\n `Invalid iterations value: ${iterations}. Must be a positive integer.`,\n { code: EvalErrorCode.INVALID_CONFIG, context: { iterations } }\n )\n }\n}\n\nasync function runMultipleIterations<TInput, TOutput>(\n testCases: TestCase<TInput>[],\n executeContext: { agent: EvalAgent<TInput, TOutput>; judge: Judge; agentDescription: string },\n options: RunOptions | undefined,\n iterations: number\n): Promise<EvalTestResult<TInput, TOutput>[]> {\n const allIterationResults: EvalTestResult<TInput, TOutput>[][] = []\n\n for (let i = 0; i < iterations; i++) {\n const iterationResults = await runWithConcurrency<TInput, TOutput>(\n testCases,\n executeContext,\n { ...options, iterations: undefined }\n )\n allIterationResults.push(iterationResults)\n }\n\n return aggregateIterationResults(allIterationResults)\n}\n","/**\n * agent-eval - LLM-as-Judge based AI Agent testing library\n *\n * @example\n * ```typescript\n * import {\n * createEvalSuite,\n * createJudge,\n * createOpenAIClient,\n * accuracy,\n * relevance,\n * } from 'agent-eval'\n *\n * const openai = createOpenAIClient({\n * apiKey: process.env.OPENAI_API_KEY,\n * defaultModel: 'gpt-5-nano',\n * reasoningEffort: 'minimal',\n * })\n *\n * const judge = createJudge({\n * llm: openai,\n * criteria: [accuracy(), relevance()],\n * })\n *\n * const suite = createEvalSuite({\n * agent: myAgent,\n * judge,\n * agentDescription: 'Recommends careers based on student profiles',\n * })\n *\n * const report = await suite.run(testCases, { concurrency: 3 })\n * console.log(report.summary)\n * ```\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Suite - Main Entry Point\n// ============================================================================\n\nexport {\n createEvalSuite,\n type EvalSuiteConfig,\n type EvalSuite,\n type RunOptions,\n} from '@/core/suite';\n\n// ============================================================================\n// Runner - Low-level Execution\n// ============================================================================\n\nexport { executeTestCase, runWithConcurrency, type ExecuteContext } from '@/core/runner';\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\nexport type {\n // Token usage\n EvalTokenUsage,\n // Agent types\n EvalAgent,\n EvalAgentConfig,\n AgentPrompt,\n AgentResult,\n AgentMetadata,\n // Component metadata types (Phase 10)\n ComponentMetadata,\n JudgeMetadata,\n ImproverMetadata,\n // Test types\n TestCase,\n TestResult,\n TestResultWithVerdict,\n MetricsResult,\n // Iteration types (Phase 6.2)\n IterationStats,\n IterationData,\n // Multi-turn iteration types (Phase 7.2)\n MultiTurnIterationStats,\n // Eval result types (Discriminated Union)\n EvalResultKind,\n EvalTestResult,\n SingleTurnResult,\n SingleTurnIteratedResult,\n MultiTurnResult,\n MultiTurnIteratedResult,\n ConversationEntry,\n TerminationInfo,\n MultiTurnData,\n // Evaluation types\n Verdict,\n Criterion,\n // Schema validation types (Phase 6.3)\n SchemaValidationResult,\n ValidatorFn,\n ValidatorCriterion,\n ZodIssue,\n // File context types (Phase 5.3)\n FileContent,\n FileContentMetadata,\n} from '@/core/types';\n\nexport {\n toEvalAgent,\n // Type guards for EvalTestResult\n isSingleTurnResult,\n isMultiTurnResult,\n isIteratedResult,\n} from '@/core/types';\n\n// ============================================================================\n// FileSource (Embedded Files in Input)\n// ============================================================================\n\nexport {\n // Resolver\n resolveFileSource,\n resolveFileSourcesInInput,\n // Scanner\n scanForFileSources,\n // Display info\n getFileSourceDisplayInfo,\n getFileSourcesDisplayInfo,\n // Utilities\n inferMediaType,\n // Type guards\n isFileSource,\n isFileSourcePath,\n isFileSourceData,\n isFileSourceBase64,\n isFileSourceUrl,\n // Types\n type FileSource,\n type FileSourcePath,\n type FileSourceData,\n type FileSourceBase64,\n type FileSourceUrl,\n type FoundFileSource,\n type FileSourceDisplayInfo,\n type ResolveOptions,\n} from '@agtlantis/core';\n\n// ============================================================================\n// Iteration Utilities (Phase 6.2, 7.2)\n// ============================================================================\n\nexport {\n calculateIterationStats,\n calculateMultiTurnIterationStats,\n selectRepresentativeResult,\n aggregateIterationResults,\n calculateAvgStdDev,\n calculateAvgPassRate,\n} from '@/core/iteration';\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nexport { EvalError, EvalErrorCode, type EvalErrorOptions } from '@/core/errors';\n\n// ============================================================================\n// Judge\n// ============================================================================\n\nexport {\n createJudge,\n // Criteria\n accuracy,\n consistency,\n relevance,\n schema,\n type CriterionOptions,\n type SchemaOptions,\n // Types\n type Judge,\n type JudgeConfig,\n type JudgeContext,\n type JudgePrompt,\n // Context-based API types (Phase 5.3)\n type EvalContext,\n type JudgeResult,\n} from '@/judge/index';\n\n// ============================================================================\n// Reporter\n// ============================================================================\n\nexport type {\n EvalReport,\n ReportSummary,\n ReportMarkdownOptions,\n ReportComparison,\n} from '@/reporter/types';\n\nexport { reportToMarkdown, saveReportMarkdown, compareReports } from '@/reporter/markdown';\n\n// Reporter classes\nexport {\n JsonReporter,\n MarkdownReporter,\n ConsoleReporter,\n CompositeReporter,\n type MarkdownReporterOptions,\n} from '@/reporter';\n\n// Reporter factory functions\nexport {\n createJsonReporter,\n createMarkdownReporter,\n createConsoleReporter,\n createCompositeReporter,\n createDefaultReporter,\n} from '@/reporter';\n\n// Report runner (convenience wrapper)\nexport { createReportRunner, type ReportRunnerOptions } from '@/reporter';\n\n// Reporter types\nexport type {\n Reporter,\n FileReporterOptions,\n ConsoleReporterOptions,\n LogVerbosity,\n} from '@/reporter';\n\n// ImprovementCycleResult helpers\nexport {\n saveCycleJson,\n logCycle,\n cycleToMarkdown,\n saveCycleMarkdown,\n type SaveCycleJsonOptions,\n type LogCycleOptions,\n type CycleMarkdownOptions,\n} from '@/reporter';\n\n// ============================================================================\n// Improver\n// ============================================================================\n\nexport {\n createImprover,\n // Utility functions\n suggestionDiff,\n suggestionPreview,\n suggestionSummary,\n applyPromptSuggestions,\n bumpVersion,\n // Types\n type Suggestion,\n type AggregatedMetrics,\n type Improver,\n type ImproverConfig,\n type ImproverPrompt,\n type ImproverContext,\n type ApplyPromptSuggestionsOptions,\n type ApplySuggestionsResult,\n // Phase 10 - ImproveResult with metadata\n type ImproveResult,\n} from '@/improver/index';\n\n// ============================================================================\n// Testing Utilities\n// ============================================================================\n\n// Re-export core testing mock utilities\nexport { mock, MockProvider } from '@agtlantis/core/testing';\nexport type { MockCall } from '@agtlantis/core/testing';\n\n// Agent/Judge/Improver mocks\nexport {\n createMockAgent,\n createMockJudge,\n createMockImprover,\n type MockAgentConfig,\n type MockJudgeConfig,\n type MockImproverConfig,\n} from '@/testing/mock-agent';\n\n// ============================================================================\n// Prompt (from @agtlantis/core)\n// ============================================================================\n\nexport {\n compileTemplate,\n createFilePromptRepository,\n type FilePromptRepositoryOptions,\n type FileSystem,\n type PromptTemplate,\n type PromptRepository,\n} from '@agtlantis/core';\n\n// ============================================================================\n// Multi-turn Testing\n// ============================================================================\n\n// Types\nexport type {\n ConversationContext,\n FieldsCondition,\n FieldSetCondition,\n FieldValueCondition,\n ContinueResult,\n CustomCondition,\n FollowUpInput,\n MaxTurnsCondition,\n MultiTurnTestCase,\n MultiTurnTestResult,\n NaturalLanguageConditionOptions,\n TerminatedResult,\n TerminationCheckResult,\n TerminationCondition,\n MultiTurnExecuteContext,\n MultiTurnExecuteOptions,\n} from '@/multi-turn/index';\n\n// Type guards\nexport {\n isCustomCondition,\n isFieldSetCondition,\n isFieldValueCondition,\n isMaxTurnsCondition,\n isMultiTurnTestCase,\n isTerminated,\n} from '@/multi-turn/index';\n\n// Termination utilities\nexport { checkCondition, checkTermination, getFieldValue } from '@/multi-turn/index';\n\n// Condition factory functions\nexport {\n afterTurns,\n and,\n fieldEquals,\n fieldIsSet,\n naturalLanguage,\n not,\n or,\n} from '@/multi-turn/index';\n\n// Runner\nexport { executeMultiTurnTestCase } from '@/multi-turn/index';\n\n// AI User\nexport { aiUser, type AIUserOptions } from '@/multi-turn/index';\n\n// ============================================================================\n// Cost Calculation (re-export from reporter/cost-helpers)\n// ============================================================================\n\nexport {\n calculateResultCost,\n calculateReportCosts,\n addCostsToResults,\n type CostBreakdown,\n type CostSummary,\n type MetricsWithCost,\n type TestResultWithCost,\n type EvalPricingConfig,\n} from '@/reporter/cost-helpers';\n\n// Re-export core pricing utilities for convenience\nexport {\n calculateCostFromUsage,\n OPENAI_PRICING,\n GOOGLE_PRICING,\n ANTHROPIC_PRICING,\n DEFAULT_PRICING_CONFIG,\n type PricingConfig,\n type ModelPricing,\n type CostResult,\n} from '@agtlantis/core';\n\n// ============================================================================\n// CLI Configuration\n// ============================================================================\n\nexport {\n defineConfig,\n type EvalConfig,\n type LLMConfig,\n type CLIJudgeConfig,\n type CLIImproverConfig,\n type OutputConfig,\n type RunConfig,\n type CLITestCase,\n type CLISingleTurnTestCase,\n type CLIMultiTurnTestCase,\n} from '@/cli/config/types';\n\nexport { discoverEvalFiles, type DiscoverOptions } from '@/cli/config/loader';\n\n// ============================================================================\n// Improvement Cycle (Automated Prompt Refinement)\n// ============================================================================\n\n// Types\nexport type {\n // Termination conditions\n TargetScoreCondition,\n MaxRoundsCondition,\n NoImprovementCondition,\n MaxCostCondition,\n CustomCycleCondition,\n CycleTerminationCondition,\n // Context and results\n CycleContext,\n CycleContinueResult,\n CycleTerminatedResult,\n CycleTerminationResult,\n // Round types\n RoundYield,\n RoundDecision,\n RoundCost,\n RoundResult,\n // Serialization\n SerializedPrompt,\n SerializedRoundResult,\n // History and config\n ImprovementHistory,\n HistoryConfig,\n ImprovementCycleConfig,\n ImprovementCycleOptions,\n ImprovementCycleResult,\n HistoryStorage,\n ImprovementSession,\n SessionConfig,\n} from '@/improvement-cycle';\n\n// Type guards\nexport {\n isTargetScoreCondition,\n isMaxRoundsCondition,\n isNoImprovementCondition,\n isMaxCostCondition,\n isCustomCycleCondition,\n isCycleTerminated,\n} from '@/improvement-cycle';\n\n// Condition utilities\nexport { checkCycleCondition, checkCycleTermination } from '@/improvement-cycle';\n\n// Condition factory functions\nexport {\n targetScore,\n maxRounds,\n noImprovement,\n maxCost,\n customCondition,\n // Composite conditions\n and as cycleAnd,\n or as cycleOr,\n not as cycleNot,\n} from '@/improvement-cycle';\n\n// Runner\nexport { runImprovementCycle, runImprovementCycleAuto } from '@/improvement-cycle';\n\n// History/Persistence\nexport {\n createSession,\n resumeSession,\n loadHistory,\n saveHistory,\n serializePrompt,\n deserializePrompt,\n defaultHistoryStorage,\n} from '@/improvement-cycle';\n\n// ============================================================================\n// Test Case Utilities\n// ============================================================================\n\nexport {\n TestCaseCollection,\n testCase,\n testCases,\n type RandomOptions,\n} from '@/core/test-case-collection';\n","import { type LanguageModelUsage, type ModelMessage, Output } from 'ai';\nimport { z } from 'zod';\n\nimport { SCORE } from '@/core/constants.js';\nimport { EvalError, EvalErrorCode } from '@/core/errors.js';\nimport type {\n Criterion,\n EvalTokenUsage,\n JudgeMetadata,\n ValidatorCriterion,\n Verdict,\n} from '@/core/types.js';\n\nimport { defaultJudgePrompt } from './prompts/default.js';\nimport type { EvalContext, Judge, JudgeConfig, JudgeContext, JudgeResult } from './types.js';\n\nfunction toEvalTokenUsage(usage: LanguageModelUsage): EvalTokenUsage {\n return {\n inputTokens: usage.inputTokens ?? 0,\n outputTokens: usage.outputTokens ?? 0,\n totalTokens: usage.totalTokens ?? 0,\n };\n}\n\nfunction hasValidator(criterion: Criterion): criterion is ValidatorCriterion {\n return (\n 'validator' in criterion &&\n typeof (criterion as ValidatorCriterion).validator === 'function'\n );\n}\n\nconst JudgeResponseSchema = z.object({\n verdicts: z.array(\n z.object({\n criterionId: z.string(),\n score: z.number().min(SCORE.MIN).max(SCORE.MAX),\n reasoning: z.string(),\n passed: z.boolean().optional(),\n })\n ),\n});\n\ntype JudgeResponse = z.infer<typeof JudgeResponseSchema>;\n\nfunction validateAllCriteriaHaveVerdicts(\n verdicts: JudgeResponse['verdicts'],\n criteriaIds: string[]\n): void {\n const providedIds = new Set(verdicts.map((v) => v.criterionId));\n const missingIds = criteriaIds.filter((id) => !providedIds.has(id));\n\n if (missingIds.length > 0) {\n throw new EvalError('Judge response missing verdicts for some criteria', {\n code: EvalErrorCode.VERDICT_PARSE_ERROR,\n context: { missingCriteriaIds: missingIds, providedIds: [...providedIds] },\n });\n }\n}\n\nfunction calculateOverallScore(verdicts: Verdict[], criteriaWeights: Map<string, number>): number {\n let totalWeight = 0;\n let weightedSum = 0;\n\n for (const verdict of verdicts) {\n const weight = criteriaWeights.get(verdict.criterionId) ?? 1;\n weightedSum += verdict.score * weight;\n totalWeight += weight;\n }\n\n if (totalWeight === 0) {\n return 0;\n }\n\n return Math.round((weightedSum / totalWeight) * 100) / 100;\n}\n\nfunction runValidatorCriteria(validatorCriteria: ValidatorCriterion[], output: unknown): Verdict[] {\n return validatorCriteria.map((criterion) => {\n const result = criterion.validator!(output);\n\n if (result.valid) {\n return {\n criterionId: criterion.id,\n score: 100,\n reasoning: `${criterion.name} 통과`,\n passed: true,\n };\n }\n\n return {\n criterionId: criterion.id,\n score: 0,\n reasoning: `${criterion.name} 실패:\\n${result.errorSummary ?? '유효성 검증 오류'}`,\n passed: false,\n };\n });\n}\n\nasync function runLLMEvaluation(\n provider: JudgeConfig['provider'],\n prompt: NonNullable<JudgeConfig['prompt']>,\n context: JudgeContext,\n llmCriteriaIds: string[],\n passThreshold: number\n): Promise<{ verdicts: Verdict[]; usage?: LanguageModelUsage }> {\n const messages: ModelMessage[] = [\n { role: 'system', content: prompt.system },\n { role: 'user', content: prompt.renderUserPrompt(context) },\n ];\n\n let response: JudgeResponse;\n let usage: LanguageModelUsage | undefined;\n\n try {\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages,\n output: Output.object({ schema: JudgeResponseSchema }),\n });\n return result.output!;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n response = executionResult.value;\n usage = executionResult.summary.totalLLMUsage;\n } catch (cause) {\n throw EvalError.from(cause, EvalErrorCode.LLM_API_ERROR, {\n promptId: prompt.id,\n promptVersion: prompt.version,\n });\n }\n\n validateAllCriteriaHaveVerdicts(response.verdicts, llmCriteriaIds);\n\n const verdicts: Verdict[] = response.verdicts.map((v) => ({\n criterionId: v.criterionId,\n score: v.score,\n reasoning: v.reasoning,\n passed: v.passed ?? v.score >= passThreshold,\n }));\n\n return { verdicts, usage };\n}\n\n/**\n * Creates an LLM-as-Judge evaluator.\n *\n * @example\n * ```typescript\n * import { createJudge, defaultJudgePrompt, accuracy, consistency } from 'agent-eval'\n * import { createGoogleProvider } from '@agtlantis/core'\n *\n * const provider = createGoogleProvider({ apiKey }).withDefaultModel('gemini-2.5-flash')\n *\n * const judge = createJudge({\n * provider,\n * prompt: defaultJudgePrompt,\n * criteria: [accuracy(), consistency()],\n * passThreshold: 70,\n * })\n *\n * const result = await judge.evaluate({\n * input: { query: 'What is 2+2?' },\n * output: { answer: '4' },\n * agentDescription: 'A math tutor agent',\n * files: [{ path: 'reference.md', content: '...' }],\n * })\n *\n * console.log(result.overallScore) // e.g., 85\n * console.log(result.passed) // true\n * ```\n */\nexport function createJudge(config: JudgeConfig): Judge {\n const {\n provider,\n prompt = defaultJudgePrompt,\n criteria,\n passThreshold = SCORE.DEFAULT_PASS_THRESHOLD,\n model,\n } = config;\n\n const validatorCriteria: ValidatorCriterion[] = [];\n const llmCriteria: Criterion[] = [];\n const criteriaWeights = new Map<string, number>();\n const llmCriteriaIds: string[] = [];\n\n for (const c of criteria) {\n criteriaWeights.set(c.id, c.weight ?? 1);\n\n if (hasValidator(c)) {\n validatorCriteria.push(c);\n } else {\n llmCriteria.push(c);\n llmCriteriaIds.push(c.id);\n }\n }\n\n return {\n async evaluate(evalContext: EvalContext): Promise<JudgeResult> {\n const { input, output, agentDescription, files } = evalContext;\n\n const validatorVerdicts = runValidatorCriteria(validatorCriteria, output);\n\n let llmVerdicts: Verdict[] = [];\n let llmUsage: LanguageModelUsage | undefined;\n\n if (llmCriteria.length > 0) {\n const context: JudgeContext = {\n agentDescription,\n input,\n output,\n criteria: llmCriteria,\n files,\n };\n\n const llmResult = await runLLMEvaluation(\n provider,\n prompt,\n context,\n llmCriteriaIds,\n passThreshold\n );\n llmVerdicts = llmResult.verdicts;\n llmUsage = llmResult.usage;\n }\n\n const allVerdicts: Verdict[] = [...validatorVerdicts, ...llmVerdicts];\n const overallScore = calculateOverallScore(allVerdicts, criteriaWeights);\n const passed = overallScore >= passThreshold;\n\n const metadata: JudgeMetadata | undefined = llmUsage\n ? { tokenUsage: toEvalTokenUsage(llmUsage), model }\n : undefined;\n\n return {\n verdicts: allVerdicts,\n overallScore,\n passed,\n metadata,\n };\n },\n };\n}\n","import type { JudgeContext, JudgePrompt } from '../types';\n\nexport const defaultJudgePrompt: JudgePrompt = {\n id: 'default-judge',\n version: '2.0.0',\n\n system: `You are an expert evaluator specializing in assessing AI Agent outputs.\n\nYour role is to fairly and thoroughly evaluate the agent's output against the provided criteria.\n\n## Evaluation Principles\n\n1. **Scoring**: Assign a score between 0-100 for each criterion\n - 90-100: Exceptional - Exceeds expectations with no significant issues\n - 70-89: Good - Meets expectations with minor issues\n - 50-69: Acceptable - Partially meets expectations, notable issues present\n - 30-49: Poor - Falls short of expectations, significant issues\n - 0-29: Failing - Does not meet minimum requirements\n\n2. **Reasoning**: Always provide specific, evidence-based reasoning\n - Quote or reference specific parts of the output\n - Explain both strengths and weaknesses\n - Be constructive and actionable in feedback\n\n3. **Objectivity**: Evaluate based solely on the criteria provided\n - Avoid personal preferences or unstated requirements\n - Consider the agent's intended purpose and context\n - Weight severity of issues proportionally\n\n## Response Format\n\nYou MUST respond with valid JSON only. No additional text or explanation outside the JSON structure.\n\n{\n \"verdicts\": [\n {\n \"criterionId\": \"criterion-id\",\n \"score\": 0-100,\n \"reasoning\": \"Detailed explanation with specific evidence from the output\",\n \"passed\": true/false\n }\n ]\n}`,\n\n renderUserPrompt: (ctx: JudgeContext): string => {\n const fileSection = buildFileSection(ctx.files);\n\n return `\n## Agent Under Evaluation\n${ctx.agentDescription}\n\n## Input Provided to Agent\n\\`\\`\\`json\n${JSON.stringify(ctx.input, null, 2)}\n\\`\\`\\`\n${fileSection}\n## Agent Output\n\\`\\`\\`json\n${JSON.stringify(ctx.output, null, 2)}\n\\`\\`\\`\n\n## Evaluation Criteria\n${ctx.criteria.map((c) => `- **${c.name}** (id: ${c.id}, weight: ${c.weight ?? 1}): ${c.description}`).join('\\n')}\n\nPlease evaluate the agent's output against each criterion listed above.`.trim();\n },\n};\n\nfunction buildFileSection(files: JudgeContext['files']): string {\n if (!files || files.length === 0) {\n return '';\n }\n\n return `\n## Reference Files\n${files.map((f) => `### ${f.path}\\n\\`\\`\\`\\n${f.content}\\n\\`\\`\\``).join('\\n\\n')}\n`;\n}\n","import { z, ZodError } from 'zod'\nimport type { ValidatorCriterion, SchemaValidationResult } from '@/core/types.js'\nimport type { CriterionOptions } from './index.js'\n\nexport interface SchemaOptions<T> extends CriterionOptions {\n schema: z.ZodType<T>\n /** Use unique IDs when using multiple validators */\n id?: string\n name?: string\n description?: string\n}\n\nfunction formatZodErrors(error: ZodError): string {\n return error.issues\n .map((e) => {\n const path = e.path.length > 0 ? `${e.path.join('.')}: ` : ''\n return `- ${path}${e.message}`\n })\n .join('\\n')\n}\n\n/**\n * Creates a schema validation criterion using Zod.\n *\n * Performs PROGRAMMATIC validation (not LLM-based).\n * Scoring is binary: 100 if validation passes, 0 if it fails.\n *\n * @example\n * ```typescript\n * import { z } from 'zod'\n * import { schema, createJudge, accuracy, defaultJudgePrompt } from '@agtlantis/eval'\n *\n * const RecipeSchema = z.object({\n * name: z.string(),\n * ingredients: z.array(z.object({\n * name: z.string(),\n * amount: z.string(),\n * })),\n * steps: z.array(z.string()).min(1),\n * })\n *\n * const judge = createJudge({\n * llm: openaiClient,\n * prompt: defaultJudgePrompt,\n * criteria: [\n * schema({ schema: RecipeSchema, weight: 2 }),\n * accuracy(),\n * ],\n * })\n * ```\n */\nexport function schema<T>(options: SchemaOptions<T>): ValidatorCriterion {\n const { schema, id, weight, name, description } = options\n\n return {\n id: id ?? 'schema-validation',\n name: name ?? '스키마 유효성',\n description:\n description ??\n '출력이 지정된 스키마(Zod)를 준수하는지 프로그래밍 방식으로 검증합니다.',\n weight,\n validator: (output: unknown): SchemaValidationResult => {\n const result = schema.safeParse(output)\n\n if (result.success) {\n return { valid: true }\n }\n\n return {\n valid: false,\n errors: result.error.issues,\n errorSummary: formatZodErrors(result.error),\n }\n },\n }\n}\n","import type { Criterion } from '@/core/types.js'\n\nexport { schema, type SchemaOptions } from './validate-schema.js'\n\nexport interface CriterionOptions {\n weight?: number\n}\n\n/**\n * Evaluates whether the agent's output is factually accurate\n * and free from errors or hallucinations.\n */\nexport function accuracy(options?: CriterionOptions): Criterion {\n return {\n id: 'accuracy',\n name: 'Accuracy',\n description:\n 'Evaluates whether the output is factually correct, free from errors, and avoids hallucinations. Check for incorrect facts, made-up information, or misrepresentation of the input data.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output is internally consistent\n * and doesn't contradict itself or the provided context.\n */\nexport function consistency(options?: CriterionOptions): Criterion {\n return {\n id: 'consistency',\n name: 'Consistency',\n description:\n 'Evaluates whether the output is internally coherent and logically consistent. Check for self-contradictions, conflicting statements, or logical inconsistencies within the response.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output is relevant to the input\n * and addresses the user's needs appropriately.\n */\nexport function relevance(options?: CriterionOptions): Criterion {\n return {\n id: 'relevance',\n name: 'Relevance',\n description:\n 'Evaluates whether the output directly addresses the input and fulfills the user intent. Check for off-topic content, missing key requirements, or responses that fail to answer the actual question.',\n weight: options?.weight,\n }\n}\n\n/**\n * Evaluates whether the agent's output shows clear step-by-step reasoning\n * or explanation of the solution process.\n */\nexport function stepByStep(options?: CriterionOptions): Criterion {\n return {\n id: 'step-by-step',\n name: 'Step-by-Step Reasoning',\n description:\n 'Evaluates whether the output demonstrates clear, structured reasoning with explicit steps. ' +\n 'Check for: numbered steps or clear progression, explanation of the thought process, ' +\n 'intermediate results shown before the final answer. ' +\n 'Penalize outputs that jump directly to the answer without showing work.',\n weight: options?.weight,\n }\n}\n","import { writeFile } from 'node:fs/promises';\n\nimport { getFileSourcesDisplayInfo } from '@agtlantis/core';\n\nimport { truncate } from '@/utils/json';\n\nimport type { EvalReport, ReportComparison, ReportMarkdownOptions } from './types';\n\nconst PASS_ICON = '✅';\nconst FAIL_ICON = '❌';\n\nconst PRIORITY_ORDER: Record<string, number> = { high: 0, medium: 1, low: 2 };\n\n/**\n * Converts an evaluation report to Markdown format.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases)\n * const markdown = reportToMarkdown(report)\n * console.log(markdown)\n * ```\n */\nexport function reportToMarkdown<TInput, TOutput>(\n report: EvalReport<TInput, TOutput>,\n options: ReportMarkdownOptions = {}\n): string {\n const {\n expandPassedTests = false,\n includeRawOutput = false,\n outputPreviewLength = 200,\n } = options;\n\n const { summary, results, suggestions, generatedAt, promptVersion } = report;\n const passRate =\n summary.totalTests > 0 ? ((summary.passed / summary.totalTests) * 100).toFixed(1) : '0.0';\n\n const lines: string[] = [];\n\n lines.push('# Evaluation Report');\n lines.push('');\n lines.push(`> Generated: ${generatedAt.toISOString()}`);\n lines.push(`> Prompt Version: ${promptVersion}`);\n lines.push('');\n\n lines.push('## Summary');\n lines.push('');\n lines.push(`| Metric | Value |`);\n lines.push(`|--------|-------|`);\n lines.push(`| Total Tests | ${summary.totalTests} |`);\n if (summary.iterations && summary.iterations > 1) {\n lines.push(`| **Iterations** | **${summary.iterations}** |`);\n }\n lines.push(`| Passed | ${summary.passed} (${passRate}%) |`);\n lines.push(`| Failed | ${summary.failed} |`);\n if (summary.avgStdDev !== undefined) {\n lines.push(\n `| Average Score | ${summary.avgScore.toFixed(1)} ± ${summary.avgStdDev.toFixed(1)} |`\n );\n } else {\n lines.push(`| Average Score | ${summary.avgScore.toFixed(1)} |`);\n }\n if (summary.avgPassRate !== undefined) {\n lines.push(`| Avg Pass Rate | ${(summary.avgPassRate * 100).toFixed(1)}% |`);\n }\n lines.push(`| Avg Latency | ${summary.metrics.avgLatencyMs.toFixed(0)}ms |`);\n lines.push(`| Total Tokens | ${summary.metrics.totalTokens} |`);\n if (summary.costSummary?.total !== undefined) {\n lines.push(`| Est. Cost | $${summary.costSummary.total.toFixed(4)} |`);\n }\n lines.push('');\n\n const failedResults = results.filter((r) => !r.passed);\n if (failedResults.length > 0) {\n lines.push(`## ${FAIL_ICON} Failed Tests`);\n lines.push('');\n for (const result of failedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n }\n\n const passedResults = results.filter((r) => r.passed);\n if (passedResults.length > 0) {\n lines.push(`## ${PASS_ICON} Passed Tests`);\n lines.push('');\n if (expandPassedTests) {\n for (const result of passedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n } else {\n lines.push('<details>');\n lines.push('<summary>Click to expand passed tests</summary>');\n lines.push('');\n for (const result of passedResults) {\n lines.push(formatTestResult(result, outputPreviewLength, includeRawOutput));\n }\n lines.push('</details>');\n lines.push('');\n }\n }\n\n if (suggestions.length > 0) {\n lines.push('## 💡 Improvement Suggestions');\n lines.push('');\n const sortedSuggestions = [...suggestions].sort(\n (a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]\n );\n\n for (const suggestion of sortedSuggestions) {\n lines.push(formatSuggestion(suggestion));\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Saves an evaluation report as a Markdown file.\n *\n * @example\n * ```typescript\n * const report = await suite.run(testCases)\n * await saveReportMarkdown(report, './reports/eval-2024-01.md')\n * ```\n */\nexport async function saveReportMarkdown<TInput, TOutput>(\n report: EvalReport<TInput, TOutput>,\n path: string,\n options?: ReportMarkdownOptions\n): Promise<void> {\n const markdown = reportToMarkdown(report, options);\n await writeFile(path, markdown, 'utf-8');\n}\n\nfunction jsonCodeBlock(value: unknown, maxLength?: number): string[] {\n const json = JSON.stringify(value, null, 2);\n const content = maxLength !== undefined ? truncate(json, maxLength) : json;\n return ['```json', content, '```'];\n}\n\nfunction passFailIcon(passed: boolean): string {\n return passed ? PASS_ICON : FAIL_ICON;\n}\n\ninterface TestResultForFormat<TInput, TOutput> {\n testCase: { id?: string; input: TInput; description?: string };\n output: TOutput;\n overallScore: number;\n passed: boolean;\n verdicts: Array<{ criterionId: string; score: number; reasoning: string; passed: boolean }>;\n iterationStats?: {\n iterations: number;\n scores: number[];\n mean: number;\n stdDev: number;\n min: number;\n max: number;\n passRate: number;\n passCount: number;\n };\n iterationResults?: Array<{\n overallScore: number;\n passed: boolean;\n metrics: { latencyMs: number };\n }>;\n conversationHistory?: Array<{ turn: number; input: TInput; output: TOutput | undefined }>;\n totalTurns?: number;\n terminationReason?: string;\n multiTurnIterationStats?: {\n avgTurns: number;\n minTurns: number;\n maxTurns: number;\n terminationCounts: Record<string, number>;\n };\n}\n\nfunction formatTestResult<TInput, TOutput>(\n result: TestResultForFormat<TInput, TOutput>,\n previewLength: number,\n includeRaw: boolean\n): string {\n const lines: string[] = [];\n const testId = result.testCase.id ?? 'unnamed';\n\n const scoreDisplay = result.iterationStats\n ? `${result.overallScore.toFixed(1)} ± ${result.iterationStats.stdDev.toFixed(1)}`\n : result.overallScore.toFixed(1);\n lines.push(`### ${testId} (Score: ${scoreDisplay})`);\n lines.push('');\n\n if (result.testCase.description) {\n lines.push(`> ${result.testCase.description}`);\n lines.push('');\n }\n\n const fileDisplayInfos = getFileSourcesDisplayInfo(result.testCase.input);\n if (fileDisplayInfos.length > 0) {\n lines.push('**Files:**');\n for (const info of fileDisplayInfos) {\n const namePrefix = info.filename ? `${info.filename} - ` : '';\n lines.push(`- ${namePrefix}${info.source}: ${info.description} (${info.mediaType})`);\n }\n lines.push('');\n }\n\n if (result.totalTurns !== undefined) {\n lines.push(\n `**Multi-turn:** ${result.totalTurns} turns | Termination: ${result.terminationReason ?? 'unknown'}`\n );\n lines.push('');\n }\n\n if (result.multiTurnIterationStats) {\n lines.push(...formatMultiTurnIterationStats(result.multiTurnIterationStats));\n }\n\n if (result.iterationStats && result.iterationResults) {\n lines.push(...formatIterationResults(result.iterationStats, result.iterationResults));\n }\n\n if (result.conversationHistory && result.conversationHistory.length > 0) {\n lines.push(...formatConversationHistory(result.conversationHistory, previewLength));\n } else {\n lines.push(\n ...formatSingleTurnInputOutput(result.testCase.input, result.output, previewLength)\n );\n }\n\n lines.push('**Verdicts:**');\n for (const verdict of result.verdicts) {\n lines.push(\n `- ${passFailIcon(verdict.passed)} **${verdict.criterionId}**: ${verdict.score} - ${verdict.reasoning}`\n );\n }\n lines.push('');\n\n if (includeRaw) {\n lines.push('<details>');\n lines.push('<summary>Raw Output</summary>');\n lines.push('');\n lines.push(...jsonCodeBlock(result.output));\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiTurnIterationStats(\n stats: NonNullable<TestResultForFormat<unknown, unknown>['multiTurnIterationStats']>\n): string[] {\n const terminationSummary =\n Object.entries(stats.terminationCounts)\n .map(([type, count]) => `${type}: ${count}`)\n .join(', ') || 'none';\n\n return [\n '**Multi-turn Iteration Statistics:**',\n '',\n '| Metric | Value |',\n '|--------|-------|',\n `| Avg Turns | ${stats.avgTurns.toFixed(1)} |`,\n `| Min/Max Turns | ${stats.minTurns} / ${stats.maxTurns} |`,\n `| Termination Distribution | ${terminationSummary} |`,\n '',\n ];\n}\n\nfunction formatIterationResults(\n stats: NonNullable<TestResultForFormat<unknown, unknown>['iterationStats']>,\n results: NonNullable<TestResultForFormat<unknown, unknown>['iterationResults']>\n): string[] {\n const lines: string[] = [\n '**Iteration Results:**',\n '',\n '| # | Score | Passed | Latency |',\n '|---|-------|--------|---------|',\n ];\n\n results.forEach((iter, idx) => {\n lines.push(\n `| ${idx + 1} | ${iter.overallScore.toFixed(1)} | ${passFailIcon(iter.passed)} | ${iter.metrics.latencyMs.toFixed(0)}ms |`\n );\n });\n\n lines.push('');\n lines.push(\n `**Stats:** ${stats.mean.toFixed(1)} ± ${stats.stdDev.toFixed(1)} (min: ${stats.min.toFixed(0)}, max: ${stats.max.toFixed(0)}, pass rate: ${(stats.passRate * 100).toFixed(0)}%)`\n );\n lines.push('');\n\n return lines;\n}\n\nfunction formatConversationHistory<TInput, TOutput>(\n history: Array<{ turn: number; input: TInput; output: TOutput | undefined }>,\n previewLength: number\n): string[] {\n const lines: string[] = ['**Conversation History:**', ''];\n\n for (const turn of history) {\n lines.push('<details>');\n lines.push(`<summary>Turn ${turn.turn}</summary>`);\n lines.push('');\n lines.push('**Input:**');\n lines.push(...jsonCodeBlock(turn.input, previewLength));\n lines.push('');\n lines.push('**Output:**');\n lines.push(...jsonCodeBlock(turn.output, previewLength));\n lines.push('</details>');\n lines.push('');\n }\n\n return lines;\n}\n\nfunction formatSingleTurnInputOutput<TInput, TOutput>(\n input: TInput,\n output: TOutput,\n previewLength: number\n): string[] {\n return [\n '**Input:**',\n ...jsonCodeBlock(input, previewLength),\n '',\n '**Output:**',\n ...jsonCodeBlock(output, previewLength),\n '',\n ];\n}\n\nfunction formatSuggestion(suggestion: {\n type: string;\n priority: string;\n currentValue: string;\n suggestedValue: string;\n reasoning: string;\n expectedImprovement: string;\n}): string {\n const lines: string[] = [];\n const priorityIcon = { high: '🔴', medium: '🟡', low: '🟢' }[suggestion.priority] ?? '⚪';\n\n lines.push(`### ${priorityIcon} [${suggestion.priority.toUpperCase()}] ${suggestion.type}`);\n lines.push('');\n lines.push(`**Reasoning:** ${suggestion.reasoning}`);\n lines.push('');\n lines.push(`**Expected Improvement:** ${suggestion.expectedImprovement}`);\n lines.push('');\n lines.push('**Diff:**');\n lines.push('```diff');\n lines.push(`- ${suggestion.currentValue.split('\\n').join('\\n- ')}`);\n lines.push(`+ ${suggestion.suggestedValue.split('\\n').join('\\n+ ')}`);\n lines.push('```');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Compares two evaluation reports and returns the differences.\n * Useful for tracking improvements across prompt versions.\n *\n * @example\n * ```typescript\n * const beforeReport = await suite.run(testCases)\n * // ... apply improvements ...\n * const afterReport = await suite.withAgent(improvedAgent).run(testCases)\n *\n * const comparison = compareReports(beforeReport, afterReport)\n * console.log(`Score improved by ${comparison.scoreDelta} points`)\n * console.log(`Tests improved: ${comparison.improved.join(', ')}`)\n * console.log(`Tests regressed: ${comparison.regressed.join(', ')}`)\n * ```\n */\nexport function compareReports<TInput, TOutput>(\n before: EvalReport<TInput, TOutput>,\n after: EvalReport<TInput, TOutput>\n): ReportComparison {\n const scoreDelta = after.summary.avgScore - before.summary.avgScore;\n\n const beforePassRate =\n before.summary.totalTests > 0 ? before.summary.passed / before.summary.totalTests : 0;\n const afterPassRate =\n after.summary.totalTests > 0 ? after.summary.passed / after.summary.totalTests : 0;\n const passRateDelta = afterPassRate - beforePassRate;\n\n const metricsDelta = {\n latencyMs: after.summary.metrics.avgLatencyMs - before.summary.metrics.avgLatencyMs,\n tokenUsage: after.summary.metrics.totalTokens - before.summary.metrics.totalTokens,\n };\n\n const beforeScores = buildScoreMap(before.results);\n const afterScores = buildScoreMap(after.results);\n\n const improved: string[] = [];\n const regressed: string[] = [];\n\n for (const [id, afterScore] of afterScores) {\n const beforeScore = beforeScores.get(id);\n if (beforeScore === undefined) continue;\n if (afterScore > beforeScore) {\n improved.push(id);\n } else if (afterScore < beforeScore) {\n regressed.push(id);\n }\n }\n\n const removed = [...beforeScores.keys()].filter((id) => !afterScores.has(id));\n\n return {\n scoreDelta,\n passRateDelta,\n metricsDelta,\n improved,\n regressed,\n removed,\n };\n}\n\nfunction buildScoreMap<TInput, TOutput>(\n results: Array<{ testCase: { id?: string }; overallScore: number }>\n): Map<string, number> {\n const scoreMap = new Map<string, number>();\n for (const result of results) {\n scoreMap.set(result.testCase.id ?? 'unnamed', result.overallScore);\n }\n return scoreMap;\n}\n","import { writeFileSync } from 'node:fs'\nimport type { Reporter, FileReporterOptions, EvalReport } from './types'\nimport { calculateReportCosts, type CostSummary, type EvalPricingConfig } from './cost-helpers'\nimport { buildOutputPath } from './format-utils'\n\ninterface SerializedReport<TInput, TOutput> {\n summary: EvalReport<TInput, TOutput>['summary']\n results: EvalReport<TInput, TOutput>['results']\n suggestions: EvalReport<TInput, TOutput>['suggestions']\n generatedAt: string\n promptVersion: string\n costs?: CostSummary\n}\n\n/**\n * Reporter that saves EvalReport as JSON.\n *\n * @example\n * ```typescript\n * const reporter = new JsonReporter({ outputDir: './reports' })\n * reporter.save(report, 'my-test') // -> ./reports/my-test-1736691234567.json\n *\n * // Without timestamp\n * const fixedReporter = new JsonReporter({\n * outputDir: './reports',\n * addTimestamp: false,\n * })\n * fixedReporter.save(report, 'round-1') // -> ./reports/round-1.json\n * ```\n */\nexport class JsonReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly outputDir: string\n private readonly pricing?: EvalPricingConfig\n private readonly addTimestamp: boolean\n\n constructor(options: FileReporterOptions) {\n this.outputDir = options.outputDir\n this.pricing = options.pricing\n this.addTimestamp = options.addTimestamp ?? true\n }\n\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const filepath = buildOutputPath(this.outputDir, name, 'json', this.addTimestamp)\n\n const costs = this.pricing\n ? calculateReportCosts(report, this.pricing)\n : undefined\n\n const output: SerializedReport<TInput, TOutput> = {\n summary: report.summary,\n results: report.results,\n suggestions: report.suggestions,\n generatedAt: report.generatedAt.toISOString(),\n promptVersion: report.promptVersion,\n ...(costs && { costs }),\n }\n\n writeFileSync(filepath, JSON.stringify(output, null, 2))\n return filepath\n }\n}\n","import type { EvalTokenUsage } from '@/core/types'\nimport {\n calculateCostFromUsage,\n type ProviderType,\n type ProviderPricing,\n} from '@agtlantis/core'\nimport type { LanguageModelUsage } from 'ai'\n\nfunction toLanguageModelUsage(usage: EvalTokenUsage): LanguageModelUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n } as LanguageModelUsage\n}\n\n/** Cost breakdown by component (Agent, Judge, Improver) */\nexport interface CostBreakdown {\n agent?: number\n judge?: number\n improver?: number\n total?: number\n}\n\n/** Cost summary aggregated across all test results */\nexport interface CostSummary {\n total: number\n byComponent: {\n agent: number\n judge: number\n improver?: number\n }\n}\n\nexport interface MetricsWithCost {\n latencyMs: number\n tokenUsage: EvalTokenUsage\n costBreakdown: CostBreakdown\n}\n\n/** Test result with cost breakdown, returned by addCostsToResults() */\nexport interface TestResultWithCost<TInput, TOutput> {\n testCase: {\n id?: string\n input: TInput\n tags?: string[]\n description?: string\n expectedOutput?: unknown\n }\n output: TOutput\n metrics: MetricsWithCost\n error?: Error\n verdicts: Array<{\n criterionId: string\n score: number\n reasoning: string\n passed: boolean\n }>\n overallScore: number\n passed: boolean\n}\n\n/** Pricing configuration for eval */\nexport interface EvalPricingConfig {\n /** Provider-specific pricing overrides. Key is provider name (e.g., 'google', 'openai'), value is model pricing. */\n providerPricing?: Partial<Record<ProviderType, ProviderPricing>>\n}\n\n/** Maps eval's provider names to core's provider names (eval uses 'gemini', core uses 'google') */\nconst PROVIDER_MAPPING: Record<string, ProviderType> = {\n gemini: 'google',\n openai: 'openai',\n anthropic: 'anthropic',\n google: 'google',\n}\n\nfunction detectProvider(model: string | undefined): ProviderType {\n if (!model) return 'google' // default\n\n if (model.startsWith('gpt-') || model.startsWith('o1') || model.startsWith('o3')) {\n return 'openai'\n }\n if (model.startsWith('gemini-')) {\n return 'google'\n }\n if (model.startsWith('claude-')) {\n return 'anthropic'\n }\n\n return 'google'\n}\n\nfunction normalizeProvider(provider: string | undefined): ProviderType {\n if (!provider) return 'google'\n return PROVIDER_MAPPING[provider] ?? provider\n}\n\n/** Minimal result interface compatible with TestResultWithVerdict and TestResultWithIteration */\ninterface ResultForCostCalculation<TInput, TOutput> {\n testCase: {\n id?: string\n input: TInput\n tags?: string[]\n description?: string\n expectedOutput?: unknown\n }\n output: TOutput\n metrics: {\n latencyMs: number\n tokenUsage: EvalTokenUsage\n }\n error?: Error\n verdicts: Array<{\n criterionId: string\n score: number\n reasoning: string\n passed: boolean\n }>\n overallScore: number\n passed: boolean\n agentMetadata?: {\n tokenUsage?: EvalTokenUsage\n model?: string\n provider?: string\n }\n judgeMetadata?: {\n tokenUsage?: EvalTokenUsage\n model?: string\n provider?: string\n }\n}\n\ninterface ReportForCostCalculation<TInput, TOutput> {\n results: ResultForCostCalculation<TInput, TOutput>[]\n}\n\nfunction calculateComponentCost(\n tokenUsage: EvalTokenUsage | undefined,\n model: string | undefined,\n provider: string | undefined,\n config?: EvalPricingConfig\n): number | undefined {\n if (!tokenUsage) return undefined\n\n const normalizedProvider = provider\n ? normalizeProvider(provider)\n : detectProvider(model)\n\n // Get the pricing for this specific provider from the config\n const providerPricing = config?.providerPricing?.[normalizedProvider]\n\n const result = calculateCostFromUsage(\n toLanguageModelUsage(tokenUsage),\n model ?? 'unknown',\n normalizedProvider,\n providerPricing\n )\n\n return result.total\n}\n\nfunction buildCostBreakdown(costs: {\n agent?: number\n judge?: number\n improver?: number\n}): CostBreakdown {\n const total =\n (costs.agent ?? 0) + (costs.judge ?? 0) + (costs.improver ?? 0)\n\n return {\n ...costs,\n total: total > 0 ? total : undefined,\n }\n}\n\nexport function calculateResultCost<TInput, TOutput>(\n result: ResultForCostCalculation<TInput, TOutput>,\n config?: EvalPricingConfig\n): CostBreakdown {\n const agentCost = calculateComponentCost(\n result.metrics.tokenUsage,\n result.agentMetadata?.model,\n result.agentMetadata?.provider,\n config\n )\n\n const judgeCost = result.judgeMetadata?.tokenUsage\n ? calculateComponentCost(\n result.judgeMetadata.tokenUsage,\n result.judgeMetadata.model,\n result.judgeMetadata.provider,\n config\n )\n : undefined\n\n return buildCostBreakdown({\n agent: agentCost,\n judge: judgeCost,\n })\n}\n\nexport function calculateReportCosts<TInput, TOutput>(\n report: ReportForCostCalculation<TInput, TOutput>,\n config?: EvalPricingConfig\n): CostSummary {\n let totalAgent = 0\n let totalJudge = 0\n\n for (const result of report.results) {\n const breakdown = calculateResultCost(result, config)\n totalAgent += breakdown.agent ?? 0\n totalJudge += breakdown.judge ?? 0\n }\n\n return {\n total: totalAgent + totalJudge,\n byComponent: {\n agent: totalAgent,\n judge: totalJudge,\n },\n }\n}\n\n/** Add cost breakdown to each result. Returns new array (does not mutate original). */\nexport function addCostsToResults<TInput, TOutput>(\n results: ResultForCostCalculation<TInput, TOutput>[],\n config?: EvalPricingConfig\n): TestResultWithCost<TInput, TOutput>[] {\n return results.map((result) => {\n const costBreakdown = calculateResultCost(result, config)\n\n const metricsWithCost: MetricsWithCost = {\n latencyMs: result.metrics.latencyMs,\n tokenUsage: result.metrics.tokenUsage,\n costBreakdown,\n }\n\n return {\n testCase: result.testCase,\n output: result.output,\n metrics: metricsWithCost,\n error: result.error,\n verdicts: result.verdicts,\n overallScore: result.overallScore,\n passed: result.passed,\n }\n })\n}\n","import { mkdirSync } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * Formats a score delta for display with consistent sign prefix.\n *\n * @example\n * formatScoreDelta(5.2) // \"+5.2\"\n * formatScoreDelta(-3.1) // \"-3.1\"\n * formatScoreDelta(0) // \"+0.0\"\n * formatScoreDelta(null) // \"-\"\n */\nexport function formatScoreDelta(delta: number | null): string {\n if (delta === null) {\n return '-'\n }\n const sign = delta >= 0 ? '+' : ''\n return `${sign}${delta.toFixed(1)}`\n}\n\n/**\n * Builds the output file path, creating the output directory if it doesn't exist.\n * Used by file-based reporters for consistent path handling.\n */\nexport function buildOutputPath(\n outputDir: string,\n name: string,\n extension: string,\n addTimestamp: boolean\n): string {\n mkdirSync(outputDir, { recursive: true })\n const filename = addTimestamp\n ? `${name}-${Date.now()}.${extension}`\n : `${name}.${extension}`\n return path.join(outputDir, filename)\n}\n\n/** Converts a Date to ISO string, handling both Date objects and already-serialized strings */\nexport function toISOStringIfDate(value: Date | string): string {\n return value instanceof Date ? value.toISOString() : value\n}\n","import { writeFileSync } from 'node:fs'\nimport type { Reporter, FileReporterOptions, EvalReport, ReportMarkdownOptions } from './types'\nimport { reportToMarkdown } from './markdown'\nimport { buildOutputPath } from './format-utils'\n\nexport interface MarkdownReporterOptions extends FileReporterOptions {\n /** Markdown generation options */\n markdown?: ReportMarkdownOptions\n}\n\n/**\n * Reporter that saves EvalReport as Markdown.\n *\n * @example\n * ```typescript\n * const reporter = new MarkdownReporter({ outputDir: './reports' })\n * reporter.save(report, 'my-test') // -> ./reports/my-test-1736691234567.md\n *\n * // With expanded passed tests\n * const detailedReporter = new MarkdownReporter({\n * outputDir: './reports',\n * markdown: { expandPassedTests: true },\n * })\n * ```\n */\nexport class MarkdownReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly outputDir: string\n private readonly addTimestamp: boolean\n private readonly markdownOptions: ReportMarkdownOptions\n\n constructor(options: MarkdownReporterOptions) {\n this.outputDir = options.outputDir\n this.addTimestamp = options.addTimestamp ?? true\n this.markdownOptions = options.markdown ?? {}\n }\n\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const filepath = buildOutputPath(this.outputDir, name, 'md', this.addTimestamp)\n const markdown = reportToMarkdown(report, this.markdownOptions)\n writeFileSync(filepath, markdown)\n return filepath\n }\n}\n","import type { Reporter, ConsoleReporterOptions, EvalReport, LogVerbosity } from './types'\nimport { calculateReportCosts, type EvalPricingConfig } from './cost-helpers'\nimport { truncate } from '@/utils/json'\n\n/**\n * Reporter that logs EvalReport to console.\n *\n * @example\n * ```typescript\n * const reporter = new ConsoleReporter({ verbosity: 'detailed' })\n * reporter.log(report) // Logs to console\n *\n * // With cost display\n * const costReporter = new ConsoleReporter({\n * verbosity: 'summary',\n * pricing: GOOGLE_PRICING,\n * })\n * ```\n */\nexport class ConsoleReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n private readonly verbosity: LogVerbosity\n private readonly pricing?: EvalPricingConfig\n\n constructor(options: ConsoleReporterOptions = {}) {\n this.verbosity = options.verbosity ?? 'summary'\n this.pricing = options.pricing\n }\n\n log(report: EvalReport<TInput, TOutput>): void {\n const { summary } = report\n const passRate = summary.totalTests > 0 ? summary.passed / summary.totalTests : 0\n\n console.log(`\\n📊 Eval Report: ${summary.totalTests} tests`)\n console.log(` Score: ${summary.avgScore.toFixed(1)} | Pass Rate: ${(passRate * 100).toFixed(0)}%`)\n\n if (this.verbosity === 'summary') {\n this.logCostIfAvailable(report)\n return\n }\n\n console.log('')\n for (const result of report.results) {\n const testId = result.testCase.id || 'unknown'\n const status = result.passed ? '✓' : '✗'\n console.log(` ${status} [${testId}] Score: ${result.overallScore.toFixed(1)}`)\n\n if (this.verbosity === 'full') {\n console.log(` Input: ${truncate(JSON.stringify(result.testCase.input), 80)}`)\n console.log(` Output: ${truncate(String(result.output), 80)}`)\n }\n }\n\n this.logCostIfAvailable(report)\n }\n\n private logCostIfAvailable(report: EvalReport<TInput, TOutput>): void {\n if (this.pricing) {\n const costs = calculateReportCosts(report, this.pricing)\n console.log(`\\n 💰 Cost: $${costs.total.toFixed(4)}`)\n }\n }\n}\n","import type { Reporter, EvalReport } from './types'\n\n/**\n * Combines multiple reporters to save/log to multiple outputs.\n *\n * @example\n * ```typescript\n * const reporter = new CompositeReporter([\n * new JsonReporter({ outputDir: './reports' }),\n * new ConsoleReporter({ verbosity: 'detailed' }),\n * ])\n * reporter.save(report, 'my-test') // JSON 저장 + 콘솔 출력\n * ```\n */\nexport class CompositeReporter<TInput = unknown, TOutput = unknown>\n implements Reporter<TInput, TOutput>\n{\n constructor(private readonly reporters: Reporter<TInput, TOutput>[]) {}\n\n /**\n * Saves to all reporters that support saving.\n * Returns the first successful file path (usually JsonReporter).\n */\n save(report: EvalReport<TInput, TOutput>, name: string): string {\n const errors: Array<{ reporter: string; error: Error }> = []\n let firstPath: string | undefined\n\n for (const reporter of this.reporters) {\n // Skip reporters that don't support save\n if (!reporter.save) {\n reporter.log?.(report)\n continue\n }\n\n try {\n const savedPath = reporter.save(report, name)\n if (!firstPath) firstPath = savedPath\n } catch (error) {\n errors.push({\n reporter: reporter.constructor.name,\n error: error as Error,\n })\n }\n\n // Log regardless of save success/failure - user should see output even if save fails\n reporter.log?.(report)\n }\n\n if (!firstPath) {\n const details = errors.length > 0\n ? errors.map(e => `${e.reporter}: ${e.error.message}`).join(', ')\n : 'No reporters support save()'\n throw new Error(`No reporter saved successfully. ${details}`)\n }\n\n return firstPath\n }\n\n log(report: EvalReport<TInput, TOutput>): void {\n for (const reporter of this.reporters) {\n reporter.log?.(report)\n }\n }\n}\n","import { JsonReporter } from './json-reporter'\nimport { MarkdownReporter, type MarkdownReporterOptions } from './markdown-reporter'\nimport { ConsoleReporter } from './console-reporter'\nimport { CompositeReporter } from './composite-reporter'\nimport type { FileReporterOptions, ConsoleReporterOptions, Reporter, LogVerbosity } from './types'\nimport type { EvalPricingConfig } from './cost-helpers'\n\n/**\n * Create a JSON reporter.\n *\n * @example\n * ```typescript\n * const reporter = createJsonReporter('./reports')\n * reporter.save(report, 'my-test') // → ./reports/my-test-1736691234567.json\n * ```\n */\nexport function createJsonReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: Omit<FileReporterOptions, 'outputDir'>,\n): JsonReporter<TInput, TOutput> {\n return new JsonReporter({ outputDir, ...options })\n}\n\n/**\n * Create a Markdown reporter.\n *\n * @example\n * ```typescript\n * const reporter = createMarkdownReporter('./reports')\n * reporter.save(report, 'my-test') // → ./reports/my-test-1736691234567.md\n * ```\n */\nexport function createMarkdownReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: Omit<MarkdownReporterOptions, 'outputDir'>,\n): MarkdownReporter<TInput, TOutput> {\n return new MarkdownReporter({ outputDir, ...options })\n}\n\n/**\n * Create a console reporter.\n *\n * @example\n * ```typescript\n * const reporter = createConsoleReporter({ verbosity: 'detailed' })\n * reporter.log(report) // Logs to console\n * ```\n */\nexport function createConsoleReporter<TInput = unknown, TOutput = unknown>(\n options?: ConsoleReporterOptions,\n): ConsoleReporter<TInput, TOutput> {\n return new ConsoleReporter(options)\n}\n\n/**\n * Create a composite reporter from multiple reporters.\n *\n * @example\n * ```typescript\n * const reporter = createCompositeReporter([\n * createJsonReporter('./reports'),\n * createConsoleReporter({ verbosity: 'summary' }),\n * ])\n * ```\n */\nexport function createCompositeReporter<TInput = unknown, TOutput = unknown>(\n reporters: Reporter<TInput, TOutput>[],\n): CompositeReporter<TInput, TOutput> {\n return new CompositeReporter(reporters)\n}\n\n/**\n * Convenience: Create JSON + Console reporter combo.\n *\n * @example\n * ```typescript\n * const reporter = createDefaultReporter('./reports', {\n * pricing: GOOGLE_PRICING,\n * verbosity: 'summary',\n * })\n * reporter.save(report, 'my-test') // JSON 저장 + 콘솔 출력\n * ```\n */\nexport function createDefaultReporter<TInput = unknown, TOutput = unknown>(\n outputDir: string,\n options?: {\n pricing?: EvalPricingConfig\n verbosity?: LogVerbosity\n addTimestamp?: boolean\n },\n): CompositeReporter<TInput, TOutput> {\n return new CompositeReporter([\n new JsonReporter({\n outputDir,\n pricing: options?.pricing,\n addTimestamp: options?.addTimestamp,\n }),\n new ConsoleReporter({\n verbosity: options?.verbosity,\n pricing: options?.pricing,\n }),\n ])\n}\n","import type { EvalSuite } from '@/core/suite'\nimport type { TestCase } from '@/core/types'\nimport type { EvalReport, LogVerbosity } from './types'\nimport type { EvalPricingConfig } from './cost-helpers'\nimport { JsonReporter } from './json-reporter'\nimport { ConsoleReporter } from './console-reporter'\n\n/**\n * Options for creating a report runner.\n */\nexport interface ReportRunnerOptions {\n /** Directory where reports will be saved */\n outputDir: string\n /** Pricing config for cost calculation */\n pricing?: EvalPricingConfig\n /** Verbosity level for console output (false to disable logging) */\n verbosity?: LogVerbosity | false\n}\n\n\n/**\n * Result returned by the report runner.\n */\nexport interface ReportRunnerResult<TInput, TOutput> {\n /** The generated evaluation report */\n report: EvalReport<TInput, TOutput>\n /** Path where the report was saved */\n savedPath: string\n}\n\n/**\n * Creates a runner that automatically logs and saves reports.\n *\n * @param options - Runner configuration\n * @returns A function that runs the suite and handles reporting\n *\n * @example\n * ```typescript\n * import { createReportRunner, GOOGLE_PRICING } from '@agtlantis/eval'\n *\n * const run = createReportRunner({\n * outputDir: './reports',\n * pricing: GOOGLE_PRICING,\n * verbosity: 'detailed',\n * })\n *\n * const { report, savedPath } = await run(suite, testCases, 'my-evaluation')\n * // Logs to console and saves to ./reports/my-evaluation-{timestamp}.json\n * console.log(`Saved to: ${savedPath}`)\n * ```\n */\nexport function createReportRunner(options: ReportRunnerOptions) {\n const { outputDir, pricing, verbosity } = options\n\n const jsonReporter = new JsonReporter({ outputDir, pricing })\n const consoleReporter = verbosity !== false\n ? new ConsoleReporter({ verbosity: verbosity || 'summary', pricing })\n : null\n\n return async <TInput, TOutput>(\n suite: EvalSuite<TInput, TOutput>,\n testCases: TestCase<TInput>[],\n name: string,\n ): Promise<ReportRunnerResult<TInput, TOutput>> => {\n const report = await suite.run(testCases)\n\n consoleReporter?.log(report)\n const savedPath = jsonReporter.save(report, name)\n\n return { report, savedPath }\n }\n}\n","import { writeFileSync, mkdirSync } from 'node:fs'\nimport path from 'node:path'\nimport type { ImprovementCycleResult } from '@/improvement-cycle/types'\nimport { toISOStringIfDate } from './format-utils'\n\n/**\n * Options for saving an ImprovementCycleResult as JSON.\n *\n * Supports two modes:\n * - **Auto mode**: Provide `outputDir` and `name` to create a timestamped subdirectory\n * - **Explicit mode**: Provide `directory` to use an existing directory directly\n */\nexport interface SaveCycleJsonOptions {\n /** Base output directory (creates {name}-{timestamp}/ subdirectory) */\n outputDir?: string\n /** Cycle name (used for folder name with timestamp) */\n name?: string\n /** Use this exact directory path (no timestamp suffix added) */\n directory?: string\n /** Whether to save individual round reports (default: true) */\n saveRounds?: boolean\n}\n\n/**\n * Saves an ImprovementCycleResult to JSON files.\n *\n * Creates a directory containing:\n * - `cycle-summary.json`: Structured cycle summary\n * - `round-{n}-report.json`: Individual round reports (if saveRounds=true)\n *\n * @example Auto mode (creates timestamped directory)\n * ```typescript\n * const dir = saveCycleJson(result, {\n * outputDir: './reports',\n * name: 'my-agent',\n * })\n * // -> ./reports/my-agent-1736691234567/\n * ```\n *\n * @example Explicit mode (uses existing directory)\n * ```typescript\n * const dir = saveCycleJson(result, {\n * directory: './reports/my-existing-dir',\n * })\n * // -> ./reports/my-existing-dir/\n * ```\n */\nexport function saveCycleJson<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: SaveCycleJsonOptions,\n): string {\n const { outputDir, name, directory, saveRounds = true } = options\n\n const cycleDir = resolveCycleDirectory(outputDir, name, directory)\n mkdirSync(cycleDir, { recursive: true })\n\n saveCycleSummary(cycleDir, result)\n\n if (saveRounds) {\n saveRoundReports(cycleDir, result.rounds)\n }\n\n return cycleDir\n}\n\nfunction resolveCycleDirectory(\n outputDir: string | undefined,\n name: string | undefined,\n directory: string | undefined\n): string {\n if (directory) {\n return directory\n }\n if (outputDir && name) {\n return path.join(outputDir, `${name}-${Date.now()}`)\n }\n throw new Error('saveCycleJson requires either \"directory\" or both \"outputDir\" and \"name\"')\n}\n\nfunction saveCycleSummary<TInput, TOutput>(\n cycleDir: string,\n result: ImprovementCycleResult<TInput, TOutput>\n): void {\n const summaryPath = path.join(cycleDir, 'cycle-summary.json')\n const summary = {\n rounds: result.rounds.map((round) => ({\n round: round.round,\n completedAt: toISOStringIfDate(round.completedAt),\n score: round.report.summary.avgScore,\n scoreDelta: round.scoreDelta,\n cost: round.cost,\n suggestionsGenerated: round.suggestionsGenerated.length,\n suggestionsApproved: round.suggestionsApproved.length,\n promptVersionAfter: round.promptVersionAfter,\n })),\n terminationReason: result.terminationReason,\n totalCost: result.totalCost,\n roundCount: result.rounds.length,\n initialScore: result.rounds[0]?.report.summary.avgScore ?? null,\n finalScore: result.rounds[result.rounds.length - 1]?.report.summary.avgScore ?? null,\n }\n writeFileSync(summaryPath, JSON.stringify(summary, null, 2))\n}\n\nfunction saveRoundReports<TInput, TOutput>(\n cycleDir: string,\n rounds: ImprovementCycleResult<TInput, TOutput>['rounds']\n): void {\n for (const round of rounds) {\n const roundPath = path.join(cycleDir, `round-${round.round}-report.json`)\n const roundData = {\n round: round.round,\n completedAt: toISOStringIfDate(round.completedAt),\n report: {\n ...round.report,\n generatedAt: toISOStringIfDate(round.report.generatedAt),\n },\n suggestionsGenerated: round.suggestionsGenerated,\n suggestionsApproved: round.suggestionsApproved,\n promptSnapshot: round.promptSnapshot,\n cost: round.cost,\n scoreDelta: round.scoreDelta,\n }\n writeFileSync(roundPath, JSON.stringify(roundData, null, 2))\n }\n}\n","import type { ImprovementCycleResult } from '@/improvement-cycle/types'\nimport type { LogVerbosity } from './types'\nimport { ConsoleReporter } from './console-reporter'\nimport { formatScoreDelta } from './format-utils'\n\n/**\n * Options for logging an ImprovementCycleResult to console.\n */\nexport interface LogCycleOptions {\n /** Verbosity level for per-round details */\n verbosity?: LogVerbosity\n /** Show per-round details (default: false, summary only) */\n showRounds?: boolean\n}\n\n/**\n * Logs an ImprovementCycleResult to the console.\n *\n * Shows cycle summary including round count, termination reason, total cost,\n * and score progression. Optionally shows per-round details.\n *\n * @param result - The improvement cycle result to log\n * @param options - Logging options\n *\n * @example\n * ```typescript\n * import { logCycle } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * logCycle(result, { verbosity: 'detailed', showRounds: true })\n * ```\n */\nexport function logCycle<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: LogCycleOptions = {},\n): void {\n const { verbosity = 'summary', showRounds = false } = options\n\n console.log('\\n🔄 Improvement Cycle Complete')\n console.log(` Rounds: ${result.rounds.length}`)\n console.log(` Termination: ${result.terminationReason}`)\n console.log(` Total Cost: $${result.totalCost.toFixed(4)}`)\n\n if (result.rounds.length > 0) {\n const firstScore = result.rounds[0].report.summary.avgScore\n const lastScore = result.rounds[result.rounds.length - 1].report.summary.avgScore\n const delta = lastScore - firstScore\n console.log(` Score: ${firstScore.toFixed(1)} -> ${lastScore.toFixed(1)} (${formatScoreDelta(delta)})`)\n }\n\n if (showRounds) {\n const consoleReporter = new ConsoleReporter({ verbosity })\n for (const round of result.rounds) {\n console.log(`\\n -- Round ${round.round} --`)\n consoleReporter.log(round.report)\n }\n }\n}\n","import { writeFileSync } from 'node:fs';\n\nimport type { ImprovementCycleResult } from '@/improvement-cycle/types';\n\nimport { formatScoreDelta } from './format-utils';\nimport { reportToMarkdown } from './markdown';\n\n/**\n * Options for generating cycle markdown.\n */\nexport interface CycleMarkdownOptions {\n /** Include full per-round details (default: true) */\n includeRoundDetails?: boolean;\n /** Show prompt evolution - initial vs final (default: false) */\n showPromptEvolution?: boolean;\n}\n\n/**\n * Converts an ImprovementCycleResult to markdown.\n *\n * Generates a comprehensive report including:\n * - Summary table (rounds, termination, cost, scores)\n * - Score progression table\n * - Per-round details (optional)\n * - Prompt evolution (optional)\n *\n * @param result - The improvement cycle result\n * @param options - Markdown generation options\n * @returns Markdown string\n *\n * @example\n * ```typescript\n * import { cycleToMarkdown } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * const markdown = cycleToMarkdown(result, {\n * includeRoundDetails: true,\n * showPromptEvolution: true,\n * })\n * ```\n */\nexport function cycleToMarkdown<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n options: CycleMarkdownOptions = {}\n): string {\n const { includeRoundDetails = true, showPromptEvolution = false } = options;\n const lines: string[] = [];\n\n // Header\n lines.push('# Improvement Cycle Report');\n lines.push('');\n\n // Summary\n lines.push('## Summary');\n lines.push('');\n lines.push('| Metric | Value |');\n lines.push('|--------|-------|');\n lines.push(`| Rounds | ${result.rounds.length} |`);\n lines.push(`| Termination | ${result.terminationReason} |`);\n lines.push(`| Total Cost | $${result.totalCost.toFixed(4)} |`);\n\n if (result.rounds.length > 0) {\n const first = result.rounds[0].report.summary.avgScore;\n const last = result.rounds[result.rounds.length - 1].report.summary.avgScore;\n lines.push(`| Initial Score | ${first.toFixed(1)} |`);\n lines.push(`| Final Score | ${last.toFixed(1)} |`);\n lines.push(`| Improvement | ${formatScoreDelta(last - first)} |`);\n }\n lines.push('');\n\n // Score progression table\n lines.push('## Score Progression');\n lines.push('');\n lines.push('| Round | Score | Delta | Cost |');\n lines.push('|-------|-------|-------|------|');\n for (const round of result.rounds) {\n const delta = formatScoreDelta(round.scoreDelta);\n lines.push(\n `| ${round.round} | ${round.report.summary.avgScore.toFixed(1)} | ${delta} | $${round.cost.total.toFixed(4)} |`\n );\n }\n lines.push('');\n\n // Per-round details\n if (includeRoundDetails) {\n lines.push('## Round Details');\n lines.push('');\n for (const round of result.rounds) {\n lines.push(`### Round ${round.round}`);\n lines.push('');\n lines.push(reportToMarkdown(round.report));\n lines.push('');\n }\n }\n\n // Prompt evolution\n if (showPromptEvolution && result.rounds.length > 0) {\n lines.push('## Prompt Evolution');\n lines.push('');\n lines.push('### Initial Prompt');\n lines.push('');\n lines.push('```');\n lines.push(result.rounds[0].promptSnapshot.userTemplate);\n lines.push('```');\n lines.push('');\n lines.push('### Final Prompt');\n lines.push('');\n lines.push('```');\n // Use the final prompt's userTemplate if available, otherwise try to call renderUserPrompt\n const finalPrompt = result.finalPrompt;\n if ('userTemplate' in finalPrompt && typeof finalPrompt.userTemplate === 'string') {\n lines.push(finalPrompt.userTemplate);\n } else {\n lines.push('[Compiled prompt - template not available]');\n }\n lines.push('```');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Saves an ImprovementCycleResult as markdown.\n *\n * @param result - The improvement cycle result\n * @param filePath - Path to save the markdown file\n * @param options - Markdown generation options\n *\n * @example\n * ```typescript\n * import { saveCycleMarkdown } from '@agtlantis/eval'\n *\n * const result = await runImprovementCycleAuto(config)\n * saveCycleMarkdown(result, './reports/cycle-report.md', {\n * includeRoundDetails: true,\n * })\n * ```\n */\nexport function saveCycleMarkdown<TInput, TOutput>(\n result: ImprovementCycleResult<TInput, TOutput>,\n filePath: string,\n options?: CycleMarkdownOptions\n): void {\n const markdown = cycleToMarkdown(result, options);\n writeFileSync(filePath, markdown);\n}\n","import { compileTemplate } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt } from '@/core/types';\nimport { truncate } from '@/utils/json';\n\nimport type { Suggestion } from './types';\n\n/**\n * Generates a unified diff string for a suggestion.\n *\n * @example\n * ```typescript\n * const diff = suggestionDiff(suggestion)\n * console.log(diff)\n * // - Old value here\n * // + New value here\n * ```\n */\nexport function suggestionDiff(suggestion: Suggestion): string {\n const oldLines = suggestion.currentValue.split('\\n');\n const newLines = suggestion.suggestedValue.split('\\n');\n\n const lines: string[] = [];\n lines.push(`--- ${suggestion.type} (current)`);\n lines.push(`+++ ${suggestion.type} (suggested)`);\n lines.push('');\n\n for (const line of oldLines) {\n lines.push(`- ${line}`);\n }\n for (const line of newLines) {\n lines.push(`+ ${line}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Generates a preview of what the suggestion would look like when applied.\n *\n * @example\n * ```typescript\n * const preview = suggestionPreview(suggestion)\n * console.log(preview)\n * ```\n */\nexport function suggestionPreview(suggestion: Suggestion): string {\n const lines: string[] = [];\n\n lines.push(`=== Suggestion Preview ===`);\n lines.push(`Type: ${suggestion.type}`);\n lines.push(`Priority: ${suggestion.priority}`);\n lines.push(``);\n lines.push(`Reasoning: ${suggestion.reasoning}`);\n lines.push(``);\n lines.push(`Expected Improvement: ${suggestion.expectedImprovement}`);\n lines.push(``);\n lines.push(`--- Current Value ---`);\n lines.push(suggestion.currentValue);\n lines.push(``);\n lines.push(`--- Suggested Value ---`);\n lines.push(suggestion.suggestedValue);\n\n return lines.join('\\n');\n}\n\n/**\n * Formats a suggestion as a compact summary string.\n *\n * @example\n * ```typescript\n * console.log(suggestionSummary(suggestion))\n * // [HIGH] system_prompt: Improve clarity in instructions\n * ```\n */\nexport function suggestionSummary(suggestion: Suggestion): string {\n const priorityTag = `[${suggestion.priority.toUpperCase()}]`;\n return `${priorityTag} ${suggestion.type}: ${truncate(suggestion.reasoning, 60)}`;\n}\n\n/**\n * Safely replaces the first occurrence of a search string with a replacement string.\n * Uses a function replacement to avoid special pattern interpretation ($&, $1, etc.)\n * that JavaScript's String.replace() performs.\n *\n * @internal\n */\nfunction safeReplace(str: string, search: string, replacement: string): string {\n return str.replace(search, () => replacement);\n}\n\n/**\n * Options for applying suggestions to a prompt.\n */\nexport interface ApplyPromptSuggestionsOptions {\n /**\n * Version bump type for semver.\n * - 'major': 1.0.0 → 2.0.0 (breaking changes)\n * - 'minor': 1.0.0 → 1.1.0 (new features)\n * - 'patch': 1.0.0 → 1.0.1 (bug fixes)\n */\n bumpVersion?: 'major' | 'minor' | 'patch';\n}\n\n/**\n * Result of applying suggestions to a prompt.\n */\nexport interface ApplySuggestionsResult<TInput, TOutput = unknown> {\n /** The updated prompt with suggestions applied */\n prompt: AgentPrompt<TInput>;\n /** Number of suggestions that were successfully applied */\n appliedCount: number;\n /** Suggestions that could not be applied (currentValue not found) */\n skipped: Array<{ suggestion: Suggestion; reason: string }>;\n}\n\n/**\n * Bumps a semver version string.\n *\n * @example\n * ```typescript\n * bumpVersion('1.0.0', 'major') // '2.0.0'\n * bumpVersion('1.0.0', 'minor') // '1.1.0'\n * bumpVersion('1.0.0', 'patch') // '1.0.1'\n * bumpVersion('1.2.3', 'minor') // '1.3.0'\n * ```\n */\nexport function bumpVersion(version: string, bump: 'major' | 'minor' | 'patch'): string {\n const parts = version.split('.').map((n) => parseInt(n, 10));\n\n // Handle invalid version formats\n if (parts.length !== 3 || parts.some(isNaN)) {\n throw new EvalError(\n `Invalid version format: \"${version}\". Expected semver format (x.y.z)`,\n {\n code: EvalErrorCode.SUGGESTION_APPLY_ERROR,\n context: { version, expectedFormat: 'x.y.z' },\n }\n );\n }\n\n const [major, minor, patch] = parts;\n\n switch (bump) {\n case 'major':\n return `${major + 1}.0.0`;\n case 'minor':\n return `${major}.${minor + 1}.0`;\n case 'patch':\n return `${major}.${minor}.${patch + 1}`;\n }\n}\n\n/**\n * Applies approved suggestions to an AgentPrompt and returns a new prompt.\n *\n * This function:\n * - Only applies suggestions where `approved === true`\n * - For `system_prompt`: replaces `currentValue` in `prompt.system`\n * - For `user_prompt`: requires `prompt.userTemplate` field, updates it and regenerates `renderUserPrompt`\n * - For `parameters`: applies to custom fields in the prompt\n * - Optionally bumps the version (major/minor/patch)\n *\n * **Important behaviors:**\n * - Only the **first occurrence** of `currentValue` is replaced (not all occurrences)\n * - Special characters like `$&`, `$1` in `suggestedValue` are preserved as-is (no regex interpretation)\n *\n * @example\n * ```typescript\n * // Apply approved suggestions with minor version bump\n * const result = applyPromptSuggestions(\n * currentPrompt,\n * suggestions.filter(s => s.approved),\n * { bumpVersion: 'minor' }\n * )\n *\n * console.log(result.prompt.version) // '1.1.0'\n * console.log(`Applied ${result.appliedCount} suggestions`)\n *\n * if (result.skipped.length > 0) {\n * console.warn('Skipped suggestions:', result.skipped)\n * }\n * ```\n *\n * @throws {EvalError} with code SUGGESTION_APPLY_ERROR if:\n * - A `user_prompt` suggestion is applied but prompt lacks `userTemplate` field\n * - Version format is invalid when bumpVersion is specified\n */\nexport function applyPromptSuggestions<TInput, TOutput = unknown>(\n currentPrompt: AgentPrompt<TInput>,\n suggestions: Suggestion[],\n options?: ApplyPromptSuggestionsOptions\n): ApplySuggestionsResult<TInput, TOutput> {\n const approvedSuggestions = suggestions.filter((s) => s.approved);\n\n if (approvedSuggestions.length === 0) {\n return {\n prompt: currentPrompt,\n appliedCount: 0,\n skipped: [],\n };\n }\n\n let newPrompt: AgentPrompt<TInput> = { ...currentPrompt };\n let appliedCount = 0;\n const skipped: Array<{ suggestion: Suggestion; reason: string }> = [];\n\n for (const suggestion of approvedSuggestions) {\n const applyResult = applySingleSuggestion(newPrompt, suggestion);\n\n if (applyResult.success) {\n newPrompt = applyResult.prompt;\n appliedCount++;\n } else {\n skipped.push({ suggestion, reason: applyResult.reason });\n }\n }\n\n if (options?.bumpVersion && appliedCount > 0) {\n newPrompt = {\n ...newPrompt,\n version: bumpVersion(currentPrompt.version, options.bumpVersion),\n };\n }\n\n return {\n prompt: newPrompt,\n appliedCount,\n skipped,\n };\n}\n\n/** Fields that are part of the core AgentPrompt interface and should not be modified by 'parameters' suggestions */\nconst AGENT_PROMPT_CORE_FIELDS = [\n 'id',\n 'version',\n 'system',\n 'renderUserPrompt',\n 'userTemplate',\n] as const;\n\nfunction applySingleSuggestion<TInput, TOutput>(\n prompt: AgentPrompt<TInput>,\n suggestion: Suggestion\n): { success: true; prompt: AgentPrompt<TInput> } | { success: false; reason: string } {\n switch (suggestion.type) {\n case 'system_prompt': {\n if (!prompt.system.includes(suggestion.currentValue)) {\n return {\n success: false,\n reason: `currentValue not found in system prompt: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n return {\n success: true,\n prompt: {\n ...prompt,\n system: safeReplace(\n prompt.system,\n suggestion.currentValue,\n suggestion.suggestedValue\n ),\n },\n };\n }\n\n case 'user_prompt': {\n const userTemplate = prompt.userTemplate as string | undefined;\n\n if (typeof userTemplate !== 'string') {\n throw new EvalError(\n `Cannot apply user_prompt suggestion: prompt does not have a userTemplate field. ` +\n `The renderUserPrompt is a function and cannot be modified directly.`,\n {\n code: EvalErrorCode.SUGGESTION_APPLY_ERROR,\n context: {\n suggestionType: suggestion.type,\n hasUserTemplate: 'userTemplate' in prompt,\n },\n }\n );\n }\n\n if (!userTemplate.includes(suggestion.currentValue)) {\n return {\n success: false,\n reason: `currentValue not found in userTemplate: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n\n const newTemplate = safeReplace(\n userTemplate,\n suggestion.currentValue,\n suggestion.suggestedValue\n );\n\n return {\n success: true,\n prompt: {\n ...prompt,\n userTemplate: newTemplate,\n renderUserPrompt: compileTemplate<TInput>(newTemplate, prompt.id),\n },\n };\n }\n\n case 'parameters': {\n const updatedPrompt = { ...prompt };\n let found = false;\n\n for (const [key, value] of Object.entries(updatedPrompt)) {\n if (\n AGENT_PROMPT_CORE_FIELDS.includes(\n key as (typeof AGENT_PROMPT_CORE_FIELDS)[number]\n )\n ) {\n continue;\n }\n\n if (typeof value === 'string' && value.includes(suggestion.currentValue)) {\n (updatedPrompt as Record<string, unknown>)[key] = safeReplace(\n value,\n suggestion.currentValue,\n suggestion.suggestedValue\n );\n found = true;\n break;\n }\n }\n\n if (!found) {\n return {\n success: false,\n reason: `currentValue not found in any parameter field: \"${truncate(suggestion.currentValue, 50)}\"`,\n };\n }\n\n return {\n success: true,\n prompt: updatedPrompt,\n };\n }\n\n default: {\n const _exhaustive: never = suggestion.type;\n return {\n success: false,\n reason: `Unknown suggestion type: ${suggestion.type}`,\n };\n }\n }\n}\n","import { type LanguageModelUsage, type ModelMessage, Output } from 'ai';\nimport { z } from 'zod';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt, EvalTestResult, EvalTokenUsage, ImproverMetadata } from '@/core/types';\n\nimport { defaultImproverPrompt } from './prompts/default';\nimport type {\n AggregatedMetrics,\n ImproveResult,\n Improver,\n ImproverConfig,\n ImproverContext,\n Suggestion,\n} from './types';\n\nfunction toEvalTokenUsage(usage: LanguageModelUsage): EvalTokenUsage {\n return {\n inputTokens: usage.inputTokens ?? 0,\n outputTokens: usage.outputTokens ?? 0,\n totalTokens: usage.totalTokens ?? 0,\n };\n}\n\nconst ImproverResponseSchema = z.object({\n suggestions: z.array(\n z.object({\n type: z.enum(['system_prompt', 'user_prompt', 'parameters']),\n priority: z.enum(['high', 'medium', 'low']),\n currentValue: z.string(),\n suggestedValue: z.string(),\n reasoning: z.string(),\n expectedImprovement: z.string(),\n })\n ),\n});\n\ntype ImproverResponse = z.infer<typeof ImproverResponseSchema>;\n\nfunction aggregateMetrics(results: EvalTestResult<unknown, unknown>[]): AggregatedMetrics {\n if (results.length === 0) {\n return {\n avgLatencyMs: 0,\n totalTokens: 0,\n };\n }\n\n let totalLatency = 0;\n let totalTokens = 0;\n\n for (const result of results) {\n totalLatency += result.metrics.latencyMs;\n totalTokens += result.metrics.tokenUsage.totalTokens;\n }\n\n return {\n avgLatencyMs: Math.round(totalLatency / results.length),\n totalTokens,\n };\n}\n\n/**\n * Creates an LLM-based prompt improver.\n *\n * Analyzes test results and suggests improvements to the agent's prompt,\n * focusing on low-scoring criteria with actionable suggestions.\n *\n * @example\n * ```typescript\n * import { createImprover, defaultImproverPrompt } from '@agtlantis/eval'\n * import { createGoogleProvider } from '@agtlantis/core'\n *\n * const provider = createGoogleProvider({ apiKey }).withDefaultModel('gemini-2.5-flash')\n *\n * const improver = createImprover({\n * provider,\n * prompt: defaultImproverPrompt,\n * })\n *\n * const { suggestions } = await improver.improve(agent.prompt, evaluatedResults)\n *\n * for (const suggestion of suggestions) {\n * console.log(suggestionDiff(suggestion))\n * suggestion.approved = true\n * }\n *\n * const newPrompt = applyPromptSuggestions(agent.prompt, suggestions)\n * ```\n */\nexport function createImprover(config: ImproverConfig): Improver {\n const { provider, prompt = defaultImproverPrompt, model } = config;\n\n return {\n async improve(\n agentPrompt: AgentPrompt<any>,\n results: EvalTestResult<any, any>[]\n ): Promise<ImproveResult> {\n const context: ImproverContext = {\n agentPrompt,\n evaluatedResults: results,\n aggregatedMetrics: aggregateMetrics(results),\n };\n\n const messages: ModelMessage[] = [\n { role: 'system', content: prompt.system },\n { role: 'user', content: prompt.renderUserPrompt(context) },\n ];\n\n let response: ImproverResponse;\n let llmUsage: LanguageModelUsage | undefined;\n\n try {\n const execution = provider.simpleExecution(async (session) => {\n const result = await session.generateText({\n messages,\n output: Output.object({ schema: ImproverResponseSchema }),\n });\n return result.output!;\n });\n\n const executionResult = await execution.result();\n\n if (executionResult.status !== 'succeeded') {\n throw executionResult.status === 'failed'\n ? executionResult.error\n : new Error('Execution was canceled');\n }\n\n response = executionResult.value;\n llmUsage = executionResult.summary.totalLLMUsage;\n } catch (cause) {\n throw EvalError.from(cause, EvalErrorCode.LLM_API_ERROR, {\n promptId: prompt.id,\n promptVersion: prompt.version,\n });\n }\n\n const suggestions: Suggestion[] = response.suggestions.map((s) => ({\n ...s,\n approved: undefined,\n modified: undefined,\n }));\n\n const metadata: ImproverMetadata | undefined = llmUsage\n ? { tokenUsage: toEvalTokenUsage(llmUsage), model }\n : undefined;\n\n return { suggestions, metadata };\n },\n };\n}\n","import { truncate } from '@/utils/json';\n\nimport type { ImproverContext, ImproverPrompt } from '../types';\n\nexport const defaultImproverPrompt: ImproverPrompt = {\n id: 'default-improver',\n version: '2.0.0',\n\n system: `You are an expert prompt engineer specializing in optimizing AI Agent prompts.\n\nYour role is to analyze test results and evaluation feedback to propose targeted improvements.\n\n## Improvement Principles\n\n1. **Focus on Impact**: Prioritize changes that address the lowest-scoring criteria\n - Target specific failure patterns, not general improvements\n - One well-crafted change is better than many superficial ones\n\n2. **Be Specific and Actionable**: Provide concrete changes, not vague suggestions\n - Show exact text to add, modify, or remove\n - Explain the mechanism by which the change will help\n\n3. **Consider Trade-offs**: Evaluate side effects of each change\n - Will this fix break other test cases?\n - Does it increase prompt length/cost significantly?\n - Could it introduce new failure modes?\n\n4. **Maintain Prompt Quality**: Preserve clarity and structure\n - Keep prompts readable and maintainable\n - Avoid over-engineering or excessive constraints\n - Ensure changes align with the agent's core purpose\n\n## Suggestion Priority Levels\n- **high**: Critical issues causing test failures, should be addressed immediately\n- **medium**: Issues affecting quality scores, recommended for next iteration\n- **low**: Minor optimizations, nice-to-have improvements\n\n## Response Format\n\nYou MUST respond with valid JSON only. No additional text outside the JSON structure.\n\n{\n \"suggestions\": [\n {\n \"type\": \"system_prompt\" | \"user_prompt\" | \"parameters\",\n \"priority\": \"high\" | \"medium\" | \"low\",\n \"currentValue\": \"The specific text or value being changed\",\n \"suggestedValue\": \"The proposed replacement text or value\",\n \"reasoning\": \"Why this change addresses the identified issue\",\n \"expectedImprovement\": \"Predicted impact on scores and behavior\"\n }\n ]\n}`,\n\n renderUserPrompt: (ctx: ImproverContext): string => {\n const failedDetails = buildFailedCaseDetails(ctx.evaluatedResults);\n\n return `\n## Current Agent Prompt\n\n### System Prompt\n\\`\\`\\`\n${ctx.agentPrompt.system}\n\\`\\`\\`\n\n## Test Results Summary\n- Total tests: ${ctx.evaluatedResults.length}\n- Passed: ${ctx.evaluatedResults.filter((r) => r.passed).length}\n- Failed: ${ctx.evaluatedResults.filter((r) => !r.passed).length}\n\n## Performance Metrics\n- Average latency: ${ctx.aggregatedMetrics.avgLatencyMs}ms\n- Total tokens used: ${ctx.aggregatedMetrics.totalTokens}\n\n## Failed/Low-Score Cases Details\n${failedDetails}\n\nBased on the above results, please propose specific prompt improvements.`.trim();\n },\n};\n\nfunction buildFailedCaseDetails(results: ImproverContext['evaluatedResults']): string {\n const failedOrLowScore = results.filter((r) => !r.passed || r.overallScore < 70);\n\n if (failedOrLowScore.length === 0) {\n return '(None - all tests passed with acceptable scores)';\n }\n\n return failedOrLowScore\n .map(\n (r) => `\n### ${r.testCase.id ?? 'unnamed'} (Score: ${r.overallScore})\n**Input:** ${truncate(JSON.stringify(r.testCase.input), 200)}\n**Output:** ${truncate(JSON.stringify(r.output), 200)}\n**Evaluation:**\n${r.verdicts.map((v) => `- ${v.criterionId}: ${v.score}/100 - ${v.reasoning}`).join('\\n')}`\n )\n .join('\\n');\n}\n","import type {\n AgentPrompt,\n EvalAgent,\n EvalTokenUsage,\n TestResultWithVerdict,\n Verdict,\n} from '@/core/types';\nimport type { ImproveResult, Improver, Suggestion } from '@/improver/types';\nimport type { EvalContext, Judge, JudgeResult } from '@/judge/types';\n\n/**\n * Configuration for creating a mock agent.\n */\nexport interface MockAgentConfig<TInput, TOutput> {\n /** Name for the mock agent */\n name?: string;\n\n /** Description for the mock agent */\n description?: string;\n\n /** Response to return from execute() */\n response?: TOutput;\n\n /** Token usage to include in metadata */\n tokenUsage?: EvalTokenUsage;\n\n /** Delay in ms before returning response */\n delay?: number;\n\n /** If true, throw an error instead of returning response */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom execute function for more control */\n executeFn?: (\n input: TInput\n ) => Promise<{ result: TOutput; metadata?: { tokenUsage?: EvalTokenUsage } }>;\n}\n\n/**\n * Creates a mock agent for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const agent = createMockAgent<{ query: string }, { answer: string }>({\n * response: { answer: 'Hello!' },\n * })\n *\n * // With delay and token usage\n * const agent = createMockAgent({\n * response: { answer: 'Response' },\n * delay: 100,\n * tokenUsage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n * })\n *\n * // Error testing\n * const agent = createMockAgent({\n * shouldError: true,\n * errorMessage: 'Agent failed',\n * })\n * ```\n */\nexport function createMockAgent<TInput, TOutput>(\n config: MockAgentConfig<TInput, TOutput> = {}\n): EvalAgent<TInput, TOutput> {\n const {\n name = 'MockAgent',\n description = 'A mock agent for testing',\n response = {} as TOutput,\n tokenUsage = { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n delay = 0,\n shouldError = false,\n errorMessage = 'Mock agent execution failed',\n executeFn,\n } = config;\n\n return {\n config: { name, description },\n prompt: {\n id: 'mock-prompt',\n version: '1.0.0',\n system: 'You are a mock agent',\n renderUserPrompt: (input: TInput) => JSON.stringify(input),\n },\n execute: async (input: TInput) => {\n if (executeFn) {\n return executeFn(input);\n }\n\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return {\n result: response,\n metadata: { tokenUsage },\n };\n },\n };\n}\n\n/**\n * Configuration for creating a mock judge.\n */\nexport interface MockJudgeConfig {\n /** Overall score to return (0-100) */\n score?: number;\n\n /** Whether the evaluation passed */\n passed?: boolean;\n\n /** Verdicts to return */\n verdicts?: Verdict[];\n\n /** Metadata to return (for cost tracking tests) */\n metadata?: JudgeResult['metadata'];\n\n /** If true, throw an error instead of returning result */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom evaluate function for more control */\n evaluateFn?: (context: EvalContext) => Promise<JudgeResult>;\n}\n\n/**\n * Creates a mock judge for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage - passing test\n * const judge = createMockJudge({\n * score: 85,\n * passed: true,\n * })\n *\n * // Custom verdicts\n * const judge = createMockJudge({\n * verdicts: [\n * { criterionId: 'accuracy', score: 90, reasoning: 'Good', passed: true },\n * { criterionId: 'clarity', score: 80, reasoning: 'Clear', passed: true },\n * ],\n * score: 85,\n * passed: true,\n * })\n *\n * // Failing test\n * const judge = createMockJudge({\n * score: 40,\n * passed: false,\n * })\n *\n * // Error testing\n * const judge = createMockJudge({\n * shouldError: true,\n * errorMessage: 'Judge failed to evaluate',\n * })\n * ```\n */\nexport function createMockJudge(config: MockJudgeConfig = {}): Judge {\n const {\n score = 80,\n passed = true,\n verdicts = [\n { criterionId: 'default', score: 80, reasoning: 'Default verdict', passed: true },\n ],\n metadata,\n shouldError = false,\n errorMessage = 'Mock judge evaluation failed',\n evaluateFn,\n } = config;\n\n return {\n evaluate: async (context: EvalContext) => {\n if (evaluateFn) {\n return evaluateFn(context);\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return {\n verdicts,\n overallScore: score,\n passed,\n metadata,\n };\n },\n };\n}\n\n/**\n * Configuration for creating a mock improver.\n */\nexport interface MockImproverConfig {\n /** Suggestions to return */\n suggestions?: Suggestion[];\n\n /** If true, throw an error instead of returning suggestions */\n shouldError?: boolean;\n\n /** Custom error message when shouldError is true */\n errorMessage?: string;\n\n /** Custom improve function for more control */\n improveFn?: (\n agentPrompt: AgentPrompt<any>,\n results: TestResultWithVerdict<any, any>[]\n ) => Promise<ImproveResult>;\n}\n\n/**\n * Creates a mock improver for testing purposes.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const improver = createMockImprover({\n * suggestions: [\n * {\n * type: 'system_prompt',\n * priority: 'high',\n * currentValue: 'Old prompt',\n * suggestedValue: 'New prompt',\n * reasoning: 'Better clarity',\n * expectedImprovement: '10% improvement',\n * },\n * ],\n * })\n *\n * // Empty suggestions\n * const improver = createMockImprover({ suggestions: [] })\n *\n * // Error testing\n * const improver = createMockImprover({\n * shouldError: true,\n * errorMessage: 'Improver failed',\n * })\n * ```\n */\nexport function createMockImprover(config: MockImproverConfig = {}): Improver {\n const {\n suggestions = [],\n shouldError = false,\n errorMessage = 'Mock improver failed',\n improveFn,\n } = config;\n\n return {\n improve: async (agentPrompt, results) => {\n if (improveFn) {\n return improveFn(agentPrompt, results);\n }\n\n if (shouldError) {\n throw new Error(errorMessage);\n }\n\n return { suggestions };\n },\n };\n}\n","/**\n * CLI Configuration Types\n *\n * Defines the configuration schema for `agent-eval.config.ts` files.\n * Use `defineConfig()` helper for type inference and IDE autocompletion.\n */\n\nimport type {\n EvalAgent,\n TestCase,\n Criterion,\n ValidatorCriterion,\n FileContent,\n} from '@/core/types'\nimport type { JudgePrompt } from '@/judge/types'\nimport type { ImproverPrompt } from '@/improver/types'\nimport type { EvalPricingConfig } from '@/reporter/cost-helpers'\nimport type {\n MultiTurnTestCase,\n TerminationCondition,\n FollowUpInput,\n} from '@/multi-turn/types'\n\n/**\n * LLM provider configuration.\n * API keys fall back to OPENAI_API_KEY or GOOGLE_API_KEY env vars.\n */\nexport interface LLMConfig {\n /** LLM provider */\n provider: 'openai' | 'gemini'\n /** API key (optional - falls back to environment variable) */\n apiKey?: string\n /** Default model to use */\n defaultModel?: string\n /**\n * OpenAI reasoning effort (o1/o3 models only)\n * @see https://platform.openai.com/docs/guides/reasoning\n */\n reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high'\n /**\n * Default response format\n * @see https://platform.openai.com/docs/guides/structured-outputs\n */\n defaultResponseFormat?: { type: 'json_object' | 'text' }\n}\n\nexport interface CLIJudgeConfig {\n /**\n * LLM configuration for judge.\n * If not specified, uses the main `llm` config.\n */\n llm?: LLMConfig\n /**\n * Evaluation criteria.\n * Use built-in criteria factories like `accuracy()`, `relevance()`,\n * or define custom criteria objects.\n */\n criteria: Array<Criterion | ValidatorCriterion>\n /**\n * Score threshold for passing (0-100).\n * @default 70\n */\n passThreshold?: number\n /**\n * Custom judge prompt.\n * If not specified, uses the default judge prompt.\n */\n prompt?: JudgePrompt\n}\n\nexport interface CLIImproverConfig {\n /**\n * LLM configuration for improver.\n * If not specified, uses the main `llm` config.\n */\n llm?: LLMConfig\n /**\n * Custom improver prompt.\n * If not specified, uses the default improver prompt.\n */\n prompt?: ImproverPrompt\n}\n\nexport interface OutputConfig {\n /**\n * Directory for report output.\n * @default './reports'\n */\n dir?: string\n /**\n * Custom filename pattern.\n * Supports `{timestamp}` placeholder.\n * @default 'eval-{timestamp}.md'\n */\n filename?: string\n /**\n * Include verbose details in console output.\n * @default false\n */\n verbose?: boolean\n}\n\nexport interface RunConfig {\n /**\n * Number of concurrent test executions.\n * @default 1\n */\n concurrency?: number\n /**\n * Number of iterations per test case (for statistical analysis).\n * @default 1\n */\n iterations?: number\n /**\n * Stop execution on first test failure.\n * @default false\n */\n stopOnFirstFailure?: boolean\n}\n\nexport interface CLISingleTurnTestCase<TInput> extends TestCase<TInput> {\n /** Test case must NOT have multiTurn field */\n multiTurn?: never\n}\n\nexport interface CLIMultiTurnTestCase<TInput, TOutput = unknown>\n extends TestCase<TInput> {\n /** Multi-turn configuration */\n multiTurn: {\n /**\n * Inputs for 2nd turn onwards.\n * First turn uses `input` field.\n */\n followUpInputs?: FollowUpInput<TInput, TOutput>[]\n /**\n * Termination conditions (OR relationship).\n * Any one triggers termination.\n */\n terminateWhen: TerminationCondition<TInput, TOutput>[]\n /**\n * Safety limit: maximum turns.\n * @default 10\n */\n maxTurns?: number\n /**\n * Outcome when termination condition is met.\n * @default 'pass'\n */\n onConditionMet?: 'pass' | 'fail'\n /**\n * Outcome when maxTurns is reached.\n * @default 'fail'\n */\n onMaxTurnsReached?: 'pass' | 'fail'\n }\n}\n\nexport type CLITestCase<TInput, TOutput = unknown> =\n | CLISingleTurnTestCase<TInput>\n | CLIMultiTurnTestCase<TInput, TOutput>\n\n/**\n * Main evaluation configuration for CLI.\n * @typeParam TInput - Agent input type\n * @typeParam TOutput - Agent output type\n */\nexport interface EvalConfig<TInput = unknown, TOutput = unknown> {\n /**\n * Human-readable name for this evaluation.\n */\n name?: string\n\n /**\n * Description of what the agent does.\n * Used by Judge for evaluation context.\n */\n agentDescription?: string\n\n /**\n * The agent to evaluate.\n */\n agent: EvalAgent<TInput, TOutput>\n\n /**\n * LLM configuration (shared by Judge and Improver unless overridden).\n */\n llm: LLMConfig\n\n /**\n * Judge configuration for evaluating agent outputs.\n */\n judge: CLIJudgeConfig\n\n /**\n * Improver configuration for prompt improvement suggestions.\n * Optional - if not specified, no improvements are generated.\n */\n improver?: CLIImproverConfig\n\n /**\n * Test cases to run (inline TypeScript definition).\n * Can mix single-turn and multi-turn test cases.\n *\n * Either `testCases` or `include` must be provided.\n * - Use `testCases` for inline TypeScript test case definitions\n * - Use `include` for YAML-based test case files\n */\n testCases?: CLITestCase<TInput, TOutput>[]\n\n /**\n * Output configuration for reports.\n */\n output?: OutputConfig\n\n /**\n * Run configuration for test execution.\n */\n run?: RunConfig\n\n /**\n * Pricing configuration for cost calculation.\n * If provided, cost breakdown will be included in test metrics.\n *\n * @example\n * ```typescript\n * pricing: {\n * openai: { 'gpt-4o': { inputPricePerMillion: 2.5, outputPricePerMillion: 10 } },\n * fallback: { inputPricePerMillion: 1.0, outputPricePerMillion: 3.0 },\n * }\n * ```\n */\n pricing?: EvalPricingConfig\n\n /**\n * Glob patterns to discover YAML eval files.\n * Required when using YAML-based test cases instead of inline testCases.\n *\n * @example\n * ```typescript\n * include: ['evals/booking/*.eval.yaml']\n * ```\n */\n include?: string[]\n\n /**\n * Agent registry for YAML file references.\n * YAML files reference agents by name (e.g., `agent: booking-agent`).\n *\n * @example\n * ```typescript\n * agents: {\n * 'booking-agent': bookingAgent,\n * 'qa-agent': qaAgent,\n * }\n * ```\n */\n agents?: Record<string, EvalAgent<unknown, unknown>>\n}\n\n/** Identity function for type inference and IDE autocompletion. */\nexport function defineConfig<TInput = unknown, TOutput = unknown>(\n config: EvalConfig<TInput, TOutput>\n): EvalConfig<TInput, TOutput> {\n return config\n}\n\nexport function isMultiTurnConfig<TInput, TOutput>(\n testCase: CLITestCase<TInput, TOutput>\n): testCase is CLIMultiTurnTestCase<TInput, TOutput> {\n return 'multiTurn' in testCase && testCase.multiTurn !== undefined\n}\n","import { existsSync } from 'node:fs'\nimport { resolve, extname } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { bundleRequire } from 'bundle-require'\nimport fg from 'fast-glob'\nimport { validateConfig, type ValidatedEvalConfig } from './schema.js'\nimport type { EvalConfig } from './types.js'\n\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly code: ConfigErrorCode,\n public readonly context?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'ConfigError'\n }\n}\n\nexport type ConfigErrorCode =\n | 'CONFIG_NOT_FOUND'\n | 'CONFIG_LOAD_ERROR'\n | 'CONFIG_NO_DEFAULT_EXPORT'\n | 'CONFIG_VALIDATION_ERROR'\n | 'CONFIG_NO_INCLUDE_PATTERN'\n\nexport const DEFAULT_CONFIG_FILE = 'agent-eval.config.ts'\n\nexport const SUPPORTED_EXTENSIONS = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs']\n\nexport function resolveConfigPath(\n configPath: string = DEFAULT_CONFIG_FILE,\n cwd: string = process.cwd()\n): string {\n return resolve(cwd, configPath)\n}\n\nexport async function loadConfig(configPath: string): Promise<EvalConfig> {\n const absolutePath = resolve(process.cwd(), configPath)\n\n if (!existsSync(absolutePath)) {\n throw new ConfigError(\n `Config file not found: ${configPath}\\n\\n` +\n `Create an ${DEFAULT_CONFIG_FILE} file or specify a path:\\n` +\n ` npx agent-eval run ./path/to/config.ts`,\n 'CONFIG_NOT_FOUND',\n { path: absolutePath }\n )\n }\n\n const ext = extname(absolutePath).toLowerCase()\n if (!SUPPORTED_EXTENSIONS.includes(ext)) {\n throw new ConfigError(\n `Unsupported config file extension: ${ext}\\n` +\n `Supported extensions: ${SUPPORTED_EXTENSIONS.join(', ')}`,\n 'CONFIG_LOAD_ERROR',\n { path: absolutePath, extension: ext }\n )\n }\n\n let mod: { default?: EvalConfig } | EvalConfig\n\n try {\n if (ext === '.ts' || ext === '.mts' || ext === '.cts') {\n const result = await bundleRequire({\n filepath: absolutePath,\n format: 'esm',\n esbuildOptions: { sourcemap: 'inline' },\n })\n mod = result.mod\n } else {\n const fileUrl = pathToFileURL(absolutePath).href\n mod = await import(fileUrl)\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ConfigError(\n `Failed to load config file: ${configPath}\\n\\n` +\n `Error: ${message}\\n\\n` +\n `Make sure the file is valid TypeScript/JavaScript and has no syntax errors.`,\n 'CONFIG_LOAD_ERROR',\n { path: absolutePath, originalError: message }\n )\n }\n\n const config = 'default' in mod ? mod.default : mod\n\n if (!config || typeof config !== 'object') {\n throw new ConfigError(\n `Config file must export a default configuration object.\\n\\n` +\n `Example:\\n` +\n ` import { defineConfig } from '@agtlantis/eval'\\n` +\n ` export default defineConfig({ ... })`,\n 'CONFIG_NO_DEFAULT_EXPORT',\n { path: absolutePath }\n )\n }\n\n try {\n validateConfig(config)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new ConfigError(\n message,\n 'CONFIG_VALIDATION_ERROR',\n { path: absolutePath }\n )\n }\n\n return config as EvalConfig\n}\n\nexport async function loadConfigWithDefaults(\n configPath?: string,\n cwd?: string\n): Promise<EvalConfig> {\n const resolvedPath = resolveConfigPath(configPath, cwd)\n return loadConfig(resolvedPath)\n}\n\nexport interface DiscoverOptions {\n /** Override config include patterns (CLI --include) */\n include?: string[]\n /** Base directory for glob patterns (defaults to process.cwd()) */\n cwd?: string\n /** Ignore patterns (default excludes node_modules) */\n ignore?: string[]\n}\n\n/** Discover YAML eval files matching glob patterns. CLI patterns override config. */\nexport async function discoverEvalFiles(\n config: Pick<EvalConfig, 'include'>,\n options: DiscoverOptions = {}\n): Promise<string[]> {\n const patterns = options.include ?? config.include\n\n if (!patterns || patterns.length === 0) {\n throw new ConfigError(\n 'No include patterns specified.\\n\\n' +\n 'Add an include field to your config:\\n' +\n \" include: ['evals/**/*.eval.yaml']\\n\\n\" +\n 'Or use the --include CLI option:\\n' +\n ' npx agent-eval --include \"evals/**/*.eval.yaml\"',\n 'CONFIG_NO_INCLUDE_PATTERN'\n )\n }\n\n const cwd = options.cwd ?? process.cwd()\n const ignore = options.ignore ?? ['**/node_modules/**']\n\n const files = await fg(patterns, {\n absolute: true,\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n followSymbolicLinks: false,\n unique: true,\n suppressErrors: false,\n })\n\n return files.sort()\n}\n","import { z } from 'zod';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\n\nexport const llmConfigSchema = z.object({\n provider: z.enum(['openai', 'gemini'], {\n error: \"provider must be 'openai' or 'gemini'\",\n }),\n apiKey: z.string().optional(),\n defaultModel: z.string().optional(),\n reasoningEffort: z.enum(['minimal', 'low', 'medium', 'high']).optional(),\n defaultResponseFormat: z\n .object({\n type: z.enum(['json_object', 'text']),\n })\n .optional(),\n});\n\nexport const criterionSchema = z.object({\n id: z.string().min(1, 'Criterion id is required'),\n name: z.string().min(1, 'Criterion name is required'),\n description: z.string().min(1, 'Criterion description is required'),\n weight: z.number().positive().optional(),\n validator: z.function().optional(),\n});\n\nexport const judgeConfigSchema = z.object({\n llm: llmConfigSchema.optional(),\n criteria: z.array(criterionSchema).min(1, 'At least one criterion is required'),\n passThreshold: z.number().min(0).max(100).optional(),\n prompt: z.any().optional(),\n});\n\nexport const improverConfigSchema = z\n .object({\n llm: llmConfigSchema.optional(),\n prompt: z.any().optional(),\n })\n .optional();\n\nexport const outputConfigSchema = z\n .object({\n dir: z.string().optional(),\n filename: z.string().optional(),\n verbose: z.boolean().optional(),\n })\n .optional();\n\nexport const runConfigSchema = z\n .object({\n concurrency: z.number().int().positive().optional(),\n iterations: z.number().int().positive().optional(),\n stopOnFirstFailure: z.boolean().optional(),\n })\n .optional();\n\nconst maxTurnsConditionSchema = z.object({\n type: z.literal('maxTurns'),\n count: z.number().int().positive(),\n});\n\nconst fieldSetConditionSchema = z.object({\n type: z.literal('fieldSet'),\n fieldPath: z.string().min(1),\n});\n\nconst fieldValueConditionSchema = z.object({\n type: z.literal('fieldValue'),\n fieldPath: z.string().min(1),\n expectedValue: z.unknown(),\n});\n\nconst customConditionSchema = z.object({\n type: z.literal('custom'),\n check: z.function(),\n description: z.string().optional(),\n});\n\nexport const terminationConditionSchema = z.union([\n maxTurnsConditionSchema,\n fieldSetConditionSchema,\n fieldValueConditionSchema,\n customConditionSchema,\n]);\n\nexport const followUpInputSchema = z.object({\n input: z.unknown(),\n description: z.string().optional(),\n turns: z.number().optional(),\n});\n\nexport const multiTurnConfigSchema = z.object({\n followUpInputs: z.array(followUpInputSchema).optional(),\n terminateWhen: z\n .array(terminationConditionSchema)\n .min(1, 'At least one termination condition is required'),\n maxTurns: z.number().int().positive().optional(),\n onConditionMet: z.enum(['pass', 'fail']).optional(),\n onMaxTurnsReached: z.enum(['pass', 'fail']).optional(),\n});\n\nexport const testCaseSchema = z.object({\n id: z.string().optional(),\n input: z.unknown(),\n tags: z.array(z.string()).optional(),\n description: z.string().optional(),\n expectedOutput: z.unknown().optional(),\n files: z.array(z.any()).optional(),\n multiTurn: multiTurnConfigSchema.optional(),\n});\n\nexport const agentSchema = z.object({\n config: z.object({\n name: z.string(),\n description: z.string().optional(),\n }),\n prompt: z.object({\n id: z.string(),\n version: z.string(),\n system: z.string(),\n renderUserPrompt: z.function(),\n }),\n execute: z.function(),\n});\n\nexport const evalConfigSchema = z\n .object({\n name: z.string().optional(),\n agentDescription: z.string().optional(),\n agent: agentSchema,\n llm: llmConfigSchema,\n judge: judgeConfigSchema,\n improver: improverConfigSchema,\n testCases: z.array(testCaseSchema).optional(),\n output: outputConfigSchema,\n run: runConfigSchema,\n include: z\n .array(z.string().min(1, 'Include pattern cannot be empty'))\n .min(1, 'Include array must have at least one pattern')\n .optional(),\n agents: z.record(z.string(), agentSchema).optional(),\n })\n .refine(\n (data) => {\n const hasTestCases = (data.testCases?.length ?? 0) > 0;\n const hasInclude = (data.include?.length ?? 0) > 0;\n return hasTestCases || hasInclude;\n },\n {\n message:\n 'Either testCases or include must be provided. ' +\n 'Use testCases for inline TypeScript tests, or include for YAML file discovery.',\n path: ['testCases'],\n }\n );\n\nexport type ValidatedLLMConfig = z.infer<typeof llmConfigSchema>;\nexport type ValidatedJudgeConfig = z.infer<typeof judgeConfigSchema>;\nexport type ValidatedImproverConfig = z.infer<typeof improverConfigSchema>;\nexport type ValidatedOutputConfig = z.infer<typeof outputConfigSchema>;\nexport type ValidatedRunConfig = z.infer<typeof runConfigSchema>;\nexport type ValidatedTestCase = z.infer<typeof testCaseSchema>;\nexport type ValidatedEvalConfig = z.infer<typeof evalConfigSchema>;\n\nexport function validateConfig(config: unknown): ValidatedEvalConfig {\n const result = evalConfigSchema.safeParse(config);\n\n if (!result.success) {\n const errors = result.error.issues\n .map((issue) => {\n const path = issue.path.join('.');\n return path ? ` - ${path}: ${issue.message}` : ` - ${issue.message}`;\n })\n .join('\\n');\n\n throw new EvalError(`Invalid configuration:\\n${errors}`, {\n code: EvalErrorCode.INVALID_CONFIG,\n });\n }\n\n return result.data;\n}\n\nexport function validateConfigPartial(config: unknown): {\n success: boolean;\n errors?: string[];\n} {\n const result = evalConfigSchema.safeParse(config);\n\n if (result.success) {\n return { success: true };\n }\n\n return {\n success: false,\n errors: result.error.issues.map((issue) => {\n const path = issue.path.join('.');\n return path ? `${path}: ${issue.message}` : issue.message;\n }),\n };\n}\n","import type { AgentPrompt, EvalAgent, TestCase } from '@/core/types';\nimport type { Improver, Suggestion } from '@/improver/types';\nimport type { Judge } from '@/judge/types';\nimport type { EvalPricingConfig } from '@/reporter/cost-helpers';\nimport type { EvalReport } from '@/reporter/types';\n\nimport type { ImprovementSession } from './history';\n\n/** Terminate when average score reaches threshold */\nexport interface TargetScoreCondition {\n type: 'targetScore';\n /** Score threshold (0-100) */\n threshold: number;\n}\n\n/** Terminate after N rounds */\nexport interface MaxRoundsCondition {\n type: 'maxRounds';\n /** Maximum number of improvement rounds */\n count: number;\n}\n\n/** Terminate when score doesn't improve for N consecutive rounds */\nexport interface NoImprovementCondition {\n type: 'noImprovement';\n /** Number of consecutive rounds without improvement */\n consecutiveRounds: number;\n /** Minimum score delta to count as improvement (default: 0) */\n minDelta?: number;\n}\n\n/** Terminate when total cost exceeds budget */\nexport interface MaxCostCondition {\n type: 'maxCost';\n /** Maximum cost in USD */\n maxUSD: number;\n}\n\n/** Custom condition with user-defined check function */\nexport interface CustomCycleCondition {\n type: 'custom';\n /** Function to check if termination condition is met */\n check: (ctx: CycleContext) => boolean | Promise<boolean>;\n /** Human-readable description (for debugging/logging) */\n description?: string;\n}\n\n/** Discriminated union of termination conditions. Uses OR semantics - first match triggers. */\nexport type CycleTerminationCondition =\n | TargetScoreCondition\n | MaxRoundsCondition\n | NoImprovementCondition\n | MaxCostCondition\n | CustomCycleCondition;\n\n/** Context available to termination condition checks */\nexport interface CycleContext {\n /** Current round number (1-indexed) */\n currentRound: number;\n /** Average score from the latest round */\n latestScore: number;\n /** Score history from all previous rounds */\n previousScores: number[];\n /** Total accumulated cost in USD */\n totalCost: number;\n /** Full history of completed rounds */\n history: RoundResult[];\n}\n\n/** Result when cycle should continue (no termination) */\nexport interface CycleContinueResult {\n terminated: false;\n reason: string;\n /** Not present when not terminated (for type safety with discriminated union) */\n matchedCondition?: never;\n}\n\n/** Result when cycle should terminate */\nexport interface CycleTerminatedResult {\n terminated: true;\n matchedCondition: CycleTerminationCondition;\n reason: string;\n}\n\nexport type CycleTerminationResult = CycleContinueResult | CycleTerminatedResult;\n\n/**\n * Data yielded after each improvement round for Human-in-the-Loop (HITL) control.\n * The AsyncGenerator yields this after each round, allowing inspection and decision.\n */\nexport interface RoundYield {\n /** Result of the completed round */\n roundResult: RoundResult;\n /** Current cycle context */\n context: CycleContext;\n /** Suggestions awaiting approval */\n pendingSuggestions: Suggestion[];\n /** Termination check result (use isCycleTerminated() to check if terminated) */\n terminationCheck: CycleTerminationResult;\n}\n\n/** Decision from the caller after reviewing a round */\nexport interface RoundDecision {\n /** Action to take */\n action: 'continue' | 'stop' | 'rollback';\n /** Target round for rollback (required if action is 'rollback') */\n rollbackToRound?: number;\n /** Suggestions approved by user (optional override) */\n approvedSuggestions?: Suggestion[];\n}\n\n/** Cost breakdown for a single round */\nexport interface RoundCost {\n /** Agent LLM cost in USD */\n agent: number;\n /** Judge LLM cost in USD */\n judge: number;\n /** Improver LLM cost in USD */\n improver: number;\n /** Total cost in USD */\n total: number;\n}\n\n/** Result of a single improvement round */\nexport interface RoundResult {\n /** Round number (1-indexed) */\n round: number;\n /** When this round completed */\n completedAt: Date;\n /** Full evaluation report */\n report: EvalReport<unknown, unknown>;\n /** All suggestions generated by improver */\n suggestionsGenerated: Suggestion[];\n /** Suggestions that were approved/applied */\n suggestionsApproved: Suggestion[];\n /** Prompt snapshot at start of this round (for rollback) */\n promptSnapshot: SerializedPrompt;\n /** Prompt version after applying suggestions */\n promptVersionAfter: string;\n /** Cost breakdown for this round */\n cost: RoundCost;\n /** Score change from previous round (null for first round) */\n scoreDelta: number | null;\n}\n\n/**\n * Serialized prompt for JSON storage.\n * Note: renderUserPrompt cannot be serialized; use compileTemplate(userTemplate) to reconstruct.\n */\nexport interface SerializedPrompt {\n /** Prompt unique ID */\n id: string;\n /** Version string (e.g., \"1.0.0\") */\n version: string;\n /** System prompt */\n system: string;\n /** User prompt template (Mustache format) */\n userTemplate: string;\n /** Additional custom fields from AgentPrompt */\n customFields?: Record<string, unknown>;\n}\n\n/** Serialized round result for JSON storage */\nexport interface SerializedRoundResult {\n /** Round number (1-indexed) */\n round: number;\n /** Completion timestamp (ISO 8601) */\n completedAt: string;\n /** Average score from this round */\n avgScore: number;\n /** Number of passed tests */\n passed: number;\n /** Number of failed tests */\n failed: number;\n /** Total number of tests */\n totalTests: number;\n /** All suggestions generated */\n suggestionsGenerated: Suggestion[];\n /** Suggestions that were approved/applied */\n suggestionsApproved: Suggestion[];\n /** Prompt snapshot at start of this round */\n promptSnapshot: SerializedPrompt;\n /** Prompt version after applying suggestions */\n promptVersionAfter: string;\n /** Cost breakdown */\n cost: RoundCost;\n /** Score change from previous round */\n scoreDelta: number | null;\n}\n\n/**\n * Improvement cycle history (JSON file schema v1.1.0).\n * Includes promptSnapshot per round for rollback support.\n */\nexport interface ImprovementHistory {\n /** Schema version for migration compatibility */\n schemaVersion: '1.1.0';\n /** Unique session identifier */\n sessionId: string;\n /** Session start timestamp (ISO 8601) */\n startedAt: string;\n /** Session completion timestamp (ISO 8601, if completed) */\n completedAt?: string;\n /** Initial prompt before any improvements */\n initialPrompt: SerializedPrompt;\n /** Current/latest prompt */\n currentPrompt: SerializedPrompt;\n /** All completed rounds */\n rounds: SerializedRoundResult[];\n /** Reason for termination (if completed) */\n terminationReason?: string;\n /** Total accumulated cost in USD */\n totalCost: number;\n}\n\n/** History persistence configuration */\nexport interface HistoryConfig {\n /** Path to save history JSON */\n path: string;\n /** Auto-save after each round (default: true) */\n autoSave?: boolean;\n}\n\n/** Configuration for running an improvement cycle */\nexport interface ImprovementCycleConfig<TInput, TOutput> {\n /** Factory function to create agent with given prompt */\n createAgent: (prompt: AgentPrompt<TInput>) => EvalAgent<TInput, TOutput>;\n /** Starting prompt for improvements */\n initialPrompt: AgentPrompt<TInput>;\n /** Test cases to evaluate against */\n testCases: TestCase<TInput>[];\n /** Judge for evaluation */\n judge: Judge;\n /** Improver for generating suggestions */\n improver: Improver;\n /** Termination conditions (OR semantics) */\n terminateWhen: CycleTerminationCondition[];\n /** Optional configuration */\n options?: ImprovementCycleOptions;\n}\n\n/** Optional configuration for improvement cycle */\nexport interface ImprovementCycleOptions {\n /** Options passed to eval suite run */\n runOptions?: { concurrency?: number; iterations?: number };\n /** How to bump version on each improvement */\n versionBump?: 'major' | 'minor' | 'patch';\n /** Pricing configuration for cost calculation */\n pricingConfig?: EvalPricingConfig;\n /** History persistence settings */\n history?: HistoryConfig;\n /** Description for agent (passed to judge) */\n agentDescription?: string;\n /** Existing session to resume (preserves session ID and accumulated state) */\n session?: ImprovementSession;\n}\n\n/** Final result of an improvement cycle */\nexport interface ImprovementCycleResult<TInput, TOutput> {\n /** Final improved prompt */\n finalPrompt: AgentPrompt<TInput>;\n /** All completed rounds */\n rounds: RoundResult[];\n /** Reason for termination */\n terminationReason: string;\n /** Total cost in USD */\n totalCost: number;\n /** Saved history (if persistence was enabled) */\n history?: ImprovementHistory;\n}\n\nexport function isTargetScoreCondition(\n condition: CycleTerminationCondition\n): condition is TargetScoreCondition {\n return condition.type === 'targetScore';\n}\n\nexport function isMaxRoundsCondition(\n condition: CycleTerminationCondition\n): condition is MaxRoundsCondition {\n return condition.type === 'maxRounds';\n}\n\nexport function isNoImprovementCondition(\n condition: CycleTerminationCondition\n): condition is NoImprovementCondition {\n return condition.type === 'noImprovement';\n}\n\nexport function isMaxCostCondition(\n condition: CycleTerminationCondition\n): condition is MaxCostCondition {\n return condition.type === 'maxCost';\n}\n\nexport function isCustomCycleCondition(\n condition: CycleTerminationCondition\n): condition is CustomCycleCondition {\n return condition.type === 'custom';\n}\n\nexport function isCycleTerminated(result: CycleTerminationResult): result is CycleTerminatedResult {\n return result.terminated === true;\n}\n","import type {\n CycleContext,\n CycleTerminationCondition,\n CycleTerminationResult,\n TargetScoreCondition,\n MaxRoundsCondition,\n NoImprovementCondition,\n MaxCostCondition,\n CustomCycleCondition,\n} from './types'\nimport {\n isTargetScoreCondition,\n isMaxRoundsCondition,\n isNoImprovementCondition,\n isMaxCostCondition,\n isCustomCycleCondition,\n} from './types'\nimport { EvalError, EvalErrorCode } from '@/core/errors'\nimport {\n createAndCheck,\n createOrCheck,\n createNotCheck,\n formatCompositeDescription,\n} from '../utils/condition-composites'\n\n/** Terminates when the average score reaches or exceeds threshold. */\nexport function targetScore(threshold: number): TargetScoreCondition {\n if (!Number.isFinite(threshold)) {\n throw new EvalError('threshold must be a finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { threshold },\n })\n }\n if (threshold < 0 || threshold > 100) {\n throw new EvalError('threshold must be between 0 and 100', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { threshold },\n })\n }\n return { type: 'targetScore', threshold }\n}\n\n/** Terminates after completing the specified number of rounds. */\nexport function maxRounds(count: number): MaxRoundsCondition {\n if (!Number.isInteger(count) || count < 1) {\n throw new EvalError('count must be a positive integer', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { count },\n })\n }\n return { type: 'maxRounds', count }\n}\n\n/** Terminates when score hasn't improved for N consecutive rounds. */\nexport function noImprovement(\n consecutiveRounds: number,\n minDelta?: number\n): NoImprovementCondition {\n if (!Number.isInteger(consecutiveRounds) || consecutiveRounds < 1) {\n throw new EvalError('consecutiveRounds must be a positive integer', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { consecutiveRounds },\n })\n }\n if (minDelta !== undefined && (!Number.isFinite(minDelta) || minDelta < 0)) {\n throw new EvalError('minDelta must be a non-negative finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { minDelta },\n })\n }\n return {\n type: 'noImprovement',\n consecutiveRounds,\n ...(minDelta !== undefined && { minDelta }),\n }\n}\n\n/** Terminates when total accumulated cost reaches or exceeds the budget. */\nexport function maxCost(maxUSD: number): MaxCostCondition {\n if (!Number.isFinite(maxUSD) || maxUSD <= 0) {\n throw new EvalError('maxUSD must be a positive finite number', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { maxUSD },\n })\n }\n return { type: 'maxCost', maxUSD }\n}\n\n/** Custom termination condition with arbitrary logic. Supports async checks. */\nexport function customCondition(\n check: (ctx: CycleContext) => boolean | Promise<boolean>,\n description?: string\n): CustomCycleCondition {\n return {\n type: 'custom',\n check,\n ...(description !== undefined && { description }),\n }\n}\n\n/** All conditions must be met for termination. Short-circuits on first false. */\nexport function and(\n ...conditions: CycleTerminationCondition[]\n): CustomCycleCondition {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('and', []),\n }\n }\n\n return {\n type: 'custom',\n check: createAndCheck(conditions, checkCycleCondition),\n description: formatCompositeDescription('and', conditions),\n }\n}\n\n/** Any condition being met causes termination. Short-circuits on first true. */\nexport function or(\n ...conditions: CycleTerminationCondition[]\n): CustomCycleCondition {\n if (conditions.length === 0) {\n return {\n type: 'custom',\n check: () => false,\n description: formatCompositeDescription('or', []),\n }\n }\n\n return {\n type: 'custom',\n check: createOrCheck(conditions, checkCycleCondition),\n description: formatCompositeDescription('or', conditions),\n }\n}\n\n/** Invert a condition's result. Terminates when inner condition does NOT terminate. */\nexport function not(\n condition: CycleTerminationCondition\n): CustomCycleCondition {\n return {\n type: 'custom',\n check: createNotCheck(condition, checkCycleCondition),\n description: `not(${condition.type})`,\n }\n}\n\nfunction checkTargetScore(\n condition: TargetScoreCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.latestScore >= condition.threshold) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Target score ${condition.threshold} reached (current: ${ctx.latestScore})`,\n }\n }\n return {\n terminated: false,\n reason: `Score ${ctx.latestScore} below target ${condition.threshold}`,\n }\n}\n\nfunction checkMaxRounds(\n condition: MaxRoundsCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.currentRound >= condition.count) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Maximum rounds reached (${condition.count})`,\n }\n }\n return {\n terminated: false,\n reason: `Round ${ctx.currentRound} of ${condition.count}`,\n }\n}\n\n/**\n * Counts consecutive rounds without improvement from most recent to oldest.\n * Breaks on null delta (first round) or on improvement (scoreDelta > minDelta).\n */\nfunction checkNoImprovement(\n condition: NoImprovementCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n const { consecutiveRounds, minDelta = 0 } = condition\n const { history } = ctx\n\n let noImprovementCount = 0\n\n for (let i = history.length - 1; i >= 0; i--) {\n const round = history[i]\n\n if (round.scoreDelta === null) break\n if (round.scoreDelta <= minDelta) {\n noImprovementCount++\n } else {\n break\n }\n }\n\n if (noImprovementCount >= consecutiveRounds) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `No improvement for ${noImprovementCount} consecutive round${noImprovementCount === 1 ? '' : 's'}`,\n }\n }\n\n const roundWord = noImprovementCount === 1 ? 'round' : 'rounds'\n return {\n terminated: false,\n reason: `${noImprovementCount} ${roundWord} without improvement (need ${consecutiveRounds})`,\n }\n}\n\nfunction checkMaxCost(\n condition: MaxCostCondition,\n ctx: CycleContext\n): CycleTerminationResult {\n if (ctx.totalCost >= condition.maxUSD) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `Cost limit exceeded ($${ctx.totalCost.toFixed(2)} >= $${condition.maxUSD.toFixed(2)})`,\n }\n }\n return {\n terminated: false,\n reason: `Cost $${ctx.totalCost.toFixed(2)} under limit $${condition.maxUSD.toFixed(2)}`,\n }\n}\n\nasync function checkCustomCondition(\n condition: CustomCycleCondition,\n ctx: CycleContext\n): Promise<CycleTerminationResult> {\n const description = condition.description ?? 'Custom condition'\n\n try {\n const shouldTerminate = await condition.check(ctx)\n\n if (shouldTerminate) {\n return {\n terminated: true,\n matchedCondition: condition,\n reason: `${description} met`,\n }\n }\n return {\n terminated: false,\n reason: `${description} not met`,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n terminated: false,\n reason: `${description} check failed: ${message}`,\n }\n }\n}\n\n/** Dispatches to the appropriate check function based on condition type. */\nexport async function checkCycleCondition(\n condition: CycleTerminationCondition,\n context: CycleContext\n): Promise<CycleTerminationResult> {\n if (isTargetScoreCondition(condition)) {\n return checkTargetScore(condition, context)\n }\n if (isMaxRoundsCondition(condition)) {\n return checkMaxRounds(condition, context)\n }\n if (isNoImprovementCondition(condition)) {\n return checkNoImprovement(condition, context)\n }\n if (isMaxCostCondition(condition)) {\n return checkMaxCost(condition, context)\n }\n if (isCustomCycleCondition(condition)) {\n return checkCustomCondition(condition, context)\n }\n\n // Exhaustive check - TypeScript will error if we miss a case\n const _exhaustive: never = condition\n throw new EvalError(`Unknown condition type: ${JSON.stringify(_exhaustive)}`, {\n code: EvalErrorCode.UNKNOWN_ERROR,\n context: { condition: _exhaustive },\n })\n}\n\n/** Check all conditions with OR semantics - first match wins. */\nexport async function checkCycleTermination(\n conditions: CycleTerminationCondition[],\n context: CycleContext\n): Promise<CycleTerminationResult> {\n if (conditions.length === 0) {\n return {\n terminated: false,\n reason: 'No termination conditions specified',\n }\n }\n\n for (const condition of conditions) {\n const result = await checkCycleCondition(condition, context)\n if (result.terminated) {\n return result // First match wins (OR semantics)\n }\n }\n\n return {\n terminated: false,\n reason: 'No termination conditions met',\n }\n}\n","import type { LanguageModelUsage } from 'ai'\nimport { calculateCostFromUsage } from '@agtlantis/core'\nimport { createEvalSuite } from '@/core/suite'\nimport { applyPromptSuggestions } from '@/improver/utils'\nimport { calculateReportCosts, type EvalPricingConfig } from '@/reporter/cost-helpers'\nimport type { EvalAgent, AgentPrompt, EvalTokenUsage } from '@/core/types'\nimport type { EvalReport } from '@/reporter/types'\nimport type { Suggestion, ImproveResult } from '@/improver/types'\n\nimport { createSession, serializePrompt, deserializePrompt } from './history'\nimport type { ImprovementSession, SessionConfig } from './history'\nimport { checkCycleTermination } from './conditions'\nimport type {\n ImprovementCycleConfig,\n ImprovementCycleResult,\n RoundYield,\n RoundDecision,\n RoundResult,\n RoundCost,\n CycleContext,\n SerializedPrompt,\n} from './types'\n\ninterface CycleState<TInput, TOutput> {\n currentPrompt: AgentPrompt<TInput>\n currentRound: number\n previousScores: number[]\n totalCost: number\n completedRounds: RoundResult[]\n}\n\n/** Initialize cycle state, resuming from existing session if provided. */\nfunction initializeCycleState<TInput, TOutput>(\n initialPrompt: AgentPrompt<TInput>,\n existingSession: ImprovementSession | undefined\n): CycleState<TInput, TOutput> {\n const resumeFromRound = existingSession ? existingSession.history.rounds.length : 0\n return {\n currentPrompt: initialPrompt,\n currentRound: resumeFromRound,\n previousScores: existingSession\n ? existingSession.history.rounds.map((r) => r.avgScore)\n : [],\n totalCost: existingSession ? existingSession.history.totalCost : 0,\n completedRounds: [],\n }\n}\n\n/** Returns null for the first round (no previous score to compare). */\nfunction calculateScoreDelta(currentScore: number, previousScores: number[]): number | null {\n if (previousScores.length === 0) {\n return null\n }\n const previousScore = previousScores[previousScores.length - 1]\n return currentScore - previousScore\n}\n\nfunction buildCycleContext<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n currentScore: number\n): CycleContext {\n return {\n currentRound: state.currentRound,\n latestScore: currentScore,\n previousScores: [...state.previousScores],\n totalCost: state.totalCost,\n history: state.completedRounds,\n }\n}\n\nfunction createRoundResult<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n report: EvalReport<TInput, TOutput>,\n improveResult: ImproveResult,\n cost: RoundCost,\n scoreDelta: number | null,\n promptSnapshot: SerializedPrompt\n): RoundResult {\n return {\n round: state.currentRound,\n report: report as EvalReport<unknown, unknown>,\n completedAt: new Date(),\n suggestionsGenerated: improveResult.suggestions,\n suggestionsApproved: [], // Will be updated after decision\n promptSnapshot,\n promptVersionAfter: state.currentPrompt.version,\n cost,\n scoreDelta,\n }\n}\n\nasync function handleStopDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n session: ImprovementSession,\n roundResult: RoundResult,\n promptSnapshot: SerializedPrompt,\n terminatedByCondition: boolean,\n conditionReason: string | undefined\n): Promise<ImprovementCycleResult<TInput, TOutput>> {\n const reason = terminatedByCondition ? conditionReason! : 'User requested stop'\n\n session.addRound(roundResult, promptSnapshot)\n session.complete(reason)\n await session.flush()\n state.completedRounds.push(roundResult)\n\n return {\n rounds: state.completedRounds,\n finalPrompt: deserializePrompt(session.history.currentPrompt),\n terminationReason: reason,\n totalCost: state.totalCost,\n history: session.history,\n }\n}\n\n/** Throws if target round is invalid. */\nfunction handleRollbackDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n rollbackToRound: number\n): void {\n const targetRoundIndex = rollbackToRound - 1\n if (targetRoundIndex < 0 || targetRoundIndex >= state.completedRounds.length) {\n throw new Error(`Cannot rollback to round ${rollbackToRound}: round not found`)\n }\n\n const targetRound = state.completedRounds[targetRoundIndex]\n state.currentPrompt = deserializePrompt(targetRound.promptSnapshot)\n state.previousScores = state.previousScores.slice(0, rollbackToRound - 1)\n}\n\nfunction handleContinueDecision<TInput, TOutput>(\n state: CycleState<TInput, TOutput>,\n session: ImprovementSession,\n roundResult: RoundResult,\n approvedSuggestions: Suggestion[],\n versionBump: 'major' | 'minor' | 'patch'\n): RoundResult {\n const updatedRoundResult: RoundResult = {\n ...roundResult,\n suggestionsApproved: approvedSuggestions,\n }\n\n if (approvedSuggestions.length > 0) {\n const applyResult = applyPromptSuggestions(state.currentPrompt, approvedSuggestions, {\n bumpVersion: versionBump,\n })\n state.currentPrompt = applyResult.prompt\n updatedRoundResult.promptVersionAfter = state.currentPrompt.version\n }\n\n const updatedPromptSnapshot = serializePrompt(state.currentPrompt)\n session.addRound(updatedRoundResult, updatedPromptSnapshot)\n state.completedRounds.push(updatedRoundResult)\n\n return updatedRoundResult\n}\n\ninterface RoundExecutionResult<TInput, TOutput> {\n report: EvalReport<TInput, TOutput>\n improveResult: ImproveResult\n cost: RoundCost\n}\n\nasync function executeRound<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>,\n state: CycleState<TInput, TOutput>,\n pricingConfig: EvalPricingConfig | undefined\n): Promise<RoundExecutionResult<TInput, TOutput>> {\n const { createAgent, judge, improver, testCases, options = {} } = config\n const agent = createAgent(state.currentPrompt)\n\n // Improver is called separately (not via suite) to capture full ImproveResult\n // with metadata, enabling accurate cost calculation via tokenUsage\n const suite = createEvalSuite({\n agent,\n judge,\n agentDescription: options.agentDescription,\n })\n const report = await suite.run(testCases, options.runOptions)\n\n const improveResult: ImproveResult = improver\n ? await improver.improve(state.currentPrompt, report.results)\n : { suggestions: [] }\n\n const cost = calculateRoundCost(report, improveResult, pricingConfig)\n\n return { report, improveResult, cost }\n}\n\nfunction detectProviderForImprover(model: string | undefined): string {\n if (!model) return 'anthropic' // improver typically uses Claude\n\n if (model.startsWith('claude-')) return 'anthropic'\n if (model.startsWith('gpt-') || model.startsWith('o1') || model.startsWith('o3')) return 'openai'\n if (model.startsWith('gemini-')) return 'google'\n\n return 'anthropic'\n}\n\nfunction toLanguageModelUsage(usage: EvalTokenUsage): LanguageModelUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.totalTokens,\n } as LanguageModelUsage\n}\n\nfunction calculateImproverCost(\n improveResult: ImproveResult,\n pricingConfig?: EvalPricingConfig\n): number {\n const usage = improveResult.metadata?.tokenUsage as EvalTokenUsage | undefined\n if (!usage) return 0\n\n const model = improveResult.metadata?.model ?? 'unknown'\n const provider = detectProviderForImprover(model)\n\n // Get the pricing for this specific provider\n const providerPricing = pricingConfig?.providerPricing?.[provider]\n\n const result = calculateCostFromUsage(\n toLanguageModelUsage(usage),\n model,\n provider,\n providerPricing\n )\n\n return result.total\n}\n\nfunction calculateRoundCost(\n report: EvalReport<unknown, unknown>,\n improveResult: ImproveResult,\n pricingConfig?: EvalPricingConfig\n): RoundCost {\n const reportCosts = pricingConfig\n ? calculateReportCosts(report, pricingConfig)\n : { total: 0, byComponent: { agent: 0, judge: 0 } }\n\n const improverCost = calculateImproverCost(improveResult, pricingConfig)\n\n return {\n agent: reportCosts.byComponent.agent ?? 0,\n judge: reportCosts.byComponent.judge ?? 0,\n improver: improverCost,\n total: reportCosts.total + improverCost,\n }\n}\n\n/**\n * Run an improvement cycle as an AsyncGenerator for Human-in-the-Loop control.\n * Yields after each round for decision-making (continue, stop, or rollback).\n */\nexport async function* runImprovementCycle<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>\n): AsyncGenerator<RoundYield, ImprovementCycleResult<TInput, TOutput>, RoundDecision | undefined> {\n const { initialPrompt, terminateWhen = [], options = {} } = config\n const { pricingConfig, versionBump = 'patch', history: historyConfig, session: existingSession } = options\n\n const session: ImprovementSession = existingSession ?? createSession(\n initialPrompt,\n historyConfig ? { path: historyConfig.path, autoSave: historyConfig.autoSave } : undefined\n )\n const state = initializeCycleState(initialPrompt, existingSession)\n\n try {\n while (true) {\n state.currentRound++\n\n const { report, improveResult, cost } = await executeRound(config, state, pricingConfig)\n state.totalCost += cost.total\n\n const currentScore = report.summary.avgScore\n const scoreDelta = calculateScoreDelta(currentScore, state.previousScores)\n const promptSnapshot = serializePrompt(state.currentPrompt)\n const roundResult = createRoundResult(state, report, improveResult, cost, scoreDelta, promptSnapshot)\n const context = buildCycleContext(state, currentScore)\n\n state.previousScores.push(currentScore)\n\n const terminationCheck = await checkCycleTermination(terminateWhen, context)\n const pendingSuggestions: Suggestion[] = improveResult.suggestions.map((s) => ({\n ...s,\n approved: false,\n }))\n\n const roundYield: RoundYield = {\n roundResult,\n pendingSuggestions,\n terminationCheck,\n context,\n }\n\n const decision: RoundDecision | undefined = yield roundYield\n\n if (!decision || decision.action === 'stop') {\n return await handleStopDecision(\n state,\n session,\n roundResult,\n promptSnapshot,\n terminationCheck.terminated,\n terminationCheck.reason\n )\n }\n\n if (decision.action === 'rollback' && decision.rollbackToRound !== undefined) {\n handleRollbackDecision(state, decision.rollbackToRound)\n continue\n }\n\n handleContinueDecision(\n state,\n session,\n roundResult,\n decision.approvedSuggestions ?? [],\n versionBump\n )\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n session.complete(`Error: ${errorMessage}`)\n throw error\n }\n}\n\n/**\n * Run improvement cycle with automatic approval of all suggestions.\n * Continues until a termination condition is met.\n */\nexport async function runImprovementCycleAuto<TInput, TOutput>(\n config: ImprovementCycleConfig<TInput, TOutput>\n): Promise<ImprovementCycleResult<TInput, TOutput>> {\n const cycle = runImprovementCycle(config)\n\n let iteratorResult = await cycle.next()\n\n while (!iteratorResult.done) {\n const roundYield = iteratorResult.value\n let decision: RoundDecision\n\n if (roundYield.terminationCheck.terminated) {\n decision = { action: 'stop' }\n } else {\n const approvedSuggestions = roundYield.pendingSuggestions.map((s) => ({\n ...s,\n approved: true,\n }))\n decision = { action: 'continue', approvedSuggestions }\n }\n\n iteratorResult = await cycle.next(decision)\n }\n\n return iteratorResult.value\n}\n","import crypto from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport { compileTemplate } from '@agtlantis/core';\n\nimport { EvalError, EvalErrorCode } from '@/core/errors';\nimport type { AgentPrompt } from '@/core/types';\n\nimport type {\n ImprovementHistory,\n RoundResult,\n SerializedPrompt,\n SerializedRoundResult,\n} from './types';\n\n/** Storage abstraction for testability - allows injecting mock storage */\nexport interface HistoryStorage {\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, content: string) => Promise<void>;\n exists: (path: string) => boolean;\n mkdir: (path: string, options?: { recursive?: boolean }) => Promise<string | undefined | void>;\n}\n\nexport const defaultHistoryStorage: HistoryStorage = {\n readFile: (path) => readFile(path, 'utf-8'),\n writeFile: (path, content) => writeFile(path, content, 'utf-8'),\n exists: existsSync,\n mkdir: (path, options) => mkdir(path, options),\n};\n\nexport interface ImprovementSession {\n readonly sessionId: string;\n readonly history: Readonly<ImprovementHistory>;\n readonly canSave: boolean;\n addRound(roundResult: RoundResult, updatedPrompt: SerializedPrompt): void;\n complete(terminationReason: string): void;\n save(): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface SessionConfig {\n path?: string;\n autoSave?: boolean;\n storage?: HistoryStorage;\n onAutoSaveError?: (error: Error) => void;\n}\n\nexport function hasUserTemplate(\n prompt: AgentPrompt<unknown>\n): prompt is AgentPrompt<unknown> & { userTemplate: string } {\n return typeof (prompt as { userTemplate?: unknown }).userTemplate === 'string';\n}\n\n/** @throws EvalError with PROMPT_INVALID_FORMAT if userTemplate is missing */\nexport function serializePrompt<TInput>(prompt: AgentPrompt<TInput>): SerializedPrompt {\n const p = prompt as AgentPrompt<unknown>;\n if (!hasUserTemplate(p)) {\n throw new EvalError('Cannot serialize prompt: userTemplate field is required', {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId: p.id },\n });\n }\n\n const { id, version, system, userTemplate, renderUserPrompt, ...rest } =\n p as AgentPrompt<unknown> & {\n userTemplate: string;\n };\n const customFields =\n Object.keys(rest).length > 0 ? (rest as Record<string, unknown>) : undefined;\n\n return {\n id,\n version,\n system,\n userTemplate,\n ...(customFields && { customFields }),\n };\n}\n\nfunction validateDeserializedPrompt(\n obj: Record<string, unknown>,\n promptId: string\n): asserts obj is Record<string, unknown> & {\n id: string;\n version: string;\n system: string;\n userTemplate: string;\n renderUserPrompt: (input: unknown) => string;\n} {\n const requiredStrings = ['id', 'version', 'system', 'userTemplate'] as const;\n for (const field of requiredStrings) {\n if (typeof obj[field] !== 'string') {\n throw new EvalError(`Invalid deserialized prompt: ${field} must be a string`, {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId, field, actual: typeof obj[field] },\n });\n }\n }\n\n if (typeof obj.renderUserPrompt !== 'function') {\n throw new EvalError('Invalid deserialized prompt: renderUserPrompt must be a function', {\n code: EvalErrorCode.PROMPT_INVALID_FORMAT,\n context: { promptId, actual: typeof obj.renderUserPrompt },\n });\n }\n}\n\n/** Reconstructs renderUserPrompt using compileTemplate. */\nexport function deserializePrompt<TInput>(serialized: SerializedPrompt): AgentPrompt<TInput> {\n const { id, version, system, userTemplate, customFields } = serialized;\n\n let renderUserPrompt: (input: TInput) => string;\n try {\n renderUserPrompt = compileTemplate<TInput>(userTemplate, id);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new EvalError(`Failed to compile userTemplate: ${message}`, {\n code: EvalErrorCode.TEMPLATE_COMPILE_ERROR,\n context: { promptId: id, userTemplate },\n });\n }\n\n // Spread customFields first, then core fields to prevent override attacks\n const result = {\n ...customFields,\n id,\n version,\n system,\n userTemplate,\n renderUserPrompt,\n };\n\n validateDeserializedPrompt(result, id);\n return result as AgentPrompt<TInput>;\n}\n\nfunction serializeRoundResult(result: RoundResult): SerializedRoundResult {\n const { summary } = result.report;\n\n return {\n round: result.round,\n completedAt: result.completedAt.toISOString(),\n avgScore: summary.avgScore,\n passed: summary.passed,\n failed: summary.failed,\n totalTests: summary.totalTests,\n suggestionsGenerated: result.suggestionsGenerated,\n suggestionsApproved: result.suggestionsApproved,\n promptSnapshot: result.promptSnapshot,\n promptVersionAfter: result.promptVersionAfter,\n cost: result.cost,\n scoreDelta: result.scoreDelta,\n };\n}\n\nfunction validateHistorySchema(data: unknown): asserts data is ImprovementHistory {\n if (typeof data !== 'object' || data === null) {\n throw new EvalError('Invalid history: not an object', {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n });\n }\n\n const h = data as Record<string, unknown>;\n\n if (h.schemaVersion !== '1.1.0') {\n throw new EvalError(`Unsupported schema version: ${String(h.schemaVersion)}`, {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n context: { schemaVersion: h.schemaVersion },\n });\n }\n\n const requiredFields = [\n 'sessionId',\n 'startedAt',\n 'initialPrompt',\n 'currentPrompt',\n 'rounds',\n 'totalCost',\n ];\n for (const field of requiredFields) {\n if (!(field in h)) {\n throw new EvalError(`Invalid history: missing field \"${field}\"`, {\n code: EvalErrorCode.SCHEMA_VALIDATION_ERROR,\n context: { missingField: field },\n });\n }\n }\n}\n\nclass ImprovementSessionImpl implements ImprovementSession {\n private _history: ImprovementHistory;\n private _isUpdating = false;\n private _savePromise: Promise<void> = Promise.resolve();\n private readonly config: Required<Pick<SessionConfig, 'autoSave'>> & SessionConfig;\n\n constructor(history: ImprovementHistory, config: SessionConfig = {}) {\n this._history = history;\n this.config = {\n autoSave: config.autoSave ?? false,\n ...config,\n };\n }\n\n get sessionId(): string {\n return this._history.sessionId;\n }\n\n get history(): Readonly<ImprovementHistory> {\n return this._history;\n }\n\n get canSave(): boolean {\n return this.config.path !== undefined;\n }\n\n addRound(roundResult: RoundResult, updatedPrompt: SerializedPrompt): void {\n if (this._isUpdating) {\n throw new EvalError('Session is being updated', {\n code: EvalErrorCode.CONCURRENT_MODIFICATION,\n context: { sessionId: this.sessionId },\n });\n }\n\n if (this._history.completedAt) {\n throw new EvalError('Cannot add round to completed session', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { sessionId: this.sessionId },\n });\n }\n\n this._isUpdating = true;\n try {\n const serializedRound = serializeRoundResult(roundResult);\n\n this._history = {\n ...this._history,\n currentPrompt: updatedPrompt,\n rounds: [...this._history.rounds, serializedRound],\n totalCost: this._history.totalCost + roundResult.cost.total,\n };\n\n if (this.config.autoSave && this.canSave) {\n this.save().catch((err) => this.handleAutoSaveError(err));\n }\n } finally {\n this._isUpdating = false;\n }\n }\n\n complete(terminationReason: string): void {\n this._history = {\n ...this._history,\n completedAt: new Date().toISOString(),\n terminationReason,\n };\n\n if (this.config.autoSave && this.canSave) {\n this.save().catch((err) => this.handleAutoSaveError(err));\n }\n }\n\n private handleAutoSaveError(error: unknown): void {\n const err = error instanceof Error ? error : new Error(String(error));\n if (this.config.onAutoSaveError) {\n this.config.onAutoSaveError(err);\n } else {\n console.error('Auto-save failed:', err);\n }\n }\n\n async save(): Promise<void> {\n if (!this.config.path) {\n throw new EvalError('Cannot save: no path configured', {\n code: EvalErrorCode.INVALID_CONFIG,\n context: { sessionId: this.sessionId },\n });\n }\n\n // Serialize saves to prevent race conditions from back-to-back autoSave triggers\n this._savePromise = this._savePromise.then(async () => {\n await saveHistory(this._history, this.config.path!, this.config.storage);\n });\n return this._savePromise;\n }\n\n async flush(): Promise<void> {\n return this._savePromise;\n }\n}\n\n/** @throws EvalError with PROMPT_INVALID_FORMAT if prompt lacks userTemplate */\nexport function createSession<TInput>(\n initialPrompt: AgentPrompt<TInput>,\n config?: SessionConfig\n): ImprovementSession {\n const serializedPrompt = serializePrompt(initialPrompt);\n\n const history: ImprovementHistory = {\n schemaVersion: '1.1.0',\n sessionId: crypto.randomUUID(),\n startedAt: new Date().toISOString(),\n initialPrompt: serializedPrompt,\n currentPrompt: serializedPrompt,\n rounds: [],\n totalCost: 0,\n };\n\n return new ImprovementSessionImpl(history, config);\n}\n\n/** Resume from a history file. Clears completion status to allow adding new rounds. */\nexport async function resumeSession(\n path: string,\n config?: Omit<SessionConfig, 'path'>\n): Promise<ImprovementSession> {\n const history = await loadHistory(path, config?.storage);\n\n const reopenedHistory: ImprovementHistory = {\n ...history,\n completedAt: undefined,\n terminationReason: undefined,\n };\n\n return new ImprovementSessionImpl(reopenedHistory, { ...config, path });\n}\n\n/** Save history to JSON file. Creates parent directories if needed. */\nexport async function saveHistory(\n history: ImprovementHistory,\n path: string,\n storage: HistoryStorage = defaultHistoryStorage\n): Promise<void> {\n try {\n const dir = dirname(path);\n if (dir && dir !== '.' && dir !== '/' && !storage.exists(dir)) {\n await storage.mkdir(dir, { recursive: true });\n }\n await storage.writeFile(path, JSON.stringify(history, null, 2));\n } catch (error) {\n if (error instanceof EvalError) throw error;\n throw EvalError.from(error, EvalErrorCode.FILE_WRITE_ERROR, { path });\n }\n}\n\nexport async function loadHistory(\n path: string,\n storage: HistoryStorage = defaultHistoryStorage\n): Promise<ImprovementHistory> {\n try {\n if (!storage.exists(path)) {\n throw new EvalError(`History file not found: ${path}`, {\n code: EvalErrorCode.FILE_READ_ERROR,\n context: { path },\n });\n }\n\n const content = await storage.readFile(path);\n const history = JSON.parse(content) as unknown;\n validateHistorySchema(history);\n\n return history;\n } catch (error) {\n if (error instanceof EvalError) throw error;\n throw EvalError.from(error, EvalErrorCode.FILE_READ_ERROR, { path });\n }\n}\n","import type { TestCase } from './types'\n\n/**\n * Options for random selection.\n */\nexport interface RandomOptions {\n /** Seed for reproducible random selection */\n seed?: number\n}\n\n/**\n * Immutable collection for managing and selecting test cases.\n * Provides fluent API for filtering, sampling, and accessing test cases.\n *\n * ## Immutability\n * - All selection methods (`filter`, `first`, `random`, etc.) return **new collections**\n * - Chaining creates intermediate collections without modifying the original\n * - Internal array is frozen with `Object.freeze()` to prevent accidental mutation\n * - `toArray()` returns a **mutable copy** for consumer convenience\n *\n * @example\n * ```typescript\n * import { TestCaseCollection, createEvalSuite } from '@agtlantis/eval'\n *\n * const cases = TestCaseCollection.from([\n * { id: 'basic', input: { query: 'Hello' } },\n * { id: 'complex', input: { query: 'Explain quantum computing' } },\n * { id: 'edge', input: { query: '' } },\n * ])\n *\n * // Development: quick feedback\n * await suite.run(cases.minimal().toArray())\n *\n * // CI: full coverage\n * await suite.run(cases.all().toArray())\n *\n * // Debugging specific case\n * await suite.run(cases.byIds(['edge']).toArray())\n *\n * // Chaining: filter then sample\n * const filtered = cases.filter(tc => tc.tags?.includes('fast')).random(3).toArray()\n * ```\n */\nexport class TestCaseCollection<TInput> {\n private readonly cases: ReadonlyArray<TestCase<TInput>>\n\n private constructor(cases: TestCase<TInput>[]) {\n this.cases = Object.freeze([...cases])\n }\n\n // ============================================================================\n // Static Factories\n // ============================================================================\n\n /**\n * Create a collection from an array of test cases.\n */\n static from<T>(cases: TestCase<T>[]): TestCaseCollection<T> {\n return new TestCaseCollection(cases)\n }\n\n /**\n * Create an empty collection.\n */\n static empty<T>(): TestCaseCollection<T> {\n return new TestCaseCollection<T>([])\n }\n\n // ============================================================================\n // Properties\n // ============================================================================\n\n /**\n * Number of test cases in the collection.\n */\n get length(): number {\n return this.cases.length\n }\n\n /**\n * Whether the collection is empty.\n */\n get isEmpty(): boolean {\n return this.cases.length === 0\n }\n\n // ============================================================================\n // Selection Methods (return new TestCaseCollection - chainable)\n // ============================================================================\n\n /**\n * Returns all test cases.\n * Returns `this` since the collection is immutable (frozen array).\n * Useful as explicit starting point in chains.\n */\n all(): TestCaseCollection<TInput> {\n return this\n }\n\n /**\n * Returns the first N test cases (default: 1).\n * Useful for cost-controlled testing during development.\n */\n minimal(count: number = 1): TestCaseCollection<TInput> {\n return this.first(count)\n }\n\n /**\n * Returns the first N test cases.\n */\n first(count: number): TestCaseCollection<TInput> {\n if (count <= 0) {\n return TestCaseCollection.empty()\n }\n return new TestCaseCollection([...this.cases.slice(0, count)])\n }\n\n /**\n * Returns the last N test cases (default: 1).\n * Preserves original order (earlier cases first).\n */\n last(count: number = 1): TestCaseCollection<TInput> {\n if (count <= 0) {\n return TestCaseCollection.empty()\n }\n const startIndex = Math.max(0, this.cases.length - count)\n return new TestCaseCollection([...this.cases.slice(startIndex)])\n }\n\n /**\n * Returns N random test cases.\n *\n * @param count - Number of cases to select\n * @param options - Optional seed for reproducibility\n *\n * @example\n * ```typescript\n * // Different each time\n * collection.random(5)\n *\n * // Same result with same seed\n * collection.random(5, { seed: 42 })\n * ```\n */\n random(count: number, options?: RandomOptions): TestCaseCollection<TInput> {\n if (count <= 0 || this.cases.length === 0) {\n return TestCaseCollection.empty()\n }\n\n const actualCount = Math.min(count, this.cases.length)\n const indices = [...Array(this.cases.length).keys()]\n\n const rng =\n options?.seed !== undefined ? createSeededRng(options.seed) : Math.random\n\n // Fisher-Yates shuffle\n for (let i = indices.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1))\n ;[indices[i], indices[j]] = [indices[j], indices[i]]\n }\n\n const selected = indices.slice(0, actualCount).map((i) => this.cases[i])\n return new TestCaseCollection([...selected])\n }\n\n /**\n * Filter test cases by predicate.\n */\n filter(\n predicate: (testCase: TestCase<TInput>) => boolean,\n ): TestCaseCollection<TInput> {\n return new TestCaseCollection([...this.cases.filter(predicate)])\n }\n\n /**\n * Find test case by ID.\n * Returns collection with single case or empty collection.\n */\n byId(id: string): TestCaseCollection<TInput> {\n const found = this.cases.find((tc) => tc.id === id)\n return found\n ? new TestCaseCollection([found])\n : TestCaseCollection.empty<TInput>()\n }\n\n /**\n * Find test cases by multiple IDs.\n * Preserves order of provided IDs (first occurrence).\n * Skips non-existent IDs. Duplicate IDs in input are deduplicated.\n *\n * @example\n * ```typescript\n * collection.byIds(['a', 'b', 'a']) // returns [case-a, case-b] (deduplicated)\n * collection.byIds(['b', 'a']) // returns [case-b, case-a] (order preserved)\n * ```\n */\n byIds(ids: string[]): TestCaseCollection<TInput> {\n const uniqueIds = [...new Set(ids)]\n const idSet = new Set(uniqueIds)\n const idToCase = new Map<string, TestCase<TInput>>()\n\n for (const tc of this.cases) {\n if (tc.id && idSet.has(tc.id) && !idToCase.has(tc.id)) {\n idToCase.set(tc.id, tc)\n }\n }\n\n const result = uniqueIds\n .map((id) => idToCase.get(id))\n .filter((tc): tc is TestCase<TInput> => tc !== undefined)\n\n return new TestCaseCollection(result)\n }\n\n // ============================================================================\n // Access Methods\n // ============================================================================\n\n /**\n * Get test case by ID.\n * Returns undefined if not found.\n */\n get(id: string): TestCase<TInput> | undefined {\n return this.cases.find((tc) => tc.id === id)\n }\n\n /**\n * Get test case by index.\n * Supports negative indices (e.g., -1 for last item).\n * Returns undefined if index is out of bounds.\n */\n at(index: number): TestCase<TInput> | undefined {\n const normalizedIndex = index < 0 ? this.cases.length + index : index\n if (normalizedIndex < 0 || normalizedIndex >= this.cases.length) {\n return undefined\n }\n return this.cases[normalizedIndex]\n }\n\n // ============================================================================\n // Conversion Methods\n // ============================================================================\n\n /**\n * Convert to array.\n * Returns a mutable copy of the internal array.\n */\n toArray(): TestCase<TInput>[] {\n return [...this.cases]\n }\n\n // ============================================================================\n // Iterator Support\n // ============================================================================\n\n /**\n * Iterator support for for...of loops and spread operator.\n */\n [Symbol.iterator](): Iterator<TestCase<TInput>> {\n return this.cases[Symbol.iterator]()\n }\n}\n\nlet autoIdCounter = 0\n\n/**\n * Create a single test case with auto-generated ID if not provided.\n *\n * Auto-generated IDs use a global counter: `test-1`, `test-2`, etc.\n *\n * @param input - The test case input data\n * @param id - Optional custom ID (uses auto-generated if omitted)\n * @returns A TestCase object\n *\n * @example\n * ```typescript\n * const case1 = testCase({ name: 'Alice' }) // id: 'test-1'\n * const case2 = testCase({ name: 'Bob' }) // id: 'test-2'\n * const case3 = testCase({ name: 'Charlie' }, 'custom-id') // id: 'custom-id'\n * ```\n *\n * @remarks\n * The global counter increments on every call. For deterministic IDs,\n * provide an explicit ID or use `testCases()` with a prefix.\n */\nexport function testCase<TInput>(input: TInput, id?: string): TestCase<TInput> {\n return {\n id: id ?? `test-${++autoIdCounter}`,\n input,\n }\n}\n\n/**\n * Create multiple test cases from inputs.\n * Auto-generates IDs with optional prefix.\n *\n * @example\n * ```typescript\n * const cases = testCases([{ name: 'Alice' }, { name: 'Bob' }], 'greet')\n * // Results in: [{ id: 'greet-0', input: {...} }, { id: 'greet-1', input: {...} }]\n * ```\n */\nexport function testCases<TInput>(\n inputs: TInput[],\n prefix: string = 'case',\n): TestCase<TInput>[] {\n return inputs.map((input, index) => ({\n id: `${prefix}-${index}`,\n input,\n }))\n}\n\n/**\n * Simple seeded random number generator (mulberry32 algorithm).\n * Provides reproducible pseudo-random sequences for test case selection.\n *\n * **Algorithm**: Mulberry32 - fast, good distribution, 32-bit state\n * **Period**: ~2^32 unique outputs per seed\n * **Use case**: Test case shuffling (not suitable for cryptographic purposes)\n *\n * @see https://github.com/bryc/code/blob/master/jshash/PRNGs.md\n * @internal\n */\nfunction createSeededRng(seed: number): () => number {\n let state = seed\n return () => {\n state = (state + 0x6d2b79f5) | 0\n let t = Math.imul(state ^ (state >>> 15), state | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n"],"mappings":"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","names":["resolveFileSourcesInInput","testCase","EvalErrorCode","fieldIsSet","testCase","resolve","testCase","resolveFileSourcesInInput","error","testCases","testCases","resolveFileSourcesInInput","getFileSourcesDisplayInfo","path","schema","path","writeFileSync","writeFileSync","testCases","writeFileSync","mkdirSync","path","mkdirSync","path","writeFileSync","writeFileSync","writeFileSync","Output","z","toEvalTokenUsage","z","Output","resolve","compileTemplate","calculateCostFromUsage","z","z","and","or","not","calculateCostFromUsage","existsSync","writeFile","compileTemplate","path","writeFile","existsSync","compileTemplate","testCases","toLanguageModelUsage","calculateCostFromUsage"]}