mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
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
This commit is contained in:
parent
44fd975b17
commit
472c3960b0
4 changed files with 84 additions and 2 deletions
|
|
@ -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) {
|
||||
|
|
@ -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)!, {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export interface TaskHeaderProps {
|
|||
aggregatedCost?: number
|
||||
hasSubtasks?: boolean
|
||||
parentTaskId?: string
|
||||
rootOrchestrationCost?: number
|
||||
costBreakdown?: string
|
||||
contextTokens: number
|
||||
buttonsDisabled: boolean
|
||||
|
|
@ -53,6 +54,7 @@ const TaskHeader = ({
|
|||
aggregatedCost,
|
||||
hasSubtasks,
|
||||
parentTaskId,
|
||||
rootOrchestrationCost,
|
||||
costBreakdown,
|
||||
contextTokens,
|
||||
buttonsDisabled,
|
||||
|
|
@ -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>
|
||||
)}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue