Skip to content

预付款退款退还已使用额度 - #4355

Open
cts926 wants to merge 85 commits into
QuantumNous:mainfrom
lynxtoncloud:stc
Open

预付款退款退还已使用额度#4355
cts926 wants to merge 85 commits into
QuantumNous:mainfrom
lynxtoncloud:stc

Conversation

@cts926

@cts926 cts926 commented Apr 20, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

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

📸 运行证明 / Proof of Work

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

Summary by CodeRabbit

  • New Features

    • Configure and manage model display names and modalities via system options.
    • Model display names and modalities are now exposed in the configuration cache.
    • Model listings and pricing views include display name and modality information.
  • Bug Fixes

    • No user-facing behavioral changes to quota handling in this release.

@coderabbitai

coderabbitai Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Added configuration storage and APIs for model display names and modalities, wired through option updates, cached exposure, and pricing/controller surfaces; minor commented-out quota counter calls were introduced in task billing functions.

Changes

Cohort / File(s) Summary
Model Metadata Configuration
setting/ratio_setting/model_ratio.go
Added two maps (modelDisplayNameMap, modelModalitiesMap) plus JSON serialize/deserialize, lookup, and copy functions (8 new exported helpers).
Exposed Cache
setting/ratio_setting/exposed_cache.go
Cache exposure now includes model_display_name and model_modalities, populated from new getters.
Controller Option Handling
controller/option.go
UpdateOption now intercepts ModelDisplayName and ModelModalities keys and calls corresponding ratio_setting update functions with early-return on failure.
Controller Model Responses
controller/model.go
Populates Modalities (and SupportedEndpointTypes in one branch) for models returned by List/Retrieve paths using ratio_setting.GetModelModalities.
DTO / Pricing Surfaces
dto/pricing.go, model/pricing.go
Added Modalities to OpenAIModels DTO and Modalities/DisplayName fields to pricing structs; pricing population now fills these from ratio_setting.
Service (Billing)
service/task_billing.go
Inserted commented-out per-user/channel quota update calls in RefundTaskQuota and RecalculateTaskQuota (no active behavior change).

Sequence Diagram(s)

sequenceDiagram
    participant Admin
    participant Controller
    participant RatioSetting as "ratio_setting\n(config store)"
    participant Cache
    participant PricingModel as "model/pricing & dto"

    Admin->>Controller: POST UpdateOption (ModelDisplayName/Modalities)
    Controller->>RatioSetting: UpdateModelDisplayName/ModalitiesByJSONString
    RatioSetting-->>Controller: OK / error
    Controller-->>Admin: HTTP 200 (success/failure)

    Note over RatioSetting,Cache: configuration updated
    RatioSetting->>Cache: GetExposedData (includes new maps)
    Cache-->>Controller: exposed data includes model_display_name/modalities

    Controller->>PricingModel: ListModels / RetrieveModel
    PricingModel->>RatioSetting: GetModelDisplayName / GetModelModalities
    RatioSetting-->>PricingModel: display name / modalities
    PricingModel-->>Controller: enriched model DTOs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • seefs001

Poem

