feat: 支持渠道级透传选项,支持设置渠道系统提示词 - #1441
Conversation
WalkthroughSeveral handler functions and data structures were updated to support conditional pass-through of raw HTTP request bodies and the addition of channel-specific settings, such as system prompts and pass-through body toggles. UI components and localization files were extended to expose these new settings in the frontend, while error handling and parameter override logic were improved throughout the codebase. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Frontend
participant Backend
participant Handler
participant UpstreamAPI
User->>Frontend: Opens Edit Channel Modal
Frontend->>Frontend: Loads channel settings (parse JSON, populate controls)
User->>Frontend: Modifies settings (e.g., enable pass-through, set system prompt)
Frontend->>Frontend: Updates channelSettings state
User->>Frontend: Submits form
Frontend->>Backend: Sends updated channel config (JSON with new settings)
Backend->>Handler: Receives request
Handler->>Handler: Checks pass-through and system prompt settings
alt Pass-through enabled
Handler->>UpstreamAPI: Forwards raw request body
else
Handler->>Handler: Converts and marshals request
Handler->>Handler: Applies system prompt and parameter overrides
Handler->>UpstreamAPI: Sends processed request body
end
UpstreamAPI-->>Handler: Returns response
Handler-->>Backend: Forwards response
Backend-->>Frontend: Returns result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
dto/channel_settings.go(1 hunks)dto/openai_request.go(1 hunks)i18n/zh-cn.json(1 hunks)relay/claude_handler.go(1 hunks)relay/gemini_handler.go(2 hunks)relay/image_handler.go(2 hunks)relay/relay-text.go(2 hunks)relay/rerank_handler.go(2 hunks)types/error.go(3 hunks)web/src/components/table/channels/modals/EditChannelModal.jsx(7 hunks)web/src/i18n/locales/en.json(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
relay/image_handler.go (1)
Learnt from: 9Ninety
PR: #1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
relay/relay-text.go (1)
Learnt from: 9Ninety
PR: #1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
relay/rerank_handler.go (1)
Learnt from: 9Ninety
PR: #1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
relay/gemini_handler.go (1)
Learnt from: 9Ninety
PR: #1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
🪛 Checkov (3.2.334)
i18n/zh-cn.json
[MEDIUM] 596-597: Basic Auth Credentials
(CKV_SECRET_4)
web/src/i18n/locales/en.json
[MEDIUM] 1341-1342: Basic Auth Credentials
(CKV_SECRET_4)
🔇 Additional comments (14)
dto/channel_settings.go (1)
7-8: LGTM! Clean addition of new channel settings fields.The new
PassThroughBodyEnabledandSystemPromptfields are well-structured with appropriate JSON tags and follow the existing naming conventions. Theomitemptytags ensure backward compatibility.dto/openai_request.go (1)
76-83: LGTM! Well-implemented role name determination method.The
GetSystemRoleName()method correctly handles the role name logic for different OpenAI model variants. The exception handling for o1-mini and o1-preview models is appropriate, and the string prefix matching logic is sound.web/src/i18n/locales/en.json (1)
1333-1345: LGTM! Comprehensive translations for new channel settings.The new translation entries for channel extra settings are well-written and provide clear descriptions for users. The translations accurately convey the functionality of the new features including force formatting, pass-through body, proxy configuration, and system prompts.
The static analysis warning about basic auth credentials is a false positive - line 1342 contains an example proxy URL format, not actual credentials.
types/error.go (3)
31-31: LGTM: New error type constant added correctly.The new
ErrorTypeUpstreamErrorconstant follows the established naming convention and provides clear semantic meaning for upstream error classification.
198-200: LGTM: Appropriate default error type handling.Setting the error type to "upstream_error" when empty ensures consistent error classification and prevents undefined error types from upstream services.
211-213: LGTM: Consistent error type handling applied.The same default error type logic applied to Claude errors ensures uniform error classification behavior across all error types.
i18n/zh-cn.json (1)
588-601: LGTM: Comprehensive localization for new channel features.The Chinese translations are well-structured and provide clear descriptions for the new channel configuration options including system prompts, request body pass-through, and proxy settings. The example proxy format string ("socks5://user:pass@host:port") flagged by static analysis is appropriate documentation text, not actual credentials.
relay/relay-text.go (3)
173-173: LGTM: Channel-level pass-through configuration added.The additional condition properly allows channel-specific override of the global pass-through setting, providing the flexibility mentioned in the PR objectives.
185-203: LGTM: Well-implemented system prompt injection.The system prompt logic correctly:
- Only activates when configured
- Checks for existing system messages to avoid duplication
- Uses the request's own system role naming convention
- Prepends the system message to ensure proper ordering
- Respects user priority by not overriding existing system prompts
The implementation aligns with the "user priority" behavior described in the localization.
205-205: LGTM: Consistent use of common.Marshal.The change to use
common.Marshalinstead ofjson.Marshalappears to be part of standardizing serialization across the codebase, likely providing consistent error handling or custom serialization behavior.relay/rerank_handler.go (2)
6-6: LGTM: Necessary imports added.The
ioandmodel_settingimports are required for the new pass-through functionality and represent minimal, focused additions.Also applies to: 13-13
75-109: LGTM: Consistent pass-through implementation.The request body handling refactoring follows the same pattern as other relay handlers, providing:
- Proper conditional logic for pass-through (global OR channel setting)
- Appropriate error handling with correct HTTP status codes
- Parameter override support when not using pass-through
- Preserved debug logging functionality
The implementation maintains backward compatibility while adding the new channel-level configuration capability.
relay/claude_handler.go (1)
110-144: LGTM: Consistent Claude-specific pass-through implementation.The request body handling follows the established pattern from other relay handlers while properly using Claude-specific request conversion. The implementation maintains:
- Consistent conditional logic for pass-through
- Proper error handling with appropriate status codes
- Claude-specific request conversion when not using pass-through
- Parameter override support
- Debug logging functionality
The refactoring preserves all Claude-specific behavior while adding the new channel-level configuration capabilities.
relay/image_handler.go (1)
191-228: LGTM! Well-structured implementation of pass-through and parameter override features.The implementation correctly handles both pass-through mode and standard conversion mode with parameter overrides. The error handling is comprehensive with appropriate error codes.
| if common.DebugEnabled { | ||
| println("Gemini request body: %s", string(requestBody)) | ||
| if common.DebugEnabled { | ||
| println("Gemini request body: %s", string(jsonData)) |
There was a problem hiding this comment.
Fix incorrect println usage.
The println function doesn't support format strings. Use fmt.Printf or fmt.Println instead.
- println("Gemini request body: %s", string(jsonData))
+ fmt.Printf("Gemini request body: %s\n", string(jsonData))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| println("Gemini request body: %s", string(jsonData)) | |
| fmt.Printf("Gemini request body: %s\n", string(jsonData)) |
🤖 Prompt for AI Agents
In relay/gemini_handler.go at line 225, the code incorrectly uses println with a
format string, which println does not support. Replace println with fmt.Printf
to correctly handle the format string and print the Gemini request body as
intended.
| const parseChannelSettings = (settingJson) => { | ||
| try { | ||
| if (settingJson && settingJson.trim()) { | ||
| const parsed = JSON.parse(settingJson); | ||
| setChannelSettings({ | ||
| force_format: parsed.force_format || false, | ||
| thinking_to_content: parsed.thinking_to_content || false, | ||
| proxy: parsed.proxy || '', | ||
| pass_through_body_enabled: parsed.pass_through_body_enabled || false, | ||
| system_prompt: parsed.system_prompt || '', | ||
| }); | ||
| } else { | ||
| setChannelSettings({ | ||
| force_format: false, | ||
| thinking_to_content: false, | ||
| proxy: '', | ||
| pass_through_body_enabled: false, | ||
| system_prompt: '', | ||
| }); | ||
| } | ||
| } catch (error) { | ||
| console.error('解析渠道设置失败:', error); | ||
| setChannelSettings({ | ||
| force_format: false, | ||
| thinking_to_content: false, | ||
| proxy: '', | ||
| pass_through_body_enabled: false, | ||
| system_prompt: '', | ||
| }); | ||
| } | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Remove unused parseChannelSettings function.
This function is defined but never called. The same logic is implemented inline in the loadChannel function, making this dead code.
Consider removing this function entirely or refactoring to use it in loadChannel to avoid code duplication.
🤖 Prompt for AI Agents
In web/src/components/table/channels/modals/EditChannelModal.jsx between lines
182 and 212, the parseChannelSettings function is defined but never used,
duplicating logic already present in the loadChannel function. To fix this,
remove the parseChannelSettings function entirely to eliminate dead code, or
refactor loadChannel to call parseChannelSettings instead, consolidating the
parsing logic and avoiding duplication.
| // 解析渠道额外设置并合并到data中 | ||
| if (data.setting) { | ||
| try { | ||
| const parsedSettings = JSON.parse(data.setting); | ||
| data.force_format = parsedSettings.force_format || false; | ||
| data.thinking_to_content = parsedSettings.thinking_to_content || false; | ||
| data.proxy = parsedSettings.proxy || ''; | ||
| data.pass_through_body_enabled = parsedSettings.pass_through_body_enabled || false; | ||
| data.system_prompt = parsedSettings.system_prompt || ''; | ||
| } catch (error) { | ||
| console.error('解析渠道设置失败:', error); | ||
| data.force_format = false; | ||
| data.thinking_to_content = false; | ||
| data.proxy = ''; | ||
| data.pass_through_body_enabled = false; | ||
| } | ||
| } else { | ||
| data.force_format = false; | ||
| data.thinking_to_content = false; | ||
| data.proxy = ''; | ||
| data.pass_through_body_enabled = false; | ||
| data.system_prompt = ''; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve error handling in channel settings parsing.
The current implementation silently falls back to defaults when parsing fails. Consider preserving the original JSON string for debugging purposes or showing a warning to the user.
if (data.setting) {
try {
const parsedSettings = JSON.parse(data.setting);
data.force_format = parsedSettings.force_format || false;
data.thinking_to_content = parsedSettings.thinking_to_content || false;
data.proxy = parsedSettings.proxy || '';
data.pass_through_body_enabled = parsedSettings.pass_through_body_enabled || false;
data.system_prompt = parsedSettings.system_prompt || '';
} catch (error) {
console.error('解析渠道设置失败:', error);
+ showError(t('渠道设置格式错误,将使用默认值'));
data.force_format = false;
data.thinking_to_content = false;
data.proxy = '';
data.pass_through_body_enabled = false;
+ data.system_prompt = '';
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 解析渠道额外设置并合并到data中 | |
| if (data.setting) { | |
| try { | |
| const parsedSettings = JSON.parse(data.setting); | |
| data.force_format = parsedSettings.force_format || false; | |
| data.thinking_to_content = parsedSettings.thinking_to_content || false; | |
| data.proxy = parsedSettings.proxy || ''; | |
| data.pass_through_body_enabled = parsedSettings.pass_through_body_enabled || false; | |
| data.system_prompt = parsedSettings.system_prompt || ''; | |
| } catch (error) { | |
| console.error('解析渠道设置失败:', error); | |
| data.force_format = false; | |
| data.thinking_to_content = false; | |
| data.proxy = ''; | |
| data.pass_through_body_enabled = false; | |
| } | |
| } else { | |
| data.force_format = false; | |
| data.thinking_to_content = false; | |
| data.proxy = ''; | |
| data.pass_through_body_enabled = false; | |
| data.system_prompt = ''; | |
| } | |
| // 解析渠道额外设置并合并到data中 | |
| if (data.setting) { | |
| try { | |
| const parsedSettings = JSON.parse(data.setting); | |
| data.force_format = parsedSettings.force_format || false; | |
| data.thinking_to_content = parsedSettings.thinking_to_content || false; | |
| data.proxy = parsedSettings.proxy || ''; | |
| data.pass_through_body_enabled = parsedSettings.pass_through_body_enabled || false; | |
| data.system_prompt = parsedSettings.system_prompt || ''; | |
| } catch (error) { | |
| console.error('解析渠道设置失败:', error); | |
| showError(t('渠道设置格式错误,将使用默认值')); | |
| data.force_format = false; | |
| data.thinking_to_content = false; | |
| data.proxy = ''; | |
| data.pass_through_body_enabled = false; | |
| data.system_prompt = ''; | |
| } | |
| } else { | |
| data.force_format = false; | |
| data.thinking_to_content = false; | |
| data.proxy = ''; | |
| data.pass_through_body_enabled = false; | |
| data.system_prompt = ''; | |
| } |
🤖 Prompt for AI Agents
In web/src/components/table/channels/modals/EditChannelModal.jsx around lines
326 to 348, the error handling for JSON parsing of channel settings only logs
the error and falls back to defaults silently. Improve this by preserving the
original JSON string in a separate variable for debugging and optionally display
a user warning or notification about the parsing failure. This will help in
diagnosing issues without losing the original data.
…and relay components
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
relay/channel/gemini/relay-gemini.go (1)
222-229: Consider logging unmarshaling errors for better debugging.The logic correctly handles the type change from pointer to
json.RawMessage. However, unmarshaling errors are silently ignored, which could make debugging difficult when malformed JSON schemas are provided.Consider adding error logging when unmarshaling fails:
if len(textRequest.ResponseFormat.JsonSchema) > 0 { // 先将json.RawMessage解析 var jsonSchema dto.FormatJsonSchema - if err := common.Unmarshal(textRequest.ResponseFormat.JsonSchema, &jsonSchema); err == nil { + if err := common.Unmarshal(textRequest.ResponseFormat.JsonSchema, &jsonSchema); err == nil { cleanedSchema := removeAdditionalPropertiesWithDepth(jsonSchema.Schema, 0) geminiRequest.GenerationConfig.ResponseSchema = cleanedSchema + } else { + common.LogWarn(c, "Failed to unmarshal JSON schema: "+err.Error()) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
dto/openai_request.go(2 hunks)middleware/distributor.go(1 hunks)relay/channel/gemini/relay-gemini.go(1 hunks)relay/relay-text.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- relay/relay-text.go
- dto/openai_request.go
🧰 Additional context used
🧠 Learnings (1)
relay/channel/gemini/relay-gemini.go (1)
Learnt from: 9Ninety
PR: #1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
🧬 Code Graph Analysis (1)
relay/channel/gemini/relay-gemini.go (2)
dto/openai_request.go (2)
ResponseFormat(9-12)FormatJsonSchema(14-19)common/json.go (1)
Unmarshal(8-10)
🔇 Additional comments (2)
middleware/distributor.go (2)
114-114: LGTM: Improved error message for better diagnostics.The updated error message explicitly indicates a database consistency issue and includes the component name "distributor" for easier debugging and troubleshooting.
124-124: LGTM: Simplified error message aligns with removed consistency check.The error message simplification is consistent with the commented out database consistency check logic above. The message remains informative for debugging while being more user-friendly.
| //if channel != nil { | ||
| // common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) | ||
| // message = "数据库一致性已被破坏,请联系管理员" | ||
| //} |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify impact of removing database consistency check logic.
The commented out code was responsible for:
- Detecting database consistency issues (error + non-nil channel)
- Logging system errors for administrator attention
- Providing user-friendly error messages
Removing this logic could result in:
- Undetected database consistency problems
- Missing system error logs
- Technical error messages exposed to users
Please confirm this logic is handled elsewhere or provide justification for its removal.
🏁 Script executed:
#!/bin/bash
# Search for alternative database consistency checks in the codebase
echo "Searching for database consistency checks..."
rg -A 3 -B 3 "数据库一致性|database consistency|consistency.*broken" --type go
echo -e "\nSearching for system error logging patterns..."
rg -A 2 "common\.SysError|SysError" --type go
echo -e "\nSearching for channel nil checks in error scenarios..."
ast-grep --pattern 'if $_ != nil {
$$$
if channel != nil {
$$$
}
$$$
}'Length of output: 28269
Restore database consistency handling in distributor middleware
The commented-out block in middleware/distributor.go (lines 116–119) removed both the system error log and the generic user-friendly message without any replacement:
- Loss of
common.SysErrorcall means DB consistency breaches won’t be logged for admins - Overwriting the message to a generic “数据库一致性已被破坏,请联系管理员” was removed, so users now always see technical
err.Error()details - No other code in this middleware logs or handles the
channel != nil && err != nilscenario
Please re-introduce explicit consistency detection and logging, for example:
- // 如果错误,但是渠道不为空,说明是数据库一致性问题
- //if channel != nil {
- // common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id))
- // message = "数据库一致性已被破坏,请联系管理员"
- //}
+ // 如果错误,但是渠道不为空,说明是数据库一致性问题
+ if channel != nil {
+ common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id))
+ message = "数据库一致性已被破坏,请联系管理员"
+ }By restoring this block, you’ll ensure:
- Consistency breaches are logged to the error stream
- Users receive a clear, non-technical message when the data layer is corrupt
- Technical error details aren’t exposed to end users
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| //if channel != nil { | |
| // common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) | |
| // message = "数据库一致性已被破坏,请联系管理员" | |
| //} | |
| // 如果错误,但是渠道不为空,说明是数据库一致性问题 | |
| if channel != nil { | |
| common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) | |
| message = "数据库一致性已被破坏,请联系管理员" | |
| } |
🤖 Prompt for AI Agents
In middleware/distributor.go around lines 116 to 119, the commented-out code
that logs a system error and sets a generic user-friendly message when database
consistency is broken should be restored. Re-enable the common.SysError call to
log the inconsistency for administrators and set the message variable to a
clear, non-technical string like "数据库一致性已被破坏,请联系管理员" to prevent exposing
technical error details to users. This will ensure proper logging and user
communication in case of data consistency issues.
feat: 支持渠道级透传选项,支持设置渠道系统提示词
close #1102
close #646
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Bug Fixes
Localization