-
Notifications
You must be signed in to change notification settings - Fork 11.1k
一些BUG的修复,以及一些新功能。尽可能的没有动后端,只是对前端进行了部分修改 #4784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5941711
f7eb8d7
a29c60c
bb8cc4f
4cf9f8d
8852083
05c4161
76559c6
d6eb205
3344526
95c3b3e
9ed3559
f66d1dc
9cf8be9
51b3008
d51cec8
85b8952
1b9bcc9
f73e66b
552e802
11ddc89
f1e48ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,18 @@ var ( | |
| "flux-", | ||
| "flux.1-", | ||
| } | ||
| VideoGenerationModels = []string{ | ||
| "doubao-seedance-", | ||
| "seedance-", | ||
| "sora-", | ||
| "veo-", | ||
| "kling", | ||
| "vidu", | ||
| "hailuo", | ||
| "jimeng", | ||
| "cogvideo", | ||
| "video", | ||
| } | ||
|
Comment on lines
+20
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review overly generic video model matching. The Consider:
♻️ Example refinement VideoGenerationModels = []string{
"doubao-seedance-",
"seedance-",
"sora-",
"veo-",
"kling",
"vidu",
"hailuo",
"jimeng",
"cogvideo",
- "video",
+ "prefix:video-gen-", // or remove if no such models exist
}🤖 Prompt for AI Agents |
||
| OpenAITextModels = []string{ | ||
| "gpt-", | ||
| "o1", | ||
|
|
@@ -48,6 +60,19 @@ func IsImageGenerationModel(modelName string) bool { | |
| return false | ||
| } | ||
|
|
||
| func IsVideoGenerationModel(modelName string) bool { | ||
| modelName = strings.ToLower(modelName) | ||
| for _, m := range VideoGenerationModels { | ||
| if strings.Contains(modelName, m) { | ||
| return true | ||
| } | ||
| if strings.HasPrefix(m, "prefix:") && strings.HasPrefix(modelName, strings.TrimPrefix(m, "prefix:")) { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func IsOpenAITextModel(modelName string) bool { | ||
| modelName = strings.ToLower(modelName) | ||
| for _, m := range OpenAITextModels { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package controller | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/QuantumNous/new-api/common" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/QuantumNous/new-api/model" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/QuantumNous/new-api/service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/gin-gonic/gin" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type AITranslationSettingsRequest struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Enabled any `json:"enabled"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BaseURL string `json:"base_url"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| APIKey string `json:"api_key"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Model string `json:"model"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TimeoutSeconds any `json:"timeout_seconds"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func UpdateAITranslationSettings(c *gin.Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var req AITranslationSettingsRequest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := common.DecodeJson(c.Request.Body, &req); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusBadRequest, gin.H{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "success": false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": "invalid request", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updates := map[string]string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "AITranslationEnabled": common.Interface2String(req.Enabled), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "AITranslationBaseURL": strings.TrimSpace(req.BaseURL), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "AITranslationModel": strings.TrimSpace(req.Model), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "AITranslationTimeoutSeconds": common.Interface2String(req.TimeoutSeconds), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if strings.TrimSpace(req.APIKey) != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updates["AITranslationAPIKey"] = strings.TrimSpace(req.APIKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for key, value := range updates { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := model.UpdateOption(key, value); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.ApiError(c, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusOK, gin.H{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "success": true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func GenerateAITranslations(c *gin.Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sources := make([]service.AITranslationSource, 0, 8) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectSource := func(scope string, build func() any, paths []string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start := time.Now() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload := build() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sources = append(sources, service.AITranslationSource{Scope: scope, Payload: payload, Paths: paths}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation source collected: scope=" + scope + ", elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectSource("status", func() any { return buildStatusResponse() }, statusTranslationPaths) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectSource("notice", func() any { return buildNoticeResponse() }, noticeTranslationPaths) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectSource("user_groups", func() any { return buildUserGroupsResponse("default") }, userGroupsTranslationPaths) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectSource("pricing", func() any { return buildPricingResponse("default") }, pricingTranslationPaths) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+58
to
+68
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add panic recovery to protect against builder function failures. The inline 🛡️ Proposed fix with panic recovery collectSource := func(scope string, build func() any, paths []string) {
+ defer func() {
+ if r := recover(); r != nil {
+ common.SysLog("AI translation source collection panic: scope=" + scope + ", error=" + fmt.Sprint(r))
+ }
+ }()
start := time.Now()
payload := build()
sources = append(sources, service.AITranslationSource{Scope: scope, Payload: payload, Paths: paths})
common.SysLog("AI translation source collected: scope=" + scope + ", elapsed=" + time.Since(start).String())
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start := time.Now() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if plansResp, err := buildSubscriptionPlansResponse(); err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sources = append(sources, service.AITranslationSource{Scope: "subscription_plans", Payload: plansResp, Paths: subscriptionPlansTranslationPaths}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation source collected: scope=subscription_plans, elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation source skipped: scope=subscription_plans, error=" + err.Error() + ", elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start = time.Now() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if rankingsResp, err := buildRankingsResponse("week"); err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sources = append(sources, service.AITranslationSource{Scope: "rankings", Payload: rankingsResp, Paths: rankingsTranslationPaths}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation source collected: scope=rankings, elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation source skipped: scope=rankings, error=" + err.Error() + ", elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start = time.Now() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapshot, err := service.GenerateAITranslationSnapshot(c.Request.Context(), sources) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation snapshot failed: elapsed=" + time.Since(start).String() + ", error=" + err.Error()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusOK, gin.H{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "success": false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": err.Error(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| common.SysLog("AI translation snapshot generated: elapsed=" + time.Since(start).String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusOK, gin.H{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "success": true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "message": "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "data": gin.H{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "updated_at": snapshot.UpdatedAt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "stats": snapshot.Stats, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| package controller | ||
|
|
||
| var statusTranslationPaths = []string{ | ||
| "data.announcements.*.content", | ||
| "data.announcements.*.extra", | ||
| "data.api_info.*.description", | ||
| "data.api_info.*.route", | ||
| "data.chats.*.@key", | ||
| "data.faq.*.answer", | ||
| "data.faq.*.question", | ||
| } | ||
|
|
||
| var noticeTranslationPaths = []string{ | ||
| "data", | ||
| } | ||
|
|
||
| var uptimeTranslationPaths = []string{ | ||
| "data.*.categoryName", | ||
| "data.*.monitors.*.group", | ||
| "data.*.monitors.*.name", | ||
| } | ||
|
|
||
| var userGroupsTranslationPaths = []string{ | ||
| "data.@key", | ||
| "data.*.desc", | ||
| } | ||
|
|
||
| var subscriptionPlansTranslationPaths = []string{ | ||
| "data.*.plan.subtitle", | ||
| "data.*.plan.title", | ||
| } | ||
|
|
||
| var pricingTranslationPaths = []string{ | ||
| "auto_groups.*", | ||
| "data.*.enable_groups.*", | ||
| "data.*.description", | ||
| "data.*.tags", | ||
| "group_ratio.@key", | ||
| "usable_group.@key", | ||
| "usable_group.@value", | ||
| "vendors.*.name", | ||
| } | ||
|
|
||
| var rankingsTranslationPaths = []string{ | ||
| "data.models.*.vendor", | ||
| "data.models_history.models.*.vendor", | ||
| "data.models_history.points.*.vendor", | ||
| "data.top_droppers.*.vendor", | ||
| "data.top_movers.*.vendor", | ||
| "data.vendor_share_history.points.*.vendor", | ||
| "data.vendor_share_history.vendors.*.name", | ||
| "data.vendors.*.vendor", | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate channel before publishing tags.
Line 40 and Line 121 use
GITHUB_REF_NAMEdirectly as channel. Withworkflow_dispatch, this can publish unexpected channels (for example from a non-release branch) and produce unintended image tags.Suggested fix
Use the same guard in both jobs.
Also applies to: 119-123
🤖 Prompt for AI Agents