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:
parent
77b0c43392
commit
c85f572687
2 changed files with 28 additions and 9 deletions
|
|
@ -178,17 +178,34 @@ func buildRequestBody(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process messages
|
// Process messages
|
||||||
var systemPrompt string
|
var systemBlocks []map[string]any
|
||||||
var apiMessages []any
|
var apiMessages []any
|
||||||
|
|
||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
switch msg.Role {
|
switch msg.Role {
|
||||||
case "system":
|
case "system":
|
||||||
// Accumulate system messages
|
// Prefer structured SystemParts for per-block cache_control.
|
||||||
if systemPrompt != "" {
|
// This enables Anthropic prompt caching: static blocks keep a
|
||||||
systemPrompt += "\n\n" + msg.Content
|
// 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 {
|
} 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":
|
case "user":
|
||||||
|
|
@ -280,9 +297,9 @@ func buildRequestBody(
|
||||||
|
|
||||||
result["messages"] = apiMessages
|
result["messages"] = apiMessages
|
||||||
|
|
||||||
// Set system prompt if present
|
// Set system prompt if present (always as content blocks array for cache_control support)
|
||||||
if systemPrompt != "" {
|
if len(systemBlocks) > 0 {
|
||||||
result["system"] = systemPrompt
|
result["system"] = systemBlocks
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tools if present
|
// Add tools if present
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,9 @@ func TestBuildRequestBody(t *testing.T) {
|
||||||
want: map[string]any{
|
want: map[string]any{
|
||||||
"model": "test-model",
|
"model": "test-model",
|
||||||
"max_tokens": int64(8192),
|
"max_tokens": int64(8192),
|
||||||
"system": "You are a helpful assistant.",
|
"system": []map[string]any{
|
||||||
|
{"type": "text", "text": "You are a helpful assistant."},
|
||||||
|
},
|
||||||
"messages": []any{
|
"messages": []any{
|
||||||
map[string]any{
|
map[string]any{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue