@aphrody/m3-ai

中文文档
1.4.7发布于 2026/10/23Apache-2.0 AND MITTypeScriptES Module近 30 天下载 1875

Material Design 3 agent-interaction components (tool calls, markdown, chat composer, workers, tasks): the SpaceUI (@spacedrive/ai) set rebuilt on @aphrody/m3-primitives.

原始使用文档
文档目录6 节
  1. CSS setup
  2. Usage
  3. Components
  4. Local chat
  5. Tests
  6. Credits

@aphrody/m3-ai

Material Design 3 React components for agent interfaces (tool-call cards, markdown, chat bubbles and composer, model selector, task board) and a streaming client for OpenAI-compatible chat servers, rebuilt from SpaceUI's @spacedrive/ai.

bun add @aphrody/m3-ai @aphrody/m3-primitives @aphrody/m3-motion react react-dom tailwindcss
import { useState } from "react";
import { ChatComposer, MessageBubble } from "@aphrody/m3-ai";

export function Chat() {
  const [draft, setDraft] = useState("");
  return (
    <>
      <MessageBubble content="Hello" isUser />
      <ChatComposer
        draft={draft}
        onDraftChange={setDraft}
        onSend={() => setDraft("")}
      />
    </>
  );
}

License: Apache-2.0 AND MIT (LICENSE, LICENSE.spaceui). Install guide: docs/material/m3/INSTALL.md.

Built on @aphrody/m3-primitives, the M3 colour roles, typescale, shapes and motion, and Material Symbols icons. Peers: react and react-dom 18 or 19, tailwindcss 4.1+. @aphrody/m3-ai/ag-ui holds the AG-UI protocol bindings.

CSS setup

The components ship Tailwind class names that use the M3 utilities of @aphrody/m3-theme. Import the tokens, a palette sheet and the M3 utilities, then let Tailwind scan the package output. The full recipe is in SPACEUI-M3-FUSION.md, section "Integration":

@import "tailwindcss";
@import "@aphrody/m3-tokens/m3-tokens.css";
@import "@aphrody/m3-theme/spaceui.css";
@import "@aphrody/m3-theme/tailwind.css";

@source "../node_modules/@aphrody/m3-primitives/dist";
@source "../node_modules/@aphrody/m3-ai/dist";

Load the Material Symbols font once: import @aphrody/m3-fonts/fonts-symbols.css, or call ensureMaterialSymbols() from @aphrody/material-web/icon/material-symbols.js.

Usage

import { ChatComposer, MessageBubble, ToolCall } from "@aphrody/m3-ai";
import type { ToolCallPair } from "@aphrody/m3-ai";

const pair: ToolCallPair = {
  id: "1",
  name: "file_read",
  argsRaw: '{"path":"README.md"}',
  args: { path: "README.md" },
  resultRaw: '{"text":"# Aphrody"}',
  result: { text: "# Aphrody" },
  status: "completed",
};

export function Conversation({ draft, setDraft, send }: Props) {
  return (
    <>
      <MessageBubble content="List the files" isUser />
      <ToolCall pair={pair} />
      <MessageBubble content="There is one file: `README.md`." isUser={false} />
      <ChatComposer draft={draft} onDraftChange={setDraft} onSend={send} />
    </>
  );
}

Components

ComponentM3 anatomy
ToolCallOutlined card (surface-container-low, medium shape): status icon or circular indicator, text-label-large tool name, expandable arguments and result blocks in font-code on surface-container-highest, error results on error-container.
MarkdownProse on the M3 typescale (headline / title / body), font-code code blocks, primary links, outline-variant quotes and tables. size picks the body scale; allowHtml enables raw HTML for trusted content.
MessageBubbleUser turn as a secondary-container bubble (large shape), assistant turn as markdown on the surface with a standard copy icon button.
ChatComposerSearch-bar anatomy: surface-container-high, extra-large shape, text-body-large input, project pill, model chip, standard mic icon button, filled send / stop icon button.
ModelSelectorPill trigger opening an M3 menu (surface-container, extra-small shape, level 2): search field, provider section headers, 48 dp items, selection on secondary-container, capability chips. ModelOptionList and groupModelsByProvider expose the list alone.
InlineWorkerCardFilled card (surface-container, medium shape), text-title-small header, status chip, circular indicator while running, expandable transcript of ToolCalls and markdown.
InlineBranchCardFilled card for a thinking branch: indicator or branch icon, status chip, expandable conclusion.
TaskStatusIconMaterial Symbol per status: done success, in progress and ready primary, pending approval warning, backlog outline.
TaskPriorityIconMaterial Symbol per priority: critical error, high warning, medium primary, low outline.
TaskRowDense M3 list item (48 dp): text-body-large headline, text-body-small supporting columns, 8 % hover state layer, secondary-container selection, overflow menu.
TaskListTasks grouped by status: collapsible text-title-small section headers, outline-variant dividers.
TaskDetailTask on an M3 surface: text-headline-small title, property grid, subtasks as a checkbox list, markdown description, filled and text buttons.
TaskCreateFormTitle and description text fields, priority select, filled Create and text Cancel buttons.

