fix(research): Claude Opus 4.7 rejects temperature param + log executor errors

- claude-web-search.ts: only send `temperature` when caller explicitly
  sets one. Opus 4.7 deprecated the param and returns
  400 invalid_request_error "`temperature` is deprecated for this
  model." Sonnet/Haiku still accept it, so keep the opt-in path.
- execute-research.ts: log provider errors via console.warn so future
  integration failures are visible in stdout. Previously the executor
  swallowed the underlying error and only returned a generic errorCode,
  which made diagnosing vendor-specific API changes impossible.

Discovered via smoke-testing with a real Anthropic key — the direct
curl worked, but our provider 400'd because Opus 4.7 tightened the
accepted param set.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-18 16:36:22 +02:00
parent 5d67179842
commit 536fc89050
2 changed files with 20 additions and 14 deletions

View file

@ -133,6 +133,7 @@ export async function executeResearch(
function makeError(providerId: ProviderId, t0: number, err: Error): ExecuteResearchOutput {
const code = (err as { code?: string }).code ?? err.name ?? 'ERROR';
console.warn(`[executor.research] ${providerId} failed:`, err.message, err);
return {
success: false,
meta: {

View file

@ -55,6 +55,24 @@ export function createClaudeWebSearchProvider(): ResearchAgent {
const model = options.model ?? DEFAULT_MODEL;
// Claude Opus 4.7 deprecated the `temperature` param; only set it
// when the caller explicitly asked for one (older Sonnet/Haiku
// accept it but Opus 4.7 rejects with 400 invalid_request_error).
const body: Record<string, unknown> = {
model,
max_tokens: options.maxTokens ?? 2048,
system: options.systemPrompt,
messages: [{ role: 'user', content: query }],
tools: [
{
type: 'web_search_20250305',
name: 'web_search',
max_uses: DEFAULT_MAX_SEARCHES,
},
],
};
if (options.temperature !== undefined) body.temperature = options.temperature;
const res = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
@ -62,20 +80,7 @@ export function createClaudeWebSearchProvider(): ResearchAgent {
'anthropic-version': '2023-06-01',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model,
max_tokens: options.maxTokens ?? 2048,
temperature: options.temperature ?? 0.3,
system: options.systemPrompt,
messages: [{ role: 'user', content: query }],
tools: [
{
type: 'web_search_20250305',
name: 'web_search',
max_uses: DEFAULT_MAX_SEARCHES,
},
],
}),
body: JSON.stringify(body),
signal: ctx.signal,
});