{"version":3,"sources":["../../src/harness.ts","../../src/judges/judgeHarness.ts","../../src/judges/factualityJudge.ts","../../src/internal/matchers.ts","../../src/internal/structuredOutputScorer.ts","../../src/judges/structuredOutputJudge.ts","../../src/internal/toolCallScorer.ts","../../src/judges/toolCallJudge.ts"],"sourcesContent":["import {\n  assistantMessages,\n  failedSpans,\n  latestAssistantMessageContent,\n  messagesByRole,\n  messagesToTranscriptEvents,\n  NormalizedSessionSchema,\n  spans,\n  spansByKind,\n  systemMessages,\n  TranscriptEventSchema,\n  toolCalls,\n  toolMessages,\n  userMessages,\n} from \"@vitest-evals/core\";\nimport type {\n  GenAiOperationName,\n  HarnessRun,\n  HarnessRunError,\n  NormalizedError,\n  JsonPrimitive,\n  JsonValue,\n  TranscriptMessageEvent,\n  NormalizedSession,\n  NormalizedSpan,\n  NormalizedSpanAttributes,\n  NormalizedSpanEvent,\n  TranscriptEvent,\n  NormalizedTrace,\n  TimingSummary,\n  ToolCall,\n  TranscriptMessageInput,\n  TranscriptMessageContentPart,\n  TranscriptMessageTextPart,\n  TranscriptMessageToolCallPart,\n  TranscriptMessageToolCall,\n  TranscriptMessageToolResultPart,\n  UsageSummary,\n} from \"@vitest-evals/core\";\n\nexport {\n  assistantMessages,\n  failedSpans,\n  latestAssistantMessageContent,\n  messagesByRole,\n  messagesToTranscriptEvents,\n  spans,\n  spansByKind,\n  systemMessages,\n  toolCalls,\n  toolMessages,\n  userMessages,\n} from \"@vitest-evals/core\";\nexport type {\n  GenAiOperationName,\n  GenAiOutputType,\n  GenAiProviderName,\n  GenAiSemanticAttributeKey,\n  GenAiSemanticAttributes,\n  GenAiTokenType,\n  GenAiToolType,\n  HarnessRun,\n  HarnessRunError,\n  NormalizedError,\n  JsonPrimitive,\n  JsonValue,\n  TranscriptMessageEvent,\n  NormalizedSession,\n  NormalizedSpan,\n  NormalizedSpanAttributeKey,\n  NormalizedSpanAttributes,\n  NormalizedSpanEvent,\n  TranscriptToolCallEvent,\n  TranscriptToolResultEvent,\n  TranscriptEvent,\n  NormalizedTrace,\n  OpenTelemetrySemanticAttributeKey,\n  OpenTelemetrySemanticAttributes,\n  TimingSummary,\n  ToolCall,\n  TranscriptMessageInput,\n  TranscriptMessageContentPart,\n  TranscriptMessageTextPart,\n  TranscriptMessageToolCallPart,\n  TranscriptMessageToolCall,\n  TranscriptMessageToolResultPart,\n  UsageSummary,\n} from \"@vitest-evals/core\";\n\n/** Options for attaching a fallback run trace to a harness result. */\nexport type EnsureRunTraceOptions = {\n  /** Human-readable run or harness name. */\n  name: string;\n  /** Wall-clock start time for the harness run. */\n  startedAt: Date;\n  /** Wall-clock finish time for the harness run. */\n  finishedAt: Date;\n  /** Optional trace id. A generated id is used when omitted. */\n  id?: string;\n  /** GenAI operation name to place on the root run span. */\n  operationName?: GenAiOperationName;\n  /** Optional JSON-safe source marker for the trace metadata. */\n  source?: string;\n};\n\ntype OutputField<TOutput extends JsonValue | undefined> =\n  undefined extends TOutput ? { output?: TOutput } : { output: TOutput };\n\n/** Generic JSON-like metadata record used by normalized artifacts and reports. */\nexport type HarnessMetadata = Record<string, unknown>;\n\n/**\n * Runtime context passed from the eval fixture into a harness run.\n *\n * @example\n * ```ts\n * const harness: Harness<string> = {\n *   name: \"refund-agent\",\n *   async run(input, context) {\n *     context.setArtifact(\"inputLength\", input.length);\n *\n *     return {\n *       output: undefined,\n *       session: { events: [{ type: \"message\", role: \"user\", content: input }] },\n *       usage: {},\n *       errors: [],\n *     };\n *   },\n * };\n * ```\n */\nexport type HarnessContext = {\n  /** Abort signal from Vitest when available. */\n  signal?: AbortSignal;\n  /** Mutable JSON-safe artifact bag shared with the harness. */\n  artifacts: Record<string, JsonValue>;\n  /** Stores one JSON-safe artifact on the current run. */\n  setArtifact: (name: string, value: JsonValue) => void;\n};\n\n/**\n * Adapter that executes the system under test and returns a normalized run.\n *\n * @example\n * ```ts\n * const harness: Harness<string, { status: \"approved\" | \"denied\" }> = {\n *   name: \"refund-agent\",\n *   async run(input, context) {\n *     return normalizeHarnessRun(input, await runRefundFlow(input), context);\n *   },\n * };\n * ```\n */\nexport type Harness<\n  TInput = unknown,\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n> = {\n  /** Stable harness name used in reports. */\n  name: string;\n  /** Executes the system under test and returns a normalized run. */\n  run: (input: TInput, context: HarnessContext) => Promise<HarnessRun<TOutput>>;\n};\n\n/** Value or promise accepted by lightweight harness callbacks. */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/** Lightweight span event accepted by `createHarness(...)` results. */\nexport type SimpleSpanEvent = Omit<NormalizedSpanEvent, \"attributes\"> & {\n  /** Raw event attributes accepted by `createHarness(...)` before normalization. */\n  attributes?: Record<string, unknown>;\n};\n\n/** Lightweight span record accepted by `createHarness(...)` results. */\nexport type SimpleSpanRecord = Omit<\n  NormalizedSpan,\n  \"attributes\" | \"error\" | \"events\"\n> & {\n  /** Raw span attributes accepted by `createHarness(...)` before normalization. */\n  attributes?: Record<string, unknown>;\n  /** Raw span error accepted by `createHarness(...)` before normalization. */\n  error?: unknown;\n  /** Raw span events accepted by `createHarness(...)` before normalization. */\n  events?: SimpleSpanEvent[];\n};\n\n/** Lightweight trace record accepted by `createHarness(...)` results. */\nexport type SimpleTraceRecord = Omit<NormalizedTrace, \"metadata\" | \"spans\"> & {\n  /** Raw trace metadata accepted by `createHarness(...)` before normalization. */\n  metadata?: Record<string, unknown>;\n  /** Lightweight spans to normalize into the trace. */\n  spans: SimpleSpanRecord[];\n};\n\n/** Lightweight transcript input accepted by `createHarness(...)` results. */\nexport type SimpleTranscriptInput =\n  | {\n      /** Ordered normalized transcript events for the application run. */\n      events: TranscriptEvent[];\n      messages?: never;\n    }\n  | {\n      /** Strict camelCase message transport normalized into transcript events. */\n      messages: TranscriptMessageInput[];\n      events?: never;\n    };\n\n/**\n * Lightweight result shape normalized by `createHarness(...)`.\n *\n * @example\n * ```ts\n * const result: SimpleHarnessResult<{ status: \"approved\" }> = {\n *   output: { status: \"approved\" },\n *   events: [\n *     { type: \"message\", role: \"user\", content: \"Refund invoice inv_123\" },\n *     { type: \"message\", role: \"assistant\", content: { status: \"approved\" } },\n *   ],\n *   usage: { totalTokens: 260 },\n * };\n * ```\n */\nexport type SimpleHarnessResult<\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n> = OutputField<TOutput> &\n  SimpleTranscriptInput & {\n    /** Usage summary to attach to the run. */\n    usage?: UsageSummary;\n    /** Timing summary to attach to the run. */\n    timings?: TimingSummary;\n    /** Raw artifact values to normalize and merge into the run. */\n    artifacts?: Record<string, unknown>;\n    /** Lightweight traces and spans to normalize into the run. */\n    traces?: SimpleTraceRecord[];\n    /** Raw session metadata to normalize into the session. */\n    metadata?: Record<string, unknown>;\n    /** Raw errors to normalize into the run. */\n    errors?: unknown[];\n  };\n\n/** Either a complete normalized run or a lightweight result to normalize. */\nexport type HarnessResultLike<\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n> = HarnessRun<TOutput> | SimpleHarnessResult<TOutput>;\n\n/** Arguments passed to the `createHarness(...)` convenience callback. */\nexport type CreateHarnessRunArgs<TInput> = {\n  /** Original input passed to `run(input)`. */\n  input: TInput;\n  /** Abort signal from Vitest when available. */\n  signal?: AbortSignal;\n  /** Mutable run artifact bag. */\n  artifacts: HarnessContext[\"artifacts\"];\n  /** Stores one JSON-safe artifact on the current run. */\n  setArtifact: HarnessContext[\"setArtifact\"];\n};\n\n/**\n * Options for creating a lightweight custom application harness.\n *\n * Prefer this helper for custom harnesses. Implement `Harness` directly only\n * when the callback already returns a full `HarnessRun` with canonical\n * `session.events`.\n *\n * @example\n * ```ts\n * const options: CreateHarnessOptions<string, { status: \"approved\" }> = {\n *   name: \"refund-agent\",\n *   run: async ({ input }) => ({\n *     output: await classifyRefund(input),\n *     events: [{ type: \"message\", role: \"user\", content: input }],\n *   }),\n * };\n * ```\n */\nexport type CreateHarnessOptions<\n  TInput = unknown,\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n> = {\n  /** Stable harness name used in reports. */\n  name: string;\n  /** Executes application code and returns either a lightweight result or full `HarnessRun`. */\n  run: (\n    args: CreateHarnessRunArgs<TInput>,\n  ) => MaybePromise<HarnessResultLike<TOutput>>;\n};\n\nfunction isJsonPrimitive(value: unknown): value is JsonPrimitive {\n  return (\n    value === null ||\n    typeof value === \"string\" ||\n    typeof value === \"boolean\" ||\n    (typeof value === \"number\" && Number.isFinite(value))\n  );\n}\n\nfunction isJsonRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeJsonArray(value: unknown[], seen: WeakSet<object>) {\n  if (seen.has(value)) {\n    return undefined;\n  }\n\n  seen.add(value);\n  const normalized = value.map((item) => {\n    const normalized = toJsonValueInternal(item, seen);\n    return normalized === undefined ? null : normalized;\n  });\n  seen.delete(value);\n\n  return normalized;\n}\n\nfunction normalizeJsonObject(\n  value: Record<string, unknown>,\n  seen: WeakSet<object>,\n): Record<string, JsonValue> {\n  const normalized: Record<string, JsonValue> = {};\n\n  if (seen.has(value)) {\n    return normalized;\n  }\n\n  seen.add(value);\n  try {\n    for (const [key, entryValue] of Object.entries(value)) {\n      const entry = toJsonValueInternal(entryValue, seen);\n      if (entry !== undefined) {\n        normalized[key] = entry;\n      }\n    }\n  } finally {\n    seen.delete(value);\n  }\n\n  return normalized;\n}\n\n/** Returns true when a value exposes a callable method with the given name. */\nexport function hasCallableMethod(value: unknown, methodName: string) {\n  return (\n    value !== null &&\n    (typeof value === \"object\" || typeof value === \"function\") &&\n    methodName in value &&\n    typeof (value as Record<string, unknown>)[methodName] === \"function\"\n  );\n}\n\n/** Normalizes an unknown value into the JSON-safe shape used by harness runs. */\nexport function toJsonValue(value: unknown): JsonValue | undefined {\n  return toJsonValueInternal(value, new WeakSet());\n}\n\nfunction toJsonValueInternal(\n  value: unknown,\n  seen: WeakSet<object>,\n): JsonValue | undefined {\n  if (isJsonPrimitive(value)) {\n    return value;\n  }\n\n  if (\n    value !== null &&\n    typeof value === \"object\" &&\n    seen.has(value as object)\n  ) {\n    return undefined;\n  }\n\n  if (Array.isArray(value)) {\n    return normalizeJsonArray(value, seen);\n  }\n\n  if (isJsonRecord(value)) {\n    return normalizeJsonObject(value, seen);\n  }\n\n  return undefined;\n}\n\n/** Drops non-JSON properties from a record while preserving valid values. */\nexport function normalizeRecord(\n  value: Record<string, unknown>,\n): Record<string, JsonValue> {\n  return normalizeJsonObject(value, new WeakSet());\n}\n\n/** Normalizes metadata and omits the field entirely when nothing survives. */\nexport function normalizeMetadata(\n  value: Record<string, unknown>,\n): Record<string, JsonValue> | undefined {\n  const normalized = normalizeRecord(value);\n  return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/** Converts arbitrary content into the JSON-safe message content shape. */\nexport function normalizeContent(value: unknown): JsonValue {\n  const normalized = toJsonValue(value);\n  return normalized !== undefined ? normalized : String(value);\n}\n\n/**\n * Creates a harness from the common \"run app code and return output\" shape.\n *\n * @param options - Harness name plus the callback that executes app code.\n *\n * @example\n * ```ts\n * import { createHarness } from \"vitest-evals\";\n *\n * export const refundHarness = createHarness<\n *   string,\n *   { status: \"approved\" | \"denied\" }\n * >({\n *   name: \"refund-agent\",\n *   run: async ({ input, setArtifact }) => {\n *     const result = await runRefundFlow(input);\n *     const output = { status: result.status };\n *\n *     setArtifact(\"case\", { invoiceId: result.invoiceId });\n *\n *     return {\n *       output,\n *       events: [\n *         { type: \"message\", role: \"user\", content: input },\n *         {\n *           type: \"tool_call\",\n *           id: \"call_lookup\",\n *           name: \"lookupInvoice\",\n *           arguments: { invoiceId: result.invoiceId },\n *         },\n *         {\n *           type: \"tool_result\",\n *           toolCallId: \"call_lookup\",\n *           name: \"lookupInvoice\",\n *           content: { refundable: result.refundable },\n *         },\n *         { type: \"message\", role: \"assistant\", content: output },\n *       ],\n *       usage: { provider: \"openai\", model: \"gpt-4o-mini\" },\n *     };\n *   },\n * });\n * ```\n */\nexport function createHarness<\n  TInput = unknown,\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n>(options: CreateHarnessOptions<TInput, TOutput>): Harness<TInput, TOutput>;\nexport function createHarness<\n  TInput = unknown,\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n>(options: CreateHarnessOptions<TInput, TOutput>): Harness<TInput, TOutput> {\n  const harness: Harness<TInput, TOutput> = {\n    name: options.name,\n    run: async (input, context) => {\n      const startedAt = new Date();\n\n      try {\n        const result = await options.run({\n          input,\n          signal: context.signal,\n          artifacts: context.artifacts,\n          setArtifact: context.setArtifact,\n        });\n        const run = normalizeHarnessRun(input, result, context);\n        ensureRunTrace(run, {\n          name: options.name,\n          startedAt,\n          finishedAt: new Date(),\n        });\n\n        return run;\n      } catch (error) {\n        const partialRun = getHarnessRunFromError(error);\n        if (partialRun) {\n          if (\n            Object.keys(context.artifacts).length > 0 &&\n            !partialRun.artifacts\n          ) {\n            partialRun.artifacts = context.artifacts;\n          }\n          ensureRunTrace(partialRun, {\n            name: options.name,\n            startedAt,\n            finishedAt: new Date(),\n          });\n          throw attachHarnessRunToError(error, partialRun);\n        }\n\n        const failedRun = createFailedHarnessRun(input, error, {\n          artifacts: context.artifacts,\n        });\n        ensureRunTrace(failedRun, {\n          name: options.name,\n          startedAt,\n          finishedAt: new Date(),\n        });\n\n        throw attachHarnessRunToError(error, failedRun);\n      }\n    },\n  };\n\n  return harness;\n}\n\n/**\n * Normalizes a lightweight harness result into the reporter-facing run shape.\n *\n * @param input - Original input passed to the harness.\n * @param result - Lightweight result or pre-normalized harness run.\n * @param context - Optional per-run context used to merge artifacts.\n *\n * @example\n * ```ts\n * const run = normalizeHarnessRun(\"Refund invoice inv_123\", {\n *   output: { status: \"approved\" },\n *   events: [\n *     { type: \"message\", role: \"user\", content: \"Refund invoice inv_123\" },\n *     {\n *       type: \"tool_call\",\n *       id: \"call_lookup\",\n *       name: \"lookupInvoice\",\n *       arguments: { invoiceId: \"inv_123\" },\n *     },\n *     {\n *       type: \"tool_result\",\n *       toolCallId: \"call_lookup\",\n *       name: \"lookupInvoice\",\n *       content: { refundable: true },\n *     },\n *   ],\n *   usage: { provider: \"openai\", model: \"gpt-4o-mini\" },\n * });\n *\n * expect(toolCalls(run)).toHaveLength(1);\n * ```\n */\nexport function normalizeHarnessRun<\n  TInput = unknown,\n  TOutput extends JsonValue | undefined = JsonValue | undefined,\n>(\n  input: TInput,\n  result: HarnessResultLike<TOutput>,\n  context?: HarnessContext,\n): HarnessRun<TOutput> {\n  if (isHarnessRun(result)) {\n    if (\n      context &&\n      Object.keys(context.artifacts).length > 0 &&\n      !result.artifacts\n    ) {\n      return {\n        ...result,\n        artifacts: context.artifacts,\n      };\n    }\n\n    return result;\n  }\n\n  if (\"toolCalls\" in result) {\n    throw new TypeError(\n      'createHarness results do not accept top-level toolCalls. Return ordered session events with type: \"tool_call\" and type: \"tool_result\" entries instead.',\n    );\n  }\n\n  const output = result.output;\n  const usage = result.usage ?? {};\n  const events = normalizeTranscriptInput(result);\n  if (!events) {\n    throw new TypeError(\n      \"createHarness results must include ordered events or messages. Return a full HarnessRun or a lightweight result with events/messages.\",\n    );\n  }\n  if (events.length === 0) {\n    throw new TypeError(\n      \"createHarness results must include at least one transcript event. Return ordered events or message transport inputs that normalize into events.\",\n    );\n  }\n  const metadata = result.metadata\n    ? normalizeMetadata(result.metadata)\n    : undefined;\n  const artifacts = normalizeMergedArtifacts(\n    context?.artifacts,\n    result.artifacts,\n  );\n  const traces = normalizeSimpleTraces(result.traces);\n\n  return {\n    session: {\n      events,\n      ...(usage.provider ? { provider: usage.provider } : {}),\n      ...(usage.model ? { model: usage.model } : {}),\n      ...(metadata ? { metadata } : {}),\n    },\n    ...(output !== undefined ? { output } : {}),\n    usage,\n    ...(result.timings ? { timings: result.timings } : {}),\n    ...(artifacts ? { artifacts } : {}),\n    ...(traces ? { traces } : {}),\n    errors: normalizeSimpleErrors(result.errors),\n  } as HarnessRun<TOutput>;\n}\n\nfunction normalizeTranscriptInput(\n  result: HarnessResultLike,\n): TranscriptEvent[] | undefined {\n  if (\"events\" in result && Array.isArray(result.events)) {\n    return result.events.map((event) => TranscriptEventSchema.parse(event));\n  }\n\n  if (\"messages\" in result && Array.isArray(result.messages)) {\n    return messagesToTranscriptEvents(result.messages).map((event) =>\n      TranscriptEventSchema.parse(event),\n    );\n  }\n\n  return undefined;\n}\n\n/**\n * Builds a JSON-safe failed run for errors that happen before a harness can return.\n *\n * @param input - Original input passed to the harness.\n * @param error - Error thrown by setup or execution.\n * @param options - Optional artifacts to preserve on the failed run.\n */\nexport function createFailedHarnessRun(\n  input: unknown,\n  error: unknown,\n  options: { artifacts?: Record<string, JsonValue> } = {},\n): HarnessRun {\n  const artifacts = options.artifacts;\n\n  return {\n    session: {\n      events: [\n        {\n          type: \"message\",\n          role: \"user\",\n          content: normalizeContent(input),\n        },\n      ],\n    },\n    usage: {},\n    ...(artifacts && Object.keys(artifacts).length > 0 ? { artifacts } : {}),\n    errors: [serializeError(error)],\n  };\n}\n\nfunction normalizeMergedArtifacts(\n  contextArtifacts: Record<string, JsonValue> | undefined,\n  resultArtifacts: Record<string, unknown> | undefined,\n) {\n  const artifacts = {\n    ...(contextArtifacts ?? {}),\n    ...(resultArtifacts ? normalizeRecord(resultArtifacts) : {}),\n  };\n\n  return Object.keys(artifacts).length > 0 ? artifacts : undefined;\n}\n\nfunction normalizeSimpleErrors(\n  errors: unknown[] | undefined,\n): Array<Record<string, JsonValue>> {\n  return (errors ?? []).map((error) => {\n    const normalized = toJsonValue(error);\n\n    if (\n      normalized &&\n      typeof normalized === \"object\" &&\n      !Array.isArray(normalized) &&\n      Object.keys(normalized).length > 0\n    ) {\n      return normalized;\n    }\n\n    return serializeError(error);\n  });\n}\n\nfunction normalizeSimpleTraces(\n  traces: SimpleTraceRecord[] | undefined,\n): NormalizedTrace[] | undefined {\n  if (!Array.isArray(traces)) {\n    return undefined;\n  }\n\n  const normalized = traces\n    .map(normalizeSimpleTrace)\n    .filter((trace): trace is NormalizedTrace => Boolean(trace));\n\n  return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeSimpleTrace(trace: unknown): NormalizedTrace | undefined {\n  if (!isJsonRecord(trace)) {\n    return undefined;\n  }\n\n  const {\n    metadata: rawMetadata,\n    spans: rawSpans,\n    ...traceFields\n  } = trace as Partial<SimpleTraceRecord>;\n  const spans = (Array.isArray(rawSpans) ? rawSpans : [])\n    .map((span) => normalizeSimpleSpan(span))\n    .filter((span): span is NormalizedSpan => Boolean(span));\n  const metadata = isJsonRecord(rawMetadata)\n    ? normalizeMetadata(rawMetadata)\n    : undefined;\n\n  if (spans.length === 0 && !traceFields.id && !traceFields.name) {\n    return undefined;\n  }\n\n  return {\n    ...traceFields,\n    ...(metadata ? { metadata } : {}),\n    spans,\n  };\n}\n\nfunction normalizeSimpleSpan(span: unknown): NormalizedSpan | undefined {\n  if (!isJsonRecord(span) || typeof span.name !== \"string\" || !span.name) {\n    return undefined;\n  }\n\n  const {\n    attributes: rawAttributes,\n    error: rawError,\n    events: rawEvents,\n    ...spanFields\n  } = span as Partial<SimpleSpanRecord> & { name: string };\n  const attributes = rawAttributes\n    ? isJsonRecord(rawAttributes)\n      ? normalizeMetadata(rawAttributes)\n      : undefined\n    : undefined;\n  const error = normalizeSpanError(rawError);\n  const events = normalizeSimpleSpanEvents(rawEvents);\n\n  return {\n    ...spanFields,\n    ...(attributes\n      ? { attributes: attributes as NormalizedSpanAttributes }\n      : {}),\n    ...(error ? { error } : {}),\n    ...(events ? { events } : {}),\n  };\n}\n\nfunction normalizeSimpleSpanEvents(\n  events: unknown,\n): NormalizedSpanEvent[] | undefined {\n  if (!Array.isArray(events)) {\n    return undefined;\n  }\n\n  const normalized = events\n    .map(normalizeSimpleSpanEvent)\n    .filter((event): event is NormalizedSpanEvent => Boolean(event));\n\n  return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeSimpleSpanEvent(\n  event: unknown,\n): NormalizedSpanEvent | undefined {\n  if (!isJsonRecord(event) || typeof event.name !== \"string\" || !event.name) {\n    return undefined;\n  }\n\n  const { attributes: rawAttributes, ...eventFields } =\n    event as Partial<SimpleSpanEvent> & { name: string };\n  const attributes = rawAttributes\n    ? isJsonRecord(rawAttributes)\n      ? normalizeMetadata(rawAttributes)\n      : undefined\n    : undefined;\n\n  return {\n    ...eventFields,\n    ...(attributes\n      ? { attributes: attributes as NormalizedSpanAttributes }\n      : {}),\n  };\n}\n\n/** Normalizes arbitrary span errors while preserving object-shaped messages. */\nexport function normalizeSpanError(\n  error: unknown,\n): NormalizedSpan[\"error\"] | undefined {\n  if (error === undefined) {\n    return undefined;\n  }\n\n  if (error instanceof Error) {\n    const details = normalizeMetadata(\n      error as unknown as Record<string, unknown>,\n    );\n\n    return {\n      ...(details ?? {}),\n      type: error.name,\n      message: error.message,\n    };\n  }\n\n  if (\n    error &&\n    typeof error === \"object\" &&\n    !Array.isArray(error) &&\n    typeof (error as { message?: unknown }).message === \"string\"\n  ) {\n    const normalized = normalizeMetadata(error as Record<string, unknown>);\n    const { message, type, ...details } = normalized ?? {};\n\n    return {\n      ...details,\n      message: message as string,\n      ...(typeof type === \"string\" ? { type } : {}),\n    };\n  }\n\n  const serialized = serializeError(error);\n  const { message, type, ...details } = serialized;\n\n  return {\n    ...details,\n    message: typeof message === \"string\" ? message : String(message),\n    ...(typeof type === \"string\" ? { type } : {}),\n  };\n}\n\n/** Normalizes raw span attributes into the JSON-safe span attribute shape. */\nexport function normalizeSpanAttributes(\n  attributes: Record<string, unknown>,\n): NormalizedSpanAttributes | undefined {\n  return normalizeMetadata(attributes) as NormalizedSpanAttributes | undefined;\n}\n\n/** Builds common OpenTelemetry GenAI usage attributes from a usage summary. */\nexport function createGenAiUsageAttributes(\n  usage: UsageSummary | undefined,\n  options: { provider?: string } = {},\n) {\n  return {\n    \"gen_ai.provider.name\": usage?.provider ?? options.provider,\n    \"gen_ai.request.model\": usage?.model,\n    \"gen_ai.response.model\": usage?.model,\n    \"gen_ai.usage.input_tokens\": usage?.inputTokens,\n    \"gen_ai.usage.output_tokens\": usage?.outputTokens,\n    \"gen_ai.usage.reasoning.output_tokens\": usage?.reasoningTokens,\n  } satisfies Record<string, unknown>;\n}\n\n/**\n * Attaches a fallback run trace when a harness result does not already contain spans.\n *\n * This keeps custom harnesses inspectable while first-party harness packages\n * remain free to attach richer native traces.\n */\nexport function ensureRunTrace(\n  run: HarnessRun,\n  options: EnsureRunTraceOptions,\n): NormalizedTrace | undefined {\n  if (spans(run).length > 0) {\n    return undefined;\n  }\n\n  const traceId = options.id ?? createGeneratedTraceId();\n  const rootSpanId = `${traceId}:run`;\n  const durationMs = options.finishedAt.getTime() - options.startedAt.getTime();\n  const rootError =\n    run.errors.length > 0 ? normalizeSpanError(run.errors[0]) : undefined;\n  const runSpan: NormalizedSpan = {\n    id: rootSpanId,\n    traceId,\n    name: options.name,\n    kind: \"run\",\n    startedAt: options.startedAt.toISOString(),\n    finishedAt: options.finishedAt.toISOString(),\n    durationMs,\n    status: rootError ? \"error\" : \"ok\",\n    ...(rootError ? { error: rootError } : {}),\n    attributes: normalizeSpanAttributes({\n      \"gen_ai.operation.name\": options.operationName ?? \"invoke_workflow\",\n      \"gen_ai.workflow.name\": options.name,\n      ...createGenAiUsageAttributes(run.usage),\n    }),\n  };\n  const trace: NormalizedTrace = {\n    id: traceId,\n    name: options.name,\n    startedAt: options.startedAt.toISOString(),\n    finishedAt: options.finishedAt.toISOString(),\n    durationMs,\n    ...(options.source ? { metadata: { source: options.source } } : {}),\n    spans: [runSpan],\n  };\n\n  run.traces = [trace];\n  return trace;\n}\n\nlet nextGeneratedTraceId = 0;\n\nfunction createGeneratedTraceId() {\n  nextGeneratedTraceId += 1;\n  return `trace_${nextGeneratedTraceId}`;\n}\n\n/**\n * Attaches a partial or complete harness run to an arbitrary thrown error.\n *\n * @param error - Thrown value to wrap.\n * @param run - Partial or complete normalized harness run to preserve.\n *\n * @example\n * ```ts\n * try {\n *   return await runAgent(input);\n * } catch (error) {\n *   throw attachHarnessRunToError(error, partialRun);\n * }\n * ```\n */\nexport function attachHarnessRunToError(\n  error: unknown,\n  run: HarnessRun,\n): HarnessRunError {\n  const baseError =\n    error instanceof Error\n      ? error\n      : new Error(String(error ?? \"Unknown error\"));\n  return Object.assign(baseError, {\n    vitestEvalsRun: run,\n  });\n}\n\n/**\n * Reads an attached harness run back off a previously wrapped error value.\n *\n * @param error - Unknown thrown value that may contain a harness run.\n *\n * @example\n * ```ts\n * const partialRun = getHarnessRunFromError(error);\n *\n * if (partialRun) {\n *   console.log(toolCalls(partialRun.session));\n * }\n * ```\n */\nexport function getHarnessRunFromError(error: unknown): HarnessRun | undefined {\n  if (\n    error &&\n    typeof error === \"object\" &&\n    \"vitestEvalsRun\" in error &&\n    isHarnessRun((error as { vitestEvalsRun?: unknown }).vitestEvalsRun)\n  ) {\n    return (error as { vitestEvalsRun: HarnessRun }).vitestEvalsRun;\n  }\n\n  return undefined;\n}\n\n/** Returns true when a value matches the normalized `HarnessRun` contract. */\nexport function isHarnessRun(value: unknown): value is HarnessRun {\n  if (!value || typeof value !== \"object\") {\n    return false;\n  }\n\n  const candidate = value as {\n    session?: unknown;\n    usage?: unknown;\n    errors?: unknown;\n  };\n\n  return (\n    isNormalizedSession(candidate.session) &&\n    Boolean(candidate.usage) &&\n    typeof candidate.usage === \"object\" &&\n    !Array.isArray(candidate.usage) &&\n    Array.isArray(candidate.errors)\n  );\n}\n\n/** Returns true when a value matches the normalized session contract. */\nexport function isNormalizedSession(\n  value: unknown,\n): value is NormalizedSession {\n  return NormalizedSessionSchema.safeParse(value).success;\n}\n\n/** Reuses pre-normalized harness errors when a runtime already returns them. */\nexport function resolveHarnessRunErrors(\n  result: unknown,\n): Array<Record<string, JsonValue>> {\n  if (\n    result &&\n    typeof result === \"object\" &&\n    Array.isArray((result as Record<string, unknown>).errors)\n  ) {\n    return (result as { errors: Array<Record<string, JsonValue>> }).errors;\n  }\n\n  return [];\n}\n\n/** Serializes an arbitrary thrown value into the normalized error shape. */\nexport function serializeError(error: unknown): Record<string, JsonValue> {\n  if (error instanceof Error) {\n    return {\n      type: error.name,\n      message: error.message,\n    };\n  }\n\n  return {\n    type: \"Error\",\n    message: String(error),\n  };\n}\n","import {\n  createHarness,\n  type Harness,\n  type HarnessContext,\n  type HarnessResultLike,\n  type HarnessRun,\n  isHarnessRun,\n  latestAssistantMessageContent,\n  type JsonValue,\n  type MaybePromise,\n  normalizeContent,\n} from \"../harness\";\n\n/**\n * Provider-neutral prompt request issued by an LLM-backed judge.\n *\n * @example\n * ```ts\n * const input: JudgeHarnessInput = {\n *   system: \"Grade factual consistency.\",\n *   prompt: \"Compare the submitted answer with the reference answer.\",\n *   responseFormat: {\n *     type: \"json\",\n *   },\n * };\n * ```\n */\nexport type JudgeHarnessInput = {\n  /** Optional system prompt for the judge model. */\n  system?: string;\n  /** User prompt or instruction payload for the judge model. */\n  prompt: string;\n  /** Optional response-format hint for adapters that support structured output. */\n  responseFormat?: {\n    /** Requests a JSON-compatible response. */\n    type: \"json\";\n    /** Optional JSON Schema passed through to provider-specific adapters. */\n    schema?: JsonValue;\n  };\n};\n\n/** JSON-safe output returned by a judge harness. */\nexport type JudgeHarnessOutput = JsonValue | undefined;\n\n/**\n * Harness used by LLM-backed judges to issue judge-side prompts.\n *\n * This is separate from the application harness under test.\n *\n * @example\n * ```ts\n * const judgeHarness: JudgeHarness = createJudgeHarness({\n *   name: \"judge-model\",\n *   run: async ({ prompt }, { signal }) => {\n *     return callJudgeModel({ prompt, signal });\n *   },\n * });\n * ```\n */\nexport type JudgeHarness = Harness<JudgeHarnessInput, JudgeHarnessOutput>;\n\n/** Runtime options supplied when a judge calls `runJudge(...)`. */\nexport type RunJudgeOptions = {\n  /** Abort signal from the current eval run when available. */\n  signal?: AbortSignal;\n};\n\n/**\n * Curried judge-harness runner available inside `JudgeContext`.\n *\n * @example\n * ```ts\n * const verdict = await ctx.runJudge?.({\n *   prompt: \"Return a JSON verdict.\",\n *   responseFormat: { type: \"json\" },\n * });\n * ```\n */\nexport type RunJudge = (\n  input: JudgeHarnessInput,\n  options?: RunJudgeOptions,\n) => Promise<JudgeHarnessOutput>;\n\n/** Runtime options passed to `createJudgeHarness(...)` callbacks. */\nexport type CreateJudgeHarnessRunOptions = {\n  /** Abort signal from the current eval run when available. */\n  signal?: AbortSignal;\n};\n\n/**\n * Configuration for `createJudgeHarness(...)`.\n *\n * @example\n * ```ts\n * const judgeHarness = createJudgeHarness({\n *   name: \"custom-judge\",\n *   run: async ({ system, prompt }, { signal }) => {\n *     return callProvider({ system, prompt, signal });\n *   },\n * });\n * ```\n */\nexport type CreateJudgeHarnessOptions = {\n  /** Stable harness name used in diagnostics. */\n  name?: string;\n  /**\n   * Runs one provider-specific judge prompt.\n   *\n   * Return a JSON-safe value, a raw provider value to normalize, a lightweight\n   * `{ output }` result, or a full normalized `HarnessRun`.\n   */\n  run: (\n    input: JudgeHarnessInput,\n    options: CreateJudgeHarnessRunOptions,\n  ) => MaybePromise<unknown>;\n};\n\n/**\n * Creates a judge harness from a provider-specific prompt callback.\n *\n * @param options - Harness name plus the callback that issues the judge prompt.\n *\n * @example\n * ```ts\n * const judgeHarness = createJudgeHarness({\n *   run: async ({ prompt }) => callJudgeModel(prompt),\n * });\n * ```\n */\nexport function createJudgeHarness(\n  options: CreateJudgeHarnessOptions,\n): JudgeHarness {\n  return createHarness({\n    name: options.name ?? \"judge-harness\",\n    run: async ({ input, signal }) => {\n      return normalizeJudgeHarnessResult(\n        input,\n        await options.run(input, { signal }),\n      );\n    },\n  });\n}\n\n/**\n * Runs a judge harness with eval-scoped context already supplied.\n *\n * @param judgeHarness - Judge-side harness configured on the matcher, judge, or suite.\n * @param input - Provider-neutral judge prompt request.\n * @param options - Run-scoped abort signal.\n */\nexport async function runJudgeHarness(\n  judgeHarness: JudgeHarness,\n  input: JudgeHarnessInput,\n  options: RunJudgeOptions = {},\n): Promise<JudgeHarnessOutput> {\n  const artifacts: HarnessContext[\"artifacts\"] = {};\n  const run = await judgeHarness.run(input, {\n    signal: options.signal,\n    artifacts,\n    setArtifact: (name, value) => {\n      artifacts[name] = value;\n    },\n  });\n\n  return run.output !== undefined\n    ? run.output\n    : resolveJudgeHarnessAssistantOutput(run);\n}\n\n/** Binds a judge harness to the current eval run context. */\nexport function createRunJudge(\n  judgeHarness: JudgeHarness | undefined,\n  signal?: AbortSignal,\n): RunJudge | undefined {\n  if (!judgeHarness) {\n    return undefined;\n  }\n\n  return (input, options) =>\n    runJudgeHarness(judgeHarness, input, {\n      signal: options?.signal ?? signal,\n    });\n}\n\nfunction normalizeJudgeHarnessResult(\n  input: JudgeHarnessInput,\n  result: Awaited<ReturnType<CreateJudgeHarnessOptions[\"run\"]>>,\n): HarnessResultLike<JudgeHarnessOutput> {\n  if (isHarnessRun(result)) {\n    return result as HarnessRun<JudgeHarnessOutput>;\n  }\n\n  const output = hasOutputField(result)\n    ? normalizeJudgeHarnessOutput(result.output)\n    : normalizeJudgeHarnessOutput(result);\n\n  return {\n    output,\n    messages: createJudgeHarnessMessages(input, output),\n  };\n}\n\nfunction hasOutputField(value: unknown): value is { output?: unknown } {\n  return (\n    value !== null &&\n    typeof value === \"object\" &&\n    !Array.isArray(value) &&\n    Object.keys(value).length === 1 &&\n    \"output\" in value\n  );\n}\n\nfunction normalizeJudgeHarnessOutput(value: unknown): JudgeHarnessOutput {\n  if (value === undefined) {\n    return undefined;\n  }\n\n  return normalizeContent(value);\n}\n\nfunction createJudgeHarnessMessages(\n  input: JudgeHarnessInput,\n  output: JudgeHarnessOutput,\n) {\n  return [\n    ...(input.system\n      ? [{ role: \"system\" as const, content: input.system }]\n      : []),\n    { role: \"user\" as const, content: input.prompt },\n    ...(output !== undefined\n      ? [{ role: \"assistant\" as const, content: output }]\n      : []),\n  ];\n}\n\nfunction resolveJudgeHarnessAssistantOutput(\n  run: HarnessRun<JudgeHarnessOutput>,\n): JudgeHarnessOutput {\n  return latestAssistantMessageContent(run.session) ?? \"\";\n}\n","import { type Harness, latestAssistantMessageContent } from \"../harness\";\nimport type { JsonValue } from \"../harness\";\nimport { createRunJudge } from \"./judgeHarness\";\nimport type { JudgeHarness } from \"./judgeHarness\";\nimport type { Judge, JudgeContext, JudgeResult } from \"./types\";\n\n/**\n * Rubric choice returned by a factuality judge model call.\n *\n * @example\n * ```ts\n * import type { FactualityJudgeChoice } from \"vitest-evals\";\n *\n * const choice: FactualityJudgeChoice = \"C\";\n * ```\n */\nexport type FactualityJudgeChoice = \"A\" | \"B\" | \"C\" | \"D\" | \"E\";\n\n/**\n * Prompt payload sent to the configured judge harness.\n *\n * @example\n * ```ts\n * import type { FactualityJudgePrompt } from \"vitest-evals\";\n *\n * const payload: FactualityJudgePrompt = {\n *   system: \"Grade factual consistency.\",\n *   prompt: \"Compare these answers.\",\n * };\n * ```\n */\nexport type FactualityJudgePrompt = {\n  /** System prompt for the judge model. */\n  system: string;\n  /** User prompt containing the question, expert answer, submitted answer, and rubric. */\n  prompt: string;\n};\n\n/**\n * Parsed verdict returned by a factuality judge model call.\n *\n * @example\n * ```ts\n * import type { FactualityJudgeVerdict } from \"vitest-evals\";\n *\n * const verdict: FactualityJudgeVerdict = {\n *   choice: \"C\",\n *   rationale: \"The submitted answer matches the expert answer.\",\n * };\n * ```\n */\nexport type FactualityJudgeVerdict = {\n  /** Rubric choice selected by the judge model. */\n  choice: FactualityJudgeChoice;\n  /** Human-readable explanation for the selected choice. */\n  rationale: string;\n};\n\nconst FACTUALITY_CHOICE_SCORES: Record<FactualityJudgeChoice, number> = {\n  A: 0.4,\n  B: 0.6,\n  C: 1,\n  D: 0,\n  E: 1,\n};\n\nconst FACTUALITY_SYSTEM =\n  \"You are comparing factual content. Ignore differences in style, grammar, punctuation, and formatting.\";\n\nconst FACTUALITY_RESPONSE_SCHEMA = {\n  type: \"object\",\n  additionalProperties: false,\n  required: [\"choice\", \"rationale\"],\n  properties: {\n    choice: {\n      enum: [\"A\", \"B\", \"C\", \"D\", \"E\"],\n    },\n    rationale: {\n      type: \"string\",\n    },\n  },\n} as const satisfies JsonValue;\n\n/**\n * Expert answer or reference facts accepted by `FactualityJudge()`.\n *\n * @example\n * ```ts\n * import type { FactualityJudgeExpected } from \"vitest-evals\";\n *\n * const expected: FactualityJudgeExpected =\n *   \"Paris is the capital of France.\";\n * ```\n */\nexport type FactualityJudgeExpected = JsonValue;\n\n/**\n * Configuration for the factuality judge.\n *\n * The judge harness can be supplied here, by `describeEval({ judgeHarness })`,\n * or by `expect(...).toSatisfyJudge(..., { judgeHarness })`. Passing it here\n * keeps the judge self-contained while preserving provider neutrality.\n *\n * @example\n * ```ts\n * import { FactualityJudge, type JudgeHarness } from \"vitest-evals\";\n *\n * declare const judgeHarness: JudgeHarness;\n *\n * const judge = FactualityJudge({ name: \"FactJudge\", judgeHarness });\n * ```\n */\nexport type FactualityJudgeConfig = {\n  /** Stable judge name used in assertion messages and reports. */\n  name?: string;\n  /** Default judge-side harness used when matcher options do not provide one. */\n  judgeHarness?: JudgeHarness;\n  /** Expert answer or reference facts used by this judge instance. */\n  expected?: FactualityJudgeExpected;\n};\n\n/**\n * Matcher context accepted by `FactualityJudge()`.\n *\n * @example\n * ```ts\n * import { aiSdkJudgeHarness } from \"@vitest-evals/harness-ai-sdk\";\n * import { openai } from \"@ai-sdk/openai\";\n * import { expect } from \"vitest\";\n * import { FactualityJudge } from \"vitest-evals\";\n *\n * const judgeHarness = aiSdkJudgeHarness({\n *   model: openai(\"gpt-4.1-mini\"),\n * });\n *\n * await expect(result).toSatisfyJudge(FactualityJudge(), {\n *   expected: \"Paris is the capital of France.\",\n *   judgeHarness,\n * });\n * ```\n */\nexport type FactualityJudgeOptions<\n  TInput = any,\n  TOutput extends JsonValue | undefined = any,\n  THarness extends Harness<TInput, TOutput> | undefined = any,\n> = JudgeContext<TInput, TOutput, THarness> & {\n  /** Expert answer or reference facts. Overrides the judge config default. */\n  expected?: FactualityJudgeExpected;\n};\n\n/**\n * Creates a factuality judge over normalized harness output.\n *\n * `FactualityJudge()` compares `input`, `output`, and an expert answer. Bind a\n * suite-wide expert answer on the judge config, or pass a case-specific\n * `expected` value to `toSatisfyJudge(...)`. Configure the LLM used for grading\n * with `judgeHarness` on the judge, suite, or matcher options.\n *\n * @param config - Optional judge name and reusable judge harness default.\n *\n * @example\n * ```ts\n * import { anthropic } from \"@ai-sdk/anthropic\";\n * import { aiSdkJudgeHarness } from \"@vitest-evals/harness-ai-sdk\";\n * import { describeEval, FactualityJudge } from \"vitest-evals\";\n * import { qaHarness } from \"./qaHarness\";\n *\n * const judgeHarness = aiSdkJudgeHarness({\n *   model: anthropic(\"claude-sonnet-4-5\"),\n *   temperature: 0,\n * });\n * const factualityJudge = FactualityJudge({\n *   judgeHarness,\n *   expected: \"Paris is the capital of France.\",\n * });\n *\n * describeEval(\"qa agent\", {\n *   harness: qaHarness,\n *   judges: [factualityJudge],\n * }, (it) => {\n *   it(\"answers a geography question\", async ({ run }) => {\n *     await run(\"What is the capital of France?\");\n *   });\n * });\n * ```\n */\nexport function FactualityJudge(\n  config: FactualityJudgeConfig = {},\n): Judge<FactualityJudgeOptions> {\n  const judgeHarness = config.judgeHarness;\n\n  return {\n    name: config.name ?? \"FactualityJudge\",\n    judgeHarness,\n    assess: (opts) =>\n      assessFactuality(opts, {\n        expected: config.expected,\n        judgeHarness,\n      }),\n  };\n}\n\nasync function assessFactuality(\n  opts: FactualityJudgeOptions,\n  config: {\n    expected: FactualityJudgeExpected | undefined;\n    judgeHarness: JudgeHarness | undefined;\n  },\n) {\n  const expected = opts.expected ?? config.expected;\n\n  if (isMissingExpectedAnswer(expected)) {\n    return {\n      score: 0,\n      metadata: {\n        rationale:\n          \"FactualityJudge requires a non-empty expert answer in `expected` or FactualityJudge(...) config.\",\n      },\n    };\n  }\n\n  const runJudge =\n    opts.runJudge ??\n    createRunJudge(\n      config.judgeHarness,\n      (opts as { signal?: AbortSignal }).signal,\n    );\n\n  if (!runJudge) {\n    throw new Error(\n      \"FactualityJudge requires a judgeHarness in FactualityJudge(...) config, describeEval(...) options, toSatisfyJudge(...) options, or JudgeContext.runJudge.\",\n    );\n  }\n\n  const verdict = await runJudge({\n    system: FACTUALITY_SYSTEM,\n    prompt: formatFactualityPrompt({\n      input: opts.input,\n      expected,\n      output: resolveJudgeOutput(opts),\n    }),\n    responseFormat: {\n      type: \"json\",\n      schema: FACTUALITY_RESPONSE_SCHEMA,\n    },\n  });\n\n  return formatJudgeResult(parseFactualityJudgeVerdict(verdict));\n}\n\nfunction isMissingExpectedAnswer(value: FactualityJudgeExpected | undefined) {\n  return (\n    value == null || (typeof value === \"string\" && value.trim().length === 0)\n  );\n}\n\nfunction resolveJudgeOutput(opts: FactualityJudgeOptions) {\n  if (opts.output !== undefined) {\n    return opts.output;\n  }\n\n  return latestAssistantMessageContent(opts.session) ?? \"\";\n}\n\nfunction parseFactualityJudgeVerdict(value: unknown): FactualityJudgeVerdict {\n  const parsed = typeof value === \"string\" ? parseJsonObject(value) : value;\n\n  if (!parsed || typeof parsed !== \"object\") {\n    throw new Error(\n      \"FactualityJudge judgeHarness must return an object with `choice` and `rationale`.\",\n    );\n  }\n\n  const verdict = parsed as Record<string, unknown>;\n  if (!isFactualityChoice(verdict.choice)) {\n    throw new Error(\n      \"FactualityJudge judgeHarness must return choice A, B, C, D, or E.\",\n    );\n  }\n\n  if (typeof verdict.rationale !== \"string\") {\n    throw new Error(\n      \"FactualityJudge judgeHarness must return a string `rationale`.\",\n    );\n  }\n\n  return {\n    choice: verdict.choice,\n    rationale: verdict.rationale,\n  };\n}\n\nfunction parseJsonObject(value: string) {\n  try {\n    return JSON.parse(value);\n  } catch {\n    const fencedJson = value.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/i);\n    if (!fencedJson) {\n      throw new Error(\n        \"FactualityJudge judgeHarness must return JSON with `choice` and `rationale`.\",\n      );\n    }\n\n    return JSON.parse(fencedJson[1]);\n  }\n}\n\nfunction isFactualityChoice(value: unknown): value is FactualityJudgeChoice {\n  return (\n    value === \"A\" ||\n    value === \"B\" ||\n    value === \"C\" ||\n    value === \"D\" ||\n    value === \"E\"\n  );\n}\n\nfunction formatFactualityPrompt({\n  input,\n  expected,\n  output,\n}: {\n  input: unknown;\n  expected: unknown;\n  output: unknown;\n}) {\n  const comparison = formatJudgeValue({\n    question: input ?? \"\",\n    expert_answer: expected,\n    submitted_answer: output ?? \"\",\n  });\n\n  return `Compare the submitted answer with the expert answer.\n\nComparison payload:\n${comparison}\n\nSelect exactly one option:\nA: The submission is a fully consistent subset of the expert answer.\nB: The submission is a fully consistent superset of the expert answer.\nC: The submission contains the same factual details as the expert answer.\nD: The submission disagrees with the expert answer.\nE: The answers differ only in ways that do not affect factuality.\n\nReturn JSON with exactly these fields:\n{\n  \"choice\": \"C\",\n  \"rationale\": \"Brief explanation for the selected choice\"\n}\n\nThe choice value must be one of A, B, C, D, or E.`;\n}\n\nfunction formatJudgeValue(value: unknown) {\n  if (typeof value === \"string\") {\n    return value;\n  }\n\n  if (value === undefined) {\n    return \"\";\n  }\n\n  try {\n    return JSON.stringify(value, null, 2) ?? String(value);\n  } catch {\n    return String(value);\n  }\n}\n\nfunction formatJudgeResult(object: FactualityJudgeVerdict): JudgeResult {\n  return {\n    score: FACTUALITY_CHOICE_SCORES[object.choice],\n    metadata: {\n      rationale: object.rationale,\n      choice: object.choice,\n    },\n  };\n}\n","/**\n * Shared configuration for built-in value matchers.\n *\n * @example\n * ```ts\n * const config: BaseMatcherConfig = {\n *   requireAll: true,\n *   allowExtras: false,\n * };\n * ```\n */\nexport interface BaseMatcherConfig {\n  /** Require every expected field or tool to match. */\n  requireAll?: boolean;\n  /** Allow actual output/tool calls to contain extra fields or calls. */\n  allowExtras?: boolean;\n  /** Emit matcher debug details to the console. */\n  debug?: boolean;\n}\n\n/**\n * Matching strategy used by structured-output and tool-call judges.\n *\n * @example\n * ```ts\n * const exact: MatchStrategy = \"strict\";\n * const custom: MatchStrategy = (expected, actual) =>\n *   String(actual).includes(String(expected));\n * ```\n */\nexport type MatchStrategy<T = unknown> =\n  | \"strict\"\n  | \"fuzzy\"\n  | ((expected: T, actual: T, context?: string) => boolean);\n\n/**\n * Options controlling fuzzy matcher behavior.\n *\n * @example\n * ```ts\n * const fuzzyOptions: FuzzyMatchOptions = {\n *   caseInsensitive: true,\n *   substring: true,\n *   numericTolerance: 0.01,\n * };\n * ```\n */\nexport interface FuzzyMatchOptions {\n  /** Compare strings without case sensitivity. */\n  caseInsensitive?: boolean;\n  /** Treat either string containing the other as a match. */\n  substring?: boolean;\n  /** Relative and absolute tolerance used for numeric comparisons. */\n  numericTolerance?: number;\n  /** Match arrays without requiring the same order. */\n  ignoreArrayOrder?: boolean;\n  /** Allow simple string/number/boolean coercions before failing. */\n  coerceTypes?: boolean;\n}\n\ntype Mismatch = {\n  key: string;\n  expected: unknown;\n  actual: unknown;\n};\n\n/** Debug logger interface accepted by matcher helpers. */\nexport interface Logger {\n  log: (message: string, ...args: unknown[]) => void;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Compares two values with strict deep equality semantics. */\nexport function strictEquals(\n  expected: unknown,\n  actual: unknown,\n  context?: string,\n): boolean {\n  void context;\n\n  if (expected === actual) {\n    return true;\n  }\n\n  if (\n    expected === null ||\n    expected === undefined ||\n    actual === null ||\n    actual === undefined\n  ) {\n    return false;\n  }\n\n  if (typeof expected !== typeof actual) {\n    return false;\n  }\n\n  if (Array.isArray(expected)) {\n    return (\n      Array.isArray(actual) &&\n      expected.length === actual.length &&\n      expected.every((item, index) =>\n        strictEquals(item, actual[index], context),\n      )\n    );\n  }\n\n  if (isRecord(expected) && isRecord(actual)) {\n    const expectedKeys = Object.keys(expected);\n    const actualKeys = Object.keys(actual);\n\n    return (\n      expectedKeys.length === actualKeys.length &&\n      expectedKeys.every(\n        (key) =>\n          key in actual && strictEquals(expected[key], actual[key], context),\n      )\n    );\n  }\n\n  return false;\n}\n\nfunction fuzzyMatchString(\n  expected: string,\n  actual: string,\n  options: FuzzyMatchOptions,\n): boolean {\n  const { caseInsensitive = true, substring = false } = options;\n  const expectedText = caseInsensitive ? expected.toLowerCase() : expected;\n  const actualText = caseInsensitive ? actual.toLowerCase() : actual;\n\n  return substring\n    ? actualText.includes(expectedText) || expectedText.includes(actualText)\n    : expectedText === actualText;\n}\n\nfunction fuzzyMatchNumber(\n  expected: number,\n  actual: number,\n  options: FuzzyMatchOptions,\n): boolean {\n  const { numericTolerance = 0.001 } = options;\n  const tolerance = Math.max(\n    Math.abs(expected) * numericTolerance,\n    numericTolerance,\n  );\n\n  return Math.abs(expected - actual) <= tolerance;\n}\n\nfunction fuzzyMatchArray(\n  expected: unknown[],\n  actual: unknown[],\n  options: FuzzyMatchOptions,\n  context?: string,\n): boolean {\n  const { ignoreArrayOrder = true } = options;\n\n  if (!ignoreArrayOrder) {\n    return (\n      expected.length === actual.length &&\n      expected.every((item, index) =>\n        fuzzyMatch(item, actual[index], options, context),\n      )\n    );\n  }\n\n  const actualUsed = actual.map(() => false);\n  return expected.every((expectedItem) => {\n    for (const [index, actualItem] of actual.entries()) {\n      if (actualUsed[index]) {\n        continue;\n      }\n\n      if (fuzzyMatch(expectedItem, actualItem, options, context)) {\n        actualUsed[index] = true;\n        return true;\n      }\n    }\n\n    return false;\n  });\n}\n\nfunction fuzzyMatchObject(\n  expected: Record<string, unknown>,\n  actual: Record<string, unknown>,\n  options: FuzzyMatchOptions,\n  context?: string,\n): boolean {\n  return Object.entries(expected).every(\n    ([key, value]) =>\n      key in actual && fuzzyMatch(value, actual[key], options, context),\n  );\n}\n\nfunction fuzzyMatchWithCoercion(expected: unknown, actual: unknown): boolean {\n  if (typeof expected === \"boolean\" && typeof actual === \"string\") {\n    return expected === (actual.toLowerCase() === \"true\" || actual === \"1\");\n  }\n\n  if (typeof expected === \"string\" && typeof actual === \"number\") {\n    return Number.parseFloat(expected) === actual;\n  }\n\n  if (typeof expected === \"number\" && typeof actual === \"string\") {\n    return expected === Number.parseFloat(actual);\n  }\n\n  return false;\n}\n\n/** Compares two values with the configured fuzzy matching rules. */\nexport function fuzzyMatch(\n  expected: unknown,\n  actual: unknown,\n  options: FuzzyMatchOptions = {},\n  context?: string,\n): boolean {\n  const { coerceTypes = false } = options;\n\n  if (expected instanceof RegExp) {\n    return typeof actual === \"string\" && expected.test(actual);\n  }\n\n  if (typeof expected === \"function\") {\n    return Boolean((expected as (value: unknown) => unknown)(actual));\n  }\n\n  if (\n    expected === null ||\n    expected === undefined ||\n    actual === null ||\n    actual === undefined\n  ) {\n    return expected === actual;\n  }\n\n  if (typeof expected === \"string\" && typeof actual === \"string\") {\n    return fuzzyMatchString(expected, actual, options);\n  }\n\n  if (typeof expected === \"number\" && typeof actual === \"number\") {\n    return fuzzyMatchNumber(expected, actual, options);\n  }\n\n  if (Array.isArray(expected) && Array.isArray(actual)) {\n    return fuzzyMatchArray(expected, actual, options, context);\n  }\n\n  if (isRecord(expected) && isRecord(actual)) {\n    return fuzzyMatchObject(expected, actual, options, context);\n  }\n\n  if (coerceTypes && fuzzyMatchWithCoercion(expected, actual)) {\n    return true;\n  }\n\n  return expected === actual;\n}\n\n/** Builds a reusable matcher function from a strict, fuzzy, or custom strategy. */\nexport function createMatcher<T = unknown>(\n  strategy: MatchStrategy<T>,\n  options?: FuzzyMatchOptions,\n): (expected: T, actual: T, context?: string) => boolean {\n  if (typeof strategy === \"function\") {\n    return (expected, actual, context) => strategy(expected, actual, context);\n  }\n\n  if (strategy === \"strict\") {\n    return (expected, actual, context) =>\n      strictEquals(expected, actual, context);\n  }\n\n  return (expected, actual, context) =>\n    fuzzyMatch(expected, actual, options ?? {}, context);\n}\n\n/** Formats a value for scorer rationale and debug output. */\nexport function formatValue(value: unknown): string {\n  if (value === undefined) {\n    return \"undefined\";\n  }\n\n  if (value === null) {\n    return \"null\";\n  }\n\n  if (value instanceof RegExp) {\n    return value.toString();\n  }\n\n  if (typeof value === \"string\") {\n    return `\"${value}\"`;\n  }\n\n  if (typeof value === \"object\") {\n    try {\n      return JSON.stringify(value);\n    } catch {\n      return String(value);\n    }\n  }\n\n  return String(value);\n}\n\n/** Returns a normalized partial-credit score for match-based scorers. */\nexport function calculatePartialScore(\n  matched: number,\n  total: number,\n  requireAll: boolean,\n): number {\n  if (requireAll && matched < total) {\n    return 0;\n  }\n\n  return total > 0 ? matched / total : 1;\n}\n\nconst defaultLogger: Logger = {\n  log: (message: string, ...args: unknown[]) => {\n    if (\n      process.env.NODE_ENV === \"development\" ||\n      process.env.NODE_ENV === \"test\" ||\n      process.env.VITEST_EVALS_DEBUG === \"true\"\n    ) {\n      console.log(message, ...args);\n    }\n  },\n};\n\n/** Emits scorer debug details through the provided logger. */\nexport function debugLog(\n  context: string,\n  data: {\n    expected: unknown;\n    actual: unknown;\n    matches?: string[];\n    mismatches?: Mismatch[];\n    extras?: string[];\n  },\n  logger: Logger = defaultLogger,\n): void {\n  logger.log(`${context} debug:`);\n  logger.log(\"Expected:\", data.expected);\n  logger.log(\"Actual:\", data.actual);\n  if (data.matches) {\n    logger.log(\"Matches:\", data.matches);\n  }\n  if (data.mismatches) {\n    logger.log(\"Mismatches:\", data.mismatches);\n  }\n  if (data.extras) {\n    logger.log(\"Extras:\", data.extras);\n  }\n}\n","import type { BaseScorerOptions, ScoredResult } from \"./scoring\";\nimport {\n  createMatcher,\n  debugLog,\n  formatValue,\n  type BaseMatcherConfig,\n  type FuzzyMatchOptions,\n  type MatchStrategy,\n} from \"./matchers\";\n\nexport interface StructuredOutputScorerOptions extends BaseScorerOptions {\n  /** Expected structured output fields. */\n  expected?: Record<string, unknown>;\n}\n\nexport interface StructuredOutputScorerConfig extends BaseMatcherConfig {\n  /** Field matching strategy used for expected structured output values. */\n  match?: MatchStrategy;\n  /** Output field that indicates an error. Set to `null` to disable. */\n  errorField?: string | null;\n  /** Options used when `match` is `\"fuzzy\"`. */\n  fuzzyOptions?: FuzzyMatchOptions;\n}\n\nfunction formatMismatchDetails(\n  mismatches: Array<{ key: string; expected: unknown; actual: unknown }>,\n): string {\n  return mismatches\n    .map(\n      ({ key, expected, actual }) =>\n        `${key}: expected ${formatValue(expected)}, got ${formatValue(actual)}`,\n    )\n    .join(\"; \");\n}\n\n/** Creates a structured-output scorer used by both harness judges and legacy wrappers. */\nexport function StructuredOutputScorer(\n  config: StructuredOutputScorerConfig = {},\n) {\n  const {\n    match = \"strict\",\n    requireAll = true,\n    allowExtras = true,\n    debug = false,\n    errorField = \"error\",\n    fuzzyOptions = {},\n  } = config;\n\n  const fieldMatcher =\n    typeof match === \"function\" ? match : createMatcher(match, fuzzyOptions);\n\n  const scorer = async (\n    opts: StructuredOutputScorerOptions,\n  ): Promise<ScoredResult> => {\n    const expected = opts.expected ?? {};\n    let parsed: Record<string, unknown>;\n\n    try {\n      parsed = JSON.parse(opts.output) as Record<string, unknown>;\n    } catch (error) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Failed to parse output as JSON: ${error}`,\n          output: opts.output,\n        },\n      };\n    }\n\n    if (Object.keys(expected).length === 0) {\n      return {\n        score: 1,\n        metadata: {\n          rationale: \"Valid JSON output (no expected fields specified)\",\n        },\n      };\n    }\n\n    const errorValue = errorField !== null ? parsed[errorField] : undefined;\n    if (\n      errorField !== null &&\n      errorValue &&\n      errorValue !== \"\" &&\n      errorValue !== null\n    ) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Output contains error: ${String(errorValue)}`,\n          output: opts.output,\n        },\n      };\n    }\n\n    const matches: string[] = [];\n    const mismatches: Array<{\n      key: string;\n      expected: unknown;\n      actual: unknown;\n    }> = [];\n    const extras: string[] = [];\n\n    for (const [key, expectedValue] of Object.entries(expected)) {\n      const actualValue = parsed[key];\n      if (fieldMatcher(expectedValue, actualValue, key)) {\n        matches.push(key);\n      } else {\n        mismatches.push({\n          key,\n          expected: expectedValue,\n          actual: actualValue,\n        });\n      }\n    }\n\n    const expectedKeys = new Set(Object.keys(expected));\n    for (const key of Object.keys(parsed)) {\n      if (!expectedKeys.has(key)) {\n        extras.push(key);\n      }\n    }\n\n    if (debug) {\n      debugLog(\"StructuredOutputScorer\", {\n        expected,\n        actual: parsed,\n        matches,\n        mismatches,\n        extras,\n      });\n    }\n\n    const totalExpected = Object.keys(expected).length;\n    const totalMatched = matches.length;\n\n    if (requireAll && mismatches.length > 0) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Missing required fields: ${mismatches.map((mismatch) => mismatch.key).join(\", \")} - ${formatMismatchDetails(mismatches)}`,\n        },\n      };\n    }\n\n    if (!allowExtras && extras.length > 0) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Unexpected extra fields: ${extras.join(\", \")}`,\n        },\n      };\n    }\n\n    const score = totalExpected > 0 ? totalMatched / totalExpected : 1;\n    if (score === 1) {\n      const extraInfo =\n        extras.length > 0 ? ` (plus extra fields: ${extras.join(\", \")})` : \"\";\n\n      return {\n        score: 1,\n        metadata: {\n          rationale: `All expected fields match${extraInfo}`,\n        },\n      };\n    }\n\n    return {\n      score,\n      metadata: {\n        rationale: `Matched ${totalMatched}/${totalExpected} fields - ${formatMismatchDetails(mismatches)}`,\n        matched: totalMatched,\n        total: totalExpected,\n      },\n    };\n  };\n\n  Object.defineProperty(scorer, \"name\", {\n    value: \"StructuredOutputScorer\",\n  });\n\n  return scorer;\n}\n","import type { Judge, JudgeContext } from \"./types\";\nimport {\n  StructuredOutputScorer,\n  type StructuredOutputScorerConfig,\n  type StructuredOutputScorerOptions,\n} from \"../internal/structuredOutputScorer\";\n\n/**\n * Expected structured fields accepted by `StructuredOutputJudge()`.\n *\n * @example\n * ```ts\n * const expected: StructuredOutputJudgeExpected = {\n *   status: \"approved\",\n *   risk: \"low\",\n * };\n * ```\n */\nexport type StructuredOutputJudgeExpected = Record<string, unknown>;\n\n/**\n * Matcher context accepted by `StructuredOutputJudge()`.\n *\n * @example\n * ```ts\n * await expect(result).toSatisfyJudge(StructuredOutputJudge(), {\n *   expected: { status: \"approved\" },\n * });\n * ```\n */\nexport interface StructuredOutputJudgeOptions\n  extends JudgeContext<any, any, any>,\n    Omit<StructuredOutputScorerOptions, \"input\" | \"output\" | \"toolCalls\"> {\n  expected?: StructuredOutputJudgeExpected;\n}\n\n/**\n * Configuration for the deterministic structured-output judge.\n *\n * @example\n * ```ts\n * const judge = StructuredOutputJudge({\n *   match: \"fuzzy\",\n *   fuzzyOptions: { caseInsensitive: true },\n * });\n * ```\n */\nexport interface StructuredOutputJudgeConfig\n  extends StructuredOutputScorerConfig {\n  /** Expected structured fields used by this judge instance. */\n  expected?: StructuredOutputJudgeExpected;\n}\n\n/**\n * Creates a deterministic judge that compares structured output fields.\n *\n * @param config - Matching behavior shared by every assessment from this judge.\n *\n * @example\n * ```ts\n * describeEval(\"refund agent\", {\n *   harness: refundHarness,\n *   judges: [StructuredOutputJudge({ expected: { status: \"approved\" } })],\n * }, (it) => {\n *   it(\"returns the expected decision\", async ({ run }) => {\n *     await run(\"Refund invoice inv_123\");\n *   });\n * });\n * ```\n */\nexport function StructuredOutputJudge(\n  config: StructuredOutputJudgeConfig = {},\n): Judge<StructuredOutputJudgeOptions> {\n  const { expected, ...scorerConfig } = config;\n  const scorer = StructuredOutputScorer(scorerConfig);\n  return {\n    name: \"StructuredOutputJudge\",\n    assess: (opts: StructuredOutputJudgeOptions) => {\n      return scorer({\n        ...opts,\n        input: formatStructuredOutput(opts.input),\n        expected: opts.expected ?? expected,\n        output: formatStructuredOutput(opts.output),\n      });\n    },\n  };\n}\n\nfunction formatStructuredOutput(output: unknown) {\n  if (typeof output === \"string\") {\n    return output;\n  }\n\n  if (output !== undefined) {\n    try {\n      return JSON.stringify(output);\n    } catch {\n      return String(output);\n    }\n  }\n\n  return \"\";\n}\n","import type { BaseScorerOptions, ScoredResult, ToolCallLike } from \"./scoring\";\nimport { normalizeContent } from \"../harness\";\nimport {\n  createMatcher,\n  type BaseMatcherConfig,\n  type FuzzyMatchOptions,\n  type MatchStrategy,\n} from \"./matchers\";\n\nexport type ExpectedTool = {\n  /** Expected tool name. */\n  name: string;\n  /** Expected tool arguments matched according to the configured strategy. */\n  arguments?: unknown;\n};\n\nexport interface ToolCallScorerOptions extends BaseScorerOptions {\n  /** Expected tool calls for the run. */\n  expectedTools?: ExpectedTool[];\n}\n\nexport interface ToolCallScorerConfig extends BaseMatcherConfig {\n  /** Require expected tools to appear in the configured order. */\n  ordered?: boolean;\n  /** Matching strategy for expected tool arguments. */\n  params?: MatchStrategy;\n  /** Options used when argument matching is fuzzy. */\n  fuzzyOptions?: FuzzyMatchOptions;\n}\n\n/** Creates a tool-call scorer used by both harness judges and legacy wrappers. */\nexport function ToolCallScorer(config: ToolCallScorerConfig = {}) {\n  const {\n    ordered = false,\n    requireAll = true,\n    allowExtras = true,\n    params = \"strict\",\n    fuzzyOptions: userFuzzyOptions,\n  } = config;\n\n  const fuzzyOptions: FuzzyMatchOptions = {\n    substring: true,\n    caseInsensitive: true,\n    ignoreArrayOrder: true,\n    numericTolerance: 0.001,\n    coerceTypes: false,\n    ...userFuzzyOptions,\n  };\n  const argMatcher = createMatcher(params, fuzzyOptions);\n\n  const scorer = async (opts: ToolCallScorerOptions): Promise<ScoredResult> => {\n    const expectedTools = opts.expectedTools ?? [];\n    const actualCalls = opts.toolCalls ?? [];\n\n    if (expectedTools.length === 0) {\n      return {\n        score: 1,\n        metadata: {\n          rationale: \"No tool calls expected\",\n        },\n      };\n    }\n\n    if (actualCalls.length === 0) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Expected ${expectedTools.length} tool(s) but none were called`,\n        },\n      };\n    }\n\n    return ordered\n      ? evaluateOrderedTools(expectedTools, actualCalls, {\n          argMatcher,\n          allowExtras,\n          requireAllTools: requireAll,\n        })\n      : evaluateUnorderedTools(expectedTools, actualCalls, {\n          argMatcher,\n          requireAllTools: requireAll,\n          allowExtras,\n        });\n  };\n\n  Object.defineProperty(scorer, \"name\", {\n    value: \"ToolCallScorer\",\n  });\n\n  return scorer;\n}\n\nfunction evaluateOrderedTools(\n  expected: ExpectedTool[],\n  actual: ToolCallLike[],\n  options: {\n    argMatcher: (expected: unknown, actual: unknown) => boolean;\n    allowExtras: boolean;\n    requireAllTools: boolean;\n  },\n): ScoredResult {\n  let expectedIndex = 0;\n  let actualIndex = 0;\n\n  while (expectedIndex < expected.length && actualIndex < actual.length) {\n    const expectedTool = expected[expectedIndex];\n    const actualTool = actual[actualIndex];\n\n    if (expectedTool.name === actualTool.name) {\n      if (\n        expectedTool.arguments !== undefined &&\n        !options.argMatcher(expectedTool.arguments, actualTool.arguments ?? {})\n      ) {\n        return {\n          score: expectedIndex / expected.length,\n          metadata: {\n            rationale: `Tool '${expectedTool.name}' called with incorrect arguments at position ${expectedIndex + 1} (${expectedIndex}/${expected.length} tools matched correctly)`,\n            expected: normalizeContent(expectedTool.arguments),\n            actual:\n              actualTool.arguments === undefined\n                ? undefined\n                : normalizeContent(actualTool.arguments),\n            matched: expectedIndex,\n            total: expected.length,\n          },\n        };\n      }\n\n      expectedIndex++;\n      actualIndex++;\n      continue;\n    }\n\n    if (options.allowExtras) {\n      actualIndex++;\n      continue;\n    }\n\n    return {\n      score: 0,\n      metadata: {\n        rationale: `Expected '${expectedTool.name}' at position ${expectedIndex + 1} but found '${actualTool.name}'`,\n      },\n    };\n  }\n\n  if (expectedIndex < expected.length) {\n    const missing = expected.slice(expectedIndex).map((tool) => tool.name);\n    if (options.requireAllTools) {\n      return {\n        score: 0,\n        metadata: {\n          rationale: `Missing required tools in sequence: ${missing.join(\", \")}`,\n        },\n      };\n    }\n\n    const matchedCount = expectedIndex;\n    const totalCount = expected.length;\n    return {\n      score: totalCount > 0 ? matchedCount / totalCount : 1,\n      metadata: {\n        rationale: `Partial match: ${matchedCount}/${totalCount} tools called in order (missing: ${missing.join(\", \")})`,\n        matched: matchedCount,\n        total: totalCount,\n      },\n    };\n  }\n\n  if (!options.allowExtras && actualIndex < actual.length) {\n    const extra = actual.slice(actualIndex).map((tool) => tool.name);\n    return {\n      score: 0,\n      metadata: {\n        rationale: `Unexpected extra tools: ${extra.join(\", \")}`,\n      },\n    };\n  }\n\n  return {\n    score: 1,\n    metadata: {\n      rationale: \"All tools called in expected order with correct arguments\",\n    },\n  };\n}\n\nfunction evaluateUnorderedTools(\n  expected: ExpectedTool[],\n  actual: ToolCallLike[],\n  options: {\n    argMatcher: (expected: unknown, actual: unknown) => boolean;\n    requireAllTools: boolean;\n    allowExtras: boolean;\n  },\n): ScoredResult {\n  const remainingExpected = [...expected];\n  const remainingActual = [...actual];\n  const issues: string[] = [];\n\n  for (let index = remainingExpected.length - 1; index >= 0; index--) {\n    const expectedTool = remainingExpected[index];\n    const matchIndex = remainingActual.findIndex((actualTool) => {\n      if (expectedTool.name !== actualTool.name) {\n        return false;\n      }\n\n      return expectedTool.arguments === undefined\n        ? true\n        : options.argMatcher(\n            expectedTool.arguments,\n            actualTool.arguments ?? {},\n          );\n    });\n\n    if (matchIndex !== -1) {\n      remainingExpected.splice(index, 1);\n      remainingActual.splice(matchIndex, 1);\n    }\n  }\n\n  for (const missingTool of remainingExpected) {\n    if (missingTool.arguments !== undefined) {\n      const wrongArgsCalls = actual.filter(\n        (call) => call.name === missingTool.name,\n      );\n      issues.push(\n        wrongArgsCalls.length > 0\n          ? `Tool '${missingTool.name}' called but with incorrect arguments`\n          : `Missing required tool: ${missingTool.name}`,\n      );\n    } else {\n      issues.push(`Missing required tool: ${missingTool.name}`);\n    }\n  }\n\n  const extraTools = remainingActual.map((tool) => tool.name);\n  if (!options.allowExtras && extraTools.length > 0) {\n    issues.push(`Unexpected extra tools: ${extraTools.join(\", \")}`);\n  }\n\n  const expectedMatched = expected.length - remainingExpected.length;\n  const score = expected.length > 0 ? expectedMatched / expected.length : 1;\n  if (issues.length > 0 && (options.requireAllTools || !options.allowExtras)) {\n    return {\n      score: 0,\n      metadata: {\n        rationale: issues.join(\"; \"),\n      },\n    };\n  }\n\n  if (score === 1) {\n    const extraInfo =\n      extraTools.length > 0 ? ` (plus extra: ${extraTools.join(\", \")})` : \"\";\n\n    return {\n      score: 1,\n      metadata: {\n        rationale: `All expected tools were called${extraInfo}`,\n      },\n    };\n  }\n\n  return {\n    score,\n    metadata: {\n      rationale: issues.join(\"; \"),\n      matched: expectedMatched,\n      total: expected.length,\n    },\n  };\n}\n","import type { Judge, JudgeContext } from \"./types\";\nimport {\n  ToolCallScorer,\n  type ToolCallScorerConfig,\n  type ToolCallScorerOptions,\n} from \"../internal/toolCallScorer\";\n\n/**\n * Expected tool-call shape accepted by `ToolCallJudge()`.\n *\n * @example\n * ```ts\n * const expectedTools: ToolCallJudgeExpectedTool[] = [\n *   \"lookupInvoice\",\n *   { name: \"createRefund\", arguments: { invoiceId: \"inv_123\" } },\n * ];\n * ```\n */\nexport type ToolCallJudgeExpectedTool =\n  | string\n  | {\n      name: string;\n      arguments?: unknown;\n    };\n\n/**\n * Configuration for the deterministic tool-call judge.\n *\n * @example\n * ```ts\n * const judge = ToolCallJudge({\n *   ordered: true,\n *   allowExtra: false,\n * });\n * ```\n */\nexport interface ToolCallJudgeConfig extends ToolCallScorerConfig {\n  /** Expected tool calls used by this judge instance. */\n  expectedTools?: ToolCallJudgeExpectedTool[];\n}\n\n/**\n * Matcher context accepted by `ToolCallJudge()`.\n *\n * @example\n * ```ts\n * await expect(result).toSatisfyJudge(ToolCallJudge(), {\n *   expectedTools: [\"lookupInvoice\", \"createRefund\"],\n * });\n * ```\n */\nexport interface ToolCallJudgeOptions\n  extends JudgeContext<any, any, any>,\n    Omit<\n      ToolCallScorerOptions,\n      \"input\" | \"output\" | \"toolCalls\" | \"expectedTools\"\n    > {\n  expectedTools?: ToolCallJudgeExpectedTool[];\n}\n\n/**\n * Creates a deterministic judge that checks expected tool calls.\n *\n * @param config - Matching behavior shared by every assessment from this judge.\n *\n * @example\n * ```ts\n * describeEval(\"refund agent\", {\n *   harness: refundHarness,\n *   judges: [\n *     ToolCallJudge({\n *       ordered: true,\n *       expectedTools: [\"lookupInvoice\", \"createRefund\"],\n *     }),\n *   ],\n * }, (it) => {\n *   it(\"creates a refund after lookup\", async ({ run }) => {\n *     await run(\"Refund invoice inv_123\");\n *   });\n * });\n * ```\n */\nexport function ToolCallJudge(\n  config: ToolCallJudgeConfig = {},\n): Judge<ToolCallJudgeOptions> {\n  const { expectedTools, ...scorerConfig } = config;\n  const scorer = ToolCallScorer(scorerConfig);\n  return {\n    name: \"ToolCallJudge\",\n    assess: (opts: ToolCallJudgeOptions) => {\n      return scorer({\n        ...opts,\n        input: formatJudgeValue(opts.input),\n        output: formatJudgeValue(opts.output),\n        expectedTools: normalizeExpectedTools(\n          opts.expectedTools ?? expectedTools,\n        ),\n      });\n    },\n  };\n}\n\nfunction normalizeExpectedTools(\n  expectedTools: ToolCallJudgeExpectedTool[] | undefined,\n) {\n  return expectedTools?.map((tool) =>\n    typeof tool === \"string\" ? { name: tool } : tool,\n  );\n}\n\nfunction formatJudgeValue(value: unknown) {\n  if (typeof value === \"string\") {\n    return value;\n  }\n\n  if (value !== undefined) {\n    try {\n      return JSON.stringify(value) ?? String(value);\n    } catch {\n      return String(value);\n    }\n  }\n\n  return \"\";\n}\n"],"mappings":"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","names":["assistantMessages","failedSpans","latestAssistantMessageContent","messagesByRole","messagesToTranscriptEvents","spans","spansByKind","systemMessages","toolCalls","toolMessages","userMessages","normalized","spans","details","message","type","latestAssistantMessageContent","latestAssistantMessageContent","formatJudgeValue"]}