@@ -4,7 +4,7 @@ import SkillsTags from "@/webview/components/SkillsTags";
44import ContextIndicator from "@/webview/components/ContextIndicator" ;
55import { PromptAttachments , usePromptAttachments } from "@/webview/components/PromptAttachments" ;
66import type { ActiveEditor , EditingMessage , SessionMessage , SkillInfo , TokenTelemetry } from "@/webview/types" ;
7- import { FileCodeIcon , Reply , Siren , Square } from "lucide-react" ;
7+ import { FileCodeIcon , Hand , Reply , Siren , Square , SquareChartGantt } from "lucide-react" ;
88import { InputGroup , InputGroupAddon , InputGroupButton , InputGroupTextarea } from "@/webview/components/ui/input-group" ;
99import { Separator } from "@/webview/components/ui/separator" ;
1010import { HoverCard , HoverCardContent , HoverCardTrigger } from "./ui/hover-card" ;
@@ -13,6 +13,16 @@ import { Field, FieldDescription, FieldGroup } from "./ui/field";
1313import { Spinner } from "@/webview/components/ui/spinner" ;
1414import { Switch } from "@/webview/components/ui/switch" ;
1515import { Tooltip , TooltipContent , TooltipTrigger } from "@/webview/components/ui/tooltip" ;
16+ import {
17+ DropdownMenu ,
18+ DropdownMenuContent ,
19+ DropdownMenuGroup ,
20+ DropdownMenuLabel ,
21+ DropdownMenuRadioGroup ,
22+ DropdownMenuRadioItem ,
23+ DropdownMenuTrigger ,
24+ } from "@/webview/components/ui/dropdown-menu" ;
25+ import { Item , ItemContent , ItemDescription , ItemMedia , ItemTitle } from "@/webview/components/ui/item" ;
1626
1727export interface InputPromptProps {
1828 loading : boolean ;
@@ -54,7 +64,7 @@ export default function InputPrompt({
5464 onClearEditingMessage,
5565} : InputPromptProps ) {
5666 const [ value , setValue ] = useState < string > ( "" ) ;
57- const [ planMode , setPlanMode ] = useState < boolean > ( false ) ;
67+ const [ planMode , setPlanMode ] = useState < "false" | "true" > ( " false" ) ;
5868 const [ history , setHistory ] = useState < string [ ] > ( [ ] ) ;
5969 const [ historyIdx , setHistoryIdx ] = useState < number > ( - 1 ) ;
6070 const [ draftBeforeHistory , setDraftBeforeHistory ] = useState < string > ( "" ) ;
@@ -125,7 +135,7 @@ export default function InputPrompt({
125135 setValue ( "" ) ;
126136 setHistoryIdx ( - 1 ) ;
127137
128- onSendPrompt ( trimmed , selectedSkills , images , { ...reply , planMode } ) ;
138+ onSendPrompt ( trimmed , selectedSkills , images , { ...reply , planMode : planMode === "true" } ) ;
129139 onSelectSkills ( [ ] ) ;
130140 clearAttachments ( ) ;
131141 onClearEditingMessage ( ) ;
@@ -237,18 +247,6 @@ export default function InputPrompt({
237247 } }
238248 />
239249 < Separator orientation = "vertical" className = "h-5 mt-1.5" />
240- < Tooltip >
241- < TooltipTrigger asChild >
242- < div className = "flex items-center gap-1 cursor-pointer" >
243- < Siren className = "size-3.5" />
244- < Switch id = "switch-size-sm" checked = { planMode } onCheckedChange = { ( e ) => setPlanMode ( e ) } size = "sm" />
245- </ div >
246- </ TooltipTrigger >
247- < TooltipContent side = "bottom" >
248- < p > Plan Mode</ p >
249- </ TooltipContent >
250- </ Tooltip >
251- < Separator orientation = "vertical" className = "h-5 mt-1.5" />
252250 < ContextIndicator tokenTelemetry = { tokenTelemetry } />
253251 < Separator orientation = "vertical" className = "h-5 mt-1.5" />
254252 { activeEditor && (
@@ -272,31 +270,86 @@ export default function InputPrompt({
272270 </ HoverCardContent >
273271 </ HoverCard >
274272 ) }
275- { loading ? (
276- < InputGroupButton
277- variant = "secondary"
278- size = "icon-sm"
279- className = "ml-auto group"
280- onClick = { onInterrupt }
281- title = "Stop"
282- >
283- < Square className = "h-3 w-3 hidden fill-primary group-hover:block" strokeWidth = { 0 } />
284- < Spinner className = "h-4 w-4 block group-hover:hidden text-primary" />
285- </ InputGroupButton >
286- ) : (
287- < InputGroupButton
288- variant = "default"
289- className = { cn ( "ml-auto cursor-pointer" , {
290- "cursor-not-allowed!" : ! hasContent && ! loading ,
291- } ) }
292- onClick = { handleSend }
293- disabled = { ! hasContent && ! loading }
294- title = "Send"
295- size = "icon-sm"
296- >
297- < Reply className = "rotate-x-180" />
298- </ InputGroupButton >
299- ) }
273+ < div className = "ml-auto flex gap-2 items-center" >
274+ < DropdownMenu >
275+ < DropdownMenuTrigger asChild >
276+ < InputGroupButton variant = "ghost" className = "h-8" >
277+ { planMode === "true" ? (
278+ < div className = "flex items-center gap-0.5" >
279+ < SquareChartGantt className = "size-3.5" strokeWidth = { 1.5 } />
280+ < span className = "text-xs font-normal" > Plan</ span >
281+ </ div >
282+ ) : (
283+ < div className = "flex items-center gap-0.5" >
284+ < Hand className = "size-3.5" strokeWidth = { 1.5 } />
285+ < span className = "text-xs font-normal" > Default</ span >
286+ </ div >
287+ ) }
288+ </ InputGroupButton >
289+ </ DropdownMenuTrigger >
290+ < DropdownMenuContent className = "w-80" side = "top" align = "end" >
291+ < DropdownMenuGroup >
292+ < DropdownMenuLabel > Modes</ DropdownMenuLabel >
293+ < DropdownMenuRadioGroup
294+ value = { planMode }
295+ onValueChange = { ( value ) => setPlanMode ( value as "true" | "false" ) }
296+ >
297+ < DropdownMenuRadioItem value = "false" >
298+ < Item size = "xs" >
299+ < ItemMedia variant = "icon" >
300+ < Hand className = "size-4.5 mt-2.5" strokeWidth = { 1.5 } />
301+ </ ItemMedia >
302+ < ItemContent >
303+ < ItemTitle className = "text-xs" > Default</ ItemTitle >
304+ < ItemDescription className = "text-[10px]" >
305+ Deep code will ask for approval before making each edit
306+ </ ItemDescription >
307+ </ ItemContent >
308+ </ Item >
309+ </ DropdownMenuRadioItem >
310+ < DropdownMenuRadioItem value = "true" >
311+ < Item size = "xs" >
312+ < ItemMedia variant = "icon" >
313+ < SquareChartGantt className = "size-4.5 mt-2.5" strokeWidth = { 1.5 } />
314+ </ ItemMedia >
315+ < ItemContent >
316+ < ItemTitle className = "text-xs" > Plan</ ItemTitle >
317+ < ItemDescription className = "text-[8px]" >
318+ Deep code will explore the code and present a plan before editing
319+ </ ItemDescription >
320+ </ ItemContent >
321+ </ Item >
322+ </ DropdownMenuRadioItem >
323+ </ DropdownMenuRadioGroup >
324+ </ DropdownMenuGroup >
325+ </ DropdownMenuContent >
326+ </ DropdownMenu >
327+ { loading ? (
328+ < InputGroupButton
329+ variant = "secondary"
330+ size = "icon-sm"
331+ className = "group"
332+ onClick = { onInterrupt }
333+ title = "Stop"
334+ >
335+ < Square className = "h-3 w-3 hidden fill-primary group-hover:block" strokeWidth = { 0 } />
336+ < Spinner className = "h-4 w-4 block group-hover:hidden text-primary" />
337+ </ InputGroupButton >
338+ ) : (
339+ < InputGroupButton
340+ variant = "default"
341+ className = { cn ( "cursor-pointer" , {
342+ "cursor-not-allowed!" : ! hasContent && ! loading ,
343+ } ) }
344+ onClick = { handleSend }
345+ disabled = { ! hasContent && ! loading }
346+ title = "Send"
347+ size = "icon-sm"
348+ >
349+ < Reply className = "rotate-x-180" />
350+ </ InputGroupButton >
351+ ) }
352+ </ div >
300353 </ InputGroupAddon >
301354 < SkillsTags
302355 selectedSkills = { selectedSkills }
0 commit comments