fix: normalize finish_reason to 'tool_calls' when tool calls are present (#379)
Some upstream providers (e.g. Antigravity) return non-standard finish_reason values like 'other' instead of the OpenAI-standard 'tool_calls' when the model invokes tools. This causes downstream consumers (e.g. OpenClaw) to fail to execute tool calls, breaking agentic sub-agent workflows. Changes: - nonStreamingHandler: post-translation guard that normalizes finish_reason to 'tool_calls' when message.tool_calls is present - sseToJsonHandler: accumulate tool_calls from streaming deltas in parseSSEToOpenAIResponse; extract function_call items from Responses API output in handleForcedSSEToJson - openai-responses translator: use toolCallIndex to choose between 'tool_calls' and 'stop' in flush and response.completed events Tested: 7 scenarios (non-stream text, single/multiple tool calls, stream text/tool calls, multi-turn tool conversation, tools present but unused)
This commit is contained in:
@@ -161,6 +161,16 @@ export async function handleNonStreamingResponse({ providerResponse, provider, m
|
||||
? translateNonStreamingResponse(responseBody, targetFormat, sourceFormat)
|
||||
: responseBody;
|
||||
|
||||
// Fix finish_reason for tool_calls: some providers return non-standard values (e.g. "other")
|
||||
if (translatedResponse?.choices?.[0]) {
|
||||
const choice = translatedResponse.choices[0];
|
||||
const msg = choice.message;
|
||||
const hasToolCalls = Array.isArray(msg?.tool_calls) && msg.tool_calls.length > 0;
|
||||
if (hasToolCalls && choice.finish_reason !== "tool_calls") {
|
||||
choice.finish_reason = "tool_calls";
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure OpenAI-required fields
|
||||
if (!translatedResponse.object) translatedResponse.object = "chat.completion";
|
||||
if (!translatedResponse.created) translatedResponse.created = Math.floor(Date.now() / 1000);
|
||||
|
||||
Reference in New Issue
Block a user