返回 AiToEarn
taskStatus.ts
根目录 / project / aitoearn-web / src / components / Chat / utils / taskStatus.ts
1 import type { TaskDetail, TaskMessage } from '@/api/ai/ai.types'
2
3 // 认为这些状态表示任务已结束(不再需要轮询)
4 // 同时支持大写和小写格式(兼容后端返回的格式)
5 const COMPLETED_STATUS_VALUES = [
6 'completed',
7 'COMPLETED',
8 'failed',
9 'FAILED',
10 'cancelled',
11 'CANCELLED',
12 'aborted',
13 'ABORTED',
14 'requires_action', // 需要用户操作也算完成(停止轮询)
15 'error',
16 ]
17
18 /**
19 * 根据 TaskDetail 的 status 判断任务是否完成
20 */
21 export function isTaskCompletedByStatus(
22 task: Pick<TaskDetail, 'status'> | null | undefined,
23 ): boolean {
24 if (!task)
25 return false
26 const statusValue = task.status as string
27 return (
28 COMPLETED_STATUS_VALUES.includes(statusValue?.toLowerCase())
29 || COMPLETED_STATUS_VALUES.includes(statusValue)
30 )
31 }
32
33 /**
34 * 兼容旧逻辑:根据消息列表粗略判断任务是否完成
35 * 仅在没有 status 信息时作为兜底使用
36 */
37 export function isTaskCompletedByMessages(messages: TaskMessage[]): boolean {
38 if (!messages || messages.length === 0) {
39 return false
40 }
41
42 // 从后往前遍历消息,检查是否有完成标志
43 for (let i = messages.length - 1; i >= 0; i--) {
44 const msg = messages[i]
45
46 // 检查 stream_event 类型的消息
47 if (msg.type === 'stream_event') {
48 const streamEvent = msg as any
49 const event = streamEvent.event
50
51 // message_delta 中 stop_reason === 'end_turn' 表示一轮对话结束
52 if (event?.type === 'message_delta' && event?.delta?.stop_reason === 'end_turn') {
53 return true
54 }
55 }
56 }
57
58 return false
59 }
60
61 /**
62 * 统一对外导出的方法:优先看 status,其次兜底看 messages
63 */
64 export function isTaskCompleted(
65 messages: TaskMessage[],
66 task?: Pick<TaskDetail, 'status'> | null,
67 ): boolean {
68 if (task && isTaskCompletedByStatus(task)) {
69 return true
70 }
71 return isTaskCompletedByMessages(messages)
72 }
73
73 lines TYPESCRIPT