Skip to content

Add configurable model hiding for pricing pages - #689

Merged
think-back merged 2 commits into
mainfrom
feat/pricing-page-hidden-models
Aug 11, 2026
Merged

Add configurable model hiding for pricing pages#689
think-back merged 2 commits into
mainfrom
feat/pricing-page-hidden-models

Conversation

@think-back

Copy link
Copy Markdown
Collaborator

背景

flatkey.ai/zh/models/zh/pricing 以及控制台定价页的模型列表,都来自同一条链路(model.GetPricing() → 两个 pricing 接口)。此前没有任何机制可以把个别模型从展示中摘掉——唯一手段是把 models 表的 status 改成非 1,但那是全局禁用,控制台也一起看不见。

改动

新增配置项 pricing_visibility_setting.hidden_models,逗号分隔模型名,支持 * 通配:

写法 含义
gpt-4o 精确匹配
gpt-4o* 前缀
*-internal 后缀
*test* 包含
* 全部

大小写不敏感,自动忽略空项、去重。

过滤挂在所有定价出口

  • GetPricing(控制台,带鉴权)
  • buildWebsitePricingPayloadDefault(官网默认)
  • buildWebsitePublicGroupPricingPayload(PLG 公开分组)

不影响调用:隐藏的模型照常走 relay,/v1/models 仍会列出。这里只管定价页展示。

缓存即时失效:改配置会触发监听器清掉 5 分钟的 websitePricingCache。因为 model 不能反向 import controller,回调注册放在 operation_settingOnPricingVisibilityChanged)。

控制台 UI:计费设置下新增「Pricing Page Visibility」分区,多行文本框直接编辑,无需碰数据库。

验证

  • 新增 8 个测试:5 个匹配逻辑(精确/通配/大小写/空配置/match-all)+ 3 个过滤逻辑(含不可变输入断言)
  • go test ./controller/ -run Pricing 15 个定价测试全绿,含 main 上既有的 11 个
  • go test ./setting/operation_setting/ 全绿
  • go vet 干净,前端 tsc -b 通过

说明:controller 包里 asset-task / CLI device auth / user token / channel error 几个测试在未改动的 main 上同样失败(已 stash 对照验证),与本 PR 无关。

注意

官网侧还有 Next.js 的 5 分钟 ISR 缓存,改完最多 5 分钟生效;控制台是即时的。

Adds a `pricing_visibility_setting.hidden_models` option so specific
models can be kept off the public pricing pages without disabling them.

The option takes a comma-separated list of model names and supports `*`
wildcards in prefix (`gpt-4o*`), suffix (`*-internal`), and contains
(`*test*`) positions. Matching is case-insensitive and ignores blanks.

Filtering is applied at the response boundary of every pricing payload:
the authenticated console endpoint, the public website payload, and the
PLG public-group payload. Hidden models stay fully callable through the
relay and are still listed by /v1/models — this only affects what the
pricing pages display.

Changing the option fires a listener that clears the 5-minute website
pricing response cache so edits take effect immediately. The listener
lives in operation_setting because model/ cannot import controller/.

The console gets a "Pricing Page Visibility" section under billing
settings so the list can be edited without touching the database.
@KingCesc

Copy link
Copy Markdown

🤖 OpenCodeReview · 评审 commit 7d343ed4 · 共 1 条

setting/operation_setting/pricing_visibility_setting.go

  • L58-60: [严重] 这里直接读取全局配置字段没有任何同步保护,而管理端更新 pricing_visibility_setting.hidden_models 时会通过注册的同一个配置指针反射写入该字段;定价接口并发调用 IsPricingHiddenModel 时会与写入产生 data race。建议为该配置注册并使用同一个更新锁,读取时也加锁/返回不可变快照,或在变更后将解析后的 patterns 存入 atomic.Value 供请求路径读取。
pricingVisibilitySettingMu.RLock()
	hiddenModels := pricingVisibilitySetting.HiddenModels
	pricingVisibilitySettingMu.RUnlock()
	raw := strings.FieldsFunc(hiddenModels, func(r rune) bool {
		return r == ',' || r == '\n' || r == '\r'
	})

Reviewer feedback: the hidden-models control belongs next to the other
model pricing controls, not in a separate billing section of its own.

"Pricing Page Visibility" is removed as a standalone section and becomes
a fourth "Hidden models" tab alongside Model prices / Tool prices /
Upstream price sync, so everything that shapes what the pricing pages
show now lives on one card.

PricingVisibilitySection is replaced by HiddenModelsSettings under
models/. The old component wrapped itself in SettingsSection, which
would have nested inside the card's own section; the sibling tab bodies
(ToolPriceSettings, UpstreamRatioSync) render bare content, so the new
component matches that shape. RatioSettingsCard gains the tab id, its
label, a grid-cols-5 entry, and a hiddenModelsDefault prop.

Also adds the i18n keys this feature needs across all 8 locales — the
previous commit introduced user-visible strings without them, so they
would have silently fallen back to English.
@think-back

Copy link
Copy Markdown
Collaborator Author

更新:隐藏模型配置改为 Model Pricing 的第 4 个标签页

按反馈调整了控件位置 —— 隐藏模型属于模型定价的一部分,不该单占一个计费分区。

改动

移除独立的 Pricing Page Visibility 分区,改为 Model Pricing 卡片上的第 4 个标签:

Model prices | Tool prices | Upstream price sync | Hidden models

PricingVisibilitySection 替换为 models/hidden-models-settings.tsxHiddenModelsSettings。原组件自带 SettingsSection,放进卡片会与卡片自身的 section 双层嵌套;同级的 ToolPriceSettingsUpstreamRatioSync 都是渲染裸内容,新组件与之对齐。

RatioSettingsCard 相应新增 tab id、标签文案、grid-cols-5 条目和 hiddenModelsDefault prop。

补上遗漏的 i18n

上一个 commit 引入了用户可见文案却没加翻译 key(Hidden models 和输入框说明),会静默回退英文 —— 违反项目 i18n 规则。本次补齐全部 8 个语言(en/zh/es/fr/pt/ru/ja/vi),均为真实翻译。

跑过 bun run i18n:sync,确认这两个 key 未出现在任何 _reports/{lang}.untranslated.json 中。

验证

结果
bun run typecheck 通过
bun test 1349 pass / 11 fail
bun x eslint(改动文件) 1 error
  • 11 个测试失败集中在 SMTP / 订阅 / 账单,与定价 UI 无关;已 stash 对照验证,基线(上一 commit)同样 1349 pass / 11 fail,零回归。
  • lint 的 1 个 error 在 ratio-settings-card.tsx:194react-hooks/refs),属文件原有代码,基线同样报错,本次未触碰该行。

部署

  • Router deploy: not required —— 本次仅改控制台 UI 与前端 i18n,无 Go 侧改动,不触及 /v1、relay、计费结算或共享中间件。
  • Other deploy targets: newapi-console(前端被 Go 应用 embed,需重新构建镜像)。
  • Risk / validation: 纯 UI 位置调整,配置读写路径未变。上线后验证「系统设置 → 计费 → 模型定价」出现第 4 个标签,填入模型名保存后定价页即时生效。

@think-back
think-back merged commit 49a3dc1 into main Aug 11, 2026
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