Skip to content

Commit 539a6c3

Browse files
committed
Implement reasoning effort selection and clearable sampling parameters in the preset form via a new VS Code QuickPick handler and UI updates
1 parent 4ce44e8 commit 539a6c3

12 files changed

Lines changed: 224 additions & 69 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import * as vscode from 'vscode'
2+
import { PanelProvider } from '@/views/panel/backend/panel-provider'
3+
import { PickReasoningEffortMessage } from '@/views/panel/types/messages'
4+
5+
export const handle_pick_reasoning_effort = async (
6+
panel_provider: PanelProvider,
7+
message: PickReasoningEffortMessage
8+
): Promise<void> => {
9+
const items: (vscode.QuickPickItem & { effort?: string })[] = [
10+
{ label: 'Unset', effort: undefined },
11+
...message.supported_efforts.map((effort) => ({
12+
label: effort.charAt(0).toUpperCase() + effort.slice(1),
13+
effort
14+
}))
15+
]
16+
17+
const quick_pick = vscode.window.createQuickPick()
18+
quick_pick.items = items
19+
quick_pick.title = 'Reasoning Efforts'
20+
quick_pick.placeholder = 'Choose a reasoning effort'
21+
22+
if (message.current_effort) {
23+
const active_item = items.find((i) => i.effort === message.current_effort)
24+
if (active_item) quick_pick.activeItems = [active_item]
25+
} else {
26+
quick_pick.activeItems = [items[0]]
27+
}
28+
29+
quick_pick.buttons = [
30+
{
31+
iconPath: new vscode.ThemeIcon('close'),
32+
tooltip: 'Close'
33+
}
34+
]
35+
36+
quick_pick.onDidTriggerButton((button) => {
37+
if (button.tooltip == 'Close') {
38+
quick_pick.hide()
39+
}
40+
})
41+
42+
return new Promise<void>((resolve) => {
43+
quick_pick.onDidAccept(() => {
44+
const selected = quick_pick.selectedItems[0] as any
45+
if (selected) {
46+
panel_provider.send_message({
47+
command: 'NEWLY_PICKED_REASONING_EFFORT',
48+
effort: selected.effort
49+
})
50+
}
51+
quick_pick.hide()
52+
})
53+
54+
quick_pick.onDidHide(() => {
55+
quick_pick.dispose()
56+
resolve()
57+
})
58+
59+
quick_pick.show()
60+
})
61+
}

‎apps/editor/src/views/panel/backend/message-handlers/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export * from './handle-show-prompt-template-quick-pick'
2020
export * from './handle-update-preset'
2121
export * from './handle-pick-chatbot'
2222
export * from './handle-pick-model'
23+
export * from './handle-pick-reasoning-effort'
2324
export * from './handle-save-mode'
2425
export * from './handle-get-mode'
2526
export * from './handle-edit-context'

