Error: 400 Item 'fc_...' of type 'function_call' was provided without its required 'reasoning' item: 'rs_...'for (const block of msg.content) { if (block.type === "thinking") { if (block.thinkingSignature) { // Only if signature exists const reasoningItem = JSON.parse(block.thinkingSignature); output.push(reasoningItem); } } else if (block.type === "toolCall") { // Always pushed, regardless of whether reasoning was pushed output.push({ type: "function_call", ... }); }}} else if (msg.role === "assistant") { const output: ResponseInput = []; // Check if this is an incomplete turn that shouldn't replay tool calls const isIncomplete = msg.stopReason === "error" || msg.stopReason === "aborted"; // Check if we have valid paired content (reasoning requires paired content on Azure) const hasValidReasoningSignature = msg.content.some( (b) => b.type === "thinking" && b.thinkingSignature ); const hasPairedContent = msg.content.some( (b) => b.type === "toolCall" || (b.type === "text" && (b as TextContent).text.trim().length > 0) ); const shouldReplayReasoning = !isIncomplete && hasPairedContent; const allowToolCalls = !isIncomplete && (hasValidReasoningSignature || !model.reasoning);
for (const block of msg.content) { if (block.type === "thinking" && shouldReplayReasoning) { // ... existing logic } else if (block.type === "toolCall" && allowToolCalls) { // ... existing logic } // text blocks unchanged }}if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") { continue;}if (block.type === "thinking") { // For same model: keep thinking blocks with signatures (needed for replay) // even if the thinking text is empty (OpenAI encrypted reasoning) if (isSameModel && block.thinkingSignature) return block; // Skip empty thinking blocks, convert others to plain text if (!block.thinking || block.thinking.trim() === "") return []; if (isSameModel) return block; return { type: "text" as const, text: block.thinking };}} else if (msg.role === "assistant") { const output: ResponseInput = []; // For reasoning models, only include tool calls if we have valid reasoning to pair with const hasReasoningSignature = msg.content.some( (b) => b.type === "thinking" && b.thinkingSignature );
for (const block of msg.content) { if (block.type === "thinking") { if (block.thinkingSignature) { output.push(JSON.parse(block.thinkingSignature)); } } else if (block.type === "text") { // ... unchanged } else if (block.type === "toolCall") { // Only include tool calls if we have paired reasoning (for reasoning models) // This prevents orphaned function_calls that Azure rejects if (!model.reasoning || hasReasoningSignature) { // ... existing logic } } }}const isSameModel = assistantMsg.provider === model.provider && assistantMsg.api === model.api && assistantMsg.model === model.id;if (isSameModel && block.thinkingSignature) return block; // Works!Error: 400 Item 'fc_...' of type 'function_call' was provided without its required 'reasoning' item: 'rs_...'// For reasoning models: only include function_calls if we have valid reasoning// For non-reasoning models: always include function_calls (no pairing)const hasReasoningSignature = msg.content.some( (b) => b.type === "thinking" && b.thinkingSignature);
// When processing toolCall blocks:if (block.type === "toolCall") { if (!model.reasoning || hasReasoningSignature) { // Include the tool call } // Otherwise drop it - orphaned without its paired reasoning}Error: 400 No tool call found for function call output with call_id call_...if (hasThinkingBlock && hasSignature) → send as function_callif (hasThinkingBlock && !hasSignature) → convert to text (signature lost)if (!hasThinkingBlock) → convert to text (from non-reasoning model)if (hasSignature) → send as function_callelse → convert to textconst hasReasoningSignature = msg.content.some( (b) => b.type === "thinking" && (b as ThinkingContent).thinkingSignature,);Error: 400 Item 'fc_...' of type 'function_call' was provided without its required 'reasoning' itemError: 400 Item 'fc_...' of type 'function_call' was provided without its required 'reasoning' itemconst isSameModel = assistantMsg.provider === model.provider && assistantMsg.api === model.api && assistantMsg.model === model.id;Error: 400 Item 'fc_...' of type 'function_call' was provided without its required 'reasoning' item: 'rs_...'