@workglow/eval 0.3.47 → 0.3.49

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":"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
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IExecuteContext } from "@workglow/task-graph";
7
+ import { Task } from "@workglow/task-graph";
8
+ import type { DataPortSchema } from "@workglow/util/schema";
9
+ import type { DatasetRowRecord, EvalStores } from "../storage";
10
+ import { type SweepOptions } from "./runner";
11
+ export interface EvalSweepTaskOutput {
12
+ readonly run_id: string;
13
+ readonly rows: number;
14
+ readonly models: number;
15
+ }
16
+ /** An `interface` carries no index signature; the mapped form is what `DataPorts` accepts. */
17
+ type Ports<T> = {
18
+ [K in keyof T]: T[K];
19
+ };
20
+ /**
21
+ * Runs one sweep as a task, so the run has a graph.
22
+ *
23
+ * The sweep is a nested loop over models and rows, and each row is its own
24
+ * small workflow — so putting every row through the CLI seam would report one
25
+ * RUN per row: fifteen hundred of them for a 500-row sweep of three models,
26
+ * which is not a graph anyone can read. One task for the sweep is the honest
27
+ * unit: it is what the operator started, and its progress is what they want to
28
+ * watch.
29
+ *
30
+ * The stores, rows and options are passed as construction state rather than as
31
+ * ports. They are live handles and parsed dataset records, not values a form
32
+ * could supply or a cache could serialize.
33
+ */
34
+ export declare class EvalSweepTask extends Task<Record<string, never>, Ports<EvalSweepTaskOutput>> {
35
+ #private;
36
+ static readonly type = "EvalSweepTask";
37
+ static readonly category = "Eval";
38
+ static readonly title = "Run eval sweep";
39
+ static readonly cacheable = false;
40
+ static inputSchema(): DataPortSchema;
41
+ static outputSchema(): DataPortSchema;
42
+ /** Hands the task the live handles a port cannot carry. */
43
+ withSweep(stores: EvalStores, rows: readonly DatasetRowRecord[], options: SweepOptions): this;
44
+ execute(_input: Record<string, never>, context: IExecuteContext): Promise<Ports<EvalSweepTaskOutput>>;
45
+ }
46
+ export {};
47
+ //# sourceMappingURL=EvalSweepTask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvalSweepTask.d.ts","sourceRoot":"","sources":["../../src/evals/EvalSweepTask.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAmBvD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,8FAA8F;AAC9F,KAAK,KAAK,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEzC;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,SAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;;IACxF,gBAAyB,IAAI,mBAAmB;IAChD,gBAAyB,QAAQ,UAAU;IAC3C,gBAAyB,KAAK,oBAAoB;IAClD,gBAAyB,SAAS,SAAS;IAE3C,OAAgB,WAAW,IAAI,cAAc,CAE5C;IACD,OAAgB,YAAY,IAAI,cAAc,CAE7C;IAMD,2DAA2D;IAC3D,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,gBAAgB,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAK5F;IAEc,OAAO,CACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC7B,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CA2BrC;CACF"}
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type { ModelPricing } from "@workglow/ai";
7
- import type { StreamEvent, Usage } from "@workglow/task-graph";
7
+ import type { IExecuteContext, StreamEvent, Usage } from "@workglow/task-graph";
8
8
  import type { EvalKind } from "../models";
9
9
  import type { DatasetRowRecord, EvalStores } from "../storage";
10
10
  import type { ColumnOptions, DatasetContext } from "./types";
@@ -22,6 +22,12 @@ export interface SweepOptions {
22
22
  * pays nothing for it.
23
23
  */
24
24
  readonly onStreamChunk?: ((event: StreamEvent) => void) | undefined;
25
+ /**
26
+ * The sweep task's own context. Given one, each row's workflow is owned for
27
+ * its duration, so the run is a single task graph the progress surfaces can
28
+ * see into rather than a loop of invisible standalone runs.
29
+ */
30
+ readonly owner?: IExecuteContext | undefined;
25
31
  }
26
32
  /**
27
33
  * Map one run's token accounting onto the result row's columns.
@@ -1 +1 @@
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
+ {"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,eAAe,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAEhF,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;IACpE;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;CAC9C;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,CAmFjB"}
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type { StreamEvent, Workflow } from "@workglow/task-graph";
7
+ import type { RowOwner } from "./types";
7
8
  /**
8
9
  * Run a workflow, forwarding its `stream_chunk` events to `onStreamChunk` for
9
10
  * the duration of the run only.
@@ -11,5 +12,5 @@ import type { StreamEvent, Workflow } from "@workglow/task-graph";
11
12
  * When no listener is given, nothing is subscribed at all — a 500-row sweep
12
13
  * without `--stream` pays nothing for it.
13
14
  */
