@tangle-network/agent-bench 0.8.12 → 0.8.15

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.
@@ -9,16 +9,18 @@ import "@tangle-network/agent-interface";
9
9
  */
10
10
  async function runBenchRouterTurn(config, input) {
11
11
  if (!config.profile.model?.default) throw new Error("runBenchRouterTurn: profile.model.default is required");
12
+ const factory = createExecutor({
13
+ backend: "router",
14
+ routerBaseUrl: config.routerBaseUrl,
15
+ routerKey: config.routerKey,
16
+ ...config.tools ? { tools: config.tools } : {}
17
+ });
18
+ const turnInput = typeof input === "string" ? { prompt: input } : { providerOptions: { messages: input.messages.map((message) => ({ ...message })) } };
12
19
  const turn = await collectAgentTurn(streamAgentTurn({
13
20
  kind: "executor",
14
- factory: createExecutor({
15
- backend: "router",
16
- routerBaseUrl: config.routerBaseUrl,
17
- routerKey: config.routerKey,
18
- ...config.tools ? { tools: config.tools } : {}
19
- }),
21
+ factory,
20
22
  profile: config.profile
21
- }, input, {
23
+ }, turnInput, {
22
24
  ...config.timeoutMs === void 0 ? {} : { timeoutMs: config.timeoutMs },
23
25
  ...config.signal ? { signal: config.signal } : {}
24
26
  }));
@@ -28,4 +30,4 @@ async function runBenchRouterTurn(config, input) {
28
30
  //#endregion
29
31
  export { runBenchRouterTurn as t };
30
32
 
31
- //# sourceMappingURL=router-turn-C2wMiDoo.js.map
33
+ //# sourceMappingURL=router-turn-uTYO6KQ1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-turn-uTYO6KQ1.js","names":[],"sources":["../src/router-turn.ts"],"sourcesContent":["import {\n type AgentProfile,\n agentProfileSchema,\n type ReasoningEffort,\n} from '@tangle-network/agent-interface'\nimport {\n collectAgentTurn,\n createExecutor,\n streamAgentTurn,\n type AgentTurnInput,\n type CollectedAgentTurn,\n type ToolSpec,\n} from '@tangle-network/agent-runtime/kernel'\n\n/** Bench-local target shorthand; Runtime still executes only the exact profile below. */\nexport interface BenchRouterTarget {\n routerBaseUrl: string\n routerKey: string\n profile: AgentProfile\n}\n\nexport interface BenchRouterTurnConfig extends BenchRouterTarget {\n tools?: ReadonlyArray<ToolSpec>\n timeoutMs?: number\n signal?: AbortSignal\n}\n\nexport interface BenchProfileSettings {\n systemPrompt?: string\n temperature?: number\n maxTokens?: number\n retry?: {\n maxAttempts?: number\n initialBackoffMs?: number\n maxBackoffMs?: number\n jitter?: number\n retryStatuses?: ReadonlyArray<number>\n requestTimeoutMs?: number\n }\n maxTurns?: number\n seed?: number\n reasoningEffort?: ReasoningEffort\n extraBody?: Readonly<Record<string, unknown>>\n toolChoice?: 'auto' | 'required' | 'none'\n}\n\n/** Author an exact direct-Router profile for a benchmark. This is profile construction only;\n * execution still accepts no model or generation fields outside the returned AgentProfile. */\nexport function benchRouterProfile(\n name: string,\n model: string,\n settings: BenchProfileSettings = {},\n): AgentProfile {\n return withBenchProfile(\n {\n name,\n harness: 'cli-base',\n model: { provider: 'tangle-router', default: model },\n },\n settings,\n )\n}\n\n/** Derive another exact profile while preserving all untouched canonical axes. */\nexport function withBenchProfile(\n base: AgentProfile,\n settings: BenchProfileSettings & { name?: string },\n): AgentProfile {\n const metadata = {\n ...(base.model?.metadata ?? {}),\n ...(settings.temperature !== undefined ? { temperature: settings.temperature } : {}),\n ...(settings.maxTokens !== undefined ? { maxTokens: settings.maxTokens } : {}),\n ...(settings.retry !== undefined ? { retry: settings.retry } : {}),\n ...(settings.maxTurns !== undefined ? { maxTurns: settings.maxTurns } : {}),\n ...(settings.seed !== undefined ? { seed: settings.seed } : {}),\n ...(settings.extraBody !== undefined ? { extraBody: settings.extraBody } : {}),\n ...(settings.toolChoice !== undefined ? { toolChoice: settings.toolChoice } : {}),\n }\n return agentProfileSchema.parse({\n ...base,\n ...(settings.name ? { name: settings.name } : {}),\n model: {\n ...base.model,\n ...(settings.reasoningEffort !== undefined\n ? { reasoningEffort: settings.reasoningEffort }\n : {}),\n ...(Object.keys(metadata).length > 0 ? { metadata } : {}),\n },\n ...(settings.systemPrompt !== undefined\n ? { prompt: { ...base.prompt, systemPrompt: settings.systemPrompt } }\n : {}),\n })\n}\n\nexport function benchProfileModel(profile: AgentProfile): string {\n const model = profile.model?.default\n if (typeof model !== 'string' || model.length === 0 || model === 'runtime-selected') {\n throw new Error('benchmark AgentProfile.model.default must be concrete')\n }\n return model\n}\n\n/**\n * The benchmark-side entry to Runtime's canonical one-turn path.\n * It is only an ergonomic composition: Runtime still parses the exact profile,\n * materializes the executor, records identity/usage/result events, and refuses\n * profile axes the direct Router backend cannot carry.\n */\nexport async function runBenchRouterTurn(\n config: BenchRouterTurnConfig,\n input: string | { readonly messages: ReadonlyArray<Readonly<Record<string, unknown>>> },\n): Promise<CollectedAgentTurn> {\n if (!config.profile.model?.default) {\n throw new Error('runBenchRouterTurn: profile.model.default is required')\n }\n const factory = createExecutor({\n backend: 'router',\n routerBaseUrl: config.routerBaseUrl,\n routerKey: config.routerKey,\n ...(config.tools ? { tools: config.tools } : {}),\n })\n const turnInput: AgentTurnInput =\n typeof input === 'string'\n ? { prompt: input }\n : {\n providerOptions: {\n messages: input.messages.map((message) => ({ ...message })),\n },\n }\n const turn = await collectAgentTurn(\n streamAgentTurn(\n { kind: 'executor', factory, profile: config.profile },\n turnInput,\n {\n ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),\n ...(config.signal ? { signal: config.signal } : {}),\n },\n ),\n )\n if (turn.status !== 'completed') {\n throw new Error(turn.error?.message ?? `Router turn ended with status ${turn.status}`)\n }\n return turn\n}\n"],"mappings":";;;;;;;;;AA4GA,eAAsB,mBACpB,QACA,OAC6B;CAC7B,IAAI,CAAC,OAAO,QAAQ,OAAO,SACzB,MAAM,IAAI,MAAM,uDAAuD;CAEzE,MAAM,UAAU,eAAe;EAC7B,SAAS;EACT,eAAe,OAAO;EACtB,WAAW,OAAO;EAClB,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;CAChD,CAAC;CACD,MAAM,YACJ,OAAO,UAAU,WACb,EAAE,QAAQ,MAAM,IAChB,EACE,iBAAiB,EACf,UAAU,MAAM,SAAS,KAAK,aAAa,EAAE,GAAG,QAAQ,EAAE,EAC5D,EACF;CACN,MAAM,OAAO,MAAM,iBACjB,gBACE;EAAE,MAAM;EAAY;EAAS,SAAS,OAAO;CAAQ,GACrD,WACA;EACE,GAAI,OAAO,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,OAAO,UAAU;EACxE,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;CACnD,CACF,CACF;CACA,IAAI,KAAK,WAAW,aAClB,MAAM,IAAI,MAAM,KAAK,OAAO,WAAW,iCAAiC,KAAK,QAAQ;CAEvF,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-bench",
3
- "version": "0.8.12",
3
+ "version": "0.8.15",
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,11 +25,11 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@tangle-network/agent-eval": "0.145.21",
29
- "@tangle-network/agent-interface": "1.0.0",
30
- "@tangle-network/agent-knowledge": "8.0.5",
31
- "@tangle-network/sandbox": "0.27.1",
32
- "@tangle-network/agent-runtime": "0.137.0"
28
+ "@tangle-network/agent-eval": ">=0.148.0 <0.149.0",
29
+ "@tangle-network/agent-interface": "^1.1.0",
30
+ "@tangle-network/agent-knowledge": "^8.0.9",
31
+ "@tangle-network/sandbox": ">=0.27.1 <0.28.0",
32
+ "@tangle-network/agent-runtime": "^0.141.1"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@arethetypeswrong/cli": "0.18.5",
@@ -73,7 +73,8 @@
73
73
  "typecheck:public": "tsc -p tsconfig.public.json",
74
74
  "verify:package": "pnpm run verify:package:static && node scripts/verify-packed-consumer.mjs",
75
75
  "verify:package:local-runtime": "pnpm run verify:package:static && node scripts/verify-packed-consumer.mjs --local-runtime",
76
- "verify:package:static": "pnpm run build && publint && attw --pack --profile esm-only .",
76
+ "verify:package:static": "pnpm run build && publint && attw --pack --profile esm-only . && node ../scripts/check-published-ranges.mjs bench && node ../scripts/check-api-surface.mjs bench",
77
+ "api:surface": "node ../scripts/check-api-surface.mjs --write bench",
77
78
  "wait:published-dependencies": "node scripts/wait-for-published-dependencies.mjs",
78
79
  "verify:pier": "tsx scripts/verify-pier-pair.mts"
79
80
  }
@@ -226,7 +226,7 @@ export async function callAuthor(
226
226
  const turn = await collectAgentTurn(
227
227
  streamAgentTurn(
228
228
  { kind: 'executor', factory, profile, agentRunName: profile.name ?? 'agent-graphs-author' },
229
- prompt,
229
+ { prompt },
230
230
  timeoutMs === undefined ? {} : { timeoutMs },
231
231
  ),
232
232
  )
@@ -103,7 +103,7 @@ async function bridgeChat(opts: {
103
103
  const turn = await collectAgentTurn(
104
104
  streamAgentTurn(
105
105
  { kind: 'executor', factory, profile },
106
- opts.messages.map((message) => message.content).join('\n\n'),
106
+ { prompt: opts.messages.map((message) => message.content).join('\n\n') },
107
107
  ),
108
108
  )
109
109
  if (turn.status !== 'completed') {
@@ -440,7 +440,7 @@ export function appworldToolLoopClient(cfg: {
440
440
  const loop = await collectAgentTurn(
441
441
  streamAgentTurn(
442
442
  { kind: 'executor', factory, profile },
443
- `Task: ${instruction}`,
443
+ { prompt: `Task: ${instruction}` },
444
444
  { signal },
445
445
  ),
446
446
  )
@@ -330,7 +330,7 @@ async function runShotLocal(task: BenchTask, attempt: number, cfg: ShotCfg, stee
330
330
  const turn = await collectAgentTurn(
331
331
  streamAgentTurn(
332
332
  { kind: 'executor', factory, profile: workerProfile(cfg, `commit0-local-${attempt}`) },
333
- prompt,
333
+ { prompt },
334
334
  cfg.timeoutMs > 0 ? { timeoutMs: cfg.timeoutMs } : {},
335
335
  ),
336
336
  )
@@ -89,7 +89,7 @@ async function repairAttempt(cfg: BenchRouterTarget, task: HumanEvalTask, k: num
89
89
  },
90
90
  })
91
91
  const r = await collectAgentTurn(
92
- streamAgentTurn({ kind: 'executor', factory, profile }, basePrompt(task)),
92
+ streamAgentTurn({ kind: 'executor', factory, profile }, { prompt: basePrompt(task) }),
93
93
  )
94
94
  if (r.status !== 'completed') {
95
95
  throw new Error(r.error?.message ?? `repair turn ended with status ${r.status}`)
@@ -70,7 +70,7 @@ async function bridgeChat(messages: Array<{ role: string; content: string }>, mc
70
70
  const turn = await collectAgentTurn(
71
71
  streamAgentTurn(
72
72
  { kind: 'executor', factory, profile },
73
- messages.map((message) => message.content).join('\n\n'),
73
+ { prompt: messages.map((message) => message.content).join('\n\n') },
74
74
  ),
75
75
  )
76
76
  if (turn.status !== 'completed') {
@@ -249,7 +249,7 @@ async function profileShot(opts: {
249
249
  const turn = await collectAgentTurn(
250
250
  streamAgentTurn(
251
251
  { kind: 'executor', factory, profile: opts.profile },
252
- opts.prompt,
252
+ { prompt: opts.prompt },
253
253
  { timeoutMs: opts.timeoutMs },
254
254
  ),
255
255
  )
@@ -7,6 +7,7 @@ import {
7
7
  collectAgentTurn,
8
8
  createExecutor,
9
9
  streamAgentTurn,
10
+ type AgentTurnInput,
10
11
  type CollectedAgentTurn,
11
12
  type ToolSpec,
12
13
  } from '@tangle-network/agent-runtime/kernel'
@@ -118,10 +119,18 @@ export async function runBenchRouterTurn(
118
119
  routerKey: config.routerKey,
119
120
  ...(config.tools ? { tools: config.tools } : {}),
120
121
  })
122
+ const turnInput: AgentTurnInput =
123
+ typeof input === 'string'
124
+ ? { prompt: input }
125
+ : {
126
+ providerOptions: {
127
+ messages: input.messages.map((message) => ({ ...message })),
128
+ },
129
+ }
121
130
  const turn = await collectAgentTurn(
122
131
  streamAgentTurn(
123
132
  { kind: 'executor', factory, profile: config.profile },
124
- input,
133
+ turnInput,
125
134
  {
126
135
  ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),
127
136
  ...(config.signal ? { signal: config.signal } : {}),
@@ -185,13 +185,17 @@ const openSandboxShot: BenchShot = async ({ adapter, task, cell, prompt, routerB
185
185
  ...(timeoutMs ? { timeoutMs } : {}),
186
186
  })
187
187
  const harness = cell.harness ?? (cell.profile?.metadata?.backendType as string | undefined) ?? 'opencode'
188
- const profile: AgentProfile =
189
- cell.profile ?? {
190
- name: cell.label,
191
- harness: harness as AgentProfile['harness'],
192
- model: { provider: 'tangle-router', default: cell.model },
193
- metadata: { backendType: harness },
194
- }
188
+ // The cell's harness and model are the identity the box must run, so they override whatever a
189
+ // supplied profile declared rather than being dropped when one is supplied. `buildBackendOptions`
190
+ // now sends this provider/model pair on the create request and refuses a conflicting override,
191
+ // so the two must be derived from the same profile.
192
+ const profileProvider = cell.profile?.model?.provider ?? 'tangle-router'
193
+ const profile: AgentProfile = {
194
+ ...(cell.profile ?? { name: cell.label }),
195
+ harness: harness as AgentProfile['harness'],
196
+ model: { ...cell.profile?.model, provider: profileProvider, default: cell.model },
197
+ metadata: { ...cell.profile?.metadata, backendType: harness },
198
+ }
195
199
  // Unique per shot: the same (adapter, task) runs concurrently across cells and reps, so the box
196
200
  // name and runId must not collide.
197
201
  const uniq = Math.random().toString(36).slice(2, 8)
@@ -202,7 +206,7 @@ const openSandboxShot: BenchShot = async ({ adapter, task, cell, prompt, routerB
202
206
  sandboxOverrides: {
203
207
  name: `bench-${adapter.name}-${task.id}-${uniq}`.replace(/[^a-zA-Z0-9_.-]/g, '_').slice(0, 60),
204
208
  environment: 'universal',
205
- backend: { type: harness as never, model: { provider: 'openai', model: cell.model, baseUrl: routerBaseUrl } },
209
+ backend: { type: harness as never, model: { provider: profileProvider, model: cell.model, baseUrl: routerBaseUrl } },
206
210
  },
207
211
  }
208
212
  const deliverable: Deliverable<string> = {
@@ -525,7 +525,7 @@ export async function runSoloArm(spec: SoloArmSpec, ctx: ArmRunContext): Promise
525
525
  const turn = await collectAgentTurn(
526
526
  streamAgentTurn(
527
527
  { kind: 'executor', factory, profile: spec.profile },
528
- prompt,
528
+ { prompt },
529
529
  { timeoutMs, ...(ctx.signal ? { signal: ctx.signal } : {}) },
530
530
  ),
531
531
  )
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-turn-C2wMiDoo.js","names":[],"sources":["../src/router-turn.ts"],"sourcesContent":["import {\n type AgentProfile,\n agentProfileSchema,\n type ReasoningEffort,\n} from '@tangle-network/agent-interface'\nimport {\n collectAgentTurn,\n createExecutor,\n streamAgentTurn,\n type CollectedAgentTurn,\n type ToolSpec,\n} from '@tangle-network/agent-runtime/kernel'\n\n/** Bench-local target shorthand; Runtime still executes only the exact profile below. */\nexport interface BenchRouterTarget {\n routerBaseUrl: string\n routerKey: string\n profile: AgentProfile\n}\n\nexport interface BenchRouterTurnConfig extends BenchRouterTarget {\n tools?: ReadonlyArray<ToolSpec>\n timeoutMs?: number\n signal?: AbortSignal\n}\n\nexport interface BenchProfileSettings {\n systemPrompt?: string\n temperature?: number\n maxTokens?: number\n retry?: {\n maxAttempts?: number\n initialBackoffMs?: number\n maxBackoffMs?: number\n jitter?: number\n retryStatuses?: ReadonlyArray<number>\n requestTimeoutMs?: number\n }\n maxTurns?: number\n seed?: number\n reasoningEffort?: ReasoningEffort\n extraBody?: Readonly<Record<string, unknown>>\n toolChoice?: 'auto' | 'required' | 'none'\n}\n\n/** Author an exact direct-Router profile for a benchmark. This is profile construction only;\n * execution still accepts no model or generation fields outside the returned AgentProfile. */\nexport function benchRouterProfile(\n name: string,\n model: string,\n settings: BenchProfileSettings = {},\n): AgentProfile {\n return withBenchProfile(\n {\n name,\n harness: 'cli-base',\n model: { provider: 'tangle-router', default: model },\n },\n settings,\n )\n}\n\n/** Derive another exact profile while preserving all untouched canonical axes. */\nexport function withBenchProfile(\n base: AgentProfile,\n settings: BenchProfileSettings & { name?: string },\n): AgentProfile {\n const metadata = {\n ...(base.model?.metadata ?? {}),\n ...(settings.temperature !== undefined ? { temperature: settings.temperature } : {}),\n ...(settings.maxTokens !== undefined ? { maxTokens: settings.maxTokens } : {}),\n ...(settings.retry !== undefined ? { retry: settings.retry } : {}),\n ...(settings.maxTurns !== undefined ? { maxTurns: settings.maxTurns } : {}),\n ...(settings.seed !== undefined ? { seed: settings.seed } : {}),\n ...(settings.extraBody !== undefined ? { extraBody: settings.extraBody } : {}),\n ...(settings.toolChoice !== undefined ? { toolChoice: settings.toolChoice } : {}),\n }\n return agentProfileSchema.parse({\n ...base,\n ...(settings.name ? { name: settings.name } : {}),\n model: {\n ...base.model,\n ...(settings.reasoningEffort !== undefined\n ? { reasoningEffort: settings.reasoningEffort }\n : {}),\n ...(Object.keys(metadata).length > 0 ? { metadata } : {}),\n },\n ...(settings.systemPrompt !== undefined\n ? { prompt: { ...base.prompt, systemPrompt: settings.systemPrompt } }\n : {}),\n })\n}\n\nexport function benchProfileModel(profile: AgentProfile): string {\n const model = profile.model?.default\n if (typeof model !== 'string' || model.length === 0 || model === 'runtime-selected') {\n throw new Error('benchmark AgentProfile.model.default must be concrete')\n }\n return model\n}\n\n/**\n * The benchmark-side entry to Runtime's canonical one-turn path.\n * It is only an ergonomic composition: Runtime still parses the exact profile,\n * materializes the executor, records identity/usage/result events, and refuses\n * profile axes the direct Router backend cannot carry.\n */\nexport async function runBenchRouterTurn(\n config: BenchRouterTurnConfig,\n input: string | { readonly messages: ReadonlyArray<Readonly<Record<string, unknown>>> },\n): Promise<CollectedAgentTurn> {\n if (!config.profile.model?.default) {\n throw new Error('runBenchRouterTurn: profile.model.default is required')\n }\n const factory = createExecutor({\n backend: 'router',\n routerBaseUrl: config.routerBaseUrl,\n routerKey: config.routerKey,\n ...(config.tools ? { tools: config.tools } : {}),\n })\n const turn = await collectAgentTurn(\n streamAgentTurn(\n { kind: 'executor', factory, profile: config.profile },\n input,\n {\n ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),\n ...(config.signal ? { signal: config.signal } : {}),\n },\n ),\n )\n if (turn.status !== 'completed') {\n throw new Error(turn.error?.message ?? `Router turn ended with status ${turn.status}`)\n }\n return turn\n}\n"],"mappings":";;;;;;;;;AA2GA,eAAsB,mBACpB,QACA,OAC6B;CAC7B,IAAI,CAAC,OAAO,QAAQ,OAAO,SACzB,MAAM,IAAI,MAAM,uDAAuD;CAQzE,MAAM,OAAO,MAAM,iBACjB,gBACE;EAAE,MAAM;EAAY,SARR,eAAe;GAC7B,SAAS;GACT,eAAe,OAAO;GACtB,WAAW,OAAO;GAClB,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;EAChD,CAG8B;EAAG,SAAS,OAAO;CAAQ,GACrD,OACA;EACE,GAAI,OAAO,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,OAAO,UAAU;EACxE,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;CACnD,CACF,CACF;CACA,IAAI,KAAK,WAAW,aAClB,MAAM,IAAI,MAAM,KAAK,OAAO,WAAW,iCAAiC,KAAK,QAAQ;CAEvF,OAAO;AACT"}