Preserve Codex reasoning signatures for Claude

This commit is contained in:
sususu
2026-04-27 16:46:00 +08:00
parent d85e13b044
commit c523101439
4 changed files with 332 additions and 74 deletions
@@ -31,6 +31,7 @@ type ConvertCodexResponseToClaudeParams struct {
ThinkingBlockOpen bool
ThinkingStopPending bool
ThinkingSignature string
ThinkingSummarySeen bool
}
// ConvertCodexResponseToClaude performs sophisticated streaming response format conversion.
@@ -86,12 +87,8 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa
if params.ThinkingBlockOpen && params.ThinkingStopPending {
output = append(output, finalizeCodexThinkingBlock(params)...)
}
template = []byte(`{"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}}`)
template, _ = sjson.SetBytes(template, "index", params.BlockIndex)
params.ThinkingBlockOpen = true
params.ThinkingStopPending = false
output = translatorcommon.AppendSSEEventBytes(output, "content_block_start", template, 2)
params.ThinkingSummarySeen = true
output = append(output, startCodexThinkingBlock(params)...)
} else if typeStr == "response.reasoning_summary_text.delta" {
template = []byte(`{"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":""}}`)
template, _ = sjson.SetBytes(template, "index", params.BlockIndex)
@@ -100,9 +97,6 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa
output = translatorcommon.AppendSSEEventBytes(output, "content_block_delta", template, 2)
} else if typeStr == "response.reasoning_summary_part.done" {
params.ThinkingStopPending = true
if params.ThinkingSignature != "" {
output = append(output, finalizeCodexThinkingBlock(params)...)
}
} else if typeStr == "response.content_part.added" {
template = []byte(`{"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}`)
template, _ = sjson.SetBytes(template, "index", params.BlockIndex)
@@ -169,10 +163,8 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa
output = translatorcommon.AppendSSEEventBytes(output, "content_block_delta", template, 2)
} else if itemType == "reasoning" {
params.ThinkingSummarySeen = false
params.ThinkingSignature = itemResult.Get("encrypted_content").String()
if params.ThinkingStopPending {
output = append(output, finalizeCodexThinkingBlock(params)...)
}
}
} else if typeStr == "response.output_item.done" {
itemResult := rootResult.Get("item")
@@ -229,8 +221,13 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa
if signature := itemResult.Get("encrypted_content").String(); signature != "" {
params.ThinkingSignature = signature
}
output = append(output, finalizeCodexThinkingBlock(params)...)
if params.ThinkingSummarySeen {
output = append(output, finalizeCodexThinkingBlock(params)...)
} else {
output = append(output, finalizeCodexSignatureOnlyThinkingBlock(params)...)
}
params.ThinkingSignature = ""
params.ThinkingSummarySeen = false
}
} else if typeStr == "response.function_call_arguments.delta" {
params.HasReceivedArgumentsDelta = true
@@ -437,6 +434,29 @@ func ClaudeTokenCount(_ context.Context, count int64) []byte {
return translatorcommon.ClaudeInputTokensJSON(count)
}
func startCodexThinkingBlock(params *ConvertCodexResponseToClaudeParams) []byte {
if params.ThinkingBlockOpen {
return nil
}
template := []byte(`{"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}}`)
template, _ = sjson.SetBytes(template, "index", params.BlockIndex)
params.ThinkingBlockOpen = true
params.ThinkingStopPending = false
return translatorcommon.AppendSSEEventBytes(nil, "content_block_start", template, 2)
}
func finalizeCodexSignatureOnlyThinkingBlock(params *ConvertCodexResponseToClaudeParams) []byte {
if params.ThinkingSignature == "" {
return nil
}
output := startCodexThinkingBlock(params)
output = append(output, finalizeCodexThinkingBlock(params)...)
return output
}
func finalizeCodexThinkingBlock(params *ConvertCodexResponseToClaudeParams) []byte {
if !params.ThinkingBlockOpen {
return nil