fix: prompt caching, conversation length management and token usage display

This commit is contained in:
2026-02-26 20:07:06 +01:00
parent daf8addb53
commit 9149c21bdf
20 changed files with 317 additions and 7 deletions

View File

@@ -123,11 +123,24 @@ export const AssistantSidebar: React.FC = () => {
}
});
const unsubTokenUsage = window.electronAPI?.chat.onTokenUsage((data) => {
if (data.conversationId === conversationId) {
useAppStore.getState().setChatTokenUsage(conversationId, {
inputTokens: data.cumulativeInputTokens,
outputTokens: data.cumulativeOutputTokens,
cacheReadTokens: data.cumulativeCacheReadTokens,
cacheWriteTokens: data.cumulativeCacheWriteTokens,
totalTokens: data.cumulativeTotalTokens,
});
}
});
return () => {
unsubDelta?.();
unsubToolCall?.();
unsubToolResult?.();
unsubTitle?.();
unsubTokenUsage?.();
};
}, [conversationId, appendStreamDelta, recordToolCall, recordToolResult]);

View File

@@ -148,11 +148,24 @@ export const ChatPanel: React.FC<ChatPanelProps> = ({ conversationId }) => {
}
});
const unsubTokenUsage = window.electronAPI?.chat.onTokenUsage((data) => {
if (data.conversationId === conversationId) {
useAppStore.getState().setChatTokenUsage(conversationId, {
inputTokens: data.cumulativeInputTokens,
outputTokens: data.cumulativeOutputTokens,
cacheReadTokens: data.cumulativeCacheReadTokens,
cacheWriteTokens: data.cumulativeCacheWriteTokens,
totalTokens: data.cumulativeTotalTokens,
});
}
});
return () => {
unsubDelta?.();
unsubToolCall?.();
unsubToolResult?.();
unsubTitle?.();
unsubTokenUsage?.();
};
}, [conversationId, loadData, scrollToBottom, checkReady, appendStreamDelta, recordToolCall, recordToolResult]);

View File

@@ -95,6 +95,11 @@
border-radius: 3px;
}
.status-bar-item.token-usage {
font-variant-numeric: tabular-nums;
opacity: 0.85;
}
.status-bar-item.language-badge {
border: 1px solid var(--vscode-statusBar-border, transparent);
border-radius: 3px;

View File

@@ -21,6 +21,9 @@ export const StatusBar: React.FC = () => {
selectedPostId,
totalPosts,
picoTheme,
tabs,
activeTabId,
chatTokenUsage,
} = useAppStore();
const [selectedPostStatus, setSelectedPostStatus] = useState<string | null>(null);
@@ -39,6 +42,10 @@ export const StatusBar: React.FC = () => {
const runningTasks = tasks.filter(t => t.status === 'running');
const activeTheme = getRendererPicoTheme(picoTheme);
// Detect active chat tab and its token usage
const activeTab = tabs.find(tab => tab.id === activeTabId);
const activeChatUsage = activeTab?.type === 'chat' ? chatTokenUsage[activeTab.id] : null;
return (
<div className="status-bar">
<div className="status-bar-left">
@@ -74,6 +81,17 @@ export const StatusBar: React.FC = () => {
<span>{t('statusBar.media', { count: media.length })}</span>
</div>
{/* Token Usage (visible when chat tab is active) */}
{activeChatUsage && (
<div className="status-bar-item token-usage">
<span>{t('statusBar.tokens', {
input: activeChatUsage.inputTokens.toLocaleString(),
output: activeChatUsage.outputTokens.toLocaleString(),
cached: activeChatUsage.cacheReadTokens.toLocaleString(),
})}</span>
</div>
)}
<div className="status-bar-item theme-badge">
<span>{t('statusBar.theme', { theme: activeTheme })}</span>
</div>