@tangle-network/agent-bench 0.4.3 → 0.4.5

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.5
4
+
5
+ - Allow the zero-model Pier proof to complete a cold separate-verifier image build before its task and overall execution deadlines.
6
+ - Consume Runtime 0.107.5 with Eval 0.133.3, Interface 0.36.0, Knowledge 6.1.5, and Sandbox 0.15.1.
7
+
8
+ ## 0.4.4
9
+
10
+ - Consume Runtime 0.107.2 and Sandbox 0.15.0 with the current Eval, Interface, and Knowledge packages.
11
+ - Publish fake Pier terminal results atomically so the full test suite cannot observe partial JSON.
12
+
3
13
  ## 0.4.3
4
14
 
5
15
  - Consume Runtime 0.107.1 with Eval 0.133.0, Interface 0.36.0, and Knowledge 6.1.2.
@@ -16,7 +16,7 @@ tags = ["no-model", "separate-verifier"]
16
16
  timeout_sec = 60.0
17
17
 
18
18
  [verifier]
19
- timeout_sec = 60.0
19
+ timeout_sec = 300.0
20
20
  environment_mode = "separate"
21
21
 
22
22
  [verifier.environment]
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-bench",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "type": "module",
5
- "description": "The unified benchmark suite for agent-runtime agents: 31 adapters (commit0, enterpriseops-gym, ragbench, crag, nomiracl, open-rag-bench, t2-ragbench, tau3-banking, bfcl, finresearchbench, …) behind one resolveAdapter registry, each with a real judge or fail-loud unsupported scorer. Score any profile/skill/prompt change against them. Map: bench/HARNESS.md.",
5
+ "description": "Benchmark adapters and execution for agent-runtime across coding, tool-use, RAG, memory, browser, and terminal tasks.",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/tangle-network/agent-runtime.git",
@@ -25,11 +25,11 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@tangle-network/agent-eval": "0.133.0",
28
+ "@tangle-network/agent-eval": "0.133.3",
29
29
  "@tangle-network/agent-interface": "0.36.0",
