Skip to content

🐛 fix(pricing): sync currently exposed CPA runtime models before first use (#515) - #792

Merged
seakee merged 1 commit into
devfrom
fix/515-runtime-model-price-sync
Sep 16, 2026
Merged

seakee merged 1 commit into
devfrom
fix/515-runtime-model-price-sync

Conversation

@seakee

@seakee seakee commented Sep 16, 2026

Copy link
Copy Markdown
Owner

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

  • Frontend panel
  • Manager Server
  • CPA panel mode
  • Full Docker mode
  • Native packages / release
  • Docs / Wiki
  • CI / build / tooling

Changes

  • CPA Client Extensions (client.go, client_test.go):
    • Add FetchAPIKeys to read client API keys via /v0/management/api-keys, trimming and deduplicating keys while preserving configured order.
    • Add FetchModels to retrieve model IDs via /v1/models, parsing OpenAI-compatible data[].id, deduplicating, sorting stably, and supporting anonymous access without sending authorization when keys are omitted.
  • Runtime Discovery & Effective Scope (service.go, service_test.go):
    • Add IncludeRuntimeModels boolean flag to SyncRequest to maintain backward compatibility.
    • Add discoverRuntimeModels helper with dedicated 5s timeout (defaultRuntimeModelDiscoveryTimeout), resolving CPA upstream credentials and querying models best-effort.
    • Construct effectiveModels = knownModels ∪ runtimeModels when IncludeRuntimeModels: true.
    • Safe No-op: When IncludeRuntimeModels: true and effectiveModels is empty, safely return current prices without hitting price sources, strictly preventing unintentional catalog imports via legacy selectAllUnambiguousModelPrices().
    • Propagate effectiveModels across the entire pipeline: price fetching, collection selection, and preserveFailedSourcePrices.
    • Add RuntimeModelCount and sanitized RuntimeModelDiscoveryError to SyncResult.
  • Frontend API & Hooks (usageService.ts, useUsageData.ts):
    • Update ModelPriceSyncRequest and ModelPriceSyncResponse types.
    • Support { includeRuntimeModels: true } in syncModelPrices.
  • Model Prices Page & UI Feedback (ModelPricesPage.tsx, modelPriceSyncFeedback.ts):
    • Remove preflight check that prevented empty sync models list from triggering API calls, enabling zero-history deployments to discover runtime models.
    • Always enable includeRuntimeModels: true when clicking sync on the price page.
    • Handle all 4 sync feedback outcomes (A: success; B: runtime discovery error fallback with known models; C: runtime discovery error with zero known models; D: runtime discovery success with zero discovered models).
  • Internationalization (zh-CN.json, zh-TW.json, en.json, ru.json):
    • Update sync_idle and sync_model_count to reflect recorded and available CPA models.
    • Add sync_runtime_discovery_failed_fallback and sync_runtime_discovery_failed_empty across all 4 locales.
  • Verification Tests:
    • CPA client unit tests (API keys, models with key, anonymous models).
    • Backend integration tests (union sync, zero-history runtime sync, discovery failure fallback, safe no-op on failure with empty known models, legacy empty models compatibility, manual price protection, preferred source failure preservation).
    • Frontend unit tests for feedback resolution and API serialization.

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

  • CPA panel mode: Fully compatible.
  • Manager Server mode: Fully compatible.
  • Full Docker / native packages: Fully compatible.
  • Backward Compatibility: Calling /v0/management/model-prices/sync with includeRuntimeModels: false or omitted maintains legacy behavior.
  • Security: CPA Client API keys and management keys are never exposed to the browser or returned in API responses. Public /models proxy authentication semantics remain unchanged.
  • No database migrations, background schedulers, or model registries introduced.

Data / Security Notes

  • No secrets logged or persisted.
  • Manual prices (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

  • Type check
  • Lint
  • Tests
  • Build
  • Manual UI check
  • Docs/link check
  • Not applicable, docs-only

Commands / evidence:

npm run manager-server:test — passed (all Go tests pass)
npm run test:web — passed (226 test files, 3,484 tests pass)
npm run type-check — passed (0 errors)
npm run lint — passed (0 errors)
npm run build — passed (dist/index.html singlefile built)

Screenshots / Recordings

N/A — Backend model price discovery and frontend sync feedback notification verified by comprehensive unit and integration tests.

Docs

  • README / README_CN updated for user-visible capabilities
  • Matching docs manual and navigation updated
  • Demo fixtures, screenshots, and deep links reviewed
  • Release notes needed
  • Not needed — explanation included below

Docs decision:
No user-facing documentation structure changes required for runtime model price synchronization scope expansion.

Related

Closes #515

…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.
@seakee
seakee merged commit cb3b09c into dev Sep 16, 2026
15 of 20 checks passed
@seakee
seakee deleted the fix/515-runtime-model-price-sync branch September 16, 2026 16:33
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.

1 participant