@kindlm/core 0.1.0
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.cjs +40 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3061 -0
- package/dist/index.d.ts +3061 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/provider.ts","../src/types/result.ts","../src/assertions/tool-calls.ts","../src/assertions/schema.ts","../src/assertions/pii.ts","../src/assertions/keywords.ts","../src/assertions/judge.ts","../src/assertions/drift.ts","../src/assertions/latency.ts","../src/assertions/cost.ts","../src/assertions/registry.ts","../src/assertions/classification.ts","../src/providers/retry.ts","../src/providers/openai.ts","../src/providers/anthropic.ts","../src/providers/ollama.ts","../src/providers/gemini.ts","../src/providers/mistral.ts","../src/providers/cohere.ts","../src/providers/registry.ts","../src/providers/conversation.ts","../src/config/schema.ts","../src/trace/types.ts","../src/config/parser.ts","../src/config/interpolation.ts","../src/engine/aggregator.ts","../src/engine/command.ts","../src/engine/runner.ts","../src/engine/gate.ts","../src/reporters/interface.ts","../src/reporters/pretty.ts","../src/reporters/json.ts","../src/reporters/junit.ts","../src/reporters/compliance.ts","../src/baseline/store.ts","../src/baseline/builder.ts","../src/baseline/compare.ts","../src/trace/parser.ts","../src/trace/mapper.ts"],"sourcesContent":["// ============================================================\n// HTTP Client (injected — core has zero I/O)\n// ============================================================\n\nexport interface HttpClient {\n fetch(url: string, init: HttpRequestInit): Promise<HttpResponse>;\n}\n\nexport interface HttpRequestInit {\n method: string;\n headers: Record<string, string>;\n body: string;\n timeoutMs?: number;\n}\n\nexport interface HttpResponse {\n ok: boolean;\n status: number;\n json(): Promise<unknown>;\n}\n\n// ============================================================\n// Messages\n// ============================================================\n\nexport interface ProviderMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n toolCallId?: string;\n toolName?: string;\n toolCalls?: ProviderToolCall[];\n}\n\nexport interface ProviderToolDefinition {\n name: string;\n description?: string;\n parameters?: Record<string, unknown>;\n}\n\nexport interface ProviderToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\nexport interface ProviderRequest {\n model: string;\n messages: ProviderMessage[];\n params: {\n temperature: number;\n maxTokens: number;\n topP?: number;\n stopSequences?: string[];\n seed?: number;\n };\n tools?: ProviderToolDefinition[];\n toolChoice?: \"auto\" | \"required\" | \"none\";\n}\n\nexport interface ProviderResponse {\n text: string;\n toolCalls: ProviderToolCall[];\n usage: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n };\n raw: unknown;\n latencyMs: number;\n modelId: string;\n finishReason: \"stop\" | \"max_tokens\" | \"tool_calls\" | \"error\" | \"unknown\";\n}\n\nexport type ProviderErrorCode =\n | \"AUTH_FAILED\"\n | \"RATE_LIMITED\"\n | \"TIMEOUT\"\n | \"MODEL_NOT_FOUND\"\n | \"CONTEXT_LENGTH\"\n | \"CONTENT_FILTERED\"\n | \"NETWORK_ERROR\"\n | \"PROVIDER_ERROR\"\n | \"UNKNOWN\";\n\nexport class ProviderError extends Error {\n constructor(\n public code: ProviderErrorCode,\n message: string,\n public statusCode?: number,\n public retryable: boolean = false,\n public raw?: unknown,\n ) {\n super(message);\n this.name = \"ProviderError\";\n }\n}\n\nexport interface ProviderAdapter {\n readonly name: string;\n initialize(config: ProviderAdapterConfig): Promise<void>;\n complete(request: ProviderRequest): Promise<ProviderResponse>;\n estimateCost(model: string, usage: ProviderResponse[\"usage\"]): number | null;\n supportsTools(model: string): boolean;\n}\n\nexport interface ProviderAdapterConfig {\n apiKey: string;\n baseUrl?: string;\n organization?: string;\n timeoutMs: number;\n maxRetries: number;\n}\n\nexport interface ConversationTurn {\n request: ProviderRequest;\n response: ProviderResponse;\n}\n\nexport interface ConversationResult {\n turns: ConversationTurn[];\n finalText: string;\n allToolCalls: ProviderToolCall[];\n totalUsage: ProviderResponse[\"usage\"];\n totalLatencyMs: number;\n}\n","export type Result<T, E = KindlmError> =\n | { success: true; data: T }\n | { success: false; error: E };\n\nexport interface KindlmError {\n code: ErrorCode;\n message: string;\n details?: Record<string, unknown>;\n cause?: Error;\n}\n\nexport type ErrorCode =\n // Config errors\n | \"CONFIG_NOT_FOUND\"\n | \"CONFIG_PARSE_ERROR\"\n | \"CONFIG_VALIDATION_ERROR\"\n | \"CONFIG_FILE_REF_ERROR\"\n | \"CONFIG_TOO_LARGE\"\n | \"PATH_TRAVERSAL\"\n // Provider errors\n | \"PROVIDER_NOT_FOUND\"\n | \"PROVIDER_AUTH_ERROR\"\n | \"PROVIDER_RATE_LIMIT\"\n | \"PROVIDER_TIMEOUT\"\n | \"PROVIDER_API_ERROR\"\n | \"PROVIDER_NETWORK_ERROR\"\n // Assertion errors\n | \"ASSERTION_EVAL_ERROR\"\n | \"SCHEMA_FILE_ERROR\"\n | \"JUDGE_EVAL_ERROR\"\n // Engine errors\n | \"ENGINE_MAX_TURNS\"\n | \"ENGINE_EMPTY_RESPONSE\"\n // Baseline errors\n | \"BASELINE_NOT_FOUND\"\n | \"BASELINE_CORRUPT\"\n | \"BASELINE_VERSION_MISMATCH\"\n // Cloud errors\n | \"CLOUD_AUTH_ERROR\"\n | \"CLOUD_UPLOAD_ERROR\"\n | \"CLOUD_PLAN_LIMIT\"\n | \"CLOUD_RATE_LIMIT\"\n // System errors\n | \"UNKNOWN_ERROR\";\n\nexport function ok<T>(data: T): Result<T, never> {\n return { success: true, data };\n}\n\nexport function err<E = KindlmError>(error: E): Result<never, E> {\n return { success: false, error };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface ToolCallExpectation {\n tool: string;\n shouldNotCall?: boolean;\n argsMatch?: Record<string, unknown>;\n argsSchema?: string;\n order?: number;\n}\n\nfunction matchArgs(\n actual: Record<string, unknown>,\n expected: Record<string, unknown>,\n): boolean {\n for (const [key, value] of Object.entries(expected)) {\n if (JSON.stringify(actual[key]) !== JSON.stringify(value)) {\n return false;\n }\n }\n return true;\n}\n\nexport function createToolCalledAssertion(\n tool: string,\n argsMatch?: Record<string, unknown>,\n): Assertion {\n return {\n type: \"tool_called\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const results: AssertionResult[] = [];\n const matching = context.toolCalls.filter((tc) => tc.name === tool);\n const actualNames = context.toolCalls.map((tc) => tc.name);\n\n if (matching.length === 0) {\n results.push({\n assertionType: \"tool_called\",\n label: `Tool \"${tool}\" called`,\n passed: false,\n score: 0,\n failureCode: \"TOOL_CALL_MISSING\",\n failureMessage: `Expected tool \"${tool}\" to be called, but got: [${actualNames.join(\", \")}]`,\n });\n return Promise.resolve(results);\n }\n\n results.push({\n assertionType: \"tool_called\",\n label: `Tool \"${tool}\" called`,\n passed: true,\n score: 1,\n });\n\n if (argsMatch) {\n const anyMatch = matching.some((tc) => matchArgs(tc.arguments, argsMatch));\n results.push({\n assertionType: \"tool_called\",\n label: `Tool \"${tool}\" args match`,\n passed: anyMatch,\n score: anyMatch ? 1 : 0,\n failureCode: anyMatch ? undefined : \"TOOL_CALL_ARGS_MISMATCH\",\n failureMessage: anyMatch\n ? undefined\n : `Expected args ${JSON.stringify(argsMatch)}, got ${JSON.stringify(matching[0]?.arguments)}`,\n });\n }\n\n return Promise.resolve(results);\n },\n };\n}\n\nexport function createToolNotCalledAssertion(tool: string): Assertion {\n return {\n type: \"tool_not_called\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const found = context.toolCalls.some((tc) => tc.name === tool);\n return Promise.resolve([\n {\n assertionType: \"tool_not_called\",\n label: `Tool \"${tool}\" not called`,\n passed: !found,\n score: found ? 0 : 1,\n failureCode: found ? \"TOOL_CALL_UNEXPECTED\" : undefined,\n failureMessage: found\n ? `Expected tool \"${tool}\" to NOT be called, but it was`\n : undefined,\n },\n ]);\n },\n };\n}\n\nexport function createToolOrderAssertion(\n expectations: ToolCallExpectation[],\n): Assertion {\n return {\n type: \"tool_order\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const results: AssertionResult[] = [];\n\n for (const exp of expectations) {\n if (exp.shouldNotCall) {\n const found = context.toolCalls.some((tc) => tc.name === exp.tool);\n results.push({\n assertionType: \"tool_order\",\n label: `Tool \"${exp.tool}\" not called`,\n passed: !found,\n score: found ? 0 : 1,\n failureCode: found ? \"TOOL_CALL_UNEXPECTED\" : undefined,\n failureMessage: found\n ? `Expected tool \"${exp.tool}\" to NOT be called, but it was`\n : undefined,\n });\n continue;\n }\n\n const matching = context.toolCalls.filter((tc) => tc.name === exp.tool);\n if (matching.length === 0) {\n results.push({\n assertionType: \"tool_order\",\n label: `Tool \"${exp.tool}\" called`,\n passed: false,\n score: 0,\n failureCode: \"TOOL_CALL_MISSING\",\n failureMessage: `Expected tool \"${exp.tool}\" to be called, but it was not`,\n });\n continue;\n }\n\n results.push({\n assertionType: \"tool_order\",\n label: `Tool \"${exp.tool}\" called`,\n passed: true,\n score: 1,\n });\n\n if (exp.argsMatch) {\n const anyMatch = matching.some((tc) =>\n matchArgs(tc.arguments, exp.argsMatch ?? {}),\n );\n results.push({\n assertionType: \"tool_order\",\n label: `Tool \"${exp.tool}\" args match`,\n passed: anyMatch,\n score: anyMatch ? 1 : 0,\n failureCode: anyMatch ? undefined : \"TOOL_CALL_ARGS_MISMATCH\",\n failureMessage: anyMatch\n ? undefined\n : `Expected args ${JSON.stringify(exp.argsMatch)}, got ${JSON.stringify(matching[0]?.arguments)}`,\n });\n }\n\n if (exp.order !== undefined) {\n const actualIndex = context.toolCalls.findIndex(\n (tc) => tc.name === exp.tool,\n );\n const orderMatch = actualIndex === exp.order;\n results.push({\n assertionType: \"tool_order\",\n label: `Tool \"${exp.tool}\" at position ${exp.order}`,\n passed: orderMatch,\n score: orderMatch ? 1 : 0,\n failureCode: orderMatch ? undefined : \"TOOL_CALL_ORDER_WRONG\",\n failureMessage: orderMatch\n ? undefined\n : `Expected \"${exp.tool}\" at position ${exp.order}, but found at position ${actualIndex}`,\n });\n }\n }\n\n return Promise.resolve(results);\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\n// AJV is CJS — dynamic import to avoid verbatimModuleSyntax issues\nlet ajvInstance: AjvInstance | undefined;\n\nasync function getAjvInstance(): Promise<AjvInstance> {\n if (ajvInstance) return ajvInstance;\n const ajvMod = await import(\"ajv\");\n const formatsMod = await import(\"ajv-formats\");\n const Ajv = (ajvMod as unknown as { default: { new (opts: object): AjvInstance } }).default;\n const addFormats = (formatsMod as unknown as { default: (ajv: AjvInstance) => void }).default;\n const instance = new Ajv({ allErrors: true, strict: false });\n addFormats(instance);\n ajvInstance = instance;\n return instance;\n}\n\ninterface AjvInstance {\n compile(schema: object): AjvValidateFunction;\n getSchema(key: string): AjvValidateFunction | undefined;\n addSchema(schema: object, key: string): AjvInstance;\n errorsText(errors: unknown[] | null | undefined): string;\n}\n\ninterface AjvValidateFunction {\n (data: unknown): boolean;\n errors: unknown[] | null;\n}\n\n// Cache compiled validators keyed by JSON-serialized schema\nconst validatorCache = new Map<string, AjvValidateFunction>();\n\nfunction getOrCompileValidator(ajv: AjvInstance, schema: Record<string, unknown>): AjvValidateFunction {\n const key = JSON.stringify(schema);\n const cached = validatorCache.get(key);\n if (cached) return cached;\n const validate = ajv.compile(schema);\n validatorCache.set(key, validate);\n return validate;\n}\n\nexport interface SchemaAssertionConfig {\n format: \"text\" | \"json\";\n schemaFile?: string;\n schemaContent?: Record<string, unknown>;\n contains?: string[];\n notContains?: string[];\n maxLength?: number;\n}\n\nexport function createSchemaAssertion(config: SchemaAssertionConfig): Assertion {\n return {\n type: \"schema\",\n async evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const results: AssertionResult[] = [];\n let parsed: unknown = undefined;\n\n if (config.format === \"json\") {\n try {\n parsed = JSON.parse(context.outputText);\n results.push({\n assertionType: \"schema\",\n label: \"Output is valid JSON\",\n passed: true,\n score: 1,\n });\n } catch (e) {\n results.push({\n assertionType: \"schema\",\n label: \"Output is valid JSON\",\n passed: false,\n score: 0,\n failureCode: \"SCHEMA_PARSE_ERROR\",\n failureMessage: `Failed to parse output as JSON: ${e instanceof Error ? e.message : String(e)}`,\n });\n return results;\n }\n }\n\n if (config.schemaContent) {\n const ajv = await getAjvInstance();\n const validate = getOrCompileValidator(ajv, config.schemaContent);\n const valid = validate(parsed ?? context.outputText);\n results.push({\n assertionType: \"schema\",\n label: \"Output matches JSON Schema\",\n passed: valid,\n score: valid ? 1 : 0,\n failureCode: valid ? undefined : \"SCHEMA_INVALID\",\n failureMessage: valid\n ? undefined\n : `Schema validation failed: ${ajv.errorsText(validate.errors)}`,\n metadata: valid ? undefined : { errors: validate.errors },\n });\n }\n\n if (config.contains) {\n const lowerOutput = context.outputText.toLowerCase();\n for (const substring of config.contains) {\n const found = lowerOutput.includes(substring.toLowerCase());\n results.push({\n assertionType: \"schema\",\n label: `Output contains \"${substring}\"`,\n passed: found,\n score: found ? 1 : 0,\n failureCode: found ? undefined : \"CONTAINS_FAILED\",\n failureMessage: found\n ? undefined\n : `Expected output to contain \"${substring}\"`,\n });\n }\n }\n\n if (config.notContains) {\n const lowerOutputNc = context.outputText.toLowerCase();\n for (const substring of config.notContains) {\n const found = lowerOutputNc.includes(substring.toLowerCase());\n results.push({\n assertionType: \"schema\",\n label: `Output does not contain \"${substring}\"`,\n passed: !found,\n score: found ? 0 : 1,\n failureCode: found ? \"NOT_CONTAINS_FAILED\" : undefined,\n failureMessage: found\n ? `Expected output to NOT contain \"${substring}\"`\n : undefined,\n });\n }\n }\n\n if (config.maxLength !== undefined) {\n const withinLimit = context.outputText.length <= config.maxLength;\n results.push({\n assertionType: \"schema\",\n label: `Output length <= ${config.maxLength}`,\n passed: withinLimit,\n score: withinLimit ? 1 : 0,\n failureCode: withinLimit ? undefined : \"MAX_LENGTH_EXCEEDED\",\n failureMessage: withinLimit\n ? undefined\n : `Output length ${context.outputText.length} exceeds max ${config.maxLength}`,\n });\n }\n\n return results;\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface PiiAssertionConfig {\n denyPatterns: string[];\n customPatterns?: Array<{ name: string; pattern: string }>;\n}\n\nconst MAX_PII_MATCHES = 1000;\nconst REGEX_TIMEOUT_MS = 100;\n\nfunction redact(match: string): string {\n if (match.length <= 4) return \"*\".repeat(match.length);\n return match.slice(0, 2) + \"*\".repeat(match.length - 4) + match.slice(-2);\n}\n\nconst NESTED_QUANTIFIER_RE = /(\\+|\\*|\\{[^}]+\\})\\)?(\\+|\\*|\\{[^}]+\\})/;\n\nexport function hasNestedQuantifiers(pattern: string): boolean {\n return NESTED_QUANTIFIER_RE.test(pattern);\n}\n\nfunction safeRegexExec(\n regex: RegExp,\n text: string,\n maxMatches: number,\n): string[] {\n const results: string[] = [];\n const start = Date.now();\n // Reset lastIndex for global regexes reused across evaluations\n regex.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = regex.exec(text)) !== null) {\n results.push(m[0]);\n if (results.length >= maxMatches) break;\n if (Date.now() - start > REGEX_TIMEOUT_MS) break;\n }\n return results;\n}\n\nexport function createPiiAssertion(config: PiiAssertionConfig): Assertion {\n // Pre-compile all regexes once at assertion creation time\n const compiledPatterns: Array<{ name: string; regex: RegExp }> = [];\n let compilationError: AssertionResult[] | undefined;\n\n for (let i = 0; i < config.denyPatterns.length; i++) {\n const pattern = config.denyPatterns[i];\n if (pattern === undefined) continue;\n compiledPatterns.push({\n name: `pii-pattern-${i + 1}`,\n regex: new RegExp(pattern, \"gi\"),\n });\n }\n\n if (config.customPatterns) {\n for (const cp of config.customPatterns) {\n if (hasNestedQuantifiers(cp.pattern)) {\n compilationError = [\n {\n assertionType: \"pii\",\n label: \"No PII detected\",\n passed: false,\n score: 0,\n failureCode: \"INVALID_PATTERN\",\n failureMessage: `Custom pattern \"${cp.name}\" contains nested quantifiers and may cause catastrophic backtracking`,\n },\n ];\n break;\n }\n compiledPatterns.push({\n name: cp.name,\n regex: new RegExp(cp.pattern, \"gi\"),\n });\n }\n }\n\n return {\n type: \"pii\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n if (compilationError) {\n return Promise.resolve(compilationError);\n }\n\n const matches: Array<{ name: string; redacted: string }> = [];\n let totalMatches = 0;\n\n for (const { name, regex } of compiledPatterns) {\n if (totalMatches >= MAX_PII_MATCHES) break;\n const remaining = MAX_PII_MATCHES - totalMatches;\n const found = safeRegexExec(regex, context.outputText, remaining);\n for (const m of found) {\n matches.push({ name, redacted: redact(m) });\n }\n totalMatches += found.length;\n }\n\n const passed = matches.length === 0;\n return Promise.resolve([\n {\n assertionType: \"pii\",\n label: \"No PII detected\",\n passed,\n score: passed ? 1 : 0,\n failureCode: passed ? undefined : \"PII_DETECTED\",\n failureMessage: passed\n ? undefined\n : `Found ${matches.length} PII match(es): ${matches.map((m) => `${m.name}=${m.redacted}`).join(\", \")}`,\n metadata: passed ? undefined : { matches },\n },\n ]);\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport function createKeywordsPresentAssertion(keywords: string[]): Assertion {\n return {\n type: \"keywords_present\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const lower = context.outputText.toLowerCase();\n const found = keywords.some((kw) => lower.includes(kw.toLowerCase()));\n return Promise.resolve([\n {\n assertionType: \"keywords_present\",\n label: \"Required keyword present\",\n passed: found,\n score: found ? 1 : 0,\n failureCode: found ? undefined : \"KEYWORD_MISSING\",\n failureMessage: found\n ? undefined\n : `Expected at least one of [${keywords.join(\", \")}] in output`,\n },\n ]);\n },\n };\n}\n\nexport function createKeywordsAbsentAssertion(keywords: string[]): Assertion {\n return {\n type: \"keywords_absent\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const lower = context.outputText.toLowerCase();\n const results: AssertionResult[] = [];\n\n for (const keyword of keywords) {\n const found = lower.includes(keyword.toLowerCase());\n results.push({\n assertionType: \"keywords_absent\",\n label: `Keyword \"${keyword}\" absent`,\n passed: !found,\n score: found ? 0 : 1,\n failureCode: found ? \"KEYWORD_DENIED\" : undefined,\n failureMessage: found\n ? `Denied keyword \"${keyword}\" found in output`\n : undefined,\n });\n }\n\n return Promise.resolve(results);\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface JudgeAssertionConfig {\n criteria: string;\n minScore: number;\n rubric?: string;\n}\n\nconst JUDGE_SYSTEM_PROMPT = `You are an impartial AI judge evaluating an AI assistant's response.\nYou will be given:\n- The assistant's response\n- Evaluation criteria\n- An optional rubric\n\nScore the response from 0.0 to 1.0 based on how well it meets the criteria.\n\nRespond ONLY with a JSON object in this exact format:\n{\"score\": <number between 0.0 and 1.0>, \"reasoning\": \"<brief explanation>\"}`;\n\nfunction buildUserPrompt(\n outputText: string,\n criteria: string,\n rubric?: string,\n): string {\n let prompt = `## Assistant Response\\n${outputText}\\n\\n## Criteria\\n${criteria}`;\n if (rubric) {\n prompt += `\\n\\n## Rubric\\n${rubric}`;\n }\n return prompt;\n}\n\nfunction parseJudgeResponse(text: string): { score: number; reasoning: string } | null {\n const jsonMatch = text.match(/```(?:json)?\\s*([\\s\\S]*?)```/) ?? text.match(/(\\{[\\s\\S]*\\})/);\n if (!jsonMatch?.[1]) return null;\n try {\n const parsed = JSON.parse(jsonMatch[1]) as Record<string, unknown>;\n if (typeof parsed.score === \"number\" && typeof parsed.reasoning === \"string\") {\n return { score: parsed.score, reasoning: parsed.reasoning };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function createJudgeAssertion(config: JudgeAssertionConfig): Assertion {\n return {\n type: \"judge\",\n async evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n if (!context.judgeAdapter || !context.judgeModel) {\n return [\n {\n assertionType: \"judge\",\n label: `Judge: ${config.criteria}`,\n passed: false,\n score: 0,\n failureCode: \"INTERNAL_ERROR\",\n failureMessage:\n \"Judge assertion requires judgeAdapter and judgeModel in context\",\n },\n ];\n }\n\n const response = await context.judgeAdapter.complete({\n model: context.judgeModel,\n messages: [\n { role: \"system\", content: JUDGE_SYSTEM_PROMPT },\n {\n role: \"user\",\n content: buildUserPrompt(\n context.outputText,\n config.criteria,\n config.rubric,\n ),\n },\n ],\n params: { temperature: 0, maxTokens: 512 },\n });\n\n const parsed = parseJudgeResponse(response.text);\n if (!parsed) {\n return [\n {\n assertionType: \"judge\",\n label: `Judge: ${config.criteria}`,\n passed: false,\n score: 0,\n failureCode: \"INTERNAL_ERROR\",\n failureMessage: `Failed to parse judge response: ${response.text.slice(0, 200)}`,\n },\n ];\n }\n\n const passed = parsed.score >= config.minScore;\n return [\n {\n assertionType: \"judge\",\n label: `Judge: ${config.criteria}`,\n passed,\n score: parsed.score,\n failureCode: passed ? undefined : \"JUDGE_BELOW_THRESHOLD\",\n failureMessage: passed\n ? undefined\n : `Score ${parsed.score} below threshold ${config.minScore}: ${parsed.reasoning}`,\n metadata: { reasoning: parsed.reasoning },\n },\n ];\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface DriftAssertionConfig {\n maxScore: number;\n method: \"judge\" | \"embedding\" | \"field-diff\";\n fields?: string[];\n}\n\nconst DRIFT_JUDGE_SYSTEM = `You are an impartial AI judge comparing two AI assistant responses.\nYou will be given a baseline response and a new response.\nEvaluate how much the new response has drifted from the baseline.\n\nScore from 0.0 to 1.0 where:\n- 0.0 = responses are semantically identical\n- 0.5 = moderate differences in tone, detail, or structure\n- 1.0 = completely different meaning or contradictory\n\nRespond ONLY with a JSON object in this exact format:\n{\"driftScore\": <number between 0.0 and 1.0>, \"reasoning\": \"<brief explanation>\"}`;\n\nfunction parseDriftResponse(text: string): { driftScore: number; reasoning: string } | null {\n const jsonMatch = text.match(/```(?:json)?\\s*([\\s\\S]*?)```/) ?? text.match(/(\\{[\\s\\S]*\\})/);\n if (!jsonMatch?.[1]) return null;\n try {\n const parsed = JSON.parse(jsonMatch[1]) as Record<string, unknown>;\n if (typeof parsed.driftScore === \"number\" && typeof parsed.reasoning === \"string\") {\n return { driftScore: parsed.driftScore, reasoning: parsed.reasoning };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction getNestedField(obj: unknown, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\nfunction fieldDiff(\n baselineText: string,\n outputText: string,\n fields: string[],\n): { driftScore: number; mismatched: string[] } {\n let baselineObj: unknown;\n let outputObj: unknown;\n try {\n baselineObj = JSON.parse(baselineText);\n outputObj = JSON.parse(outputText);\n } catch {\n return { driftScore: 1, mismatched: [\"(parse error)\"] };\n }\n\n const mismatched: string[] = [];\n for (const field of fields) {\n const baseVal = getNestedField(baselineObj, field);\n const outVal = getNestedField(outputObj, field);\n if (JSON.stringify(baseVal) !== JSON.stringify(outVal)) {\n mismatched.push(field);\n }\n }\n const driftScore = fields.length > 0 ? mismatched.length / fields.length : 0;\n return { driftScore, mismatched };\n}\n\nexport function createDriftAssertion(config: DriftAssertionConfig): Assertion {\n return {\n type: \"drift\",\n async evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n if (!context.baselineText) {\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check\",\n passed: true,\n score: 1,\n metadata: { reason: \"No baseline available\" },\n },\n ];\n }\n\n if (config.method === \"embedding\") {\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check (embedding)\",\n passed: true,\n score: 1,\n metadata: { reason: \"Embedding method not yet implemented\" },\n },\n ];\n }\n\n if (config.method === \"field-diff\") {\n const fields = config.fields ?? [];\n const { driftScore, mismatched } = fieldDiff(\n context.baselineText,\n context.outputText,\n fields,\n );\n const score = 1 - driftScore;\n const passed = driftScore <= config.maxScore;\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check (field-diff)\",\n passed,\n score,\n failureCode: passed ? undefined : \"DRIFT_EXCEEDED\",\n failureMessage: passed\n ? undefined\n : `Drift score ${driftScore.toFixed(2)} exceeds max ${config.maxScore}. Mismatched: [${mismatched.join(\", \")}]`,\n metadata: { driftScore, mismatched },\n },\n ];\n }\n\n // method === \"judge\"\n if (!context.judgeAdapter || !context.judgeModel) {\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check (judge)\",\n passed: false,\n score: 0,\n failureCode: \"INTERNAL_ERROR\",\n failureMessage:\n \"Drift judge method requires judgeAdapter and judgeModel in context\",\n },\n ];\n }\n\n const response = await context.judgeAdapter.complete({\n model: context.judgeModel,\n messages: [\n { role: \"system\", content: DRIFT_JUDGE_SYSTEM },\n {\n role: \"user\",\n content: `## Baseline Response\\n${context.baselineText}\\n\\n## New Response\\n${context.outputText}`,\n },\n ],\n params: { temperature: 0, maxTokens: 512 },\n });\n\n const parsed = parseDriftResponse(response.text);\n if (!parsed) {\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check (judge)\",\n passed: false,\n score: 0,\n failureCode: \"INTERNAL_ERROR\",\n failureMessage: `Failed to parse drift judge response: ${response.text.slice(0, 200)}`,\n },\n ];\n }\n\n const score = 1 - parsed.driftScore;\n const passed = parsed.driftScore <= config.maxScore;\n return [\n {\n assertionType: \"drift\",\n label: \"Drift check (judge)\",\n passed,\n score,\n failureCode: passed ? undefined : \"DRIFT_EXCEEDED\",\n failureMessage: passed\n ? undefined\n : `Drift score ${parsed.driftScore.toFixed(2)} exceeds max ${config.maxScore}: ${parsed.reasoning}`,\n metadata: { driftScore: parsed.driftScore, reasoning: parsed.reasoning },\n },\n ];\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface LatencyAssertionConfig {\n maxMs: number;\n}\n\nexport function createLatencyAssertion(config: LatencyAssertionConfig): Assertion {\n return {\n type: \"latency\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const latencyMs = context.latencyMs ?? 0;\n const passed = latencyMs <= config.maxMs;\n return Promise.resolve([\n {\n assertionType: \"latency\",\n label: `Latency <= ${config.maxMs}ms`,\n passed,\n score: passed ? 1 : 0,\n failureCode: passed ? undefined : \"PROVIDER_TIMEOUT\",\n failureMessage: passed\n ? undefined\n : `Latency ${latencyMs}ms exceeds max ${config.maxMs}ms`,\n metadata: { latencyMs },\n },\n ]);\n },\n };\n}\n","import type { Assertion, AssertionContext, AssertionResult } from \"./interface.js\";\n\nexport interface CostAssertionConfig {\n maxUsd: number;\n}\n\nexport function createCostAssertion(config: CostAssertionConfig): Assertion {\n return {\n type: \"cost\",\n evaluate(context: AssertionContext): Promise<AssertionResult[]> {\n const costUsd = context.costUsd ?? 0;\n const passed = costUsd <= config.maxUsd;\n return Promise.resolve([\n {\n assertionType: \"cost\",\n label: `Cost <= $${config.maxUsd}`,\n passed,\n score: passed ? 1 : 0,\n failureCode: passed ? undefined : \"INTERNAL_ERROR\",\n failureMessage: passed\n ? undefined\n : `Cost $${costUsd.toFixed(4)} exceeds max $${config.maxUsd}`,\n metadata: { costUsd },\n },\n ]);\n },\n };\n}\n","import type { Assertion } from \"./interface.js\";\nimport type { Expect } from \"../types/config.js\";\nimport {\n createToolCalledAssertion,\n createToolNotCalledAssertion,\n createToolOrderAssertion,\n} from \"./tool-calls.js\";\nimport { createSchemaAssertion } from \"./schema.js\";\nimport { createPiiAssertion } from \"./pii.js\";\nimport {\n createKeywordsPresentAssertion,\n createKeywordsAbsentAssertion,\n} from \"./keywords.js\";\nimport { createJudgeAssertion } from \"./judge.js\";\nimport { createDriftAssertion } from \"./drift.js\";\nimport { createLatencyAssertion } from \"./latency.js\";\nimport { createCostAssertion } from \"./cost.js\";\n\nexport type AssertionFactory = (config: Expect) => Assertion;\n\nexport interface AssertionOverrides {\n schemaContent?: Record<string, unknown>;\n}\n\nexport function createAssertionsFromExpect(expect: Expect, overrides?: AssertionOverrides): Assertion[] {\n const assertions: Assertion[] = [];\n\n if (expect.toolCalls) {\n const hasOrder = expect.toolCalls.some((tc) => tc.order !== undefined);\n\n if (hasOrder) {\n assertions.push(createToolOrderAssertion(expect.toolCalls));\n } else {\n for (const tc of expect.toolCalls) {\n if (tc.shouldNotCall) {\n assertions.push(createToolNotCalledAssertion(tc.tool));\n } else {\n assertions.push(\n createToolCalledAssertion(tc.tool, tc.argsMatch ?? undefined),\n );\n }\n }\n }\n }\n\n if (expect.output) {\n assertions.push(\n createSchemaAssertion({\n format: expect.output.format,\n schemaFile: expect.output.schemaFile,\n schemaContent: overrides?.schemaContent,\n contains: expect.output.contains,\n notContains: expect.output.notContains,\n maxLength: expect.output.maxLength,\n }),\n );\n }\n\n if (expect.guardrails?.pii) {\n assertions.push(\n createPiiAssertion({\n denyPatterns: expect.guardrails.pii.denyPatterns,\n customPatterns: expect.guardrails.pii.customPatterns,\n }),\n );\n }\n\n if (expect.guardrails?.keywords) {\n if (\n expect.guardrails.keywords.allow &&\n expect.guardrails.keywords.allow.length > 0\n ) {\n assertions.push(\n createKeywordsPresentAssertion(expect.guardrails.keywords.allow),\n );\n }\n if (expect.guardrails.keywords.deny.length > 0) {\n assertions.push(\n createKeywordsAbsentAssertion(expect.guardrails.keywords.deny),\n );\n }\n }\n\n if (expect.judge) {\n for (const criterion of expect.judge) {\n assertions.push(\n createJudgeAssertion({\n criteria: criterion.criteria,\n minScore: criterion.minScore,\n rubric: criterion.rubric,\n }),\n );\n }\n }\n\n if (expect.baseline?.drift) {\n assertions.push(\n createDriftAssertion({\n maxScore: expect.baseline.drift.maxScore,\n method: expect.baseline.drift.method,\n fields: expect.baseline.drift.fields,\n }),\n );\n }\n\n return assertions;\n}\n\nexport function createAssertionRegistry(): Map<string, AssertionFactory> {\n return new Map<string, AssertionFactory>([\n [\"tool_called\", (config) => createToolCalledAssertion(config.toolCalls?.[0]?.tool ?? \"\")],\n [\"schema\", (config) => createSchemaAssertion(config.output ?? { format: \"text\" })],\n [\"pii\", (config) => createPiiAssertion(config.guardrails?.pii ?? { denyPatterns: [] })],\n [\"judge\", (config) => createJudgeAssertion(config.judge?.[0] ?? { criteria: \"\", minScore: 0.7 })],\n [\"drift\", (config) => createDriftAssertion(config.baseline?.drift ?? { maxScore: 0.15, method: \"judge\" })],\n [\"latency\", () => createLatencyAssertion({ maxMs: 60000 })],\n [\"cost\", () => createCostAssertion({ maxUsd: 1.0 })],\n ]);\n}\n","export type AssertionCategory = \"deterministic\" | \"probabilistic\";\n\nconst PROBABILISTIC_TYPES = new Set([\"judge\", \"drift\"]);\n\nexport function classifyAssertion(assertionType: string): AssertionCategory {\n return PROBABILISTIC_TYPES.has(assertionType) ? \"probabilistic\" : \"deterministic\";\n}\n\nexport function isDeterministic(assertionType: string): boolean {\n return classifyAssertion(assertionType) === \"deterministic\";\n}\n\nexport function isProbabilistic(assertionType: string): boolean {\n return classifyAssertion(assertionType) === \"probabilistic\";\n}\n","export interface RetryOptions {\n maxRetries: number;\n shouldRetry: (error: unknown) => boolean;\n baseDelayMs?: number;\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions,\n): Promise<T> {\n const { maxRetries, shouldRetry, baseDelayMs = 500 } = options;\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n if (attempt >= maxRetries || !shouldRetry(error)) {\n throw error;\n }\n\n const delay = baseDelayMs * Math.pow(2, attempt);\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nconst OPENAI_PRICING: Record<string, { input: number; output: number }> = {\n \"gpt-4o\": { input: 2.5, output: 10.0 },\n \"gpt-4o-mini\": { input: 0.15, output: 0.6 },\n \"gpt-4-turbo\": { input: 10.0, output: 30.0 },\n \"o3-mini\": { input: 1.1, output: 4.4 },\n};\n\nfunction mapFinishReason(\n reason: string | undefined,\n): ProviderResponse[\"finishReason\"] {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"max_tokens\";\n case \"tool_calls\":\n return \"tool_calls\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"error\" in data\n ? String(\n (data as { error: { message?: string } }).error?.message ??\n \"Unknown error\",\n )\n : \"Unknown error\";\n\n switch (status) {\n case 401:\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 400:\n if (message.toLowerCase().includes(\"context length\")) {\n return new ProviderError(\n \"CONTEXT_LENGTH\",\n message,\n status,\n false,\n data,\n );\n }\n return new ProviderError(\"PROVIDER_ERROR\", message, status, false, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createOpenAIAdapter(httpClient: HttpClient): ProviderAdapter {\n let apiKey = \"\";\n let baseUrl = \"https://api.openai.com/v1\";\n let organization: string | undefined;\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"openai\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (!config.apiKey) {\n throw new ProviderError(\"AUTH_FAILED\", \"API key is required\");\n }\n apiKey = config.apiKey;\n if (config.baseUrl) baseUrl = config.baseUrl;\n organization = config.organization;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const body: Record<string, unknown> = {\n model: request.model,\n messages: request.messages.map((m) => {\n if (m.role === \"tool\") {\n return {\n role: \"tool\",\n content: m.content,\n tool_call_id: m.toolCallId,\n };\n }\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n return {\n role: \"assistant\",\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: JSON.stringify(tc.arguments),\n },\n })),\n };\n }\n return { role: m.role, content: m.content };\n }),\n temperature: request.params.temperature,\n max_tokens: request.params.maxTokens,\n };\n\n if (request.params.topP !== undefined)\n body.top_p = request.params.topP;\n if (request.params.seed !== undefined) body.seed = request.params.seed;\n if (request.params.stopSequences)\n body.stop = request.params.stopSequences;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n if (request.toolChoice) {\n body.tool_choice = request.toolChoice;\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n };\n if (organization) {\n headers[\"OpenAI-Organization\"] = organization;\n }\n\n const startTime = Date.now();\n\n const response = await withRetry(\n () =>\n httpClient.fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from OpenAI API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n choices?: Array<{\n message?: {\n content?: string | null;\n tool_calls?: Array<{\n id: string;\n function: { name: string; arguments: string };\n }>;\n };\n finish_reason?: string;\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n model?: string;\n };\n\n const choice = parsed.choices?.[0];\n const message = choice?.message;\n\n const toolCalls: ProviderToolCall[] = (message?.tool_calls ?? []).map(\n (tc) => {\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(tc.function.arguments || \"{}\") as Record<\n string,\n unknown\n >;\n } catch {\n args = { _raw: tc.function.arguments };\n }\n return {\n id: tc.id,\n name: tc.function.name,\n arguments: args,\n };\n },\n );\n\n return {\n text: message?.content ?? \"\",\n toolCalls,\n usage: {\n inputTokens: parsed.usage?.prompt_tokens ?? 0,\n outputTokens: parsed.usage?.completion_tokens ?? 0,\n totalTokens: parsed.usage?.total_tokens ?? 0,\n },\n raw: json,\n latencyMs,\n modelId: parsed.model ?? request.model,\n finishReason: mapFinishReason(choice?.finish_reason),\n };\n },\n\n estimateCost(\n model: string,\n usage: ProviderResponse[\"usage\"],\n ): number | null {\n const pricing = OPENAI_PRICING[model];\n if (!pricing) return null;\n return (\n (usage.inputTokens / 1_000_000) * pricing.input +\n (usage.outputTokens / 1_000_000) * pricing.output\n );\n },\n\n supportsTools(model: string): boolean {\n return !model.startsWith(\"o1-\");\n },\n };\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nconst ANTHROPIC_PRICING: Record<string, { input: number; output: number }> = {\n \"claude-opus-4-5-20250929\": { input: 15.0, output: 75.0 },\n \"claude-sonnet-4-5-20250929\": { input: 3.0, output: 15.0 },\n \"claude-haiku-4-5-20251001\": { input: 0.8, output: 4.0 },\n};\n\nfunction mapFinishReason(\n reason: string | undefined,\n): ProviderResponse[\"finishReason\"] {\n switch (reason) {\n case \"end_turn\":\n return \"stop\";\n case \"max_tokens\":\n return \"max_tokens\";\n case \"tool_use\":\n return \"tool_calls\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"error\" in data\n ? String(\n (data as { error: { message?: string } }).error?.message ??\n \"Unknown error\",\n )\n : \"Unknown error\";\n\n switch (status) {\n case 401:\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 400:\n if (message.toLowerCase().includes(\"context length\")) {\n return new ProviderError(\n \"CONTEXT_LENGTH\",\n message,\n status,\n false,\n data,\n );\n }\n return new ProviderError(\"PROVIDER_ERROR\", message, status, false, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createAnthropicAdapter(\n httpClient: HttpClient,\n): ProviderAdapter {\n let apiKey = \"\";\n let baseUrl = \"https://api.anthropic.com\";\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"anthropic\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (!config.apiKey) {\n throw new ProviderError(\"AUTH_FAILED\", \"API key is required\");\n }\n apiKey = config.apiKey;\n if (config.baseUrl) baseUrl = config.baseUrl;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const systemMessage = request.messages.find((m) => m.role === \"system\");\n const nonSystemMessages = request.messages\n .filter((m) => m.role !== \"system\")\n .map((m) => {\n if (m.role === \"tool\") {\n return {\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: m.toolCallId,\n content: m.content,\n },\n ],\n };\n }\n if (m.role === \"assistant\") {\n if (m.toolCalls && m.toolCalls.length > 0) {\n const contentBlocks: unknown[] = [];\n if (m.content) {\n contentBlocks.push({ type: \"text\", text: m.content });\n }\n for (const tc of m.toolCalls) {\n contentBlocks.push({\n type: \"tool_use\",\n id: tc.id,\n name: tc.name,\n input: tc.arguments,\n });\n }\n return { role: \"assistant\", content: contentBlocks };\n }\n return { role: \"assistant\", content: m.content };\n }\n return { role: \"user\", content: m.content };\n });\n\n const body: Record<string, unknown> = {\n model: request.model,\n max_tokens: request.params.maxTokens,\n messages: nonSystemMessages,\n };\n\n if (systemMessage) body.system = systemMessage.content;\n if (request.params.temperature !== undefined)\n body.temperature = request.params.temperature;\n if (request.params.topP !== undefined)\n body.top_p = request.params.topP;\n if (request.params.stopSequences)\n body.stop_sequences = request.params.stopSequences;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n name: t.name,\n description: t.description ?? \"\",\n input_schema: t.parameters ?? { type: \"object\", properties: {} },\n }));\n if (request.toolChoice) {\n body.tool_choice =\n request.toolChoice === \"required\"\n ? { type: \"any\" }\n : { type: request.toolChoice };\n }\n }\n\n const startTime = Date.now();\n\n const response = await withRetry(\n () =>\n httpClient.fetch(`${baseUrl}/v1/messages`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from Anthropic API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n content?: Array<\n | { type: \"text\"; text: string }\n | { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n >;\n usage?: { input_tokens?: number; output_tokens?: number };\n model?: string;\n stop_reason?: string;\n };\n\n let text = \"\";\n const toolCalls: ProviderToolCall[] = [];\n\n for (const block of parsed.content ?? []) {\n if (block.type === \"text\") {\n text += block.text;\n } else if (block.type === \"tool_use\") {\n toolCalls.push({\n id: block.id,\n name: block.name,\n arguments: block.input ?? {},\n });\n }\n }\n\n const inputTokens = parsed.usage?.input_tokens ?? 0;\n const outputTokens = parsed.usage?.output_tokens ?? 0;\n\n return {\n text,\n toolCalls,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n raw: json,\n latencyMs,\n modelId: parsed.model ?? request.model,\n finishReason: mapFinishReason(parsed.stop_reason),\n };\n },\n\n estimateCost(\n model: string,\n usage: ProviderResponse[\"usage\"],\n ): number | null {\n const entry = Object.entries(ANTHROPIC_PRICING).find(\n ([key]) => model.includes(key) || key.includes(model),\n );\n if (!entry) return null;\n return (\n (usage.inputTokens / 1_000_000) * entry[1].input +\n (usage.outputTokens / 1_000_000) * entry[1].output\n );\n },\n\n supportsTools(_model: string): boolean {\n return true;\n },\n };\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nfunction mapFinishReason(\n doneReason: string | undefined,\n hasToolCalls: boolean,\n): ProviderResponse[\"finishReason\"] {\n if (hasToolCalls) return \"tool_calls\";\n switch (doneReason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"max_tokens\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"error\" in data\n ? String((data as { error: string }).error)\n : \"Unknown error\";\n\n switch (status) {\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createOllamaAdapter(httpClient: HttpClient): ProviderAdapter {\n let baseUrl = \"http://localhost:11434\";\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"ollama\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (config.baseUrl) baseUrl = config.baseUrl;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const messages = request.messages.map((m) => {\n if (m.role === \"tool\") {\n return {\n role: \"tool\" as const,\n content: m.content,\n };\n }\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n return {\n role: \"assistant\" as const,\n content: m.content || \"\",\n tool_calls: m.toolCalls.map((tc) => ({\n function: {\n name: tc.name,\n arguments: tc.arguments,\n },\n })),\n };\n }\n return { role: m.role, content: m.content };\n });\n\n const body: Record<string, unknown> = {\n model: request.model,\n messages,\n stream: false,\n options: {\n temperature: request.params.temperature,\n num_predict: request.params.maxTokens,\n },\n };\n\n const options = body.options as Record<string, unknown>;\n if (request.params.topP !== undefined)\n options.top_p = request.params.topP;\n if (request.params.seed !== undefined) options.seed = request.params.seed;\n if (request.params.stopSequences)\n options.stop = request.params.stopSequences;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n const startTime = Date.now();\n\n const response = await withRetry(\n () =>\n httpClient.fetch(`${baseUrl}/api/chat`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from Ollama API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n message?: {\n content?: string;\n tool_calls?: Array<{\n function: { name: string; arguments: Record<string, unknown> };\n }>;\n };\n done_reason?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n model?: string;\n };\n\n const message = parsed.message;\n const rawToolCalls = message?.tool_calls ?? [];\n\n const toolCalls: ProviderToolCall[] = rawToolCalls.map((tc, index) => ({\n id: `ollama_call_${index}`,\n name: tc.function.name,\n arguments: tc.function.arguments ?? {},\n }));\n\n return {\n text: message?.content ?? \"\",\n toolCalls,\n usage: {\n inputTokens: parsed.prompt_eval_count ?? 0,\n outputTokens: parsed.eval_count ?? 0,\n totalTokens:\n (parsed.prompt_eval_count ?? 0) + (parsed.eval_count ?? 0),\n },\n raw: json,\n latencyMs,\n modelId: parsed.model ?? request.model,\n finishReason: mapFinishReason(\n parsed.done_reason,\n rawToolCalls.length > 0,\n ),\n };\n },\n\n estimateCost(): number | null {\n return 0;\n },\n\n supportsTools(): boolean {\n return true;\n },\n };\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nconst GEMINI_PRICING: Record<string, { input: number; output: number }> = {\n \"gemini-2.0-flash\": { input: 0.1, output: 0.4 },\n \"gemini-2.0-flash-lite\": { input: 0.075, output: 0.3 },\n \"gemini-1.5-pro\": { input: 1.25, output: 5.0 },\n \"gemini-1.5-flash\": { input: 0.075, output: 0.3 },\n \"gemini-1.5-flash-8b\": { input: 0.0375, output: 0.15 },\n};\n\nfunction mapFinishReason(\n reason: string | undefined,\n hasToolCalls: boolean,\n): ProviderResponse[\"finishReason\"] {\n if (hasToolCalls) return \"tool_calls\";\n switch (reason) {\n case \"STOP\":\n return \"stop\";\n case \"MAX_TOKENS\":\n return \"max_tokens\";\n case \"SAFETY\":\n return \"stop\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"error\" in data\n ? String(\n (data as { error: { message?: string } }).error?.message ??\n \"Unknown error\",\n )\n : \"Unknown error\";\n\n switch (status) {\n case 400:\n if (message.toLowerCase().includes(\"api key\")) {\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n }\n return new ProviderError(\"PROVIDER_ERROR\", message, status, false, data);\n case 401:\n case 403:\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createGeminiAdapter(httpClient: HttpClient): ProviderAdapter {\n let apiKey = \"\";\n let baseUrl = \"https://generativelanguage.googleapis.com/v1beta\";\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"gemini\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (!config.apiKey) {\n throw new ProviderError(\"AUTH_FAILED\", \"API key is required\");\n }\n apiKey = config.apiKey;\n if (config.baseUrl) baseUrl = config.baseUrl;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const contents: Array<{\n role: string;\n parts: Array<Record<string, unknown>>;\n }> = [];\n let systemInstruction: { parts: Array<{ text: string }> } | undefined;\n\n for (const m of request.messages) {\n if (m.role === \"system\") {\n systemInstruction = { parts: [{ text: m.content }] };\n continue;\n }\n\n if (m.role === \"tool\") {\n contents.push({\n role: \"function\",\n parts: [\n {\n functionResponse: {\n name: m.toolName ?? \"unknown\",\n response: parseToolContent(m.content),\n },\n },\n ],\n });\n continue;\n }\n\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n const parts: Record<string, unknown>[] = [];\n if (m.content) parts.push({ text: m.content });\n for (const tc of m.toolCalls) {\n parts.push({\n functionCall: { name: tc.name, args: tc.arguments },\n });\n }\n contents.push({ role: \"model\", parts });\n continue;\n }\n\n const geminiRole = m.role === \"assistant\" ? \"model\" : \"user\";\n contents.push({\n role: geminiRole,\n parts: [{ text: m.content }],\n });\n }\n\n const body: Record<string, unknown> = {\n contents,\n generationConfig: {\n temperature: request.params.temperature,\n maxOutputTokens: request.params.maxTokens,\n },\n };\n\n if (systemInstruction) {\n body.systemInstruction = systemInstruction;\n }\n\n const generationConfig = body.generationConfig as Record<\n string,\n unknown\n >;\n if (request.params.topP !== undefined) {\n generationConfig.topP = request.params.topP;\n }\n if (request.params.stopSequences) {\n generationConfig.stopSequences = request.params.stopSequences;\n }\n\n if (request.tools && request.tools.length > 0) {\n body.tools = [\n {\n functionDeclarations: request.tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n })),\n },\n ];\n if (request.toolChoice) {\n body.toolConfig = mapToolChoice(request.toolChoice);\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n };\n\n const startTime = Date.now();\n\n const url = `${baseUrl}/models/${request.model}:generateContent`;\n\n const response = await withRetry(\n () =>\n httpClient.fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from Gemini API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n candidates?: Array<{\n content?: {\n parts?: Array<{\n text?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n }>;\n };\n finishReason?: string;\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n };\n modelVersion?: string;\n };\n\n const candidate = parsed.candidates?.[0];\n const parts = candidate?.content?.parts ?? [];\n\n let text = \"\";\n const toolCalls: ProviderToolCall[] = [];\n let toolCallIndex = 0;\n\n for (const part of parts) {\n if (part.text !== undefined) {\n text += part.text;\n }\n if (part.functionCall) {\n toolCalls.push({\n id: `gemini_call_${toolCallIndex}`,\n name: part.functionCall.name,\n arguments: part.functionCall.args ?? {},\n });\n toolCallIndex++;\n }\n }\n\n return {\n text,\n toolCalls,\n usage: {\n inputTokens: parsed.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: parsed.usageMetadata?.candidatesTokenCount ?? 0,\n totalTokens: parsed.usageMetadata?.totalTokenCount ?? 0,\n },\n raw: json,\n latencyMs,\n modelId: parsed.modelVersion ?? request.model,\n finishReason: mapFinishReason(\n candidate?.finishReason,\n toolCalls.length > 0,\n ),\n };\n },\n\n estimateCost(\n model: string,\n usage: ProviderResponse[\"usage\"],\n ): number | null {\n const pricing = GEMINI_PRICING[model];\n if (!pricing) return null;\n return (\n (usage.inputTokens / 1_000_000) * pricing.input +\n (usage.outputTokens / 1_000_000) * pricing.output\n );\n },\n\n supportsTools(): boolean {\n return true;\n },\n };\n}\n\nfunction parseToolContent(content: string): unknown {\n try {\n return JSON.parse(content);\n } catch {\n return { result: content };\n }\n}\n\nfunction mapToolChoice(\n choice: \"auto\" | \"required\" | \"none\",\n): Record<string, unknown> {\n switch (choice) {\n case \"auto\":\n return { functionCallingConfig: { mode: \"AUTO\" } };\n case \"required\":\n return { functionCallingConfig: { mode: \"ANY\" } };\n case \"none\":\n return { functionCallingConfig: { mode: \"NONE\" } };\n }\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nfunction mapFinishReason(\n reason: string | undefined,\n): ProviderResponse[\"finishReason\"] {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"max_tokens\";\n case \"tool_calls\":\n return \"tool_calls\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"message\" in data\n ? String((data as { message?: string }).message ?? \"Unknown error\")\n : typeof data === \"object\" && data !== null && \"error\" in data\n ? String(\n (data as { error: { message?: string } }).error?.message ??\n \"Unknown error\",\n )\n : \"Unknown error\";\n\n switch (status) {\n case 401:\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 400:\n if (message.toLowerCase().includes(\"context length\")) {\n return new ProviderError(\n \"CONTEXT_LENGTH\",\n message,\n status,\n false,\n data,\n );\n }\n return new ProviderError(\"PROVIDER_ERROR\", message, status, false, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createMistralAdapter(httpClient: HttpClient): ProviderAdapter {\n let apiKey = \"\";\n let baseUrl = \"https://api.mistral.ai/v1\";\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"mistral\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (!config.apiKey) {\n throw new ProviderError(\"AUTH_FAILED\", \"API key is required\");\n }\n apiKey = config.apiKey;\n if (config.baseUrl) baseUrl = config.baseUrl;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const body: Record<string, unknown> = {\n model: request.model,\n messages: request.messages.map((m) => {\n if (m.role === \"tool\") {\n return {\n role: \"tool\",\n content: m.content,\n tool_call_id: m.toolCallId,\n };\n }\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n return {\n role: \"assistant\",\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: JSON.stringify(tc.arguments),\n },\n })),\n };\n }\n return { role: m.role, content: m.content };\n }),\n temperature: request.params.temperature,\n max_tokens: request.params.maxTokens,\n };\n\n if (request.params.topP !== undefined)\n body.top_p = request.params.topP;\n if (request.params.stopSequences)\n body.stop = request.params.stopSequences;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n if (request.toolChoice) {\n body.tool_choice = request.toolChoice;\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n };\n\n const startTime = Date.now();\n\n const response = await withRetry(\n () =>\n httpClient.fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from Mistral API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n choices?: Array<{\n message?: {\n content?: string | null;\n tool_calls?: Array<{\n id: string;\n function: { name: string; arguments: string };\n }>;\n };\n finish_reason?: string;\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n model?: string;\n };\n\n const choice = parsed.choices?.[0];\n const message = choice?.message;\n\n const toolCalls: ProviderToolCall[] = (message?.tool_calls ?? []).map(\n (tc) => {\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(tc.function.arguments || \"{}\") as Record<\n string,\n unknown\n >;\n } catch {\n args = { _raw: tc.function.arguments };\n }\n return {\n id: tc.id,\n name: tc.function.name,\n arguments: args,\n };\n },\n );\n\n return {\n text: message?.content ?? \"\",\n toolCalls,\n usage: {\n inputTokens: parsed.usage?.prompt_tokens ?? 0,\n outputTokens: parsed.usage?.completion_tokens ?? 0,\n totalTokens: parsed.usage?.total_tokens ?? 0,\n },\n raw: json,\n latencyMs,\n modelId: parsed.model ?? request.model,\n finishReason: mapFinishReason(choice?.finish_reason),\n };\n },\n\n estimateCost(\n _model: string,\n _usage: ProviderResponse[\"usage\"],\n ): number | null {\n // Mistral does not have a public pricing API; return null\n return null;\n },\n\n supportsTools(_model: string): boolean {\n // All current Mistral models support function calling\n return true;\n },\n };\n}\n","import type {\n HttpClient,\n ProviderAdapter,\n ProviderAdapterConfig,\n ProviderRequest,\n ProviderResponse,\n ProviderToolCall,\n} from \"./interface.js\";\nimport { ProviderError } from \"./interface.js\";\nimport { withRetry } from \"./retry.js\";\n\nfunction mapFinishReason(\n reason: string | undefined,\n): ProviderResponse[\"finishReason\"] {\n switch (reason) {\n case \"COMPLETE\":\n return \"stop\";\n case \"MAX_TOKENS\":\n return \"max_tokens\";\n case \"TOOL_CALL\":\n return \"tool_calls\";\n default:\n return \"unknown\";\n }\n}\n\nfunction mapError(status: number, data: unknown): ProviderError {\n const message =\n typeof data === \"object\" && data !== null && \"message\" in data\n ? String((data as { message?: string }).message ?? \"Unknown error\")\n : \"Unknown error\";\n\n switch (status) {\n case 401:\n return new ProviderError(\"AUTH_FAILED\", message, status, false, data);\n case 429:\n return new ProviderError(\"RATE_LIMITED\", message, status, true, data);\n case 404:\n return new ProviderError(\"MODEL_NOT_FOUND\", message, status, false, data);\n case 400:\n if (message.toLowerCase().includes(\"context length\")) {\n return new ProviderError(\n \"CONTEXT_LENGTH\",\n message,\n status,\n false,\n data,\n );\n }\n return new ProviderError(\"PROVIDER_ERROR\", message, status, false, data);\n case 408:\n return new ProviderError(\"TIMEOUT\", message, status, true, data);\n default:\n return new ProviderError(\n status >= 500 ? \"PROVIDER_ERROR\" : \"UNKNOWN\",\n message,\n status,\n status >= 500,\n data,\n );\n }\n}\n\nexport function createCohereAdapter(httpClient: HttpClient): ProviderAdapter {\n let apiKey = \"\";\n let baseUrl = \"https://api.cohere.com\";\n let timeoutMs = 60_000;\n let maxRetries = 2;\n\n return {\n name: \"cohere\",\n\n async initialize(config: ProviderAdapterConfig): Promise<void> {\n if (!config.apiKey) {\n throw new ProviderError(\"AUTH_FAILED\", \"API key is required\");\n }\n apiKey = config.apiKey;\n if (config.baseUrl) baseUrl = config.baseUrl;\n timeoutMs = config.timeoutMs;\n maxRetries = config.maxRetries;\n },\n\n async complete(request: ProviderRequest): Promise<ProviderResponse> {\n const body: Record<string, unknown> = {\n model: request.model,\n messages: request.messages.map((m) => {\n if (m.role === \"tool\") {\n return {\n role: \"tool\",\n content: m.content,\n tool_call_id: m.toolCallId,\n };\n }\n if (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n return {\n role: \"assistant\",\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: JSON.stringify(tc.arguments),\n },\n })),\n };\n }\n return { role: m.role, content: m.content };\n }),\n temperature: request.params.temperature,\n max_tokens: request.params.maxTokens,\n };\n\n if (request.params.topP !== undefined)\n body.p = request.params.topP;\n if (request.params.stopSequences)\n body.stop_sequences = request.params.stopSequences;\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }));\n if (request.toolChoice) {\n body.tool_choice = request.toolChoice;\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n };\n\n const startTime = Date.now();\n\n const response = await withRetry(\n () =>\n httpClient.fetch(`${baseUrl}/v2/chat`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n timeoutMs,\n }),\n {\n maxRetries,\n shouldRetry: (error) =>\n error instanceof ProviderError && error.retryable,\n },\n );\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n throw new ProviderError(\n \"PROVIDER_ERROR\",\n \"Malformed response body from Cohere API\",\n response.status,\n response.status >= 500,\n );\n }\n const latencyMs = Date.now() - startTime;\n\n if (!response.ok) {\n throw mapError(response.status, json);\n }\n\n const parsed = json as {\n message?: {\n role?: string;\n content?: Array<{ type: string; text: string }>;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n };\n finish_reason?: string;\n usage?: {\n tokens?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n model?: string;\n };\n\n const text =\n parsed.message?.content\n ?.filter((c) => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\") ?? \"\";\n\n const toolCalls: ProviderToolCall[] = (\n parsed.message?.tool_calls ?? []\n ).map((tc) => {\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(tc.function.arguments || \"{}\") as Record<\n string,\n unknown\n >;\n } catch {\n args = { _raw: tc.function.arguments };\n }\n return {\n id: tc.id,\n name: tc.function.name,\n arguments: args,\n };\n });\n\n const inputTokens = parsed.usage?.tokens?.input_tokens ?? 0;\n const outputTokens = parsed.usage?.tokens?.output_tokens ?? 0;\n\n return {\n text,\n toolCalls,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n raw: json,\n latencyMs,\n modelId: parsed.model ?? request.model,\n finishReason: mapFinishReason(parsed.finish_reason),\n };\n },\n\n estimateCost(\n _model: string,\n _usage: ProviderResponse[\"usage\"],\n ): number | null {\n // Cohere pricing varies by model; return null for now\n return null;\n },\n\n supportsTools(_model: string): boolean {\n // Cohere v2 API supports tools for all current models\n return true;\n },\n };\n}\n","import type { HttpClient, ProviderAdapter } from \"./interface.js\";\nimport { createOpenAIAdapter } from \"./openai.js\";\nimport { createAnthropicAdapter } from \"./anthropic.js\";\nimport { createOllamaAdapter } from \"./ollama.js\";\nimport { createGeminiAdapter } from \"./gemini.js\";\nimport { createMistralAdapter } from \"./mistral.js\";\nimport { createCohereAdapter } from \"./cohere.js\";\n\nconst PROVIDER_FACTORIES: Record<string, (httpClient: HttpClient) => ProviderAdapter> = {\n openai: createOpenAIAdapter,\n anthropic: createAnthropicAdapter,\n ollama: createOllamaAdapter,\n gemini: createGeminiAdapter,\n mistral: createMistralAdapter,\n cohere: createCohereAdapter,\n};\n\nexport function createProvider(\n name: string,\n httpClient: HttpClient,\n): ProviderAdapter {\n const factory = PROVIDER_FACTORIES[name];\n if (!factory) {\n const supported = Object.keys(PROVIDER_FACTORIES).join(\", \");\n throw new Error(`Unknown provider: \"${name}\". Supported providers: ${supported}`);\n }\n return factory(httpClient);\n}\n","import type {\n ProviderAdapter,\n ProviderRequest,\n ProviderMessage,\n ProviderToolCall,\n ConversationResult,\n ConversationTurn,\n} from \"./interface.js\";\nimport type { ToolSimulation } from \"../types/config.js\";\n\nconst DEFAULT_MAX_TURNS = 10;\n\nexport async function runConversation(\n adapter: ProviderAdapter,\n initialRequest: ProviderRequest,\n toolSimulations: ToolSimulation[],\n options?: { maxTurns?: number },\n): Promise<ConversationResult> {\n const maxTurns = options?.maxTurns ?? DEFAULT_MAX_TURNS;\n const turns: ConversationTurn[] = [];\n const allToolCalls: ProviderToolCall[] = [];\n let messages: ProviderMessage[] = [...initialRequest.messages];\n const totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n let totalLatencyMs = 0;\n\n for (let turn = 0; turn < maxTurns; turn++) {\n const request: ProviderRequest = {\n ...initialRequest,\n messages,\n };\n\n const response = await adapter.complete(request);\n\n turns.push({ request, response });\n totalUsage.inputTokens += response.usage.inputTokens;\n totalUsage.outputTokens += response.usage.outputTokens;\n totalUsage.totalTokens += response.usage.totalTokens;\n totalLatencyMs += response.latencyMs;\n\n if (response.toolCalls.length === 0) {\n return {\n turns,\n finalText: response.text,\n allToolCalls,\n totalUsage,\n totalLatencyMs,\n };\n }\n\n allToolCalls.push(...response.toolCalls);\n\n messages = [\n ...messages,\n { role: \"assistant\", content: response.text, toolCalls: response.toolCalls },\n ];\n\n for (const toolCall of response.toolCalls) {\n const simulation = toolSimulations.find((s) => s.name === toolCall.name);\n let toolResponse: unknown;\n\n if (simulation) {\n toolResponse = resolveToolResponse(simulation, toolCall.arguments);\n } else {\n toolResponse = { error: `Tool \"${toolCall.name}\" not simulated` };\n }\n\n messages.push({\n role: \"tool\",\n content: JSON.stringify(toolResponse),\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n });\n }\n }\n\n const lastTurn = turns[turns.length - 1];\n const lastResponse = lastTurn?.response ?? {\n text: \"\",\n toolCalls: [],\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n raw: null,\n latencyMs: 0,\n modelId: initialRequest.model,\n finishReason: \"unknown\" as const,\n };\n return {\n turns,\n finalText: lastResponse.text,\n allToolCalls,\n totalUsage,\n totalLatencyMs,\n };\n}\n\nfunction resolveToolResponse(\n simulation: ToolSimulation,\n args: Record<string, unknown>,\n): unknown {\n if (simulation.responses) {\n for (const resp of simulation.responses) {\n if (matchArgs(resp.when, args)) {\n return resp.then;\n }\n }\n }\n\n if (simulation.defaultResponse !== undefined) {\n return simulation.defaultResponse;\n }\n\n return { error: \"No matching simulation response\" };\n}\n\nfunction matchArgs(\n expected: Record<string, unknown>,\n actual: Record<string, unknown>,\n): boolean {\n for (const [key, value] of Object.entries(expected)) {\n if (JSON.stringify(actual[key]) !== JSON.stringify(value)) {\n return false;\n }\n }\n return true;\n}\n","import { z } from \"zod\";\nimport type { Result, KindlmError } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\nimport { TraceConfigSchema } from \"../trace/types.js\";\n\n// ============================================================\n// Primitive / Reusable Schemas\n// ============================================================\n\nconst NonEmptyString = z.string().min(1, \"Must not be empty\");\n\nconst Temperature = z.number().min(0).max(2).default(0.2);\n\nconst Score01 = z.number().min(0).max(1);\n\nconst RegexPattern = z.string().refine(\n (val) => {\n try {\n new RegExp(val);\n return true;\n } catch {\n return false;\n }\n },\n { message: \"Must be a valid regex pattern\" },\n);\n\n// ============================================================\n// Provider Schemas\n// ============================================================\n\nconst ProviderConfigSchema = z.object({\n apiKeyEnv: NonEmptyString.describe(\n \"Environment variable name containing the API key. Never a raw key.\",\n ),\n baseUrl: z\n .string()\n .url()\n .optional()\n .describe(\n \"Custom base URL for API-compatible proxies (e.g., Azure OpenAI, LiteLLM)\",\n ),\n organization: z\n .string()\n .optional()\n .describe(\"Organization ID (OpenAI-specific)\"),\n});\n\nconst OllamaProviderConfigSchema = z.object({\n apiKeyEnv: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Environment variable name containing the API key. Optional for Ollama (local).\",\n ),\n baseUrl: z\n .string()\n .url()\n .optional()\n .describe(\n \"Ollama server URL. Defaults to http://localhost:11434.\",\n ),\n});\n\nconst ProvidersSchema = z\n .object({\n openai: ProviderConfigSchema.optional(),\n anthropic: ProviderConfigSchema.optional(),\n ollama: OllamaProviderConfigSchema.optional(),\n gemini: ProviderConfigSchema.optional(),\n mistral: ProviderConfigSchema.optional(),\n cohere: ProviderConfigSchema.optional(),\n })\n .refine(\n (providers) =>\n Object.keys(providers).some(\n (k) => providers[k as keyof typeof providers] !== undefined,\n ),\n { message: \"At least one provider must be configured\" },\n );\n\n// ============================================================\n// Model Schema\n// ============================================================\n\nconst ModelParamsSchema = z.object({\n temperature: Temperature,\n maxTokens: z.number().int().min(1).max(128000).default(1024),\n topP: z.number().min(0).max(1).optional(),\n stopSequences: z.array(z.string()).optional(),\n seed: z\n .number()\n .int()\n .optional()\n .describe(\"Seed for reproducibility (provider-dependent support)\"),\n});\n\nconst ModelSchema = z.object({\n id: NonEmptyString.describe(\n \"Unique identifier for this model config, referenced in reports\",\n ),\n provider: z\n .enum([\"openai\", \"anthropic\", \"ollama\", \"gemini\", \"mistral\", \"cohere\"])\n .describe(\"Must match a key in the providers section\"),\n model: NonEmptyString.describe(\n \"Model name as the provider expects it (e.g., 'gpt-4o', 'claude-sonnet-4-5-20250929')\",\n ),\n params: ModelParamsSchema.default({}),\n});\n\n// ============================================================\n// Prompt Schema\n// ============================================================\n\nconst PromptSchema = z.object({\n system: z\n .string()\n .optional()\n .describe(\n \"System prompt template. Supports {{variable}} interpolation.\",\n ),\n user: NonEmptyString.describe(\n \"User prompt template. Supports {{variable}} interpolation.\",\n ),\n assistant: z\n .string()\n .optional()\n .describe(\"Prefill for assistant response (Anthropic-specific)\"),\n});\n\n// ============================================================\n// Assertion Schemas\n// ============================================================\n\nconst OutputExpectSchema = z\n .object({\n format: z.enum([\"text\", \"json\"]).default(\"text\"),\n schemaFile: z\n .string()\n .optional()\n .describe(\n \"Path to JSON Schema file (relative to config file). Required if format is 'json'.\",\n ),\n contains: z\n .array(z.string())\n .optional()\n .describe(\"Output must contain all of these substrings\"),\n notContains: z\n .array(z.string())\n .optional()\n .describe(\"Output must not contain any of these substrings\"),\n maxLength: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Maximum character length of the output\"),\n })\n .refine(\n (output) => {\n if (output.format === \"json\" && !output.schemaFile) {\n return false;\n }\n return true;\n },\n { message: \"schemaFile is required when format is 'json'\" },\n );\n\nconst PIIGuardrailSchema = z.object({\n enabled: z.boolean().default(true),\n denyPatterns: z\n .array(RegexPattern)\n .default([\n \"\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b\",\n \"\\\\b\\\\d{4}[\\\\s-]?\\\\d{4}[\\\\s-]?\\\\d{4}[\\\\s-]?\\\\d{4}\\\\b\",\n \"\\\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Z|a-z]{2,}\\\\b\",\n ])\n .describe(\n \"Regex patterns that must NOT appear in output. Defaults include SSN, credit card, email.\",\n ),\n customPatterns: z\n .array(\n z.object({\n name: NonEmptyString,\n pattern: RegexPattern,\n }),\n )\n .optional()\n .describe(\"Named custom PII patterns for reporting clarity\"),\n});\n\nconst KeywordGuardrailSchema = z.object({\n deny: z\n .array(z.string())\n .default([])\n .describe(\n \"Words/phrases that must NOT appear in output (case-insensitive)\",\n ),\n allow: z\n .array(z.string())\n .optional()\n .describe(\n \"If set, output MUST contain at least one of these words/phrases\",\n ),\n});\n\nconst JudgeCriterionSchema = z.object({\n criteria: NonEmptyString.describe(\n \"Natural language description of what to evaluate (e.g., 'Response is empathetic and professional')\",\n ),\n minScore: Score01.default(0.7).describe(\n \"Minimum score (0-1) for this criterion to pass\",\n ),\n model: z\n .string()\n .optional()\n .describe(\n \"Override judge model for this criterion. Defaults to first model in models list.\",\n ),\n rubric: z\n .string()\n .optional()\n .describe(\n \"Detailed rubric for the judge. If omitted, a default rubric is generated from criteria.\",\n ),\n});\n\nconst ToolCallExpectSchema = z.object({\n tool: NonEmptyString.describe(\"Expected tool/function name\"),\n shouldNotCall: z\n .boolean()\n .optional()\n .default(false)\n .describe(\"If true, assert this tool was NOT called\"),\n argsMatch: z\n .record(z.unknown())\n .optional()\n .describe(\n \"Key-value pairs that must be present in the tool call arguments (partial match)\",\n ),\n argsSchema: z\n .string()\n .optional()\n .describe(\n \"Path to JSON Schema file to validate the tool call arguments\",\n ),\n order: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\n \"Expected position in the sequence of tool calls (0-indexed)\",\n ),\n responseContains: z\n .string()\n .optional()\n .describe(\n \"Assert the simulated tool response contains this substring\",\n ),\n});\n\nconst BaselineDriftSchema = z.object({\n maxScore: Score01.default(0.15).describe(\n \"Maximum drift score (0-1). Higher = more drift allowed. Fail if exceeded.\",\n ),\n method: z\n .enum([\"judge\", \"embedding\", \"field-diff\"])\n .default(\"judge\")\n .describe(\n \"Drift detection method. 'judge' uses LLM comparison, 'embedding' uses cosine similarity, 'field-diff' compares JSON fields.\",\n ),\n fields: z\n .array(z.string())\n .optional()\n .describe(\n \"For field-diff method: JSON paths to compare (e.g., ['response.action', 'response.message'])\",\n ),\n});\n\nconst GuardrailsSchema = z.object({\n pii: PIIGuardrailSchema.optional(),\n keywords: KeywordGuardrailSchema.optional(),\n});\n\nconst ExpectSchema = z.object({\n output: OutputExpectSchema.optional(),\n guardrails: GuardrailsSchema.optional(),\n judge: z\n .array(JudgeCriterionSchema)\n .optional()\n .describe(\n \"LLM-as-judge evaluations. Each criterion is scored independently.\",\n ),\n toolCalls: z\n .array(ToolCallExpectSchema)\n .optional()\n .describe(\"Expected tool/function calls in the model response\"),\n baseline: z\n .object({\n drift: BaselineDriftSchema.optional(),\n })\n .optional(),\n});\n\n// ============================================================\n// Tool Simulation Schema (for agent testing)\n// ============================================================\n\nconst ToolSimulationSchema = z.object({\n name: NonEmptyString.describe(\"Tool/function name as the model sees it\"),\n description: z\n .string()\n .optional()\n .describe(\"Tool description for documentation\"),\n parameters: z\n .record(z.unknown())\n .optional()\n .describe(\"JSON Schema for the tool's parameters\"),\n responses: z\n .array(\n z.object({\n when: z\n .record(z.unknown())\n .describe(\n \"Condition: match tool call arguments (partial match)\",\n ),\n then: z.unknown().describe(\n \"Simulated response to return when condition matches\",\n ),\n }),\n )\n .optional()\n .describe(\"Simulated responses based on argument matching\"),\n defaultResponse: z\n .unknown()\n .optional()\n .describe(\"Response when no 'when' condition matches\"),\n});\n\n// ============================================================\n// Test Case Schema\n// ============================================================\n\nconst TestCaseSchema = z.object({\n name: NonEmptyString.describe(\n \"Unique test case name within the suite. Used in reports and JUnit output.\",\n ),\n prompt: NonEmptyString.optional().describe(\n \"Reference to a key in the prompts section. Exactly one of prompt or command must be set.\",\n ),\n command: NonEmptyString.optional().describe(\n \"Shell command to execute. Stdout is captured and assertions run against it. Exactly one of prompt or command must be set.\",\n ),\n vars: z\n .record(z.string())\n .default({})\n .describe(\"Variables to interpolate into the prompt template or command\"),\n models: z\n .array(z.string())\n .optional()\n .describe(\n \"Override: run this test only against these model IDs. Defaults to all models. Ignored for command tests.\",\n ),\n repeat: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\n \"Override: number of repeat runs for this specific test case\",\n ),\n tools: z\n .array(ToolSimulationSchema)\n .optional()\n .describe(\n \"Simulated tools available to the model for this test case\",\n ),\n expect: ExpectSchema.describe(\n \"Assertions to evaluate against the model output\",\n ),\n tags: z\n .array(z.string())\n .optional()\n .describe(\n \"Tags for filtering test cases in CLI (e.g., --tags regression)\",\n ),\n skip: z\n .boolean()\n .optional()\n .default(false)\n .describe(\"Skip this test case during execution\"),\n}).refine(\n (test) => {\n const hasPrompt = test.prompt !== undefined;\n const hasCommand = test.command !== undefined;\n return (hasPrompt || hasCommand) && !(hasPrompt && hasCommand);\n },\n { message: \"Exactly one of 'prompt' or 'command' must be set on each test case\" },\n);\n\n// ============================================================\n// Gates Schema\n// ============================================================\n\nconst GatesSchema = z.object({\n passRateMin: Score01.default(0.95).describe(\n \"Minimum overall pass rate (0-1). Computed after repeats and aggregation.\",\n ),\n schemaFailuresMax: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\n \"Maximum allowed schema validation failures across entire suite\",\n ),\n judgeAvgMin: Score01.optional().describe(\n \"Minimum average LLM-as-judge score across all criteria and test cases\",\n ),\n driftScoreMax: Score01.optional().describe(\n \"Maximum allowed drift score against active baseline\",\n ),\n piiFailuresMax: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Maximum allowed PII detection failures\"),\n keywordFailuresMax: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Maximum allowed keyword guardrail failures\"),\n costMaxUsd: z\n .number()\n .positive()\n .optional()\n .describe(\n \"Maximum total cost in USD for the entire run. Aborts if exceeded mid-run.\",\n ),\n latencyMaxMs: z\n .number()\n .positive()\n .optional()\n .describe(\n \"Maximum average latency in ms. Fails gate if exceeded.\",\n ),\n deterministicPassRate: Score01.optional().describe(\n \"Minimum pass rate for deterministic assertions only (tool_called, schema, pii, keywords, etc.)\",\n ),\n probabilisticPassRate: Score01.optional().describe(\n \"Minimum pass rate for probabilistic assertions only (judge, drift)\",\n ),\n});\n\n// ============================================================\n// Compliance Schema\n// ============================================================\n\nconst ComplianceSchema = z.object({\n enabled: z.boolean().default(false),\n framework: z.enum([\"eu-ai-act\", \"custom\"]).default(\"eu-ai-act\"),\n outputDir: z.string().default(\"./compliance-reports\"),\n metadata: z\n .object({\n systemName: z\n .string()\n .optional()\n .describe(\"Name of the AI system being tested\"),\n systemVersion: z\n .string()\n .optional()\n .describe(\"Version of the AI system\"),\n riskLevel: z.enum([\"high\", \"limited\", \"minimal\"]).optional(),\n operator: z\n .string()\n .optional()\n .describe(\"Organization operating the AI system\"),\n intendedPurpose: z\n .string()\n .optional()\n .describe(\n \"Documented intended purpose of the AI system\",\n ),\n dataGovernanceNotes: z.string().optional(),\n })\n .optional(),\n});\n\n// ============================================================\n// Upload Schema\n// ============================================================\n\nconst UploadSchema = z.object({\n enabled: z.boolean().default(false),\n includeArtifacts: z\n .boolean()\n .default(false)\n .describe(\n \"Upload raw prompt inputs and model outputs. Disabled by default for privacy.\",\n ),\n redactPatterns: z\n .array(RegexPattern)\n .optional()\n .describe(\n \"Patterns to redact from artifacts before upload (applied on top of PII guardrails)\",\n ),\n apiUrl: z\n .string()\n .url()\n .default(\"https://api.kindlm.com/v1\")\n .describe(\n \"Cloud API URL. Override for self-hosted deployments.\",\n ),\n});\n\n// ============================================================\n// Suite Schema\n// ============================================================\n\nconst SuiteSchema = z.object({\n name: NonEmptyString,\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\n// ============================================================\n// Top-Level Config Schema\n// ============================================================\n\nexport const KindLMConfigSchema = z.object({\n kindlm: z.literal(1).describe(\"Config schema version. Must be 1.\"),\n project: NonEmptyString.describe(\n \"Project identifier for cloud upload and report grouping\",\n ),\n suite: SuiteSchema,\n providers: ProvidersSchema,\n models: z\n .array(ModelSchema)\n .min(1, \"At least one model must be configured\"),\n prompts: z\n .record(PromptSchema)\n .refine((prompts) => Object.keys(prompts).length > 0, {\n message: \"At least one prompt must be defined\",\n }),\n tests: z\n .array(TestCaseSchema)\n .min(1, \"At least one test case must be defined\"),\n gates: GatesSchema.default({}),\n compliance: ComplianceSchema.optional(),\n trace: TraceConfigSchema.optional().describe(\n \"OpenTelemetry trace ingestion configuration for the 'kindlm trace' command\",\n ),\n upload: UploadSchema.default({}),\n defaults: z\n .object({\n repeat: z\n .number()\n .int()\n .min(1)\n .default(1)\n .describe(\"Default repeat count per test case\"),\n concurrency: z\n .number()\n .int()\n .min(1)\n .max(32)\n .default(4)\n .describe(\"Default concurrency for test execution\"),\n timeoutMs: z\n .number()\n .int()\n .min(1000)\n .default(60000)\n .describe(\"Default timeout per provider call in ms\"),\n judgeModel: z\n .string()\n .optional()\n .describe(\n \"Default model ID for LLM-as-judge assertions. Must reference a configured model.\",\n ),\n })\n .default({}),\n});\n\n// ============================================================\n// Inferred Types\n// ============================================================\n\nexport type KindLMConfig = z.infer<typeof KindLMConfigSchema>;\nexport type TestCase = z.infer<typeof TestCaseSchema>;\nexport type Expect = z.infer<typeof ExpectSchema>;\nexport type ModelConfig = z.infer<typeof ModelSchema>;\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type GatesConfig = z.infer<typeof GatesSchema>;\nexport type JudgeCriterion = z.infer<typeof JudgeCriterionSchema>;\nexport type ToolCallExpect = z.infer<typeof ToolCallExpectSchema>;\nexport type ToolSimulation = z.infer<typeof ToolSimulationSchema>;\nexport type ComplianceConfig = z.infer<typeof ComplianceSchema>;\n\n// ============================================================\n// Validation\n// ============================================================\n\nexport function validateConfig(\n raw: unknown,\n): Result<KindLMConfig, KindlmError> {\n const result = KindLMConfigSchema.safeParse(raw);\n if (!result.success) {\n return err({\n code: \"CONFIG_VALIDATION_ERROR\",\n message: \"Config validation failed\",\n details: {\n errors: result.error.issues.map(\n (issue) => `${issue.path.join(\".\")}: ${issue.message}`,\n ),\n },\n });\n }\n return ok(result.data);\n}\n","import { z } from \"zod\";\n\n// ============================================================\n// OTLP JSON Wire Types (subset we care about)\n// ============================================================\n\nexport interface OtlpAttribute {\n key: string;\n value: OtlpAttributeValue;\n}\n\nexport interface OtlpAttributeValue {\n stringValue?: string;\n intValue?: string;\n doubleValue?: number;\n boolValue?: boolean;\n arrayValue?: { values: OtlpAttributeValue[] };\n}\n\nexport interface OtlpSpan {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes?: OtlpAttribute[];\n status?: { code?: number; message?: string };\n}\n\nexport interface OtlpScopeSpans {\n scope?: { name?: string; version?: string };\n spans: OtlpSpan[];\n}\n\nexport interface OtlpResourceSpans {\n resource?: {\n attributes?: OtlpAttribute[];\n };\n scopeSpans: OtlpScopeSpans[];\n}\n\nexport interface OtlpTracesPayload {\n resourceSpans: OtlpResourceSpans[];\n}\n\n// ============================================================\n// Normalized Parsed Span\n// ============================================================\n\nexport interface ParsedSpan {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n kind: number;\n startTimeMs: number;\n endTimeMs: number;\n durationMs: number;\n attributes: Record<string, string | number | boolean>;\n resourceAttributes: Record<string, string | number | boolean>;\n statusCode?: number;\n statusMessage?: string;\n}\n\n// ============================================================\n// Span Mapping Result\n// ============================================================\n\nexport interface SpanMappingResult {\n outputText: string;\n toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[];\n latencyMs: number;\n inputTokens: number;\n outputTokens: number;\n model?: string;\n system?: string;\n}\n\n// ============================================================\n// Trace Config Schema (for kindlm.yaml)\n// ============================================================\n\nexport const SpanMappingSchema = z.object({\n outputTextAttr: z.string().default(\"gen_ai.completion.0.content\"),\n modelAttr: z.string().default(\"gen_ai.response.model\"),\n systemAttr: z.string().default(\"gen_ai.system\"),\n inputTokensAttr: z.string().default(\"gen_ai.usage.input_tokens\"),\n outputTokensAttr: z.string().default(\"gen_ai.usage.output_tokens\"),\n});\n\nexport const SpanFilterSchema = z.object({\n namePattern: z.string().optional().describe(\"Regex to filter span names\"),\n attributeMatch: z.record(z.string()).optional().describe(\"Attributes that must match\"),\n minDurationMs: z.number().min(0).optional(),\n});\n\nexport const TraceConfigSchema = z.object({\n port: z.number().int().min(1).max(65535).default(4318),\n timeoutMs: z.number().int().min(1000).default(30000),\n spanMapping: SpanMappingSchema.default({}),\n spanFilter: SpanFilterSchema.optional(),\n});\n\nexport type TraceConfig = z.infer<typeof TraceConfigSchema>;\nexport type SpanMapping = z.infer<typeof SpanMappingSchema>;\nexport type SpanFilter = z.infer<typeof SpanFilterSchema>;\n","import { parse as parseYaml } from \"yaml\";\nimport type { KindLMConfig } from \"./schema.js\";\nimport { validateConfig } from \"./schema.js\";\nimport type { Result } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\n\nexport interface FileReader {\n readFile(path: string): Result<string>;\n}\n\nexport interface ParseOptions {\n configDir: string;\n fileReader?: FileReader;\n}\n\nconst MAX_CONFIG_SIZE = 1_048_576; // 1MB\nconst MAX_TESTS = 1000;\nconst MAX_SUITES = 50;\n\nexport function parseConfig(\n yamlContent: string,\n options: ParseOptions,\n): Result<KindLMConfig> {\n // Step 0: Size guard\n if (yamlContent.length > MAX_CONFIG_SIZE) {\n return err({\n code: \"CONFIG_TOO_LARGE\",\n message: `Config exceeds maximum size of 1MB (got ${(yamlContent.length / 1_048_576).toFixed(1)}MB)`,\n });\n }\n\n // Step 1: YAML parse\n let raw: unknown;\n try {\n raw = parseYaml(yamlContent);\n } catch (cause) {\n return err({\n code: \"CONFIG_PARSE_ERROR\",\n message: `Failed to parse YAML: ${(cause as Error).message}`,\n cause: cause as Error,\n });\n }\n\n // Step 2: Zod structural validation\n const validated = validateConfig(raw);\n if (!validated.success) {\n return validated;\n }\n const config = validated.data;\n\n // Step 2.5: Cardinality limits\n if (config.tests.length > MAX_TESTS) {\n return err({\n code: \"CONFIG_VALIDATION_ERROR\",\n message: `Config exceeds maximum of ${MAX_TESTS} tests (got ${config.tests.length})`,\n });\n }\n\n // Count unique suites by model grouping — but here \"suites\" are implicit via test groupings\n // For simplicity, use the models array length as a proxy\n if (config.models.length > MAX_SUITES) {\n return err({\n code: \"CONFIG_VALIDATION_ERROR\",\n message: `Config exceeds maximum of ${MAX_SUITES} models (got ${config.models.length})`,\n });\n }\n\n // Step 3: Cross-reference validation (collect all errors)\n const errors: string[] = [];\n\n // Unique model IDs\n const modelIds = new Set<string>();\n for (const model of config.models) {\n if (modelIds.has(model.id)) {\n errors.push(`Duplicate model ID \"${model.id}\"`);\n }\n modelIds.add(model.id);\n }\n\n // Unique test names\n const testNames = new Set<string>();\n for (const test of config.tests) {\n if (testNames.has(test.name)) {\n errors.push(`Duplicate test name \"${test.name}\"`);\n }\n testNames.add(test.name);\n }\n\n // test.prompt must exist in config.prompts (only for prompt-based tests)\n for (const test of config.tests) {\n if (test.prompt && !(test.prompt in config.prompts)) {\n errors.push(\n `Test \"${test.name}\" references prompt \"${test.prompt}\" which is not defined`,\n );\n }\n }\n\n // test.models[] must reference valid model IDs\n for (const test of config.tests) {\n if (test.models) {\n for (const modelId of test.models) {\n if (!modelIds.has(modelId)) {\n errors.push(\n `Test \"${test.name}\" references model \"${modelId}\" which is not configured`,\n );\n }\n }\n }\n }\n\n // model.provider must exist in config.providers\n for (const model of config.models) {\n const providers = config.providers as Record<string, unknown>;\n if (!providers[model.provider]) {\n errors.push(\n `Model \"${model.id}\" references provider \"${model.provider}\" which is not configured`,\n );\n }\n }\n\n // defaults.judgeModel must reference valid model ID\n if (\n config.defaults.judgeModel &&\n !modelIds.has(config.defaults.judgeModel)\n ) {\n errors.push(\n `defaults.judgeModel \"${config.defaults.judgeModel}\" is not a configured model`,\n );\n }\n\n // schemaFile / argsSchema path verification via fileReader\n if (options.fileReader) {\n for (const test of config.tests) {\n if (test.expect.output?.schemaFile) {\n const pathResult = safePath(\n options.configDir,\n test.expect.output.schemaFile,\n );\n if (!pathResult.success) {\n errors.push(\n `Test \"${test.name}\": schemaFile \"${test.expect.output.schemaFile}\" — ${pathResult.error.message}`,\n );\n } else {\n const result = options.fileReader.readFile(pathResult.data);\n if (!result.success) {\n errors.push(\n `Test \"${test.name}\": schemaFile \"${test.expect.output.schemaFile}\" not found at ${pathResult.data}`,\n );\n }\n }\n }\n\n if (test.expect.toolCalls) {\n for (const tc of test.expect.toolCalls) {\n if (tc.argsSchema) {\n const pathResult = safePath(\n options.configDir,\n tc.argsSchema,\n );\n if (!pathResult.success) {\n errors.push(\n `Test \"${test.name}\": argsSchema \"${tc.argsSchema}\" for tool \"${tc.tool}\" — ${pathResult.error.message}`,\n );\n } else {\n const result = options.fileReader.readFile(pathResult.data);\n if (!result.success) {\n errors.push(\n `Test \"${test.name}\": argsSchema \"${tc.argsSchema}\" for tool \"${tc.tool}\" not found at ${pathResult.data}`,\n );\n }\n }\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n return err({\n code: \"CONFIG_VALIDATION_ERROR\",\n message: \"Config cross-reference validation failed\",\n details: { errors },\n });\n }\n\n return ok(config);\n}\n\nexport function safePath(base: string, relative: string): Result<string> {\n // Block absolute paths\n if (relative.startsWith(\"/\") || relative.startsWith(\"\\\\\")) {\n return err({\n code: \"PATH_TRAVERSAL\",\n message: \"Absolute paths are not allowed in config references\",\n });\n }\n\n // Block Windows absolute paths (e.g. C:\\)\n if (/^[a-zA-Z]:/.test(relative)) {\n return err({\n code: \"PATH_TRAVERSAL\",\n message: \"Absolute paths are not allowed in config references\",\n });\n }\n\n const normalizedBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const joined = `${normalizedBase}/${relative}`;\n\n // Normalize away .. and . segments\n const resolved = normalizePath(joined);\n\n // Verify resolved path stays under config directory\n const normalizedRoot = normalizePath(normalizedBase);\n if (!resolved.startsWith(normalizedRoot + \"/\") && resolved !== normalizedRoot) {\n return err({\n code: \"PATH_TRAVERSAL\",\n message: `Path \"${relative}\" escapes the config directory`,\n });\n }\n\n return ok(resolved);\n}\n\nfunction normalizePath(p: string): string {\n const parts = p.split(\"/\");\n const result: string[] = [];\n for (const part of parts) {\n if (part === \".\" || part === \"\") continue;\n if (part === \"..\") {\n result.pop();\n } else {\n result.push(part);\n }\n }\n // Preserve leading slash for absolute paths\n const prefix = p.startsWith(\"/\") ? \"/\" : \"\";\n return prefix + result.join(\"/\");\n}\n","import type { Result } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\n\nconst PLACEHOLDER_RE = /\\{\\{(\\w+)\\}\\}/g;\n\nexport function interpolate(\n template: string,\n vars: Record<string, string>,\n): Result<string> {\n const missing = findMissingVars(template, vars);\n if (missing.length > 0) {\n return err({\n code: \"CONFIG_VALIDATION_ERROR\",\n message: `Missing template variables: ${missing.join(\", \")}`,\n details: { missing },\n });\n }\n const result = template.replace(\n PLACEHOLDER_RE,\n (_match, key: string) => vars[key] as string,\n );\n return ok(result);\n}\n\nexport function findMissingVars(\n template: string,\n vars: Record<string, string>,\n): string[] {\n const missing = new Set<string>();\n for (const match of template.matchAll(PLACEHOLDER_RE)) {\n const key = match[1];\n if (key !== undefined && !(key in vars)) {\n missing.add(key);\n }\n }\n return [...missing];\n}\n","import type { AssertionResult } from \"../assertions/interface.js\";\n\nexport interface TestCaseRunResult {\n testCaseName: string;\n modelId: string;\n runIndex: number;\n outputText: string;\n assertions: AssertionResult[];\n latencyMs: number;\n tokenUsage: { inputTokens: number; outputTokens: number; totalTokens: number };\n costEstimateUsd: number | null;\n}\n\nexport interface AggregatedTestResult {\n testCaseName: string;\n modelId: string;\n runCount: number;\n passed: boolean;\n passRate: number;\n assertionScores: Record<string, { mean: number; min: number; max: number }>;\n failureCodes: string[];\n latencyAvgMs: number;\n totalCostUsd: number;\n totalTokens: number;\n runs: TestCaseRunResult[];\n}\n\nexport function aggregateRuns(runs: TestCaseRunResult[]): AggregatedTestResult {\n const first = runs[0];\n if (!first) {\n throw new Error(\"aggregateRuns requires at least one run\");\n }\n const { testCaseName, modelId } = first;\n\n const passedRuns = runs.filter((r) =>\n r.assertions.every((a) => a.passed),\n ).length;\n const passRate = passedRuns / runs.length;\n\n // Group assertion scores by type\n const scoresByType = new Map<string, number[]>();\n for (const run of runs) {\n for (const a of run.assertions) {\n let arr = scoresByType.get(a.assertionType);\n if (!arr) {\n arr = [];\n scoresByType.set(a.assertionType, arr);\n }\n arr.push(a.score);\n }\n }\n\n const assertionScores: Record<string, { mean: number; min: number; max: number }> = {};\n for (const [type, scores] of scoresByType) {\n const sum = scores.reduce((a, b) => a + b, 0);\n assertionScores[type] = {\n mean: sum / scores.length,\n min: Math.min(...scores),\n max: Math.max(...scores),\n };\n }\n\n // Collect unique failure codes\n const failureCodeSet = new Set<string>();\n for (const run of runs) {\n for (const a of run.assertions) {\n if (!a.passed && a.failureCode) {\n failureCodeSet.add(a.failureCode);\n }\n }\n }\n\n const latencyAvgMs =\n runs.reduce((sum, r) => sum + r.latencyMs, 0) / runs.length;\n\n const totalCostUsd = runs.reduce(\n (sum, r) => sum + (r.costEstimateUsd ?? 0),\n 0,\n );\n\n const totalTokens = runs.reduce(\n (sum, r) => sum + r.tokenUsage.totalTokens,\n 0,\n );\n\n return {\n testCaseName,\n modelId,\n runCount: runs.length,\n passed: passRate === 1,\n passRate,\n assertionScores,\n failureCodes: [...failureCodeSet],\n latencyAvgMs,\n totalCostUsd,\n totalTokens,\n runs,\n };\n}\n","import type { ProviderToolCall } from \"../types/provider.js\";\nimport type { Result } from \"../types/result.js\";\n\n// ============================================================\n// Command Executor Interface (injected — core has zero I/O)\n// ============================================================\n\nexport interface CommandExecutor {\n execute(command: string, options: CommandExecuteOptions): Promise<Result<RawCommandOutput>>;\n}\n\nexport interface CommandExecuteOptions {\n timeoutMs: number;\n env?: Record<string, string>;\n cwd?: string;\n}\n\nexport interface RawCommandOutput {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\n// ============================================================\n// Parsed Command Result\n// ============================================================\n\nexport interface CommandResult {\n outputText: string;\n toolCalls: ProviderToolCall[];\n outputJson?: unknown;\n exitCode: number;\n stderr: string;\n}\n\n// ============================================================\n// Protocol Event Types\n// ============================================================\n\ninterface KindlmToolCallEvent {\n kindlm: \"tool_call\";\n id?: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\ninterface KindlmOutputJsonEvent {\n kindlm: \"output_json\";\n data: unknown;\n}\n\ntype KindlmEvent = KindlmToolCallEvent | KindlmOutputJsonEvent;\n\n// ============================================================\n// Parser\n// ============================================================\n\nexport function parseCommandOutput(raw: RawCommandOutput): CommandResult {\n const lines = raw.stdout.split(\"\\n\");\n const textLines: string[] = [];\n const toolCalls: ProviderToolCall[] = [];\n let outputJson: unknown = undefined;\n let toolCallCounter = 0;\n\n for (const line of lines) {\n const trimmed = line.trimStart();\n if (!trimmed.startsWith(\"{\\\"kindlm\\\":\")) {\n textLines.push(line);\n continue;\n }\n\n const event = tryParseEvent(trimmed);\n if (!event) {\n textLines.push(line);\n continue;\n }\n\n if (event.kindlm === \"tool_call\") {\n toolCalls.push({\n id: event.id ?? `cmd_tc_${toolCallCounter++}`,\n name: event.name,\n arguments: event.arguments,\n });\n } else if (event.kindlm === \"output_json\") {\n outputJson = event.data;\n }\n }\n\n return {\n outputText: textLines.join(\"\\n\").trim(),\n toolCalls,\n outputJson,\n exitCode: raw.exitCode,\n stderr: raw.stderr,\n };\n}\n\nfunction tryParseEvent(line: string): KindlmEvent | null {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (typeof parsed.kindlm !== \"string\") return null;\n\n if (parsed.kindlm === \"tool_call\") {\n if (typeof parsed.name !== \"string\") return null;\n return {\n kindlm: \"tool_call\",\n id: typeof parsed.id === \"string\" ? parsed.id : undefined,\n name: parsed.name,\n arguments: (typeof parsed.arguments === \"object\" && parsed.arguments !== null\n ? parsed.arguments\n : {}) as Record<string, unknown>,\n };\n }\n\n if (parsed.kindlm === \"output_json\") {\n return {\n kindlm: \"output_json\",\n data: parsed.data,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","import type { KindLMConfig, TestCase, ModelConfig } from \"../types/config.js\";\nimport type { Result, KindlmError } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\nimport type { ProviderAdapter, ProviderRequest, ProviderMessage, ProviderToolDefinition } from \"../providers/interface.js\";\nimport type { FileReader } from \"../config/parser.js\";\nimport type { AssertionContext, AssertionResult } from \"../assertions/interface.js\";\nimport { createAssertionsFromExpect } from \"../assertions/registry.js\";\nimport type { AssertionOverrides } from \"../assertions/registry.js\";\nimport { interpolate } from \"../config/interpolation.js\";\nimport { runConversation } from \"../providers/conversation.js\";\nimport type { TestCaseRunResult, AggregatedTestResult } from \"./aggregator.js\";\nimport { aggregateRuns } from \"./aggregator.js\";\nimport type { BaselineData } from \"../baseline/store.js\";\nimport type { CommandExecutor } from \"./command.js\";\nimport { parseCommandOutput } from \"./command.js\";\n\n// ============================================================\n// Public Types\n// ============================================================\n\nexport interface RunnerDeps {\n adapters: Map<string, ProviderAdapter>;\n configDir: string;\n fileReader: FileReader;\n onProgress?: (event: ProgressEvent) => void;\n baselineData?: BaselineData;\n commandExecutor?: CommandExecutor;\n}\n\nexport type ProgressEvent =\n | { type: \"test_start\"; test: string; model: string; run: number }\n | { type: \"test_complete\"; test: string; model: string; run: number; passed: boolean };\n\nexport interface RunResult {\n suites: SuiteRunResult[];\n totalTests: number;\n passed: number;\n failed: number;\n errored: number;\n skipped: number;\n durationMs: number;\n}\n\nexport interface SuiteRunResult {\n name: string;\n status: \"passed\" | \"failed\" | \"errored\" | \"skipped\";\n tests: TestRunResult[];\n error?: string;\n}\n\nexport interface TestRunResult {\n name: string;\n modelId: string;\n status: \"passed\" | \"failed\" | \"errored\" | \"skipped\";\n assertions: AssertionResult[];\n error?: KindlmError;\n latencyMs: number;\n costUsd: number;\n}\n\nexport interface RunnerResult {\n runResult: RunResult;\n aggregated: AggregatedTestResult[];\n}\n\n// ============================================================\n// Runner Implementation\n// ============================================================\n\ninterface ExecutionUnit {\n test: TestCase;\n modelConfig: ModelConfig | null;\n runIndex: number;\n}\n\nexport function createRunner(\n config: KindLMConfig,\n deps: RunnerDeps,\n): { run(): Promise<Result<RunnerResult>> } {\n return {\n async run(): Promise<Result<RunnerResult>> {\n const startTime = Date.now();\n\n // 1. Pre-load schema files\n const schemaCache = new Map<string, Record<string, unknown>>();\n for (const test of config.tests) {\n if (test.expect.output?.schemaFile) {\n const fullPath = joinPath(deps.configDir, test.expect.output.schemaFile);\n const readResult = deps.fileReader.readFile(fullPath);\n if (!readResult.success) {\n return err({\n code: \"SCHEMA_FILE_ERROR\",\n message: `Failed to read schema file \"${test.expect.output.schemaFile}\": ${readResult.error.message}`,\n });\n }\n try {\n schemaCache.set(test.name, JSON.parse(readResult.data) as Record<string, unknown>);\n } catch (e) {\n return err({\n code: \"SCHEMA_FILE_ERROR\",\n message: `Failed to parse schema file \"${test.expect.output.schemaFile}\" as JSON: ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n }\n\n // 2. Build execution plan\n const units: ExecutionUnit[] = [];\n for (const test of config.tests) {\n if (test.skip) continue;\n\n const repeat = test.repeat ?? config.defaults.repeat;\n\n if (test.command) {\n // Command tests run once per repeat, no model multiplication\n for (let runIndex = 0; runIndex < repeat; runIndex++) {\n units.push({ test, modelConfig: null, runIndex });\n }\n } else {\n const modelIds = test.models ?? config.models.map((m) => m.id);\n for (const modelId of modelIds) {\n const modelConfig = config.models.find((m) => m.id === modelId);\n if (!modelConfig) continue;\n\n for (let runIndex = 0; runIndex < repeat; runIndex++) {\n units.push({ test, modelConfig, runIndex });\n }\n }\n }\n }\n\n // 3. Execute with concurrency pool\n const caseResults = await runWithConcurrency(\n units.map((unit) => () => executeUnit(config, deps, unit, schemaCache)),\n config.defaults.concurrency,\n );\n\n // 4. Group by (testName, modelId) and aggregate\n const groupKey = (r: TestCaseRunResult) => `${r.testCaseName}::${r.modelId}`;\n const groups = new Map<string, TestCaseRunResult[]>();\n for (const r of caseResults) {\n const key = groupKey(r);\n let arr = groups.get(key);\n if (!arr) {\n arr = [];\n groups.set(key, arr);\n }\n arr.push(r);\n }\n\n const aggregated: AggregatedTestResult[] = [];\n for (const runs of groups.values()) {\n aggregated.push(aggregateRuns(runs));\n }\n\n // 5. Build TestRunResults from aggregated\n const testRunResults: TestRunResult[] = aggregated.map((agg) => ({\n name: agg.testCaseName,\n modelId: agg.modelId,\n status: agg.passed ? \"passed\" as const : \"failed\" as const,\n assertions: agg.runs[0]?.assertions ?? [],\n latencyMs: agg.latencyAvgMs,\n costUsd: agg.totalCostUsd,\n }));\n\n // 6. Build skipped test results\n const skippedTests: TestRunResult[] = config.tests\n .filter((t) => t.skip)\n .map((t) => ({\n name: t.name,\n modelId: \"\",\n status: \"skipped\" as const,\n assertions: [],\n latencyMs: 0,\n costUsd: 0,\n }));\n\n const allTests = [...testRunResults, ...skippedTests];\n\n // 7. Build SuiteRunResult\n const passed = allTests.filter((t) => t.status === \"passed\").length;\n const failed = allTests.filter((t) => t.status === \"failed\").length;\n const errored = allTests.filter((t) => t.status === \"errored\").length;\n const skipped = allTests.filter((t) => t.status === \"skipped\").length;\n\n const suiteStatus: SuiteRunResult[\"status\"] =\n errored > 0 ? \"errored\" : failed > 0 ? \"failed\" : \"passed\";\n\n const suiteResult: SuiteRunResult = {\n name: config.suite.name,\n status: suiteStatus,\n tests: allTests,\n };\n\n const runResult: RunResult = {\n suites: [suiteResult],\n totalTests: allTests.length,\n passed,\n failed,\n errored,\n skipped,\n durationMs: Date.now() - startTime,\n };\n\n return ok({ runResult, aggregated });\n },\n };\n}\n\n// ============================================================\n// Execute a single test × model × run\n// ============================================================\n\nasync function executeUnit(\n config: KindLMConfig,\n deps: RunnerDeps,\n unit: ExecutionUnit,\n schemaCache: Map<string, Record<string, unknown>>,\n): Promise<TestCaseRunResult> {\n const { test, modelConfig, runIndex } = unit;\n\n if (test.command) {\n return executeCommandUnit(config, deps, test, runIndex, schemaCache);\n }\n\n if (!modelConfig) {\n return errorResult(test.name, \"unknown\", runIndex, \"No model config for prompt-based test\");\n }\n\n deps.onProgress?.({\n type: \"test_start\",\n test: test.name,\n model: modelConfig.id,\n run: runIndex,\n });\n\n try {\n // Look up adapter\n const adapter = deps.adapters.get(modelConfig.provider);\n if (!adapter) {\n return errorResult(test.name, modelConfig.id, runIndex, `Provider adapter \"${modelConfig.provider}\" not found`);\n }\n\n // Resolve prompt\n const promptDef = test.prompt ? config.prompts[test.prompt] : undefined;\n if (!promptDef) {\n return errorResult(test.name, modelConfig.id, runIndex, `Prompt \"${test.prompt}\" not defined`);\n }\n\n const userResult = interpolate(promptDef.user, test.vars);\n if (!userResult.success) {\n return errorResult(test.name, modelConfig.id, runIndex, userResult.error.message);\n }\n\n const messages: ProviderMessage[] = [];\n if (promptDef.system) {\n const sysResult = interpolate(promptDef.system, test.vars);\n if (!sysResult.success) {\n return errorResult(test.name, modelConfig.id, runIndex, sysResult.error.message);\n }\n messages.push({ role: \"system\", content: sysResult.data });\n }\n messages.push({ role: \"user\", content: userResult.data });\n\n // Build tool definitions from simulations\n const tools: ProviderToolDefinition[] = (test.tools ?? []).map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }));\n\n const request: ProviderRequest = {\n model: modelConfig.model,\n messages,\n params: {\n temperature: modelConfig.params.temperature,\n maxTokens: modelConfig.params.maxTokens,\n topP: modelConfig.params.topP,\n stopSequences: modelConfig.params.stopSequences,\n seed: modelConfig.params.seed,\n },\n tools: tools.length > 0 ? tools : undefined,\n };\n\n // Run conversation\n const conversation = await runConversation(adapter, request, test.tools ?? []);\n\n // Compute cost\n const costEstimate = adapter.estimateCost(modelConfig.model, conversation.totalUsage);\n\n // Build assertions with schema content override\n const overrides: AssertionOverrides = {};\n if (test.expect.output?.schemaFile && schemaCache.has(test.name)) {\n overrides.schemaContent = schemaCache.get(test.name);\n }\n const assertions = createAssertionsFromExpect(test.expect, overrides);\n\n // Resolve judge adapter if needed\n const judgeModelId = config.defaults.judgeModel ?? config.models[0]?.id;\n const judgeModelConfig = config.models.find((m) => m.id === judgeModelId);\n const judgeAdapter = judgeModelConfig ? deps.adapters.get(judgeModelConfig.provider) : undefined;\n\n // Build assertion context\n const context: AssertionContext = {\n outputText: conversation.finalText,\n toolCalls: conversation.allToolCalls,\n configDir: deps.configDir,\n latencyMs: conversation.totalLatencyMs,\n costUsd: costEstimate ?? undefined,\n judgeAdapter,\n judgeModel: judgeModelConfig?.model,\n };\n\n // Inject baseline text for drift assertions\n if (deps.baselineData) {\n const baselineKey = `${test.name}::${modelConfig.id}`;\n const baselineEntry = deps.baselineData.results[baselineKey];\n if (baselineEntry) {\n context.baselineText = baselineEntry.outputText;\n }\n }\n\n // Evaluate all assertions\n const allResults = [];\n for (const assertion of assertions) {\n const results = await assertion.evaluate(context);\n allResults.push(...results);\n }\n\n const allPassed = allResults.every((r) => r.passed);\n\n deps.onProgress?.({\n type: \"test_complete\",\n test: test.name,\n model: modelConfig.id,\n run: runIndex,\n passed: allPassed,\n });\n\n return {\n testCaseName: test.name,\n modelId: modelConfig.id,\n runIndex,\n outputText: conversation.finalText,\n assertions: allResults,\n latencyMs: conversation.totalLatencyMs,\n tokenUsage: conversation.totalUsage,\n costEstimateUsd: costEstimate,\n };\n } catch (e) {\n deps.onProgress?.({\n type: \"test_complete\",\n test: test.name,\n model: modelConfig.id,\n run: runIndex,\n passed: false,\n });\n\n return errorResult(\n test.name,\n modelConfig.id,\n runIndex,\n e instanceof Error ? e.message : String(e),\n );\n }\n}\n\nasync function executeCommandUnit(\n config: KindLMConfig,\n deps: RunnerDeps,\n test: TestCase,\n runIndex: number,\n schemaCache: Map<string, Record<string, unknown>>,\n): Promise<TestCaseRunResult> {\n const modelId = \"command\";\n\n deps.onProgress?.({\n type: \"test_start\",\n test: test.name,\n model: modelId,\n run: runIndex,\n });\n\n try {\n if (!deps.commandExecutor) {\n return errorResult(test.name, modelId, runIndex, \"Command executor not available\");\n }\n\n if (!test.command) {\n return errorResult(test.name, modelId, runIndex, \"No command specified\");\n }\n\n // Interpolate vars into command string\n const cmdResult = interpolate(test.command, test.vars);\n if (!cmdResult.success) {\n return errorResult(test.name, modelId, runIndex, cmdResult.error.message);\n }\n\n const startTime = Date.now();\n const execResult = await deps.commandExecutor.execute(cmdResult.data, {\n timeoutMs: config.defaults.timeoutMs,\n cwd: deps.configDir,\n });\n\n if (!execResult.success) {\n return errorResult(test.name, modelId, runIndex, execResult.error.message);\n }\n\n const latencyMs = Date.now() - startTime;\n const parsed = parseCommandOutput(execResult.data);\n\n // Build assertions\n const overrides: AssertionOverrides = {};\n if (test.expect.output?.schemaFile && schemaCache.has(test.name)) {\n overrides.schemaContent = schemaCache.get(test.name);\n }\n const assertions = createAssertionsFromExpect(test.expect, overrides);\n\n // Resolve judge adapter if needed\n const judgeModelId = config.defaults.judgeModel ?? config.models[0]?.id;\n const judgeModelConfig = config.models.find((m) => m.id === judgeModelId);\n const judgeAdapter = judgeModelConfig ? deps.adapters.get(judgeModelConfig.provider) : undefined;\n\n // Build assertion context\n const context: AssertionContext = {\n outputText: parsed.outputText,\n outputJson: parsed.outputJson,\n toolCalls: parsed.toolCalls,\n configDir: deps.configDir,\n latencyMs,\n judgeAdapter,\n judgeModel: judgeModelConfig?.model,\n };\n\n // Inject baseline text for drift assertions\n if (deps.baselineData) {\n const baselineKey = `${test.name}::${modelId}`;\n const baselineEntry = deps.baselineData.results[baselineKey];\n if (baselineEntry) {\n context.baselineText = baselineEntry.outputText;\n }\n }\n\n // Evaluate all assertions\n const allResults: AssertionResult[] = [];\n for (const assertion of assertions) {\n const results = await assertion.evaluate(context);\n allResults.push(...results);\n }\n\n const allPassed = allResults.every((r) => r.passed);\n\n deps.onProgress?.({\n type: \"test_complete\",\n test: test.name,\n model: modelId,\n run: runIndex,\n passed: allPassed,\n });\n\n return {\n testCaseName: test.name,\n modelId,\n runIndex,\n outputText: parsed.outputText,\n assertions: allResults,\n latencyMs,\n tokenUsage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n costEstimateUsd: null,\n };\n } catch (e) {\n deps.onProgress?.({\n type: \"test_complete\",\n test: test.name,\n model: modelId,\n run: runIndex,\n passed: false,\n });\n\n return errorResult(\n test.name,\n modelId,\n runIndex,\n e instanceof Error ? e.message : String(e),\n );\n }\n}\n\nfunction errorResult(\n testCaseName: string,\n modelId: string,\n runIndex: number,\n message: string,\n): TestCaseRunResult {\n return {\n testCaseName,\n modelId,\n runIndex,\n outputText: \"\",\n assertions: [\n {\n assertionType: \"internal\",\n label: \"Execution error\",\n passed: false,\n score: 0,\n failureCode: \"INTERNAL_ERROR\",\n failureMessage: message,\n },\n ],\n latencyMs: 0,\n tokenUsage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n costEstimateUsd: null,\n };\n}\n\n// ============================================================\n// Concurrency Helper\n// ============================================================\n\nasync function runWithConcurrency<T>(\n tasks: (() => Promise<T>)[],\n limit: number,\n): Promise<T[]> {\n const results: T[] = new Array(tasks.length);\n let nextIndex = 0;\n\n async function worker(): Promise<void> {\n while (nextIndex < tasks.length) {\n const index = nextIndex++;\n const task = tasks[index];\n if (task) results[index] = await task();\n }\n }\n\n const workers = Array.from({ length: Math.min(limit, tasks.length) }, () => worker());\n await Promise.all(workers);\n return results;\n}\n\n// ============================================================\n// Path Helper\n// ============================================================\n\nfunction joinPath(base: string, relative: string): string {\n if (relative.startsWith(\"/\")) return relative;\n const normalizedBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n return `${normalizedBase}/${relative}`;\n}\n","import type { GatesConfig } from \"../types/config.js\";\nimport type { AggregatedTestResult } from \"./aggregator.js\";\nimport { classifyAssertion } from \"../assertions/classification.js\";\n\nexport interface GateResult {\n gateName: string;\n passed: boolean;\n actual: number;\n threshold: number;\n message: string;\n}\n\nexport interface GateEvaluation {\n passed: boolean;\n gates: GateResult[];\n}\n\nexport function evaluateGates(\n config: GatesConfig,\n results: AggregatedTestResult[],\n): GateEvaluation {\n const gates: GateResult[] = [];\n\n // 1. passRateMin — overall pass rate across all results\n const totalRuns = results.reduce((s, r) => s + r.runCount, 0);\n const totalPassed = results.reduce(\n (s, r) => s + Math.round(r.passRate * r.runCount),\n 0,\n );\n const overallPassRate = totalRuns > 0 ? totalPassed / totalRuns : 0;\n gates.push({\n gateName: \"passRateMin\",\n passed: overallPassRate >= config.passRateMin,\n actual: overallPassRate,\n threshold: config.passRateMin,\n message:\n overallPassRate >= config.passRateMin\n ? `Pass rate ${fmt(overallPassRate)} meets minimum ${fmt(config.passRateMin)}`\n : `Pass rate ${fmt(overallPassRate)} below minimum ${fmt(config.passRateMin)}`,\n });\n\n // 2. schemaFailuresMax\n const schemaFailures = countFailures(results, [\n \"SCHEMA_INVALID\",\n \"SCHEMA_PARSE_ERROR\",\n ]);\n gates.push({\n gateName: \"schemaFailuresMax\",\n passed: schemaFailures <= config.schemaFailuresMax,\n actual: schemaFailures,\n threshold: config.schemaFailuresMax,\n message:\n schemaFailures <= config.schemaFailuresMax\n ? `Schema failures ${schemaFailures} within limit ${config.schemaFailuresMax}`\n : `Schema failures ${schemaFailures} exceed limit ${config.schemaFailuresMax}`,\n });\n\n // 3. judgeAvgMin (optional)\n if (config.judgeAvgMin !== undefined) {\n const judgeScores = collectScores(results, \"judge\");\n const judgeAvg =\n judgeScores.length > 0\n ? judgeScores.reduce((a, b) => a + b, 0) / judgeScores.length\n : 1;\n gates.push({\n gateName: \"judgeAvgMin\",\n passed: judgeAvg >= config.judgeAvgMin,\n actual: judgeAvg,\n threshold: config.judgeAvgMin,\n message:\n judgeAvg >= config.judgeAvgMin\n ? `Judge average ${fmt(judgeAvg)} meets minimum ${fmt(config.judgeAvgMin)}`\n : `Judge average ${fmt(judgeAvg)} below minimum ${fmt(config.judgeAvgMin)}`,\n });\n }\n\n // 4. driftScoreMax (optional)\n if (config.driftScoreMax !== undefined) {\n const driftScores = collectScores(results, \"drift\");\n const maxDrift =\n driftScores.length > 0 ? Math.max(...driftScores) : 0;\n gates.push({\n gateName: \"driftScoreMax\",\n passed: maxDrift <= config.driftScoreMax,\n actual: maxDrift,\n threshold: config.driftScoreMax,\n message:\n maxDrift <= config.driftScoreMax\n ? `Drift score ${fmt(maxDrift)} within limit ${fmt(config.driftScoreMax)}`\n : `Drift score ${fmt(maxDrift)} exceeds limit ${fmt(config.driftScoreMax)}`,\n });\n }\n\n // 5. piiFailuresMax\n const piiFailures = countFailures(results, [\"PII_DETECTED\"]);\n gates.push({\n gateName: \"piiFailuresMax\",\n passed: piiFailures <= config.piiFailuresMax,\n actual: piiFailures,\n threshold: config.piiFailuresMax,\n message:\n piiFailures <= config.piiFailuresMax\n ? `PII failures ${piiFailures} within limit ${config.piiFailuresMax}`\n : `PII failures ${piiFailures} exceed limit ${config.piiFailuresMax}`,\n });\n\n // 6. keywordFailuresMax\n const keywordFailures = countFailures(results, [\n \"KEYWORD_DENIED\",\n \"KEYWORD_MISSING\",\n ]);\n gates.push({\n gateName: \"keywordFailuresMax\",\n passed: keywordFailures <= config.keywordFailuresMax,\n actual: keywordFailures,\n threshold: config.keywordFailuresMax,\n message:\n keywordFailures <= config.keywordFailuresMax\n ? `Keyword failures ${keywordFailures} within limit ${config.keywordFailuresMax}`\n : `Keyword failures ${keywordFailures} exceed limit ${config.keywordFailuresMax}`,\n });\n\n // 7. costMaxUsd (optional)\n if (config.costMaxUsd !== undefined) {\n const totalCost = results.reduce((s, r) => s + r.totalCostUsd, 0);\n gates.push({\n gateName: \"costMaxUsd\",\n passed: totalCost <= config.costMaxUsd,\n actual: totalCost,\n threshold: config.costMaxUsd,\n message:\n totalCost <= config.costMaxUsd\n ? `Total cost $${totalCost.toFixed(4)} within limit $${config.costMaxUsd.toFixed(4)}`\n : `Total cost $${totalCost.toFixed(4)} exceeds limit $${config.costMaxUsd.toFixed(4)}`,\n });\n }\n\n // 8. latencyMaxMs (optional)\n if (config.latencyMaxMs !== undefined) {\n const avgLatency =\n results.length > 0\n ? results.reduce((s, r) => s + r.latencyAvgMs, 0) / results.length\n : 0;\n gates.push({\n gateName: \"latencyMaxMs\",\n passed: avgLatency <= config.latencyMaxMs,\n actual: avgLatency,\n threshold: config.latencyMaxMs,\n message:\n avgLatency <= config.latencyMaxMs\n ? `Average latency ${Math.round(avgLatency)}ms within limit ${config.latencyMaxMs}ms`\n : `Average latency ${Math.round(avgLatency)}ms exceeds limit ${config.latencyMaxMs}ms`,\n });\n }\n\n // 9. deterministicPassRate (optional)\n if (config.deterministicPassRate !== undefined) {\n const rate = computeCategoryPassRate(results, \"deterministic\");\n gates.push({\n gateName: \"deterministicPassRate\",\n passed: rate >= config.deterministicPassRate,\n actual: rate,\n threshold: config.deterministicPassRate,\n message:\n rate >= config.deterministicPassRate\n ? `Deterministic pass rate ${fmt(rate)} meets minimum ${fmt(config.deterministicPassRate)}`\n : `Deterministic pass rate ${fmt(rate)} below minimum ${fmt(config.deterministicPassRate)}`,\n });\n }\n\n // 10. probabilisticPassRate (optional)\n if (config.probabilisticPassRate !== undefined) {\n const rate = computeCategoryPassRate(results, \"probabilistic\");\n gates.push({\n gateName: \"probabilisticPassRate\",\n passed: rate >= config.probabilisticPassRate,\n actual: rate,\n threshold: config.probabilisticPassRate,\n message:\n rate >= config.probabilisticPassRate\n ? `Probabilistic pass rate ${fmt(rate)} meets minimum ${fmt(config.probabilisticPassRate)}`\n : `Probabilistic pass rate ${fmt(rate)} below minimum ${fmt(config.probabilisticPassRate)}`,\n });\n }\n\n return {\n passed: gates.every((g) => g.passed),\n gates,\n };\n}\n\nfunction computeCategoryPassRate(\n results: AggregatedTestResult[],\n category: \"deterministic\" | \"probabilistic\",\n): number {\n let total = 0;\n let passed = 0;\n for (const r of results) {\n for (const run of r.runs) {\n for (const a of run.assertions) {\n if (classifyAssertion(a.assertionType) === category) {\n total++;\n if (a.passed) passed++;\n }\n }\n }\n }\n return total > 0 ? passed / total : 1;\n}\n\nfunction countFailures(\n results: AggregatedTestResult[],\n codes: string[],\n): number {\n let count = 0;\n for (const r of results) {\n for (const code of codes) {\n if (r.failureCodes.includes(code)) {\n count++;\n }\n }\n }\n return count;\n}\n\nfunction collectScores(\n results: AggregatedTestResult[],\n assertionType: string,\n): number[] {\n const scores: number[] = [];\n for (const r of results) {\n const entry = r.assertionScores[assertionType];\n if (entry) {\n scores.push(entry.mean);\n }\n }\n return scores;\n}\n\nfunction fmt(n: number): string {\n return (n * 100).toFixed(1) + \"%\";\n}\n","import type { RunResult } from \"../engine/runner.js\";\nimport type { GateEvaluation } from \"../engine/gate.js\";\n\nexport interface ReporterOutput {\n content: string;\n format: \"text\" | \"json\" | \"xml\" | \"markdown\";\n}\n\nexport interface Reporter {\n readonly name: string;\n generate(runResult: RunResult, gateEvaluation: GateEvaluation): ReporterOutput;\n}\n\nexport interface Colorize {\n bold: (text: string) => string;\n red: (text: string) => string;\n green: (text: string) => string;\n yellow: (text: string) => string;\n cyan: (text: string) => string;\n dim: (text: string) => string;\n greenBold: (text: string) => string;\n redBold: (text: string) => string;\n}\n\nconst identity = (t: string): string => t;\n\nexport const noColor: Colorize = {\n bold: identity,\n red: identity,\n green: identity,\n yellow: identity,\n cyan: identity,\n dim: identity,\n greenBold: identity,\n redBold: identity,\n};\n","import type { Colorize, Reporter, ReporterOutput } from \"./interface.js\";\nimport { noColor } from \"./interface.js\";\nimport type { RunResult, SuiteRunResult, TestRunResult } from \"../engine/runner.js\";\nimport type { GateEvaluation } from \"../engine/gate.js\";\nimport type { AssertionResult } from \"../assertions/interface.js\";\n\nexport function createPrettyReporter(colorize: Colorize = noColor): Reporter {\n return {\n name: \"pretty\",\n generate(runResult: RunResult, gateEvaluation: GateEvaluation): ReporterOutput {\n const lines: string[] = [];\n const c = colorize;\n\n lines.push(\"\");\n lines.push(c.bold(\" KindLM Test Results\"));\n lines.push(\"\");\n\n let totalCost = 0;\n\n for (const suite of runResult.suites) {\n lines.push(formatSuite(suite, c));\n\n for (const test of suite.tests) {\n lines.push(formatTest(test, c));\n\n // Show model, latency, cost on the next line\n const meta = formatTestMeta(test, c);\n if (meta) lines.push(meta);\n\n // Show all assertions\n for (const a of test.assertions) {\n lines.push(formatAssertion(a, c));\n }\n\n totalCost += test.costUsd;\n }\n lines.push(\"\");\n }\n\n // Summary\n lines.push(c.bold(\" Summary\"));\n const passStr = c.green(`${runResult.passed} passed`);\n const failStr =\n runResult.failed > 0\n ? c.red(`${runResult.failed} failed`)\n : `${runResult.failed} failed`;\n const errorStr =\n runResult.errored > 0\n ? c.yellow(`${runResult.errored} errored`)\n : `${runResult.errored} errored`;\n lines.push(` ${passStr}, ${failStr}, ${errorStr} (${runResult.totalTests} total)`);\n lines.push(` Duration: ${formatDuration(runResult.durationMs)}`);\n if (totalCost > 0) {\n lines.push(` Cost: ${formatCost(totalCost)}`);\n }\n lines.push(\"\");\n\n // Gates\n if (gateEvaluation.gates.length > 0) {\n lines.push(c.bold(\" Quality Gates\"));\n for (const gate of gateEvaluation.gates) {\n const icon = gate.passed ? c.green(\"✓\") : c.red(\"✗\");\n lines.push(` ${icon} ${gate.message}`);\n }\n lines.push(\"\");\n }\n\n // Verdict\n const allPassed = runResult.failed === 0 && runResult.errored === 0 && gateEvaluation.passed;\n if (allPassed) {\n lines.push(c.greenBold(\" ✓ All tests passed\"));\n } else {\n lines.push(c.redBold(\" ✗ Some tests failed\"));\n }\n lines.push(\"\");\n\n return { content: lines.join(\"\\n\"), format: \"text\" };\n },\n };\n}\n\nfunction formatSuite(suite: SuiteRunResult, c: Colorize): string {\n const icon =\n suite.status === \"passed\"\n ? c.green(\"✓\")\n : suite.status === \"skipped\"\n ? c.yellow(\"○\")\n : c.red(\"✗\");\n return ` ${icon} ${c.bold(suite.name)}`;\n}\n\nfunction formatTest(test: TestRunResult, c: Colorize): string {\n const icon =\n test.status === \"passed\"\n ? c.green(\"✓\")\n : test.status === \"skipped\"\n ? c.yellow(\"○\")\n : c.red(\"✗\");\n return ` ${icon} ${test.name}`;\n}\n\nfunction formatTestMeta(test: TestRunResult, c: Colorize): string | null {\n if (test.status === \"skipped\") return null;\n\n const parts: string[] = [];\n if (test.modelId) parts.push(test.modelId);\n if (test.latencyMs > 0) parts.push(formatDuration(test.latencyMs));\n if (test.costUsd >= 0.00005) parts.push(formatCost(test.costUsd));\n\n if (parts.length === 0) return null;\n return ` ${c.dim(parts.join(\" · \"))}`;\n}\n\nfunction formatAssertion(a: AssertionResult, c: Colorize): string {\n if (a.passed) {\n const scoreStr = formatScore(a);\n const label = scoreStr ? `${a.label} ${c.cyan(scoreStr)}` : a.label;\n return ` ${c.green(\"✓\")} ${c.dim(label)}`;\n }\n const scoreStr = formatScore(a);\n const detail = a.failureMessage ?? \"failed\";\n const label = scoreStr ? `${a.label} ${c.cyan(scoreStr)}` : a.label;\n return ` ${c.red(\"✗\")} ${label}: ${detail}`;\n}\n\nfunction formatScore(a: AssertionResult): string {\n // Show score for judge and drift assertions where score is meaningful\n if (a.assertionType === \"judge\" || a.assertionType === \"drift\") {\n const threshold = extractThreshold(a);\n if (threshold !== null) {\n const symbol = a.passed ? \"≥\" : \"<\";\n return `(${a.score.toFixed(2)} ${symbol} ${threshold.toFixed(2)})`;\n }\n return `(${a.score.toFixed(2)})`;\n }\n return \"\";\n}\n\nfunction extractThreshold(a: AssertionResult): number | null {\n if (a.metadata && typeof a.metadata === \"object\" && \"threshold\" in a.metadata) {\n const t = a.metadata.threshold;\n if (typeof t === \"number\") return t;\n }\n // Try to extract from label like \"Judge: criteria\" or failure message\n if (a.failureMessage) {\n const match = a.failureMessage.match(/threshold (\\d+\\.?\\d*)/i);\n if (match?.[1]) return parseFloat(match[1]);\n const belowMatch = a.failureMessage.match(/below (\\d+\\.?\\d*)/i);\n if (belowMatch?.[1]) return parseFloat(belowMatch[1]);\n }\n return null;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\nfunction formatCost(usd: number): string {\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(2)}`;\n}\n","import type { Reporter, ReporterOutput } from \"./interface.js\";\nimport type { RunResult } from \"../engine/runner.js\";\nimport type { GateEvaluation } from \"../engine/gate.js\";\n\nexport function createJsonReporter(): Reporter {\n return {\n name: \"json\",\n generate(runResult: RunResult, gateEvaluation: GateEvaluation): ReporterOutput {\n const report = {\n kindlm: {\n version: \"1.0.0\",\n timestamp: new Date().toISOString(),\n },\n summary: {\n totalTests: runResult.totalTests,\n passed: runResult.passed,\n failed: runResult.failed,\n errored: runResult.errored,\n skipped: runResult.skipped,\n durationMs: runResult.durationMs,\n },\n gates: {\n passed: gateEvaluation.passed,\n results: gateEvaluation.gates,\n },\n suites: runResult.suites.map((suite) => ({\n name: suite.name,\n status: suite.status,\n tests: suite.tests.map((test) => ({\n name: test.name,\n status: test.status,\n assertions: test.assertions,\n latencyMs: test.latencyMs,\n costUsd: test.costUsd,\n })),\n })),\n };\n\n return { content: JSON.stringify(report, null, 2), format: \"json\" };\n },\n };\n}\n","import type { Reporter, ReporterOutput } from \"./interface.js\";\nimport type { RunResult } from \"../engine/runner.js\";\nimport type { GateEvaluation } from \"../engine/gate.js\";\n\nexport function createJunitReporter(): Reporter {\n return {\n name: \"junit\",\n generate(runResult: RunResult, gateEvaluation: GateEvaluation): ReporterOutput {\n const totalTime = runResult.durationMs / 1000;\n const lines: string[] = [];\n\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n lines.push(\n `<testsuites name=\"KindLM\" tests=\"${runResult.totalTests}\" failures=\"${runResult.failed}\" errors=\"${runResult.errored}\" time=\"${totalTime.toFixed(3)}\">`,\n );\n\n for (const suite of runResult.suites) {\n const suiteFailures = suite.tests.filter(\n (t) => t.status === \"failed\",\n ).length;\n const suiteErrors = suite.tests.filter(\n (t) => t.status === \"errored\",\n ).length;\n const suiteTime =\n suite.tests.reduce((s, t) => s + t.latencyMs, 0) / 1000;\n\n lines.push(\n ` <testsuite name=\"${esc(suite.name)}\" tests=\"${suite.tests.length}\" failures=\"${suiteFailures}\" errors=\"${suiteErrors}\" time=\"${suiteTime.toFixed(3)}\">`,\n );\n\n for (const test of suite.tests) {\n const testTime = test.latencyMs / 1000;\n lines.push(\n ` <testcase name=\"${esc(test.name)}\" classname=\"${esc(suite.name)}\" time=\"${testTime.toFixed(3)}\">`,\n );\n\n if (test.status === \"skipped\") {\n lines.push(\" <skipped/>\");\n } else if (test.status === \"errored\" && test.error) {\n lines.push(\n ` <error message=\"${esc(test.error.message)}\" type=\"${esc(test.error.code)}\">${esc(test.error.message)}</error>`,\n );\n } else if (test.status === \"failed\") {\n const failedAssertions = test.assertions.filter(\n (a) => !a.passed,\n );\n for (const a of failedAssertions) {\n lines.push(\n ` <failure message=\"${esc(a.label)}\" type=\"${esc(a.failureCode ?? \"ASSERTION_FAILED\")}\">${esc(a.failureMessage ?? \"Assertion failed\")}</failure>`,\n );\n }\n }\n\n lines.push(\" </testcase>\");\n }\n\n lines.push(\" </testsuite>\");\n }\n\n // Quality gates as a separate test suite\n if (gateEvaluation.gates.length > 0) {\n const gateFailures = gateEvaluation.gates.filter(\n (g) => !g.passed,\n ).length;\n lines.push(\n ` <testsuite name=\"Quality Gates\" tests=\"${gateEvaluation.gates.length}\" failures=\"${gateFailures}\" errors=\"0\" time=\"0.000\">`,\n );\n for (const gate of gateEvaluation.gates) {\n lines.push(\n ` <testcase name=\"${esc(gate.gateName)}\" classname=\"Quality Gates\" time=\"0.000\">`,\n );\n if (!gate.passed) {\n lines.push(\n ` <failure message=\"${esc(gate.message)}\" type=\"GATE_FAILED\">${esc(gate.message)}</failure>`,\n );\n }\n lines.push(\" </testcase>\");\n }\n lines.push(\" </testsuite>\");\n }\n\n lines.push(\"</testsuites>\");\n\n return { content: lines.join(\"\\n\"), format: \"xml\" };\n },\n };\n}\n\nfunction esc(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","import { createHash } from \"node:crypto\";\nimport type { Reporter, ReporterOutput } from \"./interface.js\";\nimport type { RunResult } from \"../engine/runner.js\";\nimport type { GateEvaluation } from \"../engine/gate.js\";\n\nexport function createComplianceReporter(): Reporter {\n return {\n name: \"compliance\",\n generate(runResult: RunResult, gateEvaluation: GateEvaluation): ReporterOutput {\n const timestamp = new Date().toISOString();\n const sections: string[] = [];\n\n sections.push(\"# EU AI Act — Annex IV Compliance Report\");\n sections.push(\"\");\n sections.push(`**Generated:** ${timestamp}`);\n sections.push(`**Framework:** EU AI Act (Regulation 2024/1689)`);\n sections.push(`**Tool:** KindLM v1.0.0`);\n sections.push(\"\");\n\n // Article 9 — Risk Management\n sections.push(\"## Article 9 — Risk Management System\");\n sections.push(\"\");\n sections.push(\"Testing demonstrates ongoing risk identification and mitigation through automated behavioral regression tests.\");\n sections.push(\"\");\n sections.push(formatGateEvidence(gateEvaluation, [\"passRateMin\"]));\n\n // Article 10 — Data and Data Governance\n sections.push(\"## Article 10 — Data and Data Governance\");\n sections.push(\"\");\n sections.push(\"PII detection guardrails verify that personal data is not exposed in AI system outputs.\");\n sections.push(\"\");\n sections.push(formatGateEvidence(gateEvaluation, [\"piiFailuresMax\", \"keywordFailuresMax\"]));\n\n // Article 12 — Record-Keeping / Logging\n sections.push(\"## Article 12 — Record-Keeping\");\n sections.push(\"\");\n sections.push(\"### Test Execution Log\");\n sections.push(\"\");\n sections.push(`| Metric | Value |`);\n sections.push(`|--------|-------|`);\n sections.push(`| Total Tests | ${runResult.totalTests} |`);\n sections.push(`| Passed | ${runResult.passed} |`);\n sections.push(`| Failed | ${runResult.failed} |`);\n sections.push(`| Errored | ${runResult.errored} |`);\n sections.push(`| Duration | ${runResult.durationMs}ms |`);\n sections.push(\"\");\n sections.push(\"### Suite Results\");\n sections.push(\"\");\n for (const suite of runResult.suites) {\n sections.push(`**${suite.name}** — ${suite.status}`);\n for (const test of suite.tests) {\n const icon = test.status === \"passed\" ? \"PASS\" : \"FAIL\";\n sections.push(`- [${icon}] ${test.name}`);\n }\n sections.push(\"\");\n }\n\n // Article 13 — Transparency\n sections.push(\"## Article 13 — Transparency and Provision of Information\");\n sections.push(\"\");\n sections.push(\"This report provides transparent documentation of AI system testing methodology, results, and quality gate evaluations as required under Article 13.\");\n sections.push(\"\");\n sections.push(formatGateEvidence(gateEvaluation, [\"judgeAvgMin\", \"driftScoreMax\"]));\n\n // Article 15 — Accuracy, Robustness and Cybersecurity\n sections.push(\"## Article 15 — Accuracy, Robustness and Cybersecurity\");\n sections.push(\"\");\n sections.push(\"Schema validation and behavioral assertions verify output accuracy and robustness.\");\n sections.push(\"\");\n sections.push(formatGateEvidence(gateEvaluation, [\"schemaFailuresMax\", \"costMaxUsd\", \"latencyMaxMs\"]));\n\n // Gate Summary\n sections.push(\"## Quality Gate Summary\");\n sections.push(\"\");\n sections.push(`| Gate | Result | Actual | Threshold |`);\n sections.push(`|------|--------|--------|-----------|`);\n for (const gate of gateEvaluation.gates) {\n const result = gate.passed ? \"PASS\" : \"FAIL\";\n sections.push(`| ${gate.gateName} | ${result} | ${fmtNum(gate.actual)} | ${fmtNum(gate.threshold)} |`);\n }\n sections.push(\"\");\n\n const verdict = gateEvaluation.passed ? \"PASS\" : \"FAIL\";\n sections.push(`**Overall Verdict:** ${verdict}`);\n sections.push(\"\");\n\n // Hash — computed over everything above\n const contentAboveHash = sections.join(\"\\n\");\n const hash = createHash(\"sha256\")\n .update(contentAboveHash)\n .digest(\"hex\");\n\n sections.push(\"---\");\n sections.push(`**Tamper Evidence Hash (SHA-256):** \\`${hash}\\``);\n sections.push(\"\");\n\n return { content: sections.join(\"\\n\"), format: \"markdown\" };\n },\n };\n}\n\nfunction formatGateEvidence(\n gateEvaluation: GateEvaluation,\n gateNames: string[],\n): string {\n const relevant = gateEvaluation.gates.filter((g) =>\n gateNames.includes(g.gateName),\n );\n if (relevant.length === 0) return \"\";\n\n const lines: string[] = [];\n lines.push(\"**Gate Evidence:**\");\n for (const gate of relevant) {\n const icon = gate.passed ? \"PASS\" : \"FAIL\";\n lines.push(`- [${icon}] ${gate.message}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction fmtNum(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return n.toFixed(4);\n}\n","import type { Result } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\n\n// ============================================================\n// Constants\n// ============================================================\n\nexport const BASELINE_VERSION = \"1\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface BaselineIO {\n read(suiteName: string): Result<string>;\n write(suiteName: string, content: string): Result<void>;\n list(): Result<string[]>;\n}\n\nexport interface BaselineTestEntry {\n passRate: number;\n outputText: string;\n failureCodes: string[];\n latencyAvgMs: number;\n costUsd: number;\n runCount: number;\n}\n\nexport interface BaselineData {\n version: string;\n suiteName: string;\n createdAt: string;\n results: Record<string, BaselineTestEntry>;\n}\n\n// ============================================================\n// Serialization\n// ============================================================\n\nexport function serializeBaseline(data: BaselineData): string {\n return JSON.stringify(data, null, 2);\n}\n\nexport function deserializeBaseline(raw: string): Result<BaselineData> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file is not valid JSON\",\n });\n }\n\n if (typeof parsed !== \"object\" || parsed === null) {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file is not a JSON object\",\n });\n }\n\n const obj = parsed as Record<string, unknown>;\n\n if (typeof obj[\"version\"] !== \"string\") {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file missing required field: version\",\n });\n }\n\n if (obj[\"version\"] !== BASELINE_VERSION) {\n return err({\n code: \"BASELINE_VERSION_MISMATCH\",\n message: `Baseline version \"${obj[\"version\"]}\" does not match expected \"${BASELINE_VERSION}\". Re-run \\`kindlm baseline set\\` to update.`,\n });\n }\n\n if (typeof obj[\"suiteName\"] !== \"string\") {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file missing required field: suiteName\",\n });\n }\n\n if (typeof obj[\"createdAt\"] !== \"string\") {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file missing required field: createdAt\",\n });\n }\n\n if (typeof obj[\"results\"] !== \"object\" || obj[\"results\"] === null) {\n return err({\n code: \"BASELINE_CORRUPT\",\n message: \"Baseline file missing required field: results\",\n });\n }\n\n return ok(parsed as BaselineData);\n}\n\n// ============================================================\n// I/O-delegating functions\n// ============================================================\n\nexport function readBaseline(suiteName: string, io: BaselineIO): Result<BaselineData> {\n const readResult = io.read(suiteName);\n if (!readResult.success) {\n return readResult;\n }\n\n return deserializeBaseline(readResult.data);\n}\n\nexport function writeBaseline(data: BaselineData, io: BaselineIO): Result<void> {\n const content = serializeBaseline(data);\n return io.write(data.suiteName, content);\n}\n\nexport function listBaselines(io: BaselineIO): Result<string[]> {\n return io.list();\n}\n","import type { AggregatedTestResult } from \"../engine/aggregator.js\";\nimport type { BaselineData, BaselineTestEntry } from \"./store.js\";\nimport { BASELINE_VERSION } from \"./store.js\";\n\nexport function buildBaselineData(\n suiteName: string,\n aggregated: AggregatedTestResult[],\n timestamp: string,\n): BaselineData {\n const results: Record<string, BaselineTestEntry> = {};\n\n for (const agg of aggregated) {\n const key = `${agg.testCaseName}::${agg.modelId}`;\n\n // Pick representative output: first passing run, or first run if all failed\n const passingRun = agg.runs.find((r) => r.assertions.every((a) => a.passed));\n const representative = passingRun ?? agg.runs[0];\n\n results[key] = {\n passRate: agg.passRate,\n outputText: representative?.outputText ?? \"\",\n failureCodes: agg.failureCodes,\n latencyAvgMs: agg.latencyAvgMs,\n costUsd: agg.totalCostUsd,\n runCount: agg.runCount,\n };\n }\n\n return {\n version: BASELINE_VERSION,\n suiteName,\n createdAt: timestamp,\n results,\n };\n}\n","import type { BaselineData, BaselineTestEntry } from \"./store.js\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface BaselineComparison {\n suiteName: string;\n hasBaseline: boolean;\n regressions: BaselineRegression[];\n improvements: BaselineImprovement[];\n unchanged: BaselineUnchanged[];\n newTests: string[];\n removedTests: string[];\n}\n\nexport interface BaselineRegression {\n testName: string;\n baselinePassRate: number;\n currentPassRate: number;\n newFailureCodes: string[];\n}\n\nexport interface BaselineImprovement {\n testName: string;\n baselinePassRate: number;\n currentPassRate: number;\n}\n\nexport interface BaselineUnchanged {\n testName: string;\n passRate: number;\n}\n\n// ============================================================\n// Comparison\n// ============================================================\n\nconst EPSILON = 0.001;\n\nexport function compareBaseline(\n baseline: BaselineData,\n currentResults: Record<string, BaselineTestEntry>,\n): BaselineComparison {\n const regressions: BaselineRegression[] = [];\n const improvements: BaselineImprovement[] = [];\n const unchanged: BaselineUnchanged[] = [];\n const newTests: string[] = [];\n const removedTests: string[] = [];\n\n const baselineKeys = new Set(Object.keys(baseline.results));\n\n // Classify current tests\n for (const [key, current] of Object.entries(currentResults)) {\n const base = baseline.results[key];\n if (!base) {\n newTests.push(key);\n continue;\n }\n\n baselineKeys.delete(key);\n const diff = current.passRate - base.passRate;\n\n if (diff < -EPSILON) {\n const newFailureCodes = current.failureCodes.filter(\n (code) => !base.failureCodes.includes(code),\n );\n regressions.push({\n testName: key,\n baselinePassRate: base.passRate,\n currentPassRate: current.passRate,\n newFailureCodes,\n });\n } else if (diff > EPSILON) {\n improvements.push({\n testName: key,\n baselinePassRate: base.passRate,\n currentPassRate: current.passRate,\n });\n } else {\n unchanged.push({\n testName: key,\n passRate: current.passRate,\n });\n }\n }\n\n // Remaining baseline keys are removed tests\n for (const key of baselineKeys) {\n removedTests.push(key);\n }\n\n return {\n suiteName: baseline.suiteName,\n hasBaseline: true,\n regressions,\n improvements,\n unchanged,\n newTests,\n removedTests,\n };\n}\n","import type { Result } from \"../types/result.js\";\nimport { ok, err } from \"../types/result.js\";\nimport type {\n OtlpTracesPayload,\n OtlpAttribute,\n OtlpAttributeValue,\n ParsedSpan,\n} from \"./types.js\";\n\nexport function parseOtlpPayload(raw: unknown): Result<ParsedSpan[]> {\n if (!raw || typeof raw !== \"object\") {\n return err({\n code: \"CONFIG_PARSE_ERROR\",\n message: \"OTLP payload must be a non-null object\",\n });\n }\n\n const payload = raw as OtlpTracesPayload;\n if (!Array.isArray(payload.resourceSpans)) {\n return err({\n code: \"CONFIG_PARSE_ERROR\",\n message: \"OTLP payload missing resourceSpans array\",\n });\n }\n\n const spans: ParsedSpan[] = [];\n\n for (const resourceSpan of payload.resourceSpans) {\n const resourceAttrs = flattenAttributes(resourceSpan.resource?.attributes ?? []);\n\n if (!Array.isArray(resourceSpan.scopeSpans)) continue;\n\n for (const scopeSpan of resourceSpan.scopeSpans) {\n if (!Array.isArray(scopeSpan.spans)) continue;\n\n for (const span of scopeSpan.spans) {\n const startTimeMs = nanosToMs(span.startTimeUnixNano);\n const endTimeMs = nanosToMs(span.endTimeUnixNano);\n\n spans.push({\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || undefined,\n name: span.name,\n kind: span.kind,\n startTimeMs,\n endTimeMs,\n durationMs: endTimeMs - startTimeMs,\n attributes: flattenAttributes(span.attributes ?? []),\n resourceAttributes: resourceAttrs,\n statusCode: span.status?.code,\n statusMessage: span.status?.message,\n });\n }\n }\n }\n\n return ok(spans);\n}\n\nfunction nanosToMs(nanos: string): number {\n const n = BigInt(nanos);\n return Number(n / 1_000_000n);\n}\n\nfunction flattenAttributes(\n attrs: OtlpAttribute[],\n): Record<string, string | number | boolean> {\n const result: Record<string, string | number | boolean> = {};\n\n for (const attr of attrs) {\n const val = extractValue(attr.value);\n if (val !== undefined) {\n result[attr.key] = val;\n }\n }\n\n return result;\n}\n\nfunction extractValue(\n value: OtlpAttributeValue,\n): string | number | boolean | undefined {\n if (value.stringValue !== undefined) return value.stringValue;\n if (value.intValue !== undefined) return parseInt(value.intValue, 10);\n if (value.doubleValue !== undefined) return value.doubleValue;\n if (value.boolValue !== undefined) return value.boolValue;\n return undefined;\n}\n","import type { AssertionContext } from \"../assertions/interface.js\";\nimport type { ProviderToolCall, ProviderAdapter } from \"../types/provider.js\";\nimport type { ParsedSpan, SpanMapping, SpanFilter, SpanMappingResult } from \"./types.js\";\n\nexport function filterSpans(spans: ParsedSpan[], filter?: SpanFilter): ParsedSpan[] {\n if (!filter) return spans;\n\n return spans.filter((span) => {\n if (filter.namePattern) {\n const re = new RegExp(filter.namePattern);\n if (!re.test(span.name)) return false;\n }\n\n if (filter.attributeMatch) {\n for (const [key, value] of Object.entries(filter.attributeMatch)) {\n if (String(span.attributes[key]) !== value) return false;\n }\n }\n\n if (filter.minDurationMs !== undefined) {\n if (span.durationMs < filter.minDurationMs) return false;\n }\n\n return true;\n });\n}\n\nexport function mapSpansToResult(\n spans: ParsedSpan[],\n mapping: SpanMapping,\n): SpanMappingResult {\n let outputText = \"\";\n const toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[] = [];\n let latencyMs = 0;\n let inputTokens = 0;\n let outputTokens = 0;\n let model: string | undefined;\n let system: string | undefined;\n\n for (const span of spans) {\n const attrs = { ...span.resourceAttributes, ...span.attributes };\n\n // Extract output text from the configured attribute\n const text = attrs[mapping.outputTextAttr];\n if (typeof text === \"string\" && text) {\n outputText = outputText ? `${outputText}\\n${text}` : text;\n }\n\n // Extract model\n const m = attrs[mapping.modelAttr];\n if (typeof m === \"string\" && m) {\n model = m;\n }\n\n // Extract system\n const s = attrs[mapping.systemAttr];\n if (typeof s === \"string\" && s) {\n system = s;\n }\n\n // Extract tokens\n const inTok = attrs[mapping.inputTokensAttr];\n if (typeof inTok === \"number\") {\n inputTokens += inTok;\n }\n const outTok = attrs[mapping.outputTokensAttr];\n if (typeof outTok === \"number\") {\n outputTokens += outTok;\n }\n\n // Accumulate latency from root spans (no parent)\n if (!span.parentSpanId) {\n latencyMs += span.durationMs;\n }\n\n // Look for tool call attributes (GenAI convention)\n const toolName = attrs[\"gen_ai.tool.name\"];\n const toolArgs = attrs[\"gen_ai.tool.arguments\"];\n if (typeof toolName === \"string\") {\n let parsedArgs: Record<string, unknown> = {};\n if (typeof toolArgs === \"string\") {\n try {\n parsedArgs = JSON.parse(toolArgs) as Record<string, unknown>;\n } catch {\n // ignore parse errors\n }\n }\n toolCalls.push({\n id: span.spanId,\n name: toolName,\n arguments: parsedArgs,\n });\n }\n }\n\n return {\n outputText,\n toolCalls,\n latencyMs,\n inputTokens,\n outputTokens,\n model,\n system,\n };\n}\n\nexport interface BuildContextOptions {\n configDir: string;\n judgeAdapter?: ProviderAdapter;\n judgeModel?: string;\n baselineText?: string;\n}\n\nexport function buildContextFromTrace(\n result: SpanMappingResult,\n options: BuildContextOptions,\n): AssertionContext {\n const toolCalls: ProviderToolCall[] = result.toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n arguments: tc.arguments,\n }));\n\n return {\n outputText: result.outputText,\n toolCalls,\n configDir: options.configDir,\n latencyMs: result.latencyMs,\n judgeAdapter: options.judgeAdapter,\n judgeModel: options.judgeModel,\n baselineText: options.baselineText,\n };\n}\n"],"mappings":"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","names":["ProviderError","code","message","statusCode","retryable","raw","ok","data","err","error","matchArgs","actual","expected","key","value","createToolCalledAssertion","tool","argsMatch","context","results","matching","tc","actualNames","anyMatch","createToolNotCalledAssertion","found","createToolOrderAssertion","expectations","exp","actualIndex","orderMatch","ajvInstance","getAjvInstance","ajvMod","formatsMod","Ajv","addFormats","instance","validatorCache","getOrCompileValidator","ajv","schema","key","cached","validate","createSchemaAssertion","config","context","results","parsed","e","valid","lowerOutput","substring","found","lowerOutputNc","withinLimit","redact","match","NESTED_QUANTIFIER_RE","hasNestedQuantifiers","pattern","safeRegexExec","regex","text","maxMatches","results","start","m","createPiiAssertion","config","compiledPatterns","compilationError","i","cp","context","matches","totalMatches","name","remaining","found","passed","createKeywordsPresentAssertion","keywords","context","lower","found","kw","createKeywordsAbsentAssertion","results","keyword","JUDGE_SYSTEM_PROMPT","buildUserPrompt","outputText","criteria","rubric","prompt","parseJudgeResponse","text","jsonMatch","parsed","createJudgeAssertion","config","context","response","passed","DRIFT_JUDGE_SYSTEM","parseDriftResponse","text","jsonMatch","parsed","getNestedField","obj","path","parts","current","part","fieldDiff","baselineText","outputText","fields","baselineObj","outputObj","mismatched","field","baseVal","outVal","createDriftAssertion","config","context","driftScore","score","passed","response","createLatencyAssertion","config","context","latencyMs","passed","createCostAssertion","config","context","costUsd","passed","createAssertionsFromExpect","expect","overrides","assertions","tc","createToolOrderAssertion","createToolNotCalledAssertion","createToolCalledAssertion","createSchemaAssertion","createPiiAssertion","createKeywordsPresentAssertion","createKeywordsAbsentAssertion","criterion","createJudgeAssertion","createDriftAssertion","createAssertionRegistry","config","createLatencyAssertion","createCostAssertion","PROBABILISTIC_TYPES","classifyAssertion","assertionType","isDeterministic","isProbabilistic","withRetry","fn","options","maxRetries","shouldRetry","baseDelayMs","lastError","attempt","error","delay","sleep","ms","resolve","OPENAI_PRICING","mapFinishReason","reason","mapError","status","data","message","ProviderError","createOpenAIAdapter","httpClient","apiKey","baseUrl","organization","timeoutMs","maxRetries","config","request","body","m","tc","t","headers","startTime","response","withRetry","error","json","latencyMs","parsed","choice","toolCalls","args","model","usage","pricing","ANTHROPIC_PRICING","mapFinishReason","reason","mapError","status","data","message","ProviderError","createAnthropicAdapter","httpClient","apiKey","baseUrl","timeoutMs","maxRetries","config","request","systemMessage","m","nonSystemMessages","contentBlocks","tc","body","t","startTime","response","withRetry","error","json","latencyMs","parsed","text","toolCalls","block","inputTokens","outputTokens","model","usage","entry","key","_model","mapFinishReason","doneReason","hasToolCalls","mapError","status","data","message","ProviderError","createOllamaAdapter","httpClient","baseUrl","timeoutMs","maxRetries","config","request","messages","m","tc","body","options","t","headers","startTime","response","withRetry","error","json","latencyMs","parsed","rawToolCalls","toolCalls","index","GEMINI_PRICING","mapFinishReason","reason","hasToolCalls","mapError","status","data","message","ProviderError","createGeminiAdapter","httpClient","apiKey","baseUrl","timeoutMs","maxRetries","config","request","contents","systemInstruction","m","parseToolContent","parts","tc","geminiRole","body","generationConfig","t","mapToolChoice","headers","startTime","url","response","withRetry","error","json","latencyMs","parsed","candidate","text","toolCalls","toolCallIndex","part","model","usage","pricing","content","choice","mapFinishReason","reason","mapError","status","data","message","ProviderError","createMistralAdapter","httpClient","apiKey","baseUrl","timeoutMs","maxRetries","config","request","body","m","tc","t","headers","startTime","response","withRetry","error","json","latencyMs","parsed","choice","toolCalls","args","_model","_usage","mapFinishReason","reason","mapError","status","data","message","ProviderError","createCohereAdapter","httpClient","apiKey","baseUrl","timeoutMs","maxRetries","config","request","body","m","tc","t","headers","startTime","response","withRetry","error","json","latencyMs","parsed","text","c","toolCalls","args","inputTokens","outputTokens","_model","_usage","PROVIDER_FACTORIES","createOpenAIAdapter","createAnthropicAdapter","createOllamaAdapter","createGeminiAdapter","createMistralAdapter","createCohereAdapter","createProvider","name","httpClient","factory","supported","runConversation","adapter","initialRequest","toolSimulations","options","maxTurns","turns","allToolCalls","messages","totalUsage","totalLatencyMs","turn","request","response","toolCall","simulation","s","toolResponse","resolveToolResponse","lastResponse","args","resp","matchArgs","expected","actual","key","value","z","z","SpanMappingSchema","SpanFilterSchema","TraceConfigSchema","NonEmptyString","z","Temperature","Score01","RegexPattern","val","ProviderConfigSchema","OllamaProviderConfigSchema","ProvidersSchema","providers","k","ModelParamsSchema","ModelSchema","PromptSchema","OutputExpectSchema","output","PIIGuardrailSchema","KeywordGuardrailSchema","JudgeCriterionSchema","ToolCallExpectSchema","BaselineDriftSchema","GuardrailsSchema","ExpectSchema","ToolSimulationSchema","TestCaseSchema","test","hasPrompt","hasCommand","GatesSchema","ComplianceSchema","UploadSchema","SuiteSchema","KindLMConfigSchema","prompts","TraceConfigSchema","validateConfig","raw","result","ok","err","issue","parseYaml","MAX_CONFIG_SIZE","MAX_TESTS","MAX_SUITES","parseConfig","yamlContent","options","err","raw","parseYaml","cause","validated","validateConfig","config","errors","modelIds","model","testNames","test","modelId","pathResult","safePath","tc","ok","base","relative","normalizedBase","joined","resolved","normalizePath","normalizedRoot","p","parts","result","part","PLACEHOLDER_RE","interpolate","template","vars","missing","findMissingVars","err","result","_match","key","ok","match","aggregateRuns","runs","first","testCaseName","modelId","passRate","r","a","scoresByType","run","arr","assertionScores","type","scores","sum","failureCodeSet","latencyAvgMs","totalCostUsd","totalTokens","parseCommandOutput","raw","lines","textLines","toolCalls","outputJson","toolCallCounter","line","trimmed","event","tryParseEvent","parsed","createRunner","config","deps","startTime","schemaCache","test","fullPath","joinPath","readResult","err","e","units","repeat","runIndex","modelIds","m","modelId","modelConfig","caseResults","runWithConcurrency","unit","executeUnit","groupKey","r","groups","key","arr","aggregated","runs","aggregateRuns","testRunResults","agg","skippedTests","t","allTests","passed","failed","errored","skipped","suiteStatus","runResult","ok","executeCommandUnit","errorResult","adapter","promptDef","userResult","interpolate","messages","sysResult","tools","request","conversation","runConversation","costEstimate","overrides","assertions","createAssertionsFromExpect","judgeModelId","judgeModelConfig","judgeAdapter","context","baselineKey","baselineEntry","allResults","assertion","results","allPassed","cmdResult","execResult","latencyMs","parsed","parseCommandOutput","testCaseName","message","tasks","limit","nextIndex","worker","index","task","workers","base","relative","evaluateGates","config","results","gates","totalRuns","s","r","totalPassed","overallPassRate","fmt","schemaFailures","countFailures","judgeScores","collectScores","judgeAvg","a","b","driftScores","maxDrift","piiFailures","keywordFailures","totalCost","avgLatency","rate","computeCategoryPassRate","g","category","total","passed","run","classifyAssertion","codes","count","code","assertionType","scores","entry","n","identity","t","noColor","createPrettyReporter","colorize","noColor","runResult","gateEvaluation","lines","c","totalCost","suite","formatSuite","test","formatTest","meta","formatTestMeta","a","formatAssertion","passStr","failStr","errorStr","formatDuration","formatCost","gate","icon","parts","scoreStr","formatScore","label","detail","threshold","extractThreshold","symbol","match","belowMatch","ms","usd","createJsonReporter","runResult","gateEvaluation","report","suite","test","createJunitReporter","runResult","gateEvaluation","totalTime","lines","suite","suiteFailures","t","suiteErrors","suiteTime","s","esc","test","testTime","failedAssertions","a","gateFailures","g","gate","createHash","createComplianceReporter","runResult","gateEvaluation","timestamp","sections","formatGateEvidence","suite","test","icon","gate","result","fmtNum","verdict","contentAboveHash","hash","gateNames","relevant","g","lines","n","BASELINE_VERSION","serializeBaseline","data","deserializeBaseline","raw","parsed","err","obj","ok","readBaseline","suiteName","io","readResult","writeBaseline","content","listBaselines","buildBaselineData","suiteName","aggregated","timestamp","results","agg","key","representative","r","a","BASELINE_VERSION","compareBaseline","baseline","currentResults","regressions","improvements","unchanged","newTests","removedTests","baselineKeys","key","current","base","diff","newFailureCodes","code","parseOtlpPayload","raw","err","payload","spans","resourceSpan","resourceAttrs","flattenAttributes","scopeSpan","span","startTimeMs","nanosToMs","endTimeMs","ok","nanos","n","attrs","result","attr","val","extractValue","value","filterSpans","spans","filter","span","key","value","mapSpansToResult","mapping","outputText","toolCalls","latencyMs","inputTokens","outputTokens","model","system","attrs","text","m","s","inTok","outTok","toolName","toolArgs","parsedArgs","buildContextFromTrace","result","options","tc"]}
|