From 472c3960b02435e895a6dff97374b5159316bb63 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Mon, 16 Mar 2026 14:43:01 +0000 Subject: [PATCH] feat: show root orchestration cost tally for subtasks When viewing a subtask spawned by an orchestrator, the TaskHeader now displays the full orchestration cost (aggregated across all tasks in the orchestration) alongside the current task cost. This gives users visibility into total spend without having to navigate back to the parent task. Addresses #11928 --- webview-ui/src/components/chat/ChatView.tsx | 17 +++++++- webview-ui/src/components/chat/TaskHeader.tsx | 43 +++++++++++++++++++ .../chat/__tests__/TaskHeader.spec.tsx | 22 ++++++++++ webview-ui/src/i18n/locales/en/chat.json | 4 +- 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index fd0aca66cb7..dcc437c73f7 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -505,7 +505,15 @@ const ChatViewComponent: React.ForwardRefRenderFunction { if (isHidden) { @@ -1563,6 +1571,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction )} + {typeof rootOrchestrationCost === "number" && rootOrchestrationCost > 0 && ( + <> + ยท + + {t("chat:costs.orchestrationTotal", { + cost: rootOrchestrationCost.toFixed(2), + })} + + } + side="top" + sideOffset={8}> + + {t("chat:costs.orchestrationLabel")}: ${rootOrchestrationCost.toFixed(2)} + + + + )} )} @@ -447,6 +468,28 @@ const TaskHeader = ({ )} + {typeof rootOrchestrationCost === "number" && rootOrchestrationCost > 0 && ( + + + {t("chat:costs.orchestrationLabel")} + + + + {t("chat:costs.orchestrationTotal", { + cost: rootOrchestrationCost.toFixed(2), + })} + + } + side="top" + sideOffset={8}> + ${rootOrchestrationCost.toFixed(2)} + + + + )} + {/* Size display */} {!!currentTaskItem?.size && currentTaskItem.size > 0 && ( diff --git a/webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx b/webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx index c4ebe06973a..6ad528bdb20 100644 --- a/webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx @@ -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() + }) + }) }) diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 0e790e5c9a4..eb4433dc3f7 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -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": {