fix(provider): anthropic_messages sends system as content blocks with cache_control

- Use SystemParts structured blocks when available, with per-block
  cache_control for Anthropic prompt caching support
- Fall back to plain text block when SystemParts is absent
- Output system as content blocks array instead of flat string
- Update test expectation to match new array format
This commit is contained in:
smallwhite 2026-03-30 20:38:31 +08:00 committed by guangdianclaw
parent 77b0c43392
commit c85f572687
2 changed files with 28 additions and 9 deletions

View file

@ -178,17 +178,34 @@ func buildRequestBody(
}
// Process messages
var systemPrompt string
var systemBlocks []map[string]any
var apiMessages []any
for _, msg := range messages {
switch msg.Role {
case "system":
// Accumulate system messages
if systemPrompt != "" {
systemPrompt += "\n\n" + msg.Content
// Prefer structured SystemParts for per-block cache_control.
// This enables Anthropic prompt caching: static blocks keep a
// stable prefix hash while dynamic parts (time, session) change.
if len(msg.SystemParts) > 0 {
for _, part := range msg.SystemParts {
block := map[string]any{
"type": "text",
"text": part.Text,
}
if part.CacheControl != nil && part.CacheControl.Type != "" {
block["cache_control"] = map[string]string{
"type": part.CacheControl.Type,
}
}
systemBlocks = append(systemBlocks, block)
}
} else {
systemPrompt = msg.Content
// Fallback: no structured parts, use plain text block.
systemBlocks = append(systemBlocks, map[string]any{
"type": "text",
"text": msg.Content,
})
}
case "user":
@ -280,9 +297,9 @@ func buildRequestBody(
result["messages"] = apiMessages
// Set system prompt if present
if systemPrompt != "" {
result["system"] = systemPrompt
// Set system prompt if present (always as content blocks array for cache_control support)
if len(systemBlocks) > 0 {
result["system"] = systemBlocks
}
// Add tools if present

View file

@ -86,7 +86,9 @@ func TestBuildRequestBody(t *testing.T) {
want: map[string]any{
"model": "test-model",
"max_tokens": int64(8192),
"system": "You are a helpful assistant.",
"system": []map[string]any{
{"type": "text", "text": "You are a helpful assistant."},
},
"messages": []any{
map[string]any{
"role": "user",