Skip to content

fix: claude & gemini endpoint system prompt overwrite - #1850

Merged
seefs001 merged 2 commits into
QuantumNous:mainfrom
seefs001:fix/claude-system-prompt-overwrite
Sep 20, 2025
Merged

fix: claude & gemini endpoint system prompt overwrite#1850
seefs001 merged 2 commits into
QuantumNous:mainfrom
seefs001:fix/claude-system-prompt-overwrite

Conversation

@seefs001

@seefs001 seefs001 commented Sep 19, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Automatic system prompt override for Claude requests when enabled in channel settings.
    • Works with both plain-text and structured system messages: the channel prompt is prepended to existing content, or used alone if none exists.
    • Applies transparently before requests are sent to Claude, ensuring consistent prompt behavior across channels.

@coderabbitai

coderabbitai Bot commented Sep 19, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds logic in relay/claude_handler.go to automatically inject or prepend a channel-level system prompt into Claude requests when SystemPromptOverride is enabled, handling both string and structured system content, setting a context key for the override, and running this before building the upstream request payload.

Changes

Cohort / File(s) Summary
Claude system prompt override handling
relay/claude_handler.go
Adds pre-request logic to apply ChannelSetting.SystemPrompt when SystemPromptOverride is true: sets system string if absent, prepends when present, or inserts a text media message for structured content; sets ContextKeySystemPromptOverride; imports constant package.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Handler as Claude Handler
  participant Chan as ChannelSettings
  participant Ctx as Context
  participant Claude as Upstream Claude API

  Client->>Handler: Send request (messages incl. system)
  Handler->>Chan: Read SystemPrompt & Override flag
  alt Override enabled
    opt No system content
      Handler->>Handler: Set system = ChannelSetting.SystemPrompt
    end
    opt String system content
      Handler->>Handler: Prepend ChannelPrompt (+ newline if needed)
    end
    opt Structured system content
      Handler->>Handler: Create text media message with ChannelPrompt and prepend
    end
    Handler->>Ctx: Set ContextKeySystemPromptOverride
  end
  Handler->>Claude: Send modified payload
  Claude-->>Handler: Response
  Handler-->>Client: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I tucked a prompt before the dawn,
A whisper woven, neatly drawn—
String or media, stacked just right,
I nudge the system into sight.
With ears alert, I ship upstream,
A tidy hop to Claude’s bright stream. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The changeset primarily updates relay/claude_handler.go to implement automatic system prompt handling for Claude, so the title's reference to Claude is directly relevant; however, the title also mentions "gemini" while the provided summary shows no Gemini-related changes, making the title slightly misleading. The title is otherwise concise and communicates the main intent.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
relay/claude_handler.go (3)

73-96: Always set the context flag when overriding; simplify redundant condition.

The override flag is only set when request.System != nil. If request.System == nil, you still override but don’t mark it in context. Also, the nested else if info.ChannelSetting.SystemPromptOverride is redundant given the outer condition.

Apply this minimal diff:

