ToolFallback

Data Display

등록되지 않은 도구 호출을 보여주는 기본 카드.

Usage

커스텀 카드가 없는 도구 호출의 이름·입력·결과를 접이식으로 보여줄 때 사용한다.

import

import

import { ToolFallback } from '@mildang/design-system/unofficial/Chat';

예제를 복사해 쓸 때 필요한 준비

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

외부 패키지를 따로 설치한다. DS 의 전이 의존성에 기대지 않는다.

API Reference

ToolFallback Props

Prop

Type

Default

addResult
필수

(result: unknown) => void

지정 안 함

args
필수

any

지정 안 함

argsText
필수

string

지정 안 함

respondToApproval
필수

(response: ToolApprovalResponse) => void

지정 안 함

resume
필수

(payload: unknown) => void

지정 안 함

status
필수

{ readonly type: "running"; } | { readonly type: "complete"; } | { readonly type: "incomplete"; readonly reason: "error" | "other" | "length" | "cancelled" | "content-filter"; readonly error?: unknown; } | { readonly type: "requires-action"; readonly reason: "interrupt" | "tool-calls"; } | { readonly type: "incomplete"; readonly reason: "tool-calls"; readonly error?: ReadonlyJSONValue; }

지정 안 함

toolCallId
필수

string

지정 안 함

toolName
필수

string

지정 안 함

type
필수

"tool-call"

지정 안 함

approval

{ readonly id: string; readonly approved?: boolean; readonly reason?: string; readonly isAutomatic?: boolean; readonly options?: readonly ToolApprovalOption[]; readonly optionId?: string; readonly resolution?: "cancelled" | "expired"; }

지정 안 함

artifact

unknown

지정 안 함

interrupt

{ type: "human"; payload: unknown; }

지정 안 함

isError

boolean

지정 안 함

mcp

ToolCallMessagePartMcpMetadata

지정 안 함

messages

readonly ThreadMessage[]

지정 안 함

modelContent

readonly ToolModelContentPart[]

지정 안 함

parentId

string

지정 안 함

providerMetadata

PartProviderMetadata

지정 안 함

result

unknown

지정 안 함

timing

ToolCallTiming

지정 안 함

같은 패밀리

@mildang/design-system/unofficial/Chat 에서 같이 내보내는 컴포넌트다.

예제

완료

실행이 끝난 도구 호출을 보여주는 예시다.

코드

import { Tool } from '@mildang/design-system/unofficial/Chat';
import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

const ToolFallbackCompleteExample = () => (
    <div className={wrapper}>
      <Tool.Fallback
        {...toolProps({
          toolName: 'search_courses',
          args: { query: '이차방정식', grade: 2 },
          result: { hits: 3, top: '중2 이차방정식 개념' },
          status: { type: 'complete' },
        })}
      />
    </div>
  );

export default ToolFallbackCompleteExample;

실행 중

코드

import { Tool } from '@mildang/design-system/unofficial/Chat';
import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

const ToolFallbackRunningExample = () => (
    <div className={wrapper}>
      <Tool.Fallback
        {...toolProps({
          toolName: 'fetch_student_progress',
          args: { studentId: 'S-2043' },
          status: { type: 'running' },
        })}
      />
    </div>
  );

export default ToolFallbackRunningExample;

오류

코드

import { Tool } from '@mildang/design-system/unofficial/Chat';
import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

const ToolFallbackErrorExample = () => (
    <div className={wrapper}>
      <Tool.Fallback
        {...toolProps({
          toolName: 'grade_quiz',
          args: { quizId: 'Q-9' },
          isError: true,
          result: { error: '채점 서버에 연결하지 못했습니다.' },
          status: { type: 'incomplete', reason: 'error' },
        })}
      />
    </div>
  );

export default ToolFallbackErrorExample;

승인 대기

서버 승인 게이트나 사람 입력을 기다리는 상태다.

코드

import { Tool } from '@mildang/design-system/unofficial/Chat';
import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

const ToolFallbackAwaitingApprovalExample = () => (
    <div className={wrapper}>
      <Tool.Fallback
        {...toolProps({
          toolName: 'run_command',
          args: { command: 'pnpm test' },
          status: { type: 'requires-action', reason: 'tool-calls' },
        })}
      />
    </div>
  );

export default ToolFallbackAwaitingApprovalExample;

artifact 칩

UI 전용 산출물이 붙은 도구 호출을 보여주는 예시다.

코드

import { Tool } from '@mildang/design-system/unofficial/Chat';
import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

const ToolFallbackWithArtifactExample = () => (
    <div className={wrapper}>
      <Tool.Fallback
        {...toolProps({
          toolName: 'render_chart',
          args: { metric: 'progress' },
          result: { ok: true },
          artifact: { type: 'chart', id: 'a-1' },
        })}
      />
    </div>
  );

export default ToolFallbackWithArtifactExample;

커스텀 카드로 대체

by_name 계약으로 Fallback 대신 앱이 만든 카드를 쓰는 예시다.

코드

import { ToolFallbackProps } from '@mildang/design-system/unofficial/Chat';
import { FC } from 'react';
import { ToolCallMessagePartProps } from '@assistant-ui/react';
import { css } from '@mildang/styled-system/css';

const wrapper = css({ padding: '16', display: 'flex', flexDirection: 'column', gap: '12' });

// 전체 ToolCallMessagePartProps를 만들 필요 없이, 데모용 최소 필드만 지정하고 캐스팅한다.
const toolProps = (o: Partial<ToolFallbackProps>): ToolFallbackProps =>
  ({
    type: 'tool-call',
    toolCallId: 'demo',
    toolName: 'demo_tool',
    args: {},
    argsText: '',
    status: { type: 'complete' },
    addResult: () => {},
    resume: () => {},
    respondToApproval: () => {},
    ...o,
  }) as ToolFallbackProps;

/**
 * 앱이 소유하는 커스텀 카드(Generative UI) 예시.
 * `components.tools.by_name['get_weather']`로 주입되며, DS Fallback 대신 이 카드가 렌더된다.
 * (아래는 by_name에 넣을 컴포넌트를 직접 렌더해 시각만 보여준다.)
 */
const WeatherCard: FC<ToolCallMessagePartProps> = ({ args, result }) => {
  const a = args as { city?: string };
  const r = result as { tempC?: number; condition?: string } | undefined;
  return (
    <div
      className={css({
        borderWidth: '1px',
        borderStyle: 'solid',
        borderColor: 'info.border.base',
        backgroundColor: 'info.surface.base',
        borderRadius: 'md',
        paddingX: '16',
        paddingY: '12',
        display: 'flex',
        flexDirection: 'column',
        gap: '4',
      })}
    >
      <span className={css({ textStyle: 'chat-caption-M', color: 'info.text.base' })}>
        {a.city ?? '도시'} 날씨
      </span>
      <span className={css({ textStyle: 'chat-body', color: 'primary.text.base' })}>
        {r ? `${r.tempC}° · ${r.condition}` : '조회 중…'}
      </span>
    </div>
  );
};

const ToolCustomCardByNameExample = () => (
    <div className={wrapper}>
      <WeatherCard
        {...toolProps({
          toolName: 'get_weather',
          args: { city: '서울' },
          result: { tempC: 29, condition: '맑음' },
        })}
      />
    </div>
  );

export default ToolCustomCardByNameExample;