Skip to content

feat: glm coding plan && kimi coding plan - #2334

Merged
Calcium-Ion merged 3 commits into
QuantumNous:mainfrom
seefs001:feature/glm-coding
Nov 30, 2025
Merged

feat: glm coding plan && kimi coding plan#2334
Calcium-Ion merged 3 commits into
QuantumNous:mainfrom
seefs001:feature/glm-coding

Conversation

@seefs001

@seefs001 seefs001 commented Nov 29, 2025

Copy link
Copy Markdown
Collaborator

glm API地址写glm-coding-plan,支持OpenAI格式和Claude格式
国际版写 glm-coding-plan-international

kimi API地址写 kimi-coding-plan

Summary by CodeRabbit

  • New Features

    • Added glm-4.6 model support for Zhipu v4.
  • Refactor

    • Improved upstream URL selection to support per-plan custom Claude and OpenAI-compatible base URLs, including new handling for additional channel types (Zhipu v4, VolcEngine, Moonshot). This enables better routing to specialized deployments while preserving existing behavior for standard plans.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Nov 29, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Upstream URL construction and request routing were changed to consult a new ChannelSpecialBases map for channel-specific Claude/OpenAI base URLs; adaptors (VolcEngine, Zhipu v4, Moonshot) and controller FetchUpstreamModels now use these special bases when present, falling back to existing paths otherwise.

Changes

Cohort / File(s) Summary
Configuration & Constants
constant/channel.go
Added ChannelSpecialBase type and ChannelSpecialBases map storing per-plan ClaudeBaseURL and OpenAIBaseURL.
Upstream Model Fetching
controller/channel.go
FetchUpstreamModels now checks ChannelSpecialBases and selects OpenAI/Claude model endpoints conditionally for Zhipu_v4, VolcEngine, and Moonshot; removed an unused volcengine import.
VolcEngine Adaptor
relay/channel/volcengine/adaptor.go
Removed hardcoded Doubao constants; refactored ConvertClaudeRequest, GetRequestURL, and DoResponse to lookup ChannelSpecialBases and route to Claude/OpenAI endpoints or handlers when a special base exists.
Zhipu v4 Adaptor
relay/channel/zhipu_4v/adaptor.go
Unified baseURL resolution from channel info, consults ChannelSpecialBases, and conditionally constructs URLs for Claude, Embeddings, and Chat Completions branches using special OpenAI/Claude bases when present.
Moonshot Adaptor
relay/channel/moonshot/adaptor.go
Added ChannelSpecialBases lookup to override default Claude/OpenAI URL construction to use special ClaudeBaseURL/OpenAIBaseURL when available.
Zhipu v4 Model List
relay/channel/zhipu_4v/constants.go
Appended "glm-4.6" to the public ModelList.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Pay special attention to URL fallback logic when no special base is found.
  • Verify removal of Doubao constants doesn't leave dangling references.
  • Check consistency of Claude vs OpenAI endpoint selection across adaptors and controller.

Possibly related PRs

Suggested reviewers

  • Calcium-Ion

Poem

🐰 I hopped through configs, map in paw,
Swapping constants for a flexible law,
Claude and OpenAI now find their way,
Special bases guide them day by day —
🥕 URLs neat, I munch and play.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive The title 'feat: glm coding plan && kimi coding plan' is overly broad and generic, using vague terminology without specifying the actual implementation details of the changes. Consider a more descriptive title that explains the key change, such as 'feat: support special base URLs for Zhipu GLM and Kimi plans' or similar, to clearly convey what was modified.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • 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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa72a27 and 2359bf3.

📒 Files selected for processing (5)
  • controller/channel.go (2 hunks)
  • relay/channel/volcengine/adaptor.go (1 hunks)
  • relay/channel/volcengine/constants.go (1 hunks)
  • relay/channel/zhipu_4v/adaptor.go (2 hunks)
  • relay/channel/zhipu_4v/constants.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
controller/channel.go (1)
relay/channel/zhipu_4v/constants.go (2)
  • GlmCodingPlan (4-4)
  • GlmCodingPlanOpenAIBaseURL (6-6)
relay/channel/zhipu_4v/adaptor.go (4)
constant/channel.go (2)
  • ChannelBaseURLs (61-119)
  • ChannelTypeZhipu_v4 (30-30)
