@dawn-ai/evals

Use this when

Use this package when application behavior needs repeatable datasets, scorers, reports, and release gates. Build deterministic agent runs with @dawn-ai/testing, then use runEval() to score them.

Install and import

bash
pnpm add -D @dawn-ai/evals @dawn-ai/testing
ts
import { contains, defineEval, gate, runEval } from "@dawn-ai/evals"

Compatibility and audience

SurfaceRuntimePurityAudienceStability
@dawn-ai/evalsnode-onlynot-claimedtestingsupported

The root resolves JSON and JSONL datasets from disk, so it is a Node testing surface even though individual scorers may be pure.

Public exports

@dawn-ai/evals

ExportResponsibility
defineEvalValidate and preserve an eval definition.
gateBuild report gate policies.
resolveGateResolve explicit, threshold, or informational policy.
LlmJudgeOptionsConfigure an LLM judge.
llmJudgeBuild an LLM-judged scorer.
resolveDatasetResolve inline, JSON, JSONL, or factory data.
RunEvalOptionsConfigure case execution and dataset paths.
runEvalRun and score an eval definition.
NormalizedScoreDescribe a normalized verdict.
normalizeScoreClamp a score into the report shape.
containsScore final-message substring presence.
customWrap an application scorer.
exactMatchScore exact final-message equality.
jsonEqualsScore JSON serialization equality.
memoryFreshScore expected fresh memory text.
memoryIsolatedScore absence of forbidden memory text.
memoryRecalledScore expected recalled IDs.
regexScore a final-message regular expression.
tokensUnderScore a strict collected-stream-delta budget.
toolCalledScore whether a tool was called.
CaseResultDescribe scores for one case.
CaseScoreDescribe one case-scorer result.
DatasetName accepted dataset sources.
EvalCaseDescribe one dataset row.
EvalDefinitionConfigure an evaluation.
EvalReportDescribe the complete report.
GatePolicyDefine report pass policy.
GateResultDescribe a gate decision.
ScoreName accepted scorer output.
ScoredReportDescribe data passed to a gate.
ScorerDefine one scoring function.
ScorerAggregateDescribe one scorer's aggregate.

Key contracts

EvalDefinition

ts
export interface EvalDefinition {
  readonly name: string
  readonly route?: string
  readonly dataset: Dataset
  readonly scorers: readonly Scorer[]
  readonly threshold?: number
  readonly gate?: GatePolicy
}

Fields: @dawn-ai/evals#.:EvalDefinition

FieldTypeRequiredDescription
readonly namestringyesName the report.
readonly routestringnoSelect a route key.
readonly datasetDatasetyesSupply inline, file, or factory cases.
readonly scorersreadonly Scorer[]yesScore every case.
readonly thresholdnumbernoShorthand for a mean gate.
readonly gateGatePolicynoDefine explicit report pass policy.
ts
export declare function defineEval(def: EvalDefinition): EvalDefinition
ts
export interface EvalCase {
  readonly name?: string
  readonly input: unknown
  readonly expected?: unknown
  readonly fixtures?: FixtureSet | ScriptBuilder
  readonly metadata?: Record<string, unknown>
}
ts
export interface Scorer {
  readonly name: string
  readonly threshold?: number
  readonly score: (run: AgentRunResult, testCase: EvalCase) => Score | Promise<Score>
}
ts
export interface RunEvalOptions {
  readonly runCase: (testCase: EvalCase) => Promise<AgentRunResult>
  readonly baseDir?: string
}
ts
export interface EvalReport extends ScoredReport {
  readonly gated: boolean
  readonly passed: boolean
  readonly reason?: string
}
ts
export declare function runEval(
  def: EvalDefinition,
  options: RunEvalOptions,
): Promise<EvalReport>

Behavior contract evals.scorer-errors.zero-score

runEval records a thrown scorer as a zero with its error reason and continues evaluating the report.

Behavior contract evals.run-and-gate

runEval scores every case with every scorer; a scorer exception becomes zero without aborting; an explicit gate wins over threshold, and no gate or threshold is informational and passes. gate.perScorer() checks only scorers with explicit thresholds and ignores scorers without one.

Evaluation semantics

Cases and scorers run sequentially. A scorer error is contained, but a runCase error is not. An explicit gate wins over top-level threshold; without either, the report is informational with gated: false and passed: true. A scorer's own threshold controls its case pass bar and inclusion in gate.perScorer(); case pass status otherwise uses the separate default bar of 0.5. gate.perScorer() ignores scorers without an explicit threshold.

defineEval() rejects an empty inline dataset, but a file or factory may resolve empty. Programmatic runEval() resolves relative dataset paths from baseDir or the current working directory; the CLI supplies the eval file's context. jsonEquals() uses JSON.stringify() equality. tokensUnder() is strictly less than its budget and counts collected stream chunks or deltas, not model-tokenizer tokens. Memory scorers are behavioral signals—not authorization checks.

ts
import { contains, defineEval, gate } from "@dawn-ai/evals"
import { script } from "@dawn-ai/testing"
 
export default defineEval({
  name: "support replies",
  route: "/support#agent",
  dataset: [{
    input: "Where is my order?",
    fixtures: script().user("Where is my order?").replies("Your order is in transit."),
  }],
  scorers: [contains("order", { threshold: 1 })],
  gate: gate.perScorer(),
})

Continue with Evals, Agent Test Harness, and Fixtures and Recording.