1. 11 Aug, 2025 15 commits
  2. 10 Aug, 2025 22 commits
    • 🔧 chore(db): drop legacy single-column UNIQUE indexes to prevent duplicate-key… · 067f3ce9
      🔧 chore(db): drop legacy single-column UNIQUE indexes to prevent duplicate-key errors after soft-delete
      
      Why
      Previous versions created single-column UNIQUE constraints (`models.model_name`, `vendors.name`).
      After introducing composite indexes on `(model_name, deleted_at)` and `(name, deleted_at)` for soft-delete support, those legacy constraints could still exist in user databases.
      When a record was soft-deleted and re-inserted with the same name, MySQL raised `Error 1062 … for key 'models.model_name'`.
      
      What
      • In `migrateDB` and `migrateDBFast` paths of `model/main.go`, proactively drop:
        – `models.uk_model_name` and fallback `models.model_name`
        – `vendors.uk_vendor_name` and fallback `vendors.name`
      • Keeps existing helper `dropIndexIfExists` to ensure the operation is MySQL-only and error-free when indexes are already absent.
      
      Result
      Startup migration now removes every possible legacy UNIQUE index, ensuring composite index strategy works correctly.
      Users can soft-delete and recreate models/vendors with identical names without hitting duplicate-entry errors.
      t0ng7u committed
    • 🤓 chore: format code file · 8d54f862
      t0ng7u committed
    • 🏎️ perf: optimize aggregated model look-ups by batching bound-channel queries · 0bcd7388
      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.
      t0ng7u committed
    • Merge pull request #1547 from seefs001/feature/model_list · 3b6d0d02
       feat: Enhance model listing and retrieval with support for Anthropic and Gemini models; refactor routes for better API key handling
      Seefs committed
    • 🔍 feat: Show matched model names & counts for non-exact model rules · 51f7f891
      Summary
      -------
      1. **Backend**
         • `model/model_meta.go`
           – Add `MatchedModels []string` and `MatchedCount int` (ignored by GORM) to expose matching details in API responses.
         • `controller/model_meta.go`
           – When processing prefix/suffix/contains rules in `fillModelExtra`, collect every matched model name, fill `MatchedModels`, and calculate `MatchedCount`.
      
      2. **Frontend**
         • `web/src/components/table/models/ModelsColumnDefs.js`
           – Import `Tooltip`.
           – Enhance `renderNameRule` to:
             – Display tag text like “前缀 5个模型” for non-exact rules.
             – Show a tooltip listing all matched model names on hover.
      
      Impact
      ------
      Users now see the total number of concrete models aggregated under each prefix/suffix/contains rule and can inspect the exact list via tooltip, improving transparency in model management.
      t0ng7u committed
    • feat: enhance model billing aggregation & UI display for unknown quota type · 85ecfd70
      Summary
      -------
      1. **Backend**
         • `controller/model_meta.go`
           – For prefix/suffix/contains rules, aggregate endpoints, bound channels, enable groups, and quota types across all matched models.
           – When mixed billing types are detected, return `quota_type = -1` (unknown) instead of defaulting to volume-based.
      
      2. **Frontend**
         • `web/src/helpers/utils.js`
           – `calculateModelPrice` now handles `quota_type = -1`, returning placeholder `'-'`.
      
         • `web/src/components/table/model-pricing/view/card/PricingCardView.jsx`
           – Billing tag logic updated: displays “按次计费” (times), “按量计费” (volume), or `'-'` for unknown.
      
         • `web/src/components/table/model-pricing/view/table/PricingTableColumns.js`
           – `renderQuotaType` shows “未知” for unknown billing type.
      
         • `web/src/components/table/models/ModelsColumnDefs.js`
           – Unified `renderQuotaType` to return `'-'` when type is unknown.
      
         • `web/src/components/table/model-pricing/modal/components/ModelPricingTable.jsx`
           – Group price table honors unknown billing type; pricing columns show `'-'` and neutral tag color.
      
      3. **Utilities**
         • Added safe fallback colours/tags for unknown billing type across affected components.
      
      Impact
      ------
      • Ensures correct data aggregation for non-exact model matches.
      • Prevents UI from implying volume billing when actual type is ambiguous.
      • Provides consistent placeholder display (`'-'` or “未知”) across cards, tables and modals.
      
      No breaking API changes; frontend gracefully handles legacy values.
      t0ng7u committed
    • 🔠 refactor: refine group label formatting in price info · 2cabe4f6
      Summary:
      • Updated `helpers/utils.js` to display the “group” label without a colon, ensuring consistent typography with other price elements.
      
      Details:
      1. `formatPriceInfo`
         – Changed `{t('分组')}:` to `{t('分组')}` for a cleaner look.
         – Keeps spacing intact between label and selected group name.
      2. No functional impact; purely visual polish.
      t0ng7u committed
    • 📱 style: Hide vendor introduction on mobile devices · ca85d224
      Summary:
      • Updated `PricingTopSection.jsx` to conditionally render `PricingVendorIntroWithSkeleton` only when `isMobile` is false.
      
      Details:
      1. Wrapped vendor-intro block in `!isMobile` check, preventing unnecessary content on small screens.
      2. Kept desktop experience unchanged; no impact on other features.
      3. Lint check passed with no new issues.
      
      Result:
      Cleaner mobile UI with improved performance and visual focus.
      t0ng7u committed
    • feat: Add tag-based filtering & refactor filter counts logic · b6dd701c
      Overview:
      • Introduced a new “Model Tag” filter across pricing screens
      • Refactored `usePricingFilterCounts` to eliminate duplicated logic
      • Improved tag handling to be case-insensitive and deduplicated
      • Extended utilities to reset & persist the new filter
      
      Details:
      1. Added `filterTag` state to `useModelPricingData` and integrated it into all filtering paths.
      2. Created reusable `PricingTags` component using `SelectableButtonGroup`.
      3. Incorporated tag filter into `PricingSidebar` and mobile `PricingFilterModal`, including reset support.
      4. Enhanced `resetPricingFilters` (helpers/utils) to restore tag filter defaults.
      5. Refactored `usePricingFilterCounts.js`:
         • Centralized predicate `matchesFilters` to remove redundancy
         • Normalized tag parsing via `normalizeTags` helper
         • Memoized model subsets with concise filter calls
      6. Updated lints – zero errors after refactor.
      
      Result:
      Users can now filter models by custom tags with consistent UX, and internal logic is cleaner, faster, and easier to extend.
      t0ng7u committed
    • 🐛 fix(PricingCardView): hide placeholder dash when no custom tags · 7130ec8e
      Previously, the card view displayed a “-” whenever a model had no custom tags,
      because `renderLimitedItems` returned a dash for an empty array.
      Now the function is only invoked when `customTags.length > 0`, removing the
      unwanted placeholder and keeping the UI clean.
      
      File affected:
      - web/src/components/table/model-pricing/view/card/PricingCardView.jsx
      t0ng7u committed
    • fix: prevent model name flicker when closing SideSheet · c79b6cea
      - Delay clearing selectedModel until SideSheet close animation completes
      - Prevents brief display of 'AI/Unknown Model' text during closing transition
      - Improves user experience by eliminating visual flicker
      - Uses 300ms timeout matching Semi UI default animation duration
      t0ng7u committed
    • feat: Enhance EditChannelModal with JSONEditor key updates and input reset · 54f470bc
      - Added unique keys for JSONEditor components to ensure proper re-rendering based on channelId.
      - Implemented input reset to clear previous JSON field values when the modal is opened.
      CaIon committed
    • 🖼️ chore: format code file · 1ea54eb2
      t0ng7u committed
    • feat: Enhance model listing and retrieval with support for Anthropic and… · 4cf1ffa8
       feat: Enhance model listing and retrieval with support for Anthropic and Gemini models; refactor routes for better API key handling
      nekohy committed
    • Merge pull request #1496 from Bliod-Cook/feat-linuxdo-minumum-trust-level · ac9a1ae8
      feat: allow admin to restrict the minimum linuxdo trust level to register
      Calcium-Ion committed
    • Merge pull request #1537 from RedwindA/feat/support-native-gemini-embedding · c59253ea
      feat: 支持原生Gemini Embedding格式
      Calcium-Ion committed
    • Merge pull request #1541 from QuantumNous/fluent-read · 571301ad
      feat: added "流畅阅读" (FluentRead) as a new chat provider option.
      Calcium-Ion committed
  3. 09 Aug, 2025 3 commits
    • feat: Add model icon support across backend and UI; prefer model icon over… · abee65c1
       feat: Add model icon support across backend and UI; prefer model icon over vendor; add icon column in Models table
      
      Backend:
      - Model: Add `icon` field to `model.Model` (gorm: varchar(128)); auto-migrated via GORM.
      - Pricing API: Extend `model.Pricing` with `icon` and populate from model meta in `GetPricing()`.
      
      Frontend:
      - EditModelModal: Add `icon` input (with @lobehub/icons helper link); wire into init/load/submit flows.
      - ModelHeader / PricingCardView: Prefer rendering `model.icon`; fallback to `vendor_icon`; final fallback to initials avatar.
      - Models table: Add leading “Icon” column, rendering `model.icon` or `vendor` icon via `getLobeHubIcon`.
      
      Notes:
      - Backward-compatible. Existing data without `icon` remain unaffected.
      - No manual SQL needed; column is added by AutoMigrate.
      
      Affected files:
      - model/model_meta.go
      - model/pricing.go
      - web/src/components/table/models/modals/EditModelModal.jsx
      - web/src/components/table/model-pricing/modal/components/ModelHeader.jsx
      - web/src/components/table/model-pricing/view/card/PricingCardView.jsx
      - web/src/components/table/models/ModelsColumnDefs.js
      t0ng7u committed
    • feat: Support dot‑chained props for LobeHub icons · 734ef7dd
      - render.js: Enhance getLobeHubIcon to parse dot‑chained props, e.g.:
        - OpenAI.Avatar.type={'platform'}
        - OpenRouter.Avatar.shape={'square'}
        - Parses booleans/numbers/strings and {…} wrappers; keeps the 2nd arg `size` unless overridden by chain props. Backward compatible.
      - EditVendorModal.jsx: Update UI copy — simplify placeholder; document chain‑parameter examples in extra text with doc link.
      - en.json: Fix invalid escape sequences in the new i18n string to satisfy linter.
      
      No behavioral changes outside icon rendering; lints pass.
      t0ng7u committed
    • 🍎 chore: modify pagination pageSizeOpts · 58af8ed6
      t0ng7u committed