feat(playground): add playground parameter settings panel#6044
Conversation
- constrain the desktop selector panel so long group and model lists scroll within a shared height. - make the selected model stand out with stronger row and label styling. - scroll both lists to the active selections after the popover opens.
- expose playground controls for sampling, penalty, token, and seed parameters. - reuse the existing persisted config and parameter-enabled state so requests only send enabled values. - add localized parameter copy and keep the panel scrollable on short screens.
WalkthroughAdds a scroll-into-view helper and shared layout classes for the model group selector, plus a new Playground parameter panel (temperature, top_p, penalties, max_tokens, seed) wired through playground input components and state, with localized labels/descriptions added across all supported locale files and static keys. ChangesModel Group Selector Scroll Behavior
Playground Parameter Panel Feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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: 2
🧹 Nitpick comments (4)
web/default/src/components/model-group-selector.tsx (2)
1-834: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffFile exceeds the ~200-line guideline threshold.
The component (830+ lines) has grown well past the recommended size. Consider extracting
renderGroupList,renderModelList, and the scroll-into-view effect/refs into dedicated subcomponents or a custom hook (e.g.,useModelGroupScrollIntoView). As per path instructions, "Keep files reasonably small; when a single file grows beyond about 200 lines, consider extracting subcomponents or custom hooks."🤖 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/components/model-group-selector.tsx` around lines 1 - 834, The file is far over the recommended size, so split the large selectors into smaller pieces. Extract the shared trigger UI and the list-rendering logic from ModelSelector, GroupSelector, and ModelGroupSelector into dedicated subcomponents, and move the open-state scrolling/refs logic into a custom hook such as useModelGroupScrollIntoView. Keep the existing symbols like ModelGroupSelector, renderGroupList, renderModelList, and scrollSelectedOptionIntoView as the main entry points while relocating implementation details into separate files or helpers.Source: Path instructions
744-777: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract
isSelectedto avoid repeating the comparison.
selectedModel === model.valueis recomputed four times per row (className, ref, text className, Check icon).renderGroupListalready extractsisSelectedfor the same pattern — apply the same here for consistency and readability.♻️ Proposed refactor
{filteredModels.map((model) => ( + (() => { + const isSelected = selectedModel === model.value + return ( <CommandItem className={cn( modelGroupSelectorLayoutClasses.modelItem, - selectedModel === model.value + isSelected ? modelGroupSelectorLayoutClasses.selectedModelItem : modelGroupSelectorLayoutClasses.unselectedModelItem )} key={model.value} onSelect={handleModelChange} - ref={ - selectedModel === model.value - ? selectedModelOptionRef - : undefined - } + ref={isSelected ? selectedModelOptionRef : undefined} value={model.value} > <span className={cn( 'min-w-0 truncate', - selectedModel === model.value + isSelected ? modelGroupSelectorLayoutClasses.selectedModelText : modelGroupSelectorLayoutClasses.unselectedModelText )} > {model.label} </span> <Check className={cn( 'size-3.5 shrink-0', - selectedModel === model.value ? 'opacity-100' : 'opacity-0' + isSelected ? 'opacity-100' : 'opacity-0' )} /> </CommandItem> + ) + })() ))}(Alternatively, extract a small
ModelListItemcomponent that takesisSelectedas a prop for a cleaner structure.)🤖 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/components/model-group-selector.tsx` around lines 744 - 777, In the filteredModels mapping inside model-group-selector.tsx, the selectedModel === model.value check is duplicated multiple times per row, making the JSX noisy and inconsistent with renderGroupList. Extract a local isSelected boolean before returning each CommandItem, then reuse it for className, ref, the span text class, and the Check opacity logic; alternatively, move the row into a small ModelListItem component that receives isSelected. Use the existing filteredModels map and CommandItem rendering as the place to apply the refactor.web/default/src/features/playground/components/input/playground-parameter-panel.tsx (1)
201-217: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHide the count badge when no parameters are enabled.
The badge always renders, showing "0" when
activeCountis 0. Consider only rendering it whenactiveCount > 0to avoid a misleading persistent indicator.🎨 Proposed fix
<SlidersHorizontalIcon size={16} /> - <span className='bg-primary text-primary-foreground absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full px-1 text-[9px] leading-none font-semibold'> - {activeCount} - </span> + {activeCount > 0 && ( + <span className='bg-primary text-primary-foreground absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full px-1 text-[9px] leading-none font-semibold'> + {activeCount} + </span> + )}🤖 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/playground/components/input/playground-parameter-panel.tsx` around lines 201 - 217, The parameter count badge in the playground parameter panel should not render when no controls are enabled. Update the trigger UI in playground-parameter-panel.tsx around the PromptInputButton/activeCount logic so the badge is conditionally shown only when activeCount is greater than zero, while leaving the existing count calculation and button behavior unchanged.web/default/src/features/playground/lib/parameters/playground-parameters.ts (1)
19-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNarrow
ParameterValueto the actual parameter keys.
ParameterValue = PlaygroundConfig[keyof PlaygroundConfig]pulls inmodel/group(string) andstream(boolean) even thoughgetParameterControlValueTextonly ever receives values for the six numeric/nullable parameter keys. Narrowing this toPlaygroundConfig[PlaygroundParameterKey]would give a tighter, more accurate type without any behavior change.♻️ Proposed refactor
-type ParameterValue = PlaygroundConfig[keyof PlaygroundConfig] - export type PlaygroundParameterKey = keyof ParameterEnabled + +type ParameterValue = PlaygroundConfig[PlaygroundParameterKey]Also applies to: 120-129
🤖 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/playground/lib/parameters/playground-parameters.ts` around lines 19 - 22, Narrow the `ParameterValue` alias in `playground-parameters.ts` so it only covers the actual numeric/nullable parameter keys used by `getParameterControlValueText`, instead of `PlaygroundConfig[keyof PlaygroundConfig]` which also includes `model`, `group`, and `stream`. Update the type to use `PlaygroundConfig[PlaygroundParameterKey]` (or an equivalent key-restricted union) and keep the existing behavior unchanged while tightening the types around `getParameterControlValueText` and related parameter helpers.
🤖 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/components/model-group-selector.tsx`:
- Around line 621-642: The mobile auto-scroll in the useEffect around
scrollSelectedOptionIntoView is targeting the wrong container, so the selected
group cannot actually scroll into view on mobile. Update the open-state scroll
logic in model-group-selector.tsx to avoid passing groupScrollContainerRef when
the group list is not the scrollable ancestor, and let the
selectedGroupOptionRef use native scrollIntoView behavior on mobile like
selectedModelOptionRef. Keep the desktop path using the group scroll container,
and make sure the layout condition in
modelGroupSelectorLayoutClasses.groupScroll matches the ref usage.
In `@web/default/src/i18n/locales/zh-TW.json`:
- Line 1507: The zh-TW locale entry for the referral-rewards message regressed
to the English source text; replace the value in zh-TW.json with the proper
Traditional Chinese translation for the string used by this referral rewards
copy so zh-TW users no longer see English. Keep the key unchanged and update
only the translated value for this locale entry.
---
Nitpick comments:
In `@web/default/src/components/model-group-selector.tsx`:
- Around line 1-834: The file is far over the recommended size, so split the
large selectors into smaller pieces. Extract the shared trigger UI and the
list-rendering logic from ModelSelector, GroupSelector, and ModelGroupSelector
into dedicated subcomponents, and move the open-state scrolling/refs logic into
a custom hook such as useModelGroupScrollIntoView. Keep the existing symbols
like ModelGroupSelector, renderGroupList, renderModelList, and
scrollSelectedOptionIntoView as the main entry points while relocating
implementation details into separate files or helpers.
- Around line 744-777: In the filteredModels mapping inside
model-group-selector.tsx, the selectedModel === model.value check is duplicated
multiple times per row, making the JSX noisy and inconsistent with
renderGroupList. Extract a local isSelected boolean before returning each
CommandItem, then reuse it for className, ref, the span text class, and the
Check opacity logic; alternatively, move the row into a small ModelListItem
component that receives isSelected. Use the existing filteredModels map and
CommandItem rendering as the place to apply the refactor.
In
`@web/default/src/features/playground/components/input/playground-parameter-panel.tsx`:
- Around line 201-217: The parameter count badge in the playground parameter
panel should not render when no controls are enabled. Update the trigger UI in
playground-parameter-panel.tsx around the PromptInputButton/activeCount logic so
the badge is conditionally shown only when activeCount is greater than zero,
while leaving the existing count calculation and button behavior unchanged.
In `@web/default/src/features/playground/lib/parameters/playground-parameters.ts`:
- Around line 19-22: Narrow the `ParameterValue` alias in
`playground-parameters.ts` so it only covers the actual numeric/nullable
parameter keys used by `getParameterControlValueText`, instead of
`PlaygroundConfig[keyof PlaygroundConfig]` which also includes `model`, `group`,
and `stream`. Update the type to use `PlaygroundConfig[PlaygroundParameterKey]`
(or an equivalent key-restricted union) and keep the existing behavior unchanged
while tightening the types around `getParameterControlValueText` and related
parameter helpers.
🪄 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: f5326b8b-aa9e-4dff-bfbd-9abf8f066a86
📒 Files selected for processing (16)
web/default/src/components/model-group-selector-layout.tsweb/default/src/components/model-group-selector.tsxweb/default/src/features/playground/components/input/playground-input-tools.tsxweb/default/src/features/playground/components/input/playground-input.tsxweb/default/src/features/playground/components/input/playground-parameter-panel.tsxweb/default/src/features/playground/index.tsxweb/default/src/features/playground/lib/index.tsweb/default/src/features/playground/lib/parameters/playground-parameters.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-TW.jsonweb/default/src/i18n/locales/zh.jsonweb/default/src/i18n/static-keys.ts
| useEffect(() => { | ||
| if (!open) { | ||
| return | ||
| } | ||
|
|
||
| let secondFrameId = 0 | ||
| const firstFrameId = window.requestAnimationFrame(() => { | ||
| secondFrameId = window.requestAnimationFrame(() => { | ||
| scrollSelectedOptionIntoView( | ||
| selectedGroupOptionRef.current, | ||
| groupScrollContainerRef.current | ||
| ) | ||
| scrollSelectedOptionIntoView(selectedModelOptionRef.current) | ||
| }) | ||
| }) | ||
|
|
||
| return () => { | ||
| window.cancelAnimationFrame(firstFrameId) | ||
| window.cancelAnimationFrame(secondFrameId) | ||
| } | ||
| }, [open, selectedGroup, selectedModel]) | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Mobile group auto-scroll is a no-op.
groupScrollContainerRef is attached unconditionally, but the container only gets overflow-y-auto/scrollable layout (modelGroupSelectorLayoutClasses.groupScroll) when !isMobile (Line 669-684). On mobile the group list has no overflow set, so scrollTop/scrollTo assignments in scrollSelectedOptionIntoView are effectively no-ops — the selected group is never actually scrolled into view, contradicting the PR's "auto-scrolling to the current selection when opened" goal for mobile. The real scroll container on mobile is the Drawer's own wrapper (overflow-y-auto, further down in the render tree), so this ref/container mismatch silently breaks the intended UX on mobile.
🔧 Proposed fix
scrollSelectedOptionIntoView(
selectedGroupOptionRef.current,
- groupScrollContainerRef.current
+ isMobile ? undefined : groupScrollContainerRef.current
)This makes the mobile path fall back to native scrollIntoView, which will correctly locate the Drawer's scrollable ancestor (as already happens for selectedModelOptionRef).
Also applies to: 669-684
🤖 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/components/model-group-selector.tsx` around lines 621 - 642,
The mobile auto-scroll in the useEffect around scrollSelectedOptionIntoView is
targeting the wrong container, so the selected group cannot actually scroll into
view on mobile. Update the open-state scroll logic in model-group-selector.tsx
to avoid passing groupScrollContainerRef when the group list is not the
scrollable ancestor, and let the selectedGroupOptionRef use native
scrollIntoView behavior on mobile like selectedModelOptionRef. Keep the desktop
path using the group scroll container, and make sure the layout condition in
modelGroupSelectorLayoutClasses.groupScroll matches the ref usage.
| "Each tier supports up to 2 conditions; the last tier is the catch-all without conditions. Use full input length for tier conditions to avoid mis-routing when cache hits reduce billable input tokens.": "每個檔位最多支援 2 個條件;最後一個檔位是不帶條件的兜底檔。建議使用完整輸入長度作為檔位條件,避免緩存命中減少收費輸入 token 後誤判檔位。", | ||
| "Each tier supports up to 2 conditions. The last tier without conditions is the fallback.": "每個階梯最多支援 2 個條件。最後一個無條件階梯作為兜底。", | ||
| "Earn rewards when your referrals add funds. Transfer accumulated rewards to your balance anytime.": "當您的推薦人儲值時即可獲得獎勵。隨時將累計獎勵轉移到您的餘額。", | ||
| "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.": "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Untranslated string regressed to English.
The zh-TW value for this referral-rewards message is now identical to the English source text instead of a Traditional Chinese translation, so zh-TW users will see English here.
🌐 Proposed fix
- "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.": "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.",
+ "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.": "當用戶透過您的推薦連結加入時獲得獎勵。可隨時將累積獎勵轉入您的餘額。",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.": "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.", | |
| "Earn rewards when users join through your referral link. Transfer accumulated rewards to your balance anytime.": "當用戶透過您的推薦連結加入時獲得獎勵。可隨時將累積獎勵轉入您的餘額。", |
🤖 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/zh-TW.json` at line 1507, The zh-TW locale entry
for the referral-rewards message regressed to the English source text; replace
the value in zh-TW.json with the proper Traditional Chinese translation for the
string used by this referral rewards copy so zh-TW users no longer see English.
Keep the key unchanged and update only the translated value for this locale
entry.
…s#6044) Merge pull request QuantumNous#6044 from QuantumNous/feat/playground-parameter-panel
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
概述
改动说明
使用方式
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)


Summary by CodeRabbit
New Features
Bug Fixes