CopilotKit Chat Slots 深度验证指南:CrewAI 集成下的欢迎页、免责声明与消息气泡定制
2026/9/13 14:33:08 网站建设 项目流程

CopilotKit Chat Slots 深度验证指南:CrewAI 集成下的欢迎页、免责声明与消息气泡定制

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

导读

本文围绕 CopilotKit 的 Chat Slots(插槽覆盖)机制,以 CrewAI (Crews) 集成仓库 中的 chat-slots 演示页为对象,完整梳理 QA 验证的目标、前置条件、测试步骤与预期结果,并结合前端源码、共享辅助函数与 Playwright E2E 用例,讲清 "slot 覆盖为什么能生效"、"slot 路径如何命名" 以及 "如何自动化断言" 三个层面的问题。读完本文,你将掌握 CopilotChat 三大核心插槽——welcomeScreeninput.disclaimermessageView.assistantMessage——的定制方法、标记方式与端到端验证手段。

一、QA 目标:三个 Slot 覆盖必须同时可见

chat-slots演示页的本职工作是验证 CopilotChat 的插槽机制:开发者可以把聊天界面的默认区块替换成自定义 React 组件,且替换必须"端到端"生效——从欢迎屏到输入区再到消息气泡。QA 文档把验收收敛为一条可判定的断言:

  • welcomeScreen(欢迎屏)覆盖可见:默认欢迎页被自定义组件替换;
  • input.disclaimer(输入区免责声明)覆盖可见:输入框下方展示自定义声明文案;
  • messageView.assistantMessage(助手消息气泡)覆盖可见:助手回复被自定义包裹组件渲染。

对应关系可参考 chat-slots QA 文档 以及生产演示页 page.tsx 中的插槽注册代码。

二、前置条件:Demo 已部署且 Agent 后端健康

执行 QA 之前必须满足:

  1. Demo 已部署crewai-crews集成应用处于可访问状态,/demos/chat-slots路由可正常打开;
  2. Agent 后端健康:CrewAI Flow 服务(默认运行在8000端口)已启动且响应正常。

后端的健康状态可以借助 API 路由 暴露的GET /api/copilotkit健康探针确认——它返回agent_urlagent_statusreachable/unreachable),同时透出OPENAI_API_KEY是否已设置。Agent 地址由环境变量AGENT_URL决定,默认http://localhost:8000(见 route.ts)。

值得一提的细节:chat-slots这个 agent 名并没有独立后端,而是被注册映射到中立的 chat Flow 端点/chat(见 route.ts 的 agentNames 列表)。这意味着它不会产生 AG-UI 的 reasoning 事件,也不会夹带 CrewAI crew 默认的系统提示词自述——这正是该演示页能纯粹展示 UI 插槽的前提。

三、测试步骤逐条拆解

QA 文档给出的步骤是:

  1. 打开/demos/chat-slots
  2. 确认自定义欢迎屏可见(data-testid="custom-welcome-screen"),并带有靛蓝渐变卡片与 "Custom Slot" 标签;
  3. 确认 "Write a sonnet" 与 "Tell me a joke" 两个建议词可见;
  4. 点击 "Write a sonnet"(或直接发送消息);
  5. 确认助手回复被自定义消息卡片包裹(data-testid="custom-assistant-message"),带靛蓝边框与 "slot" 徽标;
  6. 确认输入框下方出现自定义免责声明(data-testid="custom-disclaimer")。

3.1 欢迎屏:WelcomeScreen与嵌套WelcomeMessage子插槽

欢迎屏是展示插槽嵌套能力的典型区域。在 slot-wrappers.tsx 中,CustomWelcomeScreen接收inputsuggestionView两个 ReactElement,自行排列布局,并在内部又嵌入了CustomWelcomeMessage子插槽。QA 步骤中"靛蓝渐变卡片 + Custom Slot 标签"指的就是这一层SlotMarker(indigo 色、虚线边框、可点击的 slot 路径徽标)包裹出的视觉效果。

从源码看,欢迎屏同时暴露了两个data-testid:外层custom-welcome-screen、内层custom-welcome-message。E2E 用例刻意同时断言这两者,正是为了防止意外回退到默认欢迎页——详见 chat-slots.spec.ts。

3.2 建议词:由useConfigureSuggestions驱动

