fix(transformers): preserve tool ordering across proxy streams

- reject pending tool_result layouts that cannot be translated without reordering user content

- keep interleaved GLMT tool_use blocks open until finalization instead of stopping early

- cover leading/interleaved tool_result regressions and interleaved streaming tool fragments
This commit is contained in:
Tam Nhu Tran committed 2026-04-20 13:17:30 -04:00
1 parent 889d3d89e9
commit 399f403322
5 files changed
+202 -34

No files matched your search

+39 -18
View File
@@ -457,9 +457,35 @@ function transformMessages(messagesValue: unknown): OpenAIMessage[] {
}
if (role === 'user') {
const preToolResultParts: OpenAIContentPart[] = [];
const userParts: OpenAIContentPart[] = [];
const followUpParts: OpenAIContentPart[] = [];
const resolvedToolUseIds = new Set<string>();
const handleUserPart = (
part: OpenAIContentPart,
blockIndex: number,
kind: 'text' | 'image'
) => {
if (!pendingToolUseIds || pendingToolUseIds.size === 0) {
userParts.push(part);
return;
}
if (resolvedToolUseIds.size === 0) {
throw new Error(
`messages[${messageIndex}].content[${blockIndex}] ${kind} is not allowed before tool_result blocks for pending tool_use ids`
);
}
if (resolvedToolUseIds.size !== pendingToolUseIds.size) {
throw new Error(
`messages[${messageIndex}].content[${blockIndex}] ${kind} is not allowed between tool_result blocks for pending tool_use ids`
);
}
followUpParts.push(part);
};
content.forEach((block, blockIndex) => {
const parsed = assertObject(
block,
@@ -472,25 +498,16 @@ function transformMessages(messagesValue: unknown): OpenAIMessage[] {
if (parsed.type === 'text') {
const text = typeof parsed.text === 'string' ? parsed.text : '';
if (pendingToolUseIds && pendingToolUseIds.size > 0 && !resolvedToolUseIds.size) {
preToolResultParts.push({ type: 'text', text });
} else {
translatedMessages.push({ role: 'user', content: text });
}
handleUserPart({ type: 'text', text }, blockIndex, 'text');
return;
}
if (isImageBlock(parsed)) {
if (pendingToolUseIds && pendingToolUseIds.size > 0 && !resolvedToolUseIds.size) {
preToolResultParts.push(
toImagePart(parsed, `messages[${messageIndex}].content[${blockIndex}]`)
);
} else {
translatedMessages.push({
role: 'user',
content: [toImagePart(parsed, `messages[${messageIndex}].content[${blockIndex}]`)],
});
}
handleUserPart(
toImagePart(parsed, `messages[${messageIndex}].content[${blockIndex}]`),
blockIndex,
'image'
);
return;
}
@@ -555,8 +572,12 @@ function transformMessages(messagesValue: unknown): OpenAIMessage[] {
);
}
if (preToolResultParts.length > 0) {
flushUserContent(translatedMessages, preToolResultParts);
if (userParts.length > 0) {
flushUserContent(translatedMessages, userParts);
}
if (followUpParts.length > 0) {
flushUserContent(translatedMessages, followUpParts);
}
return;
}