import { type Accessor, createMemo, Match, Show, Switch } from "solid-js" import { useRouteData } from "@tui/context/route" import { useSync } from "@tui/context/sync" import { pipe, sumBy } from "remeda" import { useTheme } from "@tui/context/theme" import { SplitBorder, EmptyBorder } from "@tui/component/border" import type { AssistantMessage, Session } from "@opencode-ai/sdk/v2" import { useDirectory } from "../../context/directory" import { useKeybind } from "../../context/keybind" const Title = (props: { session: Accessor }) => { const { theme } = useTheme() return ( # {props.session().title} ) } const ContextInfo = (props: { context: Accessor; cost: Accessor }) => { const { theme } = useTheme() return ( {props.context()} ({props.cost()}) ) } export function Header() { const route = useRouteData("session") const sync = useSync() const session = createMemo(() => sync.session.get(route.sessionID)!) const messages = createMemo(() => sync.data.message[route.sessionID] ?? []) const shareEnabled = createMemo(() => sync.data.config.share !== "disabled") const cost = createMemo(() => { const total = pipe( messages(), sumBy((x) => (x.role === "assistant" ? x.cost : 0)), ) return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(total) }) const context = createMemo(() => { const last = messages().findLast((x) => x.role === "assistant" && x.tokens.output > 0) as AssistantMessage if (!last) return const total = last.tokens.input + last.tokens.output + last.tokens.reasoning + last.tokens.cache.read + last.tokens.cache.write const model = sync.data.provider.find((x) => x.id === last.providerID)?.models[last.modelID] let result = total.toLocaleString() if (model?.limit.context) { result += " " + Math.round((total / model.limit.context) * 100) + "%" } return result }) const { theme } = useTheme() const keybind = useKeybind() return ( Subagent session Prev {keybind.print("session_child_cycle_reverse")} Next {keybind.print("session_child_cycle")} <ContextInfo context={context} cost={cost} /> </box> <Show when={shareEnabled()}> <box flexDirection="row" justifyContent="space-between" gap={1}> <box flexGrow={1} flexShrink={1}> <Switch> <Match when={session().share?.url}> <text fg={theme.textMuted} wrapMode="word"> {session().share!.url} </text> </Match> <Match when={true}> <text fg={theme.text} wrapMode="word"> /share <span style={{ fg: theme.textMuted }}>copy link</span> </text> </Match> </Switch> </box> </box> </Show> </Match> </Switch> </box> </box> ) }