Merge branch 'RooVetGit:main' into feature/auto-approve-switch-modes

This commit is contained in:
Murilo Pires
2025-01-28 01:22:01 -03:00
committed by GitHub
3 changed files with 33 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ interface ApiMetrics {
totalCacheWrites?: number totalCacheWrites?: number
totalCacheReads?: number totalCacheReads?: number
totalCost: number totalCost: number
contextTokens: number // Total tokens in conversation (last message's tokensIn + tokensOut)
} }
/** /**
@@ -32,8 +33,22 @@ export function getApiMetrics(messages: ClineMessage[]): ApiMetrics {
totalCacheWrites: undefined, totalCacheWrites: undefined,
totalCacheReads: undefined, totalCacheReads: undefined,
totalCost: 0, totalCost: 0,
contextTokens: 0,
} }
// Find the last api_req_started message that has valid token information
const lastApiReq = [...messages].reverse().find((message) => {
if (message.type === "say" && message.say === "api_req_started" && message.text) {
try {
const parsedData = JSON.parse(message.text)
return typeof parsedData.tokensIn === "number" && typeof parsedData.tokensOut === "number"
} catch {
return false
}
}
return false
})
messages.forEach((message) => { messages.forEach((message) => {
if (message.type === "say" && message.say === "api_req_started" && message.text) { if (message.type === "say" && message.say === "api_req_started" && message.text) {
try { try {
@@ -55,6 +70,14 @@ export function getApiMetrics(messages: ClineMessage[]): ApiMetrics {
if (typeof cost === "number") { if (typeof cost === "number") {
result.totalCost += cost result.totalCost += cost
} }
// If this is the last api request, use its tokens for context size
if (message === lastApiReq) {
// Only update context tokens if both input and output tokens are non-zero
if (tokensIn > 0 && tokensOut > 0) {
result.contextTokens = tokensIn + tokensOut
}
}
} catch (error) { } catch (error) {
console.error("Error parsing JSON:", error) console.error("Error parsing JSON:", error)
} }

View File

@@ -920,6 +920,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
cacheWrites={apiMetrics.totalCacheWrites} cacheWrites={apiMetrics.totalCacheWrites}
cacheReads={apiMetrics.totalCacheReads} cacheReads={apiMetrics.totalCacheReads}
totalCost={apiMetrics.totalCost} totalCost={apiMetrics.totalCost}
contextTokens={apiMetrics.contextTokens}
onClose={handleTaskCloseButtonClick} onClose={handleTaskCloseButtonClick}
/> />
) : ( ) : (

View File

@@ -16,6 +16,7 @@ interface TaskHeaderProps {
cacheWrites?: number cacheWrites?: number
cacheReads?: number cacheReads?: number
totalCost: number totalCost: number
contextTokens: number
onClose: () => void onClose: () => void
} }
@@ -27,6 +28,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
cacheWrites, cacheWrites,
cacheReads, cacheReads,
totalCost, totalCost,
contextTokens,
onClose, onClose,
}) => { }) => {
const { apiConfiguration } = useExtensionState() const { apiConfiguration } = useExtensionState()
@@ -272,6 +274,13 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
{!isCostAvailable && <ExportButton />} {!isCostAvailable && <ExportButton />}
</div> </div>
<div style={{ display: "flex", alignItems: "center", gap: "4px", flexWrap: "wrap" }}>
<span style={{ fontWeight: "bold" }}>Context:</span>
<span style={{ display: "flex", alignItems: "center", gap: "3px" }}>
{contextTokens ? formatLargeNumber(contextTokens) : '-'}
</span>
</div>
{shouldShowPromptCacheInfo && (cacheReads !== undefined || cacheWrites !== undefined) && ( {shouldShowPromptCacheInfo && (cacheReads !== undefined || cacheWrites !== undefined) && (
<div style={{ display: "flex", alignItems: "center", gap: "4px", flexWrap: "wrap" }}> <div style={{ display: "flex", alignItems: "center", gap: "4px", flexWrap: "wrap" }}>
<span style={{ fontWeight: "bold" }}>Cache:</span> <span style={{ fontWeight: "bold" }}>Cache:</span>