Pluto Design System
Components

ChatProcessTrace

어시스턴트의 thinking·도구 호출·중간 멘트를 한 접힘 컨테이너로 묶는 process-trace 컴포넌트

사용

import { ChatProcessTrace } from "@fluxloop-ai/pds-ui/components/chat-process-trace";

<ChatProcessTrace blocks={blocks} isRunning={false} durationMs={4200} />

Anthropic Messages API 의 thinking · tool_use · tool_result · 중간 text 블록을 그대로 받아 시간순으로 표시한다. 최종 답변(어시스턴트의 마지막 text 블록)은 trace 외부 — 보통 ChatAssistantMessage — 로 분리한다.

동작 규칙

  • 항상 접힘 이 기본 상태. 진행 중에도 자동으로 펼쳐지지 않으며, 사용자 클릭으로만 펼침.
  • Trigger 라벨은 진행 상태에 따라 자연 전환:
    • isRunning={true}Thinking + 텍스트 shimmer (.pds-animate-text-shimmer)
    • isRunning={false} + durationMs 있음 → Thought for {⌈ms/1000⌉}s
    • isRunning={false} + durationMs 없음 → Thought
  • Tool 호출은 1 tool_use = 1 row. 같은 도구가 연속 호출되어도 묶지 않음.
  • tool_result.is_error === true 인 row 는 우측에 작은 failed 칩.
  • redacted_thinking 블록은 표시하지 않음 (의도적 — 보안상 공개 불가).

도구 라벨 결정 순서

(1) resolveToolLabel 사용자 정의 → (2) PDS 빌트인 매핑 → (3) 도구명 raw fallback.

PDS 빌트인은 Anthropic SDK 표준 도구 4종만 알고 있다:

tool_use.name라벨 형식예시
bashRan {command}Ran pdftotext input.pdf
text_editor / str_replace_editor / str_replace_based_edit_toolcommand 분기 (viewRead, createCreated, 그 외 → Edited) + pathRead src/Button.tsx
web_searchSearched "{query}"Searched "chat patterns"
code_executionExecuted code (인자 길이 가변이라 생략)Executed code

MCP 도구 (mcp__linear__* 등) 와 커스텀 도구는 resolveToolLabel 로 직접 처리한다.

<ChatProcessTrace
  blocks={blocks}
  resolveToolLabel={(name, input) => {
    if (name.startsWith("mcp__linear__")) {
      const action = name.replace("mcp__linear__", "");
      return `Linear · ${action}`;
    }
    // undefined 반환 → PDS 빌트인 / 도구명 raw fallback
  }}
/>

아이콘

좌측 카테고리 아이콘은 옵션이다. resolveToolIcon 으로 도구별 아이콘을 주입하지 않으면 라벨만 표시된다. 도구별 1:1 매핑이 아니라 카테고리 단위(예: bash/code_execution → terminal, text_editor → folder, web_search → magnifying glass) 로 묶기를 권장.

데모

① Thinking only (정적)

PDF 텍스트 추출 가능 여부부터 확인할게요. 슬라이드라서 텍스트 레이어가 있으면 바로 요약, 이미지 기반이면 페이지 렌더/OCR 필요 여부만 짧게 말하겠습니다.

텍스트 레이어가 있는 일반 PDF 라면 그대로 추출 가능합니다.

② Single tool call (정적)

먼저 디렉터리 구조를 확인하겠습니다.

total 24 drwxr-xr-x components drwxr-xr-x hooks -rw-r--r-- index.ts

src/ 아래에 components / hooks / index.ts 가 있어요.

③ Multi-tool with intermediate text (정적)

레포의 현재 폴더 구성을 읽어서 핵심 구조만 정리하겠습니다. 코드 변경 없음.

Listed files in . Listed files in .

의존성/빌드 산출물까지 섞이면 구조가 흐려져서, .git, .next, node_modules 는 제외하고 앱 중심 구조를 다시 좁혀 보겠습니다.

{"name":"my-app","version":"0.1.0"}

Found 5 results discussing grid-template-rows transition technique.

앱 중심 구조는 app/ components/ lib/ 세 갈래로 나뉘어 있고, package.json 은 v0.1.0 입니다.

④ Failed tool 포함 (정적)

command not found: pdftotext

pdftotext 는 없고 Python 런타임만 보입니다. 번들 PDF 라이브러리로 텍스트를 뽑아보겠습니다.

ok

pdftotext 가 없어서 pypdf 로 우회했어요.

⑤ Running ↔ Done 자동 토글 (라이브)

사용자 의도를 먼저 파악하고, 가장 짧은 답변을 준비합니다.

진행 중 — trigger 라벨에 shimmer 적용

Props

Prop타입기본설명
blocksProcessTraceBlock[]trace 에 포함될 콘텐츠 블록들. text · thinking · tool_use · tool_result.
isRunningbooleanfalse진행 중이면 trigger 라벨 shimmer + Thinking.
durationMsnumber완료 시 trigger 라벨에 표시할 경과시간(ms).
resolveToolLabel(name, input) => string | undefined도구 라벨 resolver. undefined 반환 시 PDS 빌트인 → 도구명 fallback.
resolveToolIcon(name, input) => ReactNode | undefined카테고리 아이콘 resolver. 미주입 시 아이콘 생략.
renderMarkdown(text) => ReactNodethinking · 중간 멘트 · tool 결과 모두 동일하게 적용.
openbooleancontrolled 모드.
defaultOpenbooleanfalseuncontrolled 초기값.
onOpenChange(open: boolean) => void펼침 상태 변경 콜백.
classNamestring추가 클래스.

What it's NOT

  • Citation / 인용 출처 카드 — 별도 컴포넌트로 다룸.
  • Streaming 시간 측정durationMs 는 외부에서 측정해 prop 으로 주입.
  • Permission prompt / subagent / todo / computer use 오버레이 — 이번 컴포넌트의 책임 밖.
  • i18n 한국어 라벨 내장 — Trigger 라벨/도구 라벨 모두 영어 default. 한국어/제품 톤은 prop override.