diff --git a/internal/builders/agent_run_log_builder.go b/internal/builders/agent_run_log_builder.go index 45fda25..8eeed79 100644 --- a/internal/builders/agent_run_log_builder.go +++ b/internal/builders/agent_run_log_builder.go @@ -3,12 +3,14 @@ package builders import ( "cs-agent/internal/models" "cs-agent/internal/pkg/dto/response" + "strings" ) func BuildAgentRunLog(item *models.AgentRunLog) response.AgentRunLogResponse { if item == nil { return response.AgentRunLogResponse{} } + hitlStatus, hitlStatusName, hitlSummary := resolveAgentRunLogHITL(item) return response.AgentRunLogResponse{ ID: item.ID, ConversationID: item.ConversationID, @@ -28,6 +30,9 @@ func BuildAgentRunLog(item *models.AgentRunLog) response.AgentRunLogResponse { PlanReason: item.PlanReason, InterruptType: item.InterruptType, ResumeSource: item.ResumeSource, + HitlStatus: hitlStatus, + HitlStatusName: hitlStatusName, + HitlSummary: hitlSummary, FinalAction: item.FinalAction, FinalStatus: item.FinalStatus, ReplyText: item.ReplyText, @@ -37,3 +42,24 @@ func BuildAgentRunLog(item *models.AgentRunLog) response.AgentRunLogResponse { CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"), } } + +func resolveAgentRunLogHITL(item *models.AgentRunLog) (status, statusName, summary string) { + if item == nil { + return "", "", "" + } + replyText := strings.TrimSpace(item.ReplyText) + switch { + case strings.TrimSpace(item.FinalStatus) == "interrupted": + return "pending", "等待确认", "Graph Tool 已发起确认,正在等待用户回复。" + case strings.TrimSpace(item.FinalStatus) == "expired": + return "expired", "已过期", "确认 checkpoint 已失效,需要重新发起。" + case strings.Contains(replyText, "已取消本次工单创建") || strings.Contains(replyText, "已取消本次转人工"): + return "cancelled", "已取消", "用户已明确取消,本次确认流程已终止。" + case strings.TrimSpace(item.ResumeSource) != "": + return "confirmed", "已确认", "用户确认后已恢复执行,并完成后续流程。" + case strings.TrimSpace(item.InterruptType) != "": + return "triggered", "已触发", "本次运行涉及确认式 HITL 流程。" + default: + return "", "", "" + } +} diff --git a/internal/pkg/dto/response/skill_response.go b/internal/pkg/dto/response/skill_response.go index a710b98..52d93b4 100644 --- a/internal/pkg/dto/response/skill_response.go +++ b/internal/pkg/dto/response/skill_response.go @@ -56,6 +56,9 @@ type AgentRunLogResponse struct { PlanReason string `json:"planReason"` InterruptType string `json:"interruptType"` ResumeSource string `json:"resumeSource"` + HitlStatus string `json:"hitlStatus"` + HitlStatusName string `json:"hitlStatusName"` + HitlSummary string `json:"hitlSummary"` FinalAction string `json:"finalAction"` FinalStatus string `json:"finalStatus"` ReplyText string `json:"replyText"` diff --git a/web/app/(console)/agent-run-logs/page.tsx b/web/app/(console)/agent-run-logs/page.tsx index 7ab8450..cdf6d7c 100644 --- a/web/app/(console)/agent-run-logs/page.tsx +++ b/web/app/(console)/agent-run-logs/page.tsx @@ -79,6 +79,21 @@ function actionBadgeVariant(action: string) { } } +function hitlBadgeVariant(status: string) { + switch (status) { + case "pending": + return "secondary" as const + case "confirmed": + return "default" as const + case "cancelled": + return "outline" as const + case "expired": + return "destructive" as const + default: + return "secondary" as const + } +} + export default function DashboardAgentRunLogsPage() { const [keywordInput, setKeywordInput] = useState("") const [plannedActionInput, setPlannedActionInput] = useState("all") @@ -323,6 +338,13 @@ export default function DashboardAgentRunLogsPage() { {item.finalAction || "-"} + {item.hitlStatusName ? ( +
+ + {item.hitlStatusName} + +
+ ) : null}
{item.finalStatus || "-"}
@@ -401,6 +423,14 @@ export default function DashboardAgentRunLogsPage() { `skillRouteTrace: ${activeLog.skillRouteTrace || "-"}`, ]} /> +