@claude-flow/cli 3.10.4 → 3.10.6
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/dist/src/benchmarks/capability-tasks.d.ts +126 -0
- package/dist/src/benchmarks/capability-tasks.d.ts.map +1 -0
- package/dist/src/benchmarks/capability-tasks.js +147 -0
- package/dist/src/benchmarks/capability-tasks.js.map +1 -0
- package/dist/src/benchmarks/gaia-agent-contrastive.d.ts +53 -0
- package/dist/src/benchmarks/gaia-agent-contrastive.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent-contrastive.js +177 -0
- package/dist/src/benchmarks/gaia-agent-contrastive.js.map +1 -0
- package/dist/src/benchmarks/gaia-agent-gemini.d.ts +51 -0
- package/dist/src/benchmarks/gaia-agent-gemini.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent-gemini.js +352 -0
- package/dist/src/benchmarks/gaia-agent-gemini.js.map +1 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts +18 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.js +253 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-agent.d.ts +198 -0
- package/dist/src/benchmarks/gaia-agent.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent.js +651 -0
- package/dist/src/benchmarks/gaia-agent.js.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.d.ts +133 -0
- package/dist/src/benchmarks/gaia-causal-memory.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.js +281 -0
- package/dist/src/benchmarks/gaia-causal-memory.js.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +22 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.js +300 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-claude-p.d.ts +105 -0
- package/dist/src/benchmarks/gaia-claude-p.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-claude-p.js +269 -0
- package/dist/src/benchmarks/gaia-claude-p.js.map +1 -0
- package/dist/src/benchmarks/gaia-claude-p.smoke.d.ts +20 -0
- package/dist/src/benchmarks/gaia-claude-p.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-claude-p.smoke.js +168 -0
- package/dist/src/benchmarks/gaia-claude-p.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-codeagent-runner.py +556 -0
- package/dist/src/benchmarks/gaia-codeagent.d.ts +129 -0
- package/dist/src/benchmarks/gaia-codeagent.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-codeagent.js +590 -0
- package/dist/src/benchmarks/gaia-codeagent.js.map +1 -0
- package/dist/src/benchmarks/gaia-codeagent.smoke.d.ts +33 -0
- package/dist/src/benchmarks/gaia-codeagent.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-codeagent.smoke.js +241 -0
- package/dist/src/benchmarks/gaia-codeagent.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.d.ts +138 -0
- package/dist/src/benchmarks/gaia-convergence.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.js +260 -0
- package/dist/src/benchmarks/gaia-convergence.js.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.d.ts +19 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.js +246 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-critic.d.ts +123 -0
- package/dist/src/benchmarks/gaia-critic.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-critic.js +312 -0
- package/dist/src/benchmarks/gaia-critic.js.map +1 -0
- package/dist/src/benchmarks/gaia-critic.smoke.d.ts +21 -0
- package/dist/src/benchmarks/gaia-critic.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-critic.smoke.js +327 -0
- package/dist/src/benchmarks/gaia-critic.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-dag-pilot.d.ts +22 -0
- package/dist/src/benchmarks/gaia-dag-pilot.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-dag-pilot.js +158 -0
- package/dist/src/benchmarks/gaia-dag-pilot.js.map +1 -0
- package/dist/src/benchmarks/gaia-dag.d.ts +110 -0
- package/dist/src/benchmarks/gaia-dag.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-dag.js +658 -0
- package/dist/src/benchmarks/gaia-dag.js.map +1 -0
- package/dist/src/benchmarks/gaia-dag.smoke.d.ts +21 -0
- package/dist/src/benchmarks/gaia-dag.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-dag.smoke.js +290 -0
- package/dist/src/benchmarks/gaia-dag.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.d.ts +125 -0
- package/dist/src/benchmarks/gaia-decomposer.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.js +350 -0
- package/dist/src/benchmarks/gaia-decomposer.js.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +21 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.js +228 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.d.ts +27 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.js +136 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-ensemble-pilot.d.ts +17 -0
- package/dist/src/benchmarks/gaia-ensemble-pilot.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-ensemble-pilot.js +106 -0
- package/dist/src/benchmarks/gaia-ensemble-pilot.js.map +1 -0
- package/dist/src/benchmarks/gaia-ensemble.d.ts +103 -0
- package/dist/src/benchmarks/gaia-ensemble.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-ensemble.js +462 -0
- package/dist/src/benchmarks/gaia-ensemble.js.map +1 -0
- package/dist/src/benchmarks/gaia-extract.smoke.d.ts +45 -0
- package/dist/src/benchmarks/gaia-extract.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-extract.smoke.js +242 -0
- package/dist/src/benchmarks/gaia-extract.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-gemini-pilot.d.ts +17 -0
- package/dist/src/benchmarks/gaia-gemini-pilot.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-gemini-pilot.js +168 -0
- package/dist/src/benchmarks/gaia-gemini-pilot.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/features.d.ts +46 -0
- package/dist/src/benchmarks/gaia-hardness/features.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/features.js +170 -0
- package/dist/src/benchmarks/gaia-hardness/features.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.d.ts +105 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.js +260 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +20 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +235 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +51 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.js +179 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.js.map +1 -0
- package/dist/src/benchmarks/gaia-judge.d.ts +88 -0
- package/dist/src/benchmarks/gaia-judge.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-judge.js +437 -0
- package/dist/src/benchmarks/gaia-judge.js.map +1 -0
- package/dist/src/benchmarks/gaia-loader.d.ts +87 -0
- package/dist/src/benchmarks/gaia-loader.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-loader.js +326 -0
- package/dist/src/benchmarks/gaia-loader.js.map +1 -0
- package/dist/src/benchmarks/gaia-mode-router.d.ts +67 -0
- package/dist/src/benchmarks/gaia-mode-router.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-mode-router.js +126 -0
- package/dist/src/benchmarks/gaia-mode-router.js.map +1 -0
- package/dist/src/benchmarks/gaia-mode-router.smoke.d.ts +15 -0
- package/dist/src/benchmarks/gaia-mode-router.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-mode-router.smoke.js +131 -0
- package/dist/src/benchmarks/gaia-mode-router.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/file_read.d.ts +35 -0
- package/dist/src/benchmarks/gaia-tools/file_read.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/file_read.js +403 -0
- package/dist/src/benchmarks/gaia-tools/file_read.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +126 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.js +225 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.smoke.d.ts +24 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.smoke.js +276 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.d.ts +45 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.js +222 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.smoke.d.ts +24 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.smoke.js +169 -0
- package/dist/src/benchmarks/gaia-tools/image_describe.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/index.d.ts +32 -0
- package/dist/src/benchmarks/gaia-tools/index.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/index.js +36 -0
- package/dist/src/benchmarks/gaia-tools/index.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/pdf_read.d.ts +27 -0
- package/dist/src/benchmarks/gaia-tools/pdf_read.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/pdf_read.js +226 -0
- package/dist/src/benchmarks/gaia-tools/pdf_read.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.d.ts +31 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.js +94 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.smoke.d.ts +13 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.smoke.js +98 -0
- package/dist/src/benchmarks/gaia-tools/python_exec.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/types.d.ts +62 -0
- package/dist/src/benchmarks/gaia-tools/types.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/types.js +12 -0
- package/dist/src/benchmarks/gaia-tools/types.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/visit_webpage.d.ts +52 -0
- package/dist/src/benchmarks/gaia-tools/visit_webpage.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/visit_webpage.js +304 -0
- package/dist/src/benchmarks/gaia-tools/visit_webpage.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.d.ts +61 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.js +217 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.smoke.d.ts +26 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.smoke.js +152 -0
- package/dist/src/benchmarks/gaia-tools/web_browse.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.d.ts +30 -0
- package/dist/src/benchmarks/gaia-tools/web_search.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.js +210 -0
- package/dist/src/benchmarks/gaia-tools/web_search.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.smoke.d.ts +24 -0
- package/dist/src/benchmarks/gaia-tools/web_search.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.smoke.js +311 -0
- package/dist/src/benchmarks/gaia-tools/web_search.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-visit-webpage.smoke.d.ts +25 -0
- package/dist/src/benchmarks/gaia-visit-webpage.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-visit-webpage.smoke.js +304 -0
- package/dist/src/benchmarks/gaia-visit-webpage.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-voting.d.ts +88 -0
- package/dist/src/benchmarks/gaia-voting.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-voting.js +297 -0
- package/dist/src/benchmarks/gaia-voting.js.map +1 -0
- package/dist/src/benchmarks/gaia-voting.smoke.d.ts +20 -0
- package/dist/src/benchmarks/gaia-voting.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-voting.smoke.js +332 -0
- package/dist/src/benchmarks/gaia-voting.smoke.js.map +1 -0
- package/dist/src/commands/gaia-bench.d.ts +40 -0
- package/dist/src/commands/gaia-bench.d.ts.map +1 -0
- package/dist/src/commands/gaia-bench.js +597 -0
- package/dist/src/commands/gaia-bench.js.map +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +41 -4
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/performance-capability.d.ts +30 -0
- package/dist/src/commands/performance-capability.d.ts.map +1 -0
- package/dist/src/commands/performance-capability.js +349 -0
- package/dist/src/commands/performance-capability.js.map +1 -0
- package/dist/src/commands/route.d.ts.map +1 -1
- package/dist/src/commands/route.js +9 -0
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +25 -6
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/mcp-generator.d.ts.map +1 -1
- package/dist/src/init/mcp-generator.js +9 -4
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +25 -2
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.js +20 -3
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +12 -1
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +34 -0
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA CodeAgent Smoke Tests — ADR-138 iter 54 (FINAL design)
|
|
3
|
+
*
|
|
4
|
+
* 5 tests validating the CodeAgent harness end-to-end.
|
|
5
|
+
* Tests 1-4 are unit-level (no API calls). Test 5 uses 1 API call.
|
|
6
|
+
*
|
|
7
|
+
* Tests:
|
|
8
|
+
* T1: Code block extraction — parser correctness (no subprocess)
|
|
9
|
+
* T2: Python runner — simple math (subprocess, no API)
|
|
10
|
+
* T3: Python runner — file read via ATTACHMENT_PATH
|
|
11
|
+
* T4: Python runner — code error recovery (traceback returned as obs)
|
|
12
|
+
* T5: End-to-end — simple factual question (1 API call, ~$0.01)
|
|
13
|
+
*
|
|
14
|
+
* Pass criteria: 5/5. Gate before iter 55 5Q run.
|
|
15
|
+
*
|
|
16
|
+
* Run: npx tsx gaia-codeagent.smoke.ts
|
|
17
|
+
* or: node dist/src/benchmarks/gaia-codeagent.smoke.js
|
|
18
|
+
*
|
|
19
|
+
* Refs: ADR-138, #2156, iter 54
|
|
20
|
+
*/
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Imports
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
import * as fs from 'node:fs';
|
|
25
|
+
import * as os from 'node:os';
|
|
26
|
+
import * as path from 'node:path';
|
|
27
|
+
import { extractCodeBlock, runCodeAgentStep, runGaiaCodeAgent, } from './gaia-codeagent.js';
|
|
28
|
+
import { resolveAnthropicApiKey } from './gaia-agent.js';
|
|
29
|
+
function makeQ(overrides = {}) {
|
|
30
|
+
return {
|
|
31
|
+
task_id: 'smoke-test',
|
|
32
|
+
level: 1,
|
|
33
|
+
question: 'What is 2 + 2?',
|
|
34
|
+
final_answer: '4',
|
|
35
|
+
file_name: null,
|
|
36
|
+
file_path: null,
|
|
37
|
+
...overrides,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// T1: Code block extraction (no subprocess, no API)
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
function testCodeBlockExtraction() {
|
|
44
|
+
const name = 'T1: Code block extraction';
|
|
45
|
+
const start = Date.now();
|
|
46
|
+
const cases = [
|
|
47
|
+
{ input: '```python\nprint(2+2)\n```', expected: 'print(2+2)' },
|
|
48
|
+
{ input: '```py\nresult = 42\n```', expected: 'result = 42' },
|
|
49
|
+
{ input: '```\nfinal_answer("test")\n```', expected: 'final_answer("test")' },
|
|
50
|
+
{ input: 'No code block here', expected: null },
|
|
51
|
+
{
|
|
52
|
+
input: 'Reasoning...\n```python\nweb_search("q")\nprint(r)\n```\nMore',
|
|
53
|
+
expected: 'web_search("q")\nprint(r)',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
for (const { input, expected } of cases) {
|
|
57
|
+
const result = extractCodeBlock(input);
|
|
58
|
+
if (result !== expected) {
|
|
59
|
+
return {
|
|
60
|
+
name,
|
|
61
|
+
passed: false,
|
|
62
|
+
message: `Case "${input.slice(0, 40)}": got "${result}", expected "${expected}"`,
|
|
63
|
+
durationMs: Date.now() - start,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { name, passed: true, message: `${cases.length}/5 cases passed`, durationMs: Date.now() - start };
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// T2: Python runner — simple math (subprocess, no API)
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
function testPythonRunnerMath() {
|
|
73
|
+
const name = 'T2: Python runner — simple math';
|
|
74
|
+
const start = Date.now();
|
|
75
|
+
const apiKey = process.env.ANTHROPIC_API_KEY ?? 'test-key';
|
|
76
|
+
const code = `result = 2 + 2\nprint(result)\nfinal_answer(str(result))`;
|
|
77
|
+
const stepResult = runCodeAgentStep(code, null, 15_000, apiKey);
|
|
78
|
+
if (stepResult.finalAnswer !== '4') {
|
|
79
|
+
return {
|
|
80
|
+
name,
|
|
81
|
+
passed: false,
|
|
82
|
+
message: `Expected finalAnswer "4", got "${stepResult.finalAnswer ?? 'null'}". Obs: ${stepResult.observation.slice(0, 200)}`,
|
|
83
|
+
durationMs: Date.now() - start,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return { name, passed: true, message: `finalAnswer="4" as expected`, durationMs: Date.now() - start };
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// T3: Python runner — file read via ATTACHMENT_PATH
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
function testPythonRunnerFileRead() {
|
|
92
|
+
const name = 'T3: Python runner — file read';
|
|
93
|
+
const start = Date.now();
|
|
94
|
+
const tmpFile = path.join(os.tmpdir(), `gaia-smoke-${Date.now()}.txt`);
|
|
95
|
+
fs.writeFileSync(tmpFile, 'The magic number is forty-two (42).', 'utf-8');
|
|
96
|
+
try {
|
|
97
|
+
const apiKey = process.env.ANTHROPIC_API_KEY ?? 'test-key';
|
|
98
|
+
const code = `content = read_file(ATTACHMENT_PATH)\nprint("Read:", content[:80])\nfinal_answer("42")`;
|
|
99
|
+
const stepResult = runCodeAgentStep(code, tmpFile, 15_000, apiKey);
|
|
100
|
+
if (stepResult.finalAnswer !== '42') {
|
|
101
|
+
return {
|
|
102
|
+
name, passed: false,
|
|
103
|
+
message: `Expected finalAnswer "42", got "${stepResult.finalAnswer ?? 'null'}". Obs: ${stepResult.observation.slice(0, 200)}`,
|
|
104
|
+
durationMs: Date.now() - start,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (!stepResult.observation.includes('forty-two') && !stepResult.observation.includes('42')) {
|
|
108
|
+
return {
|
|
109
|
+
name, passed: false,
|
|
110
|
+
message: `File content not in observation. Obs: ${stepResult.observation.slice(0, 200)}`,
|
|
111
|
+
durationMs: Date.now() - start,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { name, passed: true, message: `File read OK, finalAnswer="42"`, durationMs: Date.now() - start };
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
try {
|
|
118
|
+
fs.unlinkSync(tmpFile);
|
|
119
|
+
}
|
|
120
|
+
catch { /* ignore */ }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// T4: Python runner — code error recovery
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
function testPythonRunnerErrorRecovery() {
|
|
127
|
+
const name = 'T4: Python runner — error recovery';
|
|
128
|
+
const start = Date.now();
|
|
129
|
+
const apiKey = process.env.ANTHROPIC_API_KEY ?? 'test-key';
|
|
130
|
+
const badCode = `result = undefined_variable_xyz + 1\nprint(result)`;
|
|
131
|
+
const stepResult = runCodeAgentStep(badCode, null, 15_000, apiKey);
|
|
132
|
+
if (stepResult.finalAnswer !== null) {
|
|
133
|
+
return {
|
|
134
|
+
name, passed: false,
|
|
135
|
+
message: `Expected no finalAnswer from errored code, got "${stepResult.finalAnswer}"`,
|
|
136
|
+
durationMs: Date.now() - start,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const obs = stepResult.observation.toLowerCase();
|
|
140
|
+
if (!obs.includes('error') && !obs.includes('nameerror')) {
|
|
141
|
+
return {
|
|
142
|
+
name, passed: false,
|
|
143
|
+
message: `Observation should contain error info, got: ${stepResult.observation.slice(0, 200)}`,
|
|
144
|
+
durationMs: Date.now() - start,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
name, passed: true,
|
|
149
|
+
message: `Error returned as observation: "${stepResult.observation.slice(0, 60)}..."`,
|
|
150
|
+
durationMs: Date.now() - start,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// T5: End-to-end — simple factual question (1 API call)
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
async function testEndToEndSimple() {
|
|
157
|
+
const name = 'T5: End-to-end — simple factual (1 API call)';
|
|
158
|
+
const start = Date.now();
|
|
159
|
+
let apiKey;
|
|
160
|
+
try {
|
|
161
|
+
apiKey = resolveAnthropicApiKey();
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
return {
|
|
165
|
+
name, passed: false,
|
|
166
|
+
message: `No API key: ${String(err)}`,
|
|
167
|
+
durationMs: Date.now() - start,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const q = makeQ({
|
|
171
|
+
task_id: 'smoke-e2e-01',
|
|
172
|
+
question: 'What is 6 multiplied by 7? Answer as a number.',
|
|
173
|
+
final_answer: '42',
|
|
174
|
+
});
|
|
175
|
+
try {
|
|
176
|
+
const result = await runGaiaCodeAgent(q, {
|
|
177
|
+
model: 'claude-sonnet-4-6',
|
|
178
|
+
maxTurns: 5,
|
|
179
|
+
apiKey,
|
|
180
|
+
});
|
|
181
|
+
if (result.error && !result.finalAnswer) {
|
|
182
|
+
return { name, passed: false, message: `Agent error: ${result.error}`, durationMs: Date.now() - start };
|
|
183
|
+
}
|
|
184
|
+
if (result.finalAnswer === null) {
|
|
185
|
+
return { name, passed: false, message: `No final answer (timedOut=${result.timedOut})`, durationMs: Date.now() - start };
|
|
186
|
+
}
|
|
187
|
+
const num = parseFloat(result.finalAnswer.replace(/,/g, ''));
|
|
188
|
+
if (Math.abs(num - 42) > 0.01) {
|
|
189
|
+
return {
|
|
190
|
+
name, passed: false,
|
|
191
|
+
message: `Expected "42", got "${result.finalAnswer}" (turns=${result.turns})`,
|
|
192
|
+
durationMs: Date.now() - start,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const estCost = (result.totalInputTokens / 1e6) * 3.0 + (result.totalOutputTokens / 1e6) * 15.0;
|
|
196
|
+
return {
|
|
197
|
+
name, passed: true,
|
|
198
|
+
message: `finalAnswer="${result.finalAnswer}" turns=${result.turns} cost~=$${estCost.toFixed(4)}`,
|
|
199
|
+
durationMs: Date.now() - start,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return { name, passed: false, message: `Exception: ${String(err)}`, durationMs: Date.now() - start };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// Main
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
async function main() {
|
|
210
|
+
console.log('\n=== GAIA CodeAgent Smoke Tests (ADR-138 iter 54) ===\n');
|
|
211
|
+
const results = [
|
|
212
|
+
testCodeBlockExtraction(),
|
|
213
|
+
testPythonRunnerMath(),
|
|
214
|
+
testPythonRunnerFileRead(),
|
|
215
|
+
testPythonRunnerErrorRecovery(),
|
|
216
|
+
await testEndToEndSimple(),
|
|
217
|
+
];
|
|
218
|
+
let passed = 0;
|
|
219
|
+
for (const r of results) {
|
|
220
|
+
const status = r.passed ? 'PASS' : 'FAIL';
|
|
221
|
+
console.log(`[${status}] ${r.name} (${r.durationMs}ms)`);
|
|
222
|
+
console.log(` ${r.message}`);
|
|
223
|
+
if (r.passed)
|
|
224
|
+
passed++;
|
|
225
|
+
}
|
|
226
|
+
console.log(`\n=== ${passed}/${results.length} passed ===`);
|
|
227
|
+
if (passed === results.length) {
|
|
228
|
+
console.log('All smoke tests passed. CodeAgent harness ready for 1Q sanity check.\n');
|
|
229
|
+
process.exit(0);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
console.log(`SMOKE FAILED — ${results.length - passed} test(s) failed.\n`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
main().catch((err) => {
|
|
237
|
+
console.error('Smoke test crashed:', err);
|
|
238
|
+
process.exit(2);
|
|
239
|
+
});
|
|
240
|
+
export { testCodeBlockExtraction, testPythonRunnerMath, testPythonRunnerFileRead, testPythonRunnerErrorRecovery, testEndToEndSimple, };
|
|
241
|
+
//# sourceMappingURL=gaia-codeagent.smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaia-codeagent.smoke.js","sourceRoot":"","sources":["../../../src/benchmarks/gaia-codeagent.smoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Convergence Layer — deterministic finalization for saturated agent loops.
|
|
3
|
+
*
|
|
4
|
+
* Detects three failure modes that cause empty FINAL_ANSWER extraction:
|
|
5
|
+
* 1. max_turns hit without a final_answer call
|
|
6
|
+
* 2. Loop detected (same tool + same args called 3× in a 5-turn window)
|
|
7
|
+
* 3. Token budget exceeded (>120k tokens of conversation context)
|
|
8
|
+
*
|
|
9
|
+
* On detection, runs a FORCED COMMIT phase:
|
|
10
|
+
* - Injects a stripped-down summary prompt: "Based on all observations, answer with
|
|
11
|
+
* FINAL_ANSWER: X. Do NOT explore further."
|
|
12
|
+
* - Makes 1 final API call with strict instruction and no tools.
|
|
13
|
+
* - If still no FINAL_ANSWER in the response, runs the Stage 1 extraction cascade
|
|
14
|
+
* against ALL prior assistant messages (last to first), returns first non-empty hit.
|
|
15
|
+
* - If still empty: returns null but logs the failure mode.
|
|
16
|
+
*
|
|
17
|
+
* This is NOT a new cognition layer — it is a convergence controller.
|
|
18
|
+
* It STRIPS information rather than adding it: one final chance to commit,
|
|
19
|
+
* no tools available, prior context summarized rather than appended.
|
|
20
|
+
*
|
|
21
|
+
* Architecture principle (iter 60 post-mortem):
|
|
22
|
+
* "More information can reduce agent reliability. Past a certain point —
|
|
23
|
+
* retrieval depth, context size, browsing breadth, tool diversity — information
|
|
24
|
+
* increases trajectory entropy. The system becomes less likely to finalize coherently."
|
|
25
|
+
* This layer is the entropy-reducer.
|
|
26
|
+
*
|
|
27
|
+
* Refs: #2156, iter 60 (19/25 empty FINAL_ANSWER failures), iter 62
|
|
28
|
+
*/
|
|
29
|
+
/** Token threshold (sum of input tokens across all turns) that triggers overflow detection. */
|
|
30
|
+
export declare const TOKEN_OVERFLOW_THRESHOLD = 120000;
|
|
31
|
+
/** Number of repeated identical tool+args calls in a window that signals a loop. */
|
|
32
|
+
export declare const LOOP_REPEAT_THRESHOLD = 3;
|
|
33
|
+
/** Sliding window size (turns) for loop detection. */
|
|
34
|
+
export declare const LOOP_WINDOW_SIZE = 5;
|
|
35
|
+
/** Tracks state that the convergence layer needs to evaluate triggers. */
|
|
36
|
+
export interface ConvergenceState {
|
|
37
|
+
/** How many agent turns have elapsed so far. */
|
|
38
|
+
turnCount: number;
|
|
39
|
+
/** Sum of input tokens across all turns (used for overflow detection). */
|
|
40
|
+
totalTokens: number;
|
|
41
|
+
/** Ordered log of tool calls for loop detection. */
|
|
42
|
+
toolCalls: Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
argsHash: string;
|
|
45
|
+
turn: number;
|
|
46
|
+
}>;
|
|
47
|
+
/** Set by checkConvergenceTriggers when a failure mode is detected. */
|
|
48
|
+
detectedFailureMode: 'max_turns' | 'loop' | 'token_overflow' | null;
|
|
49
|
+
}
|
|
50
|
+
/** Result of a forced-commit attempt. */
|
|
51
|
+
export interface ForceCommitResult {
|
|
52
|
+
/** The extracted answer, or null if even forced commit could not extract one. */
|
|
53
|
+
answer: string | null;
|
|
54
|
+
/** True when the answer was recovered from prior message history rather than
|
|
55
|
+
* from the forced-commit API call. */
|
|
56
|
+
usedFallback: boolean;
|
|
57
|
+
/** The failure mode that triggered this forced commit. */
|
|
58
|
+
triggerMode: ConvergenceState['detectedFailureMode'];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Produce a stable hash of a tool call's name + args for loop detection.
|
|
62
|
+
*
|
|
63
|
+
* Uses SHA-256 truncated to 16 hex chars — collision probability is
|
|
64
|
+
* negligible for the small call volumes in a single agent run.
|
|
65
|
+
*
|
|
66
|
+
* The hash is deterministic: same toolName + same args always → same hash.
|
|
67
|
+
* Different args always → different hash (within SHA-256 collision bounds).
|
|
68
|
+
*/
|
|
69
|
+
export declare function argsHash(toolName: string, args: object): string;
|
|
70
|
+
/**
|
|
71
|
+
* Evaluate the current ConvergenceState and return the first failure mode
|
|
72
|
+
* detected, or null if no trigger has fired.
|
|
73
|
+
*
|
|
74
|
+
* Evaluation order:
|
|
75
|
+
* 1. max_turns — turnCount >= maxTurns
|
|
76
|
+
* 2. token_overflow — totalTokens >= TOKEN_OVERFLOW_THRESHOLD
|
|
77
|
+
* 3. loop — same tool+argsHash appears >= LOOP_REPEAT_THRESHOLD times
|
|
78
|
+
* in the last LOOP_WINDOW_SIZE entries of toolCalls
|
|
79
|
+
*
|
|
80
|
+
* Only the FIRST matching trigger is returned (stops at first detection).
|
|
81
|
+
* The caller is responsible for setting state.detectedFailureMode.
|
|
82
|
+
*/
|
|
83
|
+
export declare function checkConvergenceTriggers(state: ConvergenceState, maxTurns: number): ConvergenceState['detectedFailureMode'];
|
|
84
|
+
/**
|
|
85
|
+
* Run Stage 1 extraction (FINAL_ANSWER: pattern) against a raw text string.
|
|
86
|
+
* Returns the matched answer or null.
|
|
87
|
+
*/
|
|
88
|
+
export declare function extractFinalAnswerFromText(text: string): string | null;
|
|
89
|
+
/**
|
|
90
|
+
* Scan prior assistant messages from last to first, looking for FINAL_ANSWER.
|
|
91
|
+
*
|
|
92
|
+
* This is the fallback path when the forced-commit API call still does not
|
|
93
|
+
* produce a FINAL_ANSWER. We search backwards because the most recent
|
|
94
|
+
* assistant message is most likely to contain the best answer.
|
|
95
|
+
*/
|
|
96
|
+
export declare function extractFromPriorMessages(messages: Array<{
|
|
97
|
+
role: string;
|
|
98
|
+
content: string | unknown;
|
|
99
|
+
}>): string | null;
|
|
100
|
+
/**
|
|
101
|
+
* Run the forced-commit phase for a saturated agent loop.
|
|
102
|
+
*
|
|
103
|
+
* Steps:
|
|
104
|
+
* 1. Append a stripped directive prompt to the message history.
|
|
105
|
+
* 2. Call the model once with NO tools — forces text-only response.
|
|
106
|
+
* 3. If FINAL_ANSWER found in the response → return it.
|
|
107
|
+
* 4. If not → scan prior assistant messages last-to-first for FINAL_ANSWER.
|
|
108
|
+
* 5. If still empty → return { answer: null, usedFallback: false }.
|
|
109
|
+
*
|
|
110
|
+
* The callModel callback must return the raw text response (assistant turn
|
|
111
|
+
* text blocks concatenated). It should be called WITHOUT tool definitions
|
|
112
|
+
* so the model cannot call tools in this turn.
|
|
113
|
+
*
|
|
114
|
+
* @param messages Current conversation history (mutated: 1 user turn appended)
|
|
115
|
+
* @param callModel Callback that makes a single API call and returns the response text
|
|
116
|
+
* @param triggerMode The failure mode that triggered this forced commit
|
|
117
|
+
*/
|
|
118
|
+
export declare function forceCommit(messages: Array<{
|
|
119
|
+
role: string;
|
|
120
|
+
content: string | unknown;
|
|
121
|
+
}>, callModel: (messages: Array<{
|
|
122
|
+
role: string;
|
|
123
|
+
content: string | unknown;
|
|
124
|
+
}>) => Promise<string>, triggerMode?: ConvergenceState['detectedFailureMode']): Promise<ForceCommitResult>;
|
|
125
|
+
/** Create a new ConvergenceState with zero counters. */
|
|
126
|
+
export declare function createConvergenceState(): ConvergenceState;
|
|
127
|
+
/**
|
|
128
|
+
* Update ConvergenceState after each agent turn completes.
|
|
129
|
+
*
|
|
130
|
+
* @param state Mutable state object (modified in place)
|
|
131
|
+
* @param inputTokens Tokens consumed in this turn
|
|
132
|
+
* @param toolCallsThisTurn Tool calls made in this turn (name + args)
|
|
133
|
+
*/
|
|
134
|
+
export declare function recordTurn(state: ConvergenceState, inputTokens: number, toolCallsThisTurn: Array<{
|
|
135
|
+
name: string;
|
|
136
|
+
args: object;
|
|
137
|
+
}>): void;
|
|
138
|
+
//# sourceMappingURL=gaia-convergence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaia-convergence.d.ts","sourceRoot":"","sources":["../../../src/benchmarks/gaia-convergence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAQH,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,SAAU,CAAC;AAEhD,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AASlC,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,uEAAuE;IACvE,mBAAmB,EAAE,WAAW,GAAG,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;CACrE;AAED,yCAAyC;AACzC,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;2CACuC;IACvC,YAAY,EAAE,OAAO,CAAC;IACtB,0DAA0D;IAC1D,WAAW,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACtD;AAMD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/D;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAAC,qBAAqB,CAAC,CA2BzC;AA6BD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMtE;AAMD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,GAC3D,MAAM,GAAG,IAAI,CAkBf;AAsBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,EAC5D,SAAS,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,EAC5F,WAAW,GAAE,gBAAgB,CAAC,qBAAqB,CAAe,GACjE,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AAMD,wDAAwD;AACxD,wBAAgB,sBAAsB,IAAI,gBAAgB,CAOzD;AAMD;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,IAAI,CAWN"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Convergence Layer — deterministic finalization for saturated agent loops.
|
|
3
|
+
*
|
|
4
|
+
* Detects three failure modes that cause empty FINAL_ANSWER extraction:
|
|
5
|
+
* 1. max_turns hit without a final_answer call
|
|
6
|
+
* 2. Loop detected (same tool + same args called 3× in a 5-turn window)
|
|
7
|
+
* 3. Token budget exceeded (>120k tokens of conversation context)
|
|
8
|
+
*
|
|
9
|
+
* On detection, runs a FORCED COMMIT phase:
|
|
10
|
+
* - Injects a stripped-down summary prompt: "Based on all observations, answer with
|
|
11
|
+
* FINAL_ANSWER: X. Do NOT explore further."
|
|
12
|
+
* - Makes 1 final API call with strict instruction and no tools.
|
|
13
|
+
* - If still no FINAL_ANSWER in the response, runs the Stage 1 extraction cascade
|
|
14
|
+
* against ALL prior assistant messages (last to first), returns first non-empty hit.
|
|
15
|
+
* - If still empty: returns null but logs the failure mode.
|
|
16
|
+
*
|
|
17
|
+
* This is NOT a new cognition layer — it is a convergence controller.
|
|
18
|
+
* It STRIPS information rather than adding it: one final chance to commit,
|
|
19
|
+
* no tools available, prior context summarized rather than appended.
|
|
20
|
+
*
|
|
21
|
+
* Architecture principle (iter 60 post-mortem):
|
|
22
|
+
* "More information can reduce agent reliability. Past a certain point —
|
|
23
|
+
* retrieval depth, context size, browsing breadth, tool diversity — information
|
|
24
|
+
* increases trajectory entropy. The system becomes less likely to finalize coherently."
|
|
25
|
+
* This layer is the entropy-reducer.
|
|
26
|
+
*
|
|
27
|
+
* Refs: #2156, iter 60 (19/25 empty FINAL_ANSWER failures), iter 62
|
|
28
|
+
*/
|
|
29
|
+
import * as crypto from 'node:crypto';
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Constants
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/** Token threshold (sum of input tokens across all turns) that triggers overflow detection. */
|
|
34
|
+
export const TOKEN_OVERFLOW_THRESHOLD = 120_000;
|
|
35
|
+
/** Number of repeated identical tool+args calls in a window that signals a loop. */
|
|
36
|
+
export const LOOP_REPEAT_THRESHOLD = 3;
|
|
37
|
+
/** Sliding window size (turns) for loop detection. */
|
|
38
|
+
export const LOOP_WINDOW_SIZE = 5;
|
|
39
|
+
/** Pattern Claude must output to signal it has a final answer. */
|
|
40
|
+
const FINAL_ANSWER_RE = /FINAL_ANSWER:\s*(.+)/i;
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// argsHash — deterministic fingerprint of a tool call
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
/**
|
|
45
|
+
* Produce a stable hash of a tool call's name + args for loop detection.
|
|
46
|
+
*
|
|
47
|
+
* Uses SHA-256 truncated to 16 hex chars — collision probability is
|
|
48
|
+
* negligible for the small call volumes in a single agent run.
|
|
49
|
+
*
|
|
50
|
+
* The hash is deterministic: same toolName + same args always → same hash.
|
|
51
|
+
* Different args always → different hash (within SHA-256 collision bounds).
|
|
52
|
+
*/
|
|
53
|
+
export function argsHash(toolName, args) {
|
|
54
|
+
const payload = toolName + '::' + JSON.stringify(args);
|
|
55
|
+
return crypto.createHash('sha256').update(payload).digest('hex').slice(0, 16);
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// checkConvergenceTriggers
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
/**
|
|
61
|
+
* Evaluate the current ConvergenceState and return the first failure mode
|
|
62
|
+
* detected, or null if no trigger has fired.
|
|
63
|
+
*
|
|
64
|
+
* Evaluation order:
|
|
65
|
+
* 1. max_turns — turnCount >= maxTurns
|
|
66
|
+
* 2. token_overflow — totalTokens >= TOKEN_OVERFLOW_THRESHOLD
|
|
67
|
+
* 3. loop — same tool+argsHash appears >= LOOP_REPEAT_THRESHOLD times
|
|
68
|
+
* in the last LOOP_WINDOW_SIZE entries of toolCalls
|
|
69
|
+
*
|
|
70
|
+
* Only the FIRST matching trigger is returned (stops at first detection).
|
|
71
|
+
* The caller is responsible for setting state.detectedFailureMode.
|
|
72
|
+
*/
|
|
73
|
+
export function checkConvergenceTriggers(state, maxTurns) {
|
|
74
|
+
// 1. max_turns
|
|
75
|
+
if (state.turnCount >= maxTurns) {
|
|
76
|
+
return 'max_turns';
|
|
77
|
+
}
|
|
78
|
+
// 2. token_overflow
|
|
79
|
+
if (state.totalTokens >= TOKEN_OVERFLOW_THRESHOLD) {
|
|
80
|
+
return 'token_overflow';
|
|
81
|
+
}
|
|
82
|
+
// 3. loop — check the sliding window
|
|
83
|
+
const window = state.toolCalls.slice(-LOOP_WINDOW_SIZE);
|
|
84
|
+
if (window.length >= LOOP_REPEAT_THRESHOLD) {
|
|
85
|
+
const callKey = (c) => c.name + '::' + c.argsHash;
|
|
86
|
+
const counts = new Map();
|
|
87
|
+
for (const call of window) {
|
|
88
|
+
const key = callKey(call);
|
|
89
|
+
const count = (counts.get(key) ?? 0) + 1;
|
|
90
|
+
counts.set(key, count);
|
|
91
|
+
if (count >= LOOP_REPEAT_THRESHOLD) {
|
|
92
|
+
return 'loop';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// buildForcedCommitPrompt
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* Build the stripped-down "commit now" prompt injected as a final user turn.
|
|
103
|
+
*
|
|
104
|
+
* Deliberately short and directive — this is an entropy-reducer, not a
|
|
105
|
+
* context-enricher. Adding more information at this point would worsen the
|
|
106
|
+
* problem we are solving.
|
|
107
|
+
*/
|
|
108
|
+
function buildForcedCommitPrompt(triggerMode) {
|
|
109
|
+
return (`[CONVERGENCE: ${triggerMode.toUpperCase()}]\n` +
|
|
110
|
+
`You must commit to a final answer NOW. Do NOT call any more tools.\n` +
|
|
111
|
+
`Based only on the information you have already gathered:\n` +
|
|
112
|
+
`- Summarize your best answer in one line.\n` +
|
|
113
|
+
`- Output it in EXACTLY this format: FINAL_ANSWER: <your answer>\n` +
|
|
114
|
+
`- If you are uncertain, give your best estimate — do not say "I don't know".\n` +
|
|
115
|
+
`You have ONE response. No further tool calls are permitted.`);
|
|
116
|
+
}
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// extractFinalAnswerFromText — Stage 1 extraction against raw text
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
/**
|
|
121
|
+
* Run Stage 1 extraction (FINAL_ANSWER: pattern) against a raw text string.
|
|
122
|
+
* Returns the matched answer or null.
|
|
123
|
+
*/
|
|
124
|
+
export function extractFinalAnswerFromText(text) {
|
|
125
|
+
const match = FINAL_ANSWER_RE.exec(text);
|
|
126
|
+
if (match && match[1] && match[1].trim()) {
|
|
127
|
+
return match[1].trim();
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// extractFromPriorMessages — fallback scan of message history
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
/**
|
|
135
|
+
* Scan prior assistant messages from last to first, looking for FINAL_ANSWER.
|
|
136
|
+
*
|
|
137
|
+
* This is the fallback path when the forced-commit API call still does not
|
|
138
|
+
* produce a FINAL_ANSWER. We search backwards because the most recent
|
|
139
|
+
* assistant message is most likely to contain the best answer.
|
|
140
|
+
*/
|
|
141
|
+
export function extractFromPriorMessages(messages) {
|
|
142
|
+
// Iterate in reverse, assistant messages only
|
|
143
|
+
const assistantMessages = messages
|
|
144
|
+
.filter((m) => m.role === 'assistant')
|
|
145
|
+
.reverse();
|
|
146
|
+
for (const msg of assistantMessages) {
|
|
147
|
+
const text = typeof msg.content === 'string'
|
|
148
|
+
? msg.content
|
|
149
|
+
: extractTextFromContent(msg.content);
|
|
150
|
+
if (!text)
|
|
151
|
+
continue;
|
|
152
|
+
const answer = extractFinalAnswerFromText(text);
|
|
153
|
+
if (answer)
|
|
154
|
+
return answer;
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Extract plain text from a content block array (Anthropic API format).
|
|
160
|
+
* Returns concatenated text from all text-type blocks, or empty string.
|
|
161
|
+
*/
|
|
162
|
+
function extractTextFromContent(content) {
|
|
163
|
+
if (!Array.isArray(content))
|
|
164
|
+
return '';
|
|
165
|
+
const parts = [];
|
|
166
|
+
for (const block of content) {
|
|
167
|
+
if (block && typeof block === 'object' && block.type === 'text') {
|
|
168
|
+
const text = block.text;
|
|
169
|
+
if (text)
|
|
170
|
+
parts.push(text);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return parts.join('\n');
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// forceCommit
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
/**
|
|
179
|
+
* Run the forced-commit phase for a saturated agent loop.
|
|
180
|
+
*
|
|
181
|
+
* Steps:
|
|
182
|
+
* 1. Append a stripped directive prompt to the message history.
|
|
183
|
+
* 2. Call the model once with NO tools — forces text-only response.
|
|
184
|
+
* 3. If FINAL_ANSWER found in the response → return it.
|
|
185
|
+
* 4. If not → scan prior assistant messages last-to-first for FINAL_ANSWER.
|
|
186
|
+
* 5. If still empty → return { answer: null, usedFallback: false }.
|
|
187
|
+
*
|
|
188
|
+
* The callModel callback must return the raw text response (assistant turn
|
|
189
|
+
* text blocks concatenated). It should be called WITHOUT tool definitions
|
|
190
|
+
* so the model cannot call tools in this turn.
|
|
191
|
+
*
|
|
192
|
+
* @param messages Current conversation history (mutated: 1 user turn appended)
|
|
193
|
+
* @param callModel Callback that makes a single API call and returns the response text
|
|
194
|
+
* @param triggerMode The failure mode that triggered this forced commit
|
|
195
|
+
*/
|
|
196
|
+
export async function forceCommit(messages, callModel, triggerMode = 'max_turns') {
|
|
197
|
+
const trigger = triggerMode ?? 'max_turns';
|
|
198
|
+
// Step 1: append the forced-commit directive
|
|
199
|
+
const commitMessages = [
|
|
200
|
+
...messages,
|
|
201
|
+
{ role: 'user', content: buildForcedCommitPrompt(trigger) },
|
|
202
|
+
];
|
|
203
|
+
// Step 2: call the model once, no tools
|
|
204
|
+
let responseText = '';
|
|
205
|
+
try {
|
|
206
|
+
responseText = await callModel(commitMessages);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// If the API call itself fails, fall through to fallback scan
|
|
210
|
+
responseText = '';
|
|
211
|
+
}
|
|
212
|
+
// Step 3: try to extract from the forced-commit response
|
|
213
|
+
if (responseText) {
|
|
214
|
+
const answer = extractFinalAnswerFromText(responseText);
|
|
215
|
+
if (answer) {
|
|
216
|
+
return { answer, usedFallback: false, triggerMode: triggerMode };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Step 4: scan prior messages last-to-first
|
|
220
|
+
const fallbackAnswer = extractFromPriorMessages(messages);
|
|
221
|
+
if (fallbackAnswer) {
|
|
222
|
+
return { answer: fallbackAnswer, usedFallback: true, triggerMode: triggerMode };
|
|
223
|
+
}
|
|
224
|
+
// Step 5: graceful failure
|
|
225
|
+
return { answer: null, usedFallback: false, triggerMode: triggerMode };
|
|
226
|
+
}
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// createConvergenceState — factory for a fresh state object
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
/** Create a new ConvergenceState with zero counters. */
|
|
231
|
+
export function createConvergenceState() {
|
|
232
|
+
return {
|
|
233
|
+
turnCount: 0,
|
|
234
|
+
totalTokens: 0,
|
|
235
|
+
toolCalls: [],
|
|
236
|
+
detectedFailureMode: null,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// recordTurn — update state after a completed turn
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
/**
|
|
243
|
+
* Update ConvergenceState after each agent turn completes.
|
|
244
|
+
*
|
|
245
|
+
* @param state Mutable state object (modified in place)
|
|
246
|
+
* @param inputTokens Tokens consumed in this turn
|
|
247
|
+
* @param toolCallsThisTurn Tool calls made in this turn (name + args)
|
|
248
|
+
*/
|
|
249
|
+
export function recordTurn(state, inputTokens, toolCallsThisTurn) {
|
|
250
|
+
state.turnCount += 1;
|
|
251
|
+
state.totalTokens += inputTokens;
|
|
252
|
+
for (const tc of toolCallsThisTurn) {
|
|
253
|
+
state.toolCalls.push({
|
|
254
|
+
name: tc.name,
|
|
255
|
+
argsHash: argsHash(tc.name, tc.args),
|
|
256
|
+
turn: state.turnCount,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=gaia-convergence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaia-convergence.js","sourceRoot":"","sources":["../../../src/benchmarks/gaia-convergence.ts"],"names":[],"mappings":"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"}
|