fix: keep canvas chat messages ordered
This commit is contained in:
parent
690d04ec71
commit
57a4840df2
@ -381,11 +381,15 @@ export function sortCanvasMessagesByCreatedAt(messages: ChatMessage[]): ChatMess
|
|||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const messageA = a.message;
|
const messageA = a.message;
|
||||||
const messageB = b.message;
|
const messageB = b.message;
|
||||||
const timeA = getMessageTimestamp(messageA) ?? 0;
|
const timeA = getMessageTimestamp(messageA);
|
||||||
const timeB = getMessageTimestamp(messageB) ?? 0;
|
const timeB = getMessageTimestamp(messageB);
|
||||||
if (timeA !== timeB) return timeA - timeB;
|
const hasTimeA = timeA !== null;
|
||||||
|
const hasTimeB = timeB !== null;
|
||||||
|
|
||||||
if (messageA.role !== messageB.role) {
|
if (hasTimeA && hasTimeB && timeA !== timeB) return timeA - timeB;
|
||||||
|
if (hasTimeA !== hasTimeB) return hasTimeA ? -1 : 1;
|
||||||
|
|
||||||
|
if (hasTimeA && hasTimeB && messageA.role !== messageB.role) {
|
||||||
if (messageA.role === "user") return -1;
|
if (messageA.role === "user") return -1;
|
||||||
if (messageB.role === "user") return 1;
|
if (messageB.role === "user") return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
extractAssistantImageUrls,
|
extractAssistantImageUrls,
|
||||||
extractVideoUrls,
|
extractVideoUrls,
|
||||||
normalizeMediaUrl,
|
normalizeMediaUrl,
|
||||||
|
sortCanvasMessagesByCreatedAt,
|
||||||
stripMediaMarkup,
|
stripMediaMarkup,
|
||||||
} from "@/components/canvas/chat-panel/canvas-chat-media";
|
} from "@/components/canvas/chat-panel/canvas-chat-media";
|
||||||
import {
|
import {
|
||||||
@ -211,6 +212,54 @@ import type { CanvasAgentContext } from "@/types/canvas/agent-protocol";
|
|||||||
import type { ChatMessage } from "@/lib/types";
|
import type { ChatMessage } from "@/lib/types";
|
||||||
|
|
||||||
test.describe("canvas chat pure helpers", () => {
|
test.describe("canvas chat pure helpers", () => {
|
||||||
|
test("keeps optimistic messages without timestamps after persisted history", () => {
|
||||||
|
const messages = [
|
||||||
|
{
|
||||||
|
id: "optimistic-latest-user",
|
||||||
|
role: "user",
|
||||||
|
parts: [{ type: "text", text: "你能为我做什么?列出表给我" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "persisted-first-user",
|
||||||
|
role: "user",
|
||||||
|
createdAt: "2026-07-07T01:00:00.000Z",
|
||||||
|
parts: [{ type: "text", text: "你好" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "persisted-first-assistant",
|
||||||
|
role: "assistant",
|
||||||
|
createdAt: "2026-07-07T01:00:01.000Z",
|
||||||
|
parts: [{ type: "text", text: "你好,我在。" }],
|
||||||
|
},
|
||||||
|
] as ChatMessage[];
|
||||||
|
|
||||||
|
expect(sortCanvasMessagesByCreatedAt(messages).map((message) => message.id)).toEqual([
|
||||||
|
"persisted-first-user",
|
||||||
|
"persisted-first-assistant",
|
||||||
|
"optimistic-latest-user",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("preserves relative order among messages without timestamps", () => {
|
||||||
|
const messages = [
|
||||||
|
{
|
||||||
|
id: "pending-user",
|
||||||
|
role: "user",
|
||||||
|
parts: [{ type: "text", text: "生成一张图" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "pending-assistant",
|
||||||
|
role: "assistant",
|
||||||
|
parts: [{ type: "text", text: "分析中" }],
|
||||||
|
},
|
||||||
|
] as ChatMessage[];
|
||||||
|
|
||||||
|
expect(sortCanvasMessagesByCreatedAt(messages).map((message) => message.id)).toEqual([
|
||||||
|
"pending-user",
|
||||||
|
"pending-assistant",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("formats uploaded spreadsheet rows as safe markdown tables for OpenClaw", () => {
|
test("formats uploaded spreadsheet rows as safe markdown tables for OpenClaw", () => {
|
||||||
const markdown = rowsToOpenClawMarkdownTable([
|
const markdown = rowsToOpenClawMarkdownTable([
|
||||||
["名称", "备注"],
|
["名称", "备注"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user