Frontend (web)
- ModelsActions.jsx
- Replace “Sync Official” with “Sync” and open a new two-step SyncWizard.
- Pass selected locale through to preview, sync, and overwrite flows.
- Keep conflict resolution flow; inject locale into overwrite submission.
- New: models/modals/SyncWizardModal.jsx
- Two-step wizard: (1) method selection (config-sync disabled for now), (2) language selection (en/zh/ja).
- Horizontal, centered Radio cards; returns { option, locale } via onConfirm.
- UpstreamConflictModal.jsx
- Add search input (model fuzzy search) and native pagination.
- Column header checkbox now only applies to rows in the current filtered result.
- Fix “Cannot access ‘filteredDataSource’ before initialization”.
- Refactor with useMemo/useCallback; extract helpers to remove duplicated logic:
- getPresentRowsForField, getHeaderState, applyHeaderChange
- Minor code cleanups and stability improvements.
- i18n (en.json)
- Add strings for the sync wizard and related actions (Sync, Sync Wizard, Select method/source/language, etc.).
- Adjust minor translations.
Hooks
- useModelsData.jsx
- Extend previewUpstreamDiff, syncUpstream, applyUpstreamOverwrite to accept options with locale.
- Send locale via query/body accordingly.
Backend (Go)
- controller/model_sync.go
- Accept locale from query/body and resolve i18n upstream URLs.
- Add SYNC_UPSTREAM_BASE for upstream base override (default: https://basellm.github.io/llm-metadata).
- Make HTTP timeouts/retries/limits configurable:
- SYNC_HTTP_TIMEOUT_SECONDS, SYNC_HTTP_RETRY, SYNC_HTTP_MAX_MB
- Add ETag-based caching and support both envelope and pure array JSON formats.
- Concurrently fetch vendors and models; improve error responses with locale and source URLs.
- Include source meta (locale, models_url, vendors_url) in success payloads.
Notes
- No breaking changes expected.
- Lint passes for touched files.
Backend (controller/ratio_sync.go):
- Add built‑in official upstream to GetSyncableChannels (ID: -100, BaseURL: https://basellm.github.io)
- Support absolute endpoint URLs; otherwise join BaseURL + endpoint (defaults to /api/ratio_config)
- Harden HTTP client:
- IPv4‑first with IPv6 fallback for github.io
- Add ResponseHeaderTimeout
- 3 attempts with exponential backoff (200/400/800ms)
- Validate Content-Type and limit response body to 10MB (safe decode via io.LimitReader)
- Robust parsing: support type1 ratio_config map and type2 pricing list
- Use net.SplitHostPort for host parsing
- Use float tolerance in differences comparison to avoid false mismatches
- Remove unused code (tryDirect) and improve warnings
Frontend:
- UpstreamRatioSync.jsx: auto-assign official endpoint to /llm-metadata/api/newapi/ratio_config-v1-base.json
- ChannelSelectorModal.jsx:
- Pin the official source at the top of the list
- Show a green “官方” tag next to the status
- Refactor status renderer to accept the full record
Notes:
- Backward compatible; no API surface changes
- Official ratio_config reference: https://basellm.github.io/llm-metadata/api/newapi/ratio_config-v1-base.json
- Apply canonical Go formatting to all .go files
- No functional changes; whitespace/import/struct layout only
- Improves consistency, reduces diff noise, and aligns with standard tooling
This commit introduces a new function, MaskEmail, to mask user email addresses in logs, preventing PII leakage. Additionally, the RelayInfo logging has been updated to utilize this new masking function, ensuring sensitive information is properly handled. The channel test logic has also been improved to dynamically determine the relay format based on the request path.
This commit refactors the logging mechanism across the application by replacing direct logger calls with a centralized logging approach using the `common` package. Key changes include:
- Replaced instances of `logger.SysLog` and `logger.FatalLog` with `common.SysLog` and `common.FatalLog` for consistent logging practices.
- Updated resource initialization error handling to utilize the new logging structure, enhancing maintainability and readability.
- Minor adjustments to improve code clarity and organization throughout various modules.
This change aims to streamline logging and improve the overall architecture of the codebase.
This commit introduces a major architectural refactoring to improve quota management, centralize logging, and streamline the relay handling logic.
Key changes:
- **Pre-consume Quota:** Implements a new mechanism to check and reserve user quota *before* making the request to the upstream provider. This ensures more accurate quota deduction and prevents users from exceeding their limits due to concurrent requests.
- **Unified Relay Handlers:** Refactors the relay logic to use generic handlers (e.g., `ChatHandler`, `ImageHandler`) instead of provider-specific implementations. This significantly reduces code duplication and simplifies adding new channels.
- **Centralized Logger:** A new dedicated `logger` package is introduced, and all system logging calls are migrated to use it, moving this responsibility out of the `common` package.
- **Code Reorganization:** DTOs are generalized (e.g., `dalle.go` -> `openai_image.go`) and utility code is moved to more appropriate packages (e.g., `common/http.go` -> `service/http.go`) for better code structure.
Backend
- Add GetBoundChannelsByModelsMap to batch-fetch bound channels via a single JOIN (Distinct), compatible with SQLite/MySQL/PostgreSQL
- Replace per-record enrichment with a single-pass enrichModels to avoid N+1 queries; compute unions for prefix/suffix/contains matches in memory
- Change Model.QuotaType to QuotaTypes []int and expose quota_types in responses
- Add GetModelQuotaTypes for cached O(1) lookups; exact models return a single-element array
- Sort quota_types for stable output order
- Remove unused code: GetModelByName, GetBoundChannels, GetBoundChannelsForModels, FindModelByNameWithRule, buildPrefixes, buildSuffixes
- Clean up redundant comments, keeping concise and readable code
Frontend
- Models table: switch to quota_types, render multiple billing modes ([0], [1], [0,1], future values supported)
- Pricing table: switch to quota_types; ratio display now checks quota_types.includes(0); array rendering for billing tags
Compatibility
- SQL uses standard JOIN/IN/Distinct; works across SQLite/MySQL/PostgreSQL
- Lint passes; no DB schema changes (quota_types is a JSON response field only)
Breaking Change
- API field renamed: quota_type -> quota_types (array). Update clients accordingly.
Summary
-------
1. **Backend**
• `model/model_meta.go`
– Add `GetBoundChannelsForModels([]string)` to retrieve channels for multiple models in a single SQL (`IN (?)`) and deduplicate with `GROUP BY`.
• `controller/model_meta.go`
– In non-exact `fillModelExtra`:
– Remove per-model `GetBoundChannels` calls.
– Collect matched model names, then call `GetBoundChannelsForModels` once and merge results into `channelSet`.
– Minor cleanup on loop logic; channel aggregation now happens after quota/group/endpoint processing.
Impact
------
• Eliminates N+1 query pattern for prefix/suffix/contains rules.
• Reduces DB round-trips from *N + 1* to **1**, markedly speeding up the model-management list load.
• Keeps existing `GetBoundChannels` API intact for single-model scenarios; no breaking changes.