feat: add combo routing - #5443
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (27)
✅ Files skipped from review due to trivial changes (7)
🚧 Files skipped from review as they are similar to previous changes (19)
WalkthroughImplements combo-based multi-model routing: DB model and migrations, Gin CRUD/search API, strategy resolver and request rewriting in distributor middleware, plus a React admin UI with routes, sidebar, and i18n. ChangesCombo Multi-Model Routing
Sequence DiagramsequenceDiagram
participant User
participant Frontend
participant Distributor
participant Service
participant DB
participant ChannelProvider
User->>Frontend: request with model="combo:mycombo"
Frontend->>Distributor: send request
Distributor->>DB: GetComboByNameUserId / GetComboByName
Distributor->>Service: ResolveComboModel(combo, tokenGroup)
Service->>DB: query channels / models as needed
Service-->>Distributor: ComboRoutingResult { model, channel?, group? }
Distributor->>Distributor: RewriteRequestBodyModel -> model = resolved model
Distributor->>ChannelProvider: forward to selected channel (if any) / continue selection
ChannelProvider-->>User: response from resolved downstream model
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 17
🧹 Nitpick comments (8)
controller/combo.go (2)
48-48: 💤 Low valueRedundant CreatedTime assignment.
Line 48 manually sets
combo.CreatedTime = time.Now().Unix(), butcombo.Insert()on line 50 already setsCreatedTimeinternally (seemodel/combo.goline 28). This assignment is unnecessary and will be overwritten.🧹 Proposed cleanup
userId := c.GetInt("id") combo.UserId = userId combo.Status = 1 - combo.CreatedTime = time.Now().Unix() if err := combo.Insert(); err != nil {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@controller/combo.go` at line 48, Redundant assignment: remove the manual setting of combo.CreatedTime (the line assigning combo.CreatedTime = time.Now().Unix()) since combo.Insert() already initializes CreatedTime internally; update the controller method that calls combo.Insert() (referencing combo.CreatedTime and the combo.Insert() call) to delete that assignment and rely on the model implementation in model/combo.go to set CreatedTime.
34-34: ⚡ Quick winConsider extracting strategy validation to a constant or helper.
The strategy validation on line 34 uses hardcoded string literals repeated inline. For better maintainability and to avoid typos, consider defining allowed strategies as a package-level constant slice and using a helper function for validation.
♻️ Example refactor
var allowedStrategies = []string{"fallback", "random", "weighted", "round_robin"} func isValidStrategy(s string) bool { for _, valid := range allowedStrategies { if s == valid { return true } } return false }Then replace line 34:
- if combo.Strategy != "fallback" && combo.Strategy != "random" && combo.Strategy != "weighted" && combo.Strategy != "round_robin" { + if !isValidStrategy(combo.Strategy) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@controller/combo.go` at line 34, Extract the inline strategy check into a package-level allowedStrategies slice and a helper isValidStrategy(s string) bool, then replace the long condition that reads combo.Strategy != "fallback" && ... with a call to isValidStrategy(combo.Strategy); ensure allowedStrategies contains "fallback", "random", "weighted", "round_robin" and update the validation logic in the function/method that reads combo.Strategy to use isValidStrategy.web/default/src/features/combos/components/combos-multi-delete-dialog.tsx (2)
36-43: ⚡ Quick winAvoid destructuring component props.
The component destructures props
open,onOpenChange, andselectedIds. As per coding guidelines, useprops.open,props.onOpenChange, andprops.selectedIdsdirectly instead for clarity and consistency.♻️ Proposed refactor
export function CombosMultiDeleteDialog({ - open, - onOpenChange, - selectedIds, -}: { + props +}: props: { open: boolean onOpenChange: (open: boolean) => void selectedIds: number[] }) { const { t } = useTranslation() const { triggerRefresh } = useCombos() const [isDeleting, setIsDeleting] = useState(false) const handleDelete = async () => { setIsDeleting(true) try { - await Promise.all(selectedIds.map((id) => deleteCombo(id))) + await Promise.all(props.selectedIds.map((id) => deleteCombo(id))) toast.success(t(SUCCESS_MESSAGES.COMBO_BATCH_DELETED)) triggerRefresh() - onOpenChange(false) + props.onOpenChange(false) } catch { toast.error(t(ERROR_MESSAGES.UNEXPECTED)) } finally { setIsDeleting(false) } } return ( - <AlertDialog open={open} onOpenChange={onOpenChange}> + <AlertDialog open={props.open} onOpenChange={props.onOpenChange}> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle>{t('Are you sure?')}</AlertDialogTitle> <AlertDialogDescription> {t('This will permanently delete')} {selectedIds.length}{' '} - {selectedIds.length === 1 ? t('combo') : t('combos')} + {props.selectedIds.length === 1 ? t('combo') : t('combos')} .{t(' This action cannot be undone.')} </AlertDialogDescription>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-multi-delete-dialog.tsx` around lines 36 - 43, The component CombosMultiDeleteDialog currently destructures props (open, onOpenChange, selectedIds); change it to use the props object instead to follow guidelines—replace destructuring in the function signature and all internal references so they read props.open, props.onOpenChange, and props.selectedIds, ensuring the prop type annotation remains intact for the function parameter.Source: Coding guidelines
49-61: ⚖️ Poor tradeoffConsider handling partial deletion failures gracefully.
Promise.allfails atomically—if any single delete fails, the entire operation is rejected and the user sees a generic error. Users cannot tell which combos failed or succeeded. Consider usingPromise.allSettledto track individual results and show a more informative toast indicating partial success/failure counts.♻️ Proposed enhancement
const handleDelete = async () => { setIsDeleting(true) try { - await Promise.all(selectedIds.map((id) => deleteCombo(id))) - toast.success(t(SUCCESS_MESSAGES.COMBO_BATCH_DELETED)) + const results = await Promise.allSettled( + selectedIds.map((id) => deleteCombo(id)) + ) + const succeeded = results.filter((r) => r.status === 'fulfilled').length + const failed = results.filter((r) => r.status === 'rejected').length + if (failed === 0) { + toast.success(t(SUCCESS_MESSAGES.COMBO_BATCH_DELETED)) + } else if (succeeded > 0) { + toast.warning(`${succeeded} deleted, ${failed} failed`) + } else { + toast.error(t(ERROR_MESSAGES.UNEXPECTED)) + } triggerRefresh() onOpenChange(false) } catch { toast.error(t(ERROR_MESSAGES.UNEXPECTED)) } finally { setIsDeleting(false) } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-multi-delete-dialog.tsx` around lines 49 - 61, The handleDelete function currently uses Promise.all so any single deleteCombo(id) rejection shows a generic error; change it to use Promise.allSettled(selectedIds.map(id => deleteCombo(id))) in handleDelete, then count fulfilled vs rejected results, show a toast reflecting full success, partial success (e.g., "X deleted, Y failed"), or full failure, and optionally include/log the failed ids; still call triggerRefresh() after successful deletions and setIsDeleting(false) in finally, and keep invoking onOpenChange(false) only when at least one delete succeeded (or per your UX decision).web/default/src/features/combos/components/combos-provider.tsx (1)
35-35: ⚡ Quick winAvoid destructuring component props.
The component destructures
childrenfrom props. As per coding guidelines, useprops.childrendirectly instead for clarity and consistency.♻️ Proposed refactor
-export function CombosProvider({ children }: { children: React.ReactNode }) { +export function CombosProvider(props: { children: React.ReactNode }) { const [open, setOpen] = React.useState<ComboDialogType | null>(null) const [currentRow, setCurrentRow] = React.useState<Combo | null>(null) const [refreshTrigger, setRefreshTrigger] = React.useState(0) const triggerRefresh = useCallback(() => { setRefreshTrigger((v) => v + 1) }, []) return ( <CombosContext.Provider value={{ open, setOpen, currentRow, setCurrentRow, refreshTrigger, triggerRefresh, }} > - {children} + {props.children} </CombosContext.Provider> ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-provider.tsx` at line 35, The CombosProvider component currently destructures children in its parameter list; change the component to accept a single props parameter (e.g., props: { children: React.ReactNode }) and update the implementation to reference props.children instead of the destructured children variable so the component follows the project's non-destructuring props convention (locate the CombosProvider function declaration and any usage of children inside it and replace accordingly).Source: Coding guidelines
web/default/src/features/combos/components/combos-columns.tsx (2)
54-96: ⚡ Quick winConsider using hierarchical i18n keys for table headers.
The column headers use flat keys like
t('Name'),t('Models'), which may conflict with other features and are less maintainable. As per coding guidelines, translation keys should be hierarchical and semantically clear (e.g.,dashboard.overview.title). Consider using keys liket('combos.table.name'),t('combos.table.models'), etc.♻️ Example refactor to hierarchical keys
header: ({ column }) => ( - <DataTableColumnHeader column={column} title={t('Name')} /> + <DataTableColumnHeader column={column} title={t('combos.table.name')} /> ),Apply similar changes to 'Models', 'Strategy', 'Status', and 'Created At' headers.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-columns.tsx` around lines 54 - 96, Update the hardcoded flat i18n keys used in the DataTableColumnHeader calls to hierarchical, semantically-scoped keys; replace t('Name'), t('Models'), t('Strategy'), t('Status'), and t('Created At') with keys like t('combos.table.name'), t('combos.table.models'), t('combos.table.strategy'), t('combos.table.status'), and t('combos.table.createdAt') respectively in the combos-columns component where DataTableColumnHeader is rendered (refer to the column definitions using accessorKey 'name', 'models', 'strategy', 'status', 'created_time' and the StrategyCell/StatusCell usages) so translations are organized and unambiguous.Source: Coding guidelines
98-102: ⚡ Quick winConsider locale-aware date formatting.
The
.toLocaleString()method without a locale parameter uses the browser's default locale, which may not match the user's selected language in the application. Consider passing the current i18n locale to ensure consistent date formatting.♻️ Example using i18n locale
+import { useTranslation } from 'react-i18next' + export function useCombosColumns(): ColumnDef<Combo>[] { - const { t } = useTranslation() + const { t, i18n } = useTranslation() return [ // ... { accessorKey: 'created_time', header: ({ column }) => ( <DataTableColumnHeader column={column} title={t('Created At')} /> ), cell: ({ row }) => { const time = row.getValue('created_time') as number | null if (!time) return '-' - return new Date(time * 1000).toLocaleString() + return new Date(time * 1000).toLocaleString(i18n.language) }, size: 160, },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-columns.tsx` around lines 98 - 102, The date cell renderer in combos-columns.tsx (cell: ({ row }) => { ... }) uses toLocaleString() without specifying a locale; update the cell implementation to retrieve the app's current i18n locale (e.g., from i18n.language or the app's locale context) and pass it as the first argument to Date.prototype.toLocaleString so the created_time display respects the user's selected language/locale; ensure you still handle null/undefined created_time and convert the epoch seconds (time * 1000) before formatting.web/default/src/features/combos/components/combos-table.tsx (1)
90-96: ⚡ Quick winConsider using hierarchical i18n keys.
Similar to the columns file, these UI strings use flat keys like
t('No Combos Found'),t('Search combos...'). As per coding guidelines, translation keys should be hierarchical (e.g.,t('combos.empty.title'),t('combos.search.placeholder')).♻️ Example refactor to hierarchical keys
emptyTitle={t('combos.empty.title')} emptyDescription={t('combos.empty.description')} // ... <Input - placeholder={t('Search combos...')} + placeholder={t('combos.search.placeholder')} value={globalFilter ?? ''} onChange={(e) => onGlobalFilterChange(e.target.value)} className='max-w-sm' />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-table.tsx` around lines 90 - 96, The UI strings in combos-table.tsx are using flat i18n keys (e.g., t('No Combos Found'), t('Search combos...')) — update the calls to use hierarchical keys such as t('combos.empty.title'), t('combos.empty.description'), and t('combos.search.placeholder') in the emptyTitle, emptyDescription and Input placeholder props (within the renderToolbar block), and ensure corresponding entries are added/updated in the translation resource files for all supported locales so the new keys resolve at runtime.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@model/combo.go`:
- Around line 111-118: DeleteComboById currently calls DB.Delete immediately
then reassigns query, causing two deletes; change it to build the query first
(e.g., use DB.Model(&Combo{}) or DB.Unscoped()/DB.Session if needed) so no
delete is executed on initialization, then conditionally add the user scoping
with Where("user_id = ?", userId[0]) on the same query, and finally call
query.Delete(&Combo{}, "id = ?", id) once; update the query variable in the
DeleteComboById function and ensure you return query.Error.
In `@model/main.go`:
- Line 284: migrateDBFast() is missing the Combo model in its migrations slice
causing the combos table to be skipped; update the migrations slice inside
migrateDBFast() to include &Combo{} just like migrateDB() does (or if
migrateDBFast() is intentionally deprecated, remove/mark it accordingly). Locate
the migrations []interface{} declaration in migrateDBFast() and add &Combo{} to
that list so the Combo model is created/migrated when migrateDBFast() runs.
In `@service/combo_routing.go`:
- Around line 184-191: The global comboRoundRobinCounters map is accessed
concurrently in resolveRoundRobin (comboRoundRobinCounters and combo.Id),
causing race conditions; protect it by introducing synchronization: add a
package-level sync.Mutex (e.g., comboRRMutex) and wrap the read-modify-write and
subsequent read (the increment and idx calculation inside resolveRoundRobin)
with comboRRMutex.Lock()/Unlock(), ensuring you increment the counter and
compute idx while holding the lock and return &ComboRoutingResult{ResolvedModel:
models[idx]}; alternatively replace comboRoundRobinCounters with a sync.Map and
perform atomic load/store semantics, but ensure the resolveRoundRobin logic
updates and reads the counter atomically.
- Line 159: Replace the direct use of encoding/json's json.Unmarshal in
combo_routing.go (the call json.Unmarshal([]byte(weightsStr), &parsed) that
deserializes weightsStr into parsed) with the project's wrapper common.Unmarshal
to enforce consistent JSON handling (i.e., call common.Unmarshal with the same
input/target used previously). After changing the call, remove the
"encoding/json" import if it becomes unused. Ensure you update the call site
referencing weightsStr and parsed so compilation and behavior remain equivalent.
In `@web/default/src/features/combos/components/combos-cells.tsx`:
- Around line 36-49: Replace the hardcoded English labels in StatusCell with
calls to the i18n t() function: import or obtain t (e.g., via
useTranslation/useTranslations as used in the codebase), keep the existing
enabled computation (const enabled = combo.status === 1) and change the
displayed text to t('combos.status.enabled') when enabled and
t('combos.status.disabled') when not; ensure to add the import/hook usage for t
at the top of the component and update any tests or story text keys accordingly.
- Around line 21-34: Replace hardcoded English labels in StrategyCell by calling
the i18n t() function: change strategyMap in the StrategyCell component to map
keys to translation keys (e.g. 'fallback' -> t('combos.strategy.fallback'),
'random' -> t('combos.strategy.random'), etc.) and compute label as
strategyMap[combo.strategy] || t(`combos.strategy.${combo.strategy}`) so unknown
strategies are translated too; also add the required import or hook for t() at
the top of the file and keep the rest of the component (span and classNames)
unchanged.
In `@web/default/src/features/combos/components/combos-mutate-drawer.tsx`:
- Around line 176-177: The placeholder strings in the combos-mutate-drawer
component are hardcoded (e.g., the Textarea placeholder 'gpt-4, claude-3,
gemini-pro' and the other user-facing string around lines 229-230); replace
these literals with translation calls using the t() function from
useTranslation() (import/use useTranslation in this component if not already
present) and reference appropriate i18n keys (e.g.,
t('combos.placeholder_models') and t('combos.placeholder_otherField')), then add
the corresponding keys to the translation resource files so the placeholders are
localized.
- Around line 99-115: The effect calls getCombo asynchronously and applies
form.reset with its result without verifying the response still matches the
active row; capture the currentRow id (e.g., const expectedId = currentRow?.id)
before calling getCombo and after the promise resolves verify that open &&
isUpdate && currentRow?.id === expectedId (or use an AbortController/signal if
getCombo supports cancellation) before calling form.reset, so stale responses do
not overwrite the form for a different currentRow.
In `@web/default/src/features/combos/components/combos-row-actions.tsx`:
- Around line 57-59: The icon-only action button in the CombosRowActions
component lacks an accessible name; update the Button (in
combos-row-actions.tsx) to include a clear aria-label (e.g., aria-label="More
actions" or similar) so screen readers can announce it, and mark the decorative
icon MoreHorizontal with aria-hidden="true" to avoid duplicate/verbose
announcements; ensure the label text matches the button's purpose and is
localized if needed.
- Around line 38-47: The handler handleToggleStatus currently calls updateCombo
with the entire combo payload (using combo.name/models/weights/strategy),
risking overwriting newer fields; change it to call the dedicated status-only
API (e.g., updateComboStatus or the PATCH status endpoint) with combo.id and the
computed newStatus (based on combo.status) so only the status is updated and
other fields aren’t overwritten, and remove the full payload usage in
handleToggleStatus.
In `@web/default/src/features/combos/components/combos-table.tsx`:
- Line 62: Remove the debug console.log in CombosTable's getCombos (the line
logging "[CombosTable] getCombos raw result:") — delete that console.log or
replace it with a conditional/dev-only logger if runtime diagnostics are
required (e.g., check process.env.NODE_ENV === 'development' or use the app
logger utility) so no debug console output exists in production.
In `@web/default/src/i18n/locales/fr.json`:
- Line 4558: The French locale contains an untranslated entry for the key "This
will permanently delete"; update web/default/src/i18n/locales/fr.json by
replacing the English value for the key "This will permanently delete" with a
proper French translation (for example "Cela supprimera définitivement" or
another approved French phrase), ensuring the JSON value remains a string and
respects existing formatting/escaping conventions so deletion confirmation
dialogs show French text.
In `@web/default/src/i18n/locales/ja.json`:
- Line 4558: Replace the untranslated English value for the key "This will
permanently delete" in the Japanese locale by providing a proper Japanese
translation (e.g., "これにより完全に削除されます" or "これを実行すると完全に削除されます") so the UI is fully
localized; update the value string in ja.json for the identical key while
preserving the JSON key format and punctuation.
- Line 4542: Remove the duplicate JSON key that includes a leading space (" This
action cannot be undone.") so lookups only use the canonical key ("This action
cannot be undone."); locate the entry with the leading-space key in ja.json and
delete that key/value pair, ensuring only the correctly-spaced key remains to
avoid duplicate mapping and inconsistent translations.
In `@web/default/src/i18n/locales/ru.json`:
- Line 4558: The Russian locale entry for the key "This will permanently delete"
in ru.json is still English; replace the value string currently set to "This
will permanently delete" with an appropriate Russian translation (e.g., "Это
действие удалит навсегда" or another accurate Russian phrasing) so the
confirmation UI is fully localized; update only the value for the existing JSON
key without changing the key itself.
In `@web/default/src/i18n/locales/vi.json`:
- Around line 4558-4565: The vi.json contains untranslated values for keys like
"This will permanently delete" and "combo" (also "combos" at the end); update
their string values to proper Vietnamese translations (e.g., "This will
permanently delete" -> "Điều này sẽ xóa vĩnh viễn", "combo" -> localized term
such as "combo" or "gói-khuyến-mãi" depending on project terminology, and
"combos" -> plural form) so all new combo-related keys ("This will permanently
delete combo", "combo-name", etc.) have Vietnamese values consistent with
existing entries like "combo" -> "combo" or the chosen translation and
"combo-name" -> "tên-combo".
In `@web/default/src/i18n/locales/zh.json`:
- Line 4558: The zh.json entry with key "This will permanently delete" currently
keeps the English text as its value; update the value to a proper Chinese
translation (for example: "此操作将永久删除") so the delete confirmation is fully
localized; locate the JSON key "This will permanently delete" in the zh locale
and replace the right-hand string with the Chinese translation, keeping the
surrounding JSON syntax intact.
---
Nitpick comments:
In `@controller/combo.go`:
- Line 48: Redundant assignment: remove the manual setting of combo.CreatedTime
(the line assigning combo.CreatedTime = time.Now().Unix()) since combo.Insert()
already initializes CreatedTime internally; update the controller method that
calls combo.Insert() (referencing combo.CreatedTime and the combo.Insert() call)
to delete that assignment and rely on the model implementation in model/combo.go
to set CreatedTime.
- Line 34: Extract the inline strategy check into a package-level
allowedStrategies slice and a helper isValidStrategy(s string) bool, then
replace the long condition that reads combo.Strategy != "fallback" && ... with a
call to isValidStrategy(combo.Strategy); ensure allowedStrategies contains
"fallback", "random", "weighted", "round_robin" and update the validation logic
in the function/method that reads combo.Strategy to use isValidStrategy.
In `@web/default/src/features/combos/components/combos-columns.tsx`:
- Around line 54-96: Update the hardcoded flat i18n keys used in the
DataTableColumnHeader calls to hierarchical, semantically-scoped keys; replace
t('Name'), t('Models'), t('Strategy'), t('Status'), and t('Created At') with
keys like t('combos.table.name'), t('combos.table.models'),
t('combos.table.strategy'), t('combos.table.status'), and
t('combos.table.createdAt') respectively in the combos-columns component where
DataTableColumnHeader is rendered (refer to the column definitions using
accessorKey 'name', 'models', 'strategy', 'status', 'created_time' and the
StrategyCell/StatusCell usages) so translations are organized and unambiguous.
- Around line 98-102: The date cell renderer in combos-columns.tsx (cell: ({ row
}) => { ... }) uses toLocaleString() without specifying a locale; update the
cell implementation to retrieve the app's current i18n locale (e.g., from
i18n.language or the app's locale context) and pass it as the first argument to
Date.prototype.toLocaleString so the created_time display respects the user's
selected language/locale; ensure you still handle null/undefined created_time
and convert the epoch seconds (time * 1000) before formatting.
In `@web/default/src/features/combos/components/combos-multi-delete-dialog.tsx`:
- Around line 36-43: The component CombosMultiDeleteDialog currently
destructures props (open, onOpenChange, selectedIds); change it to use the props
object instead to follow guidelines—replace destructuring in the function
signature and all internal references so they read props.open,
props.onOpenChange, and props.selectedIds, ensuring the prop type annotation
remains intact for the function parameter.
- Around line 49-61: The handleDelete function currently uses Promise.all so any
single deleteCombo(id) rejection shows a generic error; change it to use
Promise.allSettled(selectedIds.map(id => deleteCombo(id))) in handleDelete, then
count fulfilled vs rejected results, show a toast reflecting full success,
partial success (e.g., "X deleted, Y failed"), or full failure, and optionally
include/log the failed ids; still call triggerRefresh() after successful
deletions and setIsDeleting(false) in finally, and keep invoking
onOpenChange(false) only when at least one delete succeeded (or per your UX
decision).
In `@web/default/src/features/combos/components/combos-provider.tsx`:
- Line 35: The CombosProvider component currently destructures children in its
parameter list; change the component to accept a single props parameter (e.g.,
props: { children: React.ReactNode }) and update the implementation to reference
props.children instead of the destructured children variable so the component
follows the project's non-destructuring props convention (locate the
CombosProvider function declaration and any usage of children inside it and
replace accordingly).
In `@web/default/src/features/combos/components/combos-table.tsx`:
- Around line 90-96: The UI strings in combos-table.tsx are using flat i18n keys
(e.g., t('No Combos Found'), t('Search combos...')) — update the calls to use
hierarchical keys such as t('combos.empty.title'),
t('combos.empty.description'), and t('combos.search.placeholder') in the
emptyTitle, emptyDescription and Input placeholder props (within the
renderToolbar block), and ensure corresponding entries are added/updated in the
translation resource files for all supported locales so the new keys resolve at
runtime.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 70c3b5cb-9271-461c-a6a7-e842b1d5edb2
📒 Files selected for processing (31)
constant/context_key.gocontroller/combo.godocs/design/combo-feature.mdmiddleware/distributor.gomodel/combo.gomodel/main.gorouter/api-router.goservice/combo_routing.goweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
705a47e to
1d24954
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/hooks/use-sidebar-data.ts`:
- Around line 91-95: The Combos nav item (title: "Combos", url: "/combos", icon:
GitMerge) is currently placed in the general nav group in use-sidebar-data.ts
but is configured as an admin module in use-sidebar-config.ts (mapped to
section: 'admin', module: 'combo'); remove the Combos entry from the general
group and add the same nav item object into the admin group alongside other
admin items (Channels, Models, Users, Redemption Codes) so the sidebar placement
matches the config.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 66d450bb-8507-4ec6-a366-070a1b8c0694
📒 Files selected for processing (27)
controller/combo.godocs/design/combo-feature.mdweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (3)
- docs/design/combo-feature.md
- web/default/src/i18n/locales/ja.json
- web/default/src/i18n/locales/vi.json
🚧 Files skipped from review as they are similar to previous changes (21)
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- web/default/src/features/combos/components/combos-table.tsx
- web/default/src/features/combos/constants.ts
- web/default/src/routes/_authenticated/combos/index.tsx
- web/default/src/features/combos/components/combos-dialogs.tsx
- web/default/src/i18n/locales/ru.json
- web/default/src/features/combos/components/combos-cells.tsx
- web/default/src/features/combos/components/combos-provider.tsx
- web/default/src/i18n/locales/fr.json
- web/default/src/features/combos/api.ts
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- web/default/src/features/combos/components/combos-columns.tsx
- controller/combo.go
- web/default/src/routeTree.gen.ts
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/types.ts
- web/default/src/i18n/locales/en.json
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/i18n/locales/zh.json
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
web/default/src/features/combos/constants.ts (2)
35-42: ⚡ Quick winPrefer hierarchical i18n keys for status labels.
The
labelKeyvalues use flat English words ('Enabled','Disabled') instead of hierarchical keys. As per coding guidelines, i18n key names should be hierarchical and semantically clear (e.g.,combos.status.enabled,common.enabled).♻️ Suggested refactor for hierarchical i18n keys
[COMBO_STATUS.ENABLED]: { variant: 'success', - labelKey: 'Enabled', + labelKey: 'combos.status.enabled', }, [COMBO_STATUS.DISABLED]: { variant: 'neutral', - labelKey: 'Disabled', + labelKey: 'combos.status.disabled', },Then add corresponding entries to locale JSON files (en.json, etc.):
{ "combos": { "status": { "enabled": "Enabled", "disabled": "Disabled" } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/constants.ts` around lines 35 - 42, The status labelKey values in constants.ts use flat English strings; update the COMBO_STATUS mapping (the [COMBO_STATUS.ENABLED] and [COMBO_STATUS.DISABLED] entries) to use hierarchical i18n keys such as "combos.status.enabled" and "combos.status.disabled" instead of "Enabled"/"Disabled", and then add matching entries under the combos.status tree in your locale JSON files (e.g., en.json) so the translation lookup for labelKey works correctly.Source: Coding guidelines
66-69: ⚡ Quick winPrefer hierarchical i18n keys for strategy labels.
Similar to the status labels, the strategy
labelKeyvalues use flat English strings ('Fallback','Random', etc.) instead of hierarchical keys. Consider using a pattern likecombos.strategy.fallbackfor consistency with i18n guidelines.♻️ Suggested refactor for hierarchical strategy keys
export const COMBO_STRATEGY_OPTIONS = [ - { value: COMBO_STRATEGIES.FALLBACK, labelKey: 'Fallback' }, - { value: COMBO_STRATEGIES.RANDOM, labelKey: 'Random' }, - { value: COMBO_STRATEGIES.WEIGHTED, labelKey: 'Weighted' }, - { value: COMBO_STRATEGIES.ROUND_ROBIN, labelKey: 'Round Robin' }, + { value: COMBO_STRATEGIES.FALLBACK, labelKey: 'combos.strategy.fallback' }, + { value: COMBO_STRATEGIES.RANDOM, labelKey: 'combos.strategy.random' }, + { value: COMBO_STRATEGIES.WEIGHTED, labelKey: 'combos.strategy.weighted' }, + { value: COMBO_STRATEGIES.ROUND_ROBIN, labelKey: 'combos.strategy.roundRobin' }, ]Then add to locale files:
{ "combos": { "strategy": { "fallback": "Fallback", "random": "Random", "weighted": "Weighted", "roundRobin": "Round Robin" } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/constants.ts` around lines 66 - 69, Change the flat English labelKey strings in the combos strategy options to hierarchical i18n keys; specifically update the objects that reference COMBO_STRATEGIES (the array with entries for COMBO_STRATEGIES.FALLBACK, .RANDOM, .WEIGHTED, .ROUND_ROBIN) to use keys like "combos.strategy.fallback", "combos.strategy.random", "combos.strategy.weighted", and "combos.strategy.roundRobin" and add corresponding entries to the locale files under combos.strategy so the translator lookup works consistently with the status labels.Source: Coding guidelines
middleware/distributor.go (1)
46-68: 💤 Low valueError messages should use i18n for consistency.
The new error messages use hardcoded English strings while existing code in this file (e.g., line 38) uses
i18n.T(). For consistency and localization support, consider adding i18n message keys for:
- Line 47:
"Combo name is empty"- Line 52:
"Combo not found: "+comboName- Line 56:
"Combo is disabled: "+comboName- Line 67:
"Combo routing failed: "+comboErr.Error()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@middleware/distributor.go` around lines 46 - 68, Replace hardcoded English error strings in the distributor middleware with i18n calls: use i18n.T(...) for messages where abortWithOpenAiMessage is invoked when comboName == "", when model.GetComboByName returns nil/error, when combo.Status != 1, and when service.ResolveComboModel returns comboErr; keep the dynamic parts (comboName and comboErr.Error()) by passing them as format args to i18n.T (or using the project’s i18n interpolation pattern) so calls around abortWithOpenAiMessage(c, ...) use i18n.T("key", comboName) or i18n.T("key", comboErr.Error()); update or add the corresponding i18n keys for "Combo name is empty", "Combo not found: %s", "Combo is disabled: %s", and "Combo routing failed: %s" to the translations resource so messages remain localized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@middleware/distributor.go`:
- Around line 72-74: The middleware currently logs but continues when
service.RewriteRequestBodyModel(c, result.ResolvedModel) fails, leaving
modelRequest.Model updated while the request body still contains the original
"combo:..." string; change this to abort the request on rewrite failure: after
service.RewriteRequestBodyModel returns an error, call the request
abort/response helper (e.g., use c.AbortWithStatusJSON or the project's standard
abort function) and return immediately instead of just logging via
common.SysError, ensuring modelRequest.Model and the actual request body remain
consistent for downstream handlers and retries; reference the call site where
RewriteRequestBodyModel is invoked and where modelRequest.Model is set
(result.ResolvedModel) to implement the early return/abort flow.
In `@web/default/src/features/combos/constants.ts`:
- Around line 45-52: Replace the O(n²) derivation in COMBO_STATUS_OPTIONS by
iterating COMBO_STATUSES with Object.entries instead of Object.values + nested
Object.keys.find; specifically, iterate Object.entries(COMBO_STATUSES) and map
each [key, config] to { value: key as `${number}`, label: config.labelKey } so
COMBO_STATUS_OPTIONS is produced in one pass and removes the nested find and
type assertion complexity.
In `@web/default/src/i18n/locales/en.json`:
- Line 4542: Remove the duplicate i18n key that starts with a leading space ("
This action cannot be undone.") and consolidate translations to the correct key
without the leading space ("This action cannot be undone."); specifically delete
the entry with the leading-space key and, if it contains any different
translation value, move that value to the canonical key "This action cannot be
undone." to avoid lookup failures and duplicate keys in en.json.
---
Nitpick comments:
In `@middleware/distributor.go`:
- Around line 46-68: Replace hardcoded English error strings in the distributor
middleware with i18n calls: use i18n.T(...) for messages where
abortWithOpenAiMessage is invoked when comboName == "", when
model.GetComboByName returns nil/error, when combo.Status != 1, and when
service.ResolveComboModel returns comboErr; keep the dynamic parts (comboName
and comboErr.Error()) by passing them as format args to i18n.T (or using the
project’s i18n interpolation pattern) so calls around abortWithOpenAiMessage(c,
...) use i18n.T("key", comboName) or i18n.T("key", comboErr.Error()); update or
add the corresponding i18n keys for "Combo name is empty", "Combo not found:
%s", "Combo is disabled: %s", and "Combo routing failed: %s" to the translations
resource so messages remain localized.
In `@web/default/src/features/combos/constants.ts`:
- Around line 35-42: The status labelKey values in constants.ts use flat English
strings; update the COMBO_STATUS mapping (the [COMBO_STATUS.ENABLED] and
[COMBO_STATUS.DISABLED] entries) to use hierarchical i18n keys such as
"combos.status.enabled" and "combos.status.disabled" instead of
"Enabled"/"Disabled", and then add matching entries under the combos.status tree
in your locale JSON files (e.g., en.json) so the translation lookup for labelKey
works correctly.
- Around line 66-69: Change the flat English labelKey strings in the combos
strategy options to hierarchical i18n keys; specifically update the objects that
reference COMBO_STRATEGIES (the array with entries for
COMBO_STRATEGIES.FALLBACK, .RANDOM, .WEIGHTED, .ROUND_ROBIN) to use keys like
"combos.strategy.fallback", "combos.strategy.random",
"combos.strategy.weighted", and "combos.strategy.roundRobin" and add
corresponding entries to the locale files under combos.strategy so the
translator lookup works consistently with the status labels.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f73971f7-d295-4128-8fae-9fd97d18c93c
📒 Files selected for processing (33)
constant/context_key.gocontroller/combo.godocs/design/combo-feature.mdmiddleware/distributor.gomodel/combo.gomodel/main.gorouter/api-router.goservice/combo_routing.goweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (3)
- web/default/src/i18n/locales/ja.json
- web/default/src/hooks/use-sidebar-config.ts
- web/default/src/routeTree.gen.ts
🚧 Files skipped from review as they are similar to previous changes (25)
- model/main.go
- web/default/src/hooks/use-sidebar-data.ts
- web/default/src/features/combos/components/combos-dialogs.tsx
- web/default/src/features/combos/components/combos-provider.tsx
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- web/default/src/features/combos/index.tsx
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- constant/context_key.go
- web/default/src/i18n/locales/vi.json
- web/default/src/routes/_authenticated/combos/index.tsx
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- web/default/src/features/combos/components/combos-columns.tsx
- web/default/src/i18n/locales/ru.json
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/features/combos/components/combos-cells.tsx
- router/api-router.go
- web/default/src/features/combos/components/combos-table.tsx
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/types.ts
- controller/combo.go
- web/default/src/i18n/locales/fr.json
- model/combo.go
- web/default/src/features/combos/api.ts
- service/combo_routing.go
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/hooks/use-sidebar-config.ts`:
- Line 48: The visibility mapping for '/combos' is wrong:
URL_TO_CONFIG_MAP['/combos'] checks admin.combo while DEFAULT_SIDEBAR_MODULES
enables console.combo, causing isModuleEnabled() (which checks
adminSection[module] === true) to filter it out; fix by making the module key
consistent—either change URL_TO_CONFIG_MAP['/combos'] to check console.combo or
update DEFAULT_SIDEBAR_MODULES to enable admin.combo (and do the same fix at the
other occurrence noted around line 104), ensuring the module name used in
URL_TO_CONFIG_MAP, DEFAULT_SIDEBAR_MODULES, and isModuleEnabled() calls match
exactly.
In `@web/default/src/routes/_authenticated/combos/index.tsx`:
- Around line 24-25: Tighten the pagination schema used in validateSearch by
restricting page and pageSize to positive integers: change the page schema from
z.number().optional().catch(1) to z.number().int().min(1).optional().catch(1)
and change pageSize from z.number().optional().catch(undefined) to
z.number().int().min(1).optional().catch(undefined) so floats, zero and negative
values are rejected while preserving the existing fallbacks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 47cd8bf7-3559-43b8-b947-16fc452b9ce2
📒 Files selected for processing (33)
constant/context_key.gocontroller/combo.godocs/design/combo-feature.mdmiddleware/distributor.gomodel/combo.gomodel/main.gorouter/api-router.goservice/combo_routing.goweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (2)
- web/default/src/i18n/locales/fr.json
- web/default/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (27)
- web/default/src/hooks/use-sidebar-data.ts
- docs/design/combo-feature.md
- web/default/src/features/combos/index.tsx
- model/main.go
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- constant/context_key.go
- web/default/src/features/combos/constants.ts
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- web/default/src/features/combos/components/combos-cells.tsx
- web/default/src/features/combos/components/combos-provider.tsx
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/features/combos/components/combos-table.tsx
- web/default/src/i18n/locales/en.json
- web/default/src/features/combos/types.ts
- web/default/src/features/combos/components/combos-columns.tsx
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- web/default/src/i18n/locales/ru.json
- web/default/src/routeTree.gen.ts
- web/default/src/features/combos/api.ts
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- web/default/src/i18n/locales/vi.json
- middleware/distributor.go
- controller/combo.go
- web/default/src/i18n/locales/ja.json
- model/combo.go
- service/combo_routing.go
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
web/default/src/i18n/locales/fr.json (1)
4617-4617:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFrench locale still has an untranslated delete-confirmation fragment.
"This will permanently delete"is still mapped to English, so French UI remains mixed-language in destructive dialogs. Please translate this value infr.json.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/i18n/locales/fr.json` at line 4617, The fr locale key "This will permanently delete" is still English; update its value in the fr.json locales to a proper French translation (e.g. "Cela supprimera définitivement") so destructive dialogs are fully localized, keeping the key unchanged and only replacing the right-hand string.
🧹 Nitpick comments (3)
web/default/src/features/combos/components/combos-columns.tsx (2)
26-111: ⚡ Quick winMemoize the columns array to prevent unnecessary table re-renders.
The
useCombosColumnshook returns a new columns array on every render. Since the columns depend on thetfunction fromuseTranslation, wrap the return value inuseMemowithtas a dependency to avoid recreating columns unnecessarily and causing table re-renders.⚡ Proposed optimization
+import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { type ColumnDef } from '`@tanstack/react-table`' import { DataTableColumnHeader } from '`@/components/data-table`' import { type Combo } from '../types' import { CombosRowActions } from './combos-row-actions' import { StrategyCell, StatusCell } from './combos-cells' export function useCombosColumns(): ColumnDef<Combo>[] { const { t } = useTranslation() - return [ + return useMemo(() => [ { id: 'select', // ... rest of columns }, - ] + ], [t]) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-columns.tsx` around lines 26 - 111, The columns array returned by useCombosColumns is recreated on every render causing extra table re-renders; wrap the returned array in React's useMemo and depend on t (from useTranslation) so the columns are memoized and only recomputed when translations change. Update the useCombosColumns function to import/use useMemo, move the array into a useMemo callback, and list [t] as the dependency; keep all column definitions (including identifiers like 'select', accessorKey 'name'/'models'/'strategy'/'status'/'created_time', and cells using DataTableColumnHeader, StrategyCell, StatusCell, CombosRowActions) unchanged inside the memoized value.Source: Coding guidelines
98-102: 💤 Low valueConsider using i18n for date formatting.
toLocaleString()without arguments uses the browser's default locale, which may not align with the application's selected language. Consider using i18n date formatting utilities for consistency.🌐 Example using i18n date formatting
cell: ({ row }) => { const time = row.getValue('created_time') as number | null if (!time) return '-' return new Intl.DateTimeFormat(i18n.language).format(new Date(time * 1000)) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-columns.tsx` around lines 98 - 102, The cell renderer for the created_time column uses Date.prototype.toLocaleString() which relies on the browser default locale; update the cell function (the arrow function assigned to cell in combos-columns.tsx that reads row.getValue('created_time')) to format dates via the app i18n settings (e.g., use Intl.DateTimeFormat with the current i18n.language or the project's i18n date helper) so the displayed timestamp respects the selected locale and formatting conventions; keep the existing null check (if (!time) return '-') and only replace the toLocaleString() call with the i18n-aware formatter.Source: Coding guidelines
web/default/src/features/combos/components/combos-provider.tsx (1)
44-52: ⚡ Quick winMemoize the provider value to prevent unnecessary re-renders.
The provider value object is recreated on every render, which can cause all consumers to re-render even when the state hasn't changed. As per coding guidelines,
useMemoshould be used judiciously to reduce unnecessary re-renders.⚡ Proposed optimization
+import React, { useCallback, useMemo } from 'react' + export function CombosProvider(props: { children: React.ReactNode }) { const [open, setOpen] = React.useState<ComboDialogType | null>(null) const [currentRow, setCurrentRow] = React.useState<Combo | null>(null) const [refreshTrigger, setRefreshTrigger] = React.useState(0) const triggerRefresh = useCallback(() => { setRefreshTrigger((v) => v + 1) }, []) + const value = useMemo( + () => ({ + open, + setOpen, + currentRow, + setCurrentRow, + refreshTrigger, + triggerRefresh, + }), + [open, currentRow, refreshTrigger, triggerRefresh] + ) + return ( - <CombosContext.Provider - value={{ - open, - setOpen, - currentRow, - setCurrentRow, - refreshTrigger, - triggerRefresh, - }} - > + <CombosContext.Provider value={value}> {props.children} </CombosContext.Provider> ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/combos/components/combos-provider.tsx` around lines 44 - 52, The provider value object for CombosContext.Provider is recreated every render; wrap the value in a useMemo to memoize it and prevent unnecessary consumer re-renders: import React's useMemo, create a memoizedValue using useMemo(() => ({ open, setOpen, currentRow, setCurrentRow, refreshTrigger, triggerRefresh }), [open, setOpen, currentRow, setCurrentRow, refreshTrigger, triggerRefresh]) and pass memoizedValue to CombosContext.Provider's value prop (adjust dependencies if any of those setters/handlers are stable and can be omitted).Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@service/combo_routing.go`:
- Around line 190-196: In resolveRoundRobin, the counter is incremented before
computing idx so new combos start at models[1]; change the order so you compute
idx from the current counter and then increment it (i.e., use
comboRoundRobinCounters[combo.Id] % len(models) to pick the model, then
increment comboRoundRobinCounters[combo.Id]) while preserving the mutex
(comboRoundRobinMutex) and returning the selected model in ComboRoutingResult;
this ensures the first request maps to models[0].
- Around line 249-260: replaceModelFieldInJSON currently assumes JSON and
silently returns unchanged bytes on failure; update the flow so
RewriteRequestBodyModel only attempts JSON rewriting when Content-Type is
application/json and treat non-JSON bodies as unsupported for combo rewrite:
modify replaceModelFieldInJSON to return (result []byte, err error) and return a
clear error when the input is not a top-level JSON object or sjson.Set fails,
change RewriteRequestBodyModel to check Content-Type and either call the new
replaceModelFieldInJSON and propagate errors (causing Distribute to reject the
request) or, if you prefer to support forms, implement equivalent rewriting for
form/multipart there; finally update Distribute to handle and surface the error
from RewriteRequestBodyModel instead of proceeding when body rewrite failed
(also ensure getModelFromRequest and common.UnmarshalBodyReusable remain the
source of the model but do not mask rewrite failures).
In `@web/default/src/features/combos/components/combos-columns.tsx`:
- Around line 32-37: Add accessible labels to the selection checkboxes by adding
aria-label attributes: for the header checkbox (the input using
checked={table.getIsAllPageRowsSelected()} and
onChange={table.toggleAllPageRowsSelected(...)}) add aria-label="Select all rows
on page" (or similar), and for each row checkbox (the input in the row
rendering, where row.toggleSelected and row.getIsSelected are used) add
aria-label={`Select row ${row.index + 1}`} or a more specific label using the
row's identifying data; ensure labels are concise and unique for screen readers.
---
Duplicate comments:
In `@web/default/src/i18n/locales/fr.json`:
- Line 4617: The fr locale key "This will permanently delete" is still English;
update its value in the fr.json locales to a proper French translation (e.g.
"Cela supprimera définitivement") so destructive dialogs are fully localized,
keeping the key unchanged and only replacing the right-hand string.
---
Nitpick comments:
In `@web/default/src/features/combos/components/combos-columns.tsx`:
- Around line 26-111: The columns array returned by useCombosColumns is
recreated on every render causing extra table re-renders; wrap the returned
array in React's useMemo and depend on t (from useTranslation) so the columns
are memoized and only recomputed when translations change. Update the
useCombosColumns function to import/use useMemo, move the array into a useMemo
callback, and list [t] as the dependency; keep all column definitions (including
identifiers like 'select', accessorKey
'name'/'models'/'strategy'/'status'/'created_time', and cells using
DataTableColumnHeader, StrategyCell, StatusCell, CombosRowActions) unchanged
inside the memoized value.
- Around line 98-102: The cell renderer for the created_time column uses
Date.prototype.toLocaleString() which relies on the browser default locale;
update the cell function (the arrow function assigned to cell in
combos-columns.tsx that reads row.getValue('created_time')) to format dates via
the app i18n settings (e.g., use Intl.DateTimeFormat with the current
i18n.language or the project's i18n date helper) so the displayed timestamp
respects the selected locale and formatting conventions; keep the existing null
check (if (!time) return '-') and only replace the toLocaleString() call with
the i18n-aware formatter.
In `@web/default/src/features/combos/components/combos-provider.tsx`:
- Around line 44-52: The provider value object for CombosContext.Provider is
recreated every render; wrap the value in a useMemo to memoize it and prevent
unnecessary consumer re-renders: import React's useMemo, create a memoizedValue
using useMemo(() => ({ open, setOpen, currentRow, setCurrentRow, refreshTrigger,
triggerRefresh }), [open, setOpen, currentRow, setCurrentRow, refreshTrigger,
triggerRefresh]) and pass memoizedValue to CombosContext.Provider's value prop
(adjust dependencies if any of those setters/handlers are stable and can be
omitted).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9a75ace8-9e4c-4ee6-a609-2c78da8ee7d8
📒 Files selected for processing (33)
constant/context_key.gocontroller/combo.godocs/design/combo-feature.mdmiddleware/distributor.gomodel/combo.gomodel/main.gorouter/api-router.goservice/combo_routing.goweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (6)
- docs/design/combo-feature.md
- web/default/src/i18n/locales/en.json
- web/default/src/i18n/locales/ja.json
- web/default/src/i18n/locales/vi.json
- web/default/src/routeTree.gen.ts
- web/default/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (22)
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- web/default/src/features/combos/index.tsx
- web/default/src/hooks/use-sidebar-config.ts
- web/default/src/hooks/use-sidebar-data.ts
- constant/context_key.go
- web/default/src/routes/_authenticated/combos/index.tsx
- model/main.go
- web/default/src/features/combos/components/combos-dialogs.tsx
- router/api-router.go
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- web/default/src/features/combos/components/combos-cells.tsx
- web/default/src/i18n/locales/ru.json
- web/default/src/features/combos/types.ts
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- web/default/src/features/combos/api.ts
- web/default/src/features/combos/constants.ts
- controller/combo.go
- model/combo.go
- middleware/distributor.go
a69b1f3 to
965b182
Compare
- New model.Combo struct with Insert/Update/Delete/GetByID/GetByName/GetByUserID/GetAll/Search methods
- New controller with 6 handlers: CreateCombo, GetComboList, GetCombo, UpdateCombo, DeleteCombo, SearchCombos
- Auto-migration via DB.AutoMigrate(&Combo{})
- Routes under /api/combo/ with UserAuth middleware
- Design doc at docs/design/combo-feature.md
Combo bundles multiple models with a routing strategy (fallback/random/weighted/round_robin).
Users reference a combo via model: "combo:<name>" in requests (Phase 2).
- Detect model: "combo:<name>" in Distribute() and resolve via service.ResolveComboModel() per strategy - Rewrite request body model field from combo:xxx to real model - Fallback strategy pre-selects channel, bypasses normal selection - Non-fallback strategies pass resolved model to normal channel selection - Store combo metadata in context for downstream logging/billing - Add Group field to ComboRoutingResult for auto-group communication
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
middleware/distributor.go (1)
47-75: ⚡ Quick winUser-facing error messages should use i18n.
The combo routing error messages are hardcoded in English, but per coding guidelines, all user-facing text should use i18n. Other error messages in this file use
i18n.T(c, ...).if comboName == "" { - abortWithOpenAiMessage(c, http.StatusBadRequest, "Combo name is empty") + abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgComboNameEmpty)) return } userId := c.GetInt("id") combo, comboErr := model.GetComboByNameUserId(comboName, userId) if comboErr != nil || combo == nil { - abortWithOpenAiMessage(c, http.StatusNotFound, "Combo not found: "+comboName) + abortWithOpenAiMessage(c, http.StatusNotFound, i18n.T(c, i18n.MsgComboNotFound, map[string]any{"Name": comboName})) return } if combo.Status != 1 { - abortWithOpenAiMessage(c, http.StatusForbidden, "Combo is disabled: "+comboName) + abortWithOpenAiMessage(c, http.StatusForbidden, i18n.T(c, i18n.MsgComboDisabled, map[string]any{"Name": comboName})) return } ... - abortWithOpenAiMessage(c, http.StatusServiceUnavailable, "Combo routing failed: "+comboErr.Error(), types.ErrorCodeModelNotFound) + abortWithOpenAiMessage(c, http.StatusServiceUnavailable, i18n.T(c, i18n.MsgComboRoutingFailed, map[string]any{"Error": comboErr.Error()}), types.ErrorCodeModelNotFound) ... - abortWithOpenAiMessage(c, http.StatusInternalServerError, "Failed to rewrite request body") + abortWithOpenAiMessage(c, http.StatusInternalServerError, i18n.T(c, i18n.MsgComboRewriteFailed))This requires adding the corresponding i18n message constants and translations.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@middleware/distributor.go` around lines 47 - 75, Replace hardcoded English messages passed to abortWithOpenAiMessage and logged in the combo routing block by using i18n.T(c, "<key>") calls: update the abortWithOpenAiMessage calls around ResolveComboModel and RewriteRequestBodyModel (and the "Combo not found" / "Combo is disabled" messages earlier in the same block if present) to use new i18n keys (e.g., "combo.not_found", "combo.disabled", "combo.routing_failed", "combo.rewrite_failed") instead of literal strings, and add those keys to the i18n message constants and translation files so the messages are available in supported locales; keep the same HTTP status and types.ErrorCodeModelNotFound usage when calling abortWithOpenAiMessage.Source: Coding guidelines
service/combo_routing.go (1)
156-163: 💤 Low valueMinor: Fix indentation inside the outer
ifblock.The
if err := common.Unmarshal...block (lines 159-162) appears to have inconsistent indentation relative to its enclosingifstatement at line 158. This is a cosmetic issue but affects readability.func parseWeights(weightsStr string, models []string) map[string]int { parsed := make(map[string]int) if weightsStr != "" && weightsStr != "{}" { - if err := common.Unmarshal([]byte(weightsStr), &parsed); err != nil { - // Invalid JSON — ignore, all models get default weight - parsed = make(map[string]int) - } + if err := common.Unmarshal([]byte(weightsStr), &parsed); err != nil { + // Invalid JSON — ignore, all models get default weight + parsed = make(map[string]int) + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@service/combo_routing.go` around lines 156 - 163, In parseWeights, fix the indentation of the inner if block that calls common.Unmarshal so it is consistently nested under the outer if (weightsStr != "" && weightsStr != "{}"); adjust spacing so the lines starting with "if err := common.Unmarshal..." and its body (the comment and parsed = make(map[string]int)) align one level deeper than the outer if, preserving the existing logic and variable names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/features/combos/components/combos-columns.tsx`:
- Around line 105-107: The null-check for the created_time value incorrectly
uses a falsy check which treats epoch 0 as empty; in the component rendering
logic around row.getValue('created_time') replace the `if (!time)` check with an
explicit null/undefined check (e.g. `if (time == null)` or `if (time === null ||
time === undefined)`) so that valid epoch 0 timestamps are rendered, and keep
returning '-' only when the value is actually missing.
- Around line 37-44: Replace the hard-coded English aria-labels on the Checkbox
JSX with localized strings: import/use useTranslation() in the React component
that renders the Checkbox, add const { t } = useTranslation(), and change
aria-label='Select all' and aria-label='Select row' to
aria-label={t('combos.select_all')} and aria-label={t('combos.select_row')} (or
your project's chosen i18n keys); ensure the keys are added to the locale
resource files. Target the Checkbox elements shown in the combos-columns
component (the header Checkbox and the row cell Checkbox) so both labels go
through t().
In `@web/default/src/i18n/locales/fr.json`:
- Line 4612: The French translation for the key "Round Robin" is incorrect
("Tourniquet"); update the value for the "Round Robin" key in the
locales/fr.json mapping to a routing-accurate term such as "Rotation circulaire"
(or leave it as "Round Robin" if you prefer to keep the technical term
untranslated) so the UI correctly conveys the load-balancing/routing meaning.
- Line 4618: The French translation for the label "Update combo configuration"
removed the entity context and should explicitly include "combo"; update the
value for the "Update combo configuration" key in fr.json to include the word
"combo" (for example "Mettre à jour la configuration du combo" or another
grammatically appropriate variant) so the action remains unambiguous in the
admin UI.
In `@web/default/src/i18n/locales/zh.json`:
- Around line 4621-4623: The zh locale has untranslated values for the keys
"combo" and "combos" — replace the English strings with the proper Chinese
translations consistent with surrounding keys (e.g., change "combo" -> "组合" and
"combos" -> "组合列表" or another context-appropriate Chinese phrase) so all
combo-related labels in the file are localized; update the values for the keys
"combo" and "combos" in the same JSON object where "combo-name" is defined.
---
Nitpick comments:
In `@middleware/distributor.go`:
- Around line 47-75: Replace hardcoded English messages passed to
abortWithOpenAiMessage and logged in the combo routing block by using i18n.T(c,
"<key>") calls: update the abortWithOpenAiMessage calls around ResolveComboModel
and RewriteRequestBodyModel (and the "Combo not found" / "Combo is disabled"
messages earlier in the same block if present) to use new i18n keys (e.g.,
"combo.not_found", "combo.disabled", "combo.routing_failed",
"combo.rewrite_failed") instead of literal strings, and add those keys to the
i18n message constants and translation files so the messages are available in
supported locales; keep the same HTTP status and types.ErrorCodeModelNotFound
usage when calling abortWithOpenAiMessage.
In `@service/combo_routing.go`:
- Around line 156-163: In parseWeights, fix the indentation of the inner if
block that calls common.Unmarshal so it is consistently nested under the outer
if (weightsStr != "" && weightsStr != "{}"); adjust spacing so the lines
starting with "if err := common.Unmarshal..." and its body (the comment and
parsed = make(map[string]int)) align one level deeper than the outer if,
preserving the existing logic and variable names.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 58fa66bc-5f30-4869-8970-c7c802c775ee
📒 Files selected for processing (33)
constant/context_key.gocontroller/combo.godocs/design/combo-feature.mdmiddleware/distributor.gomodel/combo.gomodel/main.gorouter/api-router.goservice/combo_routing.goweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (5)
- docs/design/combo-feature.md
- web/default/src/i18n/locales/ru.json
- web/default/src/i18n/locales/en.json
- web/default/src/i18n/locales/ja.json
- web/default/src/routeTree.gen.ts
🚧 Files skipped from review as they are similar to previous changes (20)
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- web/default/src/features/combos/index.tsx
- constant/context_key.go
- model/main.go
- web/default/src/hooks/use-sidebar-config.ts
- router/api-router.go
- web/default/src/features/combos/components/combos-dialogs.tsx
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- web/default/src/features/combos/components/combos-provider.tsx
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/features/combos/constants.ts
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- model/combo.go
- web/default/src/features/combos/components/combos-cells.tsx
- web/default/src/features/combos/components/combos-table.tsx
- web/default/src/routes/_authenticated/combos/index.tsx
- controller/combo.go
- web/default/src/features/combos/types.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/i18n/locales/ru.json`:
- Around line 4621-4623: The locale entries "combo", "combo-name", and "combos"
are still in English; update their values to Russian equivalents (e.g., "combo"
-> "комбинация", "combo-name" -> "имя комбинации", "combos" -> "комбинации") so
the Russian locale uses consistent translated strings for these keys.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6f3e785a-30ee-4faf-80b5-957f8a594fe8
📒 Files selected for processing (27)
controller/combo.godocs/design/combo-feature.mdweb/default/src/features/combos/api.tsweb/default/src/features/combos/components/combos-bulk-actions.tsxweb/default/src/features/combos/components/combos-cells.tsxweb/default/src/features/combos/components/combos-columns.tsxweb/default/src/features/combos/components/combos-delete-dialog.tsxweb/default/src/features/combos/components/combos-dialogs.tsxweb/default/src/features/combos/components/combos-multi-delete-dialog.tsxweb/default/src/features/combos/components/combos-mutate-drawer.tsxweb/default/src/features/combos/components/combos-primary-buttons.tsxweb/default/src/features/combos/components/combos-provider.tsxweb/default/src/features/combos/components/combos-row-actions.tsxweb/default/src/features/combos/components/combos-table.tsxweb/default/src/features/combos/constants.tsweb/default/src/features/combos/index.tsxweb/default/src/features/combos/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/routeTree.gen.tsweb/default/src/routes/_authenticated/combos/index.tsx
✅ Files skipped from review due to trivial changes (5)
- docs/design/combo-feature.md
- web/default/src/i18n/locales/ja.json
- web/default/src/i18n/locales/vi.json
- web/default/src/i18n/locales/en.json
- web/default/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (20)
- web/default/src/features/combos/components/combos-columns.tsx
- web/default/src/features/combos/components/combos-primary-buttons.tsx
- web/default/src/features/combos/components/combos-multi-delete-dialog.tsx
- web/default/src/features/combos/index.tsx
- web/default/src/features/combos/components/combos-dialogs.tsx
- web/default/src/hooks/use-sidebar-data.ts
- web/default/src/hooks/use-sidebar-config.ts
- web/default/src/features/combos/components/combos-bulk-actions.tsx
- web/default/src/features/combos/components/combos-cells.tsx
- web/default/src/features/combos/components/combos-mutate-drawer.tsx
- web/default/src/features/combos/components/combos-provider.tsx
- web/default/src/i18n/locales/fr.json
- web/default/src/features/combos/constants.ts
- web/default/src/features/combos/components/combos-table.tsx
- web/default/src/features/combos/components/combos-row-actions.tsx
- web/default/src/features/combos/types.ts
- web/default/src/features/combos/api.ts
- web/default/src/features/combos/components/combos-delete-dialog.tsx
- controller/combo.go
- web/default/src/routeTree.gen.ts
Important
📝 变更描述 / Description
This PR aims at providing a way to allow the user to create custom model id, that can be use to route request to a list of models based on various strategies.
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit
New Features
Runtime
Documentation
Localization
Chores