@bdky/chat-pilot-kit-react
v1.0.5
Published
chat-pilot-kit 的 React 封装,提供 Provider、Context、Hooks 和 ReactNodeViewRenderer
Downloads
318
Readme
@bdky/chat-pilot-kit-react
English | 简体中文
@bdky/chat-pilot-kit的 React 适配层,提供 Provider、Hooks、NodeView 组件和国际化支持,用于构建 AI 聊天界面。
✨ 特性
- 🎯 开箱即用的 NodeView — 8 种内置节点渲染组件(文本、Markdown、思考块、工具调用、图片、文件、音频、视频)
- 🪝 React Hooks —
useConversations、useChatPilotKitEvents、useNodeInteraction等 - 🎨 高度可定制 — 通过
className、style、slots对内置组件进行二次扩展,无需完全替换 - 🌍 国际化 — 内置中英文,支持自定义翻译
- 🎨 主题系统 — CSS 自定义属性,支持亮色/暗色模式及
data-theme切换 - 📘 完整 TypeScript 支持 — 开箱即用的完整类型定义
📦 安装
# npm
npm install @bdky/chat-pilot-kit-react @bdky/chat-pilot-kit
# yarn
yarn add @bdky/chat-pilot-kit-react @bdky/chat-pilot-kit对等依赖: React ≥ 16.8
🚀 快速开始
import {createChatPilotKit, BaseAgentService} from '@bdky/chat-pilot-kit';
import {
ChatPilotKitProvider,
useConversations,
useChatPilotKit,
NodeRenderer,
getDefaultReactExtensions,
} from '@bdky/chat-pilot-kit-react';
import '@bdky/chat-pilot-kit-react/styles.css';
// 1. 实现你的 AgentService
class MyAgentService extends BaseAgentService {
async query(text: string): Promise<void> {
// 调用 AI 后端并流式返回数据
this.onData({answer: 'Hello!', nodeType: 'markdown', queryId: this.queryId(), sessionId: this.sessionId()});
this.onCompleted();
}
dispose(): void {}
}
// 2. 创建 Controller
const controller = createChatPilotKit({
agentService: MyAgentService,
extensions: getDefaultReactExtensions(),
});
// 3. 包裹应用
export default function App() {
return (
<ChatPilotKitProvider controller={controller}>
<Chat />
</ChatPilotKitProvider>
);
}
// 4. 构建聊天 UI
function Chat() {
const {controller} = useChatPilotKit();
const conversations = useConversations();
return (
<div>
{conversations.map(conv =>
conv.nodes.map(node => (
<NodeRenderer
key={node.id}
node={node}
conversation={conv.bean}
/>
))
)}
<button onClick={() => controller.query('你好')}>发送</button>
</div>
);
}🎨 样式
在应用入口处引入一次内置 CSS:
import '@bdky/chat-pilot-kit-react/styles.css';📖 API 参考
ChatPilotKitProvider
Context Provider,将 Controller 注入到所有子组件。
<ChatPilotKitProvider controller={controller}>
{children}
</ChatPilotKitProvider>| Prop | 类型 | 说明 |
|------|------|------|
| controller | ChatPilotKitController | 由 createChatPilotKit() 创建的控制器 |
| children | ReactNode | — |
Hooks
useChatPilotKit()
从 Context 中获取 Controller。若在 ChatPilotKitProvider 外部调用会抛出错误。
const {controller} = useChatPilotKit();
await controller.query('你好');
await controller.queryWithAttachments('分析这个文件', attachments);
controller.interrupt();
controller.clear();
controller.importConversations(inputs, {position: 'prepend'});
const snapshots = controller.exportConversations();useConversations()
返回响应式的对话列表,自动与 Controller 状态同步。
const conversations = useConversations();
// conversations: IConversationItem[]
// 每项包含: { conversationId, role, nodes, completed, bean }useChatPilotKitEvents(props)
订阅 Controller 生命周期事件,所有回调均为可选。
useChatPilotKitEvents({
onReady: () => {},
onConversationAdd: (payload) => {},
onConversationChange: (payload) => {
if (payload.completed && payload.role === 'aiWorker') {
setLoading(false);
}
},
onNodeAdd: (payload) => {},
onNodeUpdate: (payload) => {},
onError: (payload) => { console.error(payload); },
onInterrupt: () => {},
onClear: () => {},
onTtft: (payload) => {},
onHistoryImport: (payload) => {},
onNodeInteraction: (payload) => {},
});useNodeInteraction(props)
与 NodeView 组件进行双向通信——监听交互事件并向节点发送命令。
const {sendCommand} = useNodeInteraction({
filter: 'click', // string | string[] | (type: string) => boolean
onInteraction: (payload) => {
console.log(payload.type, payload.data, payload.nodeId);
},
});
// 向指定节点发送命令
sendCommand(nodeId, 'highlight', {color: 'yellow'});NodeView 系统
NodeView 是渲染单个对话节点的 React 组件。SDK 内置 8 种 NodeView,并提供自定义注册机制。
NodeRenderer
使用节点注册的 NodeView 渲染单个 ConversationNode。
<NodeRenderer node={node} conversation={conv.bean} />内置 Extensions
一次性注册所有内置 NodeView:
import {getDefaultReactExtensions} from '@bdky/chat-pilot-kit-react';
const controller = createChatPilotKit({
extensions: getDefaultReactExtensions(),
});也可以单独注册:
import {
ReactTextExtension,
ReactMarkdownExtension,
ReactThinkingBlockExtension,
ReactToolCallExtension,
ReactImageExtension,
ReactFileExtension,
ReactAudioExtension,
ReactVideoExtension,
} from '@bdky/chat-pilot-kit-react';自定义 NodeView
替换内置 NodeView 或注册全新的节点类型:
import {
ReactMarkdownExtension,
ReactNodeViewRenderer,
MarkdownNodeView,
} from '@bdky/chat-pilot-kit-react';
import type {NodeViewProps, MarkdownNode} from '@bdky/chat-pilot-kit';
import type {FC} from 'react';
// 包装内置 NodeView,注入自定义 props
const MyMarkdown: FC<NodeViewProps<MarkdownNode>> = (props) => (
<MarkdownNodeView {...props} className="my-markdown" />
);
// 或完全自定义
const CustomMarkdown: FC<NodeViewProps<MarkdownNode>> = ({node}) => (
<div className="custom">{node.content}</div>
);
const MyMarkdownExtension = ReactMarkdownExtension.extend({
addNodeView() {
return ReactNodeViewRenderer(MyMarkdown);
}
});NodeView 扩展 Props
所有内置 NodeView 组件均支持可选的扩展 props,无需完全替换组件即可进行二次定制。
通用 Props(所有 NodeView 均支持)
| Prop | 类型 | 说明 |
|------|------|------|
| className | string | 追加到根元素,与内置 BEM 类名共存 |
| style | CSSProperties | 合并到根元素的内联样式 |
| dataAttributes | Record<\data-${string}`, string | number | boolean>| 透传到根元素的data-*` 属性 |
ThinkingBlockNodeView
<ThinkingBlockNodeView
{...props}
defaultOpen={false}
slots={{
icon: <MyIcon />,
label: <span>思考中...</span>,
content: (text) => <pre className="custom-pre">{text}</pre>,
}}
/>| Prop | 类型 | 默认值 |
|------|------|--------|
| defaultOpen | boolean | true |
| slots.icon | ReactNode | 内置灯泡 SVG |
| slots.label | ReactNode | i18n 标签 |
| slots.content | (text: string) => ReactNode | <pre> 块 |
ToolCallNodeView
<ToolCallNodeView
{...props}
defaultOpen={true}
slots={{
icon: <TerminalIcon />,
badge: (status, label) => <MyBadge status={status}>{label}</MyBadge>,
argsContent: (args) => <JsonViewer data={args} />,
resultContent: (result) => <JsonViewer data={result} />,
errorContent: (error) => <Alert type="error">{error}</Alert>,
}}
/>| Prop | 类型 | 默认值 |
|------|------|--------|
| defaultOpen | boolean | false |
| slots.icon | ReactNode | 内置终端 SVG |
| slots.badge | (status: ToolCallStatus, label: string) => ReactNode | 内置 badge |
| slots.argsContent | (args: unknown) => ReactNode | JSON <pre> |
| slots.resultContent | (result: unknown) => ReactNode | JSON <pre> |
| slots.errorContent | (error: string) => ReactNode | 错误 <div> |
ImageNodeView
| Prop | 类型 |
|------|------|
| slots.image | (props: {src, alt, width?, height?}) => ReactNode |
| slots.caption | (alt: string) => ReactNode |
FileNodeView
| Prop | 类型 |
|------|------|
| slots.icon | (fileType: string) => ReactNode |
| slots.downloadIcon | ReactNode |
AudioNodeView
| Prop | 类型 | 说明 |
|------|------|------|
| audioProps | AudioHTMLAttributes<HTMLAudioElement> | 透传到 <audio> 元素的原生属性 |
VideoNodeView
| Prop | 类型 | 说明 |
|------|------|------|
| videoProps | VideoHTMLAttributes<HTMLVideoElement> | 透传到 <video> 元素的原生属性 |
TextNodeView 和 MarkdownNodeView 仅支持通用 Props,无 slots。
国际化
内置 NodeView(ThinkingBlock、ToolCall)开箱支持中英文。
import {CpkTranslationsProvider} from '@bdky/chat-pilot-kit-react';
<CpkTranslationsProvider locale="zh-CN">
{/* ThinkingBlockNodeView 和 ToolCallNodeView 将使用中文标签 */}
<App />
</CpkTranslationsProvider>覆盖特定文案:
<CpkTranslationsProvider
locale="zh-CN"
translations={{
thinkingBlockLabel: '推理中',
toolCallStatusRunning: '执行中...',
}}
>
<App />
</CpkTranslationsProvider>可覆盖的 key:thinkingBlockLabel、toolCallStatusPending、toolCallStatusRunning、toolCallStatusCompleted、toolCallStatusError、toolCallArguments、toolCallResult。
主题定制
NodeView 样式使用 --cpk-node-* 命名空间下的 CSS 自定义属性。覆盖这些变量即可统一定制所有 NodeView 的外观:
:root {
--cpk-node-surface: #ffffff;
--cpk-node-text-primary: #111827;
--cpk-node-accent: #2563eb;
--cpk-node-panel-bg: #f9fafb;
--cpk-node-border: #e5e7eb;
}
[data-theme='dark'] {
--cpk-node-surface: #1e1e2e;
--cpk-node-text-primary: #cdd6f4;
--cpk-node-accent: #89b4fa;
--cpk-node-panel-bg: #181825;
--cpk-node-border: #313244;
}主题系统同时支持 prefers-color-scheme 媒体查询和祖先元素上的 data-theme="light" | "dark" 属性显式切换。
📘 TypeScript
所有类型均从包根路径导出:
import type {
// 来自 @bdky/chat-pilot-kit(重新导出)
NodeViewProps,
ConversationNode,
ConversationBean,
ConversationRole,
IConversationBeanInput,
IAttachmentInput,
INodeInteractionPayload,
INodeViewCommand,
BaseAgentService,
// React 专属
ReactNodeViewComponent,
NodeViewExtensionProps,
ThinkingBlockNodeViewExtProps,
ToolCallNodeViewExtProps,
ImageNodeViewExtProps,
FileNodeViewExtProps,
AudioNodeViewExtProps,
VideoNodeViewExtProps,
ToolCallStatus,
CpkTranslations,
} from '@bdky/chat-pilot-kit-react';🔗 相关包
| 包 | 说明 |
|----|------|
| @bdky/chat-pilot-kit | 核心无头 SDK,框架无关 |
| @bdky/chat-pilot-kit-vue3 | Vue 3 适配层 |
📄 许可证
MIT © Baidu Keyue Team
Made with ❤️ by 百度智能云客悦 Ky-FE Team
