Skip to content

添加邀请返利开关;为所有模型路由添加claude-前缀 - #6408

Open
Coder-Wjt wants to merge 5 commits into
QuantumNous:mainfrom
Coder-Wjt:main
Open

添加邀请返利开关;为所有模型路由添加claude-前缀#6408
Coder-Wjt wants to merge 5 commits into
QuantumNous:mainfrom
Coder-Wjt:main

Conversation

@Coder-Wjt

@Coder-Wjt Coder-Wjt commented Jul 23, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 添加邀请返利开关
  • 为所有模型路由添加claude-前缀

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
1.不开放邀请的时候,用户登录不会显示邀请返利链接板块;
2.添加claude-前缀可以让claude code desktop客户端识别到密钥可访问的所有模型

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • [✅] ✨ 新功能 (New feature) -添加邀请返利开关;为所有模型路由添加claude-前缀
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • [✅] 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • [✅] 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • [✅] 变更理解: 我已理解这些更改的工作原理及可能影响。
  • [✅] 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • [✅] 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • [✅] 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
image

image 547d60e5acf762379c2d8fefc4502408

Summary by CodeRabbit

  • New Features
    • Added an Invitation/Affiliate Rewards setting for administrators, enabled by default and persisted in system configuration.
    • API status and wallet information now report feature availability.
    • Wallet displays the affiliate rewards card only when enabled.
    • Added localized setting labels and descriptions.
  • Bug Fixes
    • Improved Anthropic model ID handling and routing for prefixed and unprefixed names.
  • Tests
    • Added coverage for configuration updates, API status fields, and wallet visibility.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b7d461ec-b1e5-4cf8-8b23-202156438f91

📥 Commits

Reviewing files that changed from the base of the PR and between 4d9a8cb and e66c0e9.

📒 Files selected for processing (15)
  • controller/misc.go
  • controller/model.go
  • middleware/distributor.go
  • model/option.go
  • web/src/features/auth/types.ts
  • web/src/features/system-settings/billing/index.tsx
  • web/src/features/system-settings/billing/section-registry.tsx
  • web/src/features/system-settings/types.ts
  • web/src/i18n/locales/en.json
  • web/src/i18n/locales/fr.json
  • web/src/i18n/locales/ja.json
  • web/src/i18n/locales/ru.json
  • web/src/i18n/locales/vi.json
  • web/src/i18n/locales/zh-TW.json
  • web/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (15)
  • web/src/features/system-settings/billing/section-registry.tsx
  • controller/misc.go
  • web/src/features/system-settings/billing/index.tsx
  • web/src/features/system-settings/types.ts
  • web/src/i18n/locales/ja.json
  • web/src/i18n/locales/fr.json
  • model/option.go
  • web/src/i18n/locales/en.json
  • web/src/i18n/locales/vi.json
  • web/src/i18n/locales/zh.json
  • middleware/distributor.go
  • web/src/i18n/locales/ru.json
  • controller/model.go
  • web/src/features/auth/types.ts
  • web/src/i18n/locales/zh-TW.json

Walkthrough

The PR adds an AffiliateRewardsEnabled configuration flag, exposes it through backend APIs, adds frontend settings and translations, gates wallet affiliate features, and normalizes Anthropic model identifiers across model APIs and message routing.

Changes

Affiliate rewards and Anthropic model handling

