diff options
| author | Frank <[email protected]> | 2025-11-24 16:54:52 -0500 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-11-24 16:54:54 -0500 |
| commit | 823d7da4c12b71793e206ebac8b9af2802dcc6c4 (patch) | |
| tree | 10ceed263f63cca246fe8fb8638644e7f9e1f4d7 | |
| parent | 7fff191c5766be8df40d2bb08b33bd0d919dda18 (diff) | |
| download | opencode-823d7da4c12b71793e206ebac8b9af2802dcc6c4.tar.gz opencode-823d7da4c12b71793e206ebac8b9af2802dcc6c4.zip | |
zen: display reasoning tokens
| -rw-r--r-- | packages/console/app/src/routes/workspace/[id]/usage-section.tsx | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/packages/console/app/src/routes/workspace/[id]/usage-section.tsx b/packages/console/app/src/routes/workspace/[id]/usage-section.tsx index 212904f3f..8ba5dfdbd 100644 --- a/packages/console/app/src/routes/workspace/[id]/usage-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/usage-section.tsx @@ -50,6 +50,10 @@ export function UsageSection() { return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWrite5mTokens ?? 0) + (u.cacheWrite1hTokens ?? 0) } + const calculateTotalOutputTokens = (u: Awaited<ReturnType<typeof getUsageInfo>>[0]) => { + return u.outputTokens + (u.reasoningTokens ?? 0) + } + const goPrev = async () => { const usage = await getUsageInfo(params.id!, store.page - 1) setStore({ @@ -95,8 +99,11 @@ export function UsageSection() { {(usage, index) => { const date = createMemo(() => new Date(usage.timeCreated)) const totalInputTokens = createMemo(() => calculateTotalInputTokens(usage)) - const breakdownId = `breakdown-${index()}` - const isOpen = createMemo(() => openBreakdownId() === breakdownId) + const totalOutputTokens = createMemo(() => calculateTotalOutputTokens(usage)) + const inputBreakdownId = `input-breakdown-${index()}` + const outputBreakdownId = `output-breakdown-${index()}` + const isInputOpen = createMemo(() => openBreakdownId() === inputBreakdownId) + const isOutputOpen = createMemo(() => openBreakdownId() === outputBreakdownId) const isClaude = usage.model.toLowerCase().includes("claude") return ( <tr> @@ -110,13 +117,13 @@ export function UsageSection() { data-slot="breakdown-button" onClick={(e) => { e.stopPropagation() - setOpenBreakdownId(isOpen() ? null : breakdownId) + setOpenBreakdownId(isInputOpen() ? null : inputBreakdownId) }} > <IconBreakdown /> </button> <span onClick={() => setOpenBreakdownId(null)}>{totalInputTokens()}</span> - <Show when={isOpen()}> + <Show when={isInputOpen()}> <div data-slot="breakdown-popup" onClick={(e) => e.stopPropagation()}> <div data-slot="breakdown-row"> <span data-slot="breakdown-label">Input</span> @@ -136,7 +143,32 @@ export function UsageSection() { </Show> </div> </td> - <td data-slot="usage-tokens">{usage.outputTokens}</td> + <td data-slot="usage-tokens"> + <div data-slot="tokens-with-breakdown" onClick={(e) => e.stopPropagation()}> + <button + data-slot="breakdown-button" + onClick={(e) => { + e.stopPropagation() + setOpenBreakdownId(isOutputOpen() ? null : outputBreakdownId) + }} + > + <IconBreakdown /> + </button> + <span onClick={() => setOpenBreakdownId(null)}>{totalOutputTokens()}</span> + <Show when={isOutputOpen()}> + <div data-slot="breakdown-popup" onClick={(e) => e.stopPropagation()}> + <div data-slot="breakdown-row"> + <span data-slot="breakdown-label">Output</span> + <span data-slot="breakdown-value">{usage.outputTokens}</span> + </div> + <div data-slot="breakdown-row"> + <span data-slot="breakdown-label">Reasoning</span> + <span data-slot="breakdown-value">{usage.reasoningTokens ?? 0}</span> + </div> + </div> + </Show> + </div> + </td> <td data-slot="usage-cost">${((usage.cost ?? 0) / 100000000).toFixed(4)}</td> </tr> ) |
