🐛 fix(pricing): sync currently exposed CPA runtime models before first use (#515) - #792
Merged
Merged
Conversation
…t use (#515) Prior to this fix, model price sync only covered saved prices and models present in usage summary history. Newly exposed CPA models that hadn't recorded usage yet did not receive pricing in advance, requiring users to manually sync prices again after their first usage. - Fetch management API keys and runtime models via CPA `/v0/management/api-keys` and `/v1/models` in CPA client - Discover runtime models with independent 5s timeout in Manager Server model price service - Extend price sync scope to `effectiveModels = knownModels ∪ runtimeModels` when `includeRuntimeModels: true` - Implement safe no-op when `includeRuntimeModels: true` and effective models are empty, preventing unintentional catalog imports - Preserve legacy empty-models sync semantics when `includeRuntimeModels` is false or omitted - Maintain manual price priority and preferred-source failure preservation across effective models - Remove empty sync models preflight in ModelPricesPage to allow zero-history deployments to sync runtime models - Handle 4-state feedback (success, discovery failure fallback with known models, discovery failure with empty known models, zero models found) - Update i18n locales across zh-CN, zh-TW, en, and ru - Add end-to-end unit and regression tests for CPA client, model price service, and frontend feedback resolution Risk / impact: Low. Runtime discovery is best-effort and safe-no-op protected; does not expose CPA API keys, alter public proxy auth, or require database migrations.
This was referenced Sep 16, 2026
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.
Summary
Fixes #515 where model price sync previously only covered saved prices and models present in usage summary history. As a result, newly exposed CPA models that had not yet recorded any requests did not receive pricing in advance, requiring users to manually sync prices again after their first usage.
Scope
Changes
client.go,client_test.go):FetchAPIKeysto read client API keys via/v0/management/api-keys, trimming and deduplicating keys while preserving configured order.FetchModelsto retrieve model IDs via/v1/models, parsing OpenAI-compatibledata[].id, deduplicating, sorting stably, and supporting anonymous access without sending authorization when keys are omitted.service.go,service_test.go):IncludeRuntimeModelsboolean flag toSyncRequestto maintain backward compatibility.discoverRuntimeModelshelper with dedicated 5s timeout (defaultRuntimeModelDiscoveryTimeout), resolving CPA upstream credentials and querying models best-effort.effectiveModels = knownModels ∪ runtimeModelswhenIncludeRuntimeModels: true.IncludeRuntimeModels: trueandeffectiveModelsis empty, safely return current prices without hitting price sources, strictly preventing unintentional catalog imports via legacyselectAllUnambiguousModelPrices().effectiveModelsacross the entire pipeline: price fetching, collection selection, andpreserveFailedSourcePrices.RuntimeModelCountand sanitizedRuntimeModelDiscoveryErrortoSyncResult.usageService.ts,useUsageData.ts):ModelPriceSyncRequestandModelPriceSyncResponsetypes.{ includeRuntimeModels: true }insyncModelPrices.ModelPricesPage.tsx,modelPriceSyncFeedback.ts):includeRuntimeModels: truewhen clicking sync on the price page.zh-CN.json,zh-TW.json,en.json,ru.json):sync_idleandsync_model_countto reflect recorded and available CPA models.sync_runtime_discovery_failed_fallbackandsync_runtime_discovery_failed_emptyacross all 4 locales.User Impact
Users clicking "Sync Prices" can now automatically retrieve and sync prices for newly configured CPA models before they are invoked for the first time. Zero-history fresh installations can also immediately sync prices. If CPA is temporarily unreachable, price sync safely falls back to known models with a clear warning rather than failing completely.
Compatibility / Runtime Notes
/v0/management/model-prices/syncwithincludeRuntimeModels: falseor omitted maintains legacy behavior./modelsproxy authentication semantics remain unchanged.Data / Security Notes
source: manual) remain strictly protected against automatic overwrites.Risk / Rollback
Risk level: Low
Rollback notes: Reverting the commit restores previous price sync behavior targeting recorded models only.
Verification
Commands / evidence:
Screenshots / Recordings
N/A — Backend model price discovery and frontend sync feedback notification verified by comprehensive unit and integration tests.
Docs
Docs decision:
No user-facing documentation structure changes required for runtime model price synchronization scope expansion.
Related
Closes #515