Files
2026-07-13 12:35:43 +08:00

68 lines
1.8 KiB
Go

package common
import (
"fmt"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)
// AttachCacheControl copies a Claude-compatible cache_control object from src onto dst.
// Returns dst unchanged when cache_control is missing or not an object.
func AttachCacheControl(dst []byte, src gjson.Result) []byte {
cc := src.Get("cache_control")
if !cc.Exists() || cc.Type == gjson.Null || !cc.IsObject() {
return dst
}
out, err := sjson.SetRawBytes(dst, "cache_control", []byte(cc.Raw))
if err != nil {
return dst
}
return out
}
// AttachMessageCacheControl applies message-level cache_control onto the last content block.
// Part-level cache_control wins when the last block already has one.
// String content is promoted to a content array so Claude can accept cache_control.
func AttachMessageCacheControl(msg []byte, src gjson.Result) []byte {
cc := src.Get("cache_control")
if !cc.Exists() || cc.Type == gjson.Null || !cc.IsObject() {
return msg
}
content := gjson.GetBytes(msg, "content")
if content.IsArray() {
arr := content.Array()
if len(arr) == 0 {
return msg
}
lastIdx := len(arr) - 1
if arr[lastIdx].Get("cache_control").Exists() {
return msg
}
path := fmt.Sprintf("content.%d.cache_control", lastIdx)
out, err := sjson.SetRawBytes(msg, path, []byte(cc.Raw))
if err != nil {
return msg
}
return out
}
if content.Type != gjson.String {
return msg
}
textPart := []byte(`{"type":"text","text":""}`)
textPart, _ = sjson.SetBytes(textPart, "text", content.String())
textPart, errSet := sjson.SetRawBytes(textPart, "cache_control", []byte(cc.Raw))
if errSet != nil {
return msg
}
out, err := sjson.SetRawBytes(msg, "content", []byte("[]"))
if err != nil {
return msg
}
out, _ = sjson.SetRawBytes(out, "content.-1", textPart)
return out
}