Skip to content

Commit 7cf68ff

Browse files
eomcalebCline Evaluation
andauthored
Improve time display and filter out resume_task in Task Timeline (RooCodeInc#3333)
* Improve time display and filter out resume_task in Task Timeline * changeset * polishing it up a little * a little bigger * more tooltips + task header * further refinement * spacing * moving delete button up one row conditionally * removed log --------- Co-authored-by: Cline Evaluation <[email protected]>
1 parent b8af02e commit 7cf68ff

File tree

6 files changed

+323
-198
lines changed

6 files changed

+323
-198
lines changed

.changeset/smart-otters-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": patch
3+
---
4+
5+
timestamp visualization

webview-ui/src/components/chat/TaskHeader.tsx

Lines changed: 109 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { normalizeApiConfiguration } from "@/components/settings/ApiOptions"
1212
import { validateSlashCommand } from "@/utils/slash-commands"
1313
import TaskTimeline from "./TaskTimeline"
1414
import { TaskServiceClient } from "@/services/grpc-client"
15+
import HeroTooltip from "@/components/common/HeroTooltip"
1516

1617
interface TaskHeaderProps {
1718
task: ClineMessage
@@ -136,12 +137,12 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
136137
)
137138
}, [apiConfiguration?.apiProvider, apiConfiguration?.openAiModelInfo])
138139

139-
const shouldShowPromptCacheInfo =
140-
doesModelSupportPromptCache && apiConfiguration?.apiProvider !== "openrouter" && apiConfiguration?.apiProvider !== "cline"
141-
142-
const shouldShowPromptCacheInfoClineOR =
143-
doesModelSupportPromptCache &&
144-
(apiConfiguration?.apiProvider === "openrouter" || apiConfiguration?.apiProvider === "cline")
140+
const shouldShowPromptCacheInfo = () => {
141+
return (
142+
doesModelSupportPromptCache &&
143+
((cacheReads !== undefined && cacheReads > 0) || (cacheWrites !== undefined && cacheWrites > 0))
144+
)
145+
}
145146