‎apps/editor/src/views/panel/backend/panel-provider.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import {
5858
handle_toggle_pinned_api_tool_configuration,
5959
handle_pick_model,
6060
handle_pick_chatbot,
61+
handle_pick_reasoning_effort,
6162
handle_focus_on_file_in_preview,
6263
handle_go_to_file,
6364
handle_show_diff,
@@ -873,6 +874,8 @@ export class PanelProvider implements vscode.WebviewViewProvider {
873874
await handle_pick_model(this, message)
874875
} else if (message.command == 'PICK_CHATBOT') {
875876
await handle_pick_chatbot(this, message)
877+
} else if (message.command == 'PICK_REASONING_EFFORT') {
878+
await handle_pick_reasoning_effort(this, message)
876879
} else if (message.command == 'UPDATE_LAST_USED_PRESET') {
877880
update_last_used_preset_or_group({
878881
panel_provider: this,

‎apps/editor/src/views/panel/frontend/Panel.tsx‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,13 @@ export const Panel = () => {
535535
pick_chatbot={(chatbot_id) => {
536536
post_message(vscode, { command: 'PICK_CHATBOT', chatbot_id })
537537
}}
538+
pick_reasoning_effort={(supported_efforts, current_effort) => {
539+
post_message(vscode, {
540+
command: 'PICK_REASONING_EFFORT',
541+
supported_efforts,
542+
current_effort
543+
})
544+
}}
538545
on_at_sign_in_affix={() => {}}
539546
/>
540547
</UiPage>

‎apps/editor/src/views/panel/frontend/components/edit-preset-form/EditPresetForm/EditPresetForm.module.scss‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,18 @@
1111
align-items: flex-start;
1212
gap: 6px;
1313
}
14+
15+
.clear {
16+
color: var(--vscode-textLink-foreground);
17+
white-space: nowrap;
18+
font-size: 12px;
19+
20+
&:disabled {
21+
opacity: 0.5;
22+
cursor: default;
23+
}
24+
25+
&:hover:not(:disabled) {
26+
text-decoration: underline;
27+
}
28+
}

‎apps/editor/src/views/panel/frontend/components/edit-preset-form/EditPresetForm/EditPresetForm.tsx‎

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { Field as UiField } from '@ui/components/editor/panel/Field'
88
import { Slider as UiSlider } from '@ui/components/editor/panel/Slider'
99
import { Input as UiInput } from '@ui/components/editor/common/Input'
1010
import { Textarea as UiTextarea } from '@ui/components/editor/common/Textarea'
11-
import { Dropdown as UiDropdown } from '@ui/components/editor/common/Dropdown'
1211
import { BackendMessage } from '@/views/panel/types/messages'
1312
import { PresetOption as UiPresetOption } from '@ui/components/editor/panel/PresetOption'
1413
import { Scrollable as UiScrollable } from '@ui/components/editor/panel/Scrollable'
@@ -19,6 +18,10 @@ type Props = {
1918
on_update: (updated_preset: Preset) => void
2019
pick_model: (chatbot_name: string, current_model_id?: string) => void
2120
pick_chatbot: (chatbot_id?: keyof typeof CHATBOTS) => void
21+
pick_reasoning_effort: (
22+
supported_efforts: string[],
23+
current_effort?: string
24+
) => void
2225
on_at_sign_in_affix: () => void
2326
}
2427

@@ -58,9 +61,11 @@ export const EditPresetForm: React.FC<Props> = (props) => {
5861
'prompt_prefix' | 'prompt_suffix' | null
5962
>(null)
6063
const [is_prompt_template_collapsed, set_is_prompt_template_collapsed] =
61-
useState(true)
64+
useState(!(props.preset.prompt_prefix || props.preset.prompt_suffix))
6265
const [is_sampling_collapsed, set_is_sampling_collapsed] = useState(true)
63-
const [is_options_collapsed, set_is_options_collapsed] = useState(true)
66+
const [is_options_collapsed, set_is_options_collapsed] = useState(
67+
!props.preset.options?.length
68+
)
6469

6570
const chatbot_config = chatbot ? CHATBOTS[chatbot] : undefined
6671
const models = useMemo(() => chatbot_config?.models || {}, [chatbot_config])
@@ -183,6 +188,8 @@ export const EditPresetForm: React.FC<Props> = (props) => {
183188
set_model(message.model_id)
184189
} else if (message.command == 'NEWLY_PICKED_CHATBOT') {
185190
handle_chatbot_change(message.chatbot_id as keyof typeof CHATBOTS)
191+
} else if (message.command == 'NEWLY_PICKED_REASONING_EFFORT') {
192+
set_reasoning_effort(message.effort)
186193
}
187194
}
188195
window.addEventListener('message', handle_message)
@@ -200,30 +207,21 @@ export const EditPresetForm: React.FC<Props> = (props) => {
200207
}
201208
}
202209

203-
const reasoning_effort_options = useMemo(() => {
204-
const supported_efforts =
210+
const supported_reasoning_efforts = useMemo(() => {
211+
return (
205212
chatbot_config?.supported_reasoning_efforts ||
206-
model_info?.supported_reasoning_efforts
207-
208-
if (supported_efforts) {
209-
return [
210-
{ value: '—', label: '—' },
211-
...supported_efforts.map((effort: string) => {
212-
const capitalized = effort.charAt(0).toUpperCase() + effort.slice(1)
213-
return { value: effort, label: capitalized }
214-
})
215-
]
216-
}
217-
return [{ value: '—', label: '—' }]
213+
model_info?.supported_reasoning_efforts ||
214+
[]
215+
)
218216
}, [chatbot_config, model_info])
219217

220218
useEffect(() => {
221219
if (
222220
reasoning_effort &&
223-
!reasoning_effort_options.find((o) => o.value === reasoning_effort)
221+
!supported_reasoning_efforts.includes(reasoning_effort)
224222
)
225223
set_reasoning_effort(undefined)
226-
}, [reasoning_effort, reasoning_effort_options])
224+
}, [reasoning_effort, supported_reasoning_efforts])
227225

228226
return (
229227
<UiScrollable>
@@ -347,40 +345,55 @@ export const EditPresetForm: React.FC<Props> = (props) => {
347345
chatbot == 'OpenRouter' ? ' Requires a reasoning model.' : ''
348346
}`}
349347
>
350-
<UiDropdown
351-
options={reasoning_effort_options}
352-
value={reasoning_effort || '—'}
353-
onChange={(value) => {
354-
set_reasoning_effort(value == '—' ? undefined : value)
348+
<button
349+
className={dropdown_styles.button}
350+
onClick={(e) => {
351+
e.stopPropagation()
352+
props.pick_reasoning_effort(
353+
supported_reasoning_efforts,
354+
reasoning_effort
355+
)
355356
}}
356-
/>
357+
>
358+
<span>
359+
{reasoning_effort
360+
? reasoning_effort.charAt(0).toUpperCase() +
361+
reasoning_effort.slice(1)
362+
: '—'}
363+
</span>
364+
<span
365+
className={cn(
366+
'codicon codicon-chevron-down',
367+
dropdown_styles.chevron
368+
)}
369+
/>
370+
</button>
357371
</UiField>
358372
)}
359373

360-
{supports_thinking_budget &&
361-
!supports_reasoning_effort && ( // Additional check for AI Studio
362-
<UiField
363-
label="Thinking Budget"
364-
html_for="thinking-budget"
365-
info="Search for allowed min-max values."
366-
>
367-
<UiInput
368-
id="thinking-budget"
369-
type="text"
370-
value={String(thinking_budget ?? '')}
371-
on_change={(value) => {
372-
const num = parseInt(value, 10)
373-
set_thinking_budget(isNaN(num) ? undefined : num)
374-
}}
375-
placeholder="e.g. 8000"
376-
on_key_down={(e) =>
377-
!/[0-9]/.test(e.key) &&
378-
e.key != 'Backspace' &&
379-
e.preventDefault()
380-
}
381-
/>
382-
</UiField>
383-
)}
374+
{supports_thinking_budget && !supports_reasoning_effort && (
375+
<UiField
376+
label="Thinking Budget"
377+
html_for="thinking-budget"
378+
info="Search for allowed min-max values."
379+
>
380+
<UiInput
381+
id="thinking-budget"
382+
type="text"
383+
value={String(thinking_budget ?? '')}
384+
on_change={(value) => {
385+
const num = parseInt(value, 10)
386+
set_thinking_budget(isNaN(num) ? undefined : num)
387+
}}
388+
placeholder="e.g. 8000"
389+
on_key_down={(e) =>
390+
!/[0-9]/.test(e.key) &&
391+
e.key != 'Backspace' &&
392+
e.preventDefault()
393+
}
394+
/>
395+
</UiField>
396+
)}
384397

385398
{supports_system_instructions && (
386399
<UiField
@@ -455,9 +468,19 @@ export const EditPresetForm: React.FC<Props> = (props) => {
455468
<UiField
456469
label="Temperature"
457470
info="Influences response variety. Lower values are more predictable; higher values are more diverse."
471+
action={
472+
temperature !== undefined && (
473+
<button
474+
className={styles.clear}
475+
onClick={() => set_temperature(undefined)}
476+
>
477+
Clear
478+
</button>
479+
)
480+
}
458481
>
459482
<UiSlider
460-
value={temperature ?? 1}
483+
value={temperature}
461484
onChange={set_temperature}
462485
min={0}
463486
max={2}
@@ -469,13 +492,18 @@ export const EditPresetForm: React.FC<Props> = (props) => {
469492
<UiField
470493
label="Top P"
471494
info="Limits token choices to cumulative probability P. Lower values make responses more predictable."
495+
action={
496+
top_p !== undefined && (
497+
<button
498+
className={styles.clear}
499+
onClick={() => set_top_p(undefined)}
500+
>
501+
Clear
502+
</button>
503+
)
504+
}
472505
>
473-
<UiSlider
474-
value={top_p ?? 0.95}
475-
onChange={set_top_p}
476-
min={0}
477-
max={1}
478-
/>
506+
<UiSlider value={top_p} onChange={set_top_p} min={0} max={1} />
479507
</UiField>
480508
)}
481509
</UiFieldset>

‎apps/editor/src/views/panel/types/messages.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ export interface PickChatbotMessage extends BaseMessage {
206206
chatbot_id?: string
207207
}
208208

209+
export interface PickReasoningEffortMessage extends BaseMessage {
210+
command: 'PICK_REASONING_EFFORT'
211+
supported_efforts: string[]
212+
current_effort?: string
213+
}
214+
209215
export interface SaveModeMessage extends BaseMessage {
210216
command: 'SAVE_MODE'
211217
mode: Mode
@@ -570,6 +576,7 @@ export type FrontendMessage =
570576
| CaretPositionChangedWebviewMessage
571577
| PickModelMessage
572578
| PickChatbotMessage
579+
| PickReasoningEffortMessage
573580
| SaveModeMessage
574581
| GetModeMessage
575582
| EditContextMessage
@@ -727,6 +734,11 @@ export interface NewlyPickedChatbotMessage extends BaseMessage {
727734
chatbot_id: string
728735
}
729736

737+
export interface NewlyPickedReasoningEffortMessage extends BaseMessage {
738+
command: 'NEWLY_PICKED_REASONING_EFFORT'
739+
effort?: string
740+
}
741+
730742
export interface ModeMessage extends BaseMessage {
731743
command: 'MODE'
732744
mode: Mode
@@ -903,6 +915,7 @@ export type BackendMessage =
903915
| PresetUpdatedMessage
904916
| NewlyPickedModelMessage
905917
| NewlyPickedChatbotMessage
918+
| NewlyPickedReasoningEffortMessage
906919
| ModeMessage
907920
| WebPromptTypeMessage
908921
| ApiPromptTypeMessage

‎packages/ui/src/components/editor/panel/Field/Field.module.scss‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
flex-direction: column;
44
gap: 4px;
55

6+
&__header {
7+
display: flex;
8+
justify-content: space-between;
9+
align-items: center;
10+
width: 100%;
11+
}
12+
613
&__label {
714
font-size: 12px;
815
font-weight: 600;
916
color: var(--vscode-foreground);
10-
align-self: flex-start;
1117
}
1218

1319
&__info {

0 commit comments

Comments
 (0)