- 人工智能
- 大模型
- 代码智能体
- AI Agent
- 桌面应用
- 后端
- 前端
- CLI
【免费下载链接】ZCode
ZCode 是 AI 编程工作台,提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI,以及 Agent CLI 与运行时源码。
AI Elements 是一套构建在 shadcn/ui 之上的组件库与自定义注册表,为 AI 原生应用提供会话(Conversation)、消息(Message)、提示输入(PromptInput)、工具调用展示(Tool)、推理过程(Reasoning)等开箱即用的 React 组件。本文以智谱 AI 的 ZCode 仓库中内置的 ai-elements 技能文档为主体,结合仓库内 @zcode/ui 包 中实际的本地化集成源码,系统讲解 AI Elements 的环境准备、CLI 安装、组件组合用法、可扩展性与定制方式,以及常见故障排查方法。读完本文,你将掌握如何在 ZCode 这类 AI 编程工作台中快速搭建具备消息流、流式输出、工具调用、附件上传与模型选择能力的完整聊天界面。
AI Elements 是什么
AI Elements 是一个组件库与自定义注册表(custom registry),构建在 shadcn/ui 之上,目标是把 AI 原生应用中最常复用的界面能力(会话列表、消息气泡、输入框、工具执行面板等)以「组件即源码」的方式交付给开发者。
它与传统 UI 组件库最大的区别在于分发模型:组件不是打包进 npm 依赖的黑盒,而是通过 CLI 将组件代码直接下载并整合进你的项目目录(默认位于@/components/ai-elements/,也可跟随 shadcn 配置的 components 目录)。这意味着:
- 组件代码成为你代码库的一部分,可以像自己写的代码一样直接阅读、修改与定制;
- 使用方式与普通 React 组件完全一致,无需额外的 Provider 或全局初始化;
- 每个组件尽可能透传原生的 HTML 属性(例如
Message继承HTMLAttributes<HTMLDivElement>),扩展成本极低。
在 ZCode 仓库中,这一套组件已经被完整地本地化整合进了@zcode/ui包,目录为 packages/ui/src/components/ai-elements/,包含conversation.tsx、message.tsx、tool.tsx、prompt-input.tsx、reasoning.tsx、attachments.tsx、code-block.tsx、terminal.tsx等 40 余个本地实现文件。每个文件头部都带有明确的来源与授权声明(Derived from vercel/ai-elements,Copyright 2023 Vercel, Inc.,Apache-2.0,由 ZCode 做本地集成与格式化适配),完整许可与来源信息可查看仓库根目录的 THIRD-PARTY-NOTICES.md。
在 ZCode 中的本地化集成方式
从仓库源码可以确认,ZCode 的 UI 层已经深度采用了 AI Elements:
- packages/ui/components.json 在
registries字段中注册了"@ai-elements": "https://ai-sdk.dev/elements/api/registry/{name}.json",说明该包直接复用了 AI Elements 的官方 registry,shadcnCLI 可以按名拉取对应组件; - packages/ui/package.json 的
exports中显式导出了"./message"指向./src/components/ai-elements/message.tsx,依赖中同时包含ai(AI SDK v6)、use-stick-to-bottom、streamdown、shiki等与 AI Elements 配套的运行时库; - 业务侧已经在真实使用这些组件,例如 ToolCallBlocks/ToolCallBody.tsx 从 ai-elements 导入了
CodeBlock、MessageResponse、ToolInput、ToolOutput来渲染工具调用结果。
从本地实现看,ZCode 还做了一些适配性改造:以 conversation.tsx 为例,它在Conversation上固定了initial="instant"与resize="instant",以避免任务切换时「恢复历史消息 → 自动吸底」被 smooth 动画叠加成拖沓的缓动;导入方式统一改为带.js后缀的相对 ESM 导入,规避 NodeNext 下 package.jsonexports未导出深层路径导致的解析问题。这些都是将上游组件真正落地到生产级 AI 工作台时的典型工程实践。
环境准备(Prerequisites)
在安装 AI Elements 之前,需要确认项目满足以下条件:
| 依赖 | 要求 | 说明 |
|---|---|---|
| Node.js | 18 或更高版本 | 运行安装 CLI 与构建前端的基础运行时 |
| Next.js 项目 | 已初始化 | 组件面向 React 生态,示例以 Next.js App Router 展示 |
| AI SDK | 已安装 | 提供useChat、streamText、UIMessage等核心 API,组件围绕其数据结构设计 |
| shadcn/ui | 已安装(或由安装命令自动安装) | AI Elements 构建在 shadcn/ui 之上,未安装时执行任一安装命令会自动补齐 |
此外,官方建议使用 AI Gateway 并在env.local中配置AI_GATEWAY_API_KEY,这样可以在不逐个配置各家模型厂商 API Key 的情况下统一调用模型,便于快速实验。
安装组件
安装 AI Elements 组件有两种等价方式,效果一致:将所选组件的代码与所需依赖写入项目。
方式一:AI Elements CLI(推荐)
npx ai-elements@latest add <component-name>例如安装会话与消息组件:
npx ai-elements@latest add conversation npx ai-elements@latest add message npx ai-elements@latest add prompt-input重要:所有 CLI 命令都应使用项目
packageManager对应的包运行器,即npx ai-elements@latest、pnpm dlx ai-elements@latest或bunx --bun ai-elements@latest。示例统一用npx,实际项目中请替换为与你的项目一致的运行器。
方式二:shadcn/ui CLI
如果项目已经采用 shadcn 的工作流,可以直接通过 shadcn CLI 安装。前提是在components.json中配置好 AI Elements registry——ZCode 的做法可作参考(见 packages/ui/components.json):
{ "registries": { "@ai-elements": "https://ai-sdk.dev/elements/api/registry/{name}.json" } }配置完成后,shadcn CLI 即可按名拉取 AI Elements 组件。执行成功后终端会显示文件已添加的确认信息,随后即可在代码中使用该组件。
基础使用:五分钟跑通一个对话组件
组件安装完成后,像使用任何 React 组件一样导入即可。以下是来自技能文档的完整示例(保存为conversation.tsx),它用Message系列组件渲染useChat返回的流式消息:
"use client"; import { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message"; import { useChat } from "@ai-sdk/react"; const Example = () => { const { messages } = useChat(); return ( <> {messages.map(({ role, parts }, index) => ( <Message from={role} key={index}> <MessageContent> {parts.map((part, i) => { switch (part.type) { case "text": return <MessageResponse key={`${role}-${i}`}>{part.text}</MessageResponse>; } })} </MessageContent> </Message> ))} </> ); }; export default Example;关键点解读:
Message from={role}:按消息角色(user/assistant)自动切换左右对齐与样式,用户消息使用次级背景色,助手消息通栏展示;MessageContent:内容容器,负责间距与用户消息的主题色(bg-primary等);MessageResponse:渲染 Markdown 正文,默认支持 GFM、数学公式与「不完整 Markdown 智能解析」;- 数据源直接来自 AI SDK 的
useChat(),messages数组无需二次转换,组件与 AI SDK 的数据模型天然对齐。
由于组件代码就在你的项目里,你可以打开组件文件查看实现,也可以按自己的需求直接修改。
组件体系一览
技能文档在 references/ 目录 下为每个组件提供了独立文档,并在 scripts/ 目录 提供可直接运行的示例。以下表格汇总了核心组件及其用途(完整列表见 references 目录):
| 组件 | 用途 | 参考文档 |
|---|---|---|
| Conversation | 会话容器,自动吸底滚动、空态、滚动按钮、Markdown 导出 | conversation.md |
| Message | 消息气泡、动作按钮、回复分支、Markdown 渲染 | message.md |
| PromptInput | 输入框 + 附件上传 + 提交按钮 + 模型选择下拉 | prompt-input.md |
| Tool | 可折叠的工具调用详情(参数、状态、输出/错误) | tool.md |
| Reasoning | 流式推理过程展示,自动展开/收起 | reasoning.md |
| Attachments | 附件展示(网格/行内/列表三种形态) | attachments.md |
| CodeBlock | 代码块语法高亮、行号、复制按钮 | code-block.md |
| Terminal | 流式终端输出,支持 ANSI 颜色与自动滚动 | terminal.md |
| Chain of Thought | 结构化的分步思考过程展示 | chain-of-thought.md |
| Suggestion / Queue / Task 等 | 输入建议、队列状态、任务进度等场景化组件 | 见 references 目录 |
核心组件实战
Conversation:会话容器
Conversation负责包裹消息列表并自动滚动到底部,同时提供「不在底部时出现的滚动按钮」。核心子组件与能力:
ConversationContent:内容区,负责消息间距与内边距;ConversationEmptyState:空会话时的引导态(title、description、icon均可定制);ConversationScrollButton:仅在未处于底部时显示,点击回到最新消息;ConversationDownload:把整个会话导出为 Markdown 文件(默认文件名conversation.md);messagesToMarkdown:导出逻辑的底层工具函数,可自定义消息格式化器,例如只取文本部分拼接:
import { messagesToMarkdown } from "@/components/ai-elements/conversation"; const customMarkdown = messagesToMarkdown( messages, (msg, i) => `[${msg.role}]: ${msg.parts .filter((p) => p.type === "text") .map((p) => p.text) .join("")}`, );底层实现上,Conversation基于use-stick-to-bottom库(ZCode 本地实现见 conversation.tsx),支持contextRef、instance、render prop 等进阶用法,滚动按钮通过useStickToBottomContext()读取isAtBottom状态并调用scrollToBottom。
一个完整的会话 UI 通常由Conversation+PromptInput组合而成:消息区负责展示,输入区负责提交,二者共享 AI SDK 的useChat状态。
Message:消息展示全家桶
Message组件族覆盖了聊天消息展示的大部分需求:
- 消息渲染:
Message(角色与对齐)、MessageContent(内容容器)、MessageResponse(Markdown 正文); - 操作按钮:
MessageActions+MessageAction,支持带 tooltip 的 Retry / Copy / Like 等操作,label用于无障碍朗读,未提供 tooltip 时也作为后备文本; - 回复分支:
MessageBranch、MessageBranchContent、MessageBranchSelector、MessageBranchPrevious、MessageBranchNext、MessageBranchPage,用于在多条候选回复之间切换,defaultBranch指定默认分支(默认 0),onBranchChange监听切换; - 工具栏:
MessageToolbar,以 space-between 布局把操作按钮与分支选择器放在消息下方一行。
MessageResponse的 Markdown 渲染值得一提,它是流式聊天体验的关键:
parseIncompleteMarkdown(默认true):自动修复流式传输中的不完整 Markdown(未闭合的代码块、列表等);remarkPlugins(默认[remarkGfm, remarkMath])与rehypePlugins(默认含rehypeKatex):GFM 表格、任务列表、删除线与数学公式;allowedImagePrefixes/allowedLinkPrefixes:限制图片与链接的 URL 前缀,defaultOrigin处理相对地址,兼顾安全与灵活性;components:传入自定义 React 组件覆盖 Markdown 元素渲染。
在 ZCode 本地实现中(见 message.tsx,约 1670 行),Markdown 渲染链路替换为streamdown全家桶:Streamdown配合@streamdown/cjk、@streamdown/code、@streamdown/math、@streamdown/mermaid插件,语法高亮使用shiki,并额外引入了remark-cjk-friendly-gfm-strikethrough提升中文文本的删除线渲染质量——这是针对中文 AI 工作台场景的典型本地化增强。
PromptInput:带附件的提示输入
PromptInput允许用户携带文件附件向大模型发送消息,内置 textarea、文件上传、提交按钮与模型选择下拉。组件按头部/主体/底部三段式组织:
PromptInputHeader:附件展示区;PromptInputBody:自动伸缩的PromptInputTextarea(Enter 提交、Shift+Enter 换行);PromptInputFooter:工具栏PromptInputTools与提交按钮PromptInputSubmit。
工具栏能力包括:
PromptInputActionMenu:附件/截图菜单,内含PromptInputActionAddAttachments与PromptInputActionAddScreenshot;PromptInputButton:自定义动作按钮,支持带快捷键提示的 tooltip:
// 简单字符串 tooltip <PromptInputButton tooltip="Search the web"> <GlobeIcon size={16} /> </PromptInputButton> // 带快捷键提示 <PromptInputButton tooltip={{ content: "Search", shortcut: "⌘K" }} /> // 自定义位置 <PromptInputButton tooltip={{ content: "Search", side: "bottom" }} />PromptInputSelect系列:模型下拉(Trigger / Content / Item / Value 全套);- 提交按钮
PromptInputSubmit:根据status(submitted / streaming / error)自动切换图标; - 表单级能力:
onSubmit收到PromptInputMessage(含text与files)、accept/multiple/maxFiles/maxFileSize约束、globalDrop全文档拖拽、syncHiddenInput原生表单隐藏输入同步。
PromptInput还提供状态管理 hooks:
const attachments = usePromptInputAttachments(); attachments.files; // 当前附件数组 attachments.add(files); // 添加文件 attachments.remove(id); // 按 ID 移除 attachments.clear(); // 清空 attachments.openFileDialog(); // 打开文件选择对话框当需要把输入状态提升到组件外部统一控制时,使用可选的PromptInputProvider,配合usePromptInputController/useProviderAttachments/usePromptInputReferencedSources在任意子组件中访问文本输入与附件状态(完整 hooks 与属性表见 prompt-input.md,本地实现见 prompt-input.tsx)。
Tool:工具调用展示
Tool组件专为 AI SDK 的ToolUIPart设计,用可折叠面板展示工具调用的输入、输出、状态与错误:
<Tool defaultOpen={true}> <ToolHeader type="tool-fetch_weather_data" state={weatherTool.state} /> <ToolContent> <ToolInput input={weatherTool.input} /> <ToolOutput output={<MessageResponse>{formatWeatherResult(weatherTool.output)}</MessageResponse>} errorText={weatherTool.errorText} /> </ToolContent> </Tool>ToolHeader:根据state自动渲染状态徽标,getStatusBadge工具函数支持的状态包括input-streaming(Pending)、input-available(Running)、approval-requested(Awaiting Approval)、approval-responded(Responded)、output-available(Completed)、output-error(Error)、output-denied(Denied);ToolInput:以带语法高亮的 JSON 展示参数;ToolOutput:展示执行结果或errorText错误信息,完成/出错状态默认展开以呈现结果;- 类型导出
ToolPart = ToolUIPart | DynamicToolUIPart覆盖静态与动态两种工具 UI 数据。
后端示例使用 AI SDK 的streamText声明带 Zod 参数校验的工具并toUIMessageStreamResponse()流式返回,前端即可无缝渲染(完整示例见 tool.md,本地实现见 tool.tsx)。
Reasoning:流式推理展示
Reasoning组件展示模型的思考过程,流式期间自动展开、结束后自动收起:
<Reasoning className="w-full" isStreaming={isReasoningStreaming}> <ReasoningTrigger /> <ReasoningContent>{reasoningText}</ReasoningContent> </Reasoning>isStreaming:为 true 时自动打开并显示脉冲动画指示器;ReasoningTrigger:自定义思考文案,可通过getThinkingMessage(isStreaming, duration)定制;ReasoningContent:推理文本经 Streamdown 渲染;useReasoning():子组件访问{ isStreaming, isOpen, setIsOpen, duration }上下文。
适用于 Deepseek R1、Claude extended thinking 等以连续块输出思考内容的模型。如果模型输出的是离散、带标签的步骤(如搜索查询、工具调用),官方建议改用 Chain of Thought 组件做结构化展示。后端启用推理流需要显式开启:result.toUIMessageStreamResponse({ sendReasoning: true })。
Attachments / CodeBlock / Terminal:高频场景组件
- Attachments:统一展示图片、视频、音频、文档与来源文件。三种形态
variant="grid"(消息内缩略图网格)、"inline"(输入区紧凑徽标 + 悬停预览)、"list"(带元数据的文件列表)。辅助函数getMediaCategory(data)返回"image" | "video" | "audio" | "document" | "source" | "unknown",getAttachmentLabel(data)返回展示名。删除按钮onRemove回调与AttachmentRemove组件配套(见 attachments.md)。 - CodeBlock:Shiki 语法高亮,可选行号,头部可组合
CodeBlockTitle(图标 + 文件名)与CodeBlockActions(CodeBlockCopyButton,复制成功态默认 2000ms),支持CodeBlockLanguageSelector多语言切换与dark类深色模式。底层CodeBlockContainer使用contentVisibility做渲染性能优化。 - Terminal:流式终端输出,
ansi-to-react解析 ANSI 颜色(256 色、粗体、斜体、下划线),内置流式光标动画、自动滚动、复制与清空按钮(见 terminal.md)。
可扩展性
AI Elements 的设计原则是组件尽可能透传原生属性。例如Message继承HTMLAttributes<HTMLDivElement>,凡是div支持的属性(className、onClick、id、ARIA 属性等)都可以直接传入;Tool透传Collapsible的 props,ConversationScrollButton透传 shadcn/uiButton的 props。这意味着你可以:
- 用
className叠加 Tailwind 类做样式微调; - 用受控 props(如
Reasoning的open/onOpenChange)接管内部状态; - 用
components(MessageResponse)或 render prop(Conversation的children)注入自定义渲染逻辑; - 在组件之上包一层业务组件,组合出符合自己产品的交互。
定制化
安装完成后无需额外配置即可使用——组件的 Tailwind 样式与脚本已随安装集成。若需要改样式,直接编辑组件源码即可。以技能文档中的示例为例:去掉MessageContent的圆角,打开components/ai-elements/message.tsx,移除根元素上的rounded-lg类:
export const MessageContent = ({ children, className, ...props }: MessageContentProps) => ( <div className={cn( "flex flex-col gap-2 text-sm text-foreground", "group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground group-[.is-user]:px-4 group-[.is-user]:py-3", className, )} {...props} > <div className="is-user:dark">{children}</div> </div> );其中cn(...)会把传入的className与内置类合并,Tailwind 的同名类冲突时以传入为准。由于组件就在项目源码中,任何修改即时生效,这是「组件即源码」模型的核心价值。
故障排查(Troubleshooting)
技能文档针对高频问题给出了明确排查路径:
组件没有样式?确认项目已按 shadcn/ui(Tailwind 4)规范配置——globals.css导入了 Tailwind 并包含 shadcn/ui 基础样式。
运行 CLI 后项目没有任何新增文件?逐项检查:
- 当前工作目录是项目根目录(存在
package.json的位置); components.json(shadcn 风格配置)设置正确;- 使用最新版本的 CLI:
npx ai-elements@latest主题切换失效,应用一直停留在浅色模式?确保应用使用 shadcn/ui 与 AI Elements 期望的同一套data-theme系统。默认实现会在<html>元素上切换data-theme属性,同时tailwind.config.js需使用 class 或 data 选择器。
组件导入报 "module not found"?先确认文件确实存在;若存在,检查tsconfig.json是否配置了@/路径别名:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./*"] } } }AI 编程助手无法访问 AI Elements 组件?依次验证:配置文件语法是否为合法 JSON、文件路径是否与 AI 工具配置一致、修改后是否重启了编程助手、网络连接是否稳定。
结语
AI Elements 以「组件即源码」的方式,把 AI 聊天界面中最复杂、最容易做丑的部分(流式 Markdown、工具调用状态、附件管理、吸底滚动、模型选择)封装为开箱即用的可组合组件。在 ZCode 仓库中,这套组件已经完成本地化整合(见 packages/ui/src/components/ai-elements/),并针对中文渲染、ESM 解析、任务切换动画等真实工程问题做了适配改造,是研究其源码实现、学习如何在生产级 AI 工作台中落地 AI 聊天 UI 的最佳参考。无论你是要快速搭一个聊天 Demo,还是要构建完整的 AI 助手产品界面,都可以从本仓库的技能文档(SKILL.md)与其 references 组件文档 出发,按需安装、自由定制。
- 人工智能
- 大模型
- 代码智能体
- AI Agent
- 桌面应用
- 后端
- 前端
- CLI
【免费下载链接】ZCode
ZCode 是 AI 编程工作台,提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI,以及 Agent CLI 与运行时源码。
相关推荐
在 ZCode 中构建 AI 聊天界面:ai-elements Conversation 组件完整指南
在 ZCode 中构建 AI 聊天界面:ai elements Conversation 组件完整指南 Conversation 是 ZCode 仓库内置的 a
人工智能大模型代码智能体AI Agent桌面应用后端前端CLI插件系统ZCode 集成指南:使用 AI Elements Conversation 组件构建自动吸底的 AI 聊天界面
ZCode 集成指南:使用 AI Elements Conversation 组件构建自动吸底的 AI 聊天界面 导读 本指南以 ZCode 仓库内 .agen
ZCode 中构建 AI 聊天界面:AI Elements 组件库安装、组合与深度定制实战指南
ZCode 中构建 AI 聊天界面:AI Elements 组件库安装、组合与深度定制实战指南 本文以 ZCode 仓库内嵌的 ai elements 技能文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考