146147
const ContextWindowComponent = (
147148
<>
@@ -152,18 +153,6 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
152153
flexDirection: windowWidth < 270 ? "column" : "row",
153154
gap: "4px",
154155
}}>
155-
<div
156-
style={{
157-
display: "flex",
158-
alignItems: "center",
159-
gap: "4px",
160-
flexShrink: 0, // Prevents shrinking
161-
}}>
162-
<span style={{ fontWeight: "bold" }}>
163-
{/* {windowWidth > 280 && windowWidth < 310 ? "Context:" : "Context Window:"} */}
164-
Context Window:
165-
</span>
166-
</div>
167156
<div
168157
style={{
169158
display: "flex",
@@ -172,32 +161,39 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
172161
flex: 1,
173162
whiteSpace: "nowrap",
174163
}}>
175-
<span>{formatLargeNumber(lastApiReqTotalTokens || 0)}</span>
164+
<HeroTooltip content="Current tokens used in this request">
165+
<span className="cursor-pointer">{formatLargeNumber(lastApiReqTotalTokens || 0)}</span>
166+
</HeroTooltip>
176167
<div
177168
style={{
178169
display: "flex",
179170
alignItems: "center",
180171
gap: "3px",
181172
flex: 1,
182173
}}>
183-
<div
184-
style={{
185-
flex: 1,
186-
height: "4px",
187-
backgroundColor: "color-mix(in srgb, var(--vscode-badge-foreground) 20%, transparent)",
188-
borderRadius: "2px",
189-
overflow: "hidden",
190-
}}>
174+
<HeroTooltip content="Context window usage">
191175
<div
192176
style={{
193-
width: `${((lastApiReqTotalTokens || 0) / contextWindow) * 100}%`,
194-
height: "100%",
195-
backgroundColor: "var(--vscode-badge-foreground)",
177+
flex: 1,
178+
height: "4px",
179+
backgroundColor: "color-mix(in srgb, var(--vscode-badge-foreground) 20%, transparent)",
196180
borderRadius: "2px",
181+
overflow: "hidden",
197182
}}
198-
/>
199-
</div>
200-
<span>{formatLargeNumber(contextWindow)}</span>
183+
className="cursor-pointer">
184+
<div
185+
style={{
186+
width: `${((lastApiReqTotalTokens || 0) / contextWindow) * 100}%`,
187+
height: "100%",
188+
backgroundColor: "var(--vscode-badge-foreground)",
189+
borderRadius: "2px",
190+
}}
191+
/>
192+
</div>
193+
</HeroTooltip>
194+
<HeroTooltip content="Maximum context window size for this model">
195+
<span className="cursor-pointer">{formatLargeNumber(contextWindow)}</span>
196+
</HeroTooltip>
201197
</div>
202198
</div>
203199
</div>
@@ -263,7 +259,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
263259
{!isTaskExpanded && <span style={{ marginLeft: 4 }}>{highlightText(task.text, false)}</span>}
264260
</div>
265261
</div>
266-
{!isTaskExpanded && isCostAvailable && (
262+
{isCostAvailable && (
267263
<div
268264
style={{
269265
marginLeft: 10,
@@ -299,7 +295,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
299295
ref={textRef}
300296
style={{
301297
display: "-webkit-box",
302-
WebkitLineClamp: isTextExpanded ? "unset" : 3,
298+
WebkitLineClamp: isTextExpanded ? "unset" : 2,
303299
WebkitBoxOrient: "vertical",
304300
overflow: "hidden",
305301
whiteSpace: "pre-wrap",
@@ -352,18 +348,19 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
352348
</div>
353349
)}
354350
{task.images && task.images.length > 0 && <Thumbnails images={task.images} />}
351+
355352
<div
356353
style={{
357354
display: "flex",
358355
flexDirection: "column",
359-
gap: "4px",
356+
gap: "2px",
360357
}}>
361358
<div
362359
style={{
363360
display: "flex",
364361
justifyContent: "space-between",
365362
alignItems: "center",
366-
height: 17,
363+
flexWrap: "wrap",
367364
}}>
368365
<div
369366
style={{
@@ -375,140 +372,93 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
375372
<div style={{ display: "flex", alignItems: "center" }}>
376373
<span style={{ fontWeight: "bold" }}>Tokens:</span>
377374
</div>
378-
<span
379-
style={{
380-
display: "flex",
381-
alignItems: "center",
382-
gap: "3px",
383-
}}>
384-
<i
385-
className="codicon codicon-arrow-up"
386-
style={{
387-
fontSize: "12px",
388-
fontWeight: "bold",
389-
marginBottom: "-2px",
390-
}}
391-
/>
392-
{formatLargeNumber(tokensIn || 0)}
393-
</span>
394-
<span
395-
style={{
396-
display: "flex",
397-
alignItems: "center",
398-
gap: "3px",
399-
}}>
400-
<i
401-
className="codicon codicon-arrow-down"
402-
style={{
403-
fontSize: "12px",
404-
fontWeight: "bold",
405-
marginBottom: "-2px",
406-
}}
407-
/>
408-
{formatLargeNumber(tokensOut || 0)}
409-
</span>
410-
</div>
411-
{!isCostAvailable && (
412-
<DeleteButton taskSize={formatSize(currentTaskItem?.size)} taskId={currentTaskItem?.id} />
413-
)}
414-
</div>
415-
416-
<TaskTimeline messages={clineMessages} />
417-
418-
{shouldShowPromptCacheInfoClineOR && cacheReads !== undefined && (
419-
<div
420-
style={{
421-
display: "flex",
422-
alignItems: "center",
423-
gap: "4px",
424-
flexWrap: "wrap",
425-
}}>
426-
<span style={{ fontWeight: "bold" }}>Cache:</span>
427-
<span
428-
style={{
429-
display: "flex",
430-
alignItems: "center",
431-
gap: "3px",
432-
}}>
433-
<i
434-
className="codicon codicon-arrow-right"
435-
style={{
436-
fontSize: "12px",
437-
fontWeight: "bold",
438-
marginBottom: 0,
439-
}}
440-
/>
441-
{formatLargeNumber(cacheReads || 0)}
442-
</span>
443-
</div>
444-
)}
445-
{shouldShowPromptCacheInfo &&
446-
(cacheReads !== undefined ||
447-
cacheWrites !== undefined ||
448-
apiConfiguration?.apiProvider === "anthropic") && (
449-
<div
450-
style={{
451-
display: "flex",
452-
alignItems: "center",
453-
gap: "4px",
454-
flexWrap: "wrap",
455-
}}>
456-
<span style={{ fontWeight: "bold" }}>Cache:</span>
457-
<span
458-
style={{
459-
display: "flex",
460-
alignItems: "center",
461-
gap: "3px",
462-
}}>
375+
<HeroTooltip content="Prompt Tokens">
376+
<span className="flex items-center gap-[3px] cursor-pointer">
463377
<i
464-
className="codicon codicon-database"
378+
className="codicon codicon-arrow-up"
465379
style={{
466380
fontSize: "12px",
467381
fontWeight: "bold",
468-
marginBottom: "-1px",
382+
marginBottom: "-2px",
469383
}}
470384
/>
471-
+{formatLargeNumber(cacheWrites || 0)}
385+
{formatLargeNumber(tokensIn || 0)}
472386
</span>
473-
<span
474-
style={{
475-
display: "flex",
476-
alignItems: "center",
477-
gap: "3px",
478-
}}>
387+
</HeroTooltip>
388+
<HeroTooltip content="Completion Tokens">
389+
<span className="flex items-center gap-[3px] cursor-pointer">
479390
<i
480-
className="codicon codicon-arrow-right"
391+
className="codicon codicon-arrow-down"
481392
style={{
482393
fontSize: "12px",
483394
fontWeight: "bold",
484-
marginBottom: 0,
395+
marginBottom: "-2px",
485396
}}
486397
/>
487-
{formatLargeNumber(cacheReads || 0)}
398+
{formatLargeNumber(tokensOut || 0)}
488399
</span>
489-
</div>
400+
</HeroTooltip>
401+
</div>
402+
{!shouldShowPromptCacheInfo() && (
403+
<DeleteButton taskSize={formatSize(currentTaskItem?.size)} taskId={currentTaskItem?.id} />
490404
)}
491-
{ContextWindowComponent}
492-
{isCostAvailable && (
405+
</div>
406+
{shouldShowPromptCacheInfo() && (
493407
<div
494408
style={{
495409
display: "flex",
496410
justifyContent: "space-between",
497411
alignItems: "center",
498-
height: 17,
412+
flexWrap: "wrap",
499413
}}>
500414
<div
501415
style={{
502416
display: "flex",
503417
alignItems: "center",
504418
gap: "4px",
419+
flexWrap: "wrap",
505420
}}>
506-
<span style={{ fontWeight: "bold" }}>API Cost:</span>
507-
<span>${totalCost?.toFixed(4)}</span>
421+
<div style={{ display: "flex", alignItems: "center" }}>
422+
<span style={{ fontWeight: "bold" }}>Cache:</span>
423+
</div>
424+
{cacheWrites !== undefined && cacheWrites > 0 && (
425+
<HeroTooltip content="Tokens written to cache">
426+
<span className="flex items-center gap-[3px] cursor-pointer">
427+
<i
428+
className="codicon codicon-database"
429+
style={{
430+
fontSize: "12px",
431+
fontWeight: "bold",
432+
marginBottom: "-1px",
433+
}}
434+
/>
435+
+{formatLargeNumber(cacheWrites || 0)}
436+
</span>
437+
</HeroTooltip>
438+
)}
439+
{cacheReads !== undefined && cacheReads > 0 && (
440+
<HeroTooltip content="Tokens read from cache">
441+
<span className="flex items-center gap-[3px] cursor-pointer">
442+
<i
443+
className={"codicon codicon-arrow-right"}
444+
style={{
445+
fontSize: "12px",
446+
fontWeight: "bold",
447+
marginBottom: 0,
448+
}}
449+
/>
450+
{formatLargeNumber(cacheReads || 0)}
451+
</span>
452+
</HeroTooltip>
453+
)}
508454
</div>
509455
<DeleteButton taskSize={formatSize(currentTaskItem?.size)} taskId={currentTaskItem?.id} />
510456
</div>
511457
)}
458+
<div className="flex flex-col">
459+
<TaskTimeline messages={clineMessages} />
460+
{ContextWindowComponent}
461+
</div>
512462
{checkpointTrackerErrorMessage && (
513463
<div
514464
style={{
@@ -673,23 +623,25 @@ const DeleteButton: React.FC<{
673623
taskSize: string
674624
taskId?: string
675625
}> = ({ taskSize, taskId }) => (
676-
<VSCodeButton
677-
appearance="icon"
678-
onClick={() => taskId && TaskServiceClient.deleteTasksWithIds({ value: [taskId] })}
679-
style={{ padding: "0px 0px" }}>
680-
<div
681-
style={{
682-
display: "flex",
683-
alignItems: "center",
684-
gap: "3px",
685-
fontSize: "10px",
686-
fontWeight: "bold",
687-
opacity: 0.6,
688-
}}>
689-
<i className={`codicon codicon-trash`} />
690-
{taskSize}
691-
</div>
692-
</VSCodeButton>
626+
<HeroTooltip content="Delete Task & Checkpoints">
627+
<VSCodeButton
628+
appearance="icon"
629+
onClick={() => taskId && TaskServiceClient.deleteTasksWithIds({ value: [taskId] })}
630+
style={{ padding: "0px 0px" }}>
631+
<div
632+
style={{
633+
display: "flex",
634+
alignItems: "center",
635+
gap: "3px",
636+
fontSize: "10px",
637+
fontWeight: "bold",
638+
opacity: 0.6,
639+
}}>
640+
<i className={`codicon codicon-trash`} />
641+
{taskSize}
642+
</div>
643+
</VSCodeButton>
644+
</HeroTooltip>
693645
)
694646

695647
// const ExportButton = () => (

0 commit comments

Comments
 (0)