🐰
I nudge the map where model names hide,
Modalities stitched, tied side by side.
Cache hums a tune, controllers reply,
Pricing bows with a brighter display — my hop of joy! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title in Chinese translates to 'prepaid refund returns used quota', but the changeset primarily adds Modalities and DisplayName fields to pricing structures and updates model/controller logic—not refund quota returns. Update the title to accurately reflect the main changes, such as 'Add Modalities and DisplayName fields to pricing structures' or align the implementation with the refund quota objective.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@cts926 cts926 closed this Apr 20, 2026
@cts926 cts926 reopened this Apr 20, 2026

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@service/task_billing.go`:
- Around line 167-169: In RefundTaskQuota and RecalculateTaskQuota replace calls
that pass a negative quota into UpdateUserUsedQuotaAndRequestCount (e.g.,
UpdateUserUsedQuotaAndRequestCount(task.UserId, -quota) and
UpdateUserUsedQuotaAndRequestCount(task.UserId, -quotaDelta)) with the
quota-only helper updateUserUsedQuota (or the public wrapper
updateUserUsedQuota() from model/user.go) so only used_quota is decremented and
request_count remains unchanged; also audit UpdateChannelUsedQuota for the same
request_count side-effect and, if it similarly mutates request_count, switch to
a channel-only quota update helper for channel updates (e.g., a dedicated
UpdateChannelUsedQuotaOnly) to ensure refunds do not decrement request_count.
🪄 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

Run ID: 3b6a5be5-78a0-4503-8ebb-706049e13122

📥 Commits

Reviewing files that changed from the base of the PR and between f995a86 and 6dd933c.

📒 Files selected for processing (1)
  • service/task_billing.go

Comment thread service/task_billing.go Outdated
Comment on lines +167 to +169
//3. 更新用户和渠道的使用额度
model.UpdateUserUsedQuotaAndRequestCount(task.UserId, -quota)
model.UpdateChannelUsedQuota(task.ChannelId, -quota)

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 1. Show the implementation of UpdateUserUsedQuotaAndRequestCount and UpdateChannelUsedQuota.
ast-grep --pattern $'func UpdateUserUsedQuotaAndRequestCount($$$) {
  $$$
}'

ast-grep --pattern $'func UpdateChannelUsedQuota($$$) {
  $$$
}'

# 2. Look for any sibling helpers that only touch used_quota (no request count).
rg -nP --type=go '\bfunc\s+(Update|Decrease|Increase)\w*(UsedQuota|RequestCount)\w*\s*\('

# 3. See how existing refund flows in the repo adjust these counters (if at all).
rg -nP --type=go -C3 'LogTypeRefund' -g '!service/task_billing.go'

Repository: QuantumNous/new-api

Length of output: 4392


🏁 Script executed:

# Inspect the underlying updateUserUsedQuotaAndRequestCount function implementation
cat -n model/user.go | sed -n '960,1050p'

Repository: QuantumNous/new-api

Length of output: 3164


🏁 Script executed:

# Check for alternative helpers that update quota without request count
rg -nP --type=go '\bfunc\s+(Update|Decrease)\w*User\w*(Quota|UsedQuota)\w*\s*\(' model/

Repository: QuantumNous/new-api

Length of output: 224


🏁 Script executed:

# Look at how RefundTaskQuota and RecalculateTaskQuota are called/tested
cat -n service/task_billing.go | sed -n '160,180p'
cat -n service/task_billing.go | sed -n '225,245p'

Repository: QuantumNous/new-api

Length of output: 1700


🏁 Script executed:

# Check if there are test cases that verify request_count behavior during refund
grep -n "request_count\|RequestCount" service/task_billing_test.go | head -20

Repository: QuantumNous/new-api

Length of output: 45


Refund paths incorrectly decrement user request_count.

model.UpdateUserUsedQuotaAndRequestCount updates both used_quota and request_count by 1, regardless of whether the quota parameter is positive or negative. Passing -quota on the refund path (lines 168 and 233) will decrement request_count by 1.

Semantically, a failed/refunded task should roll back quota usage but NOT decrement request_count — the user made a request regardless of success. Over time, this causes request_count to drift and violates the expectation that it is monotonically increasing.

The codebase already has updateUserUsedQuota() (model/user.go:981) which updates only used_quota and leaves request_count unchanged. Use this helper (or a public wrapper) for refunds instead:

  • Line 168 in RefundTaskQuota: Replace UpdateUserUsedQuotaAndRequestCount(task.UserId, -quota) with a quota-only update.
  • Line 233 in RecalculateTaskQuota: Replace UpdateUserUsedQuotaAndRequestCount(task.UserId, -quotaDelta) with a quota-only update.

Apply the same fix to channel updates if UpdateChannelUsedQuota exhibits the same pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@service/task_billing.go` around lines 167 - 169, In RefundTaskQuota and
RecalculateTaskQuota replace calls that pass a negative quota into
UpdateUserUsedQuotaAndRequestCount (e.g.,
UpdateUserUsedQuotaAndRequestCount(task.UserId, -quota) and
UpdateUserUsedQuotaAndRequestCount(task.UserId, -quotaDelta)) with the
quota-only helper updateUserUsedQuota (or the public wrapper
updateUserUsedQuota() from model/user.go) so only used_quota is decremented and
request_count remains unchanged; also audit UpdateChannelUsedQuota for the same
request_count side-effect and, if it similarly mutates request_count, switch to
a channel-only quota update helper for channel updates (e.g., a dedicated
UpdateChannelUsedQuotaOnly) to ensure refunds do not decrement request_count.

