diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts
index bc35a0bd3f..30b5e4eaf7 100644
--- a/apps/client/src/services/utils.ts
+++ b/apps/client/src/services/utils.ts
@@ -922,6 +922,7 @@ export default {
parseDate,
formatDateISO,
formatDateTime,
+ formatTime,
formatTimeInterval,
formatSize,
localNowDateTime,
diff --git a/apps/client/src/widgets/sidebar/SidebarChat.css b/apps/client/src/widgets/sidebar/SidebarChat.css
index f852b219ea..1f332bb5a3 100644
--- a/apps/client/src/widgets/sidebar/SidebarChat.css
+++ b/apps/client/src/widgets/sidebar/SidebarChat.css
@@ -36,8 +36,8 @@
font-size: 0.9rem;
}
-/* Usage footer: pull it closer to the message above by collapsing the flex gap */
-.sidebar-chat-messages .llm-chat-usage {
+/* Footer: pull it closer to the message above by collapsing the flex gap */
+.sidebar-chat-messages .llm-chat-footer {
margin-top: -0.35rem;
margin-bottom: 0;
}
diff --git a/apps/client/src/widgets/type_widgets/llm_chat/ChatMessage.tsx b/apps/client/src/widgets/type_widgets/llm_chat/ChatMessage.tsx
index 1bfd71a1e7..0702bd5953 100644
--- a/apps/client/src/widgets/type_widgets/llm_chat/ChatMessage.tsx
+++ b/apps/client/src/widgets/type_widgets/llm_chat/ChatMessage.tsx
@@ -5,6 +5,7 @@ import { marked } from "marked";
import { useMemo } from "preact/hooks";
import { t } from "../../../services/i18n.js";
+import utils from "../../../services/utils.js";
import type { ContentBlock, StoredMessage, ToolCall } from "./llm_chat_types.js";
import { getMessageText, getMessageToolCalls } from "./llm_chat_types.js";
@@ -205,30 +206,41 @@ export default function ChatMessage({ message, isStreaming }: Props) {
)}
- {message.usage && typeof message.usage.promptTokens === "number" && (
-
- {message.usage.model && (
- {message.usage.model}
- )}
- ·
-
- {" "}
- {t("llm_chat.total_tokens", { total: shortenNumber(message.usage.totalTokens) })}
-
- {message.usage.cost != null && (
- <>
- ·
- ~${message.usage.cost.toFixed(4)}
- >
- )}
-
- )}
+
+
+ {utils.formatTime(new Date(message.createdAt))}
+
+ {message.usage && typeof message.usage.promptTokens === "number" && (
+ <>
+ {message.usage.model && (
+ <>
+ ·
+ {message.usage.model}
+ >
+ )}
+ ·
+
+ {" "}
+ {t("llm_chat.total_tokens", { total: shortenNumber(message.usage.totalTokens) })}
+
+ {message.usage.cost != null && (
+ <>
+ ·
+ ~${message.usage.cost.toFixed(4)}
+ >
+ )}
+ >
+ )}
+
>
);
}
diff --git a/apps/client/src/widgets/type_widgets/llm_chat/LlmChat.css b/apps/client/src/widgets/type_widgets/llm_chat/LlmChat.css
index 15dee696bc..bbd4fe8b4d 100644
--- a/apps/client/src/widgets/type_widgets/llm_chat/LlmChat.css
+++ b/apps/client/src/widgets/type_widgets/llm_chat/LlmChat.css
@@ -24,8 +24,8 @@
margin-top: 0;
}
-/* Collapse gap between the usage footer and the next message */
-.llm-chat-usage + .llm-chat-message {
+/* Collapse gap between the footer and the next message */
+.llm-chat-footer + .llm-chat-message {
margin-top: 0.5rem;
}
@@ -618,8 +618,8 @@
color: var(--danger-color, #dc3545);
}
-/* Token usage display (sits below the message bubble) */
-.llm-chat-usage {
+/* Message footer (timestamp + token usage, sits below the bubble) */
+.llm-chat-footer {
display: flex;
align-items: center;
gap: 0.375rem;
@@ -630,10 +630,18 @@
cursor: default;
}
-.llm-chat-usage .bx {
+.llm-chat-footer-user {
+ justify-content: flex-end;
+}
+
+.llm-chat-footer .bx {
font-size: 0.875rem;
}
+.llm-chat-footer-time {
+ cursor: help;
+}
+
.llm-chat-usage-model {
font-weight: 500;
}
@@ -643,6 +651,7 @@
}
.llm-chat-usage-tokens {
+ cursor: help;
font-family: var(--monospace-font-family, monospace);
}