@@ -9,11 +9,18 @@ import { CostsTab } from "./RightSidebar/CostsTab";
99import { VerticalTokenMeter } from "./RightSidebar/VerticalTokenMeter" ;
1010import { ReviewPanel } from "./RightSidebar/CodeReview/ReviewPanel" ;
1111import { calculateTokenMeterData } from "@/common/utils/tokens/tokenMeterUtils" ;
12+ import { sumUsageHistory , type ChatUsageDisplay } from "@/common/utils/tokens/usageAggregator" ;
1213import { matchesKeybind , KEYBINDS , formatKeybind } from "@/browser/utils/ui/keybinds" ;
1314import { Tooltip , TooltipTrigger , TooltipContent } from "./ui/tooltip" ;
1415import { cn } from "@/common/lib/utils" ;
1516import type { ReviewNoteData } from "@/common/types/review" ;
1617
18+ /** Stats reported by ReviewPanel for tab display */
19+ export interface ReviewStats {
20+ total : number ;
21+ read : number ;
22+ }
23+
1724interface SidebarContainerProps {
1825 collapsed : boolean ;
1926 wide ?: boolean ;
@@ -107,6 +114,9 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
107114 // Trigger for focusing Review panel (preserves hunk selection)
108115 const [ focusTrigger , setFocusTrigger ] = React . useState ( 0 ) ;
109116
117+ // Review stats reported by ReviewPanel
118+ const [ reviewStats , setReviewStats ] = React . useState < ReviewStats | null > ( null ) ;
119+
110120 // Notify parent (AIView) of tab changes so it can enable/disable resize functionality
111121 React . useEffect ( ( ) => {
112122 onTabChange ?.( selectedTab ) ;
@@ -144,6 +154,26 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
144154 const lastUsage = usage ?. liveUsage ?? usage ?. lastContextUsage ;
145155 const model = lastUsage ?. model ?? null ;
146156
157+ // Calculate session cost for tab display
158+ const sessionCost = React . useMemo ( ( ) => {
159+ const parts : ChatUsageDisplay [ ] = [ ] ;
160+ if ( usage . sessionTotal ) parts . push ( usage . sessionTotal ) ;
161+ if ( usage . liveCostUsage ) parts . push ( usage . liveCostUsage ) ;
162+ if ( parts . length === 0 ) return null ;
163+
164+ const aggregated = sumUsageHistory ( parts ) ;
165+ if ( ! aggregated ) return null ;
166+
167+ // Sum all cost components
168+ const total =
169+ ( aggregated . input . cost_usd ?? 0 ) +
170+ ( aggregated . cached . cost_usd ?? 0 ) +
171+ ( aggregated . cacheCreate . cost_usd ?? 0 ) +
172+ ( aggregated . output . cost_usd ?? 0 ) +
173+ ( aggregated . reasoning . cost_usd ?? 0 ) ;
174+ return total > 0 ? total : null ;
175+ } , [ usage . sessionTotal , usage . liveCostUsage ] ) ;
176+
147177 // Auto-compaction settings: threshold per-model
148178 const { threshold : autoCompactThreshold , setThreshold : setAutoCompactThreshold } =
149179 useAutoCompactionSettings ( workspaceId , model ) ;
@@ -215,39 +245,36 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
215245 >
216246 { /* Full view when not collapsed */ }
217247 < div className = { cn ( "flex-row h-full" , ! showCollapsed ? "flex" : "hidden" ) } >
218- { /* Render meter when Review tab is active */ }
219- { selectedTab === "review" && (
220- < div className = "bg-sidebar border-border-light flex w-5 shrink-0 flex-col border-r" >
221- { verticalMeter }
222- </ div >
223- ) }
224-
225- { /* Render resize handle to right of meter when Review tab is active */ }
248+ { /* Resize handle (left edge) when Review tab is active */ }
226249 { selectedTab === "review" && onStartResize && (
227250 < div
228251 className = { cn (
229- "w-1 flex-shrink-0 z-10 transition-[background] duration-150" ,
230- "bg-border-light cursor-col-resize hover:bg-accent" ,
231- isResizing && "bg-accent"
252+ "w-0.5 flex-shrink-0 z-10 transition-[background] duration-150 cursor-col-resize" ,
253+ isResizing ? "bg-accent" : "bg-border-light hover:bg-accent"
232254 ) }
233255 onMouseDown = { ( e ) => onStartResize ( e as unknown as React . MouseEvent ) }
234256 />
235257 ) }
236258
259+ { /* Render meter when Review tab is active */ }
260+ { selectedTab === "review" && (
261+ < div className = "bg-sidebar flex w-5 shrink-0 flex-col" > { verticalMeter } </ div >
262+ ) }
263+
237264 < div className = "flex min-w-0 flex-1 flex-col" >
238265 < div
239- className = "bg-background-secondary border-border flex border-b [&>*]:flex-1 "
266+ className = "border-border-light flex gap-1 border-b px-2 py-1.5 "
240267 role = "tablist"
241268 aria-label = "Metadata views"
242269 >
243270 < Tooltip >
244271 < TooltipTrigger asChild >
245272 < button
246273 className = { cn (
247- "w-full py-2.5 px-[15px] border-none border-solid cursor-pointer font-primary text-[13px] font-medium transition-all duration-200 " ,
274+ "rounded-md px-3 py-1 text-xs font-medium transition-all duration-150 flex items-center gap-1.5 " ,
248275 selectedTab === "costs"
249- ? "bg-separator border-b-2 border-b-plan-mode text-[var(--color-sidebar-tab-active)] "
250- : "bg-transparent text-secondary border-b-2 border-b-transparent hover:bg-background-secondary hover:text-foreground"
276+ ? "bg-hover text-foreground "
277+ : "bg-transparent text-muted hover:bg-hover/50 hover:text-foreground"
251278 ) }
252279 onClick = { ( ) => setSelectedTab ( "costs" ) }
253280 id = { costsTabId }
@@ -257,6 +284,11 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
257284 aria-controls = { costsPanelId }
258285 >
259286 Costs
287+ { sessionCost !== null && (
288+ < span className = "text-muted text-[10px]" >
289+ ${ sessionCost < 0.01 ? "<0.01" : sessionCost . toFixed ( 2 ) }
290+ </ span >
291+ ) }
260292 </ button >
261293 </ TooltipTrigger >
262294 < TooltipContent side = "bottom" align = "center" >
@@ -267,10 +299,10 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
267299 < TooltipTrigger asChild >
268300 < button
269301 className = { cn (
270- "w-full py-2.5 px-[15px] border-none border-solid cursor-pointer font-primary text-[13px] font-medium transition-all duration-200 " ,
302+ "rounded-md px-3 py-1 text-xs font-medium transition-all duration-150 flex items-center gap-1.5 " ,
271303 selectedTab === "review"
272- ? "bg-separator border-b-2 border-b-plan-mode text-[var(--color-sidebar-tab-active)] "
273- : "bg-transparent text-secondary border-b-2 border-b-transparent hover:bg-background-secondary hover:text-foreground"
304+ ? "bg-hover text-foreground "
305+ : "bg-transparent text-muted hover:bg-hover/50 hover:text-foreground"
274306 ) }
275307 onClick = { ( ) => setSelectedTab ( "review" ) }
276308 id = { reviewTabId }
@@ -280,6 +312,18 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
280312 aria-controls = { reviewPanelId }
281313 >
282314 Review
315+ { reviewStats !== null && reviewStats . total > 0 && (
316+ < span
317+ className = { cn (
318+ "text-[10px]" ,
319+ reviewStats . read === reviewStats . total
320+ ? "text-muted" // All read - dimmed
321+ : "text-muted"
322+ ) }
323+ >
324+ { reviewStats . read } /{ reviewStats . total }
325+ </ span >
326+ ) }
283327 </ button >
284328 </ TooltipTrigger >
285329 < TooltipContent side = "bottom" align = "center" >
@@ -309,6 +353,7 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
309353 onReviewNote = { onReviewNote }
310354 focusTrigger = { focusTrigger }
311355 isCreating = { isCreating }
356+ onStatsChange = { setReviewStats }
312357 />
313358 </ div >
314359 ) }
0 commit comments