Repository navigation
feat(qoder): 模型列表显示价格与限时免费标记 - #232
Merged
Merged
Conversation
Qoder's model catalog carries a per-model `price_factor` (the multiplier its own client renders as `0.50x Credit`) plus an `is_free` flag and a `tags` array, but the worker's snapshot dropped them, so the console showed no price for any Qoder account (Global or CN). - worker/src/catalog.mjs: forward `price_factor`, `is_free`, and `tags`, keeping them absent when upstream omits them so a missing price is never read as 0. - qoder adapter: map them onto the console's `credits`/`free` on both catalog paths (in-process ModelInfos and the legacy worker DisplayCatalog that Qoder actually serves). The free signal follows the Qoder client's own label rule: the `limited_time_free` tag (or a zero factor) marks a model free, and a positive factor is priced. This deliberately does NOT treat a bare `is_free` as free: Qwen3.8-Max reports `is_free: true` alongside `price_factor: 0.5`, and the Qoder client still labels it `0.50x Credit`, so the console now shows a multiplier instead of the contradictory "免费 / x0.5" pair. Verified against a live Qoder CN account: all 14 models report a factor (0/0.1/0.2/0.5/0.6/0.8/1.4); qwen3.8-flash (factor 0) is free, qwen3.8-max (factor 0.5) is priced.
6 tasks done
caigee-cmd
added a commit
that referenced
this pull request
Sep 25, 2026
* feat(qoder): show per-model price and limited-time-free badge Qoder's model catalog carries a per-model `price_factor` (the multiplier its own client renders as `0.50x Credit`) plus an `is_free` flag and a `tags` array, but the worker's snapshot dropped them, so the console showed no price for any Qoder account (Global or CN). - worker/src/catalog.mjs: forward `price_factor`, `is_free`, and `tags`, keeping them absent when upstream omits them so a missing price is never read as 0. - qoder adapter: map them onto the console's `credits`/`free` on both catalog paths (in-process ModelInfos and the legacy worker DisplayCatalog that Qoder actually serves). The free signal follows the Qoder client's own label rule: the `limited_time_free` tag (or a zero factor) marks a model free, and a positive factor is priced. This deliberately does NOT treat a bare `is_free` as free: Qwen3.8-Max reports `is_free: true` alongside `price_factor: 0.5`, and the Qoder client still labels it `0.50x Credit`, so the console now shows a multiplier instead of the contradictory "免费 / x0.5" pair. Verified against a live Qoder CN account: all 14 models report a factor (0/0.1/0.2/0.5/0.6/0.8/1.4); qwen3.8-flash (factor 0) is free, qwen3.8-max (factor 0.5) is priced. * feat(qoder): use upstream per-model context windows Qoder reports a `default_context_window` and a set of `available_context_windows` per model, but the worker only kept `max_input_tokens`, so the console defaulted every Qoder model to a hardcoded 180000 — under-sizing glm-5.3-flash (1M) and over-sizing deepseek-v4-pro (96K). - worker/src/catalog.mjs: forward `default_context_window`, `available_context_windows`, and `max_output_tokens`, absent when upstream omits them. - qoder adapter: map them to `catalog_context_length` (upstream default) and `catalog_context_length_max` (largest selectable window) on both catalog paths, and onto ModelCapabilities.ContextWindow / ContextWindowMax / MaxOutput for the in-process path. - control: prefer the catalog's window over the static fallback in both DecorateModelsWithContext and the per-model setting response, via a new Settings.DefaultContextLength backed by Catalog.ModelContextLength bound during app assembly. DefaultContextForModel stays as the last-resort default when Qoder reports no window. Verified against a live Qoder CN account: qwen3.8-max defaults to 200000 with a 1M max tier, glm-5.3-flash to 1M, deepseek-v4-pro to 96000. * feat(qoder): present context window like Trae's max-context switch Qoder has no upstream is_max_mode flag, so the console showed a raw number input defaulting to a hardcoded 180000. Align Qoder with the existing Trae max-context UX instead: a "default → larger" window with a switch. - control: `decorateQoderContext` mirrors `decorateProviderSettings` — `supports_max_mode` when the catalog advertises a larger tier, `max_mode` derived from the stored window. Qoder settings now read/write the numeric window (Settings.MaxContextLength) so the toggle maps onto the value the adapter already forwards; the static default is only a last resort. - frontend: Qoder models use the same window display + CompactSwitch as Trae with a Qoder-specific hint, and drop the number input / save / reset row. Refs #232 --------- Co-authored-by: BrianBoyCN <175931469+BrianBoyCN@users.noreply.github.com> Co-authored-by: 蔡及 <522caiji@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
在 Qoder(国内版/国际版)的模型列表里显示每个模型的价格与免费标记。
现状
控制台对任何 Qoder 账号都不显示价格。根因是上游给了、worker 丢了:
改动
worker/src/catalog.mjs:透传price_factor/is_free/tags;缺失时保持 absent,避免「没价 = 免费」的误判。internal/providers/qoder/:把三者映射到控制台读的credits/free,覆盖两条目录路径(进程内ModelInfos与 Qoder 实际走的遗留 workerDisplayCatalog)。免费判定对齐 Qoder 客户端自身的标签规则:
即:
limited_time_free标签(或倍率为 0)算免费,正倍率即计费。特意不把裸is_free当免费 ——Qwen3.8-Max上游同时报is_free: true和price_factor: 0.5,Qoder 客户端仍标注0.50x Credit;这样控制台显示的是倍率,而不是自相矛盾的「免费 / x0.5」。真机验证(Qoder CN 账号实测)
14 个模型全部上报
price_factor(0 / 0.1 / 0.2 / 0.5 / 0.6 / 0.8 / 1.4):qwen3.8-flash(倍率 0)→ 免费qwen3.8-max(倍率 0.5,尽管is_free: true)→ 计费,显示x0.5Test plan
go test ./...go vet ./...cd worker && npm testcd frontend && npm run build && npm run lintchangelog/unreleased/qoder-model-credits.md, or this PR has no user-facing change另附:新增单测覆盖价格映射、免费判定(含
is_free+ 正倍率 的双字段情形)与 worker 透传;go test -race ./...、gitleaks本地通过。