Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion webview-ui/src/components/chat/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,15 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
text: currentTaskItem.id,
})
}
}, [taskTs, currentTaskItem?.id, currentTaskItem?.childIds])
// When viewing a subtask, also request aggregated costs for the root orchestration task
const rootId = currentTaskItem?.rootTaskId
if (taskTs && rootId && rootId !== currentTaskItem?.id) {
vscode.postMessage({
type: "getTaskWithAggregatedCosts",
text: rootId,
})
}
}, [taskTs, currentTaskItem?.id, currentTaskItem?.childIds, currentTaskItem?.rootTaskId])

useEffect(() => {
if (isHidden) {
Expand Down Expand Up @@ -1563,6 +1571,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
)
}
parentTaskId={currentTaskItem?.parentTaskId}
rootOrchestrationCost={
currentTaskItem?.rootTaskId &&
currentTaskItem.rootTaskId !== currentTaskItem.id &&
aggregatedCostsMap.has(currentTaskItem.rootTaskId)
? aggregatedCostsMap.get(currentTaskItem.rootTaskId)!.totalCost
: undefined
}
costBreakdown={
currentTaskItem?.id && aggregatedCostsMap.has(currentTaskItem.id)
? getCostBreakdownIfNeeded(aggregatedCostsMap.get(currentTaskItem.id)!, {
Expand Down
43 changes: 43 additions & 0 deletions webview-ui/src/components/chat/TaskHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface TaskHeaderProps {
aggregatedCost?: number
hasSubtasks?: boolean
parentTaskId?: string
rootOrchestrationCost?: number
costBreakdown?: string
contextTokens: number
buttonsDisabled: boolean
Expand All @@ -53,6 +54,7 @@ const TaskHeader = ({
aggregatedCost,
hasSubtasks,
parentTaskId,
rootOrchestrationCost,
costBreakdown,
contextTokens,
buttonsDisabled,
Expand Down Expand Up @@ -315,6 +317,25 @@ const TaskHeader = ({
</StandardTooltip>
</>
)}
{typeof rootOrchestrationCost === "number" && rootOrchestrationCost > 0 && (
<>
<span>·</span>
<StandardTooltip
content={
<div>
{t("chat:costs.orchestrationTotal", {
cost: rootOrchestrationCost.toFixed(2),
})}
</div>
}
side="top"
sideOffset={8}>
<span className="text-vscode-descriptionForeground">
{t("chat:costs.orchestrationLabel")}: ${rootOrchestrationCost.toFixed(2)}
</span>
</StandardTooltip>
</>
)}
</div>
</div>
)}
Expand Down Expand Up @@ -447,6 +468,28 @@ const TaskHeader = ({
</tr>
)}

{typeof rootOrchestrationCost === "number" && rootOrchestrationCost > 0 && (
<tr>
<th className="font-medium text-left align-top w-1 whitespace-nowrap pr-3 h-[24px]">
{t("chat:costs.orchestrationLabel")}
</th>
<td className="font-light align-top">
<StandardTooltip
content={
<div>
{t("chat:costs.orchestrationTotal", {
cost: rootOrchestrationCost.toFixed(2),
})}
</div>
}
side="top"
sideOffset={8}>
<span>${rootOrchestrationCost.toFixed(2)}</span>
</StandardTooltip>
</td>
</tr>
)}

{/* Size display */}
{!!currentTaskItem?.size && currentTaskItem.size > 0 && (
<tr>
Expand Down
22 changes: 22 additions & 0 deletions webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -470,4 +470,26 @@ describe("TaskHeader", () => {
expect(screen.getByText("0%")).toBeInTheDocument()
})
})

describe("Root orchestration cost", () => {
it("should display orchestration cost when rootOrchestrationCost is provided and > 0", () => {
renderTaskHeader({ rootOrchestrationCost: 1.5 })
expect(screen.getByText("chat:costs.orchestrationLabel: $1.50")).toBeInTheDocument()
})

it("should not display orchestration cost when rootOrchestrationCost is undefined", () => {
renderTaskHeader({ rootOrchestrationCost: undefined })
expect(screen.queryByText(/chat:costs.orchestrationLabel/)).not.toBeInTheDocument()
})

it("should not display orchestration cost when rootOrchestrationCost is 0", () => {
renderTaskHeader({ rootOrchestrationCost: 0 })
expect(screen.queryByText(/chat:costs.orchestrationLabel/)).not.toBeInTheDocument()
})

it("should display orchestration cost tooltip with correct text", () => {
renderTaskHeader({ rootOrchestrationCost: 2.75 })
expect(screen.getByText("chat:costs.orchestrationLabel: $2.75")).toBeInTheDocument()
})
})
})
4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,9 @@
"costs": {
"totalWithSubtasks": "Total Cost (including subtasks): ${{cost}}",
"total": "Total Cost: ${{cost}}",
"includesSubtasks": "Includes subtask costs"
"includesSubtasks": "Includes subtask costs",
"orchestrationLabel": "Orchestration",
"orchestrationTotal": "Full orchestration cost (all tasks): ${{cost}}"
},
"codeblock": {
"tooltips": {
Expand Down
Loading