From dd6e8f093e305a1b3fd1e5645ab51b5bb2715d3f Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 20 Feb 2026 17:39:46 -0500 Subject: [PATCH] feat(tui): show tokens per second in assistant message footer --- .../src/cli/cmd/tui/routes/session/index.tsx | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index f5a7f6f6ca..7272846342 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1101,6 +1101,7 @@ export function Session() { { - if (!final()) return 0 - if (!props.message.time.completed) return 0 - const user = messages().find((x) => x.role === "user" && x.id === props.message.parentID) - if (!user || !user.time) return 0 - return props.message.time.completed - user.time.created + const stats = createMemo(() => { + if (!final() || !props.message.time.completed) return null + + const list = messages() + let tokens = props.message.tokens?.output || 0 + + for (let i = props.index - 1; i >= 0; i--) { + const msg = list[i] + if (msg.id === props.message.parentID && msg.role === "user") { + if (!msg.time?.created) return null + return { + duration: props.message.time.completed - msg.time.created, + tokens, + } + } + if (msg.role === "assistant") { + tokens += msg.tokens?.output || 0 + } + } + + return null }) return ( @@ -1334,8 +1350,14 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las {" "} {Locale.titlecase(props.message.mode)} · {props.message.modelID} - - · {Locale.duration(duration())} + + {(s) => ( + + {" "} + · {Locale.duration(s().duration)} + 0}> · {(s().tokens / (s().duration / 1000)).toFixed(1)} tok/s + + )} · interrupted