@tangle-network/agent-bench 0.8.23 → 0.9.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/CHANGELOG.md +69 -0
- package/HARNESS.md +9 -2
- package/dist/index.d.ts +27 -10
- package/dist/index.js +140 -40
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/scripts/verify-pier-agent.mts +1 -1
- package/scripts/verify-pier-recovery.mts +2 -1
- package/src/atom-mcp-e2e.mts +1 -0
- package/src/benchmarks/humaneval.test.mts +2 -2
- package/src/coordination-mcp-container-reach.mts +4 -3
- package/src/index.ts +1 -0
- package/src/mcp-mount-probe.mts +1 -0
- package/src/pier-agent.test.mts +1 -1
- package/src/pier-agent.ts +9 -4
- package/src/pier-trial-controller.test.mts +7 -5
- package/src/pier-trial-controller.ts +10 -2
- package/src/run-benchmarks.test.mts +86 -4
- package/src/run-benchmarks.ts +128 -28
- package/src/sandbox-run.ts +2 -1
- package/src/swe-arena/activation.test.mts +1 -0
- package/src/swe-arena/briefing.test.mts +1 -0
- package/src/swe-arena/execution.test.mts +3 -2
- package/src/swe-arena/factory.test.mts +5 -3
- package/src/swe-arena/gepa-seat.test.mts +2 -0
- package/src/swe-arena/premeasured-from-cells.test.mts +1 -0
- package/src/swe-arena/proc.test.mts +3 -5
- package/src/swe-arena/proposer-fanout.test.mts +1 -0
- package/src/swe-arena/run-experiment.mts +2 -0
- package/src/swe-arena/scratch-worktree.test.mts +2 -1
- package/src/swe-bench-env.test.ts +9 -1
- package/src/tb-container-executor.test.mts +4 -1
- package/src/tb-supervisor-sidecar.mts +1 -0
- package/tb_agents/opencode_supervisor_agent.py +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-bench",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Benchmark adapters and execution for agent-runtime across coding, tool-use, RAG, memory, browser, and terminal tasks.",
|
|
6
6
|
"repository": {
|
|
@@ -25,18 +25,18 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@tangle-network/agent-eval": ">=0.
|
|
29
|
-
"@tangle-network/agent-interface": "^
|
|
30
|
-
"@tangle-network/agent-knowledge": "^
|
|
31
|
-
"@tangle-network/sandbox": ">=0.
|
|
32
|
-
"@tangle-network/agent-runtime": "^0.
|
|
28
|
+
"@tangle-network/agent-eval": ">=0.175.0 <0.176.0",
|
|
29
|
+
"@tangle-network/agent-interface": "^2.3.0",
|
|
30
|
+
"@tangle-network/agent-knowledge": "^14.0.3",
|
|
31
|
+
"@tangle-network/sandbox": ">=0.36.4 <0.38.0",
|
|
32
|
+
"@tangle-network/agent-runtime": "^0.198.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@arethetypeswrong/cli": "0.18.5",
|
|
36
|
-
"@types/node": "26.
|
|
37
|
-
"publint": "0.3.
|
|
36
|
+
"@types/node": "26.4.0",
|
|
37
|
+
"publint": "0.3.24",
|
|
38
38
|
"tsdown": "0.22.14",
|
|
39
|
-
"tsx": "4.23.
|
|
39
|
+
"tsx": "4.23.12",
|
|
40
40
|
"typescript": "6.0.3"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
type ResolvedAgentCandidateContainer,
|
|
38
38
|
sealAgentCandidateBundle,
|
|
39
39
|
verifyAgentCandidateBundle,
|
|
40
|
-
} from '@tangle-network/agent-runtime'
|
|
40
|
+
} from '@tangle-network/agent-runtime/candidate-execution'
|
|
41
41
|
|
|
42
42
|
import { executePreparedPierCandidate } from '../src/pier-agent'
|
|
43
43
|
import { createPierResultGrader } from '../src/pier-result-grader'
|
|
@@ -4,7 +4,8 @@ import { tmpdir } from 'node:os'
|
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
6
6
|
|
|
7
|
-
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime'
|
|
7
|
+
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime/candidate-execution'
|
|
8
|
+
|
|
8
9
|
import { InMemoryTraceStore } from '@tangle-network/agent-eval'
|
|
9
10
|
|
|
10
11
|
import { createStagedPierCandidateExecutionFixture } from '../src/pier-agent.test-fixtures.mts'
|
package/src/atom-mcp-e2e.mts
CHANGED
|
@@ -176,6 +176,7 @@ async function main(): Promise<void> {
|
|
|
176
176
|
blobs,
|
|
177
177
|
makeWorkerAgent: (raw) => makeWorker(raw, ws, n++),
|
|
178
178
|
perWorker: { maxIterations: 2, maxTokens: 200_000 },
|
|
179
|
+
toolNames: ['spawn_worker', 'await_event', 'stop'],
|
|
179
180
|
})
|
|
180
181
|
// The supervisor's cwd carries the REAL skill file (opencode loads it from the cwd skill dirs).
|
|
181
182
|
const supCwd = mkdtempSync(join(tmpdir(), 'e2e-sup-'))
|
|
@@ -13,8 +13,8 @@ describe('HumanEval Python isolation', () => {
|
|
|
13
13
|
writeFileSync(
|
|
14
14
|
fakeDocker,
|
|
15
15
|
`#!/usr/bin/env node
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const fs = require('node:fs')
|
|
17
|
+
const path = require('node:path')
|
|
18
18
|
const args = process.argv.slice(2)
|
|
19
19
|
if (args[0] === 'rm') process.exit(0)
|
|
20
20
|
if (process.env.FAKE_DOCKER_MISSING === '1') {
|
|
@@ -118,6 +118,7 @@ async function main(): Promise<void> {
|
|
|
118
118
|
blobs,
|
|
119
119
|
makeWorkerAgent: () => trivialWorker('w'),
|
|
120
120
|
perWorker: { maxIterations: 4, maxTokens: 2000 },
|
|
121
|
+
toolNames: ['spawn_worker', 'await_event'],
|
|
121
122
|
host: HOST_BIND,
|
|
122
123
|
})
|
|
123
124
|
// Docker containers reach the host through the bridge gateway, not the 0.0.0.0 bind URL.
|
|
@@ -139,10 +140,10 @@ async function main(): Promise<void> {
|
|
|
139
140
|
console.error('')
|
|
140
141
|
|
|
141
142
|
const toolNames = (parsed.result?.tools ?? []).map((t) => t.name)
|
|
142
|
-
const hasSpawn = toolNames.includes('
|
|
143
|
+
const hasSpawn = toolNames.includes('spawn_worker')
|
|
143
144
|
const hasAwait = toolNames.includes('await_event')
|
|
144
145
|
console.error(`[probe] tools advertised: ${toolNames.join(', ')}`)
|
|
145
|
-
console.error(`[probe]
|
|
146
|
+
console.error(`[probe] spawn_worker present = ${hasSpawn}; await_event present = ${hasAwait}`)
|
|
146
147
|
ok = hasSpawn && hasAwait
|
|
147
148
|
|
|
148
149
|
if (ok) {
|
|
@@ -169,7 +170,7 @@ async function main(): Promise<void> {
|
|
|
169
170
|
|
|
170
171
|
console.error(
|
|
171
172
|
ok
|
|
172
|
-
? 'CONTAINER-REACHABLE: docker tools/list returned
|
|
173
|
+
? 'CONTAINER-REACHABLE: docker tools/list returned spawn_worker and await_event.'
|
|
173
174
|
: 'NOT reachable from container; see output above.',
|
|
174
175
|
)
|
|
175
176
|
process.exit(ok ? 0 : 1)
|
package/src/index.ts
CHANGED
package/src/mcp-mount-probe.mts
CHANGED
|
@@ -90,6 +90,7 @@ async function main(): Promise<void> {
|
|
|
90
90
|
blobs,
|
|
91
91
|
makeWorkerAgent: () => deliveringLeaf('w', { ok: true }),
|
|
92
92
|
perWorker: { maxIterations: 4, maxTokens: 2000 },
|
|
93
|
+
toolNames: ['spawn_worker', 'await_event', 'stop'],
|
|
93
94
|
})
|
|
94
95
|
console.error(`[probe] coordination MCP live at ${mcp.url}`)
|
|
95
96
|
try {
|
package/src/pier-agent.test.mts
CHANGED
|
@@ -9,7 +9,7 @@ import { canonicalJson } from '@tangle-network/agent-eval'
|
|
|
9
9
|
import type {
|
|
10
10
|
AgentCandidateExecutorRequest,
|
|
11
11
|
PreparedAgentCandidateExecution,
|
|
12
|
-
} from '@tangle-network/agent-runtime'
|
|
12
|
+
} from '@tangle-network/agent-runtime/candidate-execution'
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
awaitAbortableTrial,
|
package/src/pier-agent.ts
CHANGED
|
@@ -14,8 +14,9 @@ import type {
|
|
|
14
14
|
AgentCandidateProtectedRunCapture,
|
|
15
15
|
AgentCandidateRunFinalization,
|
|
16
16
|
PreparedAgentCandidateExecution,
|
|
17
|
-
} from '@tangle-network/agent-runtime'
|
|
18
|
-
|
|
17
|
+
} from '@tangle-network/agent-runtime/candidate-execution'
|
|
18
|
+
|
|
19
|
+
import { executePreparedAgentCandidate } from '@tangle-network/agent-runtime/candidate-execution'
|
|
19
20
|
import { canonicalJson, type TraceStore } from '@tangle-network/agent-eval'
|
|
20
21
|
|
|
21
22
|
import { capturePierTaskOutcome } from './pier-task-outcome'
|
|
@@ -219,8 +220,12 @@ async function assertRealDirectory(path: string, label: string): Promise<void> {
|
|
|
219
220
|
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
220
221
|
throw new Error(`${label} must be a real directory`)
|
|
221
222
|
}
|
|
222
|
-
|
|
223
|
-
|
|
223
|
+
// A symlinked PREFIX is the OS's own doing on macOS, where a temp root lives under /var, a
|
|
224
|
+
// symlink to /private/var. The directory itself must still be real, which the lstat above
|
|
225
|
+
// and this one both require.
|
|
226
|
+
const resolvedStats = await lstat(await realpath(path))
|
|
227
|
+
if (!resolvedStats.isDirectory() || resolvedStats.isSymbolicLink()) {
|
|
228
|
+
throw new Error(`${label} must resolve to a real directory`)
|
|
224
229
|
}
|
|
225
230
|
}
|
|
226
231
|
|
|
@@ -6,12 +6,14 @@ import path from 'node:path'
|
|
|
6
6
|
import test from 'node:test'
|
|
7
7
|
import { promisify } from 'node:util'
|
|
8
8
|
|
|
9
|
-
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime'
|
|
9
|
+
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime/candidate-execution'
|
|
10
|
+
|
|
10
11
|
import { InMemoryTraceStore } from '@tangle-network/agent-eval'
|
|
11
12
|
|
|
12
13
|
import { createStagedPierCandidateExecutionFixture } from './pier-agent.test-fixtures.mts'
|
|
13
14
|
import { FilePierCandidateTrialController } from './pier-trial-controller'
|
|
14
15
|
|
|
16
|
+
// Process identity and restart recovery require Linux /proc start-time receipts.
|
|
15
17
|
const execFileAsync = promisify(execFile)
|
|
16
18
|
|
|
17
19
|
function testRequest(executionId: string, executionPlanDigest: `sha256:${string}`) {
|
|
@@ -71,7 +73,7 @@ test('an existing Pier job is rejected without deleting or starting it', async (
|
|
|
71
73
|
}
|
|
72
74
|
})
|
|
73
75
|
|
|
74
|
-
test('the Pier result wait does not add time beyond an expired deadline', async () => {
|
|
76
|
+
test('the Pier result wait does not add time beyond an expired deadline', { skip: process.platform !== 'linux' }, async () => {
|
|
75
77
|
const root = await mkdtemp(path.join(tmpdir(), 'pier-controller-deadline-'))
|
|
76
78
|
const controlRoot = path.join(root, 'control')
|
|
77
79
|
const jobsDirectory = path.join(root, 'jobs')
|
|
@@ -144,7 +146,7 @@ setInterval(() => undefined, 1_000)
|
|
|
144
146
|
}
|
|
145
147
|
})
|
|
146
148
|
|
|
147
|
-
test('the supervisor receives only launch data and no inherited evaluator environment', async () => {
|
|
149
|
+
test('the supervisor receives only launch data and no inherited evaluator environment', { skip: process.platform !== 'linux' }, async () => {
|
|
148
150
|
const root = await mkdtemp(path.join(tmpdir(), 'pier-controller-supervisor-env-'))
|
|
149
151
|
const controlRoot = path.join(root, 'control')
|
|
150
152
|
const jobsDirectory = path.join(root, 'jobs')
|
|
@@ -217,7 +219,7 @@ renameSync(temporary, target)
|
|
|
217
219
|
}
|
|
218
220
|
})
|
|
219
221
|
|
|
220
|
-
test('terminal acknowledgements reject unknown fields', async () => {
|
|
222
|
+
test('terminal acknowledgements reject unknown fields', { skip: process.platform !== 'linux' }, async () => {
|
|
221
223
|
const root = await mkdtemp(path.join(tmpdir(), 'pier-controller-terminal-schema-'))
|
|
222
224
|
const controlRoot = path.join(root, 'control')
|
|
223
225
|
const jobsDirectory = path.join(root, 'jobs')
|
|
@@ -274,7 +276,7 @@ renameSync(temporary, target)
|
|
|
274
276
|
}
|
|
275
277
|
})
|
|
276
278
|
|
|
277
|
-
test('a fresh evaluator process terminates the persisted process and container identity', async () => {
|
|
279
|
+
test('a fresh evaluator process terminates the persisted process and container identity', { skip: process.platform !== 'linux' }, async () => {
|
|
278
280
|
const root = await mkdtemp(path.join(tmpdir(), 'pier-controller-recovery-'))
|
|
279
281
|
const controlRoot = path.join(root, 'control')
|
|
280
282
|
const jobsDirectory = path.join(root, 'jobs')
|
|
@@ -21,7 +21,8 @@ import { isAbsolute, join, resolve } from 'node:path'
|
|
|
21
21
|
import { fileURLToPath } from 'node:url'
|
|
22
22
|
import type { Writable } from 'node:stream'
|
|
23
23
|
|
|
24
|
-
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime'
|
|
24
|
+
import type { AgentCandidateExecutorRequest } from '@tangle-network/agent-runtime/candidate-execution'
|
|
25
|
+
|
|
25
26
|
import type { TraceStore } from '@tangle-network/agent-eval'
|
|
26
27
|
|
|
27
28
|
import type {
|
|
@@ -493,9 +494,16 @@ function trialKey(identity: PierCandidateTrialIdentity): string {
|
|
|
493
494
|
|
|
494
495
|
function assertRealDirectory(path: string, label: string): void {
|
|
495
496
|
const stats = lstatSync(path)
|
|
496
|
-
if (!stats.isDirectory() || stats.isSymbolicLink()
|
|
497
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
497
498
|
throw new Error(`${label} must be a real canonical directory`)
|
|
498
499
|
}
|
|
500
|
+
// A symlinked PREFIX is the OS's own doing on macOS, where a temp root lives under /var, a
|
|
501
|
+
// symlink to /private/var. The directory itself must still be real, which both this check
|
|
502
|
+
// and the lstat above require.
|
|
503
|
+
const resolvedStats = lstatSync(realpathSync(path))
|
|
504
|
+
if (!resolvedStats.isDirectory() || resolvedStats.isSymbolicLink()) {
|
|
505
|
+
throw new Error(`${label} must resolve to a real directory`)
|
|
506
|
+
}
|
|
499
507
|
}
|
|
500
508
|
|
|
501
509
|
export class FilePierCandidateTrialController implements PierCandidateTrialController {
|
|
@@ -60,6 +60,41 @@ async function main(): Promise<void> {
|
|
|
60
60
|
assert.equal(report.perTask.length, 24, 'matrix expands to benchmarks × cells × tasks')
|
|
61
61
|
assert.equal(report.rows.length, 6, 'one row per (benchmark × cell)')
|
|
62
62
|
|
|
63
|
+
const measured = await runBenchmarks({
|
|
64
|
+
benchmarks: ['alpha'], cells: [{ label: 'measured', model: 'm' }],
|
|
65
|
+
routerBaseUrl: 'x', routerKey: 'x', resolveAdapter: resolveStub, n: 1,
|
|
66
|
+
runShot: async () => ({ artifact: 'WRONG', ok: true, usage: { input: 23, output: 7, costUsd: 0.04 } }),
|
|
67
|
+
})
|
|
68
|
+
assert.equal(measured.perTask[0]?.artifact, 'WRONG', 'the exact judged artifact reaches the caller even when it fails')
|
|
69
|
+
assert.deepEqual(measured.perTask[0]?.usage, { input: 23, output: 7, costUsd: 0.04 }, 'measured usage reaches the caller')
|
|
70
|
+
|
|
71
|
+
const judgeFailure = await runBenchmarks({
|
|
72
|
+
benchmarks: ['alpha'], cells: [{ label: 'measured', model: 'm' }],
|
|
73
|
+
routerBaseUrl: 'x', routerKey: 'x', n: 1, verifyJudge: false,
|
|
74
|
+
resolveAdapter: () => ({ ...REGISTRY.alpha!, judge: async () => { throw new Error('judge unavailable') } }),
|
|
75
|
+
runShot: async () => ({ artifact: 'PATCH', ok: true, usage: { input: 23, output: 7, costUsd: 0.04 } }),
|
|
76
|
+
})
|
|
77
|
+
assert.equal(judgeFailure.perTask[0]?.ok, false)
|
|
78
|
+
assert.equal(judgeFailure.perTask[0]?.artifact, 'PATCH', 'a judge outage retains the completed agent artifact')
|
|
79
|
+
assert.equal(judgeFailure.perTask[0]?.usage?.costUsd, 0.04, 'a judge outage retains already incurred usage')
|
|
80
|
+
|
|
81
|
+
const controller = new AbortController()
|
|
82
|
+
let started = 0
|
|
83
|
+
const cancelled = await runBenchmarks({
|
|
84
|
+
benchmarks: ['alpha'], cells: [{ label: 'cancelled', model: 'm' }],
|
|
85
|
+
routerBaseUrl: 'x', routerKey: 'x', resolveAdapter: resolveStub, concurrency: 1,
|
|
86
|
+
signal: controller.signal,
|
|
87
|
+
runShot: async ({ signal }) => {
|
|
88
|
+
assert.equal(signal, controller.signal)
|
|
89
|
+
started += 1
|
|
90
|
+
controller.abort()
|
|
91
|
+
return { artifact: 'PATCH', ok: true, usage: { input: 1, output: 2, costUsd: 0.01 } }
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
assert.equal(started, 1, 'cancellation prevents every queued model call')
|
|
95
|
+
assert.equal(cancelled.perTask.length, 4, 'cancelled work remains visible')
|
|
96
|
+
assert.equal(cancelled.perTask[0]?.usage?.costUsd, 0.01)
|
|
97
|
+
|
|
63
98
|
const row = (b: string, c: string) => report.rows.find((r) => r.benchmark === b && r.cell === c)!
|
|
64
99
|
assert.equal(row('alpha', 'perfect').resolveRate, 1, 'perfect cell resolves every task')
|
|
65
100
|
assert.equal(row('alpha', 'half').resolveRate, 0.5, 'half cell resolves the even tasks')
|
|
@@ -94,7 +129,7 @@ async function main(): Promise<void> {
|
|
|
94
129
|
let prompts: string[] = []
|
|
95
130
|
const retryShot: BenchShot = async ({ task, prompt }) => {
|
|
96
131
|
prompts.push(prompt ?? task.prompt)
|
|
97
|
-
return { artifact: prompts.length === 1 ? 'WRONG' : String(task.metadata?.gold), ok: true }
|
|
132
|
+
return { artifact: prompts.length === 1 ? 'WRONG' : String(task.metadata?.gold), ok: true, usage: { input: 11, output: 3, costUsd: 0.02 } }
|
|
98
133
|
}
|
|
99
134
|
const oneShot = await runBenchmarks({
|
|
100
135
|
benchmarks: ['alpha'], cells: [{ label: 'retrying', model: 'm' }],
|
|
@@ -110,6 +145,40 @@ async function main(): Promise<void> {
|
|
|
110
145
|
assert.equal(prompts.length, 2, 'loop stops after the passing second attempt')
|
|
111
146
|
assert.match(prompts[1]!, /Previous attempts and safe checker feedback/)
|
|
112
147
|
assert.match(looped.perTask[0]!.detail ?? '', /"mode":"refine-loop"/)
|
|
148
|
+
assert.deepEqual(looped.perTask[0]?.usage, { input: 22, output: 6, costUsd: 0.04 }, 'retry cost includes the rejected attempt')
|
|
149
|
+
|
|
150
|
+
const failedRetry = await runBenchmarks({
|
|
151
|
+
benchmarks: ['alpha'], cells: [{ label: 'retrying', model: 'm' }],
|
|
152
|
+
routerBaseUrl: 'x', routerKey: 'x', resolveAdapter: resolveStub, n: 1, loopAttempts: 2,
|
|
153
|
+
runShot: async ({ attempt }) => {
|
|
154
|
+
if (attempt === 2) throw new Error('connection lost after dispatch')
|
|
155
|
+
return { artifact: 'WRONG', ok: true, usage: { input: 11, output: 3, costUsd: 0.02 } }
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
assert.deepEqual(failedRetry.perTask[0]?.usage, {
|
|
159
|
+
input: 11, output: 3, costUsd: 0.02, tokensKnown: false, usdKnown: false,
|
|
160
|
+
}, 'an unreported retry preserves the measured floor without claiming complete accounting')
|
|
161
|
+
|
|
162
|
+
let validAttempts = 0
|
|
163
|
+
const validRetry = await runBenchmarks({
|
|
164
|
+
benchmarks: ['alpha'], cells: [{ label: 'retrying', model: 'm' }],
|
|
165
|
+
routerBaseUrl: 'x', routerKey: 'x', resolveAdapter: resolveStub, n: 1, loopAttempts: 3,
|
|
166
|
+
runShot: async ({ task, attempt }) => {
|
|
167
|
+
validAttempts += 1
|
|
168
|
+
return { artifact: attempt === 1 ? 'WRONG' : String(task.metadata?.gold), ok: attempt !== 2 }
|
|
169
|
+
},
|
|
170
|
+
})
|
|
171
|
+
assert.equal(validAttempts, 3, 'a failed execution cannot stop refinement with apparent gold')
|
|
172
|
+
assert.equal(validRetry.perTask[0]?.ok, true)
|
|
173
|
+
const validIncumbent = await runBenchmarks({
|
|
174
|
+
benchmarks: ['alpha'], cells: [{ label: 'retrying', model: 'm' }],
|
|
175
|
+
routerBaseUrl: 'x', routerKey: 'x', resolveAdapter: resolveStub, n: 1, loopAttempts: 2,
|
|
176
|
+
runShot: async ({ task, attempt }) => ({
|
|
177
|
+
artifact: attempt === 1 ? 'WRONG' : String(task.metadata?.gold), ok: attempt === 1,
|
|
178
|
+
}),
|
|
179
|
+
})
|
|
180
|
+
assert.equal(validIncumbent.perTask[0]?.artifact, 'WRONG', 'a failed execution cannot replace a valid incumbent')
|
|
181
|
+
assert.equal(validIncumbent.perTask[0]?.ok, true)
|
|
113
182
|
|
|
114
183
|
// A benchmark's detail may include hidden answer fields; those must never be fed back as hints.
|
|
115
184
|
const leakyGold = 'SECRET-GOLD'
|
|
@@ -141,8 +210,11 @@ async function main(): Promise<void> {
|
|
|
141
210
|
if (runtime.openSandboxRun.toString().includes('beforeStart')) {
|
|
142
211
|
// The default shot path supports benchmark-owned box setup/extract without real sandbox infra.
|
|
143
212
|
const order: string[] = []
|
|
213
|
+
let createdOptions: unknown
|
|
214
|
+
let controlCredential: string | undefined
|
|
144
215
|
const fakeClient = {
|
|
145
|
-
async create() {
|
|
216
|
+
async create(options: unknown) {
|
|
217
|
+
createdOptions = options
|
|
146
218
|
return {
|
|
147
219
|
id: 'box-default-shot',
|
|
148
220
|
async exec(command: string, options?: { sessionId?: string }) {
|
|
@@ -151,7 +223,9 @@ async function main(): Promise<void> {
|
|
|
151
223
|
},
|
|
152
224
|
async *streamPrompt(_prompt: string, options?: { sessionId?: string }) {
|
|
153
225
|
order.push(`stream:session=${options?.sessionId ? 'yes' : 'no'}`)
|
|
226
|
+
yield { type: 'llm_call', data: { tokensIn: 23, tokensOut: 7, costUsd: 0.04 } }
|
|
154
227
|
yield { type: 'result', data: { finalText: 'fallback text' } }
|
|
228
|
+
yield { type: 'done', data: { outcome: { type: 'completed' } } }
|
|
155
229
|
},
|
|
156
230
|
async delete() {
|
|
157
231
|
order.push('delete')
|
|
@@ -175,11 +249,19 @@ async function main(): Promise<void> {
|
|
|
175
249
|
benchmarks: ['boxy'],
|
|
176
250
|
cells: [{ label: 'default-shot', model: 'm', backend: 'sandbox' }],
|
|
177
251
|
routerBaseUrl: 'x',
|
|
178
|
-
routerKey: '
|
|
252
|
+
routerKey: 'sandbox-control-token',
|
|
253
|
+
modelApiKey: 'model-grant-token',
|
|
179
254
|
resolveAdapter: () => boxAdapter,
|
|
180
|
-
resolveClient: () =>
|
|
255
|
+
resolveClient: (options) => {
|
|
256
|
+
controlCredential = options.routerKey
|
|
257
|
+
return fakeClient as never
|
|
258
|
+
},
|
|
181
259
|
})
|
|
182
260
|
assert.equal(boxy.rows[0]!.resolveRate, 1, 'boxExtract artifact is judged instead of fallback text')
|
|
261
|
+
assert.equal(boxy.perTask[0]?.artifact, 'PATCH')
|
|
262
|
+
assert.deepEqual(boxy.perTask[0]?.usage, { input: 23, output: 7, costUsd: 0.04 })
|
|
263
|
+
assert.equal(controlCredential, 'sandbox-control-token', 'inference grant never authorizes sandbox control')
|
|
264
|
+
assert.equal((createdOptions as { backend: { model: { apiKey: string } } }).backend.model.apiKey, 'model-grant-token')
|
|
183
265
|
assert.deepEqual(
|
|
184
266
|
order.slice(0, 3),
|
|
185
267
|
['exec:setup-repo:streams=0:session=yes', 'stream:session=yes', 'exec:extract-patch:streams=1:session=yes'],
|