fix(translator): stop emitting empty <think> markers into OpenAI content
This commit is contained in:
@@ -333,6 +333,9 @@ export function createResponsesApiTransformStream(logger = null) {
|
||||
|
||||
// Regular text content
|
||||
if (content) {
|
||||
// The answer starts, so thinking is over. Upstreams that send reasoning via
|
||||
// reasoning_content never emit "</think>", so close it here rather than at finish.
|
||||
closeReasoning(controller);
|
||||
if (!state.msgItemAdded[idx]) {
|
||||
state.msgItemAdded[idx] = true;
|
||||
const msgId = `msg_${state.responseId}_${idx}`;
|
||||
@@ -372,6 +375,7 @@ export function createResponsesApiTransformStream(logger = null) {
|
||||
|
||||
// Handle tool_calls
|
||||
if (delta.tool_calls) {
|
||||
closeReasoning(controller);
|
||||
closeMessage(controller, idx);
|
||||
|
||||
for (const tc of delta.tool_calls) {
|
||||
|
||||
@@ -59,10 +59,6 @@ export function claudeToOpenAIResponse(chunk, state) {
|
||||
}
|
||||
if (block?.type === CLAUDE_BLOCK.TEXT) {
|
||||
state.textBlockStarted = true;
|
||||
} else if (block?.type === CLAUDE_BLOCK.THINKING) {
|
||||
state.inThinkingBlock = true;
|
||||
state.currentBlockIndex = chunk.index;
|
||||
results.push(createChunk(state, { content: "<think>" }));
|
||||
} else if (block?.type === CLAUDE_BLOCK.TOOL_USE) {
|
||||
const toolCallIndex = state.toolCallIndex++;
|
||||
// Restore original tool name from mapping (Claude OAuth)
|
||||
@@ -89,6 +85,8 @@ export function claudeToOpenAIResponse(chunk, state) {
|
||||
if (delta?.type === "text_delta" && delta.text) {
|
||||
results.push(createChunk(state, { content: delta.text }));
|
||||
} else if (delta?.type === "thinking_delta" && delta.thinking) {
|
||||
// Thinking travels only in reasoning_content. No "<think>" markers in
|
||||
// content: OpenAI-format clients render them as literal text.
|
||||
results.push(createChunk(state, reasoningDelta(delta.thinking)));
|
||||
} else if (delta?.type === "input_json_delta" && delta.partial_json) {
|
||||
const toolCall = state.toolCalls.get(chunk.index);
|
||||
@@ -112,10 +110,6 @@ export function claudeToOpenAIResponse(chunk, state) {
|
||||
state.serverToolBlockIndex = -1;
|
||||
break;
|
||||
}
|
||||
if (state.inThinkingBlock && chunk.index === state.currentBlockIndex) {
|
||||
results.push(createChunk(state, { content: "</think>" }));
|
||||
state.inThinkingBlock = false;
|
||||
}
|
||||
state.textBlockStarted = false;
|
||||
state.thinkingBlockStarted = false;
|
||||
break;
|
||||
|
||||
@@ -129,12 +129,16 @@ export function openaiToOpenAIResponsesResponse(chunk, state) {
|
||||
}
|
||||
|
||||
if (content) {
|
||||
// The answer starts, so thinking is over. Upstreams that send reasoning via
|
||||
// reasoning_content never emit "</think>", so close it here rather than at finish.
|
||||
closeReasoning(state, emit);
|
||||
emitTextContent(state, emit, idx, content);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle tool_calls (empty array is truthy; require a real call)
|
||||
if (delta.tool_calls && delta.tool_calls.length) {
|
||||
closeReasoning(state, emit);
|
||||
closeMessage(state, emit, idx);
|
||||
for (const tc of delta.tool_calls) {
|
||||
emitToolCall(state, emit, tc);
|
||||
|
||||
Reference in New Issue
Block a user