14
- export declare function runWithStreamChunks<Output>(workflow: Workflow, onStreamChunk: ((event: StreamEvent) => void) | undefined): Promise<Output>;
15
+ export declare function runWithStreamChunks<Output>(workflow: Workflow, onStreamChunk: ((event: StreamEvent) => void) | undefined, owner?: RowOwner | undefined): Promise<Output>;
15
16
  //# sourceMappingURL=streamSubscribe.d.ts.map
@@ -1 +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"}
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;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAC9C,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,EACzD,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAC3B,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -3,7 +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
+ import type { IExecuteContext, StreamEvent, Usage } from "@workglow/task-graph";
7
7
  import type { DatasetRow, LabelNames } from "../hf/types";
8
8
  /** What one workflow execution produced for one dataset row. */
9
9
  export interface RowPrediction {
@@ -20,7 +20,21 @@ export interface RowPrediction {
20
20
  * the life of the call only — `--stream` is the only caller that passes it, so
21
21
  * an ordinary sweep never pays for the subscription.
22
22
  */
23
- export type RowExecutor = (row: DatasetRow, onStreamChunk?: (event: StreamEvent) => void) => Promise<RowPrediction>;
23
+ /**
24
+ * How a row's work joins the run's single task graph.
25
+ *
26
+ * Each row builds its own small workflow. Run standalone those are invisible:
27
+ * the run is one graph, and anything executed outside it is work no progress
28
+ * surface can see. Handing the executor the sweep task's context lets it OWN
29
+ * that workflow for the row's duration, so the row appears as a live child and
30
+ * leaves when it finishes.
31
+ */
32
+ export interface RowOwner {
33
+ readonly context: IExecuteContext;
34
+ /** Row label, e.g. `claude-haiku-4-5 · row 12`. */
35
+ readonly title: string;
36
+ }
37
+ export type RowExecutor = (row: DatasetRow, onStreamChunk?: (event: StreamEvent) => void, owner?: RowOwner) => Promise<RowPrediction>;
24
38
  export interface ColumnOptions {
25
39
  readonly textColumn: string;
26
40
  /** 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,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
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/evals/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAChF,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;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,UAAU,EACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,EAC5C,KAAK,CAAC,EAAE,QAAQ,KACb,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"}
@@ -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=evalSweepTask.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evalSweepTask.test.d.ts","sourceRoot":"","sources":["../../src/test/evalSweepTask.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -2,6 +2,7 @@
2
2
  // @bun
3
3
 
4
4
  // src/workglow-eval.ts
5
+ import { registerWebCommand } from "@workglow/cli";
5
6
  import { program } from "commander";
6
7
 
7
8
  // src/hf/auth.ts
@@ -698,6 +699,13 @@ function registerReportCommand(program, openStores) {
698
699
  });
699
700
  }
700
701
 
702
+ // src/commands/run.ts
703
+ import { withCli } from "@workglow/cli";
704
+ import { Workflow as Workflow4 } from "@workglow/task-graph";
705
+
706
+ // src/evals/EvalSweepTask.ts
707
+ import { Task } from "@workglow/task-graph";
708
+
701
709
  // src/evals/runner.ts
702
710
  import { estimateCost } from "@workglow/ai";
703
711
 
@@ -974,13 +982,17 @@ ${fence}`;
974
982
  }
975
983
 
976
984
  // src/evals/streamSubscribe.ts
977
- async function runWithStreamChunks(workflow, onStreamChunk) {
985
+ async function runWithStreamChunks(workflow, onStreamChunk, owner) {
978
986
  const listener = onStreamChunk ? (_taskId, event) => onStreamChunk(event) : undefined;
979
987
  if (listener)
980
988
  workflow.on("stream_chunk", listener);
989
+ if (owner)
990
+ owner.context.own(workflow, { title: owner.title });
981
991
  try {
982
992
  return await workflow.run();
983
993
  } finally {
994
+ if (owner)
995
+ owner.context.disown(workflow);
984
996
  if (listener)
985
997
  workflow.off("stream_chunk", listener);
986
998
  }
@@ -1025,7 +1037,7 @@ function makeClassifyExecutor(model, options, context) {
1025
1037
  required: ["label"],
1026
1038
  additionalProperties: false
1027
1039
  };
1028
- return async (row, onStreamChunk) => {
1040
+ return async (row, onStreamChunk, owner) => {
1029
1041
  const text = String(row[options.textColumn] ?? "");
1030
1042
  const workflow = new Workflow;
1031
1043
  workflow.structuredGeneration({
@@ -1035,7 +1047,7 @@ function makeClassifyExecutor(model, options, context) {
1035
1047
  temperature: 0,
1036
1048
  maxTokens: 256
1037
1049
  });
1038
- const output = await runWithStreamChunks(workflow, onStreamChunk);
1050
+ const output = await runWithStreamChunks(workflow, onStreamChunk, owner);
1039
1051
  return {
1040
1052
  expected: expectedLabel(row, options.labelColumn, context.labelNames, labels),
1041
1053
  predicted: String(output.object?.label ?? ""),
@@ -1112,7 +1124,7 @@ function makeExtractExecutor(model, options, context) {
1112
1124
  const instruction = options.instruction ?? DEFAULT_INSTRUCTION;
1113
1125
  const explicitFields = options.fields && options.fields.length > 0 ? resolveExtractionFields([], options.keyField, options.fields) : undefined;
1114
1126
  const explicitSchema = explicitFields ? buildItemsSchema(explicitFields, options.keyField) : undefined;
1115
- return async (row, onStreamChunk) => {
1127
+ return async (row, onStreamChunk, owner) => {
1116
1128
  const text = String(row[options.textColumn] ?? "");
1117
1129
  const expectedRows = parseExpectedRows(row[options.expectedColumn], options.expectedColumn);
1118
1130
  const fields = explicitFields ?? resolveExtractionFields(expectedRows, options.keyField, undefined);
@@ -1125,7 +1137,7 @@ function makeExtractExecutor(model, options, context) {
1125
1137
  temperature: 0,
1126
1138
  maxTokens: 2048
1127
1139
  });
1128
- const output = await runWithStreamChunks(workflow, onStreamChunk);
1140
+ const output = await runWithStreamChunks(workflow, onStreamChunk, owner);
1129
1141
  const items = Array.isArray(output.object?.items) ? output.object.items : [];
1130
1142
  return {
1131
1143
  expected: JSON.stringify(expectedRows),
@@ -1144,12 +1156,12 @@ function makeSimilarityExecutor(model, options, context) {
1144
1156
  throw new Error(`dataset has no column "${column}" (columns: ${context.columns.join(", ")}) \u2014 ` + `set --text-column/--pair-column/--score-column`);
1145
1157
  }
1146
1158
  }
1147
- return async (row, onStreamChunk) => {
1159
+ return async (row, onStreamChunk, owner) => {
1148
1160
  const a = String(row[options.textColumn] ?? "");
1149
1161
  const b = String(row[options.pairColumn] ?? "");
1150
1162
  const workflow = new Workflow3;
1151
1163
  workflow.textEmbedding({ model, text: [a, b] });
1152
- const output = await runWithStreamChunks(workflow, onStreamChunk);
1164
+ const output = await runWithStreamChunks(workflow, onStreamChunk, owner);
1153
1165
  const vectors = Array.isArray(output.vector) ? output.vector : [output.vector];
1154
1166
  if (vectors.length < 2) {
1155
1167
  throw new Error(`expected 2 embeddings, got ${vectors.length}`);
@@ -1230,7 +1242,7 @@ async function runSweep(stores, rows, options) {
1230
1242
  outcome = failedOutcome(parseError ?? "invalid stored row");
1231
1243
  } else {
1232
1244
  try {
1233
- const prediction = await executor(row, options.onStreamChunk);
1245
+ const prediction = await executor(row, options.onStreamChunk, options.owner ? { context: options.owner, title: `${modelId} \xB7 row ${record.row_index}` } : undefined);
1234
1246
  outcomeUsage = prediction.usage;
1235
1247
  outcome = {
1236
1248
  ok: 1,
@@ -1270,6 +1282,61 @@ function failedOutcome(error) {
1270
1282
  };
1271
1283
  }
1272
1284
 
1285
+ // src/evals/EvalSweepTask.ts
1286
+ var INPUT = {
1287
+ type: "object",
1288
+ properties: {},
1289
+ additionalProperties: false
1290
+ };
1291
+ var OUTPUT = {
1292
+ type: "object",
1293
+ properties: {
1294
+ run_id: { type: "string", title: "Run id" },
1295
+ rows: { type: "number", title: "Dataset rows" },
1296
+ models: { type: "number", title: "Models swept" }
1297
+ },
1298
+ required: ["run_id"],
1299
+ additionalProperties: false
1300
+ };
1301
+
1302
+ class EvalSweepTask extends Task {
1303
+ static type = "EvalSweepTask";
1304
+ static category = "Eval";
1305
+ static title = "Run eval sweep";
1306
+ static cacheable = false;
1307
+ static inputSchema() {
1308
+ return INPUT;
1309
+ }
1310
+ static outputSchema() {
1311
+ return OUTPUT;
1312
+ }
1313
+ #stores;
1314
+ #rows = [];
1315
+ #options;
1316
+ withSweep(stores, rows, options) {
1317
+ this.#stores = stores;
1318
+ this.#rows = rows;
1319
+ this.#options = options;
1320
+ return this;
1321
+ }
1322
+ async execute(_input, context) {
1323
+ const stores = this.#stores;
1324
+ const options = this.#options;
1325
+ if (!stores || !options)
1326
+ throw new Error("EvalSweepTask.withSweep was never called");
1327
+ await context.updateProgress(0, `${this.#rows.length} rows \xD7 ${options.models.length} model(s)`);
1328
+ const run_id = await runSweep(stores, this.#rows, {
1329
+ ...options,
1330
+ owner: context,
1331
+ onProgress: (done, total, model, ok, usage) => {
1332
+ options.onProgress?.(done, total, model, ok, usage);
1333
+ context.updateProgress(total > 0 ? done / total * 100 : 0, `${model} \xB7 ${done}/${total}`);
1334
+ }
1335
+ });
1336
+ return { run_id, rows: this.#rows.length, models: options.models.length };
1337
+ }
1338
+ }
1339
+
1273
1340
  // src/report/liveTally.ts
1274
1341
  import { estimateCost as estimateCost2, formatCost, formatUsage } from "@workglow/ai";
1275
1342
  import { mergeUsage } from "@workglow/task-graph";
@@ -1386,7 +1453,7 @@ async function runEval(kind, flags, stores) {
1386
1453
  if (event.type === "text-delta")
1387
1454
  process.stderr.write(event.textDelta);
1388
1455
  } : undefined;
1389
- const runId = await runSweep(stores, limited, {
1456
+ const sweep = new EvalSweepTask({ title: `${kind} \xB7 ${flags.dataset}` }).withSweep(stores, limited, {
1390
1457
  kind,
1391
1458
  dataset: flags.dataset,
1392
1459
  split: flags.split,
@@ -1400,6 +1467,10 @@ async function runEval(kind, flags, stores) {
1400
1467
  },
1401
1468
  onStreamChunk
1402
1469
  });
1470
+ const workflow = new Workflow4;
1471
+ workflow.pipe(sweep);
1472
+ const output = await withCli(workflow, { interactive: false }).run();
1473
+ const runId = output.run_id;
1403
1474
  console.error(`run ${runId} complete
1404
1475
  `);
1405
1476
  await printReport(stores, runId, flags.format);
@@ -1546,9 +1617,10 @@ var stores;
1546
1617
  var openStores = () => stores ??= createSqliteStores(config);
1547
1618
  var providers;
1548
1619
  var ensureProviders = () => providers ??= registerEvalProviders(config);
1549
- program.version("2.0.0").description("Workglow eval example \u2014 pull HuggingFace datasets into storage, run task workflows " + "across models, and score the stored results");
1620
+ program.name("workglow-eval").version("2.0.0").description("Workglow eval example \u2014 pull HuggingFace datasets into storage, run task workflows " + "across models, and score the stored results");
1550
1621
  registerDatasetCommand(program, openStores);
1551
1622
  registerRunCommand(program, openStores, ensureProviders);
1552
1623
  registerReportCommand(program, openStores);
1624
+ registerWebCommand(program);
1553
1625
  await program.parseAsync(process.argv);
1554
1626
  process.exit(process.exitCode ?? 0);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workglow/eval",
3
3
  "type": "module",
4
- "version": "0.3.47",
4
+ "version": "0.3.49",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/workglow-dev/libs.git",
@@ -33,18 +33,19 @@
33
33
  "src/**/*.md"
34
34
  ],
35
35
  "dependencies": {
36
- "@workglow/ai": "0.3.47",
37
- "@workglow/anthropic": "0.3.47",
38
- "@workglow/deepseek": "0.3.47",
39
- "@workglow/google-gemini": "0.3.47",
40
- "@workglow/huggingface-transformers": "0.3.47",
41
- "@workglow/node-llama-cpp": "0.3.47",
42
- "@workglow/openai": "0.3.47",
43
- "@workglow/sqlite": "0.3.47",
44
- "@workglow/storage": "0.3.47",
45
- "@workglow/task-graph": "0.3.47",
46
- "@workglow/util": "0.3.47",
47
- "@workglow/xai": "0.3.47",
36
+ "@workglow/ai": "0.3.49",
37
+ "@workglow/anthropic": "0.3.49",
38
+ "@workglow/cli": "0.3.49",
39
+ "@workglow/deepseek": "0.3.49",
40
+ "@workglow/google-gemini": "0.3.49",
41
+ "@workglow/huggingface-transformers": "0.3.49",
42
+ "@workglow/node-llama-cpp": "0.3.49",
43
+ "@workglow/openai": "0.3.49",
44
+ "@workglow/sqlite": "0.3.49",
45
+ "@workglow/storage": "0.3.49",
46
+ "@workglow/task-graph": "0.3.49",
47
+ "@workglow/util": "0.3.49",
48
+ "@workglow/xai": "0.3.49",
48
49
  "@huggingface/transformers": "^4.2.0",
49
50
  "commander": "^15.0.0",
50
51
  "hyparquet": "^1.28.2",