@@ -5,7 +5,7 @@ import path from "path"
55import { Filesystem } from "@/util/filesystem"
66import { useLocal } from "@tui/context/local"
77import { useTheme } from "@tui/context/theme"
8- import { EmptyBorder } from "@tui/component/border"
8+ import { EmptyBorder , SplitBorder } from "@tui/component/border"
99import { useSDK } from "@tui/context/sdk"
1010import { useRoute } from "@tui/context/route"
1111import { useSync } from "@tui/context/sync"
@@ -22,7 +22,7 @@ import { useKeyboard, useRenderer } from "@opentui/solid"
2222import { Editor } from "@tui/util/editor"
2323import { useExit } from "../../context/exit"
2424import { Clipboard } from "../../util/clipboard"
25- import type { FilePart } from "@opencode-ai/sdk/v2"
25+ import type { AssistantMessage , FilePart } from "@opencode-ai/sdk/v2"
2626import { TuiEvent } from "../../event"
2727import { iife } from "@/util/iife"
2828import { Locale } from "@/util/locale"
@@ -59,6 +59,10 @@ export type PromptRef = {
5959
6060const PLACEHOLDERS = [ "Fix a TODO in the codebase" , "What is the tech stack of this project?" , "Fix broken tests" ]
6161const SHELL_PLACEHOLDERS = [ "ls -la" , "git status" , "pwd" ]
62+ const money = new Intl . NumberFormat ( "en-US" , {
63+ style : "currency" ,
64+ currency : "USD" ,
65+ } )
6266
6367export function Prompt ( props : PromptProps ) {
6468 let input : TextareaRenderable
@@ -122,6 +126,25 @@ export function Prompt(props: PromptProps) {
122126 return messages . findLast ( ( m ) => m . role === "user" )
123127 } )
124128
129+ const usage = createMemo ( ( ) => {
130+ if ( ! props . sessionID ) return
131+ const msg = sync . data . message [ props . sessionID ] ?? [ ]
132+ const last = msg . findLast ( ( item ) : item is AssistantMessage => item . role === "assistant" && item . tokens . output > 0 )
133+ if ( ! last ) return
134+
135+ const tokens =
136+ last . tokens . input + last . tokens . output + last . tokens . reasoning + last . tokens . cache . read + last . tokens . cache . write
137+ if ( tokens <= 0 ) return
138+
139+ const model = sync . data . provider . find ( ( item ) => item . id === last . providerID ) ?. models [ last . modelID ]
140+ const pct = model ?. limit . context ? `${ Math . round ( ( tokens / model . limit . context ) * 100 ) } %` : undefined
141+ const cost = msg . reduce ( ( sum , item ) => sum + ( item . role === "assistant" ? item . cost : 0 ) , 0 )
142+ return {
143+ context : pct ? `${ Locale . number ( tokens ) } (${ pct } )` : Locale . number ( tokens ) ,
144+ cost : cost > 0 ? money . format ( cost ) : undefined ,
145+ }
146+ } )
147+
125148 const [ store , setStore ] = createStore < {
126149 prompt : PromptInfo
127150 mode : "normal" | "shell"
@@ -833,8 +856,7 @@ export function Prompt(props: PromptProps) {
833856 border = { [ "left" ] }
834857 borderColor = { highlight ( ) }
835858 customBorderChars = { {
836- ...EmptyBorder ,
837- vertical : "┃" ,
859+ ...SplitBorder . customBorderChars ,
838860 bottomLeft : "╹" ,
839861 } }
840862 >
@@ -1158,14 +1180,25 @@ export function Prompt(props: PromptProps) {
11581180 < box gap = { 2 } flexDirection = "row" >
11591181 < Switch >
11601182 < Match when = { store . mode === "normal" } >
1161- < Show when = { local . model . variant . list ( ) . length > 0 } >
1162- < text fg = { theme . text } >
1163- { keybind . print ( "variant_cycle" ) } < span style = { { fg : theme . textMuted } } > variants</ span >
1164- </ text >
1165- </ Show >
1166- < text fg = { theme . text } >
1167- { keybind . print ( "agent_cycle" ) } < span style = { { fg : theme . textMuted } } > agents</ span >
1168- </ text >
1183+ < Switch >
1184+ < Match when = { usage ( ) } >
1185+ { ( item ) => (
1186+ < text fg = { theme . textMuted } wrapMode = "none" >
1187+ { [ item ( ) . context , item ( ) . cost ] . filter ( Boolean ) . join ( " · " ) }
1188+ </ text >
1189+ ) }
1190+ </ Match >
1191+ < Match when = { true } >
1192+ < Show when = { local . model . variant . list ( ) . length > 0 } >
1193+ < text fg = { theme . text } >
1194+ { keybind . print ( "variant_cycle" ) } < span style = { { fg : theme . textMuted } } > variants</ span >
1195+ </ text >
1196+ </ Show >
1197+ < text fg = { theme . text } >
1198+ { keybind . print ( "agent_cycle" ) } < span style = { { fg : theme . textMuted } } > agents</ span >
1199+ </ text >
1200+ </ Match >
1201+ </ Switch >
11691202 < text fg = { theme . text } >
11701203 { keybind . print ( "command_list" ) } < span style = { { fg : theme . textMuted } } > commands</ span >
11711204 </ text >
0 commit comments