-	if info.ChannelSetting.SystemPrompt != "" && info.ChannelSetting.SystemPromptOverride {
-		if request.System == nil {
-			request.SetStringSystem(info.ChannelSetting.SystemPrompt)
-		} else if info.ChannelSetting.SystemPromptOverride {
-			common.SetContextKey(c, constant.ContextKeySystemPromptOverride, true)
+	if info.ChannelSetting.SystemPrompt != "" && info.ChannelSetting.SystemPromptOverride {
+		// Mark override for downstream logging/handlers in all cases.
+		common.SetContextKey(c, constant.ContextKeySystemPromptOverride, true)
+		if request.System == nil {
+			request.SetStringSystem(info.ChannelSetting.SystemPrompt)
+		} else {
 			if request.IsStringSystem() {
 				existing := strings.TrimSpace(request.GetStringSystem())
 				if existing == "" {
 					request.SetStringSystem(info.ChannelSetting.SystemPrompt)
 				} else {
 					request.SetStringSystem(info.ChannelSetting.SystemPrompt + "\n" + existing)
 				}
 			} else {
 				systemContents := request.ParseSystem()
 				newSystem := dto.ClaudeMediaMessage{Type: dto.ContentTypeText}
 				newSystem.SetText(info.ChannelSetting.SystemPrompt)
 				if len(systemContents) == 0 {
 					request.System = []dto.ClaudeMediaMessage{newSystem}
 				} else {
 					request.System = append([]dto.ClaudeMediaMessage{newSystem}, systemContents...)
 				}
 			}
 		}
 	}

78-85: De-duplicate to avoid double-prepending in string system case.

If the channel prompt is already present (e.g., on retries or upstream already included it), this will prepend it again.

-			if request.IsStringSystem() {
-				existing := strings.TrimSpace(request.GetStringSystem())
+			if request.IsStringSystem() {
+				existing := strings.TrimSpace(request.GetStringSystem())
+				channel := strings.TrimSpace(info.ChannelSetting.SystemPrompt)
 				if existing == "" {
-					request.SetStringSystem(info.ChannelSetting.SystemPrompt)
-				} else {
-					request.SetStringSystem(info.ChannelSetting.SystemPrompt + "\n" + existing)
+					request.SetStringSystem(channel)
+				} else if !strings.HasPrefix(existing, channel) {
+					request.SetStringSystem(channel + "\n" + existing)
 				}

86-94: De-duplicate in structured system case.

Skip prepend when the first block already equals the channel prompt (type=text, same text).

-			} else {
+			} else {
 				systemContents := request.ParseSystem()
-				newSystem := dto.ClaudeMediaMessage{Type: dto.ContentTypeText}
-				newSystem.SetText(info.ChannelSetting.SystemPrompt)
+				channel := strings.TrimSpace(info.ChannelSetting.SystemPrompt)
+				newSystem := dto.ClaudeMediaMessage{Type: dto.ContentTypeText}
+				newSystem.SetText(channel)
 				if len(systemContents) == 0 {
 					request.System = []dto.ClaudeMediaMessage{newSystem}
 				} else {
-					request.System = append([]dto.ClaudeMediaMessage{newSystem}, systemContents...)
+					dup := systemContents[0].Type == dto.ContentTypeText &&
+						systemContents[0].Text != nil &&
+						strings.TrimSpace(*systemContents[0].Text) == channel
+					if !dup {
+						request.System = append([]dto.ClaudeMediaMessage{newSystem}, systemContents...)
+					}
 				}
 			}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41be436 and ea084e7.

📒 Files selected for processing (1)
  • relay/claude_handler.go (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
relay/claude_handler.go (4)
common/gin.go (1)
  • SetContextKey (53-55)
constant/context_key.go (1)
  • ContextKeySystemPromptOverride (49-49)
dto/claude.go (1)
  • ClaudeMediaMessage (17-36)
dto/openai_request.go (1)
  • ContentTypeText (374-374)
🔇 Additional comments (2)
relay/claude_handler.go (2)

9-9: Import looks correct.

Package name matches usage (constant.ContextKeySystemPromptOverride). No action needed.


73-97: Pass‑through bypasses SystemPromptOverride — confirm intended behavior

Pass-through (global or channel PassThroughBodyEnabled) reads/forwards the original request body (relay/claude_handler.go:99-106; relay/responses_handler.go:44-47), so the earlier mutation that sets/appends SystemPrompt on the request struct (relay/claude_handler.go:73-97) will not be sent upstream. The ContextKeySystemPromptOverride is set (relay/claude_handler.go:77) but appears only used for logging (service/log_info_generate.go:32-35). Confirm intent: either apply the override to the raw request body when pass-through is enabled, or skip mutating/setting the override when pass-through is in effect.

@seefs001 seefs001 changed the title fix: claude system prompt overwrite fix: claude & gemini endpoint system prompt overwrite Sep 20, 2025
@seefs001
seefs001 merged commit 51ef19a into QuantumNous:main Sep 20, 2025
1 check was pending
@coderabbitai coderabbitai Bot mentioned this pull request Feb 14, 2026
x22x22 pushed a commit to x22x22/new-api that referenced this pull request Apr 24, 2026
…rompt-overwrite

fix: claude & gemini endpoint system prompt overwrite
jiutubaba pushed a commit to jiutubaba/fx-api that referenced this pull request May 17, 2026
…ghts

feat(monitor): channel monitor with available channels & feature flags
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants