@@ -39,6 +39,9 @@ interface ChatViewProps {
3939 showHistoryView : ( ) => void
4040 onTaskSelect : ( task : IHaiClineTask ) => void
4141 selectedHaiTask : IHaiClineTask | null
42+ haiConfig : {
43+ [ x : string ] : any
44+ }
4245}
4346
4447export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
@@ -50,6 +53,7 @@ const ChatView = ({
5053 showHistoryView,
5154 onTaskSelect,
5255 selectedHaiTask,
56+ haiConfig,
5357} : ChatViewProps ) => {
5458 const { version, clineMessages : messages , taskHistory, apiConfiguration, telemetrySetting } = useExtensionState ( )
5559
@@ -90,14 +94,18 @@ const ChatView = ({
9094 const disableAutoScrollRef = useRef ( false )
9195 const [ showScrollToBottom , setShowScrollToBottom ] = useState ( false )
9296 const [ isAtBottom , setIsAtBottom ] = useState ( false )
97+ const [ lastSuccessfullyExecutedTaskId , setLastSuccessfullyExecutedTaskId ] = useState < string | undefined > ( undefined )
9398
9499 // UI layout depends on the last 2 messages
95100 // (since it relies on the content of these messages, we are deep comparing. i.e. the button state after hitting button sets enableButtons to false, and this effect otherwise would have to true again even if messages didn't change
96101 const lastMessage = useMemo ( ( ) => messages . at ( - 1 ) , [ messages ] )
97102 const secondLastMessage = useMemo ( ( ) => messages . at ( - 2 ) , [ messages ] )
98103
99104 useEffect ( ( ) => {
100- selectedHaiTask && setInputValue ( `Task: ${ selectedHaiTask . list } ${ selectedHaiTask . acceptance } ${ selectedHaiTask . context } ` )
105+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
106+ selectedHaiTask &&
107+ selectedHaiTask ?. id &&
108+ setInputValue ( `Task: ${ selectedHaiTask . list } ${ selectedHaiTask . acceptance } ${ selectedHaiTask . context } ` )
101109 } , [ selectedHaiTask ] )
102110
103111 useDeepCompareEffect ( ( ) => {
@@ -200,6 +208,7 @@ const ChatView = ({
200208 setEnableButtons ( ! isPartial )
201209 setPrimaryButtonText ( "Start New Task" )
202210 setSecondaryButtonText ( undefined )
211+ setLastSuccessfullyExecutedTaskId ( selectedHaiTask ?. id )
203212 break
204213 case "resume_task" :
205214 setTextAreaDisabled ( false )
@@ -378,6 +387,9 @@ const ChatView = ({
378387 setSelectedImages ( [ ] )
379388 break
380389 case "completion_result" :
390+ clearSelectedHaiTaskId ( )
391+ startNewTask ( )
392+ break
381393 case "resume_completed_task" :
382394 // extension waiting for feedback. but we can just present a new task button
383395 startNewTask ( )
@@ -467,6 +479,10 @@ const ChatView = ({
467479 textAreaRef . current ?. focus ( )
468480 }
469481 break
482+ case "chatButtonClicked" :
483+ // Starting new chat so setting the current selected HaiTask Id to null
484+ clearSelectedHaiTaskId ( )
485+ break
470486 }
471487 break
472488 case "selectedImages" :
@@ -499,6 +515,10 @@ const ChatView = ({
499515 handleSecondaryButtonClick ( message . text ?? "" , message . images ?? [ ] )
500516 break
501517 }
518+ break
519+ case "writeTaskStatus" :
520+ if ( message . writeTaskStatusResult ?. success && message . writeTaskStatusResult ?. status === "Completed" )
521+ setLastSuccessfullyExecutedTaskId ( undefined )
502522 }
503523 // textAreaRef.current is not explicitly required here since react guarantees that ref will be stable across re-renders, and we're not using its value but its reference.
504524 } ,
@@ -790,6 +810,16 @@ const ChatView = ({
790810 [ expandedRows , modifiedMessages , groupedMessages . length , toggleRowExpansion , handleRowHeightChange ] ,
791811 )
792812
813+ const clearSelectedHaiTaskId = ( ) => {
814+ onTaskSelect ( {
815+ acceptance : selectedHaiTask ?. acceptance ?? "" ,
816+ context : selectedHaiTask ?. context ?? "" ,
817+ id : "" ,
818+ list : selectedHaiTask ?. list ?? "" ,
819+ status : selectedHaiTask ?. status ?? "" ,
820+ } )
821+ }
822+
793823 return (
794824 < div
795825 style = { {
@@ -910,6 +940,45 @@ const ChatView = ({
910940 />
911941 </ div >
912942 < AutoApproveMenu />
943+ { selectedHaiTask ?. id &&
944+ enableButtons &&
945+ ! isStreaming &&
946+ lastSuccessfullyExecutedTaskId &&
947+ selectedHaiTask ?. id === lastSuccessfullyExecutedTaskId && (
948+ < div style = { { padding : "12px 15px 0px" } } >
949+ < p style = { { margin : "0px 0px 6px" } } > Do you want to mark this task as completed?</ p >
950+ < div
951+ style = { {
952+ display : "flex" ,
953+ } } >
954+ < VSCodeButton
955+ appearance = "primary"
956+ style = { {
957+ marginRight : "6px" ,
958+ flexGrow : 1 ,
959+ } }
960+ onClick = { async ( ) => {
961+ // write status to the file
962+ vscode . postMessage ( {
963+ type : "writeTaskStatus" ,
964+ folder : haiConfig ?. folder ,
965+ taskId : selectedHaiTask ?. id ,
966+ status : "Completed" ,
967+ } )
968+ } } >
969+ Yes
970+ </ VSCodeButton >
971+ < VSCodeButton
972+ appearance = "secondary"
973+ style = { {
974+ flexGrow : 1 ,
975+ } }
976+ onClick = { ( ) => setLastSuccessfullyExecutedTaskId ( undefined ) } >
977+ No
978+ </ VSCodeButton >
979+ </ div >
980+ </ div >
981+ ) }
913982 { showScrollToBottom ? (
914983 < div
915984 style = { {
0 commit comments