From 31f817d189c6db22940c8b836c50f48073dae61a Mon Sep 17 00:00:00 2001 From: cyhhao Date: Thu, 29 Jan 2026 01:28:43 +0800 Subject: [PATCH] fix: add newline separation for Claude Code system prompt --- backend/internal/service/account_test_service.go | 2 +- backend/internal/service/gateway_service.go | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/internal/service/account_test_service.go b/backend/internal/service/account_test_service.go index 46376c69..3290fe52 100644 --- a/backend/internal/service/account_test_service.go +++ b/backend/internal/service/account_test_service.go @@ -123,7 +123,7 @@ func createTestPayload(modelID string) (map[string]any, error) { "system": []map[string]any{ { "type": "text", - "text": "You are Claude Code, Anthropic's official CLI for Claude.", + "text": claudeCodeSystemPrompt, "cache_control": map[string]string{ "type": "ephemeral", }, diff --git a/backend/internal/service/gateway_service.go b/backend/internal/service/gateway_service.go index b46e856e..b1507245 100644 --- a/backend/internal/service/gateway_service.go +++ b/backend/internal/service/gateway_service.go @@ -39,7 +39,9 @@ const ( claudeAPICountTokensURL = "https://api.anthropic.com/v1/messages/count_tokens?beta=true" stickySessionTTL = time.Hour // 粘性会话TTL defaultMaxLineSize = 40 * 1024 * 1024 - claudeCodeSystemPrompt = "You are Claude Code, Anthropic's official CLI for Claude." + // Keep a trailing blank line so that when upstream concatenates system strings, + // the injected Claude Code banner doesn't run into the next system instruction. + claudeCodeSystemPrompt = "You are Claude Code, Anthropic's official CLI for Claude.\n\n" maxCacheControlBlocks = 4 // Anthropic API 允许的最大 cache_control 块数量 ) @@ -2479,7 +2481,8 @@ func injectClaudeCodePrompt(body []byte, system any) []byte { case nil: newSystem = []any{claudeCodeBlock} case string: - if v == "" || v == claudeCodeSystemPrompt { + // Be tolerant of older/newer clients that may differ only by trailing whitespace/newlines. + if strings.TrimSpace(v) == "" || strings.TrimSpace(v) == strings.TrimSpace(claudeCodeSystemPrompt) { newSystem = []any{claudeCodeBlock} } else { newSystem = []any{claudeCodeBlock, map[string]any{"type": "text", "text": v}} @@ -2489,7 +2492,7 @@ func injectClaudeCodePrompt(body []byte, system any) []byte { newSystem = append(newSystem, claudeCodeBlock) for _, item := range v { if m, ok := item.(map[string]any); ok { - if text, ok := m["text"].(string); ok && text == claudeCodeSystemPrompt { + if text, ok := m["text"].(string); ok && strings.TrimSpace(text) == strings.TrimSpace(claudeCodeSystemPrompt) { continue } }