feat(app): show Go allowance when a session costs nothing (#58566)

This commit is contained in:
Adam
2026-10-24 03:43:56 -05:00
committed by GitHub
Unverified
parent 9109bcf136
commit 1873fbe304
3 changed files with 29 additions and 3 deletions
@@ -4,6 +4,8 @@ export default {
"usage.tokens": "Tokens",
"usage.usage": "Context",
"usage.cost": "Cost",
"usage.allowance": "Allowance",
"usage.allowanceAmount": "{{amount}} allowance",
"usage.view": "View context usage",
"usage.toggle": "Toggle session context",
"systemPrompt.title": "System Prompt",
@@ -23,6 +25,7 @@ export default {
"stats.userMessages": "User Messages",
"stats.assistantMessages": "Assistant Messages",
"stats.totalCost": "Total Cost",
"stats.allowance": "Allowance Used",
"stats.sessionCreated": "Session Created",
"stats.lastActivity": "Last Activity",
"export.success.title": "Session exported",
@@ -75,9 +75,18 @@ export function SessionContextUsage(props: {
const cost = createMemo(() => usd().format(spent()))
// A subscription such as OpenCode Go covers its requests from an allowance, so they cost nothing.
const allowance = createMemo(() =>
props.session.id ? props.session.server.data.session.allowance(props.session.id) : 0,
)
// Spend anywhere in the family keeps the cost visible, even when this session's model is free.
const showCost = createMemo(() => {
if (spent() > 0) return true
// The allowance shows instead of $0.00.
if (allowance() > 0) return false
const ref = info()?.model ?? messages().findLast((item) => item.type === "assistant")?.model
const model = ref ? catalogModel(props.session, ref)?.model : undefined
@@ -118,6 +127,9 @@ export function SessionContextUsage(props: {
<Show when={showCost()}>
<ContextTooltipRow name={ctx.t("usage.cost")} value={cost()} />
</Show>
<Show when={allowance() > 0}>
<ContextTooltipRow name={ctx.t("usage.allowance")} value={usd().format(allowance())} />
</Show>
<ContextTooltipRow name={ctx.t("usage.usage")} value={`${context()?.usage ?? 0}%`} />
<ContextTooltipRow name={ctx.t("usage.tokens")} value={context()?.total.toLocaleString(i18n.locale()) ?? "0"} />
</div>
@@ -150,6 +162,12 @@ export function SessionContextUsage(props: {
</span>
<span>{cost()}</span>
</Show>
<Show when={allowance() > 0}>
<span aria-hidden="true" class="flex w-1.5 shrink-0 items-center justify-center">
·
</span>
<span>{ctx.t("usage.allowanceAmount", { amount: usd().format(allowance()) })}</span>
</Show>
</span>
</Button>
}
+8 -3
View File
@@ -139,6 +139,8 @@ export default function SessionContextTab(props: { session: MountedSession }) {
// A root session's cost includes its subagent sessions, as in the TUI.
const cost = createMemo(() => usd().format(props.session.id ? data().session.cost(props.session.id) : 0))
// Spent from a subscription allowance such as OpenCode Go's instead of money; shown only when there is some.
const allowance = createMemo(() => (props.session.id ? data().session.allowance(props.session.id) : 0))
const counts = createMemo(() => {
const all = messages()
@@ -179,7 +181,7 @@ export default function SessionContextTab(props: { session: MountedSession }) {
return c.modelLabel
})
const stats = [
const stats: { label: string; value: () => JSX.Element; shown?: () => boolean }[] = [
{ label: "stats.session", value: () => info()?.title ?? (props.session.id || "—") },
{ label: "stats.messages", value: () => counts().all.toLocaleString(i18n.locale()) },
{ label: "stats.provider", value: providerLabel },
@@ -198,9 +200,10 @@ export default function SessionContextTab(props: { session: MountedSession }) {
{ label: "stats.userMessages", value: () => counts().user.toLocaleString(i18n.locale()) },
{ label: "stats.assistantMessages", value: () => counts().assistant.toLocaleString(i18n.locale()) },
{ label: "stats.totalCost", value: cost },
{ label: "stats.allowance", value: () => usd().format(allowance()), shown: () => allowance() > 0 },
{ label: "stats.sessionCreated", value: () => formatter().time(info()?.time.created) },
{ label: "stats.lastActivity", value: () => formatter().time(context()?.message.time.created) },
] satisfies { label: string; value: () => JSX.Element }[]
]
const exportSession = async () => {
const sessionID = props.session.id
@@ -292,7 +295,9 @@ export default function SessionContextTab(props: { session: MountedSession }) {
>
<div data-slot="session-usage-content" class="px-4 pt-4 pb-6 flex flex-col gap-6 md:px-6 md:pb-10 md:gap-10">
<div class="grid grid-cols-1 @[32rem]:grid-cols-2 gap-4">
<For each={stats}>{(stat) => <Stat label={ctx.t(stat.label)} value={stat.value()} />}</For>
<For each={stats.filter((stat) => stat.shown?.() ?? true)}>
{(stat) => <Stat label={ctx.t(stat.label)} value={stat.value()} />}
</For>
</div>
<Show when={systemPrompt()}>