"Write a sonnet" 与 "Tell me a joke" 并非写死在 JSX 里,而是通过 suggestions.ts 中的useConfigureSuggestions钩子注册:

useConfigureSuggestions({ suggestions: [ { title: "Write a sonnet", message: "Write a short sonnet about AI." }, { title: "Tell me a joke", message: "Tell me a short joke." }, ], available: "always", });

available: "always"意味着两个建议词在欢迎屏上立即可见(E2E 用copilot-suggestion这个 testid 过滤文本后断言可见,超时 15 秒)。点击建议词实际发送的是message字段对应的完整消息,例如 "Tell me a short joke."。

3.3 助手消息:MessageView.AssistantMessage插槽包裹

助手回复气泡由CustomAssistantMessage包裹默认的CopilotChatAssistantMessage,并在外层套上 emerald 色的SlotMarker,其data-slot-label="MessageView.AssistantMessage"属性是判断插槽是否真正生效的权威信号(见 spec.ts 顶部注释)。QA 步骤里"靛蓝边框 + slot 徽标"对应的是该 Marker 的视觉形态。

3.4 免责声明:Input.Disclaimer插槽

免责声明属于input插槽族,注册方式为input.disclaimer(见 page.tsx)。它在欢迎屏状态下是隐藏的,只有用户发送首条消息、进入聊天态后才可见——E2E 用例对此有专门断言(见 spec.ts)。

四、插槽机制源码深挖:从注册到标记

4.1makeSlotOverride:集中化的类型断言

插槽 prop 的类型是"名义类型"(nominally typed)——它要求组件与默认组件完全同构。而一个结构上兼容的自定义包装组件虽然在运行时完全可用,却过不了 TypeScript 的类型检查。为此项目提供了共享助手 slot-override.ts:

export function makeSlotOverride<TDefault>( component: ComponentType<any>, ): TDefault { return component as unknown as TDefault; }

它把as unknown as断言集中到一处,让读者一眼看出"这是在满足插槽契约",而非散落的类型体操。演示页正是通过它注册欢迎屏、文本域、发送按钮、免责声明等十余个插槽(见 page.tsx)。

提示:教学向的最小示例(欢迎屏 / 助手消息 / 免责声明三件套)单独整理在 slot-overrides.snippet.tsx 中,该文件仅供文档展示、不参与运行,适合快速对照理解插槽注册的最小形态。

4.2SlotMarker:可复用的插槽可视化外壳

slot-marker.tsx 是整页演示的视觉核心:它为每个插槽渲染虚线边框、配色徽标和可点击复制的 slot 路径按钮。几个关键实现点:

  • data-slot-label属性:渲染在 Marker 外层 span 上,是 E2E 判定插槽是否接线的规范信号;
  • 静态类名查找表SLOT_COLORS:由于 Tailwind v4 在构建期扫描源码,动态拼接border-${color}-400会失效,所以颜色表用完整的静态 class 字符串硬编码;
  • 嵌套隔离:Marker 之间会嵌套(欢迎屏包着 input 与 suggestionView),普通:hover会点亮所有层级的标签,因此 CSS 借助:not(:has(.slot-marker:hover))谓词确保只高亮最内层被悬停的 Marker;
  • 一键复制:点击徽标可把WelcomeScreenMessageView.AssistantMessage这类 slot 路径写入剪贴板,方便开发者把路径带进自己的代码。

4.3 input 插槽族与toolsMenu的联动

演示页给input同时塞入插槽覆盖与普通 props(见 page.tsx):除textAreasendButtondisclaimeraddMenuButton四个插槽外,还传了toolsMenu: [{ label: "Demo tool (no-op)", action: () => {} }]。这样做的意义是:Input.AddMenuButton插槽只有在设置了onAddFiletoolsMenu时才会渲染(见 slot-wrappers.tsx 中的注释),种子化的toolsMenu让这个插槽有了出现的理由。

4.4 完整的插槽全景

如果把演示页所有插槽按路径列出,便得到一张"插槽地图":