types/relay_format.go (2)
  • RelayFormat (3-3)
  • RelayFormatClaude (7-7)
relay/channel/zhipu_4v/constants.go (3)
  • GlmCodingPlan (4-4)
  • GlmCodingPlanClaudeBaseURL (5-5)
  • GlmCodingPlanOpenAIBaseURL (6-6)
relay/constant/relay_mode.go (1)
  • RelayModeEmbeddings (12-12)
🔇 Additional comments (6)
relay/channel/volcengine/adaptor.go (1)

26-29: LGTM! Constants properly refactored.

The Doubao coding plan constants have been correctly moved to constants.go in the same package. This improves code organization by centralizing constant definitions. The constants remain accessible throughout the package, and their usage in this file (lines 40, 246, 256, 345) continues to work correctly.

relay/channel/zhipu_4v/adaptor.go (1)

47-50: Good practice: Default baseURL resolution.

Adding default baseURL resolution when info.ChannelBaseUrl is empty is a good defensive coding practice. This prevents potential nil pointer or empty string issues downstream.

relay/channel/zhipu_4v/constants.go (2)

10-10: I'll help you verify the model identifier for "glm-4.6" in the Zhipu API. Let me start by examining the file and then searching for official documentation.
<function_calls>

cat relay/channel/zhipu_4v/constants.go

</function_calls>
<function_calls>

Zhipu GLM 4.6 model identifier API documentation

</function_calls>


3-7: Due to repository access issues, I cannot fully verify all concerns in the original review. However, the web search provided helpful information about the GLM Coding Plan API.

