diff --git a/web/hwlab-cloud-web/src/components/workbench/CodeAgentStatusSummary.vue b/web/hwlab-cloud-web/src/components/workbench/CodeAgentStatusSummary.vue index ea6a95a2..ff6fa65e 100644 --- a/web/hwlab-cloud-web/src/components/workbench/CodeAgentStatusSummary.vue +++ b/web/hwlab-cloud-web/src/components/workbench/CodeAgentStatusSummary.vue @@ -7,39 +7,58 @@ import { firstNonEmptyString } from "@/utils"; const props = defineProps<{ message: ChatMessage }>(); const trace = computed(() => props.message.runnerTrace ?? null); -const agentRun = computed(() => asAgentRun(trace.value?.agentRun)); -const error = computed(() => props.message.error ?? null); +const traceRecord = computed(() => recordValue(trace.value)); +const agentRun = computed(() => asAgentRun(traceRecord.value?.agentRun ?? (props.message as Record).agentRun)); +const error = computed(() => normalizeSummaryError(props.message.error ?? traceRecord.value?.error)); const eventCount = computed(() => trace.value?.eventCount ?? trace.value?.events?.length ?? 0); +const errorTitle = computed(() => firstNonEmptyString(error.value?.code, error.value?.category, "失败原因")); +const errorMessage = computed(() => firstNonEmptyString(error.value?.message, error.value?.userMessage, error.value?.reason)); + const rows = computed(() => [ - { key: "messageStatus", label: "消息状态", value: props.message.status }, - { key: "traceStatus", label: "Trace 状态", value: firstNonEmptyString(trace.value?.status, trace.value?.traceStatus) }, - { key: "traceId", label: "Trace", value: props.message.traceId ?? trace.value?.traceId }, - { key: "conversationId", label: "Conversation", value: props.message.conversationId }, - { key: "sessionId", label: "Session", value: props.message.sessionId ?? trace.value?.sessionId }, - { key: "threadId", label: "Thread", value: props.message.threadId ?? trace.value?.threadId }, - { key: "runnerKind", label: "Runner", value: trace.value?.runnerKind ?? agentRun.value?.adapter }, - { key: "sessionMode", label: "Session Mode", value: trace.value?.sessionMode ?? agentRun.value?.backendProfile }, - { key: "waitingFor", label: "Waiting For", value: trace.value?.waitingFor }, - { key: "lastEvent", label: "Last Event", value: trace.value?.lastEventLabel }, - { key: "eventCount", label: "Events", value: String(eventCount.value) }, - { key: "eventsCompacted", label: "Compacted", value: trace.value?.eventsCompacted === true ? "true" : "false" }, - { key: "fullTraceLoaded", label: "Full Trace", value: trace.value?.fullTraceLoaded === true ? "loaded" : "unverified" }, - { key: "runId", label: "AgentRun", value: agentRun.value?.runId }, - { key: "commandId", label: "Command", value: agentRun.value?.commandId }, - { key: "attemptId", label: "Attempt", value: agentRun.value?.attemptId }, - { key: "runnerId", label: "Runner ID", value: agentRun.value?.runnerId }, - { key: "jobName", label: "Job", value: agentRun.value?.jobName }, - { key: "namespace", label: "Namespace", value: agentRun.value?.namespace }, - { key: "terminalStatus", label: "Terminal", value: agentRun.value?.terminalStatus }, - { key: "errorCode", label: "Error Code", value: error.value?.code }, - { key: "errorCategory", label: "Error Category", value: error.value?.category }, - { key: "providerStatus", label: "Provider Status", value: error.value?.providerStatus == null ? null : String(error.value.providerStatus) } -].map((row) => ({ ...row, value: row.value == null || row.value === "" ? "未观测" : String(row.value) }))); + summaryRow("messageStatus", "消息状态", props.message.status), + summaryRow("traceStatus", "Trace 状态", firstNonEmptyString(trace.value?.status, trace.value?.traceStatus)), + summaryRow("traceId", "Trace", props.message.traceId ?? trace.value?.traceId), + summaryRow("conversationId", "Conversation", props.message.conversationId), + summaryRow("sessionId", "Session", props.message.sessionId ?? trace.value?.sessionId), + summaryRow("threadId", "Thread", props.message.threadId ?? trace.value?.threadId), + summaryRow("runnerKind", "Runner", trace.value?.runnerKind ?? agentRun.value?.adapter), + summaryRow("sessionMode", "Session Mode", trace.value?.sessionMode ?? agentRun.value?.backendProfile), + summaryRow("waitingFor", "Waiting For", trace.value?.waitingFor), + summaryRow("lastEvent", "Last Event", trace.value?.lastEventLabel), + summaryRow("eventCount", "Events", eventCount.value > 0 ? eventCount.value : null), + summaryRow("eventsCompacted", "Compacted", trace.value?.eventsCompacted === true ? "true" : null), + summaryRow("fullTraceLoaded", "Full Trace", trace.value?.fullTraceLoaded === true ? "loaded" : null), + summaryRow("runId", "AgentRun", agentRun.value?.runId), + summaryRow("commandId", "Command", agentRun.value?.commandId), + summaryRow("attemptId", "Attempt", agentRun.value?.attemptId), + summaryRow("runnerId", "Runner ID", agentRun.value?.runnerId), + summaryRow("jobName", "Job", agentRun.value?.jobName), + summaryRow("namespace", "Namespace", agentRun.value?.namespace), + summaryRow("terminalStatus", "Terminal", agentRun.value?.terminalStatus), + summaryRow("errorCode", "Error Code", error.value?.code), + summaryRow("errorCategory", "Error Category", error.value?.category), + summaryRow("providerStatus", "Provider Status", error.value?.providerStatus) +].filter((row): row is { key: string; label: string; value: string } => Boolean(row))); function asAgentRun(value: unknown): AgentRunProvenance | null { return value && typeof value === "object" ? value as AgentRunProvenance : null; } + +function recordValue(value: unknown): Record | null { + return value && typeof value === "object" ? value as Record : null; +} + +function summaryRow(key: string, label: string, value: unknown): { key: string; label: string; value: string } | null { + const text = value == null ? "" : String(value).trim(); + return text ? { key, label, value: text } : null; +} + +function normalizeSummaryError(value: unknown): Record | null { + if (!value) return null; + if (typeof value === "string") return value.trim() ? { message: value.trim() } : null; + return value && typeof value === "object" ? value as Record : null; +}