1- import { memo , useRef , useState } from "react"
2- import { useWindowSize } from "react-use"
1+ import { memo } from "react"
32import { useTranslation } from "react-i18next"
4- import { VSCodeBadge } from "@vscode/webview-ui-toolkit/react"
5- import { CloudUpload , CloudDownload , FoldVertical } from "lucide-react"
3+ import { FoldVertical } from "lucide-react"
64
75import type { ClineMessage } from "@roo-code/types"
86
97import { getModelMaxOutputTokens } from "@roo/api"
108
11- import { formatLargeNumber } from "@src/utils/format"
12- import { cn } from "@src/lib/utils"
13- import { Button , StandardTooltip } from "@src/components/ui"
9+ import { StandardTooltip } from "@src/components/ui"
1410import { useExtensionState } from "@src/context/ExtensionStateContext"
1511import { useSelectedModel } from "@/components/ui/hooks/useSelectedModel"
1612
17- import Thumbnails from "../common/Thumbnails"
18-
19- import { TaskActions } from "./TaskActions"
20- import { ShareButton } from "./ShareButton"
2113import { ContextWindowProgress } from "./ContextWindowProgress"
22- import { Mention } from "./Mention"
2314import { TodoListDisplay } from "./TodoListDisplay"
2415
2516export interface TaskHeaderProps {
2617 task : ClineMessage
27- tokensIn : number
28- tokensOut : number
29- cacheWrites ?: number
30- cacheReads ?: number
31- totalCost : number
3218 contextTokens : number
3319 buttonsDisabled : boolean
3420 handleCondenseContext : ( taskId : string ) => void
35- onClose : ( ) => void
3621 todos ?: any [ ]
3722}
3823
39- const TaskHeader = ( {
40- task,
41- tokensIn,
42- tokensOut,
43- cacheWrites,
44- cacheReads,
45- totalCost,
46- contextTokens,
47- buttonsDisabled,
48- handleCondenseContext,
49- onClose,
50- todos,
51- } : TaskHeaderProps ) => {
24+ const TaskHeader = ( { task, contextTokens, buttonsDisabled, handleCondenseContext, todos } : TaskHeaderProps ) => {
5225 const { t } = useTranslation ( )
5326 const { apiConfiguration, currentTaskItem } = useExtensionState ( )
5427 const { id : modelId , info : model } = useSelectedModel ( apiConfiguration )
55- const [ isTaskExpanded , setIsTaskExpanded ] = useState ( false )
5628
57- const textContainerRef = useRef < HTMLDivElement > ( null )
58- const textRef = useRef < HTMLDivElement > ( null )
5929 const contextWindow = model ?. contextWindow || 1
6030
61- const { width : windowWidth } = useWindowSize ( )
62-
6331 const condenseButton = (
6432 < StandardTooltip content = { t ( "chat:task.condenseContext" ) } >
6533 < button
@@ -75,42 +43,15 @@ const TaskHeader = ({
7543
7644 return (
7745 < div className = "py-2 px-3" >
78- < div
79- className = { cn (
80- "p-2.5 flex flex-col gap-1.5 relative z-1 border" ,
81- hasTodos ? "rounded-t-xs border-b-0" : "rounded-xs" ,
82- isTaskExpanded
83- ? "border-vscode-panel-border text-vscode-foreground"
84- : "border-vscode-panel-border/80 text-vscode-foreground/80" ,
85- ) } >
86- < div className = "flex justify-between items-center gap-2" >
87- < div
88- className = "flex items-center cursor-pointer -ml-0.5 select-none grow min-w-0"
89- onClick = { ( ) => setIsTaskExpanded ( ! isTaskExpanded ) } >
90- < div className = "flex items-center shrink-0" >
91- < span className = { `codicon codicon-chevron-${ isTaskExpanded ? "down" : "right" } ` } > </ span >
92- </ div >
93- < div className = "ml-1.5 whitespace-nowrap overflow-hidden text-ellipsis grow min-w-0" >
94- < span className = "font-bold" >
95- { t ( "chat:task.title" ) }
96- { ! isTaskExpanded && ":" }
97- </ span >
98- { ! isTaskExpanded && (
99- < span className = "ml-1" >
100- < Mention text = { task . text } />
101- </ span >
102- ) }
103- </ div >
46+ { /* Context Window Progress */ }
47+ { contextWindow > 0 && (
48+ < div className = "p-2.5 flex flex-col gap-1.5 relative z-1 border border-vscode-panel-border/80 rounded-xs mb-2" >
49+ < div className = "flex items-center gap-1 flex-shrink-0" >
50+ < span className = "font-bold text-sm text-vscode-foreground/80" >
51+ { t ( "chat:task.contextWindow" ) }
52+ </ span >
10453 </ div >
105- < StandardTooltip content = { t ( "chat:task.closeAndStart" ) } >
106- < Button variant = "ghost" size = "icon" onClick = { onClose } className = "shrink-0 w-5 h-5" >
107- < span className = "codicon codicon-close" />
108- </ Button >
109- </ StandardTooltip >
110- </ div >
111- { /* Collapsed state: Track context and cost if we have any */ }
112- { ! isTaskExpanded && contextWindow > 0 && (
113- < div className = { `w-full flex flex-row items-center gap-1 h-auto` } >
54+ < div className = "w-full flex flex-row items-center gap-1 h-auto" >
11455 < ContextWindowProgress
11556 contextWindow = { contextWindow }
11657 contextTokens = { contextTokens || 0 }
@@ -121,105 +62,11 @@ const TaskHeader = ({
12162 }
12263 />
12364 { condenseButton }
124- < ShareButton item = { currentTaskItem } disabled = { buttonsDisabled } />
125- { ! ! totalCost && < VSCodeBadge > ${ totalCost . toFixed ( 2 ) } </ VSCodeBadge > }
12665 </ div >
127- ) }
128- { /* Expanded state: Show task text and images */ }
129- { isTaskExpanded && (
130- < >
131- < div
132- ref = { textContainerRef }
133- className = "-mt-0.5 text-vscode-font-size overflow-y-auto break-words break-anywhere relative" >
134- < div
135- ref = { textRef }
136- className = "overflow-auto max-h-80 whitespace-pre-wrap break-words break-anywhere"
137- style = { {
138- display : "-webkit-box" ,
139- WebkitLineClamp : "unset" ,
140- WebkitBoxOrient : "vertical" ,
141- } } >
142- < Mention text = { task . text } />
143- </ div >
144- </ div >
145- { task . images && task . images . length > 0 && < Thumbnails images = { task . images } /> }
146-
147- < div className = "flex flex-col gap-1" >
148- { isTaskExpanded && contextWindow > 0 && (
149- < div
150- className = { `w-full flex ${ windowWidth < 400 ? "flex-col" : "flex-row" } gap-1 h-auto` } >
151- < div className = "flex items-center gap-1 flex-shrink-0" >
152- < span className = "font-bold" data-testid = "context-window-label" >
153- { t ( "chat:task.contextWindow" ) }
154- </ span >
155- </ div >
156- < ContextWindowProgress
157- contextWindow = { contextWindow }
158- contextTokens = { contextTokens || 0 }
159- maxTokens = {
160- model
161- ? getModelMaxOutputTokens ( {
162- modelId,
163- model,
164- settings : apiConfiguration ,
165- } )
166- : undefined
167- }
168- />
169- { condenseButton }
170- </ div >
171- ) }
172- < div className = "flex justify-between items-center h-[20px]" >
173- < div className = "flex items-center gap-1 flex-wrap" >
174- < span className = "font-bold" > { t ( "chat:task.tokens" ) } </ span >
175- { typeof tokensIn === "number" && tokensIn > 0 && (
176- < span className = "flex items-center gap-0.5" >
177- < i className = "codicon codicon-arrow-up text-xs font-bold" />
178- { formatLargeNumber ( tokensIn ) }
179- </ span >
180- ) }
181- { typeof tokensOut === "number" && tokensOut > 0 && (
182- < span className = "flex items-center gap-0.5" >
183- < i className = "codicon codicon-arrow-down text-xs font-bold" />
184- { formatLargeNumber ( tokensOut ) }
185- </ span >
186- ) }
187- </ div >
188- { ! totalCost && < TaskActions item = { currentTaskItem } buttonsDisabled = { buttonsDisabled } /> }
189- </ div >
190-
191- { ( ( typeof cacheReads === "number" && cacheReads > 0 ) ||
192- ( typeof cacheWrites === "number" && cacheWrites > 0 ) ) && (
193- < div className = "flex items-center gap-1 flex-wrap h-[20px]" >
194- < span className = "font-bold" > { t ( "chat:task.cache" ) } </ span >
195- { typeof cacheWrites === "number" && cacheWrites > 0 && (
196- < span className = "flex items-center gap-0.5" >
197- < CloudUpload size = { 16 } />
198- { formatLargeNumber ( cacheWrites ) }
199- </ span >
200- ) }
201- { typeof cacheReads === "number" && cacheReads > 0 && (
202- < span className = "flex items-center gap-0.5" >
203- < CloudDownload size = { 16 } />
204- { formatLargeNumber ( cacheReads ) }
205- </ span >
206- ) }
207- </ div >
208- ) }
66+ </ div >
67+ ) }
20968
210- { ! ! totalCost && (
211- < div className = "flex justify-between items-center h-[20px]" >
212- < div className = "flex items-center gap-1" >
213- < span className = "font-bold" > { t ( "chat:task.apiCost" ) } </ span >
214- < span > ${ totalCost ?. toFixed ( 2 ) } </ span >
215- </ div >
216- < TaskActions item = { currentTaskItem } buttonsDisabled = { buttonsDisabled } />
217- </ div >
218- ) }
219- </ div >
220- </ >
221- ) }
222- </ div >
69+ { /* Todo List */ }
22370 < TodoListDisplay todos = { todos ?? ( task as any ) ?. tool ?. todos ?? [ ] } />
22471 </ div >
22572 )
0 commit comments