From official Zhipu documentation:

  • The OpenAI-compatible endpoint https://open.bigmodel.cn/api/coding/paas/v4 is confirmed correct
  • The recommended model for Coding Plan is GLM-4.6 (note: may have capitalization differences from code)
  • The Anthropic-compatible endpoint (https://open.bigmodel.cn/api/anthropic) is not mentioned in official documentation—this requires verification

Unable to verify without codebase access:

  • How the sentinel value GlmCodingPlan = "glm-coding-plan" is actually used in routing logic
  • Whether the design pattern creates the security/UX concerns mentioned
  • Whether model name capitalization matches (glm-4.6 vs GLM-4.6)

Verify the Anthropic-compatible endpoint and sentinel value usage pattern.

One of the two endpoints is confirmed (OpenAI v4), but https://open.bigmodel.cn/api/anthropic is not mentioned in official GLM documentation and needs verification. Additionally, the sentinel value pattern design concern cannot be assessed without reviewing the routing implementation.

controller/channel.go (1)

196-200: Sentinel pattern implementation in URL construction.

This conditional logic relies on the sentinel value pattern where baseURL == zhipu_4v.GlmCodingPlan triggers different URL construction. While functional, this approach has several concerns:

  1. Fragile design: If a user configures their channel with baseURL = "glm-coding-plan" (perhaps misunderstanding the configuration), they'll get unexpected routing.
  2. No validation: There's no check to prevent users from accidentally setting this sentinel value.
  3. Code duplication: Similar pattern repeated for VolcEngine (lines 202-206).

Consider refactoring to use a helper function:

// Helper function to get models URL for a channel
func getModelsURL(channel *model.Channel, baseURL string) string {
	switch channel.Type {
	case constant.ChannelTypeZhipu_v4:
		if baseURL == zhipu_4v.GlmCodingPlan {
			return fmt.Sprintf("%s/models", zhipu_4v.GlmCodingPlanOpenAIBaseURL)
		}
		return fmt.Sprintf("%s/api/paas/v4/models", baseURL)
	case constant.ChannelTypeVolcEngine:
		if baseURL == volcengine.DoubaoCodingPlan {
			return fmt.Sprintf("%s/v1/models", volcengine.DoubaoCodingPlanOpenAIBaseURL)
		}
		return fmt.Sprintf("%s/v1/models", baseURL)
	case constant.ChannelTypeGemini:
		return fmt.Sprintf("%s/v1beta/openai/models", baseURL)
	case constant.ChannelTypeAli:
		return fmt.Sprintf("%s/compatible-mode/v1/models", baseURL)
	default:
		return fmt.Sprintf("%s/v1/models", baseURL)
	}
}

Then use it in the switch statement:

-	var url string
-	switch channel.Type {
-	case constant.ChannelTypeGemini:
-		// curl https://example.com/v1beta/models?key=$GEMINI_API_KEY
-		url = fmt.Sprintf("%s/v1beta/openai/models", baseURL) // Remove key in url since we need to use AuthHeader
-	case constant.ChannelTypeAli:
-		url = fmt.Sprintf("%s/compatible-mode/v1/models", baseURL)
-	case constant.ChannelTypeZhipu_v4:
-		if baseURL == zhipu_4v.GlmCodingPlan {
-			url = fmt.Sprintf("%s/models", zhipu_4v.GlmCodingPlanOpenAIBaseURL)
-		} else {
-			url = fmt.Sprintf("%s/api/paas/v4/models", baseURL)
-		}
-	case constant.ChannelTypeVolcEngine:
-		if baseURL == volcengine.DoubaoCodingPlan {
-			url = fmt.Sprintf("%s/v1/models", volcengine.DoubaoCodingPlanOpenAIBaseURL)
-		} else {
-			url = fmt.Sprintf("%s/v1/models", baseURL)
-		}
-	default:
-		url = fmt.Sprintf("%s/v1/models", baseURL)
-	}
+	url := getModelsURL(channel, baseURL)
⛔ Skipped due to learnings
Learnt from: Sh1n3zZ
Repo: QuantumNous/new-api PR: 1659
File: relay/relay_task.go:285-305
Timestamp: 2025-08-26T09:59:00.337Z
Learning: In controller/task_video.go, data: URLs (containing base64 encoded video data) are prevented from being stored in task.FailReason by checking if the URL starts with "data:" before assignment. This same pattern should be applied consistently across the codebase.
relay/channel/volcengine/constants.go (1)

3-7: URLs verified as official Volcengine endpoints; architectural concern requires code review for assessment.

The endpoints referenced in the constants are confirmed in official Volcengine documentation:

  • https://ark.cn-beijing.volces.com/api/coding — Primary Coding Plan endpoint
  • https://ark.cn-beijing.volces.com/api/coding/v3 — OpenAI-compatible variant (official for integration tools)
  • Model: doubao-seed-code-preview-latest

However, I cannot verify the core architectural concern (sentinel pattern confusion with baseURL assignment) or the comparison to the Zhipu implementation without access to the actual code usage patterns. This requires manual code review to assess whether:

  1. The sentinel pattern (DoubaoCodingPlan = "doubao-coding-plan") is actually mixed with baseURL logic
  2. The comparison to Zhipu's approach is accurate
  3. Defensive measures exist to prevent accidental baseURL assignment

Comment thread relay/channel/zhipu_4v/adaptor.go

@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 (1)
relay/channel/volcengine/adaptor.go (1)

345-353: Minor inconsistency in special plan validation logic.

In GetRequestURL (line 247), the code checks both hasSpecialPlan && specialPlan.ClaudeBaseURL != "" before using Claude routing. However, in DoResponse (line 347), the code only checks map existence without verifying that ClaudeBaseURL is non-empty.

While all current entries in ChannelSpecialBases have non-empty ClaudeBaseURL values, this could cause issues if a future entry has an empty ClaudeBaseURL. Consider aligning the checks:

 	if info.RelayFormat == types.RelayFormatClaude {
-		if _, ok := channelconstant.ChannelSpecialBases[info.ChannelBaseUrl]; ok {
+		if specialPlan, ok := channelconstant.ChannelSpecialBases[info.ChannelBaseUrl]; ok && specialPlan.ClaudeBaseURL != "" {
 			if info.IsStream {
 				return claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage)
 			}
 			return claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage)
 		}
 	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2359bf3 and 704cc11.

📒 Files selected for processing (5)
  • constant/channel.go (1 hunks)
  • controller/channel.go (1 hunks)
  • relay/channel/volcengine/adaptor.go (5 hunks)
  • relay/channel/zhipu_4v/adaptor.go (2 hunks)
  • relay/channel/zhipu_4v/constants.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • controller/channel.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-26T09:59:00.337Z
Learnt from: Sh1n3zZ
Repo: QuantumNous/new-api PR: 1659
File: relay/relay_task.go:285-305
Timestamp: 2025-08-26T09:59:00.337Z
Learning: In controller/task_video.go, data: URLs (containing base64 encoded video data) are prevented from being stored in task.FailReason by checking if the URL starts with "data:" before assignment. This same pattern should be applied consistently across the codebase.

Applied to files:

  • relay/channel/zhipu_4v/adaptor.go
🧬 Code graph analysis (2)
relay/channel/zhipu_4v/adaptor.go (3)
constant/channel.go (3)
  • ChannelBaseURLs (61-119)
  • ChannelTypeZhipu_v4 (30-30)
  • ChannelSpecialBases (189-202)
types/relay_format.go (2)
  • RelayFormat (3-3)
  • RelayFormatClaude (7-7)
relay/constant/relay_mode.go (1)
  • RelayModeEmbeddings (12-12)
relay/channel/volcengine/adaptor.go (1)
constant/channel.go (1)
  • ChannelSpecialBases (189-202)
🔇 Additional comments (5)
constant/channel.go (1)

183-202: Clean centralized configuration for special base URLs.

The ChannelSpecialBase struct and ChannelSpecialBases map provide a well-organized way to configure channel-specific base URLs. This approach is more maintainable than hardcoded constants scattered across adaptors.

relay/channel/zhipu_4v/constants.go (1)

3-5: LGTM!

The addition of "glm-4.6" to the model list is straightforward and follows the existing naming convention.

relay/channel/zhipu_4v/adaptor.go (1)

46-73: Good refactoring using centralized configuration.

The GetRequestURL logic now cleanly uses the ChannelSpecialBases map lookup instead of repeated sentinel pattern checks. This addresses the duplication concern from previous reviews and makes the routing logic more maintainable.

relay/channel/volcengine/adaptor.go (2)

39-46: LGTM!

The ConvertClaudeRequest method cleanly delegates to the appropriate adaptor based on whether the channel has a special base configuration.


264-265: Inconsistent special plan handling for embeddings between adaptors.

The zhipu_4v adaptor (lines 62-65) checks hasSpecialPlan && specialPlan.OpenAIBaseURL for embeddings and routes to specialPlan.OpenAIBaseURL/embeddings. However, this adaptor does not apply the same special plan logic for RelayModeEmbeddings.

If this is intentional (e.g., doubao-coding-plan doesn't support embeddings via the special URL), consider adding a comment to clarify. Otherwise, consider adding consistent handling:

 		case constant.RelayModeEmbeddings:
+			if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+				return fmt.Sprintf("%s/embeddings", specialPlan.OpenAIBaseURL), nil
+			}
 			return fmt.Sprintf("%s/api/v3/embeddings", baseUrl), nil

@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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 704cc11 and fac1675.

📒 Files selected for processing (3)
  • constant/channel.go (1 hunks)
  • controller/channel.go (1 hunks)
  • relay/channel/moonshot/adaptor.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • controller/channel.go
🧰 Additional context used
🧬 Code graph analysis (1)
relay/channel/moonshot/adaptor.go (2)
constant/channel.go (1)
  • ChannelSpecialBases (189-206)
types/relay_format.go (3)
  • RelayFormat (3-3)
  • RelayFormatClaude (7-7)
  • RelayFormatOpenAI (6-6)
🔇 Additional comments (2)
relay/channel/moonshot/adaptor.go (2)

9-9: LGTM!

The import alias is appropriate to avoid conflicts with the existing constant import.


48-56: Verify that special base URL path construction is correct.

The path construction for special bases differs from the default paths:

  • Special base OpenAI: /chat/completions (line 54)
  • Default OpenAI: /v1/chat/completions (line 67)
  • Special base Claude: /v1/messages (line 51)
  • Default Claude: /anthropic/v1/messages (line 60)

Confirm whether these differences are intentional. If the special base URLs (from ChannelSpecialBases) already include version or service prefixes (e.g., https://api.kimi.com/coding/v1 or similar), then the shorter paths are correct. Otherwise, the paths may be missing required segments.

Comment thread constant/channel.go
Comment on lines +184 to +187
type ChannelSpecialBase struct {
ClaudeBaseURL string
OpenAIBaseURL string
}

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.

🛠️ Refactor suggestion | 🟠 Major

Add documentation for the public struct.

This public struct should have a godoc comment explaining its purpose, such as how it's used to define alternative base URLs for special channel plans.

+// ChannelSpecialBase defines alternative base URLs for special channel plans
+// that support both Claude and OpenAI formats with different endpoints.
 type ChannelSpecialBase struct {
 	ClaudeBaseURL string
 	OpenAIBaseURL string
 }
📝 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.

Suggested change
type ChannelSpecialBase struct {
ClaudeBaseURL string
OpenAIBaseURL string
}
// ChannelSpecialBase defines alternative base URLs for special channel plans
// that support both Claude and OpenAI formats with different endpoints.
type ChannelSpecialBase struct {
ClaudeBaseURL string
OpenAIBaseURL string
}
🤖 Prompt for AI Agents
In constant/channel.go around lines 184 to 187, the public struct
ChannelSpecialBase lacks a godoc comment; add a one-line godoc comment
immediately above the type declaration that explains its purpose (e.g., that it
defines alternative base URLs for special channel plans and is used to override
default Claude/OpenAI endpoints), keeping the comment concise and starting with
"ChannelSpecialBase" to satisfy Go documentation conventions.

Comment thread constant/channel.go
Comment on lines +189 to +206
var ChannelSpecialBases = map[string]ChannelSpecialBase{
"glm-coding-plan": {
ClaudeBaseURL: "https://open.bigmodel.cn/api/anthropic",
OpenAIBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
},
"glm-coding-plan-international": {
ClaudeBaseURL: "https://api.z.ai/api/anthropic",
OpenAIBaseURL: "https://api.z.ai/api/coding/paas/v4",
},
"kimi-coding-plan": {
ClaudeBaseURL: "https://api.kimi.com/coding",
OpenAIBaseURL: "https://api.kimi.com/coding/v1",
},
"doubao-coding-plan": {
ClaudeBaseURL: "https://ark.cn-beijing.volces.com/api/coding",
OpenAIBaseURL: "https://ark.cn-beijing.volces.com/api/coding/v3",
},
}

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.

🛠️ Refactor suggestion | 🟠 Major

Add documentation for the public map.

This public map should have a godoc comment explaining that it maps special plan identifiers to their corresponding base URLs for different API formats.

+// ChannelSpecialBases maps special plan identifiers (e.g., "glm-coding-plan") to their
+// corresponding Claude and OpenAI base URLs. When a channel's base URL matches a key in
+// this map, the special URLs are used instead of the default channel base URL.
 var ChannelSpecialBases = map[string]ChannelSpecialBase{
 	"glm-coding-plan": {
 		ClaudeBaseURL: "https://open.bigmodel.cn/api/anthropic",
📝 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.

Suggested change
var ChannelSpecialBases = map[string]ChannelSpecialBase{
"glm-coding-plan": {
ClaudeBaseURL: "https://open.bigmodel.cn/api/anthropic",
OpenAIBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
},
"glm-coding-plan-international": {
ClaudeBaseURL: "https://api.z.ai/api/anthropic",
OpenAIBaseURL: "https://api.z.ai/api/coding/paas/v4",
},
"kimi-coding-plan": {
ClaudeBaseURL: "https://api.kimi.com/coding",
OpenAIBaseURL: "https://api.kimi.com/coding/v1",
},
"doubao-coding-plan": {
ClaudeBaseURL: "https://ark.cn-beijing.volces.com/api/coding",
OpenAIBaseURL: "https://ark.cn-beijing.volces.com/api/coding/v3",
},
}
// ChannelSpecialBases maps special plan identifiers (e.g., "glm-coding-plan") to their
// corresponding Claude and OpenAI base URLs. When a channel's base URL matches a key in
// this map, the special URLs are used instead of the default channel base URL.
var ChannelSpecialBases = map[string]ChannelSpecialBase{
"glm-coding-plan": {
ClaudeBaseURL: "https://open.bigmodel.cn/api/anthropic",
OpenAIBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
},
"glm-coding-plan-international": {
ClaudeBaseURL: "https://api.z.ai/api/anthropic",
OpenAIBaseURL: "https://api.z.ai/api/coding/paas/v4",
},
"kimi-coding-plan": {
ClaudeBaseURL: "https://api.kimi.com/coding",
OpenAIBaseURL: "https://api.kimi.com/coding/v1",
},
"doubao-coding-plan": {
ClaudeBaseURL: "https://ark.cn-beijing.volces.com/api/coding",
OpenAIBaseURL: "https://ark.cn-beijing.volces.com/api/coding/v3",
},
}
🤖 Prompt for AI Agents
In constant/channel.go around lines 189 to 206, add a Go doc comment for the
exported ChannelSpecialBases map that briefly explains its purpose: that it maps
special plan identifiers (string keys) to ChannelSpecialBase entries containing
the ClaudeBaseURL and OpenAIBaseURL for those plans, and that these base URLs
are used to override default API endpoints for specific plan identifiers; place
the comment immediately above the ChannelSpecialBases declaration, keep it
concise (one to two sentences), and mention the structure of values
(ChannelSpecialBase with ClaudeBaseURL and OpenAIBaseURL) so godoc consumers
understand the mapping.

Comment on lines +48 to +56
baseURL := info.ChannelBaseUrl
if specialPlan, ok := channelconstant.ChannelSpecialBases[baseURL]; ok {
if info.RelayFormat == types.RelayFormatClaude {
return fmt.Sprintf("%s/v1/messages", specialPlan.ClaudeBaseURL), nil
}
if info.RelayFormat == types.RelayFormatOpenAI {
return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil
}
}

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.

⚠️ Potential issue | 🔴 Critical

Critical: Handle unsupported relay formats when special base is matched.

When a special base is found but RelayFormat is neither Claude nor OpenAI, the code falls through to the switch statement at line 58. At that point, info.ChannelBaseUrl contains a plan identifier (e.g., "glm-coding-plan") rather than a valid URL, which would result in malformed URLs like "glm-coding-plan/v1/chat/completions".

Apply this diff to handle the case properly:

 	baseURL := info.ChannelBaseUrl
 	if specialPlan, ok := channelconstant.ChannelSpecialBases[baseURL]; ok {
 		if info.RelayFormat == types.RelayFormatClaude {
 			return fmt.Sprintf("%s/v1/messages", specialPlan.ClaudeBaseURL), nil
 		}
 		if info.RelayFormat == types.RelayFormatOpenAI {
 			return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil
 		}
+		// Special base found but format not supported
+		return "", fmt.Errorf("relay format %s not supported for special base %s", info.RelayFormat, baseURL)
 	}
📝 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.

Suggested change
baseURL := info.ChannelBaseUrl
if specialPlan, ok := channelconstant.ChannelSpecialBases[baseURL]; ok {
if info.RelayFormat == types.RelayFormatClaude {
return fmt.Sprintf("%s/v1/messages", specialPlan.ClaudeBaseURL), nil
}
if info.RelayFormat == types.RelayFormatOpenAI {
return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil
}
}
baseURL := info.ChannelBaseUrl
if specialPlan, ok := channelconstant.ChannelSpecialBases[baseURL]; ok {
if info.RelayFormat == types.RelayFormatClaude {
return fmt.Sprintf("%s/v1/messages", specialPlan.ClaudeBaseURL), nil
}
if info.RelayFormat == types.RelayFormatOpenAI {
return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil
}
// Special base found but format not supported
return "", fmt.Errorf("relay format %s not supported for special base %s", info.RelayFormat, baseURL)
}
🤖 Prompt for AI Agents
In relay/channel/moonshot/adaptor.go around lines 48 to 56, when
channelconstant.ChannelSpecialBases matches but info.RelayFormat is neither
RelayFormatClaude nor RelayFormatOpenAI the function currently falls through
leaving baseURL as a plan id and producing malformed URLs; detect this
unsupported format immediately and return a clear error instead of falling
through (e.g., return nil URL with fmt.Errorf("unsupported relay format %q for
special base %q", info.RelayFormat, baseURL)) so the caller can handle the
invalid combination.

@seefs001 seefs001 changed the title feat: glm coding plan feat: glm coding plan && kimi coding plan Nov 30, 2025
@Calcium-Ion
Calcium-Ion merged commit 451c594 into QuantumNous:main Nov 30, 2025
1 check passed
sususu98 pushed a commit to sususu98/new-api that referenced this pull request Dec 1, 2025
ennnnny pushed a commit to ennnnny/new-api that referenced this pull request Mar 17, 2026
feat: glm coding plan && kimi coding plan
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