@forwardimpact/libharness 3.0.2 → 3.2.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 +26 -4
- package/package.json +1 -1
- package/src/benchmark/judge.js +8 -6
- package/src/benchmark/raw-summary.js +79 -0
- package/src/benchmark/result.js +13 -7
- package/src/benchmark/runner.js +70 -67
- package/src/benchmark/task-family.js +9 -0
- package/src/benchmark/workdir.js +28 -6
- package/src/commands/benchmark-definition.js +2 -2
- package/src/commands/callback.js +28 -13
- package/src/commands/trace.js +31 -68
- package/src/events/github.js +1 -2
- package/src/index.js +1 -1
- package/src/trace-github.js +78 -60
- package/src/trace-identity.js +132 -0
- package/src/trace-multi.js +2 -17
- package/src/trace-split.js +103 -0
- package/src/benchmark/trace-split.js +0 -74
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Split the combined supervisor trace for the benchmark runner. One pass
|
|
3
|
-
* over the tagged NDJSON envelope stream separates agent events from
|
|
4
|
-
* supervisor and orchestrator events. The same pass extracts the run summary.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { createInterface } from "node:readline";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Split the combined supervisor trace into agent and supervisor files in a
|
|
11
|
-
* single pass. The same pass extracts the turn count and the submission.
|
|
12
|
-
* Agent-source events go to `agentPath`. Supervisor and orchestrator events
|
|
13
|
-
* go to `supervisorPath`.
|
|
14
|
-
*
|
|
15
|
-
* This function deliberately does not sum cost. The caller derives it from
|
|
16
|
-
* the same combined trace with `sumTraceCost`. One cost path then serves the
|
|
17
|
-
* benchmark, callback, and `gemba-trace cost` consumers.
|
|
18
|
-
* @param {import("@forwardimpact/libutil/runtime").Runtime} runtime
|
|
19
|
-
* @param {string} combinedPath
|
|
20
|
-
* @param {string} agentPath
|
|
21
|
-
* @param {string} supervisorPath
|
|
22
|
-
* @returns {Promise<{turns: number, submission: string}>}
|
|
23
|
-
*/
|
|
24
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: stream-splitting state machine
|
|
25
|
-
export async function splitAndSummarize(
|
|
26
|
-
runtime,
|
|
27
|
-
combinedPath,
|
|
28
|
-
agentPath,
|
|
29
|
-
supervisorPath,
|
|
30
|
-
) {
|
|
31
|
-
const fs = runtime.fs;
|
|
32
|
-
const agentStream = fs.createWriteStream(agentPath);
|
|
33
|
-
const supStream = fs.createWriteStream(supervisorPath);
|
|
34
|
-
const rl = createInterface({
|
|
35
|
-
input: fs.createReadStream(combinedPath),
|
|
36
|
-
crlfDelay: Infinity,
|
|
37
|
-
});
|
|
38
|
-
let turns = 0;
|
|
39
|
-
let submission = "";
|
|
40
|
-
for await (const line of rl) {
|
|
41
|
-
if (!line.trim()) continue;
|
|
42
|
-
let event;
|
|
43
|
-
try {
|
|
44
|
-
event = JSON.parse(line);
|
|
45
|
-
} catch {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
const target = event.source === "agent" ? agentStream : supStream;
|
|
49
|
-
target.write(line + "\n");
|
|
50
|
-
const inner = event.event;
|
|
51
|
-
if (!inner) continue;
|
|
52
|
-
if (event.source === "agent" && inner.type === "assistant") {
|
|
53
|
-
const text = extractText(inner);
|
|
54
|
-
if (text) submission = text;
|
|
55
|
-
}
|
|
56
|
-
if (event.source === "orchestrator" && inner.type === "summary") {
|
|
57
|
-
turns = inner.turns ?? 0;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
await Promise.all([
|
|
61
|
-
new Promise((r) => agentStream.end(r)),
|
|
62
|
-
new Promise((r) => supStream.end(r)),
|
|
63
|
-
]);
|
|
64
|
-
return { turns, submission };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function extractText(inner) {
|
|
68
|
-
const content = inner.message?.content ?? inner.content;
|
|
69
|
-
if (!Array.isArray(content)) return null;
|
|
70
|
-
for (let i = content.length - 1; i >= 0; i--) {
|
|
71
|
-
if (content[i].type === "text" && content[i].text) return content[i].text;
|
|
72
|
-
}
|
|
73
|
-
return null;
|
|
74
|
-
}
|