@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

Caution

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

⚠️ Outside diff range comments (1)
controller/usedata.go (1)

66-101: ⚠️ Potential issue | 🟠 Major

Same breaking transform issue + the 1-month guard defeats large days values.

Two concerns:

  1. Lines 79-85: when the caller passes days > 30, the handler has just set startTimestamp = endTimestamp - days*24*3600, then immediately fails the 2_592_000-second check and returns "时间跨度不能超过 1 个月". Either cap days (e.g. if days > 30 { days = 30 }) or raise/remove the limit for the days path; otherwise the new parameter is unusable beyond 30.
  2. Lines 91-101: model.GetQuotaDataByUserId returns raw, ungrouped rows, so multiple records for the same created_at will each produce a separate {date, quota} entry with duplicate date values. If the frontend expects one value per day, aggregate by date before building result. Also amount duplicating Quota has the same units concern flagged above.
Suggested fix for the day cap
-	days, err := strconv.Atoi(c.Query("days"))
-	if err == nil && days > 0 {
-		endTimestamp = time.Now().Unix()
-		startTimestamp = endTimestamp - int64(days*24*3600)
-	}
+	if days, derr := strconv.Atoi(c.Query("days")); derr == nil && days > 0 {
+		if days > 30 {
+			days = 30
+		}
+		endTimestamp = time.Now().Unix()
+		startTimestamp = endTimestamp - int64(days)*24*3600
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@controller/usedata.go` around lines 66 - 101, GetUserQuotaDates: cap the
incoming days to 30 (e.g., if days>30 set days=30) so the days path doesn't
always trigger the 1-month guard, then aggregate the rows returned by
model.GetQuotaDataByUserId by date (use
time.Unix(d.CreatedAt,0).Format("2006-01-02") as key) to coalesce multiple
records per day into a single map entry summing Quota (and set amount
accordingly) before building the final result slice; update logic in
GetUserQuotaDates where days is parsed and where result is constructed to
perform the grouping and summation.
🧹 Nitpick comments (1)
controller/usedata.go (1)

20-23: Shadowed err and minor overflow hygiene.

err declared here on Line 20 is later reused/redeclared on Line 26 (dates, err := ...) — functionally fine due to := with a new LHS (dates), but it makes the control flow harder to follow and previously caused subtle bugs in similar handlers. Prefer a scoped block as in the suggested patch for GetUserQuotaDates above. Also compute int64(days)*24*3600 rather than int64(days*24*3600) to avoid truncation if a very large days is ever passed on a 32-bit build.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@controller/usedata.go` around lines 20 - 23, Wrap the days parsing logic in
its own scoped block to avoid shadowing err (so the initial err from
strconv.Atoi(c.Query("days")) doesn’t get reused later when you do dates, err :=
...) and assign to startTimestamp/endTimestamp inside that block; also change
the duration calc to use int64(days) * 24 * 3600 (i.e. multiply after converting
days to int64) to avoid 32-bit overflow/truncation. Locate the
strconv.Atoi(c.Query("days")) call and the subsequent use of
startTimestamp/endTimestamp and adjust accordingly to a local block, leaving
later usages of dates, err (e.g., dates, err := ...) unaffected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@controller/usedata.go`:
- Around line 31-41: The current transformation over "dates" (building result :=
make([]map[string]interface{}, len(dates)) and populating map with only "date",
"quota", and "amount") drops model_name, count, and token_used returned by the
query GetAllQuotaDates; update this mapping to preserve those fields (e.g.,
include "model_name": d.ModelName, "count": d.Count, "token_used": d.TokenUsed)
and correct the "amount" value to match frontend expectations (do not set
"amount": d.Quota blindly—use the proper conversion or unit like
d.Quota/QuotaPerUnit if required), or alternatively remove this transformation
and return the original slice if per-model breakdown is intended; modify the
code that constructs result from "dates" accordingly.

---

Outside diff comments:
In `@controller/usedata.go`:
- Around line 66-101: GetUserQuotaDates: cap the incoming days to 30 (e.g., if
days>30 set days=30) so the days path doesn't always trigger the 1-month guard,
then aggregate the rows returned by model.GetQuotaDataByUserId by date (use
time.Unix(d.CreatedAt,0).Format("2006-01-02") as key) to coalesce multiple
records per day into a single map entry summing Quota (and set amount
accordingly) before building the final result slice; update logic in
GetUserQuotaDates where days is parsed and where result is constructed to
perform the grouping and summation.

---

Nitpick comments:
In `@controller/usedata.go`:
- Around line 20-23: Wrap the days parsing logic in its own scoped block to
avoid shadowing err (so the initial err from strconv.Atoi(c.Query("days"))
doesn’t get reused later when you do dates, err := ...) and assign to
startTimestamp/endTimestamp inside that block; also change the duration calc to
use int64(days) * 24 * 3600 (i.e. multiply after converting days to int64) to
avoid 32-bit overflow/truncation. Locate the strconv.Atoi(c.Query("days")) call
and the subsequent use of startTimestamp/endTimestamp and adjust accordingly to
a local block, leaving later usages of dates, err (e.g., dates, err := ...)
unaffected.
🪄 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

Run ID: 2f936870-5f92-4952-935b-056af2844771

📥 Commits

Reviewing files that changed from the base of the PR and between b796bdb and 8387c46.

📒 Files selected for processing (1)
  • controller/usedata.go

Comment thread controller/usedata.go Outdated

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@setting/ratio_setting/model_ratio.go`:
- Around line 707-728: GetModelDisplayName and GetModelModalities currently
normalize the input via FormatMatchingModelName before any lookup, which
prevents exact metadata entries (e.g., concrete Gemini thinking-budget or gizmo
names) from being found; modify both functions (GetModelDisplayName and
GetModelModalities) to first attempt an exact lookup on modelDisplayNameMap /
modelModalitiesMap with the original name, and only if that fails perform the
FormatMatchingModelName normalization and retry the lookup (falling back to
empty string if still not found), ensuring existing normalized behavior remains
as a fallback.
🪄 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

Run ID: db27c633-8760-42bb-a8d3-e68df87f958f

📥 Commits

Reviewing files that changed from the base of the PR and between 8387c46 and 1217fec.

📒 Files selected for processing (3)
  • controller/option.go
  • setting/ratio_setting/exposed_cache.go
  • setting/ratio_setting/model_ratio.go

Comment on lines +707 to +728
func GetModelDisplayName(name string) string {
name = FormatMatchingModelName(name)
if displayName, ok := modelDisplayNameMap.Get(name); ok {
return displayName
}
return ""
}

func ModelModalities2JSONString() string {
return modelModalitiesMap.MarshalJSONString()
}

func UpdateModelModalitiesByJSONString(jsonStr string) error {
return types.LoadFromJsonStringWithCallback(modelModalitiesMap, jsonStr, InvalidateExposedDataCache)
}

func GetModelModalities(name string) string {
name = FormatMatchingModelName(name)
if modalities, ok := modelModalitiesMap.Get(name); ok {
return modalities
}
return ""

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 | 🟠 Major

Try exact metadata lookup before pricing-style normalization.

FormatMatchingModelName collapses concrete Gemini thinking-budget and gizmo model names to wildcard keys. That is useful for pricing, but it makes exact model_display_name / model_modalities entries unreachable for those models. Prefer exact lookup first, then fall back to normalized lookup for wildcard defaults.

🐛 Proposed fix
 func GetModelDisplayName(name string) string {
-	name = FormatMatchingModelName(name)
 	if displayName, ok := modelDisplayNameMap.Get(name); ok {
 		return displayName
 	}
+	formattedName := FormatMatchingModelName(name)
+	if formattedName != name {
+		if displayName, ok := modelDisplayNameMap.Get(formattedName); ok {
+			return displayName
+		}
+	}
 	return ""
 }
 
 func ModelModalities2JSONString() string {
 	return modelModalitiesMap.MarshalJSONString()
@@
 func GetModelModalities(name string) string {
-	name = FormatMatchingModelName(name)
 	if modalities, ok := modelModalitiesMap.Get(name); ok {
 		return modalities
 	}
+	formattedName := FormatMatchingModelName(name)
+	if formattedName != name {
+		if modalities, ok := modelModalitiesMap.Get(formattedName); ok {
+			return modalities
+		}
+	}
 	return ""
 }
📝 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
func GetModelDisplayName(name string) string {
name = FormatMatchingModelName(name)
if displayName, ok := modelDisplayNameMap.Get(name); ok {
return displayName
}
return ""
}
func ModelModalities2JSONString() string {
return modelModalitiesMap.MarshalJSONString()
}
func UpdateModelModalitiesByJSONString(jsonStr string) error {
return types.LoadFromJsonStringWithCallback(modelModalitiesMap, jsonStr, InvalidateExposedDataCache)
}
func GetModelModalities(name string) string {
name = FormatMatchingModelName(name)
if modalities, ok := modelModalitiesMap.Get(name); ok {
return modalities
}
return ""
func GetModelDisplayName(name string) string {
if displayName, ok := modelDisplayNameMap.Get(name); ok {
return displayName
}
formattedName := FormatMatchingModelName(name)
if formattedName != name {
if displayName, ok := modelDisplayNameMap.Get(formattedName); ok {
return displayName
}
}
return ""
}
func ModelModalities2JSONString() string {
return modelModalitiesMap.MarshalJSONString()
}
func UpdateModelModalitiesByJSONString(jsonStr string) error {
return types.LoadFromJsonStringWithCallback(modelModalitiesMap, jsonStr, InvalidateExposedDataCache)
}
func GetModelModalities(name string) string {
if modalities, ok := modelModalitiesMap.Get(name); ok {
return modalities
}
formattedName := FormatMatchingModelName(name)
if formattedName != name {
if modalities, ok := modelModalitiesMap.Get(formattedName); ok {
return modalities
}
}
return ""
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@setting/ratio_setting/model_ratio.go` around lines 707 - 728,
GetModelDisplayName and GetModelModalities currently normalize the input via
FormatMatchingModelName before any lookup, which prevents exact metadata entries
(e.g., concrete Gemini thinking-budget or gizmo names) from being found; modify
both functions (GetModelDisplayName and GetModelModalities) to first attempt an
exact lookup on modelDisplayNameMap / modelModalitiesMap with the original name,
and only if that fails perform the FormatMatchingModelName normalization and
retry the lookup (falling back to empty string if still not found), ensuring
existing normalized behavior remains as a fallback.

@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.

🧹 Nitpick comments (1)
controller/model.go (1)

142-154: Consider extracting the repeated oaiModel/custom-model construction.

Lines 142‑154 and 192‑204 are now near‑identical blocks; both branches set SupportedEndpointTypes + Modalities on the map hit and construct an equivalent dto.OpenAIModels on miss. A small helper like buildUserModel(name string) dto.OpenAIModels would remove the duplication and guarantee future fields (e.g., DisplayName) are added in one place rather than two.

♻️ Proposed helper
func buildUserModel(name string) dto.OpenAIModels {
    if m, ok := openAIModelsMap[name]; ok {
        m.SupportedEndpointTypes = model.GetModelSupportEndpointTypes(name)
        m.Modalities = ratio_setting.GetModelModalities(name)
        return m
    }
    return dto.OpenAIModels{
        Id:                     name,
        Object:                 "model",
        Created:                1626777600,
        OwnedBy:                "custom",
        SupportedEndpointTypes: model.GetModelSupportEndpointTypes(name),
        Modalities:             ratio_setting.GetModelModalities(name),
    }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@controller/model.go` around lines 142 - 154, Extract the duplicated
construction of user model entries into a single helper like buildUserModel(name
string) dto.OpenAIModels: inside it, check openAIModelsMap[name], if present set
m.SupportedEndpointTypes = model.GetModelSupportEndpointTypes(name) and
m.Modalities = ratio_setting.GetModelModalities(name) and return m; otherwise
construct and return the dto.OpenAIModels literal with Id=name, Object="model",
Created=1626777600, OwnedBy="custom", and the same
SupportedEndpointTypes/Modalities calls. Replace both duplicated blocks that
append into userOpenAiModels with calls to userOpenAiModels =
append(userOpenAiModels, buildUserModel(allowModel)) (or the appropriate
variable name) so all future fields (e.g., DisplayName) are maintained in one
place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@controller/model.go`:
- Around line 142-154: Extract the duplicated construction of user model entries
into a single helper like buildUserModel(name string) dto.OpenAIModels: inside
it, check openAIModelsMap[name], if present set m.SupportedEndpointTypes =
model.GetModelSupportEndpointTypes(name) and m.Modalities =
ratio_setting.GetModelModalities(name) and return m; otherwise construct and
return the dto.OpenAIModels literal with Id=name, Object="model",
Created=1626777600, OwnedBy="custom", and the same
SupportedEndpointTypes/Modalities calls. Replace both duplicated blocks that
append into userOpenAiModels with calls to userOpenAiModels =
append(userOpenAiModels, buildUserModel(allowModel)) (or the appropriate
variable name) so all future fields (e.g., DisplayName) are maintained in one
place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35a4af5f-95b3-4dfa-bb0a-13822ec7b238

📥 Commits

Reviewing files that changed from the base of the PR and between 1217fec and cc68b83.

📒 Files selected for processing (3)
  • controller/model.go
  • dto/pricing.go
  • model/pricing.go

qqjyy and others added 28 commits May 6, 2026 11:47
stc-5/7-21.12修复空返回仍然算任务成功
stc-5/7-22.01解决文本等模型二次应用企业折扣
stc-5/8-15:53为用户使用量聚合表添加end_at字段
新增 PublishBillingSnapshotForOpsLog 与 ops 相关 context key;在文本/WSS/音频消费、违规费、MJ、LogTaskConsumption 等 RecordConsumeLog 前写入 token 与额度快照;增加 EmitAsyncBillingOpsLog 钩子及异步任务结算/退款的结构化事件字段;RecalculateTaskQuota 增加 billingTotalTokens 参数并调整调用与测试
stc-5/13-18:07 fix(channel): 修复渠道多模型时除首个外报模型ID错误
…uting

Co-authored-by: Cursor <cursoragent@cursor.com>
@Calcium-Ion
Calcium-Ion force-pushed the main branch 2 times, most recently from 51fdfc5 to 2b6f1df Compare August 30, 2026 15:03
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.

4 participants