Add toggle for usage metrics
This commit is contained in:
@@ -47,6 +47,7 @@ const App: Component = () => {
|
|||||||
preferences,
|
preferences,
|
||||||
recordWorkspaceLaunch,
|
recordWorkspaceLaunch,
|
||||||
toggleShowThinkingBlocks,
|
toggleShowThinkingBlocks,
|
||||||
|
toggleUsageMetrics,
|
||||||
setDiffViewMode,
|
setDiffViewMode,
|
||||||
setToolOutputExpansion,
|
setToolOutputExpansion,
|
||||||
setDiagnosticsExpansion,
|
setDiagnosticsExpansion,
|
||||||
@@ -205,6 +206,7 @@ const App: Component = () => {
|
|||||||
const { commands: paletteCommands, executeCommand } = useCommands({
|
const { commands: paletteCommands, executeCommand } = useCommands({
|
||||||
preferences,
|
preferences,
|
||||||
toggleShowThinkingBlocks,
|
toggleShowThinkingBlocks,
|
||||||
|
toggleUsageMetrics,
|
||||||
setDiffViewMode,
|
setDiffViewMode,
|
||||||
setToolOutputExpansion,
|
setToolOutputExpansion,
|
||||||
setDiagnosticsExpansion,
|
setDiagnosticsExpansion,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { For, Show, createMemo } from "solid-js"
|
|||||||
import type { Message, SDKPart, MessageInfo, ClientPart } from "../types/message"
|
import type { Message, SDKPart, MessageInfo, ClientPart } from "../types/message"
|
||||||
import { partHasRenderableText } from "../types/message"
|
import { partHasRenderableText } from "../types/message"
|
||||||
import { formatTokenTotal } from "../lib/formatters"
|
import { formatTokenTotal } from "../lib/formatters"
|
||||||
|
import { preferences } from "../stores/preferences"
|
||||||
import MessagePart from "./message-part"
|
import MessagePart from "./message-part"
|
||||||
|
|
||||||
interface MessageItemProps {
|
interface MessageItemProps {
|
||||||
@@ -17,6 +18,7 @@ interface MessageItemProps {
|
|||||||
|
|
||||||
export default function MessageItem(props: MessageItemProps) {
|
export default function MessageItem(props: MessageItemProps) {
|
||||||
const isUser = () => props.message.type === "user"
|
const isUser = () => props.message.type === "user"
|
||||||
|
const showUsageMetrics = () => preferences().showUsageMetrics ?? true
|
||||||
const timestamp = () => {
|
const timestamp = () => {
|
||||||
const date = new Date(props.message.timestamp)
|
const date = new Date(props.message.timestamp)
|
||||||
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
||||||
@@ -150,6 +152,9 @@ export default function MessageItem(props: MessageItemProps) {
|
|||||||
if (!info || info.role !== "assistant" || !info.tokens) {
|
if (!info || info.role !== "assistant" || !info.tokens) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
if (!showUsageMetrics()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const tokens = info.tokens
|
const tokens = info.tokens
|
||||||
const input = tokens.input ?? 0
|
const input = tokens.input ?? 0
|
||||||
|
|||||||
@@ -545,21 +545,22 @@ export default function MessageStream(props: MessageStreamProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="message-stream-container">
|
<div class="message-stream-container">
|
||||||
<div class="connection-status">
|
<div class="connection-status">
|
||||||
<div class="connection-status-text connection-status-info flex flex-wrap items-center gap-2 text-sm font-medium">
|
<div class="connection-status-text connection-status-info flex flex-wrap items-center gap-2 text-sm font-medium">
|
||||||
<div class="inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary">
|
<div class="inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary">
|
||||||
<span class="uppercase text-[10px] tracking-wide text-primary/70">Used</span>
|
<span class="uppercase text-[10px] tracking-wide text-primary/70">Used</span>
|
||||||
<span class="font-semibold text-primary">{formatTokens(sessionInfo().actualUsageTokens ?? 0)}</span>
|
<span class="font-semibold text-primary">{formatTokens(sessionInfo().actualUsageTokens ?? 0)}</span>
|
||||||
</div>
|
|
||||||
<div class="inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary">
|
|
||||||
<span class="uppercase text-[10px] tracking-wide text-primary/70">Avail</span>
|
|
||||||
<span class="font-semibold text-primary">
|
|
||||||
{sessionInfo().contextAvailableTokens !== null ? formatTokens(sessionInfo().contextAvailableTokens ?? 0) : "--"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary">
|
||||||
|
<span class="uppercase text-[10px] tracking-wide text-primary/70">Avail</span>
|
||||||
|
<span class="font-semibold text-primary">
|
||||||
|
{sessionInfo().contextAvailableTokens !== null ? formatTokens(sessionInfo().contextAvailableTokens ?? 0) : "--"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="connection-status-text connection-status-shortcut">
|
<div class="connection-status-text connection-status-shortcut">
|
||||||
|
|
||||||
<div class="connection-status-shortcut-action">
|
<div class="connection-status-shortcut-action">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ const ContextUsagePanel: Component<ContextUsagePanelProps> = (props) => {
|
|||||||
return value > 0 ? value : 0
|
return value > 0 ? value : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const formatTokenValue = (value: number | null | undefined) => {
|
const formatTokenValue = (value: number | null | undefined) => {
|
||||||
if (value === null || value === undefined) return "--"
|
if (value === null || value === undefined) return "--"
|
||||||
return formatTokenTotal(value)
|
return formatTokenTotal(value)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import type { Instance } from "../../types/instance"
|
|||||||
export interface UseCommandsOptions {
|
export interface UseCommandsOptions {
|
||||||
preferences: Accessor<Preferences>
|
preferences: Accessor<Preferences>
|
||||||
toggleShowThinkingBlocks: () => void
|
toggleShowThinkingBlocks: () => void
|
||||||
|
toggleUsageMetrics: () => void
|
||||||
setDiffViewMode: (mode: "split" | "unified") => void
|
setDiffViewMode: (mode: "split" | "unified") => void
|
||||||
setToolOutputExpansion: (mode: ExpansionPreference) => void
|
setToolOutputExpansion: (mode: ExpansionPreference) => void
|
||||||
setDiagnosticsExpansion: (mode: ExpansionPreference) => void
|
setDiagnosticsExpansion: (mode: ExpansionPreference) => void
|
||||||
@@ -421,9 +422,22 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
commandRegistry.register({
|
||||||
|
id: "token-usage-visibility",
|
||||||
|
label: () => {
|
||||||
|
const visible = options.preferences().showUsageMetrics ?? true
|
||||||
|
return `Token Usage Display · ${visible ? "Visible" : "Hidden"}`
|
||||||
|
},
|
||||||
|
description: "Show or hide token and cost stats for assistant messages",
|
||||||
|
category: "System",
|
||||||
|
keywords: ["token", "usage", "cost", "stats"],
|
||||||
|
action: options.toggleUsageMetrics,
|
||||||
|
})
|
||||||
|
|
||||||
commandRegistry.register({
|
commandRegistry.register({
|
||||||
id: "help",
|
id: "help",
|
||||||
label: "Show Help",
|
label: "Show Help",
|
||||||
|
|
||||||
description: "Display keyboard shortcuts and help",
|
description: "Display keyboard shortcuts and help",
|
||||||
category: "System",
|
category: "System",
|
||||||
keywords: ["/help", "shortcuts", "help"],
|
keywords: ["/help", "shortcuts", "help"],
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export interface Preferences {
|
|||||||
diffViewMode: DiffViewMode
|
diffViewMode: DiffViewMode
|
||||||
toolOutputExpansion: ExpansionPreference
|
toolOutputExpansion: ExpansionPreference
|
||||||
diagnosticsExpansion: ExpansionPreference
|
diagnosticsExpansion: ExpansionPreference
|
||||||
|
showUsageMetrics: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenCodeBinary {
|
export interface OpenCodeBinary {
|
||||||
@@ -60,6 +61,7 @@ const defaultPreferences: Preferences = {
|
|||||||
diffViewMode: "split",
|
diffViewMode: "split",
|
||||||
toolOutputExpansion: "expanded",
|
toolOutputExpansion: "expanded",
|
||||||
diagnosticsExpansion: "expanded",
|
diagnosticsExpansion: "expanded",
|
||||||
|
showUsageMetrics: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function deepEqual(a: unknown, b: unknown): boolean {
|
function deepEqual(a: unknown, b: unknown): boolean {
|
||||||
@@ -92,6 +94,7 @@ function normalizePreferences(pref?: Partial<Preferences> & { agentModelSelectio
|
|||||||
diffViewMode: sanitized.diffViewMode ?? defaultPreferences.diffViewMode,
|
diffViewMode: sanitized.diffViewMode ?? defaultPreferences.diffViewMode,
|
||||||
toolOutputExpansion: sanitized.toolOutputExpansion ?? defaultPreferences.toolOutputExpansion,
|
toolOutputExpansion: sanitized.toolOutputExpansion ?? defaultPreferences.toolOutputExpansion,
|
||||||
diagnosticsExpansion: sanitized.diagnosticsExpansion ?? defaultPreferences.diagnosticsExpansion,
|
diagnosticsExpansion: sanitized.diagnosticsExpansion ?? defaultPreferences.diagnosticsExpansion,
|
||||||
|
showUsageMetrics: sanitized.showUsageMetrics ?? defaultPreferences.showUsageMetrics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +273,10 @@ function toggleShowThinkingBlocks(): void {
|
|||||||
updatePreferences({ showThinkingBlocks: !preferences().showThinkingBlocks })
|
updatePreferences({ showThinkingBlocks: !preferences().showThinkingBlocks })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleUsageMetrics(): void {
|
||||||
|
updatePreferences({ showUsageMetrics: !preferences().showUsageMetrics })
|
||||||
|
}
|
||||||
|
|
||||||
function addRecentFolder(path: string): void {
|
function addRecentFolder(path: string): void {
|
||||||
updateConfig((draft) => {
|
updateConfig((draft) => {
|
||||||
draft.recentFolders = buildRecentFolderList(path, draft.recentFolders)
|
draft.recentFolders = buildRecentFolderList(path, draft.recentFolders)
|
||||||
@@ -370,6 +377,7 @@ interface ConfigContextValue {
|
|||||||
setThemePreference: typeof setThemePreference
|
setThemePreference: typeof setThemePreference
|
||||||
updateConfig: typeof updateConfig
|
updateConfig: typeof updateConfig
|
||||||
toggleShowThinkingBlocks: typeof toggleShowThinkingBlocks
|
toggleShowThinkingBlocks: typeof toggleShowThinkingBlocks
|
||||||
|
toggleUsageMetrics: typeof toggleUsageMetrics
|
||||||
setDiffViewMode: typeof setDiffViewMode
|
setDiffViewMode: typeof setDiffViewMode
|
||||||
setToolOutputExpansion: typeof setToolOutputExpansion
|
setToolOutputExpansion: typeof setToolOutputExpansion
|
||||||
setDiagnosticsExpansion: typeof setDiagnosticsExpansion
|
setDiagnosticsExpansion: typeof setDiagnosticsExpansion
|
||||||
@@ -400,6 +408,7 @@ const configContextValue: ConfigContextValue = {
|
|||||||
setThemePreference,
|
setThemePreference,
|
||||||
updateConfig,
|
updateConfig,
|
||||||
toggleShowThinkingBlocks,
|
toggleShowThinkingBlocks,
|
||||||
|
toggleUsageMetrics,
|
||||||
setDiffViewMode,
|
setDiffViewMode,
|
||||||
setToolOutputExpansion,
|
setToolOutputExpansion,
|
||||||
setDiagnosticsExpansion,
|
setDiagnosticsExpansion,
|
||||||
@@ -454,6 +463,7 @@ export {
|
|||||||
updateConfig,
|
updateConfig,
|
||||||
updatePreferences,
|
updatePreferences,
|
||||||
toggleShowThinkingBlocks,
|
toggleShowThinkingBlocks,
|
||||||
|
toggleUsageMetrics,
|
||||||
recentFolders,
|
recentFolders,
|
||||||
addRecentFolder,
|
addRecentFolder,
|
||||||
removeRecentFolder,
|
removeRecentFolder,
|
||||||
|
|||||||
Reference in New Issue
Block a user