claude-flow 3.10.4 → 3.10.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/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts +18 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent-planning.smoke.js +253 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent.d.ts +198 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent.js +651 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.d.ts +133 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.js +281 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +22 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.smoke.js +300 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.d.ts +138 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.js +260 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.smoke.d.ts +19 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.smoke.js +246 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.d.ts +123 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.js +312 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.smoke.d.ts +21 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.smoke.js +327 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.d.ts +125 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.js +350 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +21 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.smoke.js +228 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-e2e-smoke.d.ts +27 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-e2e-smoke.js +136 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-extract.smoke.d.ts +45 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-extract.smoke.js +242 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/features.d.ts +46 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/features.js +170 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.d.ts +105 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.js +260 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +20 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +235 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +51 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/train-data-loader.js +179 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-judge.d.ts +88 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-judge.js +437 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-loader.d.ts +87 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-loader.js +326 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/file_read.d.ts +35 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/file_read.js +403 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +126 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/grounded_query.js +225 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/index.d.ts +32 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/index.js +36 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/types.d.ts +62 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/types.js +12 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/web_search.d.ts +30 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/web_search.js +210 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.d.ts +88 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.js +297 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.smoke.d.ts +20 -0
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.smoke.js +332 -0
- package/v3/@claude-flow/cli/dist/src/commands/gaia-bench.d.ts +40 -0
- package/v3/@claude-flow/cli/dist/src/commands/gaia-bench.js +597 -0
- package/v3/@claude-flow/cli/dist/src/commands/index.js +2 -0
- package/v3/@claude-flow/cli/dist/src/commands/init.js +41 -4
- package/v3/@claude-flow/cli/dist/src/init/executor.js +25 -6
- package/v3/@claude-flow/cli/dist/src/init/mcp-generator.js +9 -4
- package/v3/@claude-flow/cli/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.5",
|
|
4
4
|
"description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Agent — Planning Interval Smoke Tests
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the planning-checkpoint injection logic fires at the correct
|
|
5
|
+
* turns and stays silent when conditions are not met. All tests are fully
|
|
6
|
+
* mocked — no live Anthropic API calls, $0 cost.
|
|
7
|
+
*
|
|
8
|
+
* Test cases:
|
|
9
|
+
* 1. 12-turn loop with interval=4 → replans at turns 4, 8, 12 (3 replans)
|
|
10
|
+
* 2. 3-turn loop with interval=4 → NO replan (interval never hit)
|
|
11
|
+
* 3. end_turn at turn 5 → NO replan injected (terminal state)
|
|
12
|
+
* 4. all-tool_use 8-turn loop → exactly floor(8/4) = 2 replans
|
|
13
|
+
* 5. planningInterval=0 → disabled entirely, 0 replans
|
|
14
|
+
*
|
|
15
|
+
* Refs: ADR-133, ADR-135, iter 34, #2156
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=gaia-agent-planning.smoke.d.ts.map
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Agent — Planning Interval Smoke Tests
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the planning-checkpoint injection logic fires at the correct
|
|
5
|
+
* turns and stays silent when conditions are not met. All tests are fully
|
|
6
|
+
* mocked — no live Anthropic API calls, $0 cost.
|
|
7
|
+
*
|
|
8
|
+
* Test cases:
|
|
9
|
+
* 1. 12-turn loop with interval=4 → replans at turns 4, 8, 12 (3 replans)
|
|
10
|
+
* 2. 3-turn loop with interval=4 → NO replan (interval never hit)
|
|
11
|
+
* 3. end_turn at turn 5 → NO replan injected (terminal state)
|
|
12
|
+
* 4. all-tool_use 8-turn loop → exactly floor(8/4) = 2 replans
|
|
13
|
+
* 5. planningInterval=0 → disabled entirely, 0 replans
|
|
14
|
+
*
|
|
15
|
+
* Refs: ADR-133, ADR-135, iter 34, #2156
|
|
16
|
+
*/
|
|
17
|
+
import assert from 'node:assert/strict';
|
|
18
|
+
import { runGaiaAgent, PLANNING_INTERVAL, buildPlanningCheckpoint } from './gaia-agent.js';
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Helpers
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/** Minimal GAIA question fixture. */
|
|
23
|
+
const FAKE_QUESTION = {
|
|
24
|
+
task_id: 'smoke-planning-01',
|
|
25
|
+
question: 'What is 2 + 2?',
|
|
26
|
+
final_answer: '4',
|
|
27
|
+
level: 1,
|
|
28
|
+
file_name: null,
|
|
29
|
+
file_path: null,
|
|
30
|
+
};
|
|
31
|
+
/** A trivial tool catalogue with one no-op tool. */
|
|
32
|
+
const NOOP_CATALOGUE = [
|
|
33
|
+
{
|
|
34
|
+
name: 'noop',
|
|
35
|
+
definition: {
|
|
36
|
+
name: 'noop',
|
|
37
|
+
description: 'Does nothing',
|
|
38
|
+
input_schema: { type: 'object', properties: {}, required: [] },
|
|
39
|
+
},
|
|
40
|
+
execute: async () => 'ok',
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Mock Anthropic API call factory
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
/**
|
|
47
|
+
* Build a mock `fetch` that simulates a specific turn sequence.
|
|
48
|
+
*
|
|
49
|
+
* `sequence` is an array of stop_reasons. The mock returns `tool_use`
|
|
50
|
+
* responses (with one `noop` tool_use block) for `tool_use` entries, and
|
|
51
|
+
* `end_turn` with a FINAL_ANSWER text block for `end_turn` entries.
|
|
52
|
+
*
|
|
53
|
+
* The mock replaces `global.fetch` for the duration of the test and is
|
|
54
|
+
* restored automatically via the returned `restore` function.
|
|
55
|
+
*/
|
|
56
|
+
function mockFetchSequence(sequence) {
|
|
57
|
+
const calls = []; // turn indices (0-based) of actual calls
|
|
58
|
+
let callIdx = 0;
|
|
59
|
+
const originalFetch = global.fetch;
|
|
60
|
+
global.fetch = async (_url, options) => {
|
|
61
|
+
const idx = callIdx++;
|
|
62
|
+
calls.push(idx);
|
|
63
|
+
const stopReason = sequence[idx] ?? 'end_turn';
|
|
64
|
+
let content;
|
|
65
|
+
if (stopReason === 'tool_use') {
|
|
66
|
+
content = [
|
|
67
|
+
{
|
|
68
|
+
type: 'tool_use',
|
|
69
|
+
id: `tool-${idx}`,
|
|
70
|
+
name: 'noop',
|
|
71
|
+
input: {},
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
content = [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: 'FINAL_ANSWER: 4',
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
const body = JSON.stringify({
|
|
84
|
+
id: `msg-${idx}`,
|
|
85
|
+
model: 'claude-haiku-4-5',
|
|
86
|
+
stop_reason: stopReason,
|
|
87
|
+
content,
|
|
88
|
+
usage: { input_tokens: 100, output_tokens: 50 },
|
|
89
|
+
});
|
|
90
|
+
return new Response(body, {
|
|
91
|
+
status: 200,
|
|
92
|
+
headers: { 'content-type': 'application/json' },
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
calls,
|
|
97
|
+
restore: () => {
|
|
98
|
+
global.fetch = originalFetch;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Base options for all tests
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
function baseOpts(overrides = {}) {
|
|
106
|
+
return {
|
|
107
|
+
apiKey: 'sk-ant-test-key',
|
|
108
|
+
catalogue: NOOP_CATALOGUE,
|
|
109
|
+
model: 'claude-haiku-4-5',
|
|
110
|
+
perTurnTimeoutMs: 5_000,
|
|
111
|
+
...overrides,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Test 1: 12-turn all-tool_use loop → 3 replans at turns 4, 8, 12
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
async function test_twelveToolUseTurns_threeReplans() {
|
|
118
|
+
// Turns 0-11 are tool_use, turn 12 (index 12) is end_turn
|
|
119
|
+
const sequence = [
|
|
120
|
+
...Array(12).fill('tool_use'),
|
|
121
|
+
'end_turn',
|
|
122
|
+
];
|
|
123
|
+
const { restore } = mockFetchSequence(sequence);
|
|
124
|
+
try {
|
|
125
|
+
const result = await runGaiaAgent(FAKE_QUESTION, baseOpts({ maxTurns: 13 }));
|
|
126
|
+
assert.equal(result.replanCount, 3, `Expected 3 replans, got ${result.replanCount}`);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
restore();
|
|
130
|
+
}
|
|
131
|
+
console.log(' PASS test_twelveToolUseTurns_threeReplans');
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Test 2: 3-turn loop → 0 replans (interval=4 never hit)
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
async function test_threeToolUseTurns_zeroReplans() {
|
|
137
|
+
const sequence = [
|
|
138
|
+
'tool_use',
|
|
139
|
+
'tool_use',
|
|
140
|
+
'tool_use',
|
|
141
|
+
'end_turn',
|
|
142
|
+
];
|
|
143
|
+
const { restore } = mockFetchSequence(sequence);
|
|
144
|
+
try {
|
|
145
|
+
const result = await runGaiaAgent(FAKE_QUESTION, baseOpts({ maxTurns: 8 }));
|
|
146
|
+
assert.equal(result.replanCount, 0, `Expected 0 replans, got ${result.replanCount}`);
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
restore();
|
|
150
|
+
}
|
|
151
|
+
console.log(' PASS test_threeToolUseTurns_zeroReplans');
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Test 3: end_turn at turn 5 → 1 replan (at turn 4), not at turn 5
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
async function test_endTurnAtFive_oneReplan() {
|
|
157
|
+
// Turns 0-4 are tool_use (5 of them), turn 5 is end_turn
|
|
158
|
+
// Replan fires at turn 4 (turns=4, turns%4===0), but NOT at turn 5 (end_turn → no injection)
|
|
159
|
+
const sequence = [
|
|
160
|
+
'tool_use',
|
|
161
|
+
'tool_use',
|
|
162
|
+
'tool_use',
|
|
163
|
+
'tool_use',
|
|
164
|
+
'tool_use',
|
|
165
|
+
'end_turn',
|
|
166
|
+
];
|
|
167
|
+
const { restore } = mockFetchSequence(sequence);
|
|
168
|
+
try {
|
|
169
|
+
const result = await runGaiaAgent(FAKE_QUESTION, baseOpts({ maxTurns: 10 }));
|
|
170
|
+
assert.equal(result.replanCount, 1, `Expected 1 replan (at turn 4), got ${result.replanCount}`);
|
|
171
|
+
assert.equal(result.timedOut, undefined, 'Should not time out');
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
restore();
|
|
175
|
+
}
|
|
176
|
+
console.log(' PASS test_endTurnAtFive_oneReplan');
|
|
177
|
+
}
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// Test 4: all tool_use for 8 turns → floor(8/4) = 2 replans
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
async function test_eightToolUseTurns_twoReplans() {
|
|
182
|
+
const sequence = [
|
|
183
|
+
...Array(8).fill('tool_use'),
|
|
184
|
+
'end_turn',
|
|
185
|
+
];
|
|
186
|
+
const { restore } = mockFetchSequence(sequence);
|
|
187
|
+
try {
|
|
188
|
+
const result = await runGaiaAgent(FAKE_QUESTION, baseOpts({ maxTurns: 9 }));
|
|
189
|
+
assert.equal(result.replanCount, 2, `Expected 2 replans, got ${result.replanCount}`);
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
restore();
|
|
193
|
+
}
|
|
194
|
+
console.log(' PASS test_eightToolUseTurns_twoReplans');
|
|
195
|
+
}
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Test 5: planningInterval=0 → disabled, 0 replans even on long runs
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
async function test_intervalZero_disabledReplanning() {
|
|
200
|
+
const sequence = [
|
|
201
|
+
...Array(8).fill('tool_use'),
|
|
202
|
+
'end_turn',
|
|
203
|
+
];
|
|
204
|
+
const { restore } = mockFetchSequence(sequence);
|
|
205
|
+
try {
|
|
206
|
+
const result = await runGaiaAgent(FAKE_QUESTION, baseOpts({ maxTurns: 9, planningInterval: 0 }));
|
|
207
|
+
assert.equal(result.replanCount, 0, `Expected 0 replans with interval=0, got ${result.replanCount}`);
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
restore();
|
|
211
|
+
}
|
|
212
|
+
console.log(' PASS test_intervalZero_disabledReplanning');
|
|
213
|
+
}
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
// Test 6: buildPlanningCheckpoint content smoke
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
function test_buildPlanningCheckpoint_content() {
|
|
218
|
+
const text = buildPlanningCheckpoint(4, 12);
|
|
219
|
+
assert.ok(text.includes('[PLANNING CHECKPOINT'), 'Missing checkpoint header');
|
|
220
|
+
assert.ok(text.includes('turn 4/12'), 'Missing turn counter');
|
|
221
|
+
assert.ok(text.includes('4 turns so far'), 'Missing turn count phrase');
|
|
222
|
+
assert.ok(text.includes('switch strategy'), 'Missing strategy-switch instruction');
|
|
223
|
+
assert.ok(text.includes('FINAL_ANSWER'), 'Missing FINAL_ANSWER instruction');
|
|
224
|
+
console.log(' PASS test_buildPlanningCheckpoint_content');
|
|
225
|
+
}
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
// Test 7: PLANNING_INTERVAL constant equals 4
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
function test_planningInterval_constant() {
|
|
230
|
+
assert.equal(PLANNING_INTERVAL, 4, `Expected PLANNING_INTERVAL=4, got ${PLANNING_INTERVAL}`);
|
|
231
|
+
console.log(' PASS test_planningInterval_constant');
|
|
232
|
+
}
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Runner
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
async function main() {
|
|
237
|
+
console.log('\n=== GAIA Agent Planning Interval Smoke Tests ===\n');
|
|
238
|
+
// Synchronous tests first
|
|
239
|
+
test_buildPlanningCheckpoint_content();
|
|
240
|
+
test_planningInterval_constant();
|
|
241
|
+
// Async tests
|
|
242
|
+
await test_twelveToolUseTurns_threeReplans();
|
|
243
|
+
await test_threeToolUseTurns_zeroReplans();
|
|
244
|
+
await test_endTurnAtFive_oneReplan();
|
|
245
|
+
await test_eightToolUseTurns_twoReplans();
|
|
246
|
+
await test_intervalZero_disabledReplanning();
|
|
247
|
+
console.log('\n=== All planning-interval smoke tests PASSED ===\n');
|
|
248
|
+
}
|
|
249
|
+
main().catch((err) => {
|
|
250
|
+
console.error('Planning interval smoke failed:', err);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
});
|
|
253
|
+
//# sourceMappingURL=gaia-agent-planning.smoke.js.map
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Agent — ADR-133-PR3 / ADR-135 (planning interval)
|
|
3
|
+
*
|
|
4
|
+
* Multi-turn Anthropic Messages API loop that drives Claude through the
|
|
5
|
+
* GAIA benchmark questions using a tool-use agent pattern.
|
|
6
|
+
*
|
|
7
|
+
* Loop algorithm:
|
|
8
|
+
* 1. Build initial message with the question and a system prompt that
|
|
9
|
+
* instructs Claude to output `FINAL_ANSWER: <value>` when done.
|
|
10
|
+
* 2. Call Anthropic Messages API with the registered tool definitions.
|
|
11
|
+
* 3. On `stop_reason === 'tool_use'`: execute all tool_use blocks in
|
|
12
|
+
* parallel, append results as a `user` turn, and repeat.
|
|
13
|
+
* Every PLANNING_INTERVAL turns, inject a planning-checkpoint text
|
|
14
|
+
* alongside the tool results to force strategy re-evaluation.
|
|
15
|
+
* 4. On `stop_reason === 'end_turn'`: scan content for the final answer
|
|
16
|
+
* pattern and return the result.
|
|
17
|
+
* 5. On timeout (maxTurns exceeded): return `{ timedOut: true }`.
|
|
18
|
+
*
|
|
19
|
+
* API key resolution order (mirrors resolveHfToken from gaia-loader.ts):
|
|
20
|
+
* 1. `options.apiKey` (caller-supplied)
|
|
21
|
+
* 2. `ANTHROPIC_API_KEY` env var
|
|
22
|
+
* 3. `gcloud secrets versions access latest --secret=ANTHROPIC_API_KEY`
|
|
23
|
+
*
|
|
24
|
+
* Cost discipline: smoke runs use `claude-haiku-4-5` only. The smoke
|
|
25
|
+
* runner at the bottom of this file enforces that model.
|
|
26
|
+
*
|
|
27
|
+
* Planning interval (iter 30 finding #3):
|
|
28
|
+
* smolagents CodeAgent uses planning_interval=4 — replans every 4 steps
|
|
29
|
+
* to prevent tunnel-vision on bad strategies. Adds ~80 tokens per
|
|
30
|
+
* replan event (~$0.0001 each), negligible cost.
|
|
31
|
+
*
|
|
32
|
+
* Iter 53a T2 narrowing:
|
|
33
|
+
* Three precise changes from iter 52 T2 (which had net -1q: +6 recoveries, -7 regressions):
|
|
34
|
+
* 1. extractFinalAnswer uses Stage 1 only (no Stage 2/3 prose fallback).
|
|
35
|
+
* Stage 2/3 fired too aggressively: overwriting correct Stage 1 answers and
|
|
36
|
+
* extracting wrong prose fragments. Now Stage 1 is the only extraction path.
|
|
37
|
+
* 2. System prompt removes surrender instruction ("FINAL_ANSWER: unknown / I don't know").
|
|
38
|
+
* That instruction caused the agent to give up on questions it would have figured out.
|
|
39
|
+
* Replaced with: "When you reach a final answer, output FINAL_ANSWER: <value>."
|
|
40
|
+
* 3. Reversed-text preprocessor is preserved (iter 52 T2 finding: 2d83110e has reversed text).
|
|
41
|
+
*
|
|
42
|
+
* Refs: ADR-133, ADR-135, iter 30, iter 52, iter 53a, #2156
|
|
43
|
+
*/
|
|
44
|
+
import { GaiaQuestion } from './gaia-loader.js';
|
|
45
|
+
import { GaiaToolCatalogue, ContentBlock } from './gaia-tools/index.js';
|
|
46
|
+
/**
|
|
47
|
+
* Every PLANNING_INTERVAL tool_use turns, inject a planning-checkpoint
|
|
48
|
+
* message to force the agent to reassess its strategy.
|
|
49
|
+
*
|
|
50
|
+
* Based on iter 30 research: smolagents CodeAgent uses planning_interval=4.
|
|
51
|
+
* HAL reliability analysis showed agents fail when they exhaust step
|
|
52
|
+
* budgets without recalibrating.
|
|
53
|
+
*/
|
|
54
|
+
export declare const PLANNING_INTERVAL = 4;
|
|
55
|
+
/**
|
|
56
|
+
* Build the planning-checkpoint text injected every PLANNING_INTERVAL turns.
|
|
57
|
+
* Exported so tests can snapshot the exact wording.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildPlanningCheckpoint(turn: number, maxTurns: number): string;
|
|
60
|
+
export interface GaiaAgentResult {
|
|
61
|
+
questionId: string;
|
|
62
|
+
finalAnswer: string | null;
|
|
63
|
+
turns: number;
|
|
64
|
+
toolCallsByName: Record<string, number>;
|
|
65
|
+
totalInputTokens: number;
|
|
66
|
+
totalOutputTokens: number;
|
|
67
|
+
wallMs: number;
|
|
68
|
+
/** Number of planning-checkpoint injections during this run (0 when planning is disabled). */
|
|
69
|
+
replanCount?: number;
|
|
70
|
+
timedOut?: boolean;
|
|
71
|
+
/** Set when the convergence layer fired and committed the final answer. */
|
|
72
|
+
convergenceTrigger?: string;
|
|
73
|
+
/** True when the convergence layer recovered the answer from prior message history. */
|
|
74
|
+
convergenceUsedFallback?: boolean;
|
|
75
|
+
error?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface GaiaAgentOptions {
|
|
78
|
+
/** Model to use (default: 'claude-haiku-4-5'). */
|
|
79
|
+
model?: string;
|
|
80
|
+
/** Maximum number of agent turns before giving up (default: 8). */
|
|
81
|
+
maxTurns?: number;
|
|
82
|
+
/** Maximum tokens per Anthropic API call (default: 2048). */
|
|
83
|
+
maxTokensPerTurn?: number;
|
|
84
|
+
/** Per-turn HTTP timeout in milliseconds (default: 60 000). */
|
|
85
|
+
perTurnTimeoutMs?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Inject a planning-checkpoint every N tool_use turns (default: PLANNING_INTERVAL = 4).
|
|
88
|
+
* Set to 0 to disable planning checkpoints.
|
|
89
|
+
*/
|
|
90
|
+
planningInterval?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Anthropic API key. Resolved automatically via env var + gcloud fallback
|
|
93
|
+
* if omitted.
|
|
94
|
+
*/
|
|
95
|
+
apiKey?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Pre-built tool catalogue. Defaults to `createDefaultToolCatalogue()`.
|
|
98
|
+
* Exposed so callers can inject mocks for testing.
|
|
99
|
+
*/
|
|
100
|
+
catalogue?: GaiaToolCatalogue;
|
|
101
|
+
/**
|
|
102
|
+
* Enable the convergence layer (default: true).
|
|
103
|
+
*
|
|
104
|
+
* When enabled, the convergence layer monitors for three failure modes:
|
|
105
|
+
* 1. max_turns hit without FINAL_ANSWER
|
|
106
|
+
* 2. Loop (same tool+args 3× in a 5-turn window)
|
|
107
|
+
* 3. Token overflow (>120k input tokens)
|
|
108
|
+
*
|
|
109
|
+
* On detection, a forced-commit phase is run: one API call with a
|
|
110
|
+
* directive prompt, no tools, then a fallback scan of prior messages.
|
|
111
|
+
* Set to false to disable (e.g. for ablation testing).
|
|
112
|
+
*/
|
|
113
|
+
enableConvergence?: boolean;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolve the Anthropic API key.
|
|
117
|
+
*
|
|
118
|
+
* Resolution order:
|
|
119
|
+
* 1. Caller-supplied `apiKey`
|
|
120
|
+
* 2. `ANTHROPIC_API_KEY` env var
|
|
121
|
+
* 3. `gcloud secrets versions access latest --secret=ANTHROPIC_API_KEY`
|
|
122
|
+
*
|
|
123
|
+
* Throws with a clear message if none of the above is available.
|
|
124
|
+
*/
|
|
125
|
+
export declare function resolveAnthropicApiKey(apiKey?: string): string;
|
|
126
|
+
/**
|
|
127
|
+
* If the question text appears to be reversed English, prepend a de-reversed
|
|
128
|
+
* version so the agent sees both the original and the decoded form.
|
|
129
|
+
*
|
|
130
|
+
* Iter 52 T2 — gate 1 finding: task 2d83110e has a reversed sentence.
|
|
131
|
+
* Kept in iter 53a (this is not the source of the iter 52 regressions).
|
|
132
|
+
*/
|
|
133
|
+
declare function buildUserMessage(question: string): string;
|
|
134
|
+
/** Anthropic image content block for vision API. */
|
|
135
|
+
interface ImageContentBlock {
|
|
136
|
+
type: 'image';
|
|
137
|
+
source: {
|
|
138
|
+
type: 'base64';
|
|
139
|
+
media_type: string;
|
|
140
|
+
data: string;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Parse an IMAGE_BASE64 marker returned by file_read's extractImage().
|
|
145
|
+
* Returns an Anthropic image content block, or null if the marker is invalid.
|
|
146
|
+
*
|
|
147
|
+
* Marker format: [IMAGE_BASE64:{"mediaType":"image/png","base64":"...","path":"..."}]
|
|
148
|
+
*/
|
|
149
|
+
export declare function parseImageMarker(marker: string): ImageContentBlock | null;
|
|
150
|
+
/** Minimal types for the Anthropic Messages API response. */
|
|
151
|
+
interface AnthropicResponse {
|
|
152
|
+
id: string;
|
|
153
|
+
model: string;
|
|
154
|
+
stop_reason: 'end_turn' | 'tool_use' | 'max_tokens' | string;
|
|
155
|
+
content: ContentBlock[];
|
|
156
|
+
usage: {
|
|
157
|
+
input_tokens: number;
|
|
158
|
+
output_tokens: number;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
declare function extractFinalAnswer(resp: AnthropicResponse): string | null;
|
|
162
|
+
/**
|
|
163
|
+
* Run a GAIA question through Claude with tool use.
|
|
164
|
+
*
|
|
165
|
+
* @returns GaiaAgentResult with the final answer (or null if timed out),
|
|
166
|
+
* turn count, token totals, and per-tool call counts.
|
|
167
|
+
*/
|
|
168
|
+
export declare function runGaiaAgent(question: GaiaQuestion, options?: GaiaAgentOptions): Promise<GaiaAgentResult>;
|
|
169
|
+
/**
|
|
170
|
+
* Check whether a model answer matches the expected ground-truth answer.
|
|
171
|
+
*
|
|
172
|
+
* Matching rules (mirrors GAIA evaluation):
|
|
173
|
+
* - Normalise: trim whitespace, lowercase.
|
|
174
|
+
* - Substring match: expected is contained in model answer (handles "Paris" vs "Paris, France").
|
|
175
|
+
* - Direct equality after normalisation.
|
|
176
|
+
* - Numeric: parse as floats and compare with ±1% tolerance.
|
|
177
|
+
*/
|
|
178
|
+
export declare function isAnswerCorrect(modelAnswer: string, expected: string): boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Run all 5 SMOKE_FIXTURE questions and report results to stdout.
|
|
181
|
+
*
|
|
182
|
+
* Pass criteria: ≥3/5 correct (60% pass rate).
|
|
183
|
+
*
|
|
184
|
+
* Cost estimate is printed at the end using Haiku pricing.
|
|
185
|
+
*
|
|
186
|
+
* This function is exported so tests can call it directly and capture output;
|
|
187
|
+
* it also runs when this file is executed directly via `node gaia-agent.js --smoke`.
|
|
188
|
+
*/
|
|
189
|
+
export declare function runSmokeTest(opts?: {
|
|
190
|
+
verbose?: boolean;
|
|
191
|
+
apiKey?: string;
|
|
192
|
+
}): Promise<{
|
|
193
|
+
passRate: number;
|
|
194
|
+
passed: number;
|
|
195
|
+
total: number;
|
|
196
|
+
}>;
|
|
197
|
+
export { extractFinalAnswer as _extractFinalAnswerForTest, buildUserMessage as _buildUserMessageForTest, };
|
|
198
|
+
//# sourceMappingURL=gaia-agent.d.ts.map
|