68 lines
1.8 KiB
Go
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
|
|
}
|