Taro 多端小程序接入
基于 Taro 4.x 框架开发的 AI 对话 SDK,支持编译到微信小程序、支付宝小程序、抖音小程序、H5、React Native App。仅保留对话 + 多模态 + AG-UI,移除了 TTS/ASR/RTC,代码量轻量,适合微信生态内嵌。
安装
1npm install @lingshuai/chat-taro
前置条件:项目已使用 @tarojs/taro 4.x 版本,并配置了对应平台编译目标。
快速开始
1import { View, Text, Input, Button } from '@tarojs/components';2import { useChat } from '@lingshuai/chat-taro';34export default function ChatPage() {5 const { messages, sendMessage, loading, error } = useChat({6 apiKey: 'sk_live_your_api_key',7 appId: 'your_app_id',8 });910 const [input, setInput] = useState('');11 const msgClass = (role) => role === 'user' ? 'user' : 'assistant';1213 const handleSend = async () => {14 if (!input.trim()) return;15 const val = input;16 setInput('');17 await sendMessage(val);18 };1920 return (21 <View className="chat-container">22 <View className="messages">23 {messages.map(msg => (24 <View key={msg.id} className={msgClass(msg.role)}>25 <Text>{msg.content}</Text>26 </View>27 ))}28 {loading && <Text className="loading">AI 正在输入...</Text>}29 {error && <Text className="error">{error}</Text>}30 </View>31 <View className="input-area">32 <Input value={input} onInput={e => setInput(e.detail.value)}33 onConfirm={handleSend} disabled={loading} placeholder="输入消息..." />34 <Button onClick={handleSend} disabled={loading}>发送</Button>35 </View>36 </View>37 );38}
平台支持
| 平台 | 对话 | 流式响应 | 多模态 | AG-UI |
|---|---|---|---|---|
| 微信小程序 | ✓ | ✓ | ✓ | ✓ |
| 支付宝小程序 | ✓ | ✓ | ✓ | ✓ |
| 抖音小程序 | ✓ | ✓ | ✓ | ✓ |
| H5 | ✓ | ✓ | ✓ | ✓ |
| React Native | ✓ | ✓ | ✓ | ✓ |
流式说明:微信小程序支持 onUploadProgress 实时接收 SSE 片段,实现真正的流式打字效果。 其他平台自动降级为非流式接口,体验一致但内容一次性返回。
ChatConfig(初始化配置)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| apiKey | string | ✓ | API Key(sk_live_xxx),与 tokenProvider 二选一 |
| appId | string | ✓ | 项目/应用 ID |
| baseUrl | string | API 基础地址(默认使用平台地址) | |
| tokenProvider | () => Promise<string> | 临时 Token 获取函数,与 apiKey 二选一,推荐使用 | |
| timeout | number | 请求超时毫秒数(默认 30000) | |
| sessionId | string | 会话标识(自动生成) | |
| maxStoredMessages | number | 本地存储的最大消息数(默认 100) |
useChat 方法参考
sendMessage(content: string): Promise<void>
发送纯文本消息,自动流式渲染 AI 回复。
sendWithAttachments(content, attachments): Promise<void>
发送带多模态附件的消息。
sendWithUrls(content, urls): Promise<void>
直接传 URL 发送多模态消息,无需先上传。
uploadFile(filePath, type): Promise<UploadResult>
上传本地文件到平台存储。
sendImageFromAlbum(content?): Promise<void>
调起相册选择图片,自动上传并发送。
registerAgentAction(declaration): () => void
注册 AI 可调用的前端动作(AG-UI)。
on(event, handler): () => void
订阅事件,返回取消订阅函数。
abort(): void
中止当前正在进行的请求。
resetConversation() / clearHistory() / exportMessages() / importMessages()
会话管理和消息持久化。
支持的事件
| 事件名 | 触发时机 |
|---|---|
| message:stream:chunk | AI 回复片段到达(流式打字) |
| message:stream:end | AI 回复完成 |
| message:error | AI 回复出错 |
| ai:tool_progress | AI 执行工具中的进度提示 |
| skill:artifact_created | AI 生成了附件(如 PDF、Excel) |
| agent:action_execute | AI 请求执行前端动作 |
| agent:action_confirm | AI 请求用户确认动作(HITL) |
| agent:quick_replies | AI 返回快捷回复按钮 |
1const { on } = useChat({ apiKey: 'sk_live_xxx', appId: 'your_app_id' });23useEffect(() => {4 const off1 = on('message:stream:chunk', ({ fullContent }) => {5 console.log('打字中:', fullContent);6 });78 const off2 = on('agent:quick_replies', ({ replies }) => {9 console.log('快捷回复:', replies);10 });1112 return () => { off1(); off2(); };13}, []);
核心类型定义
1// ChatConfig2export interface ChatConfig {3 apiKey: string;4 appId: string;5 baseUrl?: string;6 tokenProvider?: () => Promise<string>;7 timeout?: number;8 sessionId?: string;9 maxStoredMessages?: number;10 autoCleanup?: boolean;11}1213// Message14export interface Message {15 id: string;16 conversationId: string;17 role: 'user' | 'assistant' | 'system';18 content: string;19 status: 'sending' | 'streaming' | 'success' | 'error';20 createdAt: Date;21 error?: string;22 attachments?: MediaAttachment[];23}2425// AgentActionDeclaration26export interface AgentActionDeclaration {27 name: string;28 description: string;29 parameters: AgentActionParam[];30 needsConfirmation?: boolean;31 confirmMessage?: string;32 handler: (params: Record<string, unknown>) => Promise<AgentActionResult>;33}3435export interface AgentActionResult {36 success: boolean;37 message: string;38 data?: Record<string, unknown>;39}