@post-print/agent-test 1.1.9 → 2.0.0
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.
- package/README.md +18 -66
- package/dist/cli.d.ts +2 -64
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +26 -691
- package/dist/cli.js.map +1 -1
- package/dist/compare-scenario.d.ts +1 -1
- package/dist/compare-scenario.d.ts.map +1 -1
- package/dist/compare-scenario.js +72 -75
- package/dist/compare-scenario.js.map +1 -1
- package/dist/failures.d.ts +5 -1
- package/dist/failures.d.ts.map +1 -1
- package/dist/failures.js +1 -1
- package/dist/failures.js.map +1 -1
- package/dist/host-login.d.ts +1 -26
- package/dist/host-login.d.ts.map +1 -1
- package/dist/host-login.js +1 -92
- package/dist/host-login.js.map +1 -1
- package/dist/index.d.ts +6 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -26
- package/dist/index.js.map +1 -1
- package/dist/scenario-story.d.ts.map +1 -1
- package/dist/scenario-story.js +57 -39
- package/dist/scenario-story.js.map +1 -1
- package/dist/sdk/cli.d.ts +3 -0
- package/dist/sdk/cli.d.ts.map +1 -0
- package/dist/sdk/cli.js +20 -0
- package/dist/sdk/cli.js.map +1 -0
- package/dist/sdk/definitions.d.ts +22 -0
- package/dist/sdk/definitions.d.ts.map +1 -0
- package/dist/sdk/definitions.js +58 -0
- package/dist/sdk/definitions.js.map +1 -0
- package/dist/sdk/expect.d.ts +31 -0
- package/dist/sdk/expect.d.ts.map +1 -0
- package/dist/sdk/expect.js +68 -0
- package/dist/sdk/expect.js.map +1 -0
- package/dist/sdk/judge.d.ts +16 -0
- package/dist/sdk/judge.d.ts.map +1 -0
- package/dist/sdk/judge.js +82 -0
- package/dist/sdk/judge.js.map +1 -0
- package/dist/sdk/metrics.d.ts +3 -0
- package/dist/sdk/metrics.d.ts.map +1 -0
- package/dist/sdk/metrics.js +24 -0
- package/dist/sdk/metrics.js.map +1 -0
- package/dist/sdk/reporter.d.ts +12 -0
- package/dist/sdk/reporter.d.ts.map +1 -0
- package/dist/sdk/reporter.js +58 -0
- package/dist/sdk/reporter.js.map +1 -0
- package/dist/sdk/runtime.d.ts +33 -0
- package/dist/sdk/runtime.d.ts.map +1 -0
- package/dist/sdk/runtime.js +188 -0
- package/dist/sdk/runtime.js.map +1 -0
- package/dist/sdk/test.d.ts +27 -0
- package/dist/sdk/test.d.ts.map +1 -0
- package/dist/sdk/test.js +92 -0
- package/dist/sdk/test.js.map +1 -0
- package/dist/sdk/types.d.ts +75 -0
- package/dist/sdk/types.d.ts.map +1 -0
- package/dist/sdk/types.js +2 -0
- package/dist/sdk/types.js.map +1 -0
- package/dist/sdk/usage.d.ts +10 -0
- package/dist/sdk/usage.d.ts.map +1 -0
- package/dist/sdk/usage.js +13 -0
- package/dist/sdk/usage.js.map +1 -0
- package/dist/sdk/viewer-results.d.ts +43 -0
- package/dist/sdk/viewer-results.d.ts.map +1 -0
- package/dist/sdk/viewer-results.js +126 -0
- package/dist/sdk/viewer-results.js.map +1 -0
- package/dist/sdk/viewer.d.ts +11 -0
- package/dist/sdk/viewer.d.ts.map +1 -0
- package/dist/sdk/viewer.js +160 -0
- package/dist/sdk/viewer.js.map +1 -0
- package/dist/sdk/workspace.d.ts +33 -0
- package/dist/sdk/workspace.d.ts.map +1 -0
- package/dist/sdk/workspace.js +100 -0
- package/dist/sdk/workspace.js.map +1 -0
- package/dist/types.d.ts +4 -40
- package/dist/types.d.ts.map +1 -1
- package/dist/viewer/catalog.d.ts +2 -8
- package/dist/viewer/catalog.d.ts.map +1 -1
- package/dist/viewer/catalog.js +23 -128
- package/dist/viewer/catalog.js.map +1 -1
- package/dist/viewer/client.d.ts.map +1 -1
- package/dist/viewer/client.js +12 -12
- package/dist/viewer/client.js.map +1 -1
- package/dist/viewer/run-controller.d.ts +4 -2
- package/dist/viewer/run-controller.d.ts.map +1 -1
- package/dist/viewer/run-controller.js +297 -248
- package/dist/viewer/run-controller.js.map +1 -1
- package/dist/viewer/server.d.ts +4 -3
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +149 -112
- package/dist/viewer/server.js.map +1 -1
- package/dist/viewer/styles.d.ts +2 -0
- package/dist/viewer/styles.d.ts.map +1 -0
- package/dist/viewer/styles.js +444 -0
- package/dist/viewer/styles.js.map +1 -0
- package/dist/worker-pool.d.ts +5 -1
- package/dist/worker-pool.d.ts.map +1 -1
- package/dist/worker-pool.js +1 -1
- package/dist/worker-pool.js.map +1 -1
- package/package.json +7 -7
- package/dist/check.d.ts +0 -38
- package/dist/check.d.ts.map +0 -1
- package/dist/check.js +0 -169
- package/dist/check.js.map +0 -1
- package/dist/command-allowlist.d.ts +0 -9
- package/dist/command-allowlist.d.ts.map +0 -1
- package/dist/command-allowlist.js +0 -29
- package/dist/command-allowlist.js.map +0 -1
- package/dist/debug-bundle.d.ts +0 -81
- package/dist/debug-bundle.d.ts.map +0 -1
- package/dist/debug-bundle.js +0 -392
- package/dist/debug-bundle.js.map +0 -1
- package/dist/discover-suites.d.ts +0 -2
- package/dist/discover-suites.d.ts.map +0 -1
- package/dist/discover-suites.js +0 -19
- package/dist/discover-suites.js.map +0 -1
- package/dist/doctor.d.ts +0 -24
- package/dist/doctor.d.ts.map +0 -1
- package/dist/doctor.js +0 -272
- package/dist/doctor.js.map +0 -1
- package/dist/expect.d.ts +0 -59
- package/dist/expect.d.ts.map +0 -1
- package/dist/expect.js +0 -518
- package/dist/expect.js.map +0 -1
- package/dist/host-log.d.ts +0 -17
- package/dist/host-log.d.ts.map +0 -1
- package/dist/host-log.js +0 -154
- package/dist/host-log.js.map +0 -1
- package/dist/hosts.d.ts +0 -22
- package/dist/hosts.d.ts.map +0 -1
- package/dist/hosts.js +0 -84
- package/dist/hosts.js.map +0 -1
- package/dist/html-report.d.ts +0 -18
- package/dist/html-report.d.ts.map +0 -1
- package/dist/html-report.js +0 -1276
- package/dist/html-report.js.map +0 -1
- package/dist/live-isolation.d.ts +0 -82
- package/dist/live-isolation.d.ts.map +0 -1
- package/dist/live-isolation.js +0 -399
- package/dist/live-isolation.js.map +0 -1
- package/dist/live-timeout.d.ts +0 -11
- package/dist/live-timeout.d.ts.map +0 -1
- package/dist/live-timeout.js +0 -29
- package/dist/live-timeout.js.map +0 -1
- package/dist/load-adapters.d.ts +0 -13
- package/dist/load-adapters.d.ts.map +0 -1
- package/dist/load-adapters.js +0 -76
- package/dist/load-adapters.js.map +0 -1
- package/dist/load-suite.d.ts +0 -22
- package/dist/load-suite.d.ts.map +0 -1
- package/dist/load-suite.js +0 -154
- package/dist/load-suite.js.map +0 -1
- package/dist/mcp-config.d.ts +0 -13
- package/dist/mcp-config.d.ts.map +0 -1
- package/dist/mcp-config.js +0 -121
- package/dist/mcp-config.js.map +0 -1
- package/dist/preflight.d.ts +0 -3
- package/dist/preflight.d.ts.map +0 -1
- package/dist/preflight.js +0 -17
- package/dist/preflight.js.map +0 -1
- package/dist/progress.d.ts +0 -24
- package/dist/progress.d.ts.map +0 -1
- package/dist/progress.js +0 -111
- package/dist/progress.js.map +0 -1
- package/dist/record-trace.d.ts +0 -64
- package/dist/record-trace.d.ts.map +0 -1
- package/dist/record-trace.js +0 -124
- package/dist/record-trace.js.map +0 -1
- package/dist/report-preview-server.d.ts +0 -2
- package/dist/report-preview-server.d.ts.map +0 -1
- package/dist/report-preview-server.js +0 -24
- package/dist/report-preview-server.js.map +0 -1
- package/dist/report-preview.d.ts +0 -35
- package/dist/report-preview.d.ts.map +0 -1
- package/dist/report-preview.js +0 -205
- package/dist/report-preview.js.map +0 -1
- package/dist/run-suite.d.ts +0 -139
- package/dist/run-suite.d.ts.map +0 -1
- package/dist/run-suite.js +0 -1688
- package/dist/run-suite.js.map +0 -1
- package/dist/scenario-finalizer.d.ts +0 -27
- package/dist/scenario-finalizer.d.ts.map +0 -1
- package/dist/scenario-finalizer.js +0 -39
- package/dist/scenario-finalizer.js.map +0 -1
- package/dist/scenario-retry.d.ts +0 -15
- package/dist/scenario-retry.d.ts.map +0 -1
- package/dist/scenario-retry.js +0 -52
- package/dist/scenario-retry.js.map +0 -1
- package/dist/scenario-seed.d.ts +0 -13
- package/dist/scenario-seed.d.ts.map +0 -1
- package/dist/scenario-seed.js +0 -72
- package/dist/scenario-seed.js.map +0 -1
- package/dist/suite-summary.d.ts +0 -16
- package/dist/suite-summary.d.ts.map +0 -1
- package/dist/suite-summary.js +0 -218
- package/dist/suite-summary.js.map +0 -1
- package/dist/theme.d.ts +0 -96
- package/dist/theme.d.ts.map +0 -1
- package/dist/theme.js +0 -446
- package/dist/theme.js.map +0 -1
- package/dist/validate-seeds.d.ts +0 -20
- package/dist/validate-seeds.d.ts.map +0 -1
- package/dist/validate-seeds.js +0 -72
- package/dist/validate-seeds.js.map +0 -1
- package/dist/validate-suite.d.ts +0 -24
- package/dist/validate-suite.d.ts.map +0 -1
- package/dist/validate-suite.js +0 -542
- package/dist/validate-suite.js.map +0 -1
- package/dist/viewer/cli.d.ts +0 -17
- package/dist/viewer/cli.d.ts.map +0 -1
- package/dist/viewer/cli.js +0 -38
- package/dist/viewer/cli.js.map +0 -1
- package/dist/viewer/compare-metrics.d.ts +0 -30
- package/dist/viewer/compare-metrics.d.ts.map +0 -1
- package/dist/viewer/compare-metrics.js +0 -101
- package/dist/viewer/compare-metrics.js.map +0 -1
- package/dist/viewer/context-files.d.ts +0 -8
- package/dist/viewer/context-files.d.ts.map +0 -1
- package/dist/viewer/context-files.js +0 -57
- package/dist/viewer/context-files.js.map +0 -1
- package/dist/viewer/emit.d.ts +0 -7
- package/dist/viewer/emit.d.ts.map +0 -1
- package/dist/viewer/emit.js +0 -25
- package/dist/viewer/emit.js.map +0 -1
- package/dist/viewer/live-runner.d.ts +0 -27
- package/dist/viewer/live-runner.d.ts.map +0 -1
- package/dist/viewer/live-runner.js +0 -166
- package/dist/viewer/live-runner.js.map +0 -1
- package/dist/viewer/session-server.d.ts +0 -2
- package/dist/viewer/session-server.d.ts.map +0 -1
- package/dist/viewer/session-server.js +0 -71
- package/dist/viewer/session-server.js.map +0 -1
- package/dist/warnings.d.ts +0 -3
- package/dist/warnings.d.ts.map +0 -1
- package/dist/warnings.js +0 -13
- package/dist/warnings.js.map +0 -1
|
@@ -20,113 +20,135 @@ export function followViewerRun(controller, runId, onEvent) {
|
|
|
20
20
|
flush();
|
|
21
21
|
return unsubscribe;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
class RunController {
|
|
24
|
+
options;
|
|
25
|
+
sessions = new Map();
|
|
26
|
+
activeId;
|
|
27
|
+
maxParallel;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.options = options;
|
|
30
|
+
this.maxParallel = this.options.maxParallelAgents ?? VIEWER_MAX_PARALLEL_AGENTS;
|
|
31
|
+
for (const record of this.options.initialRuns ?? []) {
|
|
32
|
+
this.sessions.set(record.id, {
|
|
33
|
+
record: structuredClone(record),
|
|
34
|
+
events: [],
|
|
35
|
+
listeners: new Set(),
|
|
36
|
+
done: Promise.resolve(),
|
|
37
|
+
armResults: new Map(),
|
|
38
|
+
finalizing: new Set(),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
|
-
|
|
42
|
+
emit = (target, event) => {
|
|
38
43
|
target.events.push(event);
|
|
39
44
|
if (event.type === "scenario_result") {
|
|
40
|
-
addScenarioResult(target, event, options.catalog);
|
|
45
|
+
addScenarioResult(target, event, this.options.catalog);
|
|
41
46
|
}
|
|
42
47
|
for (const listener of target.listeners)
|
|
43
48
|
listener(event);
|
|
44
49
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return record ? structuredClone(record) : undefined;
|
|
52
|
-
},
|
|
53
|
-
start(request) {
|
|
54
|
-
if (activeId)
|
|
55
|
-
throw new Error("A viewer run is already in progress");
|
|
56
|
-
if (request.workers !== undefined &&
|
|
57
|
-
(!Number.isInteger(request.workers) || request.workers < 1 || request.workers > maxParallel)) {
|
|
58
|
-
throw new Error(`workers must be an integer 1-${maxParallel}`);
|
|
59
|
-
}
|
|
60
|
-
const jobs = expandViewerJobs(options.catalog, request);
|
|
61
|
-
if (jobs.length === 0)
|
|
62
|
-
throw new Error("No matching scenarios to run");
|
|
63
|
-
const runId = `run-${Date.now()}`;
|
|
64
|
-
const abort = new AbortController();
|
|
65
|
-
const current = {
|
|
66
|
-
record: {
|
|
67
|
-
id: runId,
|
|
68
|
-
request: structuredClone(request),
|
|
69
|
-
status: "running",
|
|
70
|
-
startedAt: new Date().toISOString(),
|
|
71
|
-
reports: [],
|
|
72
|
-
},
|
|
73
|
-
events: [],
|
|
74
|
-
listeners: new Set(),
|
|
75
|
-
abort,
|
|
76
|
-
done: Promise.resolve(),
|
|
77
|
-
armResults: new Map(),
|
|
78
|
-
finalizing: new Set(),
|
|
79
|
-
};
|
|
80
|
-
sessions.set(runId, current);
|
|
81
|
-
activeId = runId;
|
|
82
|
-
emit(current, { type: "run_started", runId });
|
|
83
|
-
current.done = runJobBatches({
|
|
84
|
-
jobs,
|
|
85
|
-
catalog: options.catalog,
|
|
86
|
-
hosts: request.hosts ?? options.catalog.defaultSelectedHosts,
|
|
87
|
-
parallelHosts: request.parallelHosts === true,
|
|
88
|
-
maxParallel: request.workers ?? maxParallel,
|
|
89
|
-
signal: abort.signal,
|
|
90
|
-
runner: options.runner,
|
|
91
|
-
forward: (event) => emit(current, event),
|
|
92
|
-
afterJob: () => finalizeScheduledCompares(current, options.catalog, options.runner, emit),
|
|
93
|
-
})
|
|
94
|
-
.catch((error) => emit(current, {
|
|
95
|
-
type: "error",
|
|
96
|
-
message: error instanceof Error ? error.message : String(error),
|
|
97
|
-
}))
|
|
98
|
-
.finally(() => {
|
|
99
|
-
const totals = summarizeRun(current.record.reports, current.events);
|
|
100
|
-
current.record.status = abort.signal.aborted ? "cancelled" : "completed";
|
|
101
|
-
current.record.finishedAt = new Date().toISOString();
|
|
102
|
-
emit(current, { type: "run_finished", runId, status: current.record.status, ...totals });
|
|
103
|
-
if (activeId === runId)
|
|
104
|
-
activeId = undefined;
|
|
105
|
-
});
|
|
106
|
-
return { runId };
|
|
107
|
-
},
|
|
108
|
-
cancel(runId) {
|
|
109
|
-
const target = sessions.get(runId);
|
|
110
|
-
if (!target?.abort || target.record.status !== "running")
|
|
111
|
-
return false;
|
|
112
|
-
target.record.status = "cancelling";
|
|
113
|
-
target.abort.abort();
|
|
114
|
-
return true;
|
|
115
|
-
},
|
|
116
|
-
history(runId) {
|
|
117
|
-
const target = sessions.get(runId);
|
|
118
|
-
return target ? [...target.events] : undefined;
|
|
119
|
-
},
|
|
120
|
-
subscribe(runId, listener) {
|
|
121
|
-
const target = sessions.get(runId);
|
|
122
|
-
if (!target)
|
|
123
|
-
return () => undefined;
|
|
124
|
-
target.listeners.add(listener);
|
|
125
|
-
return () => {
|
|
126
|
-
target.listeners.delete(listener);
|
|
127
|
-
};
|
|
128
|
-
},
|
|
50
|
+
activeRunId = () => this.activeId;
|
|
51
|
+
maxParallelAgents = () => this.maxParallel;
|
|
52
|
+
runs = () => [...this.sessions.values()].map(({ record }) => structuredClone(record));
|
|
53
|
+
run = (runId) => {
|
|
54
|
+
const record = this.sessions.get(runId)?.record;
|
|
55
|
+
return record ? structuredClone(record) : undefined;
|
|
129
56
|
};
|
|
57
|
+
start(request) {
|
|
58
|
+
if (this.activeId)
|
|
59
|
+
throw new Error("A viewer run is already in progress");
|
|
60
|
+
if (request.workers !== undefined &&
|
|
61
|
+
(!Number.isInteger(request.workers) ||
|
|
62
|
+
request.workers < 1 ||
|
|
63
|
+
request.workers > this.maxParallel)) {
|
|
64
|
+
throw new Error(`workers must be an integer 1-${this.maxParallel}`);
|
|
65
|
+
}
|
|
66
|
+
const jobs = expandViewerJobs(this.options.catalog, request);
|
|
67
|
+
if (jobs.length === 0)
|
|
68
|
+
throw new Error("No matching scenarios to run");
|
|
69
|
+
const runId = `run-${Date.now()}`;
|
|
70
|
+
const abort = new AbortController();
|
|
71
|
+
const current = {
|
|
72
|
+
record: {
|
|
73
|
+
id: runId,
|
|
74
|
+
request: structuredClone(request),
|
|
75
|
+
status: "running",
|
|
76
|
+
startedAt: new Date().toISOString(),
|
|
77
|
+
reports: [],
|
|
78
|
+
},
|
|
79
|
+
events: [],
|
|
80
|
+
listeners: new Set(),
|
|
81
|
+
abort,
|
|
82
|
+
done: Promise.resolve(),
|
|
83
|
+
armResults: new Map(),
|
|
84
|
+
finalizing: new Set(),
|
|
85
|
+
};
|
|
86
|
+
this.sessions.set(runId, current);
|
|
87
|
+
this.activeId = runId;
|
|
88
|
+
this.emit(current, { type: "run_started", runId });
|
|
89
|
+
this.schedule(current, jobs, abort);
|
|
90
|
+
return { runId };
|
|
91
|
+
}
|
|
92
|
+
schedule(current, jobs, abort) {
|
|
93
|
+
const runId = current.record.id;
|
|
94
|
+
const request = current.record.request;
|
|
95
|
+
current.done = runJobBatches({
|
|
96
|
+
jobs,
|
|
97
|
+
catalog: this.options.catalog,
|
|
98
|
+
hosts: request.hosts ?? this.options.catalog.defaultSelectedHosts,
|
|
99
|
+
parallelHosts: request.parallelHosts === true,
|
|
100
|
+
maxParallel: request.workers ?? this.maxParallel,
|
|
101
|
+
signal: abort.signal,
|
|
102
|
+
runner: this.options.runner,
|
|
103
|
+
forward: (event) => this.emit(current, event),
|
|
104
|
+
afterJob: () => finalizeScheduledCompares(current, {
|
|
105
|
+
catalog: this.options.catalog,
|
|
106
|
+
runner: this.options.runner,
|
|
107
|
+
emit: this.emit,
|
|
108
|
+
}),
|
|
109
|
+
})
|
|
110
|
+
.catch((error) => this.emit(current, {
|
|
111
|
+
type: "error",
|
|
112
|
+
message: error instanceof Error ? error.message : String(error),
|
|
113
|
+
}))
|
|
114
|
+
.finally(() => {
|
|
115
|
+
const totals = summarizeRun(current.record.reports, current.events);
|
|
116
|
+
current.record.status = abort.signal.aborted ? "cancelled" : "completed";
|
|
117
|
+
current.record.finishedAt = new Date().toISOString();
|
|
118
|
+
this.emit(current, {
|
|
119
|
+
type: "run_finished",
|
|
120
|
+
runId,
|
|
121
|
+
status: current.record.status,
|
|
122
|
+
...totals,
|
|
123
|
+
});
|
|
124
|
+
if (this.activeId === runId)
|
|
125
|
+
this.activeId = undefined;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
cancel(runId) {
|
|
129
|
+
const target = this.sessions.get(runId);
|
|
130
|
+
if (!target?.abort || target.record.status !== "running")
|
|
131
|
+
return false;
|
|
132
|
+
target.record.status = "cancelling";
|
|
133
|
+
target.abort.abort();
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
history(runId) {
|
|
137
|
+
const target = this.sessions.get(runId);
|
|
138
|
+
return target ? [...target.events] : undefined;
|
|
139
|
+
}
|
|
140
|
+
subscribe(runId, listener) {
|
|
141
|
+
const target = this.sessions.get(runId);
|
|
142
|
+
if (!target)
|
|
143
|
+
return () => undefined;
|
|
144
|
+
target.listeners.add(listener);
|
|
145
|
+
return () => {
|
|
146
|
+
target.listeners.delete(listener);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export function createViewerRunController(options) {
|
|
151
|
+
return new RunController(options);
|
|
130
152
|
}
|
|
131
153
|
function addScenarioResult(session, event, catalog) {
|
|
132
154
|
const report = ensureReport(session.record, event.suite, event.host);
|
|
@@ -151,8 +173,8 @@ function addScenarioResult(session, event, catalog) {
|
|
|
151
173
|
group.results.set(event.arm, event.result);
|
|
152
174
|
session.armResults.set(key, group);
|
|
153
175
|
}
|
|
154
|
-
function
|
|
155
|
-
|
|
176
|
+
function viewerCompareArms(scenario, stored) {
|
|
177
|
+
return (scenario.compare ?? []).flatMap((arm) => {
|
|
156
178
|
const result = stored.get(arm.id);
|
|
157
179
|
return result
|
|
158
180
|
? [
|
|
@@ -170,6 +192,9 @@ function buildViewerCompareResult(suite, scenarioName, scenario, stored) {
|
|
|
170
192
|
]
|
|
171
193
|
: [];
|
|
172
194
|
});
|
|
195
|
+
}
|
|
196
|
+
function buildViewerCompareResult(suite, { scenarioName, scenario, stored, }) {
|
|
197
|
+
const arms = viewerCompareArms(scenario, stored);
|
|
173
198
|
const { compare, failures } = finalizeCompareOutcome(arms, scenario.gates);
|
|
174
199
|
const passed = failures.length === 0;
|
|
175
200
|
const result = {
|
|
@@ -206,7 +231,7 @@ function buildViewerCompareResult(suite, scenarioName, scenario, stored) {
|
|
|
206
231
|
};
|
|
207
232
|
return result;
|
|
208
233
|
}
|
|
209
|
-
async function finalizeScheduledCompares(session, catalog, runner, emit) {
|
|
234
|
+
async function finalizeScheduledCompares(session, { catalog, runner, emit, }) {
|
|
210
235
|
for (const [key, group] of session.armResults) {
|
|
211
236
|
if (session.abort?.signal.aborted)
|
|
212
237
|
return;
|
|
@@ -218,79 +243,97 @@ async function finalizeScheduledCompares(session, catalog, runner, emit) {
|
|
|
218
243
|
if (!scenario?.compare?.length || group.results.size < scenario.compare.length)
|
|
219
244
|
continue;
|
|
220
245
|
session.finalizing.add(key);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
emit(session, {
|
|
234
|
-
type: "status",
|
|
235
|
-
suite: group.suite,
|
|
236
|
-
scenario: group.scenario,
|
|
237
|
-
host: group.host,
|
|
238
|
-
text: "Finalizing comparison and judge.",
|
|
239
|
-
});
|
|
240
|
-
let result;
|
|
241
|
-
try {
|
|
242
|
-
const armResults = new Map();
|
|
243
|
-
for (const [armId, armResult] of group.results) {
|
|
244
|
-
const resultWithWorkspace = structuredClone(armResult);
|
|
245
|
-
const workspace = group.judgeWorkspaces.get(armId);
|
|
246
|
-
if (workspace) {
|
|
247
|
-
Object.defineProperty(resultWithWorkspace, "judgeWorkspace", {
|
|
248
|
-
value: workspace,
|
|
249
|
-
enumerable: false,
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
armResults.set(armId, resultWithWorkspace);
|
|
253
|
-
}
|
|
254
|
-
result = runner.finalizeCompare
|
|
255
|
-
? await runner.finalizeCompare({
|
|
256
|
-
suite: group.suite,
|
|
257
|
-
scenario,
|
|
258
|
-
host: group.host,
|
|
259
|
-
armResults,
|
|
260
|
-
})
|
|
261
|
-
: buildViewerCompareResult(group.suite, group.scenario, scenario, group.results);
|
|
262
|
-
}
|
|
263
|
-
catch (error) {
|
|
264
|
-
result = buildViewerCompareResult(group.suite, group.scenario, scenario, group.results);
|
|
265
|
-
result.failures.push({
|
|
266
|
-
matcher: "compareFinalize",
|
|
267
|
-
message: error instanceof Error ? error.message : String(error),
|
|
268
|
-
category: "agent_runtime",
|
|
246
|
+
await finalizeGroup(session, { group, scenario, runner, emit });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function comparisonInputs(group) {
|
|
250
|
+
const armResults = new Map();
|
|
251
|
+
for (const [armId, armResult] of group.results) {
|
|
252
|
+
const resultWithWorkspace = structuredClone(armResult);
|
|
253
|
+
const workspace = group.judgeWorkspaces.get(armId);
|
|
254
|
+
if (workspace) {
|
|
255
|
+
Object.defineProperty(resultWithWorkspace, "judgeWorkspace", {
|
|
256
|
+
value: workspace,
|
|
257
|
+
enumerable: false,
|
|
269
258
|
});
|
|
270
|
-
result.passed = false;
|
|
271
259
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
260
|
+
armResults.set(armId, resultWithWorkspace);
|
|
261
|
+
}
|
|
262
|
+
return armResults;
|
|
263
|
+
}
|
|
264
|
+
function publishComparison(session, { group, result, emit, }) {
|
|
265
|
+
emit(session, {
|
|
266
|
+
type: "cell_finished",
|
|
267
|
+
suite: group.suite,
|
|
268
|
+
scenario: group.scenario,
|
|
269
|
+
host: group.host,
|
|
270
|
+
passed: result.passed,
|
|
271
|
+
durationMs: result.durationMs,
|
|
272
|
+
failures: result.failures.map((failure) => ({
|
|
273
|
+
matcher: failure.matcher,
|
|
274
|
+
message: failure.message,
|
|
275
|
+
})),
|
|
276
|
+
});
|
|
277
|
+
emit(session, {
|
|
278
|
+
type: "scenario_result",
|
|
279
|
+
suite: group.suite,
|
|
280
|
+
scenario: group.scenario,
|
|
281
|
+
host: group.host,
|
|
282
|
+
result,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async function finalizeGroup(session, { group, scenario, runner, emit }) {
|
|
286
|
+
emit(session, {
|
|
287
|
+
type: "cell_started",
|
|
288
|
+
suite: group.suite,
|
|
289
|
+
scenario: group.scenario,
|
|
290
|
+
host: group.host,
|
|
291
|
+
});
|
|
292
|
+
emit(session, {
|
|
293
|
+
type: "scenario_finalizing",
|
|
294
|
+
suite: group.suite,
|
|
295
|
+
scenario: group.scenario,
|
|
296
|
+
host: group.host,
|
|
297
|
+
});
|
|
298
|
+
emit(session, {
|
|
299
|
+
type: "status",
|
|
300
|
+
suite: group.suite,
|
|
301
|
+
scenario: group.scenario,
|
|
302
|
+
host: group.host,
|
|
303
|
+
text: "Finalizing comparison and judge.",
|
|
304
|
+
});
|
|
305
|
+
let result;
|
|
306
|
+
try {
|
|
307
|
+
const armResults = comparisonInputs(group);
|
|
308
|
+
result = runner.finalizeCompare
|
|
309
|
+
? await runner.finalizeCompare({
|
|
310
|
+
suite: group.suite,
|
|
311
|
+
scenario,
|
|
312
|
+
host: group.host,
|
|
313
|
+
armResults,
|
|
314
|
+
})
|
|
315
|
+
: buildViewerCompareResult(group.suite, {
|
|
316
|
+
scenarioName: group.scenario,
|
|
317
|
+
scenario: scenario,
|
|
318
|
+
stored: group.results,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
result = buildViewerCompareResult(group.suite, {
|
|
323
|
+
scenarioName: group.scenario,
|
|
324
|
+
scenario: scenario,
|
|
325
|
+
stored: group.results,
|
|
285
326
|
});
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
host: group.host,
|
|
291
|
-
result,
|
|
327
|
+
result.failures.push({
|
|
328
|
+
matcher: "compareFinalize",
|
|
329
|
+
message: error instanceof Error ? error.message : String(error),
|
|
330
|
+
category: "agent_runtime",
|
|
292
331
|
});
|
|
332
|
+
result.passed = false;
|
|
293
333
|
}
|
|
334
|
+
if (session.abort?.signal.aborted)
|
|
335
|
+
return;
|
|
336
|
+
publishComparison(session, { group, result, emit });
|
|
294
337
|
}
|
|
295
338
|
function ensureReport(record, suite, host) {
|
|
296
339
|
let report = record.reports.find((item) => item.suite === suite && item.host === host);
|
|
@@ -341,86 +384,92 @@ async function runJobBatches(options) {
|
|
|
341
384
|
for (const batch of batches) {
|
|
342
385
|
if (options.signal.aborted)
|
|
343
386
|
return;
|
|
344
|
-
await runWorkerPool(batch,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (completedResult && !options.signal.aborted)
|
|
359
|
-
options.forward({ type: "scenario_result", ...job, result: completedResult });
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
const scenario = options.catalog.suites
|
|
363
|
-
.find((suite) => suite.name === job.suite)
|
|
364
|
-
?.scenarios.find((item) => item.name === job.scenario);
|
|
365
|
-
if (!scenario || scenario.compare?.length) {
|
|
366
|
-
options.forward({ type: "scenario_result", ...job, result: completedResult });
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
options.forward({ type: "scenario_finalizing", ...job });
|
|
370
|
-
const finalized = await options.runner.finalizeScenario({ suite: job.suite, scenario, host: job.host, result: completedResult }, options.forward);
|
|
371
|
-
// The child emits an agent-only completion before parent-process judging.
|
|
372
|
-
// Replace that provisional status so the cell cannot remain green when
|
|
373
|
-
// judging later fails or becomes unavailable.
|
|
374
|
-
options.forward({
|
|
375
|
-
type: "cell_finished",
|
|
376
|
-
...job,
|
|
377
|
-
passed: finalized.passed,
|
|
378
|
-
durationMs: finalized.durationMs,
|
|
379
|
-
failures: finalized.failures.map((failure) => ({
|
|
380
|
-
matcher: failure.matcher,
|
|
381
|
-
message: failure.message,
|
|
382
|
-
})),
|
|
383
|
-
});
|
|
384
|
-
options.forward({ type: "scenario_result", ...job, result: finalized });
|
|
385
|
-
}
|
|
386
|
-
catch (error) {
|
|
387
|
-
if (options.signal.aborted)
|
|
388
|
-
return;
|
|
389
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
390
|
-
const envelope = {
|
|
391
|
-
suite: job.suite,
|
|
392
|
-
scenario: job.scenario,
|
|
393
|
-
host: job.host,
|
|
394
|
-
...(job.arm ? { arm: job.arm } : {}),
|
|
395
|
-
};
|
|
396
|
-
const failures = [
|
|
397
|
-
{ matcher: "liveScenario", message, category: "agent_runtime" },
|
|
398
|
-
];
|
|
399
|
-
options.forward({ type: "error", ...envelope, message });
|
|
400
|
-
options.forward({
|
|
401
|
-
type: "cell_finished",
|
|
402
|
-
...envelope,
|
|
403
|
-
passed: false,
|
|
404
|
-
failures,
|
|
405
|
-
durationMs: 0,
|
|
406
|
-
});
|
|
407
|
-
options.forward({
|
|
408
|
-
type: "scenario_result",
|
|
409
|
-
...envelope,
|
|
410
|
-
result: {
|
|
411
|
-
suite: job.suite,
|
|
412
|
-
scenario: job.scenario,
|
|
413
|
-
prompt: job.prompt,
|
|
414
|
-
passed: false,
|
|
415
|
-
failures,
|
|
416
|
-
durationMs: 0,
|
|
417
|
-
},
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
finally {
|
|
421
|
-
await options.afterJob();
|
|
387
|
+
await runWorkerPool(batch, {
|
|
388
|
+
workers: options.maxParallel,
|
|
389
|
+
worker: (job) => runViewerJob(job, options),
|
|
390
|
+
signal: options.signal,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async function runViewerJob(job, options) {
|
|
395
|
+
try {
|
|
396
|
+
let completedResult;
|
|
397
|
+
await options.runner.runJob(job, (event) => {
|
|
398
|
+
if (event.type === "scenario_result" && !job.arm) {
|
|
399
|
+
completedResult = event.result;
|
|
400
|
+
return;
|
|
422
401
|
}
|
|
402
|
+
options.forward(event);
|
|
423
403
|
}, options.signal);
|
|
404
|
+
await finalizeViewerJob(job, options, completedResult);
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
publishJobFailure(job, options, error);
|
|
424
408
|
}
|
|
409
|
+
finally {
|
|
410
|
+
await options.afterJob();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
async function finalizeViewerJob(job, options, completedResult) {
|
|
414
|
+
if (!completedResult || job.arm || !options.runner.finalizeScenario || options.signal.aborted) {
|
|
415
|
+
if (completedResult && !options.signal.aborted)
|
|
416
|
+
options.forward({ type: "scenario_result", ...job, result: completedResult });
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const scenario = options.catalog.suites
|
|
420
|
+
.find((suite) => suite.name === job.suite)
|
|
421
|
+
?.scenarios.find((item) => item.name === job.scenario);
|
|
422
|
+
if (!scenario || scenario.compare?.length) {
|
|
423
|
+
options.forward({ type: "scenario_result", ...job, result: completedResult });
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
options.forward({ type: "scenario_finalizing", ...job });
|
|
427
|
+
const finalized = await options.runner.finalizeScenario({ suite: job.suite, scenario, host: job.host, result: completedResult }, options.forward);
|
|
428
|
+
// The child emits an agent-only completion before parent-process judging.
|
|
429
|
+
// Replace that provisional status so the cell cannot remain green when
|
|
430
|
+
// judging later fails or becomes unavailable.
|
|
431
|
+
options.forward({
|
|
432
|
+
type: "cell_finished",
|
|
433
|
+
...job,
|
|
434
|
+
passed: finalized.passed,
|
|
435
|
+
durationMs: finalized.durationMs,
|
|
436
|
+
failures: finalized.failures.map((failure) => ({
|
|
437
|
+
matcher: failure.matcher,
|
|
438
|
+
message: failure.message,
|
|
439
|
+
})),
|
|
440
|
+
});
|
|
441
|
+
options.forward({ type: "scenario_result", ...job, result: finalized });
|
|
442
|
+
}
|
|
443
|
+
function publishJobFailure(job, options, error) {
|
|
444
|
+
if (options.signal.aborted)
|
|
445
|
+
return;
|
|
446
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
447
|
+
const envelope = {
|
|
448
|
+
suite: job.suite,
|
|
449
|
+
scenario: job.scenario,
|
|
450
|
+
host: job.host,
|
|
451
|
+
...(job.arm ? { arm: job.arm } : {}),
|
|
452
|
+
};
|
|
453
|
+
const failures = [{ matcher: "liveScenario", message, category: "agent_runtime" }];
|
|
454
|
+
options.forward({ type: "error", ...envelope, message });
|
|
455
|
+
options.forward({
|
|
456
|
+
type: "cell_finished",
|
|
457
|
+
...envelope,
|
|
458
|
+
passed: false,
|
|
459
|
+
failures,
|
|
460
|
+
durationMs: 0,
|
|
461
|
+
});
|
|
462
|
+
options.forward({
|
|
463
|
+
type: "scenario_result",
|
|
464
|
+
...envelope,
|
|
465
|
+
result: {
|
|
466
|
+
suite: job.suite,
|
|
467
|
+
scenario: job.scenario,
|
|
468
|
+
prompt: job.prompt,
|
|
469
|
+
passed: false,
|
|
470
|
+
failures,
|
|
471
|
+
durationMs: 0,
|
|
472
|
+
},
|
|
473
|
+
});
|
|
425
474
|
}
|
|
426
475
|
//# sourceMappingURL=run-controller.js.map
|