
人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载导读PromptInput是 ZCode 仓库内置的 AI Elements 组件体系中用于消息输入的核心组件它把「文本输入、文件上传、截图抓取、模型选择、提交按钮」整合进一个自管理的表单容器可直接与 AI SDK 的useChat配合构建完整聊天应用。本文将完整讲解PromptInput的安装方式、AI SDK 前后端集成示例、全部子组件与 Props、四个 Hooks 的用法并结合仓库内的真实源码实现packages/ui/src/components/ai-elements/prompt-input.tsx说明其底层工作原理帮助你在 ZCode 及其衍生项目中快速落地一个功能完整的 AI 对话输入框。PromptInput 是什么PromptInput允许用户向大语言模型发送带有文件附件attachments的消息。它由一个 textarea、文件上传能力、一个提交按钮以及一个用于选择模型的 dropdown 组合而成。在 AI Elements 技能文档 中PromptInput被定位为构建 AI 聊天界面chatbot、AI 助手 UI时的核心输入组件常与Conversation、Message等组件搭配使用。在仓库中PromptInput的完整 React 实现位于 packages/ui/src/components/ai-elements/prompt-input.tsx共 753 行并拆分出若干辅助模块packages/ui/src/components/ai-elements/prompt-input-primitives.tsx基础原语packages/ui/src/components/ai-elements/prompt-input-textarea.tsxtextarea 实现packages/ui/src/components/ai-elements/prompt-input-buttons.tsx按钮实现packages/ui/src/components/ai-elements/prompt-input-actions.tsx动作菜单实现从源码结构可以推断PromptInput通过createContext提供PromptInputController与ProviderAttachmentsContext两个上下文把文本输入与附件状态提升为可共享的全局状态任何包裹在PromptInputProvider内的组件都能读写输入状态详见下文「Hooks」一节。附件Attachment、AttachmentPreview、AttachmentRemove、Attachments则被独立拆分到单独模块见 附件组件文档。安装与 AI Elements 的其他组件一致PromptInput通过 CLI 以源码形式非隐藏库安装到你的项目组件目录默认/components/ai-elements/npx ai-elementslatest add prompt-input注意应根据项目声明的packageManager使用对应的包管理器运行器例如pnpm dlx ai-elementslatest或bunx --bun ai-elementslatest。如果项目尚未安装 shadcn/ui安装命令会自动将其一并安装。安装完成后组件代码会落到项目的components/ai-elements/prompt-input.tsx等文件中你可以像对待自己写的代码一样直接打开修改样式与逻辑这正是 AI Elements 的设计理念组件即源码可任意定制。与 AI SDK 集成构建完整聊天应用文档给出了一个端到端示例用PromptInputConversation 模型选择器搭建一个支持附件、Web 搜索开关、流式响应的聊天界面。前端组件app/page.tsxuse client; import { Attachment, AttachmentPreview, AttachmentRemove, Attachments, } from /components/ai-elements/attachments; import { PromptInput, PromptInputActionAddAttachments, PromptInputActionAddScreenshot, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuTrigger, PromptInputBody, PromptInputButton, PromptInputHeader, type PromptInputMessage, PromptInputSelect, PromptInputSelectContent, PromptInputSelectItem, PromptInputSelectTrigger, PromptInputSelectValue, PromptInputSubmit, PromptInputTextarea, PromptInputFooter, PromptInputTools, usePromptInputAttachments, } from /components/ai-elements/prompt-input; import { GlobeIcon } from lucide-react; import { useState } from react; import { useChat } from ai-sdk/react; import { Conversation, ConversationContent, ConversationScrollButton, } from /components/ai-elements/conversation; import { Message, MessageContent, MessageResponse } from /components/ai-elements/message; const PromptInputAttachmentsDisplay () { const attachments usePromptInputAttachments(); if (attachments.files.length 0) { return null; } return ( Attachments variantinline {attachments.files.map((attachment) ( Attachment data{attachment} key{attachment.id} onRemove{() attachments.remove(attachment.id)} AttachmentPreview / AttachmentRemove / /Attachment ))} /Attachments ); }; const models [ { id: gpt-4o, name: GPT-4o }, { id: claude-opus-4-20250514, name: Claude 4 Opus }, ]; const InputDemo () { const [text, setText] useStatestring(); const [model, setModel] useStatestring(models[0].id); const [useWebSearch, setUseWebSearch] useStateboolean(false); const { messages, status, sendMessage } useChat(); const handleSubmit (message: PromptInputMessage) { const hasText Boolean(message.text); const hasAttachments Boolean(message.files?.length); if (!(hasText || hasAttachments)) { return; } sendMessage( { text: message.text || Sent with attachments, files: message.files, }, { body: { model: model, webSearch: useWebSearch, }, }, ); setText(); }; return ( div classNamemax-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px] div classNameflex flex-col h-full Conversation ConversationContent {messages.map((message) ( Message from{message.role} key{message.id} MessageContent {message.parts.map((part, i) { switch (part.type) { case text: return ( MessageResponse key{${message.id}-${i}}{part.text}/MessageResponse ); default: return null; } })} /MessageContent /Message ))} /ConversationContent ConversationScrollButton / /Conversation PromptInput onSubmit{handleSubmit} classNamemt-4 globalDrop multiple PromptInputHeader PromptInputAttachmentsDisplay / /PromptInputHeader PromptInputBody PromptInputTextarea onChange{(e) setText(e.target.value)} value{text} / /PromptInputBody PromptInputFooter PromptInputTools PromptInputActionMenu PromptInputActionMenuTrigger / PromptInputActionMenuContent PromptInputActionAddAttachments / PromptInputActionAddScreenshot / /PromptInputActionMenuContent /PromptInputActionMenu PromptInputButton onClick{() setUseWebSearch(!useWebSearch)} tooltip{{ content: Search the web, shortcut: ⌘K }} variant{useWebSearch ? default : ghost} GlobeIcon size{16} / spanSearch/span /PromptInputButton PromptInputSelect onValueChange{(value) { setModel(value); }} value{model} PromptInputSelectTrigger PromptInputSelectValue / /PromptInputSelectTrigger PromptInputSelectContent {models.map((model) ( PromptInputSelectItem key{model.id} value{model.id} {model.name} /PromptInputSelectItem ))} /PromptInputSelectContent /PromptInputSelect /PromptInputTools PromptInputSubmit disabled{!text !status} status{status} / /PromptInputFooter /PromptInput /div /div ); }; export default InputDemo;示例中的关键模式组合式结构PromptInput按Header附件展示区→Bodytextarea→Footer工具栏 提交按钮三明治式组织子组件层级清晰。附件读取usePromptInputAttachments()从上下文读取当前附件列表为空时直接渲染null避免出现空附件条。模型选择PromptInputSelect系列Trigger/Value/Content/Item是内置于输入框的工具下拉切换时更新本地model状态并在提交时通过body透传给后端。提交语义onSubmit接收的PromptInputMessage统一携带text与files空消息既无文本也无附件会被直接拦截。状态驱动提交按钮PromptInputSubmit接收status来自useChat按钮图标会随submitted / streaming / error等状态自动切换。后端路由app/api/chat/route.tsimport { streamText, UIMessage, convertToModelMessages } from ai; // Allow streaming responses up to 30 seconds export const maxDuration 30; export async function POST(req: Request) { const { model, messages, webSearch, }: { messages: UIMessage[]; model: string; webSearch?: boolean; } await req.json(); const result streamText({ model: webSearch ? perplexity/sonar : model, messages: await convertToModelMessages(messages), }); return result.toUIMessageStreamResponse(); }后端要点convertToModelMessages把前端 UI 消息含附件 part转换为模型消息格式webSearch为真时切换为perplexity/sonar模型从而把「Web 搜索开关」下沉到服务端路由maxDuration 30允许流式响应最长 30 秒。前端示例代码可在仓库中直接查看scripts/prompt-input.tsx。功能特性一览PromptInput内置的完整能力清单如下自动调整高度的 textarea随内容增长支持拖拽的文件附件上传内置截图抓取动作screenshot capture图片附件的预览能力可配置的文件约束最大文件数、最大大小、可接受类型根据状态自动切换图标的提交按钮键盘快捷键支持Enter 提交、ShiftEnter 换行textarea 最小/最大高度可自定义灵活工具栏支持自定义动作与工具内置模型选择下拉内置原生语音识别按钮Web Speech API可选 Provider用于把状态提升到组件外部管理表单提交后自动重置移动端友好的响应式设计干净、现代、主题可自定义的样式基于表单的提交处理隐藏文件输入同步hidden file input sync支持原生表单提交全局文档拖放支持opt-in通过globalDrop开启其中「隐藏文件输入同步」对应PromptInput /的syncHiddenInputprop渲染一个带指定name的隐藏input使PromptInput可以被嵌入传统 HTML 表单进行原生 post「全局拖放」对应globalDrop开启后在整个 document 上接受文件拖放而不局限于输入框区域。进阶示例Cursor 风格scripts/prompt-input-cursor.tsx仓库提供了一个仿 Cursor 的复杂输入栏示例见 scripts/prompt-input-cursor.tsx。它展示了PromptInput的高度可扩展性用PromptInputHoverCard/Trigger/Content实现「 引用文件、项目规则、标签页」等悬停面板用PromptInputCommand系列实现「Add files, folders, docs...」的斜杠命令式文件选择用PromptInputTab系列展示 Active Tabs / Recents 两个标签组用usePromptInputReferencedSources()展示引用来源source documents的添加与移除用ModelSelector来自 模型选择器文档替代简单的PromptInputSelect提供带厂商 Logo、可搜索的模型选择。按钮 Tooltipscripts/prompt-input-tooltip.tsx工具栏按钮可显示带可选键盘快捷键提示的 tooltip见 scripts/prompt-input-tooltip.tsx// 简单字符串 tooltip PromptInputButton tooltipAttach files PaperclipIcon size{16} / /PromptInputButton // 带键盘快捷键提示的 tooltip PromptInputButton tooltip{{ content: Search the web, shortcut: ⌘K }} GlobeIcon size{16} / /PromptInputButton // 自定义弹出位置 PromptInputButton tooltip{{ content: Voice input, shortcut: ⌘M, side: bottom }} MicIcon size{16} / /PromptInputButtontooltip支持字符串与对象两种形态对象可包含content内容、shortcut快捷键提示文本与side弹出方向。完整的 tooltip 示例代码见上文 PromptInputButton Props 小节下方的演示。组件与 Props 完整参考PromptInput /表单容器根组件负责管理 textarea、附件、文件校验与提交。Prop类型默认值说明onSubmit(message: PromptInputMessage, event: FormEvent) void-表单提交时回调携带消息文本与文件acceptstring-可接受的文件类型如image/*multipleboolean-是否允许多文件选择globalDropboolean-为 true 时接受 document 任意位置的文件拖放syncHiddenInputboolean-渲染带指定 name 的隐藏 input用于原生表单提交maxFilesnumber-允许的最大文件数maxFileSizenumber-最大文件大小字节onError(err: { code: ... }) void-文件校验错误处理器...propsReact.HTMLAttributesHTMLFormElement-其余 props 透传到根 form 元素从 源码实现 可以看到附件经convertBlobUrlToDataUrl转换为 Data URL 后再进入提交链路文件校验错误数量、大小、类型由onError统一上报供上层做 toast 等提示。PromptInputTextarea /PromptInputTextarea placeholderPlan, search, build anything /Prop类型默认值说明...propsReact.ComponentPropstypeof Textarea-其余 props 透传到底层 Textarea 组件textarea 实现见 prompt-input-textarea.tsx支持内容驱动的自动高度调整、最小/最大高度约束以及 Enter 提交、ShiftEnter 换行的快捷键逻辑。布局容器Header/Body/Footer/ToolsPromptInputHeader /|...props|OmitReact.ComponentPropstypeof InputGroupAddon, align| - | 其余 props除 align透传到 InputGroupAddon 组件 |。用于放置附件展示、悬停面板等头部内容。PromptInputBody /|...props|React.HTMLAttributesHTMLDivElement| - | 其余 props 透传到 body div |。包裹 textarea。PromptInputFooter /|...props|React.HTMLAttributesHTMLDivElement| - | 其余 props 透传到工具栏 div |。承载工具栏与提交按钮。PromptInputTools /|...props|React.HTMLAttributesHTMLDivElement| - | 其余 props 透传到 tools div |。工具栏按钮组容器。PromptInputButton /Prop类型默认值说明tooltipstring \| { content: ReactNode; shortcut?: string; side?: ... }-悬停 tooltip可为字符串或含 content/shortcut/side 的对象...propsReact.ComponentPropstypeof Button-其余 props 透传到底层 shadcn/ui ButtonTooltip 示例// 简单字符串 tooltip PromptInputButton tooltipSearch the web GlobeIcon size{16} / /PromptInputButton // 带键盘快捷键提示 PromptInputButton tooltip{{ content: Search, shortcut: ⌘K }} GlobeIcon size{16} / /PromptInputButton // 自定义位置 PromptInputButton tooltip{{ content: Search, side: bottom }} GlobeIcon size{16} / /PromptInputButtonPromptInputSubmit /Prop类型默认值说明statusChatStatus-当前聊天状态决定按钮图标submitted、streaming、error 等...propsReact.ComponentPropstypeof Button-其余 props 透传到底层 shadcn/ui Button模型选择Select系列组件透传的底层组件说明PromptInputSelect /Select模型选择下拉根组件PromptInputSelectTrigger /SelectTrigger触发按钮PromptInputSelectContent /SelectContent下拉内容面板PromptInputSelectItem /SelectItem单个模型项value为模型 idPromptInputSelectValue /SelectValue当前选中值展示动作菜单ActionMenu系列组件透传的底层组件说明PromptInputActionMenu /DropdownMenu动作菜单根PromptInputActionMenuTrigger /Button菜单触发按钮如「」PromptInputActionMenuContent /DropdownMenuContent菜单内容面板PromptInputActionMenuItem /DropdownMenuItem菜单项PromptInputActionAddAttachments /DropdownMenuItem另有label?: string添加附件的菜单项PromptInputActionAddScreenshot /DropdownMenuItem另有label?: string截图抓取的菜单项悬停面板HoverCard系列组件Prop说明PromptInputHoverCard /openDelay: number默认0、closeDelay: number默认0其余透传HoverCard悬停卡片容器毫秒级开关延迟PromptInputHoverCardTrigger /透传HoverCardTrigger触发元素PromptInputHoverCardContent /align: unknown其余透传HoverCardContent卡片内容标签组Tab系列组件透传目标说明PromptInputTabsList /div标签列表容器PromptInputTab /div单个标签页PromptInputTabLabel /h3标签标题如 Active TabsPromptInputTabBody /div标签内容主体PromptInputTabItem /div标签内条目如文件路径行命令面板Command系列组件透传目标说明PromptInputCommand /Command命令面板根用于文件/文档搜索PromptInputCommandInput /CommandInput命令搜索输入框PromptInputCommandList /CommandList命令结果列表PromptInputCommandEmpty /CommandEmpty空结果提示PromptInputCommandGroup /CommandGroup结果分组如 Added、Other FilesPromptInputCommandItem /CommandItem单个结果项PromptInputCommandSeparator /CommandSeparator分组分隔线PromptInputProvider /Prop类型默认值说明initialInputstring-初始文本输入值childrenReact.ReactNode-可访问 Provider 上下文的子组件可选的全局 Provider把 PromptInput 的状态提升到组件外部。使用后你可以在 Provider 树内的任意位置访问并控制输入状态文本与附件不使用它时PromptInput完全自管理。这一设计与源码中的PromptInputController/ProviderAttachmentsContext上下文一一对应见 prompt-input.tsx同时支持通过__registerFileInput把隐藏文件输入注册到 Provider 以便外部触发文件对话框。HooksusePromptInputAttachments在 PromptInput 上下文中访问和管理文件附件const attachments usePromptInputAttachments(); // 可用方法 attachments.files; // 当前附件数组FileUIPart { id }[] attachments.add(files); // 添加新文件File[] 或 FileList attachments.remove(id); // 按 ID 移除附件 attachments.clear(); // 清空全部附件 attachments.openFileDialog(); // 打开文件选择对话框源码中AttachmentsContext的完整类型定义含fileInputRef可在 prompt-input.tsx 查看。usePromptInputController从PromptInputProvider获取完整的 PromptInput 控制器仅在使用了 Provider 时可用const controller usePromptInputController(); // 可用方法 controller.textInput.value; // 当前文本输入值 controller.textInput.setInput(v); // 设置文本输入值 controller.textInput.clear(); // 清空文本输入 controller.attachments; // 与 usePromptInputAttachments 相同若在未包裹PromptInputProvider时调用源码会抛出明确的错误提示Wrap your component inside PromptInputProvider to use usePromptInputController().。useProviderAttachments从PromptInputProvider访问附件上下文仅在使用了 Provider 时可用const attachments useProviderAttachments(); // 接口与 usePromptInputAttachments 完全一致usePromptInputReferencedSources访问 PromptInput 内的引用来源referenced sources上下文——即用户在输入框中引用的文档/文件来源可用于「 引用文件」类交互const sources usePromptInputReferencedSources(); // 可用方法 sources.sources; // 当前引用来源数组SourceDocumentUIPart 等 sources.add(sources); // 添加新来源 sources.remove(id); // 按 ID 移除来源 sources.clear(); // 清空全部来源该 Hook 在 Cursor 风格示例 中与PromptInputCommand面板配合实现了「Add files, folders, docs...」的引用来源管理与去重过滤通过title filename判断是否已添加。关联模块与延伸阅读附件展示组件Attachments/Attachment/AttachmentPreview/AttachmentInfo/AttachmentRemove见 附件组件文档支持 grid / inline / list 三种布局以及getMediaCategory、getAttachmentLabel两个工具函数。会话容器组件Conversation见 会话组件文档负责消息包裹与自动滚动到底部。消息展示组件Message见 消息组件文档配合MessageContent/MessageResponse渲染文本与各类型 part。模型选择器ModelSelector见 模型选择器文档提供带厂商 Logo、可搜索的模型选择体验。组件库总览与排障见 SKILL.md包含组件未安装、主题切换失败、/路径别名缺失等常见问题的排查步骤。注意事项与前提PromptInput组件及示例代码在仓库中源自 vercel/ai-elements遵循 Apache-2.0 许可并在仓库根目录的 THIRD-PARTY-NOTICES.md 中注明来源与许可信息。文中scripts/下的.tsx示例是技能目录中的组件示例文件相对技能目录而非仓库根目录的脚本它们用于演示组件用法并不是已安装的应用功能。使用PromptInput需要 Node.js 18、Next.js 项目且已安装 AI SDK若项目已使用 shadcn/ui安装会更顺畅。上述 props 表格中的默认值如openDelay、closeDelay为0以仓库内文档为准实际渲染效果请以安装后组件源码为准因为 AI Elements 的组件以源码形式进入你的项目你可以直接查看与修改。赞分享人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载相关推荐Comp AI CRM 前端工程中的 ai-elements PromptInput 组件构建带附件、模型选择与语音输入的 AI 聊天输入框Comp AI CRM 前端工程中的 ai elements PromptInput 组件构建带附件、模型选择与语音输入的 AI 聊天输入框 PromptIn后端前端CRM人工智能AI AgentZCode 中的 PromptInput 组件基于 ai-elements 构建 AI 聊天输入框的完整指南ZCode 中的 PromptInput 组件基于 ai elements 构建 AI 聊天输入框的完整指南 PromptInput 是 ai element在 ZCode 中构建 AI 模型选择器ModelSelector 命令面板组件完全指南在 ZCode 中构建 AI 模型选择器ModelSelector 命令面板组件完全指南 ModelSelector 是一个基于 cmdk 构建的可搜索 AI人工智能大模型代码智能体AI Agent桌面应用后端前端CLI插件系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考