30
- "@tangle-network/agent-knowledge": "6.1.2",
31
- "@tangle-network/sandbox": "0.14.0",
32
- "@tangle-network/agent-runtime": "0.107.1"
30
+ "@tangle-network/agent-knowledge": "6.1.5",
31
+ "@tangle-network/sandbox": "0.15.1",
32
+ "@tangle-network/agent-runtime": "0.107.5"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@arethetypeswrong/cli": "0.18.5",
@@ -435,7 +435,7 @@ ${proofArm === 'success' ? "(task / 'src/status.txt').write_text('ready\\nowner=
435
435
  workspace: taskWorkspace,
436
436
  evaluatorTaskContainer: container,
437
437
  limits: {
438
- timeoutMs: 180_000,
438
+ timeoutMs: 600_000,
439
439
  maxSteps: 8,
440
440
  maxModelCalls: 0,
441
441
  maxInputTokens: 0,
@@ -85,18 +85,20 @@ test('the Pier result wait does not add time beyond an expired deadline', async
85
85
  await chmod(fakeDocker, 0o700)
86
86
  await writeFile(
87
87
  supervisorPath,
88
- `import { createReadStream } from 'node:fs'
89
- import { writeFileSync } from 'node:fs'
88
+ `import { createReadStream, renameSync, writeFileSync } from 'node:fs'
90
89
  import path from 'node:path'
91
90
  const directory = process.argv[2]
92
91
  process.on('SIGTERM', () => {
93
- writeFileSync(path.join(directory, 'terminal.json'), JSON.stringify({
92
+ const target = path.join(directory, 'terminal.json')
93
+ const temporary = path.join(directory, '.terminal.json.tmp')
94
+ writeFileSync(temporary, JSON.stringify({
94
95
  schemaVersion: 1,
95
96
  kind: 'pier-trial-terminal',
96
97
  status: 'stopped',
97
98
  processExited: true,
98
99
  containersRemoved: true,
99
100
  }))
101
+ renameSync(temporary, target)
100
102
  process.exit(0)
101
103
  })
102
104
  for await (const _chunk of createReadStream('', { fd: 3 })) {}
@@ -156,7 +158,7 @@ test('the supervisor receives only launch data and no inherited evaluator enviro
156
158
  await chmod(fakeDocker, 0o700)
157
159
  await writeFile(
158
160
  supervisorPath,
159
- `import { createReadStream, writeFileSync } from 'node:fs'
161
+ `import { createReadStream, renameSync, writeFileSync } from 'node:fs'
160
162
  import path from 'node:path'
161
163
  const chunks = []
162
164
  for await (const chunk of createReadStream('', { fd: 3 })) chunks.push(Buffer.from(chunk))
@@ -165,7 +167,9 @@ const isolated = process.env.PIER_SUPERVISOR_MODE === 'explicit' &&
165
167
  process.env.PIER_PARENT_SECRET === undefined &&
166
168
  launch.env.PIER_PARENT_SECRET === undefined &&
167
169
  launch.env.PIER_CHILD_SECRET === 'child-only'
168
- writeFileSync(path.join(process.argv[2], 'terminal.json'), JSON.stringify({
170
+ const target = path.join(process.argv[2], 'terminal.json')
171
+ const temporary = path.join(process.argv[2], '.terminal.json.tmp')
172
+ writeFileSync(temporary, JSON.stringify({
169
173
  schemaVersion: 1,
170
174
  kind: 'pier-trial-terminal',
171
175
  status: isolated ? 'completed' : 'failed',
@@ -173,6 +177,7 @@ writeFileSync(path.join(process.argv[2], 'terminal.json'), JSON.stringify({
173
177
  containersRemoved: true,
174
178
  ...(isolated ? {} : { error: 'supervisor inherited evaluator environment' }),
175
179
  }))
180
+ renameSync(temporary, target)
176
181
  `,
177
182
  )
178
183
  const controller = new FilePierCandidateTrialController({
@@ -224,10 +229,12 @@ test('terminal acknowledgements reject unknown fields', async () => {
224
229
  await chmod(fakeDocker, 0o700)
225
230
  await writeFile(
226
231
  supervisorPath,
227
- `import { createReadStream, writeFileSync } from 'node:fs'
232
+ `import { createReadStream, renameSync, writeFileSync } from 'node:fs'
228
233
  import path from 'node:path'
229
234
  for await (const _chunk of createReadStream('', { fd: 3 })) {}
230
- writeFileSync(path.join(process.argv[2], 'terminal.json'), JSON.stringify({
235
+ const target = path.join(process.argv[2], 'terminal.json')
236
+ const temporary = path.join(process.argv[2], '.terminal.json.tmp')
237
+ writeFileSync(temporary, JSON.stringify({
231
238
  schemaVersion: 1,
232
239
  kind: 'pier-trial-terminal',
233
240
  status: 'completed',
@@ -235,6 +242,7 @@ writeFileSync(path.join(process.argv[2], 'terminal.json'), JSON.stringify({
235
242
  containersRemoved: true,
236
243
  containerRemoved: true,
237
244
  }))
245
+ renameSync(temporary, target)
238
246
  `,
239
247
  )
240
248
  const controller = new FilePierCandidateTrialController({
@@ -3,11 +3,25 @@ import { tmpdir } from 'node:os'
3
3
  import { join } from 'node:path'
4
4
  import { afterAll, describe, expect, it } from 'vitest'
5
5
  import { runSupervisorShim, supervisorDriverKillGraceMs } from './arms.ts'
6
- import { run, TIMEOUT_RC } from './proc.ts'
6
+ import { ABORT_RC, run } from './proc.ts'
7
7
 
8
8
  const dirs: string[] = []
9
9
  const workerPids: number[] = []
10
10
 
11
+ async function waitForFile(path: string, timeoutMs = 10_000): Promise<void> {
12
+ const deadline = Date.now() + timeoutMs
13
+ while (Date.now() < deadline) {
14
+ try {
15
+ await access(path)
16
+ return
17
+ } catch (error) {
18
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
19
+ }
20
+ await new Promise((resolve) => setTimeout(resolve, 10))
21
+ }
22
+ throw new Error(`timed out waiting for ${path}`)
23
+ }
24
+
11
25
  afterAll(async () => {
12
26
  for (const pid of workerPids) {
13
27
  try {
@@ -122,6 +136,7 @@ export default function fakeExtension(pi) {
122
136
  writeFileSync(join(runDir, 'state.json'), JSON.stringify({ status: 'running' }))
123
137
  appendFileSync(join(runDir, 'journal.jsonl'), JSON.stringify({ kind: 'spawned', id, label: 'root' }) + '\\n')
124
138
  appendFileSync(join(runDir, 'journal.jsonl'), JSON.stringify({ kind: 'spawned', id: id + ':s1', parent: id, label: 'w-0' }) + '\\n')
139
+ writeFileSync(join(ctx.cwd, 'outer-driver-ready.txt'), 'ready')
125
140
  return text('spawned supervisor ' + id)
126
141
  },
127
142
  })
@@ -140,10 +155,11 @@ export default function fakeExtension(pi) {
140
155
  `)
141
156
 
142
157
  const cancelTimeoutMs = 1_500
143
- const result = await run(process.execPath, [
158
+ const controller = new AbortController()
159
+ const resultPromise = run(process.execPath, [
144
160
  '--import', 'tsx', runSupervisorShim, extension, workspace, params,
145
161
  ], {
146
- timeoutMs: 1_000,
162
+ signal: controller.signal,
147
163
  killGraceMs: supervisorDriverKillGraceMs({
148
164
  DRIVER_CANCEL_TIMEOUT_MS: String(cancelTimeoutMs),
149
165
  }),
@@ -154,9 +170,19 @@ export default function fakeExtension(pi) {
154
170
  DRIVER_CANCEL_TIMEOUT_MS: String(cancelTimeoutMs),
155
171
  },
156
172
  })
173
+ try {
174
+ await waitForFile(join(workspace, 'outer-driver-ready.txt'))
175
+ } catch (error) {
176
+ controller.abort()
177
+ await resultPromise
178
+ throw error
179
+ }
180
+ controller.abort()
181
+ const result = await resultPromise
157
182
 
158
- expect(result.code, result.stdout + result.stderr).toBe(TIMEOUT_RC)
159
- expect(result.timedOut).toBe(true)
183
+ expect(result.code, result.stdout + result.stderr).toBe(ABORT_RC)
184
+ expect(result.aborted).toBe(true)
185
+ expect(result.timedOut).toBe(false)
160
186
  expect(await readFile(join(workspace, 'outer-cancel-settled.txt'), 'utf8')).toBe('settled')
161
187
  expect(JSON.parse(await readFile(join(workspace, '.loops', 'supervisor', 'sup-2-fake34', 'state.json'), 'utf8')))
162
188
  .toMatchObject({ status: 'cancelled' })
@@ -170,10 +196,10 @@ export default function fakeExtension(pi) {
170
196
  const extension = join(dir, 'fake-extension.mjs')
171
197
  await mkdir(workspace)
172
198
  await writeFile(params, '{}')
173
- const workerScript = `const fs=require('node:fs'); const marker=process.argv[1]; process.on('SIGTERM',()=>setTimeout(()=>{fs.writeFileSync(marker,'clean'); process.exit(0)},30)); setInterval(()=>{},1000)`
199
+ const workerScript = `const fs=require('node:fs'); const marker=process.argv[1]; const ready=process.argv[2]; process.on('SIGTERM',()=>setTimeout(()=>{fs.writeFileSync(marker,'clean'); process.exit(0)},30)); fs.writeFileSync(ready,'ready'); setInterval(()=>{},1000)`
174
200
  await writeFile(extension, `
175
201
  import { spawn } from 'node:child_process'
176
- import { appendFileSync, mkdirSync, writeFileSync } from 'node:fs'
202
+ import { appendFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs'
177
203
  import { join } from 'node:path'
178
204
 
179
205
  const id = 'sup-3-signal56'
@@ -188,11 +214,13 @@ export default function fakeExtension(pi) {
188
214
  writeFileSync(join(runDir, 'state.json'), JSON.stringify({ status: 'running' }))
189
215
  appendFileSync(join(runDir, 'journal.jsonl'), JSON.stringify({ kind: 'spawned', id, label: 'root' }) + '\\n')
190
216
  appendFileSync(join(runDir, 'journal.jsonl'), JSON.stringify({ kind: 'spawned', id: id + ':s1', parent: id, label: 'w-0' }) + '\\n')
191
- child = spawn(process.execPath, ['-e', ${JSON.stringify(workerScript)}, join(ctx.cwd, 'signal-worker-cleaned.txt')], {
217
+ const readyPath = join(ctx.cwd, 'signal-worker-ready.txt')
218
+ child = spawn(process.execPath, ['-e', ${JSON.stringify(workerScript)}, join(ctx.cwd, 'signal-worker-cleaned.txt'), readyPath], {
192
219
  detached: true,
193
220
  stdio: 'ignore',
194
221
  })
195
222
  writeFileSync(join(ctx.cwd, 'signal-worker.pid'), String(child.pid))
223
+ while (!existsSync(readyPath)) await new Promise((resolve) => setTimeout(resolve, 5))
196
224
  writeFileSync(join(ctx.cwd, 'spawn-entered.txt'), 'entered')
197
225
  await new Promise((resolve) => setTimeout(resolve, 30_000))
198
226
  return text('spawned supervisor ' + id)
@@ -214,10 +242,11 @@ export default function fakeExtension(pi) {
214
242
  `)
215
243
 
216
244
  const cancelTimeoutMs = 2_000
217
- const result = await run(process.execPath, [
245
+ const controller = new AbortController()
246
+ const resultPromise = run(process.execPath, [
218
247
  '--import', 'tsx', runSupervisorShim, extension, workspace, params,
219
248
  ], {
220
- timeoutMs: 1_000,
249
+ signal: controller.signal,
221
250
  killGraceMs: supervisorDriverKillGraceMs({
222
251
  DRIVER_CANCEL_TIMEOUT_MS: String(cancelTimeoutMs),
223
252
  }),
@@ -228,11 +257,21 @@ export default function fakeExtension(pi) {
228
257
  DRIVER_CANCEL_TIMEOUT_MS: String(cancelTimeoutMs),
229
258
  },
230
259
  })
260
+ try {
261
+ await waitForFile(join(workspace, 'spawn-entered.txt'))
262
+ } catch (error) {
263
+ controller.abort()
264
+ await resultPromise
265
+ throw error
266
+ }
267
+ controller.abort()
268
+ const result = await resultPromise
231
269
  const workerPid = Number(await readFile(join(workspace, 'signal-worker.pid'), 'utf8'))
232
270
  workerPids.push(workerPid)
233
271
 
234
- expect(result.code, result.stdout + result.stderr).toBe(TIMEOUT_RC)
235
- expect(result.timedOut).toBe(true)
272
+ expect(result.code, result.stdout + result.stderr).toBe(ABORT_RC)
273
+ expect(result.aborted).toBe(true)
274
+ expect(result.timedOut).toBe(false)
236
275
  expect(await readFile(join(workspace, 'spawn-entered.txt'), 'utf8')).toBe('entered')
237
276
  expect(await readFile(join(workspace, 'signal-worker-cleaned.txt'), 'utf8')).toBe('clean')
238
277
  expect(await readFile(join(workspace, 'signal-cancel-settled.txt'), 'utf8')).toBe('settled')