@workglow/eval 0.3.37 → 0.3.39

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.
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,sEAAsE;AACtE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,GACpC,IAAI,CA2CN"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;AAG/D,sEAAsE;AACtE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA0Ff;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,GACpC,IAAI,CA2CN"}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA0C7C,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EACrC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACnC,IAAI,CA0CN"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA2C7C,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EACrC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACnC,IAAI,CA2CN"}
@@ -1 +1 @@
1
- {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/evals/classify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,UAAU,EACtB,eAAe,GAAE,SAAS,MAAM,EAAO,GACtC,MAAM,CAOR;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,SAAS,MAAM,EAAE,CAQnB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAOnF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CAkCb"}
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/evals/classify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,UAAU,EACtB,eAAe,GAAE,SAAS,MAAM,EAAO,GACtC,MAAM,CAOR;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,SAAS,MAAM,EAAE,CAQnB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAOnF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CAsCb"}
@@ -1 +1 @@
1
- {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/evals/extract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAW1E;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAShF;AAED,uFAAuF;AACvF,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,SAAS,YAAY,EAAE,EACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACpC,MAAM,EAAE,CAaV;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,CASR;AA+BD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CA4Cb"}
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/evals/extract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAW1E;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAShF;AAED,uFAAuF;AACvF,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,SAAS,YAAY,EAAE,EACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACpC,MAAM,EAAE,CAaV;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,CASR;AA+BD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CAgDb"}
@@ -3,6 +3,8 @@
3
3
  * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import type { ModelPricing } from "@workglow/ai";
7
+ import type { StreamEvent, Usage } from "@workglow/task-graph";
6
8
  import type { EvalKind } from "../models";
7
9
  import type { DatasetRowRecord, EvalStores } from "../storage";
8
10
  import type { ColumnOptions, DatasetContext } from "./types";
@@ -13,8 +15,30 @@ export interface SweepOptions {
13
15
  readonly models: readonly string[];
14
16
  readonly columns: ColumnOptions;
15
17
  readonly context: DatasetContext;
16
- readonly onProgress?: ((done: number, total: number, model: string, ok: boolean) => void) | undefined;
18
+ readonly onProgress?: ((done: number, total: number, model: string, ok: boolean, usage: Usage | undefined) => void) | undefined;
19
+ /**
20
+ * Forwarded to each row's executor as its stream-chunk listener. Left
21
+ * undefined for an ordinary sweep, so nothing subscribes and a 500-row run
22
+ * pays nothing for it.
23
+ */
24
+ readonly onStreamChunk?: ((event: StreamEvent) => void) | undefined;
17
25
  }
26
+ /**
27
+ * Map one run's token accounting onto the result row's columns.
28
+ *
29
+ * An unreported counter is stored as `null`, never `0` — the database has to
30
+ * keep the distinction the in-memory type protects, or a model that never
31
+ * mentions caching becomes indistinguishable from one that cached nothing.
32
+ */
33
+ export declare function usageColumns(usage: Usage | undefined, pricing: ModelPricing | undefined): {
34
+ input_tokens: number | null;
35
+ output_tokens: number | null;
36
+ cached_tokens: number | null;
37
+ cache_write_tokens: number | null;
38
+ total_tokens: number | null;
39
+ cost: number | null;
40
+ currency: string | null;
41
+ };
18
42
  /**
19
43
  * Run every stored dataset row through the eval workflow for each model,
20
44
  * persisting one result row per (run, model, dataset row). Failures are
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/evals/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI/D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAe,MAAM,SAAS,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAClB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACnF;AAoBD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,gBAAgB,EAAE,EACjC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,CAAC,CAwEjB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/evals/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI/D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAe,MAAM,SAAS,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAChB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC,GAC7F,SAAS,CAAC;IACd;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACrE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,OAAO,EAAE,YAAY,GAAG,SAAS,GAChC;IACD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAWA;AAoBD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,gBAAgB,EAAE,EACjC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,CAAC,CA6EjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/evals/similarity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CAiCb"}
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/evals/similarity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GACtB,WAAW,CAqCb"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { StreamEvent, Workflow } from "@workglow/task-graph";
7
+ /**
8
+ * Run a workflow, forwarding its `stream_chunk` events to `onStreamChunk` for
9
+ * the duration of the run only.
10
+ *
11
+ * When no listener is given, nothing is subscribed at all — a 500-row sweep
12
+ * without `--stream` pays nothing for it.
13
+ */
14
+ export declare function runWithStreamChunks<Output>(workflow: Workflow, onStreamChunk: ((event: StreamEvent) => void) | undefined): Promise<Output>;
15
+ //# sourceMappingURL=streamSubscribe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamSubscribe.d.ts","sourceRoot":"","sources":["../../src/evals/streamSubscribe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAc,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAC9C,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,GACxD,OAAO,CAAC,MAAM,CAAC,CAUjB"}
@@ -3,6 +3,7 @@
3
3
  * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import type { StreamEvent, Usage } from "@workglow/task-graph";
6
7
  import type { DatasetRow, LabelNames } from "../hf/types";
7
8
  /** What one workflow execution produced for one dataset row. */
8
9
  export interface RowPrediction {
@@ -10,9 +11,16 @@ export interface RowPrediction {
10
11
  readonly predicted?: string | undefined;
11
12
  readonly expectedValue?: number | undefined;
12
13
  readonly predictedValue?: number | undefined;
14
+ readonly usage?: Usage | undefined;
13
15
  }
14
- /** Runs the eval workflow for a single dataset row against one model. */
15
- export type RowExecutor = (row: DatasetRow) => Promise<RowPrediction>;
16
+ /**
17
+ * Runs the eval workflow for a single dataset row against one model.
18
+ *
19
+ * `onStreamChunk`, when passed, is subscribed to the row's underlying task for
20
+ * the life of the call only — `--stream` is the only caller that passes it, so
21
+ * an ordinary sweep never pays for the subscription.
22
+ */
23
+ export type RowExecutor = (row: DatasetRow, onStreamChunk?: (event: StreamEvent) => void) => Promise<RowPrediction>;
16
24
  export interface ColumnOptions {
17
25
  readonly textColumn: string;
18
26
  /** classify: gold label column. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/evals/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED,yEAAyE;AACzE,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAChD,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAChD,uDAAuD;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/evals/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,UAAU,EACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,KACzC,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAChD,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAChD,uDAAuD;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AAI7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,CA8C1E;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBzF;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9E;AAQD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CASvD"}
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,cAAc,CAAC;AAM9D,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AA8J7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,CA8D1E;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBzF;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9E;AAQD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CASvD"}
@@ -32,4 +32,17 @@ export interface AggregateOptions {
32
32
  * tie-breaker.
33
33
  */
34
34
  export declare function aggregateResults(kind: EvalKind, results: readonly EvalResultRecord[], options?: AggregateOptions): ModelReport[];
35
+ /**
36
+ * Sum a model's token spend across a run's result rows.
37
+ *
38
+ * A null column means the provider reported nothing for that row, so it is
39
+ * skipped rather than counted as 0 — a model that never reports caching must not
40
+ * end up looking like one that cached nothing.
41
+ */
42
+ export declare function sumUsageColumns(rows: readonly EvalResultRecord[]): {
43
+ inputTokens: number | undefined;
44
+ outputTokens: number | undefined;
45
+ cachedTokens: number | undefined;
46
+ cost: number | undefined;
47
+ };
35
48
  //# sourceMappingURL=aggregate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/report/aggregate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACjD;AAWD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,OAAO,GAAE,gBAAqB,GAC7B,WAAW,EAAE,CAmDf"}
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/report/aggregate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACjD;AAWD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,OAAO,GAAE,gBAAqB,GAC7B,WAAW,EAAE,CAmDf;AA0BD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,gBAAgB,EAAE,GAAG;IAClE,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,CAgBA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { ModelPricing } from "@workglow/ai";
7
+ import type { Usage } from "@workglow/task-graph";
8
+ /**
9
+ * Running per-model totals for a sweep, rendered as a small table on stderr.
10
+ *
11
+ * Sums usage across rows because each row is a separate request — unlike a task's
12
+ * cumulative in-run total, these genuinely add up.
13
+ */
14
+ export declare class LiveTally {
15
+ private readonly pricing;
16
+ private readonly byModel;
17
+ private readonly startedAt;
18
+ constructor(pricing: (model: string) => ModelPricing | undefined, now: number);
19
+ record(model: string, ok: boolean, usage: Usage | undefined): void;
20
+ render(done: number, total: number, now: number): string;
21
+ }
22
+ //# sourceMappingURL=liveTally.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveTally.d.ts","sourceRoot":"","sources":["../../src/report/liveTally.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AASlD;;;;;GAKG;AACH,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YACmB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,EACrE,GAAG,EAAE,MAAM,EAGZ;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAMjE;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAevD;CACF"}
package/dist/storage.d.ts CHANGED
@@ -133,6 +133,27 @@ export declare const EvalResultSchema: {
133
133
  readonly latency_ms: {
134
134
  readonly type: "number";
135
135
  };
136
+ readonly input_tokens: {
137
+ readonly type: readonly ["integer", "null"];
138
+ };
139
+ readonly output_tokens: {
140
+ readonly type: readonly ["integer", "null"];
141
+ };
142
+ readonly cached_tokens: {
143
+ readonly type: readonly ["integer", "null"];
144
+ };
145
+ readonly cache_write_tokens: {
146
+ readonly type: readonly ["integer", "null"];
147
+ };
148
+ readonly total_tokens: {
149
+ readonly type: readonly ["integer", "null"];
150
+ };
151
+ readonly cost: {
152
+ readonly type: readonly ["number", "null"];
153
+ };
154
+ readonly currency: {
155
+ readonly type: readonly ["string", "null"];
156
+ };
136
157
  };
137
158
  readonly required: readonly ["run_id", "model", "row_index", "ok", "latency_ms"];
138
159
  readonly additionalProperties: false;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=liveTally.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveTally.test.d.ts","sourceRoot":"","sources":["../../src/test/liveTally.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=runSweep.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runSweep.test.d.ts","sourceRoot":"","sources":["../../src/test/runSweep.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=streamSubscribe.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamSubscribe.test.d.ts","sourceRoot":"","sources":["../../src/test/streamSubscribe.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=usageColumns.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usageColumns.test.d.ts","sourceRoot":"","sources":["../../src/test/usageColumns.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -562,6 +562,24 @@ function extractionCountsFor(pairs, options) {
562
562
  }
563
563
  return counts;
564
564
  }
565
+ function sumUsageColumns(rows) {
566
+ const sum = (pick) => {
567
+ let total;
568
+ for (const row of rows) {
569
+ const value = pick(row);
570
+ if (value === null || value === undefined)
571
+ continue;
572
+ total = (total ?? 0) + value;
573
+ }
574
+ return total;
575
+ };
576
+ return {
577
+ inputTokens: sum((r) => r.input_tokens),
578
+ outputTokens: sum((r) => r.output_tokens),
579
+ cachedTokens: sum((r) => r.cached_tokens),
580
+ cost: sum((r) => r.cost)
581
+ };
582
+ }
565
583
 
566
584
  // src/commands/report.ts
567
585
  async function printReport(stores, runId, format) {
@@ -589,22 +607,55 @@ async function printReport(stores, runId, format) {
589
607
  }
590
608
  console.log(`run ${run.run_id} \u2014 ${run.kind} on ${run.dataset} [${run.split}]`);
591
609
  const REPORT_COLUMNS = {
592
- classify: ["model", "rows", "ok", "accuracy", "avg_ms"],
593
- similarity: ["model", "rows", "ok", "pearson", "spearman", "avg_ms"],
594
- extract: ["model", "rows", "ok", "score", "found", "prec", "avg_ms"]
610
+ classify: ["model", "rows", "ok", "accuracy", "avg_ms", "tokens", "cached", "cost"],
611
+ similarity: [
612
+ "model",
613
+ "rows",
614
+ "ok",
615
+ "pearson",
616
+ "spearman",
617
+ "avg_ms",
618
+ "tokens",
619
+ "cached",
620
+ "cost"
621
+ ],
622
+ extract: [
623
+ "model",
624
+ "rows",
625
+ "ok",
626
+ "score",
627
+ "found",
628
+ "prec",
629
+ "avg_ms",
630
+ "tokens",
631
+ "cached",
632
+ "cost"
633
+ ]
595
634
  };
596
- const tableRows = reports.map((r) => ({
597
- model: r.model,
598
- rows: String(r.rows),
599
- ok: String(r.okRows),
600
- accuracy: formatMetric(r.accuracy),
601
- pearson: formatMetric(r.pearson),
602
- spearman: formatMetric(r.spearman),
603
- score: formatMetric(r.score),
604
- found: formatMetric(r.found),
605
- prec: formatMetric(r.prec),
606
- avg_ms: formatMetric(r.avgLatencyMs, 0)
607
- }));
635
+ const resultsByModel = new Map;
636
+ for (const result of results) {
637
+ const list = resultsByModel.get(result.model) ?? [];
638
+ list.push(result);
639
+ resultsByModel.set(result.model, list);
640
+ }
641
+ const tableRows = reports.map((r) => {
642
+ const totals = sumUsageColumns(resultsByModel.get(r.model) ?? []);
643
+ return {
644
+ model: r.model,
645
+ rows: String(r.rows),
646
+ ok: String(r.okRows),
647
+ accuracy: formatMetric(r.accuracy),
648
+ pearson: formatMetric(r.pearson),
649
+ spearman: formatMetric(r.spearman),
650
+ score: formatMetric(r.score),
651
+ found: formatMetric(r.found),
652
+ prec: formatMetric(r.prec),
653
+ avg_ms: formatMetric(r.avgLatencyMs, 0),
654
+ tokens: `${totals.inputTokens ?? "-"}/${totals.outputTokens ?? "-"}`,
655
+ cached: String(totals.cachedTokens ?? "-"),
656
+ cost: totals.cost === undefined ? "-" : `$${totals.cost.toFixed(4)}`
657
+ };
658
+ });
608
659
  console.log(formatTable(tableRows, REPORT_COLUMNS[kind]));
609
660
  const failures = results.filter((r) => r.ok !== 1);
610
661
  if (failures.length > 0) {
@@ -647,6 +698,9 @@ function registerReportCommand(program, openStores) {
647
698
  });
648
699
  }
649
700
 
701
+ // src/evals/runner.ts
702
+ import { estimateCost } from "@workglow/ai";
703
+
650
704
  // src/models.ts
651
705
  import { downloadModel } from "@workglow/ai";
652
706
 
@@ -673,6 +727,136 @@ function loadConfig() {
673
727
 
674
728
  // src/models.ts
675
729
  var GGUF_PREFIX = "gguf:";
730
+ var ANTHROPIC_PRICING = {
731
+ "claude-haiku-4-5": {
732
+ currency: "USD",
733
+ input: 1,
734
+ output: 5,
735
+ cached: 0.1,
736
+ cacheWrite: 1.25,
737
+ cacheStoragePerHour: undefined
738
+ },
739
+ "claude-sonnet-5": {
740
+ currency: "USD",
741
+ input: 2,
742
+ output: 10,
743
+ cached: 0.2,
744
+ cacheWrite: 2.5,
745
+ cacheStoragePerHour: undefined
746
+ },
747
+ "claude-opus-5": {
748
+ currency: "USD",
749
+ input: 15,
750
+ output: 75,
751
+ cached: 1.5,
752
+ cacheWrite: 18.75,
753
+ cacheStoragePerHour: undefined
754
+ }
755
+ };
756
+ var OPENAI_PRICING = {
757
+ "gpt-5.6-sol": {
758
+ currency: "USD",
759
+ input: 5,
760
+ output: 30,
761
+ cached: 0.5,
762
+ cacheWrite: undefined,
763
+ cacheStoragePerHour: undefined
764
+ },
765
+ "gpt-5.6-terra": {
766
+ currency: "USD",
767
+ input: 2,
768
+ output: 12,
769
+ cached: 0.2,
770
+ cacheWrite: undefined,
771
+ cacheStoragePerHour: undefined
772
+ },
773
+ "gpt-5.6-luna": {
774
+ currency: "USD",
775
+ input: 0.2,
776
+ output: 1.2,
777
+ cached: 0.02,
778
+ cacheWrite: undefined,
779
+ cacheStoragePerHour: undefined
780
+ },
781
+ "gpt-5.5": {
782
+ currency: "USD",
783
+ input: 5,
784
+ output: 15,
785
+ cached: 2.5,
786
+ cacheWrite: undefined,
787
+ cacheStoragePerHour: undefined
788
+ },
789
+ "gpt-5.4-mini": {
790
+ currency: "USD",
791
+ input: 0.4,
792
+ output: 1.6,
793
+ cached: 0.2,
794
+ cacheWrite: undefined,
795
+ cacheStoragePerHour: undefined
796
+ },
797
+ "text-embedding-3-small": {
798
+ currency: "USD",
799
+ input: 0.02,
800
+ output: undefined,
801
+ cached: undefined,
802
+ cacheWrite: undefined,
803
+ cacheStoragePerHour: undefined
804
+ }
805
+ };
806
+ var GEMINI_PRICING = {
807
+ "gemini-3.1-pro-preview": {
808
+ currency: "USD",
809
+ input: 2.5,
810
+ output: 10,
811
+ cached: 0.625,
812
+ cacheWrite: undefined,
813
+ cacheStoragePerHour: 4.5
814
+ },
815
+ "gemini-3-flash-preview": {
816
+ currency: "USD",
817
+ input: 0.3,
818
+ output: 2.5,
819
+ cached: 0.075,
820
+ cacheWrite: undefined,
821
+ cacheStoragePerHour: 1
822
+ }
823
+ };
824
+ var XAI_PRICING = {
825
+ "grok-4.6": {
826
+ currency: "USD",
827
+ input: 2,
828
+ output: 6,
829
+ cached: 0.5,
830
+ cacheWrite: undefined,
831
+ cacheStoragePerHour: undefined
832
+ }
833
+ };
834
+ var DEEPSEEK_PRICING = {
835
+ "deepseek-v4-flash": {
836
+ currency: "USD",
837
+ input: 0.14,
838
+ output: 0.28,
839
+ cached: 0.014,
840
+ cacheWrite: undefined,
841
+ cacheStoragePerHour: undefined
842
+ },
843
+ "deepseek-v4-pro": {
844
+ currency: "USD",
845
+ input: 0.56,
846
+ output: 1.68,
847
+ cached: 0.07,
848
+ cacheWrite: undefined,
849
+ cacheStoragePerHour: undefined
850
+ },
851
+ "deepseek-v4-pro-0813": {
852
+ currency: "USD",
853
+ input: 0.435,
854
+ output: 0.87,
855
+ cached: 0.0435,
856
+ cacheWrite: undefined,
857
+ cacheStoragePerHour: undefined
858
+ }
859
+ };
676
860
  function resolveModelConfig(id, kind) {
677
861
  if (id.startsWith(GGUF_PREFIX)) {
678
862
  const ref = id.slice(GGUF_PREFIX.length);
@@ -702,19 +886,35 @@ function resolveModelConfig(id, kind) {
702
886
  };
703
887
  }
704
888
  if (/^claude-/.test(id)) {
705
- return { provider: "ANTHROPIC", provider_config: { model_name: id, max_tokens: 1024 } };
889
+ return {
890
+ provider: "ANTHROPIC",
891
+ provider_config: { model_name: id },
892
+ pricing: ANTHROPIC_PRICING[id]
893
+ };
706
894
  }
707
895
  if (/^(?:gpt-|o\d|chatgpt-|text-embedding-)/.test(id)) {
708
- return { provider: "OPENAI", provider_config: { model_name: id } };
896
+ return {
897
+ provider: "OPENAI",
898
+ provider_config: { model_name: id },
899
+ pricing: OPENAI_PRICING[id]
900
+ };
709
901
  }
710
902
  if (/^gemini-/.test(id)) {
711
- return { provider: "GOOGLE_GEMINI", provider_config: { model_name: id } };
903
+ return {
904
+ provider: "GOOGLE_GEMINI",
905
+ provider_config: { model_name: id },
906
+ pricing: GEMINI_PRICING[id]
907
+ };
712
908
  }
713
909
  if (/^grok-/.test(id)) {
714
- return { provider: "XAI", provider_config: { model_name: id } };
910
+ return { provider: "XAI", provider_config: { model_name: id }, pricing: XAI_PRICING[id] };
715
911
  }
716
912
  if (/^deepseek-/.test(id)) {
717
- return { provider: "DEEPSEEK", provider_config: { model_name: id } };
913
+ return {
914
+ provider: "DEEPSEEK",
915
+ provider_config: { model_name: id },
916
+ pricing: DEEPSEEK_PRICING[id]
917
+ };
718
918
  }
719
919
  throw new Error(`cannot infer a provider for model "${id}" \u2014 use a claude-*/gpt-*/gemini-*/grok-*/deepseek-* ` + `cloud id or an org/name HuggingFace ONNX model path`);
720
920
  }
@@ -759,7 +959,7 @@ function parseModelList(models) {
759
959
  }
760
960
 
761
961
  // src/evals/classify.ts
762
- import { Workflow } from "@workglow/task-graph";
962
+ import { USAGE_OUTPUT_KEY, Workflow } from "@workglow/task-graph";
763
963
 
764
964
  // src/evals/prompt.ts
765
965
  function fenceText(text) {
@@ -771,6 +971,19 @@ ${text}
771
971
  ${fence}`;
772
972
  }
773
973
 
974
+ // src/evals/streamSubscribe.ts
975
+ async function runWithStreamChunks(workflow, onStreamChunk) {
976
+ const listener = onStreamChunk ? (_taskId, event) => onStreamChunk(event) : undefined;
977
+ if (listener)
978
+ workflow.on("stream_chunk", listener);
979
+ try {
980
+ return await workflow.run();
981
+ } finally {
982
+ if (listener)
983
+ workflow.off("stream_chunk", listener);
984
+ }
985
+ }
986
+
774
987
  // src/evals/classify.ts
775
988
  function expectedLabel(row, labelColumn, labelNames, candidateLabels = []) {
776
989
  const raw = row[labelColumn];
@@ -810,7 +1023,7 @@ function makeClassifyExecutor(model, options, context) {
810
1023
  required: ["label"],
811
1024
  additionalProperties: false
812
1025
  };
813
- return async (row) => {
1026
+ return async (row, onStreamChunk) => {
814
1027
  const text = String(row[options.textColumn] ?? "");
815
1028
  const workflow = new Workflow;
816
1029
  workflow.structuredGeneration({
@@ -820,16 +1033,17 @@ function makeClassifyExecutor(model, options, context) {
820
1033
  temperature: 0,
821
1034
  maxTokens: 256
822
1035
  });
823
- const result = await workflow.run();
1036
+ const output = await runWithStreamChunks(workflow, onStreamChunk);
824
1037
  return {
825
1038
  expected: expectedLabel(row, options.labelColumn, context.labelNames, labels),
826
- predicted: String(result.object?.label ?? "")
1039
+ predicted: String(output.object?.label ?? ""),
1040
+ usage: output[USAGE_OUTPUT_KEY]
827
1041
  };
828
1042
  };
829
1043
  }
830
1044
 
831
1045
  // src/evals/extract.ts
832
- import { Workflow as Workflow2 } from "@workglow/task-graph";
1046
+ import { USAGE_OUTPUT_KEY as USAGE_OUTPUT_KEY2, Workflow as Workflow2 } from "@workglow/task-graph";
833
1047
  var DEFAULT_INSTRUCTION = "Extract every entity mentioned in the text.";
834
1048
  var UNSAFE_FIELDS = new Set(["__proto__", "constructor", "prototype"]);
835
1049
  function parseExpectedRows(value, column) {
@@ -896,7 +1110,7 @@ function makeExtractExecutor(model, options, context) {
896
1110
  const instruction = options.instruction ?? DEFAULT_INSTRUCTION;
897
1111
  const explicitFields = options.fields && options.fields.length > 0 ? resolveExtractionFields([], options.keyField, options.fields) : undefined;
898
1112
  const explicitSchema = explicitFields ? buildItemsSchema(explicitFields, options.keyField) : undefined;
899
- return async (row) => {
1113
+ return async (row, onStreamChunk) => {
900
1114
  const text = String(row[options.textColumn] ?? "");
901
1115
  const expectedRows = parseExpectedRows(row[options.expectedColumn], options.expectedColumn);
902
1116
  const fields = explicitFields ?? resolveExtractionFields(expectedRows, options.keyField, undefined);
@@ -909,17 +1123,18 @@ function makeExtractExecutor(model, options, context) {
909
1123
  temperature: 0,
910
1124
  maxTokens: 2048
911
1125
  });
912
- const result = await workflow.run();
913
- const items = Array.isArray(result.object?.items) ? result.object.items : [];
1126
+ const output = await runWithStreamChunks(workflow, onStreamChunk);
1127
+ const items = Array.isArray(output.object?.items) ? output.object.items : [];
914
1128
  return {
915
1129
  expected: JSON.stringify(expectedRows),
916
- predicted: JSON.stringify(items)
1130
+ predicted: JSON.stringify(items),
1131
+ usage: output[USAGE_OUTPUT_KEY2]
917
1132
  };
918
1133
  };
919
1134
  }
920
1135
 
921
1136
  // src/evals/similarity.ts
922
- import { Workflow as Workflow3 } from "@workglow/task-graph";
1137
+ import { USAGE_OUTPUT_KEY as USAGE_OUTPUT_KEY3, Workflow as Workflow3 } from "@workglow/task-graph";
923
1138
  import { cosineSimilarity } from "@workglow/util/schema";
924
1139
  function makeSimilarityExecutor(model, options, context) {
925
1140
  for (const column of [options.textColumn, options.pairColumn, options.scoreColumn]) {
@@ -927,13 +1142,13 @@ function makeSimilarityExecutor(model, options, context) {
927
1142
  throw new Error(`dataset has no column "${column}" (columns: ${context.columns.join(", ")}) \u2014 ` + `set --text-column/--pair-column/--score-column`);
928
1143
  }
929
1144
  }
930
- return async (row) => {
1145
+ return async (row, onStreamChunk) => {
931
1146
  const a = String(row[options.textColumn] ?? "");
932
1147
  const b = String(row[options.pairColumn] ?? "");
933
1148
  const workflow = new Workflow3;
934
1149
  workflow.textEmbedding({ model, text: [a, b] });
935
- const result = await workflow.run();
936
- const vectors = Array.isArray(result.vector) ? result.vector : [result.vector];
1150
+ const output = await runWithStreamChunks(workflow, onStreamChunk);
1151
+ const vectors = Array.isArray(output.vector) ? output.vector : [output.vector];
937
1152
  if (vectors.length < 2) {
938
1153
  throw new Error(`expected 2 embeddings, got ${vectors.length}`);
939
1154
  }
@@ -943,12 +1158,25 @@ function makeSimilarityExecutor(model, options, context) {
943
1158
  }
944
1159
  return {
945
1160
  expectedValue: gold,
946
- predictedValue: cosineSimilarity(vectors[0], vectors[1])
1161
+ predictedValue: cosineSimilarity(vectors[0], vectors[1]),
1162
+ usage: output[USAGE_OUTPUT_KEY3]
947
1163
  };
948
1164
  };
949
1165
  }
950
1166
 
951
1167
  // src/evals/runner.ts
1168
+ function usageColumns(usage, pricing) {
1169
+ const estimate = usage ? estimateCost(usage, pricing) : undefined;
1170
+ return {
1171
+ input_tokens: usage?.input ?? null,
1172
+ output_tokens: usage?.output ?? null,
1173
+ cached_tokens: usage?.cached ?? null,
1174
+ cache_write_tokens: usage?.cacheWrite ?? null,
1175
+ total_tokens: usage?.total ?? null,
1176
+ cost: estimate?.amount ?? null,
1177
+ currency: estimate?.currency ?? null
1178
+ };
1179
+ }
952
1180
  var EXECUTORS = {
953
1181
  classify: makeClassifyExecutor,
954
1182
  similarity: makeSimilarityExecutor,
@@ -979,11 +1207,13 @@ async function runSweep(stores, rows, options) {
979
1207
  for (const modelId of options.models) {
980
1208
  let executor;
981
1209
  let setupError;
1210
+ let modelPricing;
982
1211
  try {
983
1212
  let config = resolveModelConfig(modelId, options.kind);
984
1213
  if (options.kind === "similarity")
985
1214
  config = await ensureEmbeddingDimensions(config);
986
1215
  await ensureModelDownloaded(config);
1216
+ modelPricing = config.pricing;
987
1217
  executor = makeExecutor(options.kind, config, options.columns, options.context);
988
1218
  } catch (err) {
989
1219
  setupError = err instanceof Error ? err.message : String(err);
@@ -991,13 +1221,15 @@ async function runSweep(stores, rows, options) {
991
1221
  for (const { record, row, parseError } of parsedRows) {
992
1222
  const t0 = performance.now();
993
1223
  let outcome;
1224
+ let outcomeUsage;
994
1225
  if (!executor) {
995
1226
  outcome = failedOutcome(setupError ?? "executor unavailable");
996
1227
  } else if (!row) {
997
1228
  outcome = failedOutcome(parseError ?? "invalid stored row");
998
1229
  } else {
999
1230
  try {
1000
- const prediction = await executor(row);
1231
+ const prediction = await executor(row, options.onStreamChunk);
1232
+ outcomeUsage = prediction.usage;
1001
1233
  outcome = {
1002
1234
  ok: 1,
1003
1235
  error: null,
@@ -1016,10 +1248,11 @@ async function runSweep(stores, rows, options) {
1016
1248
  model: modelId,
1017
1249
  row_index: record.row_index,
1018
1250
  latency_ms: Math.round(latency * 100) / 100,
1251
+ ...usageColumns(outcomeUsage, modelPricing),
1019
1252
  ...outcome
1020
1253
  });
1021
1254
  done++;
1022
- options.onProgress?.(done, total, modelId, outcome.ok === 1);
1255
+ options.onProgress?.(done, total, modelId, outcome.ok === 1, outcomeUsage);
1023
1256
  }
1024
1257
  }
1025
1258
  return run.run_id;
@@ -1035,6 +1268,39 @@ function failedOutcome(error) {
1035
1268
  };
1036
1269
  }
1037
1270
 
1271
+ // src/report/liveTally.ts
1272
+ import { estimateCost as estimateCost2, formatCost, formatUsage } from "@workglow/ai";
1273
+ import { mergeUsage } from "@workglow/task-graph";
1274
+
1275
+ class LiveTally {
1276
+ pricing;
1277
+ byModel = new Map;
1278
+ startedAt;
1279
+ constructor(pricing, now) {
1280
+ this.pricing = pricing;
1281
+ this.startedAt = now;
1282
+ }
1283
+ record(model, ok, usage) {
1284
+ const tally = this.byModel.get(model) ?? { rows: 0, ok: 0, usage: undefined };
1285
+ tally.rows += 1;
1286
+ if (ok)
1287
+ tally.ok += 1;
1288
+ tally.usage = mergeUsage(tally.usage, usage);
1289
+ this.byModel.set(model, tally);
1290
+ }
1291
+ render(done, total, now) {
1292
+ const elapsedSec = Math.max((now - this.startedAt) / 1000, 0.001);
1293
+ const lines = [`[${done}/${total}]`];
1294
+ for (const [model, tally] of this.byModel) {
1295
+ const tps = tally.usage?.output === undefined ? "" : ` ${Math.round(tally.usage.output / elapsedSec)} tok/s`;
1296
+ const cost = tally.usage ? formatCost(estimateCost2(tally.usage, this.pricing(model))) : "";
1297
+ lines.push(` ${model} ${tally.ok}/${tally.rows} ok ` + `${formatUsage(tally.usage, "detailed")}${tps}${cost ? ` ${cost}` : ""}`);
1298
+ }
1299
+ return lines.join(`
1300
+ `);
1301
+ }
1302
+ }
1303
+
1038
1304
  // src/commands/run.ts
1039
1305
  var DEFAULT_MODELS = {
1040
1306
  classify: "onnx-community/LFM2.5-350M-ONNX",
@@ -1053,7 +1319,7 @@ var DESCRIPTIONS = {
1053
1319
  };
1054
1320
  function registerRunCommand(program, openStores, ensureProviders) {
1055
1321
  for (const kind of ["classify", "similarity", "extract"]) {
1056
- const command = program.command(`run-${kind}`).description(DESCRIPTIONS[kind]).requiredOption("--dataset <id>", "a dataset previously stored via `dataset pull`").option("--split <split>", "dataset split", "test").option("--models <list>", `comma-separated model ids (default: ${DEFAULT_MODELS[kind]})`).option("--limit <n>", "cap the number of stored rows to run").option("--text-column <name>", `input text column (default: ${DEFAULT_TEXT_COLUMN[kind]})`).option("--format <fmt>", "report output: table or json", "table");
1322
+ const command = program.command(`run-${kind}`).description(DESCRIPTIONS[kind]).requiredOption("--dataset <id>", "a dataset previously stored via `dataset pull`").option("--split <split>", "dataset split", "test").option("--models <list>", `comma-separated model ids (default: ${DEFAULT_MODELS[kind]})`).option("--limit <n>", "cap the number of stored rows to run").option("--text-column <name>", `input text column (default: ${DEFAULT_TEXT_COLUMN[kind]})`).option("--format <fmt>", "report output: table or json", "table").option("--stream", "render in-flight generation text for the current row", false);
1057
1323
  if (kind === "classify") {
1058
1324
  command.option("--label-column <name>", "gold label column (default: label)").option("--labels <list>", "comma-separated candidate labels override");
1059
1325
  } else if (kind === "similarity") {
@@ -1113,6 +1379,11 @@ async function runEval(kind, flags, stores) {
1113
1379
  labelNames: meta.label_names ? JSON.parse(meta.label_names) : {}
1114
1380
  };
1115
1381
  console.error(`running ${kind} over ${limited.length} rows of ${flags.dataset} [${flags.split}] ` + `with ${models.length} model(s)`);
1382
+ const tally = new LiveTally((id) => resolveModelConfig(id, kind).pricing, Date.now());
1383
+ const onStreamChunk = flags.stream ? (event) => {
1384
+ if (event.type === "text-delta")
1385
+ process.stderr.write(event.textDelta);
1386
+ } : undefined;
1116
1387
  const runId = await runSweep(stores, limited, {
1117
1388
  kind,
1118
1389
  dataset: flags.dataset,
@@ -1120,9 +1391,12 @@ async function runEval(kind, flags, stores) {
1120
1391
  models,
1121
1392
  columns,
1122
1393
  context,
1123
- onProgress: (done, total, model, ok) => {
1124
- console.error(`[${done}/${total}] ${model} ${ok ? "ok" : "FAIL"}`);
1125
- }
1394
+ onProgress: (done, total, model, ok, usage) => {
1395
+ tally.record(model, ok, usage);
1396
+ process.stderr.write(`${tally.render(done, total, Date.now())}
1397
+ `);
1398
+ },
1399
+ onStreamChunk
1126
1400
  });
1127
1401
  console.error(`run ${runId} complete
1128
1402
  `);
@@ -1232,7 +1506,14 @@ var EvalResultSchema = {
1232
1506
  predicted: { type: ["string", "null"] },
1233
1507
  expected_value: { type: ["number", "null"] },
1234
1508
  predicted_value: { type: ["number", "null"] },
1235
- latency_ms: { type: "number" }
1509
+ latency_ms: { type: "number" },
1510
+ input_tokens: { type: ["integer", "null"] },
1511
+ output_tokens: { type: ["integer", "null"] },
1512
+ cached_tokens: { type: ["integer", "null"] },
1513
+ cache_write_tokens: { type: ["integer", "null"] },
1514
+ total_tokens: { type: ["integer", "null"] },
1515
+ cost: { type: ["number", "null"] },
1516
+ currency: { type: ["string", "null"] }
1236
1517
  },
1237
1518
  required: ["run_id", "model", "row_index", "ok", "latency_ms"],
1238
1519
  additionalProperties: false
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workglow/eval",
3
3
  "type": "module",
4
- "version": "0.3.37",
4
+ "version": "0.3.39",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/workglow-dev/libs.git",
@@ -21,7 +21,7 @@
21
21
  "build-js": "bun build --target=bun --packages=external --outdir ./dist ./src/workglow-eval.ts",
22
22
  "build-js-worker-hft": "bun build --target=node --packages=external --outdir ./dist ./src/worker_hft.ts",
23
23
  "build-types": "rm -f tsconfig.tsbuildinfo && tsgo",
24
- "test": "vitest run",
24
+ "test": "vitest run --config ../../vitest.config.ts --project eval",
25
25
  "test:watch": "vitest",
26
26
  "build-js-worker-llamacpp": "bun build --target=node --packages=external --outdir ./dist ./src/worker_llamacpp.ts"
27
27
  },
@@ -33,21 +33,21 @@
33
33
  "src/**/*.md"
34
34
  ],
35
35
  "dependencies": {
36
- "@workglow/ai": "0.3.37",
37
- "@workglow/anthropic": "0.3.37",
38
- "@workglow/deepseek": "0.3.37",
39
- "@workglow/google-gemini": "0.3.37",
40
- "@workglow/huggingface-transformers": "0.3.37",
41
- "@workglow/node-llama-cpp": "0.3.37",
42
- "@workglow/openai": "0.3.37",
43
- "@workglow/sqlite": "0.3.37",
44
- "@workglow/storage": "0.3.37",
45
- "@workglow/task-graph": "0.3.37",
46
- "@workglow/util": "0.3.37",
47
- "@workglow/xai": "0.3.37",
36
+ "@workglow/ai": "0.3.39",
37
+ "@workglow/anthropic": "0.3.39",
38
+ "@workglow/deepseek": "0.3.39",
39
+ "@workglow/google-gemini": "0.3.39",
40
+ "@workglow/huggingface-transformers": "0.3.39",
41
+ "@workglow/node-llama-cpp": "0.3.39",
42
+ "@workglow/openai": "0.3.39",
43
+ "@workglow/sqlite": "0.3.39",
44
+ "@workglow/storage": "0.3.39",
45
+ "@workglow/task-graph": "0.3.39",
46
+ "@workglow/util": "0.3.39",
47
+ "@workglow/xai": "0.3.39",
48
48
  "@huggingface/transformers": "^4.2.0",
49
49
  "commander": "^15.0.0",
50
- "hyparquet": "^1.27.1",
50
+ "hyparquet": "^1.28.1",
51
51
  "hyparquet-compressors": "^1.1.1"
52
52
  },
53
53
  "publishConfig": {