Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/components/ai-edition/LeftPanel.copyMessage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,15 @@ describe("ChatStripPanel Copy message (issue #738)", () => {
expect(toastError).not.toHaveBeenCalled();
});
});

describe("ChatStripPanel message time (#1134)", () => {
it("shows a stored message's time as a clock time, never as the raw ISO string", async () => {
stubClipboard(copyToClipboard);
const view = await renderPanelWithAssistantMessage();

// The main process stores every message with an ISO `createdAt`. A session loaded from it,
// like the one a first message creates, used to print that string as is.
expect(view.container.textContent).not.toContain("2026-09-23T00:00:01");
expect(view.getByText(new Date("2026-09-23T00:00:01Z").toLocaleTimeString())).toBeTruthy();
});
});
13 changes: 10 additions & 3 deletions src/components/ai-edition/LeftPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface ChatDisplayMessage {
id?: string;
role: string;
content: string;
/** ISO timestamp, as the main process stores it; formatted only where it is drawn (#1134). */
time?: string;
toolCalls?: AiEditionToolCallSummary[];
// ponytail: axcut parity — non-null on user messages that have a
Expand All @@ -46,6 +47,12 @@ interface ChatDisplayMessage {
thinking?: string;
}

/** A message's clock time; a stored value that is no date is shown as stored. */
function formatMessageTime(time: string): string {
const date = new Date(time);
return Number.isNaN(date.getTime()) ? time : date.toLocaleTimeString();
}

// Quick-access model picker anchored to the composer's model pill — mirrors
// axcut's LlmPopover in "models"/"providers" mode (a lightweight popover, not
// the full AI-settings modal). "Provider settings…" in the providers screen
Expand Down Expand Up @@ -601,7 +608,7 @@ export function ChatStripPanel() {
id: optimisticUserId,
role: "user",
content: text,
time: new Date().toLocaleTimeString(),
time: new Date().toISOString(),
checkpointId: optimisticUserId,
},
]);
Expand Down Expand Up @@ -672,7 +679,7 @@ export function ChatStripPanel() {
{
role: "assistant",
content: assistant.content,
time: new Date().toLocaleTimeString(),
time: new Date().toISOString(),
toolCalls: assistant.toolCalls,
// ponytail: snapshot the live reasoning trace onto the
// finished message so it can be revisited (collapsed by
Expand Down Expand Up @@ -1263,7 +1270,7 @@ export function ChatStripPanel() {
color: "var(--muted)",
}}
>
{m.time}
{formatMessageTime(m.time)}
</span>
) : null}
</div>
Expand Down
Loading