98 lines
3.3 KiB
TypeScript
98 lines
3.3 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
appendClawdTaskProgress,
|
|
isPendingClawdTaskStatus,
|
|
normalizeClawdTaskMetadata,
|
|
} from "@/lib/openclaw-chat/task-state";
|
|
import {
|
|
getOpenClawTaskAnswer,
|
|
getOpenClawTaskStatus,
|
|
isOpenClawAwaitingUserInputTurnComplete,
|
|
} from "@/lib/openclaw-chat/task-protocol";
|
|
|
|
test.describe("OpenClaw durable task state", () => {
|
|
test("restores a persisted running task after the page remounts", () => {
|
|
const task = normalizeClawdTaskMetadata({
|
|
composerMode: "clawd",
|
|
source: "openclaw",
|
|
taskKind: "clawd_chat",
|
|
status: "running",
|
|
userMessageId: "user-message-id",
|
|
assistantMessageId: "assistant-message-id",
|
|
processingHint: "正在处理",
|
|
progressEvents: [{ event_id: 1, message: "请求已接收" }],
|
|
upstreamTaskId: "task_test_123",
|
|
upstreamTaskKey: "enc:v1:iv:tag:ciphertext",
|
|
upstreamEventsEndpoint: "/api/chat/tasks/task_test_123/events",
|
|
upstreamLastEventId: 18,
|
|
createdAt: 100,
|
|
updatedAt: 200,
|
|
});
|
|
|
|
expect(task).not.toBeNull();
|
|
expect(task?.userMessageId).toBe("user-message-id");
|
|
expect(task && isPendingClawdTaskStatus(task.status)).toBe(true);
|
|
expect(task?.progressEvents).toEqual([
|
|
{ event_id: 1, message: "请求已接收" },
|
|
]);
|
|
expect(task?.upstreamTaskId).toBe("task_test_123");
|
|
expect(task?.upstreamLastEventId).toBe(18);
|
|
});
|
|
|
|
test("deduplicates replayed progress events while keeping new steps", () => {
|
|
const first = { event_id: 8, message: "任务已恢复" };
|
|
const second = { event_id: 9, message: "正在选择工具" };
|
|
let events = appendClawdTaskProgress([], first);
|
|
events = appendClawdTaskProgress(events, first);
|
|
events = appendClawdTaskProgress(events, second);
|
|
|
|
expect(events).toEqual([first, second]);
|
|
});
|
|
|
|
test("refreshes a heartbeat even when it reuses the current event id", () => {
|
|
const first = {
|
|
event_id: 8,
|
|
message: "正在识别产品结构",
|
|
created_at: "2026-09-06T01:00:00Z",
|
|
};
|
|
const heartbeat = {
|
|
event_id: 8,
|
|
heartbeat: true,
|
|
display_text: "正在生成包装排布",
|
|
created_at: "2026-09-06T01:00:05Z",
|
|
};
|
|
let events = appendClawdTaskProgress([], first);
|
|
events = appendClawdTaskProgress(events, heartbeat);
|
|
|
|
expect(events).toHaveLength(1);
|
|
expect(events[0]).toMatchObject({
|
|
event_id: 8,
|
|
heartbeat: true,
|
|
message: "正在识别产品结构",
|
|
display_text: "正在生成包装排布",
|
|
created_at: "2026-09-06T01:00:05Z",
|
|
});
|
|
});
|
|
|
|
test("does not classify completed tasks as pending", () => {
|
|
expect(isPendingClawdTaskStatus("completed")).toBe(false);
|
|
expect(isPendingClawdTaskStatus("failed")).toBe(false);
|
|
});
|
|
|
|
test("recognizes a completed turn that is waiting for the next upload", () => {
|
|
const response = {
|
|
task: { status: "waiting" },
|
|
output: {
|
|
answer: "请上传正视图、侧视图、开门图和尺寸图",
|
|
turn_complete: true,
|
|
awaiting_user_input: true,
|
|
business_status: "awaiting_user_input",
|
|
},
|
|
};
|
|
|
|
expect(getOpenClawTaskStatus(response)).toBe("waiting");
|
|
expect(isOpenClawAwaitingUserInputTurnComplete(response)).toBe(true);
|
|
expect(getOpenClawTaskAnswer(response)).toContain("请上传正视图");
|
|
});
|
|
});
|