mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-12 09:14:15 +00:00
fix: use sjson to build system blocks, avoid raw newlines in JSON
The previous commit used fmt.Sprintf with %s to insert multi-line string constants into JSON strings. Go raw string literals contain actual newline bytes, which produce invalid JSON (control characters in string values). Replace with buildTextBlock() helper that uses sjson.SetBytes to properly escape text content for JSON serialization.
This commit is contained in:
@@ -1302,11 +1302,14 @@ func checkSystemInstructionsWithSigningMode(payload []byte, strictMode bool, exp
|
||||
billingBlock := fmt.Sprintf(`{"type":"text","text":"%s"}`, billingText)
|
||||
|
||||
// Build system blocks matching real Claude Code structure.
|
||||
// Use buildTextBlock instead of fmt.Sprintf to properly escape multi-line text.
|
||||
// Cache control scopes: 'org' for agent block, 'global' for core prompt.
|
||||
agentBlock := fmt.Sprintf(`{"type":"text","text":"You are Claude Code, Anthropic's official CLI for Claude.","cache_control":{"type":"ephemeral","scope":"org"}}`)
|
||||
introBlock := fmt.Sprintf(`{"type":"text","text":"%s","cache_control":{"type":"ephemeral","scope":"global"}}`, claudeCodeIntro)
|
||||
systemBlock := fmt.Sprintf(`{"type":"text","text":"%s"}`, claudeCodeSystem)
|
||||
doingTasksBlock := fmt.Sprintf(`{"type":"text","text":"%s"}`, claudeCodeDoingTasks)
|
||||
agentBlock := buildTextBlock("You are Claude Code, Anthropic's official CLI for Claude.",
|
||||
map[string]string{"type": "ephemeral", "scope": "org"})
|
||||
introBlock := buildTextBlock(claudeCodeIntro,
|
||||
map[string]string{"type": "ephemeral", "scope": "global"})
|
||||
systemBlock := buildTextBlock(claudeCodeSystem, nil)
|
||||
doingTasksBlock := buildTextBlock(claudeCodeDoingTasks, nil)
|
||||
|
||||
systemResult := "[" + billingBlock + "," + agentBlock + "," + introBlock + "," + systemBlock + "," + doingTasksBlock + "]"
|
||||
payload, _ = sjson.SetRawBytes(payload, "system", []byte(systemResult))
|
||||
@@ -1337,6 +1340,20 @@ func checkSystemInstructionsWithSigningMode(payload []byte, strictMode bool, exp
|
||||
return payload
|
||||
}
|
||||
|
||||
// buildTextBlock constructs a JSON text block object with proper escaping.
|
||||
// Uses sjson.SetBytes to handle multi-line text, quotes, and control characters.
|
||||
// cacheControl is optional; pass nil to omit cache_control.
|
||||
func buildTextBlock(text string, cacheControl map[string]string) string {
|
||||
block := []byte(`{"type":"text"}`)
|
||||
block, _ = sjson.SetBytes(block, "text", text)
|
||||
if cacheControl != nil {
|
||||
for k, v := range cacheControl {
|
||||
block, _ = sjson.SetBytes(block, "cache_control."+k, v)
|
||||
}
|
||||
}
|
||||
return string(block)
|
||||
}
|
||||
|
||||
// prependToFirstUserMessage prepends text content to the first user message.
|
||||
// This avoids putting non-Claude-Code system instructions in system[] which
|
||||
// triggers Anthropic's extra usage billing for OAuth-proxied requests.
|
||||
|
||||
Reference in New Issue
Block a user