插槽路径对应区块Marker 配色
WelcomeScreen欢迎屏整体indigo
WelcomeScreen.WelcomeMessage欢迎屏内嵌标语violet
Input.TextArea输入文本框orange
Input.SendButton发送按钮red
Input.Disclaimer输入区下方免责声明yellow
Input.AddMenuButton添加菜单按钮pink
MessageView.AssistantMessage助手消息气泡emerald
MessageView.UserMessage用户消息气泡sky
MessageView.ReasoningMessage推理过程消息rose
MessageView.Cursor流式输出中的光标amber
SuggestionView.Container建议词容器cyan
SuggestionView.Suggestion单个建议词teal
ScrollView.ScrollToBottomButton回到底部按钮lime
ScrollView.Feather输入区上方渐隐遮罩fuchsia

其中MessageView.ReasoningMessage属于"挂载但不活跃"的插槽:chat-slots连的是不带 reasoning 配置的中立 Flow,永远不产生 AG-UIREASONING_MESSAGE_*事件,因此该插槽只为演示 Atlas 存在。需要看推理插槽真正点亮的效果,应访问/demos/reasoning-default/demos/reasoning-custom(此说明来自 suggestions.ts 的注释)。

五、Playwright E2E:把 QA 步骤固化为自动化断言

QA 文档的每条人工步骤都能在 tests/e2e/chat-slots.spec.ts 中找到对应的自动化用例:

  1. 首次加载渲染自定义欢迎屏:断言custom-welcome-screen与其嵌套的custom-welcome-message同时可见——双断言防止回退到默认欢迎页;
  2. 两个建议词逐字渲染:用copilot-suggestion过滤 "Write a sonnet" / "Tell me a joke",各给 15 秒超时;
  3. 点击建议词后助手消息插槽生效:点击 "Tell me a joke" 后等待MessageView.AssistantMessage的 slot-marker 出现(45 秒超时,覆盖流式首块到达时间);
  4. 发送首条消息后免责声明可见:通过copilot-send-button显式点击发送(注释说明 Enter 提交在此部署上偶发丢失),随后断言custom-disclaimer可见;
  5. 第二轮对话仍被插槽包裹:用expect.poll等待第一轮文本流稳定(2 秒无新增内容视为完成),再发第二句,断言MessageView.AssistantMessage的计数 ≥ 2,证明插槽作用于每一轮而非仅首条。

其中 "poll 等待流稳定" 的技巧值得借鉴:assistant 气泡在首个 chunk 到达时即可见,但输入区要到整个流结束后才退出 responding 状态,因此直接断言"第二条消息可见"容易产生竞态,先等文本稳定再发第二轮是稳妥做法(见 spec.ts)。

六、预期结果与验收判定

QA 文档的最终判定标准只有一个:三个插槽覆盖全部可见——welcomeScreeninput.disclaimermessageView.assistantMessage

从工程实践角度,可以再补两条隐性的判定参考:

  • 运行时信号[data-slot-label="MessageView.AssistantMessage"]出现在 DOM 中,说明覆盖真正接线而非回退默认渲染;
  • 失败模式:若欢迎屏断言通过但助手气泡是裸的默认样式,多半是插槽 prop 未正确传入或类型断言把组件注册成了错误的插槽路径;若免责声明不出现,先检查是否仍停留在欢迎屏状态。

七、快速上手:如何在你的页面里复刻这套插槽

  1. 引入 V2 组件:从@copilotkit/react-core/v2导入CopilotKitCopilotChat及其子组件(CopilotChatViewCopilotChatInputCopilotChatAssistantMessage等);
  2. 编写包装组件:用SlotMarker(或你自己的外壳)包裹默认组件,透传全部 props;
  3. makeSlotOverride注册:把包装组件断言为对应插槽的类型;
  4. 组装 propswelcomeScreeninputmessageViewsuggestionViewscrollView五个插槽组按需覆盖;
  5. 接上后端<CopilotKit runtimeUrl="/api/copilotkit" agent="chat-slots">,并由 runtime 路由把 agent 名映射到你的 AG-UI 端点;
  6. 自动化验证:参照 E2E 用例,用data-testiddata-slot-label双通道断言,防止回退到默认 UI。

需要注意的前置约束:插槽覆盖作用于CopilotChat组件树,需要配套 V2 版本依赖与健康的 agent 后端(GET /api/copilotkit返回agent_status: "reachable")。完整可运行示例以 chat-slots 演示页 与 slot-wrappers.tsx 为准。

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询