Layer / File(s) Summary
Affiliate rewards configuration and API exposure
common/constants.go, model/option.go, controller/misc.go, controller/topup.go, controller/status_affiliate_rewards_test.go, model/option_affiliate_rewards_test.go
The flag is initialized, persisted, updated, and exposed through status and top-up responses. Backend tests cover the new behavior.
Anthropic model identifier normalization
controller/model.go, middleware/distributor.go, model/ability.go
Anthropic model listing, retrieval, and message routing normalize prefixed and unprefixed identifiers.
Frontend status contracts and settings form
web/src/features/auth/types.ts, web/src/hooks/use-system-config.ts, web/src/stores/system-config-store.ts, web/src/features/system-settings/..., web/src/i18n/locales/*
Frontend types, persisted configuration, billing settings, form validation, controls, defaults, and translations represent the affiliate rewards option.
Wallet affiliate rewards gating
web/src/features/wallet/...
The wallet uses top-up data to control affiliate data fetching and rewards-card rendering. Tests cover explicit enablement.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Wallet
  participant TopupAPI
  participant useAffiliate
  participant AffiliateRewardsCard
  Wallet->>TopupAPI: request top-up information
  TopupAPI-->>Wallet: affiliate_rewards_enabled
  Wallet->>useAffiliate: pass enabled flag
  useAffiliate-->>Wallet: affiliate data or cleared state
  Wallet->>AffiliateRewardsCard: render when enabled
Loading

Possibly related PRs

Poem

A rabbit flips the rewards switch,
The wallet hides it when disabled.
Claude names gain a standard form,
Routes find the matching model.
Hop, the settings now agree! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main changes: adding an affiliate rewards toggle feature and adding claude- prefix to all model routing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/features/wallet/hooks/use-affiliate.ts (1)

46-69: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Invalidate in-flight requests when the feature is disabled.

A request started with enabled === true can resolve after Lines 99-107 clear the state; the old closure still writes affiliateCode and affiliateLink. A rapid disable/re-enable can therefore display stale data before the fresh request completes. Use request-generation checks or cancellation, and invalidate the previous request on disable.

Also applies to: 99-107

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/wallet/hooks/use-affiliate.ts` around lines 46 - 69, Update
fetchAffiliateCode and the enabled-disabled cleanup path to invalidate any
in-flight affiliate-code request when the feature is disabled. Use a
request-generation check or cancellation mechanism so responses from earlier
requests cannot update affiliateCode or affiliateLink after disable or rapid
re-enable; only the current request may commit state.
🧹 Nitpick comments (2)
web/src/features/wallet/hooks/use-affiliate.ts (1)

33-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an explicit return type to the public hook.

useAffiliate is exported but its return contract is inferred. Define a result type and annotate useAffiliate(...): UseAffiliateResult.

As per coding guidelines, web TypeScript functions should have explicit parameter and return types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/wallet/hooks/use-affiliate.ts` around lines 33 - 41, Define
a public UseAffiliateResult type describing the hook’s returned values, then
annotate the exported useAffiliate function with UseAffiliateResult while
retaining its existing UseAffiliateOptions parameter type and behavior.

Source: Coding guidelines

web/src/features/system-settings/billing/section-registry.tsx (1)

58-66: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider a fallback for AffiliateRewardsEnabled like other optional flags in this file.

Other settings here (WaffoEnabled ?? false, compliance_confirmed ?? false) defensively fall back when the backend value may be absent. AffiliateRewardsEnabled has no fallback, so if the fetched settings payload ever omits this new field (e.g., a stale cache before backend rollout), it will pass undefined through to the Switch's checked prop, risking a React controlled/uncontrolled warning.

🛡️ Proposed fix
-          AffiliateRewardsEnabled: settings.AffiliateRewardsEnabled,
+          AffiliateRewardsEnabled: settings.AffiliateRewardsEnabled ?? true,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/system-settings/billing/section-registry.tsx` around lines
58 - 66, Update the AffiliateRewardsEnabled mapping in the build function to
default missing backend values to false, matching the existing optional-flag
handling such as WaffoEnabled and compliance_confirmed. Preserve the provided
boolean when present so QuotaSettingsSection always receives a defined checked
value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@controller/model.go`:
- Around line 271-281: Make Anthropic model aliases reversible and scoped to the
requesting user/group: in controller/model.go:271-281, prevent collisions
between foo and literal claude-foo by enforcing a reserved-prefix invariant or
maintaining a per-user alias map; in controller/model.go:339-351, resolve IDs
only through the caller-visible mapping; in model/ability.go:57-70, provide
group/requester-scoped lookup where existence checks remain; in
middleware/distributor.go:41-43, pass the effective user/group context; and in
middleware/distributor.go:179-190, remove global ability-based alias
disambiguation so inaccessible abilities cannot affect routing.

In `@controller/topup.go`:
- Line 105: Update GetTopUpInfo’s read of common.AffiliateRewardsEnabled to use
common.OptionMapRWMutex for synchronization, acquiring the appropriate read lock
before accessing the feature flag and releasing it afterward; preserve the
existing affiliate_rewards_enabled response value.

---

Outside diff comments:
In `@web/src/features/wallet/hooks/use-affiliate.ts`:
- Around line 46-69: Update fetchAffiliateCode and the enabled-disabled cleanup
path to invalidate any in-flight affiliate-code request when the feature is
disabled. Use a request-generation check or cancellation mechanism so responses
from earlier requests cannot update affiliateCode or affiliateLink after disable
or rapid re-enable; only the current request may commit state.

---

Nitpick comments:
In `@web/src/features/system-settings/billing/section-registry.tsx`:
- Around line 58-66: Update the AffiliateRewardsEnabled mapping in the build
function to default missing backend values to false, matching the existing
optional-flag handling such as WaffoEnabled and compliance_confirmed. Preserve
the provided boolean when present so QuotaSettingsSection always receives a
defined checked value.

In `@web/src/features/wallet/hooks/use-affiliate.ts`:
- Around line 33-41: Define a public UseAffiliateResult type describing the
hook’s returned values, then annotate the exported useAffiliate function with
UseAffiliateResult while retaining its existing UseAffiliateOptions parameter
type and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4497fe41-54d9-4e6c-93fd-387156ba1ded

📥 Commits

Reviewing files that changed from the base of the PR and between 1721144 and e05e406.

📒 Files selected for processing (28)
  • common/constants.go
  • controller/misc.go
  • controller/model.go
  • controller/status_affiliate_rewards_test.go
  • controller/topup.go
  • middleware/distributor.go
  • model/ability.go
  • model/option.go
  • model/option_affiliate_rewards_test.go
  • web/src/features/auth/types.ts
  • web/src/features/system-settings/billing/index.tsx
  • web/src/features/system-settings/billing/section-registry.tsx
  • web/src/features/system-settings/general/quota-settings-section.tsx
  • web/src/features/system-settings/types.ts
  • web/src/features/wallet/hooks/use-affiliate.ts
  • web/src/features/wallet/index.tsx
  • web/src/features/wallet/lib/affiliate.test.ts
  • web/src/features/wallet/lib/affiliate.ts
  • web/src/features/wallet/types.ts
  • web/src/hooks/use-system-config.ts
  • web/src/i18n/locales/en.json
  • web/src/i18n/locales/fr.json
  • web/src/i18n/locales/ja.json
  • web/src/i18n/locales/ru.json
  • web/src/i18n/locales/vi.json
  • web/src/i18n/locales/zh-TW.json
  • web/src/i18n/locales/zh.json
  • web/src/stores/system-config-store.ts

Comment thread controller/model.go
Comment on lines +271 to 281
for i, m := range userOpenAiModels {
id := m.Id
if !strings.HasPrefix(id, "claude-") {
id = "claude-" + id
}
useranthropicModels[i] = dto.AnthropicModel{
ID: model.Id,
CreatedAt: time.Unix(int64(model.Created), 0).UTC().Format(time.RFC3339),
DisplayName: model.Id,
ID: id,
CreatedAt: time.Unix(int64(m.Created), 0).UTC().Format(time.RFC3339),
DisplayName: m.Id,
Type: "model",
}

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.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Make Anthropic aliases reversible and requester-scoped.

foo and a literal claude-foo both serialize as claude-foo. Retrieval and routing then prefer the literal model; moreover, an ability in another group can make routing preserve an ID the current user cannot access. This yields duplicate listings and makes the original foo unrouteable through /v1/messages.

  • controller/model.go#L271-L281: prevent emitting colliding IDs; enforce a reserved-prefix invariant or expose a per-user reversible alias map.
  • controller/model.go#L339-L351: resolve against that caller-visible mapping rather than global exact-key precedence.
  • model/ability.go#L57-L70: provide a group/requester-scoped lookup if existence checks remain part of resolution.
  • middleware/distributor.go#L41-L43: perform resolution with the effective user/group context.
  • middleware/distributor.go#L179-L190: do not use global ability existence to disambiguate aliases.
📍 Affects 3 files
  • controller/model.go#L271-L281 (this comment)
  • controller/model.go#L339-L351
  • model/ability.go#L57-L70
  • middleware/distributor.go#L41-L43
  • middleware/distributor.go#L179-L190
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controller/model.go` around lines 271 - 281, Make Anthropic model aliases
reversible and scoped to the requesting user/group: in
controller/model.go:271-281, prevent collisions between foo and literal
claude-foo by enforcing a reserved-prefix invariant or maintaining a per-user
alias map; in controller/model.go:339-351, resolve IDs only through the
caller-visible mapping; in model/ability.go:57-70, provide
group/requester-scoped lookup where existence checks remain; in
middleware/distributor.go:41-43, pass the effective user/group context; and in
middleware/distributor.go:179-190, remove global ability-based alias
disambiguation so inaccessible abilities cannot affect routing.

Comment thread controller/topup.go
"enable_waffo_topup": enableWaffo,
"enable_waffo_pancake_topup": enableWaffoPancake,
"enable_redemption": complianceConfirmed,
"affiliate_rewards_enabled": common.AffiliateRewardsEnabled,

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.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'AffiliateRewardsEnabled|OptionMapRWMutex' controller/topup.go model/option.go controller/misc.go

Repository: QuantumNous/new-api

Length of output: 5469


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== common files with AffiliateRewardsEnabled/OptionMapRWMutex declarations =="
rg -n -C2 'var OptionMapRWMutex|type OptionMapRWMutex|AffiliateRewardsEnabled' -S --glob '*.go' .

echo
echo "== controller/topup.go relevant sections =="
fd -a 'topup\.go$' . | sed 's#^\./##' | while read -r f; do
  echo "--- $f ($(wc -l < "$f") lines) ---"
  rg -n -C8 'GetTopUpInfo|affiliate_rewards_enabled|OptionMapRWMutex' "$f" || true
done

echo
echo "== direct reads/writes of AffiliateRewardsEnabled in Go sources =="
python3 - <<'PY'
import re, pathlib
for p in pathlib.Path('.').rglob('*.go'):
    s=p.read_text(errors='ignore').splitlines()
    for i,line in enumerate(s,1):
        if 'common.AffiliateRewardsEnabled' in line or 'AffiliateRewardsEnabled = ' in line:
            print(f"{p}:{i}: {line.strip()}")
PY

Repository: QuantumNous/new-api

Length of output: 9925


Protect the feature-flag read with the configuration lock.

model/option.go writes common.AffiliateRewardsEnabled while holding common.OptionMapRWMutex, but controller/topup.go reads it directly. This unprotected read from GetTopUpInfo can race with an option update and expose undefined or stale top-up visibility.

Proposed fix
+	common.OptionMapRWMutex.RLock()
+	affiliateRewardsEnabled := common.AffiliateRewardsEnabled
+	common.OptionMapRWMutex.RUnlock()
+
	data := gin.H{
-		"affiliate_rewards_enabled":        common.AffiliateRewardsEnabled,
+		"affiliate_rewards_enabled":        affiliateRewardsEnabled,
📝 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
"affiliate_rewards_enabled": common.AffiliateRewardsEnabled,
common.OptionMapRWMutex.RLock()
affiliateRewardsEnabled := common.AffiliateRewardsEnabled
common.OptionMapRWMutex.RUnlock()
data := gin.H{
"affiliate_rewards_enabled": affiliateRewardsEnabled,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controller/topup.go` at line 105, Update GetTopUpInfo’s read of
common.AffiliateRewardsEnabled to use common.OptionMapRWMutex for
synchronization, acquiring the appropriate read lock before accessing the
feature flag and releasing it afterward; preserve the existing
affiliate_rewards_enabled response value.

@mrchi

mrchi commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

That doesn't seem quite right. The display name is specific to Anthropic, while other agent clients only read the model ID.

@Coder-Wjt

Copy link
Copy Markdown
Author

That doesn't seem quite right. The display name is specific to Anthropic, while other agent clients only read the model ID.

You're right. I only considered the Claude Code Desktop.

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