-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
feat(channel): OpenAI balance refresh via /v1/organization/costs (admin key) #4995
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
base: main
Are you sure you want to change the base?
Changes from all commits
afa50d5
5bdcc59
f5a6d76
aced4d6
b02cd1f
4278d40
8140ab3
9e6e802
fa3f7a1
27502b6
8eb8dad
1f78525
06b6212
a2de995
d969c87
7d4a65b
baa9ee5
524a07b
6ea0bae
3f887a4
021953d
d2ef100
0702b5e
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 |
|---|---|---|
|
|
@@ -67,6 +67,13 @@ func clearChannelInfo(channel *model.Channel) { | |
| channel.ChannelInfo.MultiKeyDisabledReason = nil | ||
| channel.ChannelInfo.MultiKeyDisabledTime = nil | ||
| } | ||
| // Strip secrets embedded in OtherSettings JSON (e.g. OpenAIAdminKey) before serializing | ||
| // the channel back to API clients. The inference Key column is already cleared either via | ||
| // gorm Omit("key") at the query layer or by explicit channel.Key = "" in the caller. | ||
| if other := channel.GetOtherSettings(); other.OpenAIAdminKey != "" { | ||
| other.OpenAIAdminKey = "" | ||
| channel.SetOtherSettings(other) | ||
| } | ||
| } | ||
|
|
||
| func applyChannelStatusFilter(query *gorm.DB, statusFilter int) *gorm.DB { | ||
|
|
@@ -889,6 +896,19 @@ func UpdateChannel(c *gin.Context) { | |
| // Always copy the original ChannelInfo so that fields like IsMultiKey and MultiKeySize are retained. | ||
| channel.ChannelInfo = originChannel.ChannelInfo | ||
|
|
||
| // Preserve secrets embedded in OtherSettings when the client sends an empty value. | ||
| // The form masks OpenAIAdminKey on edit (the GET endpoint never returns it), so an empty | ||
| // admin_key in the PUT payload means "keep existing", not "clear". Without this merge, | ||
| // gorm's struct-based Updates(channel) would overwrite settings JSON wholesale. | ||
| incomingOther := channel.GetOtherSettings() | ||
| if incomingOther.OpenAIAdminKey == "" { | ||
| originOther := originChannel.GetOtherSettings() | ||
| if originOther.OpenAIAdminKey != "" { | ||
| incomingOther.OpenAIAdminKey = originOther.OpenAIAdminKey | ||
| channel.SetOtherSettings(incomingOther) | ||
| } | ||
| } | ||
|
Comment on lines
+903
to
+910
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. Prevent stale admin-key retention when channel type is not OpenAI. At Line 904, the preservation merge runs regardless of channel type. If a channel is edited from OpenAI to another type, this can keep Suggested fix- incomingOther := channel.GetOtherSettings()
- if incomingOther.OpenAIAdminKey == "" {
+ incomingOther := channel.GetOtherSettings()
+ if channel.Type == constant.ChannelTypeOpenAI && incomingOther.OpenAIAdminKey == "" {
originOther := originChannel.GetOtherSettings()
if originOther.OpenAIAdminKey != "" {
incomingOther.OpenAIAdminKey = originOther.OpenAIAdminKey
channel.SetOtherSettings(incomingOther)
}
}🤖 Prompt for AI Agents |
||
|
|
||
| // If the request explicitly specifies a new MultiKeyMode, apply it on top of the original info. | ||
| if channel.MultiKeyMode != nil && *channel.MultiKeyMode != "" { | ||
| channel.ChannelInfo.MultiKeyMode = constant.MultiKeyMode(*channel.MultiKeyMode) | ||
|
|
||
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.
OpenAI balance semantic change can incorrectly auto-disable healthy channels.
updateChannelOpenAIBalancenow returns month-to-date spent amount, but downstream logic still treatschannel.Balanceas remaining and disables onbalance <= 0. This can disable OpenAI channels at month start (spent = 0).🔧 Minimal mitigation diff
func updateAllChannelsBalance() error { @@ - } else { - // err is nil & balance <= 0 means quota is used up - if balance <= 0 { + } else { + // OpenAI balance is month-to-date spend (not remaining quota). + // Keep auto-disable logic only for channel types where balance semantics are "remaining". + if channel.Type != constant.ChannelTypeOpenAI && balance <= 0 { service.DisableChannel(*types.NewChannelError(channel.Id, channel.Type, channel.Name, channel.ChannelInfo.IsMultiKey, "", channel.GetAutoBan()), "余额不足") } }🤖 Prompt for AI Agents