Helpers from types.ts: pairTranscriptSteps, tryParseJson, isErrorResult, TASK_STATUS_ORDER, TASK_STATUS_LABEL, TASK_PRIORITY_LABEL, and the transcript, task and model types.

Local chat

Everything a chat over an OpenAI-compatible server (llama-server, vLLM, the Aphrody gateway) needs, with no visible string hard-coded:

ExportRole
ChatLabels, chatLabelsFr / chatLabelsEn / chatLabelsJa, resolveChatLabels, formatLabelOne dictionary for every visible string and aria-label. Every chat component takes labels?: Partial<ChatLabels>; missing keys fall back on English.
streamChatCompletion, createSseParser, parseChatCompletionChunk, chatReducer, ChatStreamErrorPure streaming client of POST <baseUrl>/chat/completions (stream: true): SSE framing, content / reasoning_content / tool-call deltas, finish_reason, top-level citations and refusal. Network failures and 404/502/503/504 are unavailable.
useOpenAIChat({ baseUrl, model, fetch?, headers?, initialMessages?, preamble?, body? })React hook: { messages, send, stop, status, error, reset, setMessages }, status is idle, streaming, error or unavailable.
ConversationListNavigation-drawer list: new conversation, optional search, rename / delete callbacks, empty state, localized dates.
ModelUnavailableDownloading / loading / unavailable state with a determinate linear indicator and a retry button.
CitedMarkdown, CitationChip, CitationList, RefusalNoticeGrounded answers: [n] markers as chips, the numbered sources, the "not established in the sources" notice. MessageBubble takes citations and refusal directly.
MemoryPanelSaved memories with per-item deletion and a confirmed "clear all" (confirmClear injects your own dialog).
ChatIconThe chat icons as inline Material Symbols SVG: no icon font is needed by the chat components.

Markdown (and MessageBubble, CitedMarkdown) open external links with target="_blank" rel="noopener noreferrer" and take onLinkClick(href, event) (call event.preventDefault() to open the system browser from a Tauri webview) or renderLink. ChatComposer takes disabled (the model is unavailable: input, send, voice and selectors are inert), distinct from isSending.

Tests

bun test

test/preload.ts resolves @aphrody/m3-primitives to its sources, so the tests do not need a built dist.

Credits

Derived from SpaceUI @spacedrive/ai (MIT, see LICENSE.spaceui), rebuilt on Material Design 3. New code is Apache-2.0.

版本与发布记录

@aphrody/m3-ai 共发布 12 个版本,首次发布于 2026/09/25;过去 12 个月发布了 12 个版本。

版本发布日期距今
1.4.7latest2026/10/2316 天前
1.4.42026/10/1821 天前
3.3.112026/10/1029 天前
3.3.92026/10/1029 天前
3.3.82026/10/0930 天前
3.3.72026/10/071 个月前

关于 @aphrody/m3-ai 的常见问题

@aphrody/m3-ai 是什么?

Material Design 3 agent-interaction components (tool calls, markdown, chat composer, workers, tasks): the SpaceUI (@spacedrive/ai) set rebuilt on @aphrody/m3-primitives.

如何安装 @aphrody/m3-ai?

在项目目录运行 npm install @aphrody/m3-ai,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18.0.0)、react-dom(>=18.0.0)、tailwindcss(>=4.1.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@aphrody/m3-ai 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aphrody/m3-ai 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aphrody/m3-ai 可以商用吗?

@aphrody/m3-ai 使用 Apache-2.0 AND MIT 许可。声明的许可为 Apache-2.0 AND MIT,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@aphrody/m3-ai 的下载量有多少?

根据 npm 官方下载统计,@aphrody/m3-ai 在 2026/10/06 – 2026/11/04 这 30 天内被下载 1,875 次,日均约 63 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aphrody/m3-ai 还在维护吗?

最新版本 1.4.7 发布于 2026/10/23(16 天前);至今共发布 12 个版本,其中过去 12 个月发布了 12 个;首次发布于 2026/09/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。