Replace legacy single-column unique indexes with composite unique indexes on
(name, deleted_at) and introduce a safe index drop utility to eliminate
duplicate-key errors and noisy MySQL 1091 warnings.
WHAT
• model/model_meta.go
- Model.ModelName → `uniqueIndex:uk_model_name,priority:1`
- Model.DeletedAt → `index; uniqueIndex:uk_model_name,priority:2`
• model/vendor_meta.go
- Vendor.Name → `uniqueIndex:uk_vendor_name,priority:1`
- Vendor.DeletedAt → `index; uniqueIndex:uk_vendor_name,priority:2`
• model/main.go
- Add `dropIndexIfExists(table, index)`:
• Checks `information_schema.statistics`
• Drops index only when present (avoids Error 1091)
- Invoke helper in `migrateDB` & `migrateDBFast`
- Remove direct `ALTER TABLE … DROP INDEX …` calls
WHY
• Users received `Error 1062 (23000)` when re-creating a soft-deleted
model/vendor because the old unique index enforced uniqueness on name alone.
• Directly dropping nonexistent indexes caused MySQL `Error 1091` noise.
HOW
• Composite unique indexes `(model_name, deleted_at)` / `(name, deleted_at)`
respect GORM soft deletes.
• Safe helper ensures idempotent migrations across environments.
RESULT
• Users can now delete and re-add the same model or vendor without manual SQL.
• Startup migration runs quietly across MySQL, PostgreSQL, and SQLite.
• No behavior changes for existing data beyond index updates.
TEST
1. Add model “deepseek-chat” → delete (soft) → re-add → success.
2. Add vendor “DeepSeek” → delete (soft) → re-add → success.
3. Restart service twice → no duplicate key or 1091 errors.
Ensure models and vendors can be re-created after soft deletion by switching to composite unique indexes on (name, deleted_at) and cleaning up legacy single-column unique indexes on MySQL.
Why
- MySQL raised 1062 duplicate key errors when re-adding a soft-deleted model/vendor because the legacy unique index enforced uniqueness on the name column alone (uk_model_name / uk_vendor_name), despite soft deletes.
- Users encountered errors such as:
- Error 1062 (23000): Duplicate entry 'deepseek-chat' for key 'models.uk_model_name'
- Error 1062 (23000): Duplicate entry 'DeepSeek' for key 'vendors.uk_vendor_name'
How
- Model indices:
- model/model_meta.go:
- Model.ModelName → gorm: uniqueIndex:uk_model_name,priority:1
- Model.DeletedAt → gorm: index; uniqueIndex:uk_model_name,priority:2
- Vendor indices:
- model/vendor_meta.go:
- Vendor.Name → gorm: uniqueIndex:uk_vendor_name,priority:1
- Vendor.DeletedAt → gorm: index; uniqueIndex:uk_vendor_name,priority:2
- Migration (automatic, idempotent):
- model/main.go (migrateDB, migrateDBFast):
- On MySQL, drop legacy single-column unique indexes if present:
- ALTER TABLE models DROP INDEX uk_model_name;
- ALTER TABLE vendors DROP INDEX uk_vendor_name;
- Then run AutoMigrate to create composite unique indexes.
- Missing-index errors are ignored to keep the migration safe to run multiple times.
Result
- Users can delete and re-add the same model/vendor name without manual SQL.
- Migration runs automatically at startup; no user action required.
- PostgreSQL and SQLite remain unaffected.
Files changed
- model/model_meta.go
- model/vendor_meta.go
- model/main.go (migrateDB, migrateDBFast)
Testing
- Create model "deepseek-chat" → delete (soft) → re-create → succeeds.
- Create vendor "DeepSeek" → delete (soft) → re-create → succeeds.
Backward compatibility
- Data remains intact; only index definitions are updated.
- Behavior is unchanged except for fixing the uniqueness constraint with soft deletes.
- Add new PrefillGroup model with CRUD operations
* Support for model, tag, and endpoint group types
* JSON storage for group items with GORM datatypes
* Automatic database migration support
- Implement backend API endpoints
* GET /api/prefill_group - List groups by type with admin auth
* POST /api/prefill_group - Create new groups
* PUT /api/prefill_group - Update existing groups
* DELETE /api/prefill_group/:id - Delete groups
- Add comprehensive frontend management interface
* PrefillGroupManagement component for group listing
* EditPrefillGroupModal for group creation/editing
* Integration with EditModelModal for auto-filling
* Responsive design with CardTable and SideSheet
- Enhance model editing workflow
* Tag group selection with auto-fill functionality
* Endpoint group selection with auto-fill functionality
* Seamless integration with existing model forms
- Create reusable UI components
* Extract common rendering utilities to models/ui/
* Shared renderLimitedItems and renderDescription functions
* Consistent styling across all model-related components
- Improve user experience
* Empty state illustrations matching existing patterns
* Fixed column positioning for operation buttons
* Item content display with +x indicators for overflow
* Tooltip support for long descriptions
Backend
• Add `model/model_meta.go` and `model/vendor_meta.go` defining Model & Vendor entities with CRUD helpers, soft-delete and time stamps
• Create corresponding controllers `controller/model_meta.go`, `controller/vendor_meta.go` and register routes in `router/api-router.go`
• Auto-migrate new tables in DB startup logic
Frontend
• Build complete “Model Management” module under `/console/models`
- New pages, tables, filters, actions, hooks (`useModelsData`) and dynamic vendor tabs
- Modals `EditModelModal.jsx` & unified `EditVendorModal.jsx`; latter now uses default confirm/cancel footer and mobile-friendly modal sizing (`full-width` / `small`) via `useIsMobile`
• Update sidebar (`SiderBar.js`) and routing (`App.js`) to surface the feature
• Add helper updates (`render.js`) incl. `stringToColor`, dynamic LobeHub icon retrieval, and tag color palettes
Table UX improvements
• Replace separate status column with inline Enable / Disable buttons in operation column (matching channel table style)
• Limit visible tags to max 3; overflow represented as “+x” tag with padded `Popover` showing remaining tags
• Color all tags deterministically using `stringToColor` for consistent theming
• Change vendor column tag color to white for better contrast
Misc
• Minor layout tweaks, compact-mode toggle relocation, lint fixes and TypeScript/ESLint clean-up
These changes collectively deliver end-to-end model & vendor administration while unifying visual language across management tables.
- Change `ModelMapping` column type from varchar(1024) to TEXT in channels table
- Add MySQL migration script to alter column type during database initialization
- Improve database schema flexibility for storing complex model mappings