mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 03:38:32 +02:00
MUL-3134: remove execution log event count
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { cleanup, screen } from "@testing-library/react";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AgentTask } from "@multica/core/types";
|
||||
import { renderWithI18n } from "../../test/i18n";
|
||||
|
||||
const mockState = vi.hoisted(() => ({
|
||||
taskMessagesOptions: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@multica/core/chat/queries", () => ({
|
||||
taskMessagesOptions: mockState.taskMessagesOptions,
|
||||
}));
|
||||
|
||||
vi.mock("../../common/actor-avatar", () => ({
|
||||
ActorAvatar: () => <span data-testid="actor-avatar" />,
|
||||
}));
|
||||
|
||||
vi.mock("../../common/task-transcript", () => ({
|
||||
TranscriptButton: ({ title }: { title?: string }) => (
|
||||
<button type="button">{title ?? "Transcript"}</button>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("./terminate-task-confirm-dialog", () => ({
|
||||
TerminateTaskConfirmDialog: () => null,
|
||||
}));
|
||||
|
||||
import { ActiveTaskRow } from "./execution-log-section";
|
||||
|
||||
function makeTask(overrides: Partial<AgentTask> = {}): AgentTask {
|
||||
return {
|
||||
id: "task-1",
|
||||
agent_id: "agent-1",
|
||||
runtime_id: "runtime-1",
|
||||
issue_id: "issue-1",
|
||||
status: "running",
|
||||
priority: 0,
|
||||
dispatched_at: null,
|
||||
started_at: "2026-06-08T08:00:00Z",
|
||||
completed_at: null,
|
||||
result: null,
|
||||
error: null,
|
||||
created_at: "2026-06-08T08:00:00Z",
|
||||
trigger_summary: "Started from comment",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cleanup();
|
||||
vi.clearAllMocks();
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-06-08T08:05:04Z"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe("ActiveTaskRow", () => {
|
||||
it("renders running status as elapsed time only", () => {
|
||||
renderWithI18n(<ActiveTaskRow task={makeTask()} issueId="issue-1" />);
|
||||
|
||||
expect(screen.getByText("5m 04s")).toBeInTheDocument();
|
||||
expect(screen.queryByText(/events?/i)).not.toBeInTheDocument();
|
||||
expect(screen.getByText("Started from comment")).toBeInTheDocument();
|
||||
expect(screen.getByText("View transcript")).toBeInTheDocument();
|
||||
expect(mockState.taskMessagesOptions).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -15,9 +15,7 @@ import {
|
||||
} from "@multica/ui/components/ui/tooltip";
|
||||
import { ActorAvatar } from "../../common/actor-avatar";
|
||||
import { formatDuration } from "../../agents/components/agent-activity-hover-content";
|
||||
import { TranscriptButton, buildTimeline } from "../../common/task-transcript";
|
||||
import { taskMessagesOptions } from "@multica/core/chat/queries";
|
||||
import { RunningStat } from "./running-stat";
|
||||
import { TranscriptButton } from "../../common/task-transcript";
|
||||
import { failureReasonLabel } from "../../agents/components/tabs/task-failure";
|
||||
import { useT } from "../../i18n";
|
||||
import { TerminateTaskConfirmDialog } from "./terminate-task-confirm-dialog";
|
||||
@@ -245,15 +243,10 @@ function useStatusLabel(status: AgentTask["status"]): string {
|
||||
}
|
||||
}
|
||||
|
||||
// One active (running / queued / dispatched / parked) task row. Exported so
|
||||
// the issue-detail header live-chip popover renders the exact same row as
|
||||
// this panel — same trigger text, same status treatment, same hover-reveal
|
||||
// Logs/Stop. The popover hosting it must use `keepMounted` so this row (and
|
||||
// its internal confirm dialog) survives the popover closing on Stop click.
|
||||
// Running rows read the shared per-task message cache (taskMessagesOptions,
|
||||
// kept live by useRealtimeSync's global task:message handler) so every surface
|
||||
// — this panel, the header-chip popover, and the transcript dialog — shows the
|
||||
// same live "N events (elapsed)" and the same streaming Logs from one source.
|
||||
// One active (running / queued / dispatched / parked) task row. Running rows
|
||||
// keep status to a single live elapsed timer; transcript and stop stay available
|
||||
// as hover actions. Transcript content lazy-loads on click via TranscriptButton,
|
||||
// so the row no longer fetches task messages just to render a count.
|
||||
export function ActiveTaskRow({
|
||||
task,
|
||||
issueId,
|
||||
@@ -268,15 +261,6 @@ export function ActiveTaskRow({
|
||||
const label = useStatusLabel(task.status);
|
||||
const trigger = useTriggerText(task);
|
||||
|
||||
// Live message stream for this task — only fetched while running. The shared
|
||||
// cache means the panel row, the popover row, and the chip all dedupe to one
|
||||
// fetch + one WS-maintained entry.
|
||||
const { data: msgs } = useQuery({
|
||||
...taskMessagesOptions(task.id),
|
||||
enabled: task.status === "running",
|
||||
});
|
||||
const items = useMemo(() => (msgs ? buildTimeline(msgs) : undefined), [msgs]);
|
||||
|
||||
// Running rows show a live-ticking elapsed timer (the ticking digits carry
|
||||
// "alive", the duration carries "how long"). Only running rows tick.
|
||||
const [now, setNow] = useState(() => Date.now());
|
||||
@@ -320,7 +304,7 @@ export function ActiveTaskRow({
|
||||
<RowStatus title={label}>
|
||||
{task.status === "running" ? (
|
||||
<>
|
||||
<RunningStat eventCount={msgs?.length ?? 0} elapsed={elapsed} />
|
||||
<span className="text-info tabular-nums">{elapsed}</span>
|
||||
<span className="sr-only">{label}</span>
|
||||
</>
|
||||
) : (
|
||||
@@ -332,8 +316,7 @@ export function ActiveTaskRow({
|
||||
<TranscriptButton
|
||||
task={task}
|
||||
agentName=""
|
||||
isLive
|
||||
items={items}
|
||||
isLive={task.status === "running"}
|
||||
title={t(($) => $.execution_log.transcript_tooltip)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useT } from "../../i18n";
|
||||
|
||||
// Shared "running" stat for the header chip and the execution-log / popover
|
||||
// rows so all three read identically: live event count (primary, info blue)
|
||||
// followed by the elapsed time in muted parens — e.g. "58 events (2m45s)".
|
||||
// Both the count and the elapsed are live (event count via the shared
|
||||
// task-messages cache, elapsed via the caller's 1s tick).
|
||||
export function RunningStat({
|
||||
eventCount,
|
||||
elapsed,
|
||||
}: {
|
||||
eventCount: number;
|
||||
elapsed: string;
|
||||
}) {
|
||||
const { t } = useT("issues");
|
||||
return (
|
||||
<span className="flex items-center gap-1 text-xs tabular-nums">
|
||||
<span className="text-info">
|
||||
{t(($) => $.agent_live.event_count, { count: eventCount })}
|
||||
</span>
|
||||
<span className="text-muted-foreground">({elapsed})</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -307,8 +307,6 @@
|
||||
"fallback_name": "Agent",
|
||||
"tool_count_one": "{{count}} tool",
|
||||
"tool_count_other": "{{count}} tools",
|
||||
"event_count_one": "{{count}} event",
|
||||
"event_count_other": "{{count}} events",
|
||||
"transcript_button": "View transcript",
|
||||
"stop_button": "Stop",
|
||||
"stop_tooltip": "Stop agent",
|
||||
|
||||
@@ -295,7 +295,6 @@
|
||||
"queued_elapsed_prefix": "{{elapsed}} 待機中",
|
||||
"fallback_name": "エージェント",
|
||||
"tool_count_other": "ツール {{count}} 件",
|
||||
"event_count_other": "イベント {{count}} 件",
|
||||
"transcript_button": "トランスクリプトを表示",
|
||||
"stop_button": "停止",
|
||||
"stop_tooltip": "エージェントを停止",
|
||||
|
||||
@@ -307,8 +307,6 @@
|
||||
"fallback_name": "에이전트",
|
||||
"tool_count_one": "도구 {{count}}개",
|
||||
"tool_count_other": "도구 {{count}}개",
|
||||
"event_count_one": "이벤트 {{count}}개",
|
||||
"event_count_other": "이벤트 {{count}}개",
|
||||
"transcript_button": "트랜스크립트 보기",
|
||||
"stop_button": "중지",
|
||||
"stop_tooltip": "에이전트 중지",
|
||||
|
||||
@@ -300,7 +300,6 @@
|
||||
"queued_elapsed_prefix": "已排队 {{elapsed}}",
|
||||
"fallback_name": "智能体",
|
||||
"tool_count_other": "{{count}} 次工具调用",
|
||||
"event_count_other": "{{count}} 个事件",
|
||||
"transcript_button": "查看记录",
|
||||
"stop_button": "停止",
|
||||
"stop_tooltip": "停止智能体",
|
||||
|
||||
Reference in New Issue
Block a user