diff --git a/packages/views/issues/components/execution-log-section.tsx b/packages/views/issues/components/execution-log-section.tsx index 5b0bfbd2a..6c93e184d 100644 --- a/packages/views/issues/components/execution-log-section.tsx +++ b/packages/views/issues/components/execution-log-section.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { ChevronRight, Loader2, RotateCcw, Square } from "lucide-react"; +import { Ban, CheckCircle2, ChevronRight, Loader2, RotateCcw, Square, XCircle } from "lucide-react"; import { toast } from "sonner"; import { api } from "@multica/core/api"; import { issueKeys } from "@multica/core/issues/queries"; @@ -28,14 +28,12 @@ import { TerminateTaskConfirmDialog } from "./terminate-task-confirm-dialog"; // (sticky card stays as a header-only banner) // - the standalone below the main content // -// Row layout — two visual columns, with an overlaid trailing slot: +// Row layout — simple left/right flex: // 1. Agent avatar (no status dot — agent availability is not the // story here; the row's right column carries the task status) -// 2. Trigger description (e.g. "From comment", "Autopilot", "Retry"), -// masked before the fixed trailing zone -// 3. Fixed right trailing zone: status by default, hover actions on top. -// Status never participates in flex layout, otherwise long terminal -// labels create invisible hover gaps and squeeze the trigger text. +// 2. Trigger description flexes and truncates +// 3. Status is a normal shrink-0 right column; hover actions overlay that +// same right edge. Do not use masks/padding gymnastics here. // // One query (`listTasksByIssue`) drives both buckets — the back-end // returns every status, the front-end filters into active vs past on the @@ -273,7 +271,7 @@ function ActiveRow({ task, issueId }: { task: AgentTask; issueId: string }) { return ( - + {task.status === "running" && } {label} @@ -327,7 +325,6 @@ function PastRow({ task, issueId }: { task: AgentTask; issueId: string }) { const { t } = useT("issues"); const timeAgo = useTimeAgo(); const [retrying, setRetrying] = useState(false); - const tone = STATUS_TONE[task.status]; const label = useStatusLabel(task.status); const trigger = useTriggerText(task); const time = task.completed_at ? timeAgo(task.completed_at) : "—"; @@ -361,9 +358,9 @@ function PastRow({ task, issueId }: { task: AgentTask; issueId: string }) { return ( - - {label} - · {time} + + + {time} $.execution_log.transcript_tooltip)} /> @@ -422,28 +419,10 @@ function RowShell({ ); } -// Trigger description leaves a real layout gutter before the absolute -// trailing slot. Padding is not enough here: text can still visually paint -// under an overlaid status. The right margin makes the text column end -// before status/actions begin. function TriggerText({ text }: { text: string }) { - return ( - - {text} - - ); + return {text}; } -// Fixed trailing status slot. This deliberately does NOT sit in flex layout: -// terminal rows can have longer status/time text, but that text must not -// reserve a huge invisible gap when hover actions fade in. function RowStatus({ children, title, @@ -454,22 +433,33 @@ function RowStatus({ return (
{children}
); } +function TaskStatusIcon({ status }: { status: AgentTask["status"] }) { + switch (status) { + case "completed": + return ; + case "failed": + return ; + case "cancelled": + return ; + default: + return null; + } +} + // Hover-only action slot — absolute-positioned over the row's right edge. -// Default trailing status and hover actions share the same fixed right zone, -// so the row never reflows and long status text never steals trigger width. -// Mirrors the compact Chat History / desktop tab / sidebar pin pattern. +// It covers the normal right status column only on hover. function RowActions({ children }: { children: React.ReactNode }) { return (