summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-11-24 16:54:52 -0500
committerFrank <[email protected]>2025-11-24 16:54:54 -0500
commit823d7da4c12b71793e206ebac8b9af2802dcc6c4 (patch)
tree10ceed263f63cca246fe8fb8638644e7f9e1f4d7
parent7fff191c5766be8df40d2bb08b33bd0d919dda18 (diff)
downloadopencode-823d7da4c12b71793e206ebac8b9af2802dcc6c4.tar.gz
opencode-823d7da4c12b71793e206ebac8b9af2802dcc6c4.zip
zen: display reasoning tokens
-rw-r--r--packages/console/app/src/routes/workspace/[id]/usage-section.tsx42
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>
)