fix(translator): map mid-conversation system message to user in claude-to-openai
Claude Code chèn role:system cuối messages[], trước đây bị map thành assistant khiến hội thoại không kết thúc bằng user → provider OpenAI-compat (LiteLLM) dịch ngược Anthropic trả 400 "assistant message prefill". Map system -> user và wrap <system-reminder> để giữ ngữ nghĩa instruction. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -129,8 +129,24 @@ function fixMissingToolResponsesOpenAI(messages) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap mid-conversation system text so it ends as a user turn (avoids Anthropic prefill 400)
|
||||||
|
function systemReminderText(content) {
|
||||||
|
const parts = Array.isArray(content)
|
||||||
|
? content.filter(c => c?.type === CLAUDE_BLOCK.TEXT).map(c => c.text || "")
|
||||||
|
: [typeof content === "string" ? content : ""];
|
||||||
|
const text = parts.filter(Boolean).join("\n");
|
||||||
|
if (!text.trim()) return "";
|
||||||
|
return `<system-reminder>\n${text}\n</system-reminder>`;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert single Claude message - returns single message or array of messages
|
// Convert single Claude message - returns single message or array of messages
|
||||||
function convertClaudeMessage(msg) {
|
function convertClaudeMessage(msg) {
|
||||||
|
// Mid-conversation system message -> user (per Anthropic placement rules)
|
||||||
|
if (msg.role === ROLE.SYSTEM) {
|
||||||
|
const text = systemReminderText(msg.content);
|
||||||
|
return text ? { role: ROLE.USER, content: text } : null;
|
||||||
|
}
|
||||||
|
|
||||||
const role = msg.role === ROLE.USER || msg.role === ROLE.TOOL ? ROLE.USER : ROLE.ASSISTANT;
|
const role = msg.role === ROLE.USER || msg.role === ROLE.TOOL ? ROLE.USER : ROLE.ASSISTANT;
|
||||||
|
|
||||||
// Simple string content
|
// Simple string content
|
||||||
|
|||||||
Reference in New Issue
Block a user