Render dashboard live progress markdown

This commit is contained in:
ejclaw
2026-04-28 16:30:37 +09:00
parent 810d3dbf2e
commit 4e0cf80d91
2 changed files with 62 additions and 2 deletions

View File

@@ -109,4 +109,56 @@ describe('RoomCardV2', () => {
expect(html).toContain('TASK_DONE');
expect(html).toContain('prod 배포 완료');
});
it('renders live progress as markdown', () => {
const html = renderToStaticMarkup(
createElement(RoomCardV2, {
activity: activity({
pairedTask: {
id: 'task-1',
title: 'OpenAPI sync',
status: 'running',
roundTripCount: 1,
updatedAt: '2026-04-28T02:01:00.000Z',
currentTurn: {
turnId: 'turn-1',
role: 'owner',
intentKind: 'implementation',
state: 'running',
attemptNo: 1,
executorServiceId: 'svc-1',
executorAgentType: 'codex',
activeRunId: null,
createdAt: '2026-04-28T02:00:00.000Z',
updatedAt: '2026-04-28T02:01:00.000Z',
completedAt: null,
lastError: null,
progressText:
'최신 `origin/dev`로 fast-forward한 뒤 `pnpm openapi:sync`를 실행합니다.',
progressUpdatedAt: '2026-04-28T02:01:00.000Z',
},
outputs: [],
},
}),
activityLoading: false,
busy: false,
draft: '',
entry: { ...entry, status: 'processing' },
expanded: false,
inboxItems: [],
locale: 'ko',
onDraftChange: () => {},
onSendMessage: () => {},
onToggle: () => {},
pinned: false,
t,
...formatters,
}),
);
expect(html).toContain('class="live-progress"');
expect(html).toContain('<code>origin/dev</code>');
expect(html).toContain('<code>pnpm openapi:sync</code>');
expect(html).not.toContain('`origin/dev`');
});
});

View File

@@ -519,7 +519,7 @@ function CollapsedLiveTurn({
</time>
</header>
{turn.progressText && turn.progressText.trim() ? (
<pre className="live-progress">{turn.progressText}</pre>
<LiveProgressBody text={turn.progressText} />
) : turn.activeRunId ? (
<code className="live-run">{turn.activeRunId}</code>
) : null}
@@ -527,6 +527,14 @@ function CollapsedLiveTurn({
);
}
function LiveProgressBody({ text }: { text: string }) {
return (
<div className="live-progress">
<ParsedBody text={text} />
</div>
);
}
function CollapsedOutputPreview({
expanded,
isProcessing,
@@ -824,7 +832,7 @@ function RoomLiveTimelineEntry({
</header>
<div className="room-timeline-body">
{liveProgressDisplay ? (
<pre className="live-progress">{liveProgressDisplay}</pre>
<LiveProgressBody text={liveProgressDisplay} />
) : (
<p className="room-empty">{t.rooms.loadingActivity}</p>
)}