ToolGroup

Data Display

연속된 도구 호출을 하나로 묶어 접는 래퍼.

Usage

여러 도구 호출이 연이어 발생할 때 "N개 도구 사용"으로 묶어 보여줄 때 사용한다.

import

import

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

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

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

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

API Reference

ToolGroup Props

Prop

Type

Default

count
필수

number

지정 안 함

running

boolean

false

같은 패밀리

@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 ToolGroupExample = () => (
    <div className={wrapper}>
      <Tool.Group count={2} running>
        <Tool.Fallback
          {...toolProps({
            toolName: 'search_courses',
            args: { query: '분수의 나눗셈' },
            result: { hits: 5 },
          })}
        />
        <Tool.Fallback
          {...toolProps({
            toolName: 'get_recommendation',
            args: { level: 'basic' },
            status: { type: 'running' },
          })}
        />
      </Tool.Group>
    </div>
  );

export default ToolGroupExample;

메시지에 배선

Message.GroupedParts와 groupPartByType으로 Fallback·Group을 실제로 연결한 예시다.

코드

// ToolWiredInMessage.example.tsx
import { groupPartByType } from "@assistant-ui/react";
import { css } from "@mildang/styled-system/css";
import { Thread, Message, Tool } from "@mildang/design-system/unofficial/Chat";

// ../../examples/mockRuntime.tsx
import {
  AssistantRuntimeProvider,
  useLocalRuntime,
  useRemoteThreadListRuntime
} from "@assistant-ui/react";
import { useState } from "react";
var mockAdapter = {
  async run() {
    return {
      content: [{ type: "text", text: "안녕하세요! 무엇을 도와드릴까요? (mock 응답)" }]
    };
  }
};
function MockRuntimeProvider({
  children,
  initialMessages
}) {
  const runtime = useLocalRuntime(mockAdapter, { initialMessages });
  return <AssistantRuntimeProvider runtime={runtime}>{children}</AssistantRuntimeProvider>;
}

// ToolWiredInMessage.example.tsx
var toolMessages = [
  { role: "user", content: "중2 이차방정식 강의 추천하고 오늘 진도도 확인해줘" },
  {
    role: "assistant",
    content: [
      {
        type: "tool-call",
        toolCallId: "c1",
        toolName: "search_courses",
        args: { query: "중2 이차방정식" },
        result: { hits: 3 },
        argsText: '{"query":"중2 이차방정식"}'
      },
      {
        type: "tool-call",
        toolCallId: "c2",
        toolName: "fetch_student_progress",
        args: { studentId: "S-2043" },
        result: { completed: 0.62 },
        argsText: '{"studentId":"S-2043"}'
      },
      { type: "text", text: "추천 강의 3개를 찾았고, 오늘 진도는 62% 완료했어요." }
    ]
  }
];
var UserMessage = () => <Message role="user">
    <Message.Content>
      <Message.Parts />
    </Message.Content>
  </Message>;
var groupTools = groupPartByType({ "tool-call": ["group-tool"] });
var AssistantMessage = () => <Message role="assistant">
    <Message.Content>
      <Message.GroupedParts groupBy={groupTools}>
        {({ part, children }) => {
  switch (part.type) {
    case "group-tool":
      return <Tool.Group count={part.indices.length} running={part.status.type === "running"}>
                  {children}
                </Tool.Group>;
    case "tool-call":
      return part.toolUI ?? <Tool.Fallback {...part} />;
    case "text":
      return <span>{part.text}</span>;
    default:
      return null;
  }
}}
      </Message.GroupedParts>
    </Message.Content>
  </Message>;
var ToolWiredInMessageExample = () => <MockRuntimeProvider initialMessages={toolMessages}>
    <div className={css({ padding: "16" })}>
      <Thread.Root>
        <Thread.Viewport>
          <Thread.Messages components={{ UserMessage, AssistantMessage }} />
        </Thread.Viewport>
      </Thread.Root>
    </div>
  </MockRuntimeProvider>;
var ToolWiredInMessage_example_default = ToolWiredInMessageExample;
export {
  ToolWiredInMessage_example_default as default
};