mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
feat(settings): channel_monitor_show_quota public setting (default off)
- 新增公开设置 key(迁移 226 已插入默认 false),控制用户端监控页 是否展示配额/余额;管理端不受影响 - 解析 fail-closed:仅字面 "true" 视为开启(对齐 available_channels_enabled 语义,而非 hide_throughput 的 fail-open) - 全链路贯通:domain key 常量 → setting_public(公开读取 + ChannelMonitorRuntime .ShowQuota + 注入 payload)→ settings_view/parse/update → handler DTO (admin/user 响应 + admin 更新请求)→ api_contract_test 两个 wantJSON 块
This commit is contained in:
@@ -374,6 +374,7 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
||||
ChannelMonitorMode: settings.ChannelMonitorMode,
|
||||
ChannelMonitorDefaultIntervalSeconds: settings.ChannelMonitorDefaultIntervalSeconds,
|
||||
ChannelMonitorHideThroughput: settings.ChannelMonitorHideThroughput,
|
||||
ChannelMonitorShowQuota: settings.ChannelMonitorShowQuota,
|
||||
|
||||
GrokDefaultTextModel: settings.GrokDefaultTextModel,
|
||||
GrokCrossClientModelMapEnabled: settings.GrokCrossClientModelMapEnabled,
|
||||
|
||||
@@ -332,6 +332,7 @@ type UpdateSettingsRequest struct {
|
||||
ChannelMonitorMode *string `json:"channel_monitor_mode"`
|
||||
ChannelMonitorDefaultIntervalSeconds *int `json:"channel_monitor_default_interval_seconds"`
|
||||
ChannelMonitorHideThroughput *bool `json:"channel_monitor_hide_throughput"`
|
||||
ChannelMonitorShowQuota *bool `json:"channel_monitor_show_quota"`
|
||||
|
||||
// Grok model mapping policy
|
||||
GrokDefaultTextModel *string `json:"grok_default_text_model"`
|
||||
@@ -1889,6 +1890,12 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}
|
||||
return previousSettings.ChannelMonitorHideThroughput
|
||||
}(),
|
||||
ChannelMonitorShowQuota: func() bool {
|
||||
if req.ChannelMonitorShowQuota != nil {
|
||||
return *req.ChannelMonitorShowQuota
|
||||
}
|
||||
return previousSettings.ChannelMonitorShowQuota
|
||||
}(),
|
||||
GrokDefaultTextModel: func() string {
|
||||
if req.GrokDefaultTextModel != nil {
|
||||
return *req.GrokDefaultTextModel
|
||||
@@ -2342,6 +2349,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
ChannelMonitorMode: updatedSettings.ChannelMonitorMode,
|
||||
ChannelMonitorDefaultIntervalSeconds: updatedSettings.ChannelMonitorDefaultIntervalSeconds,
|
||||
ChannelMonitorHideThroughput: updatedSettings.ChannelMonitorHideThroughput,
|
||||
ChannelMonitorShowQuota: updatedSettings.ChannelMonitorShowQuota,
|
||||
|
||||
GrokDefaultTextModel: updatedSettings.GrokDefaultTextModel,
|
||||
GrokCrossClientModelMapEnabled: updatedSettings.GrokCrossClientModelMapEnabled,
|
||||
|
||||
@@ -305,6 +305,7 @@ type SystemSettings struct {
|
||||
ChannelMonitorMode string `json:"channel_monitor_mode"`
|
||||
ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
|
||||
ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
|
||||
ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
|
||||
|
||||
// Grok model mapping policy (admin settings; empty account mapping falls back to these).
|
||||
GrokDefaultTextModel string `json:"grok_default_text_model"`
|
||||
@@ -414,6 +415,7 @@ type PublicSettings struct {
|
||||
ChannelMonitorMode string `json:"channel_monitor_mode"`
|
||||
ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
|
||||
ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
|
||||
ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
|
||||
|
||||
AvailableChannelsEnabled bool `json:"available_channels_enabled"`
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
|
||||
ChannelMonitorMode: settings.ChannelMonitorMode,
|
||||
ChannelMonitorDefaultIntervalSeconds: settings.ChannelMonitorDefaultIntervalSeconds,
|
||||
ChannelMonitorHideThroughput: settings.ChannelMonitorHideThroughput,
|
||||
ChannelMonitorShowQuota: settings.ChannelMonitorShowQuota,
|
||||
|
||||
AvailableChannelsEnabled: settings.AvailableChannelsEnabled,
|
||||
|
||||
|
||||
@@ -988,6 +988,7 @@ func TestAPIContracts(t *testing.T) {
|
||||
"channel_monitor_enabled": true,
|
||||
"channel_monitor_mode": "v1",
|
||||
"channel_monitor_hide_throughput": true,
|
||||
"channel_monitor_show_quota": false,
|
||||
"channel_monitor_default_interval_seconds": 60,
|
||||
"available_channels_enabled": false,
|
||||
"model_plaza_enabled": false,
|
||||
@@ -1298,6 +1299,7 @@ func TestAPIContracts(t *testing.T) {
|
||||
"channel_monitor_enabled": true,
|
||||
"channel_monitor_mode": "v1",
|
||||
"channel_monitor_hide_throughput": true,
|
||||
"channel_monitor_show_quota": false,
|
||||
"channel_monitor_default_interval_seconds": 60,
|
||||
"available_channels_enabled": false,
|
||||
"model_plaza_enabled": false,
|
||||
|
||||
@@ -477,6 +477,13 @@ const (
|
||||
// Default false (show rates). Admin endpoints always keep full metrics.
|
||||
SettingKeyChannelMonitorHideThroughput = "channel_monitor_hide_throughput"
|
||||
|
||||
// SettingKeyChannelMonitorShowQuota controls whether quota/balance snapshots
|
||||
// attached to channel monitors (check_mode=quota/quota_probe) are exposed on
|
||||
// the user-facing monitor APIs and UI. Default false (hidden); parsed
|
||||
// fail-closed (only the literal "true" enables it). Admin endpoints always
|
||||
// keep the full snapshots regardless of this flag.
|
||||
SettingKeyChannelMonitorShowQuota = "channel_monitor_show_quota"
|
||||
|
||||
// SettingKeyGrokDefaultTextModel is the fallback Grok text model for empty
|
||||
// request models and built-in Grok aliases (e.g. "grok" → this id). Default grok-4.5.
|
||||
SettingKeyGrokDefaultTextModel = "grok_default_text_model"
|
||||
|
||||
@@ -190,6 +190,7 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
|
||||
SettingKeyChannelMonitorMode: ChannelMonitorModeV1,
|
||||
SettingKeyChannelMonitorDefaultIntervalSeconds: "60",
|
||||
SettingKeyChannelMonitorHideThroughput: "true",
|
||||
SettingKeyChannelMonitorShowQuota: "false",
|
||||
|
||||
// Grok: safe defaults — no cross-vendor model rewrite unless operators enable it.
|
||||
SettingKeyGrokDefaultTextModel: "grok-4.5",
|
||||
@@ -798,6 +799,9 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
|
||||
// 默认隐藏吞吐(迁移 206 的隐私默认):未配置时必须与 setting_public.go 的
|
||||
// 公开读取路径给出同一个值,否则管理端看到“未隐藏”而用户端实际已隐藏。
|
||||
result.ChannelMonitorHideThroughput = !isFalseSettingValue(settings[SettingKeyChannelMonitorHideThroughput])
|
||||
// 配额展示默认关闭且 fail-closed:仅字面 "true" 视为开启
|
||||
// (与 setting_public.go 公开读取路径保持一致)。
|
||||
result.ChannelMonitorShowQuota = settings[SettingKeyChannelMonitorShowQuota] == "true"
|
||||
|
||||
// Grok default mapping policy
|
||||
result.GrokDefaultTextModel = strings.TrimSpace(settings[SettingKeyGrokDefaultTextModel])
|
||||
|
||||
@@ -231,6 +231,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
|
||||
SettingKeyChannelMonitorMode,
|
||||
SettingKeyChannelMonitorDefaultIntervalSeconds,
|
||||
SettingKeyChannelMonitorHideThroughput,
|
||||
SettingKeyChannelMonitorShowQuota,
|
||||
SettingKeyAvailableChannelsEnabled,
|
||||
SettingKeyModelPlazaEnabled,
|
||||
SettingKeyModelPlazaRequireAuth,
|
||||
@@ -355,6 +356,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
|
||||
ChannelMonitorMode: normalizeChannelMonitorMode(settings[SettingKeyChannelMonitorMode]),
|
||||
ChannelMonitorDefaultIntervalSeconds: parseChannelMonitorInterval(settings[SettingKeyChannelMonitorDefaultIntervalSeconds]),
|
||||
ChannelMonitorHideThroughput: !isFalseSettingValue(settings[SettingKeyChannelMonitorHideThroughput]),
|
||||
ChannelMonitorShowQuota: settings[SettingKeyChannelMonitorShowQuota] == "true",
|
||||
|
||||
AvailableChannelsEnabled: settings[SettingKeyAvailableChannelsEnabled] == "true",
|
||||
|
||||
@@ -422,6 +424,10 @@ type ChannelMonitorRuntime struct {
|
||||
DefaultIntervalSeconds int
|
||||
// HideThroughput: when true, user-facing V2 APIs omit RPM/TPM scale signals.
|
||||
HideThroughput bool
|
||||
// ShowQuota: when true, user-facing monitor views keep the quota/balance
|
||||
// snapshots; otherwise the user handler strips them server-side.
|
||||
// Parsed fail-closed (only literal "true" enables). Admin always sees them.
|
||||
ShowQuota bool
|
||||
}
|
||||
|
||||
// ActiveProbesAllowed reports whether V1 active provider probes may run.
|
||||
@@ -450,6 +456,7 @@ func (s *SettingService) GetChannelMonitorRuntime(ctx context.Context) ChannelMo
|
||||
SettingKeyChannelMonitorMode,
|
||||
SettingKeyChannelMonitorDefaultIntervalSeconds,
|
||||
SettingKeyChannelMonitorHideThroughput,
|
||||
SettingKeyChannelMonitorShowQuota,
|
||||
})
|
||||
if err != nil {
|
||||
return ChannelMonitorRuntime{
|
||||
@@ -464,6 +471,7 @@ func (s *SettingService) GetChannelMonitorRuntime(ctx context.Context) ChannelMo
|
||||
Mode: normalizeChannelMonitorMode(vals[SettingKeyChannelMonitorMode]),
|
||||
DefaultIntervalSeconds: parseChannelMonitorInterval(vals[SettingKeyChannelMonitorDefaultIntervalSeconds]),
|
||||
HideThroughput: !isFalseSettingValue(vals[SettingKeyChannelMonitorHideThroughput]),
|
||||
ShowQuota: vals[SettingKeyChannelMonitorShowQuota] == "true",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,6 +614,9 @@ type PublicSettingsInjectionPayload struct {
|
||||
// ChannelMonitorHideThroughput is public so the user UI can hide RPM/TPM
|
||||
// without waiting for API redaction alone (defense in depth).
|
||||
ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
|
||||
// ChannelMonitorShowQuota gates the user-facing quota/balance display on
|
||||
// monitors; fail-closed (absent/false = hidden). Admin UI always shows it.
|
||||
ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
|
||||
AvailableChannelsEnabled bool `json:"available_channels_enabled"`
|
||||
ModelPlazaEnabled bool `json:"model_plaza_enabled"`
|
||||
ModelPlazaRequireAuth bool `json:"model_plaza_require_auth"`
|
||||
@@ -685,6 +696,7 @@ func (s *SettingService) GetPublicSettingsForInjection(ctx context.Context) (any
|
||||
ChannelMonitorMode: settings.ChannelMonitorMode,
|
||||
ChannelMonitorDefaultIntervalSeconds: settings.ChannelMonitorDefaultIntervalSeconds,
|
||||
ChannelMonitorHideThroughput: settings.ChannelMonitorHideThroughput,
|
||||
ChannelMonitorShowQuota: settings.ChannelMonitorShowQuota,
|
||||
AvailableChannelsEnabled: settings.AvailableChannelsEnabled,
|
||||
ModelPlazaEnabled: settings.ModelPlazaEnabled,
|
||||
ModelPlazaRequireAuth: settings.ModelPlazaRequireAuth,
|
||||
|
||||
@@ -417,6 +417,7 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
|
||||
updates[SettingKeyChannelMonitorDefaultIntervalSeconds] = strconv.Itoa(v)
|
||||
}
|
||||
updates[SettingKeyChannelMonitorHideThroughput] = strconv.FormatBool(settings.ChannelMonitorHideThroughput)
|
||||
updates[SettingKeyChannelMonitorShowQuota] = strconv.FormatBool(settings.ChannelMonitorShowQuota)
|
||||
|
||||
// Grok model mapping policy
|
||||
if v := strings.TrimSpace(settings.GrokDefaultTextModel); v != "" {
|
||||
|
||||
@@ -201,6 +201,7 @@ type SystemSettings struct {
|
||||
ChannelMonitorMode string `json:"channel_monitor_mode"`
|
||||
ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
|
||||
ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
|
||||
ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
|
||||
|
||||
// Grok model mapping policy (admin settings; empty mapping falls back to these).
|
||||
GrokDefaultTextModel string `json:"grok_default_text_model"`
|
||||
@@ -378,6 +379,7 @@ type PublicSettings struct {
|
||||
ChannelMonitorMode string `json:"channel_monitor_mode"`
|
||||
ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
|
||||
ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
|
||||
ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
|
||||
|
||||
// Grok model mapping policy (admin settings).
|
||||
GrokDefaultTextModel string `json:"grok_default_text_model"`
|
||||
|
||||
Reference in New Issue
Block a user