Queries and terminals
TypeScript JQL roots, time bounds, select terminals, and result row shapes.
judgeval-js JQL source on GitHub
Root builders
traces(options?: { filter?: FilterInput }): QueryBuilder
spans(options?: { filter?: FilterInput }): QueryBuilder
sessions(options?: { filter?: FilterInput }): QueryBuilder
offline_traces(options?: { filter?: FilterInput }): QueryBuilder
offline_spans(options?: { filter?: FilterInput }): QueryBuilder| Source | Grain | Canonical fields |
|---|---|---|
traces | One row per trace | trace_id, span_id, span_name, name, input, output, duration, status, timestamp, session, customer, error |
spans | One row per span | Common fields plus cost, model, parent_span_id |
sessions | One row per session | Common fields plus error |
offline_traces | One row per offline trace | Live trace fields except session; backed by the offline trace store |
offline_spans | One row per offline span | Live span fields except session; backed by the offline trace store |
Offline roots read traces captured by an OfflineTracer. They support the same
direct terminals as their live twins, but do not expose sessions, judge scores, or
cross-grain relations.
Field catalogs can evolve. Use client.discover("fields", { source: "spans" }) before generating
dynamic query UIs or relying on project-specific attributes.
Builder methods
.where(filter: FilterInput): QueryBuilder
.last(window: string): QueryBuilder
.since(since: string): QueryBuilder
.between(start: string, end: string): QueryBuilder
.rows(options?: { fields?: string[]; limit?: number }): QueryBuilder
.ids(): QueryBuilder
.count(by?: string): QueryBuilder
.recent(n: number): QueryBuilder
.top(n: number, by: string): QueryBuilder
.ranked(options?: { within?: string; by?: string; pick?: number | [number, number] }): QueryBuilder
.agg(options: { func; field; q? }): QueryBuilder
.agg(func, field, q?): QueryBuilder
.trend(options?: { metric?: "count" | "rate"; bucket?: string }): QueryBuilder
.pipe(): PipelineBuilder
.toJSON(): SourceQueryBuilders are immutable: every method returns a new builder. Calling .where()
multiple times combines the root filters with canonical all (AND). Calling
.last(), .since(), or .between() replaces any earlier time bound.
Serialize without executing with query.toJSON().
Time object
The JSON time object must contain exactly one key:
| Builder | JSON | Input |
|---|---|---|
.last(window) | {"last":"7d"} | Relative duration string |
.since(since) | {"since":"2026-07-01"} | Date/time string accepted by the server |
.between(start, end) | {"between":["2026-07-01","2026-07-08"]} | Exactly two date/time strings |
Omitting time searches all available history unless a deployment-level policy
adds a default window.
Select terminals
A source query can contain at most one select. In TypeScript, a second select silently replaces the first — the
builder does not throw. The server
also rejects a query containing both select and pipe.
| Terminal | Inputs and defaults | Result rows |
|---|---|---|
rows | fields?: string[], limit?: number | Requested fields, or the source's default row projection |
ids | None | Distinct ID columns for the grain: trace roots return trace_id; span roots return both trace_id and span_id; sessions returns session_id |
count | by?: string | No by: {"count": number}; with by: {"key": value, "count": number} |
recent | n: int | Source rows ordered by newest timestamp |
top | n: int, by: string | Source rows ordered by the numeric field descending |
ranked | within?: string, by: "timestamp", pick: 1 | Trace/span grains, including offline. Positional rows plus _rn; pick is a nonzero rank or two-item range 1 <= a <= b |
agg | func, field, q? | Trace/span grains, including offline. Exactly one row: {"value": number | null} |
trend | metric: "count", bucket: "1d" | Count: {"bucket": datetime, "n": number}; rate: adds total and rate |
Aggregate rules
func is one of avg, sum, min, max, quantile, or
count_distinct. field is always required. q is required only for
quantile, rejected for every other function, and must satisfy 0 < q < 1.
Trend rules
metric is count or rate. bucket is a duration string such as
1d or 1w. Rate trends require a filter that defines the numerator.