diff --git a/src/renderer/components/chat-area.ts b/src/renderer/components/chat-area.ts
index f4b8ca9..c4650d3 100644
--- a/src/renderer/components/chat-area.ts
+++ b/src/renderer/components/chat-area.ts
@@ -184,13 +184,8 @@ export function appendMessageDOM(msg: ChatMessage, index: number): void {
`;
}
- const stats: string[] = [];
- const statClasses: string[] = [];
- if (msg.timestamp) { stats.push(formatTime(msg.timestamp)); statClasses.push(''); }
- if (msg.eval_count != null && msg.eval_count > 0) { stats.push(`${msg.eval_count} tokens`); statClasses.push('stat-tokens'); }
- if (msg.total_duration != null && msg.total_duration > 0) { stats.push(`${(msg.total_duration / 1e9).toFixed(1)}s`); statClasses.push('stat-duration'); }
- if (stats.length > 0) {
- contentHtml += `
;
- if (tc.name === 'read_file' && r.content) {
- const content = String(r.content);
- const lines = content.split('\n');
- const preview = lines.slice(0, 20).join('\n');
- resultHtml = `${escapeHtml(preview)}${lines.length > 20 ? `\n... (共 ${r.lines || lines.length} 行)` : ''}`;
- resultHtml += `📄 ${(r.size as number || 0) > 0 ? formatFileSize(r.size as number) : ''} · ${r.lines || '?'} 行
`;
- } else if (tc.name === 'list_directory' && r.entries) {
- const entries = r.entries as Array<{ name: string; type: string; size: number | null }>;
- resultHtml = entries.slice(0, 30).map(e =>
- `${e.type === 'directory' ? '📁' : '📄'} ${escapeHtml(e.name)}${e.size != null ? ` (${formatFileSize(e.size)})` : ''}
`
- ).join('');
- if (entries.length > 30) resultHtml += `... 共 ${(r.total as number) || entries.length} 项
`;
- } else if (tc.name === 'search_files' && r.results) {
- const results = r.results as Array<{ path: string; matches: Array<{ line: number; text: string }> }>;
- resultHtml = results.slice(0, 10).map(file =>
- file.matches.slice(0, 3).map(m =>
- `📄 ${escapeHtml(file.path)}:${m.line} ${escapeHtml(m.text).slice(0, 80)}
`
- ).join('')
- ).join('');
- resultHtml += `共 ${r.total_files || '?'} 个文件,${r.total_matches || '?'} 处匹配
`;
- } else if (tc.name === 'write_file') {
- resultHtml = `✅ 已写入 ${escapeHtml(String(r.path || ''))} (${formatFileSize(r.bytesWritten as number || 0)})
`;
- } else if (tc.name === 'create_directory') {
- resultHtml = `✅ 已创建 ${escapeHtml(String(r.path || ''))}
`;
- } else if (tc.name === 'delete_file') {
- resultHtml = `✅ 已删除 ${escapeHtml(String(r.path || ''))}
`;
- } else if (tc.name === 'run_command') {
- const stdout = String(r.stdout || '').slice(0, 1000);
- const stderr = String(r.stderr || '').slice(0, 500);
- if (stdout) resultHtml += `${escapeHtml(stdout)}`;
- if (stderr) resultHtml += `${escapeHtml(stderr)}`;
- resultHtml += `exit: ${r.exitCode || 0} · ${r.duration || 0}ms
`;
- } else if (tc.name === 'web_search' && r.results) {
- const results = r.results as Array<{ title: string; url: string; snippet: string }>;
- resultHtml = results.slice(0, 5).map((item, i) =>
- `[${i + 1}] ${escapeHtml(item.title)}
${escapeHtml(item.url)}
`
- ).join('');
- resultHtml += `共 ${r.total || results.length} 条结果
`;
- } else if (tc.name === 'web_fetch') {
- const content = String(r.content || '').slice(0, 500);
- resultHtml = `${escapeHtml(content)}${(r.content as string || '').length > 500 ? '\n...' : ''}`;
- resultHtml += `${r.length || content.length} chars
`;
- } else if (tc.name === 'git' && r.action) {
- if (r.commits) {
- resultHtml = (r.commits as Array<{ hash: string; message: string }>).slice(0, 10).map(c =>
- `${escapeHtml(c.hash)} ${escapeHtml(c.message)}
`
- ).join('');
- } else if (r.branches) {
- resultHtml = (r.branches as Array<{ name: string; current: boolean }>).map(b =>
- `${b.current ? '→ ' : ''}${escapeHtml(b.name)}
`
- ).join('');
- } else {
- resultHtml = `✅ ${r.action} 完成
`;
- }
- } else if (tc.name === 'memory_search' && r.results) {
- const results = r.results as Array<{ type: string; content: string }>;
- resultHtml = results.slice(0, 5).map(m =>
- `${m.type === 'rule' ? '📏' : m.type === 'preference' ? '⚙️' : '📌'} ${escapeHtml(m.content).slice(0, 80)}
`
- ).join('');
- } else if (tc.name === 'session_list' && r.sessions) {
- const sessions = r.sessions as Array<{ title: string; messageCount: number }>;
- resultHtml = sessions.slice(0, 5).map(s =>
- `💬 ${escapeHtml(s.title)}
`
- ).join('');
- } else if (tc.name?.startsWith('browser_')) {
- if (tc.name === 'browser_screenshot' && r.png) {
- resultHtml = `📸 截图已生成
`;
- } else if (tc.name === 'browser_extract') {
- const text = String(r.text || '').slice(0, 300);
- resultHtml = `${escapeHtml(text)}`;
- resultHtml += `链接: ${(r.links as unknown[])?.length || 0} 个
`;
- } else if (r.title) {
- resultHtml = `📄 ${escapeHtml(r.title)}
`;
- } else if (r.result) {
- resultHtml = `${escapeHtml(String(r.result).slice(0, 300))}`;
- } else {
- resultHtml = `✅ 完成
`;
- }
- } else {
- resultHtml = `✅ 操作成功
`;
- }
- } else {
- resultHtml = `❌ ${escapeHtml(tc.result.error || '未知错误')}
`;
- }
- }
-
return ``;
}
@@ -403,19 +307,6 @@ export function updateLastAssistantMessage(content: string, think: string | null
thinkBlock.querySelector('pre')!.textContent = think;
}
- if (stats) {
- let statsDiv = lastMsg.querySelector('.msg-stats');
- if (!statsDiv) {
- statsDiv = document.createElement('div');
- statsDiv.className = 'msg-stats';
- lastMsg.querySelector('.msg-body')!.appendChild(statsDiv);
- }
- const parts: string[] = [];
- if (stats.eval_count != null && stats.eval_count > 0) parts.push(`${stats.eval_count} tokens`);
- if (stats.total_duration != null && stats.total_duration > 0) parts.push(`${(stats.total_duration / 1e9).toFixed(1)}s`);
- if (parts.length) statsDiv.innerHTML = parts.join(' · ');
- }
-
scrollToBottom();
}
@@ -507,18 +398,6 @@ export function enableAutoScroll(): void {
if (scrollBtnEl) scrollBtnEl.style.display = 'none';
}
-/** 统计当前会话总 token 消耗并更新 header 显示 */
-export function updateTotalTokens(): void {
- const session = state.get(KEYS.CURRENT_SESSION);
- const el = document.querySelector('#totalTokensValue');
- if (!el) return;
- if (!session) { el.textContent = '0'; return; }
- const total = session.messages
- .filter(m => m.role === 'assistant' && m.eval_count)
- .reduce((sum, m) => sum + (m.eval_count || 0), 0);
- el.textContent = total > 0 ? total.toLocaleString() : '0';
-}
-
// ── 导出功能 ──
async function nativeSaveFile(defaultName: string, content: string): Promise {
diff --git a/src/renderer/components/history-modal.ts b/src/renderer/components/history-modal.ts
index 3683075..04a5730 100644
--- a/src/renderer/components/history-modal.ts
+++ b/src/renderer/components/history-modal.ts
@@ -4,7 +4,7 @@
import { state, KEYS } from '../state/state.js';
import { debounce, escapeHtml, formatTime } from '../utils/utils.js';
-import { exportAsMarkdown, exportAsHtml, exportAsTxt, renderMessages, clearMessages, updateTotalTokens } from './chat-area.js';
+import { exportAsMarkdown, exportAsHtml, exportAsTxt, renderMessages, clearMessages } from './chat-area.js';
import { clearToolCardsExternal, clearTerminalExternal } from './workspace-panel.js';
import { showConfirm } from './prompt-modal.js';
import { ChatDB } from '../db/chat-db.js';
@@ -186,7 +186,6 @@ async function loadHistorySession(sessionId: string): Promise {
clearMessages();
renderMessages();
- updateTotalTokens();
closeHistoryModal();
}
diff --git a/src/renderer/components/input-area.ts b/src/renderer/components/input-area.ts
index b881194..2957d6d 100644
--- a/src/renderer/components/input-area.ts
+++ b/src/renderer/components/input-area.ts
@@ -8,7 +8,7 @@ import { detectLanguage, truncate, escapeHtml, formatSize } from '../utils/utils
import { getSelectedModel, isThinkEnabled, isVisionAvailable, isToolCallingSupported } from './model-bar.js';
import {
renderMessages, clearMessagesDOM, appendAssistantPlaceholder, appendSystemMessage,
- updateLastAssistantMessage, clearMessages, safeMarkdown, enableAutoScroll, updateTotalTokens,
+ updateLastAssistantMessage, clearMessages, safeMarkdown, enableAutoScroll,
appendToolCallCardToPlaceholder, updateToolCallCardInPlaceholder, resetCurrentPlaceholder
} from './chat-area.js';
import { showToast } from './toast.js';
@@ -371,7 +371,6 @@ async function handleRetry(): Promise {
}
renderMessages();
await saveCurrentSession();
- updateTotalTokens();
}
});
} catch (err) {
@@ -424,7 +423,6 @@ async function handleUndo(): Promise {
clearMessagesDOM();
renderMessages();
- updateTotalTokens();
showToast('已撤销上一轮对话', 'success');
}
@@ -503,7 +501,6 @@ async function handleCompress(): Promise {
clearMessagesDOM();
renderMessages();
- updateTotalTokens();
logInfo(`上下文压缩完成: ${middle.length} 条 → 1 条摘要`);
showToast(`已压缩 ${middle.length} 条消息为摘要`, 'success');
@@ -754,7 +751,6 @@ export async function sendMessage(): Promise {
}
await saveCurrentSession();
- updateTotalTokens();
// ── 自动提取记忆(非阻塞)──
if (isMemoryEnabled() && freshSession.messages.length >= 10) {
@@ -1096,7 +1092,6 @@ async function sendMessageWithAgentLoop(text: string, currentSession: ChatSessio
}
renderMessages();
await saveCurrentSession();
- updateTotalTokens();
}
});
} catch (err) {
diff --git a/src/renderer/index.html b/src/renderer/index.html
index ae3b0d9..1945907 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -35,7 +35,6 @@
- 0