Hooks API
React SDK 提供的所有 Hooks API 详细说明。
useAaaSPilotKit
提供控制器实例及 Provider 内部维护的状态。
接口定义
function useAaaSPilotKit<AS extends BaseAgentService = BaseAgentService>(): {
controller: ReturnType<typeof createAaaSPilotKit<AS>> | null;
isReady: boolean;
isMuted: boolean;
isRendering: boolean;
create: () => void;
dispose: () => void;
}
返回值
| 属性 | 类型 | 说明 |
|---|---|---|
controller | IAaaSPilotKitController | null | 控制器实例,可能为 null |
isReady | boolean | 控制器是否已就绪 |
isMuted | boolean | 是否处于静音状态 |
isRendering | boolean | 是否正在播报 |
create | () => void | 手动创建控制器 |
dispose | () => void | 手动销毁控制器 |
使用示例
示例1:
function Dashboard() {
const {controller, isReady, isMuted, isRendering} = useAaaSPilotKit();
const handleSendMessage = useCallback(
() => {
if (controller && isReady) {
controller.input('你好,我想了解产品信息');
}
},
[controller, isReady]
);
const handleToggleMute = useCallback(
() => {
if (controller) {
controller.mute(!isMuted);
}
},
[controller, isMuted]
);
return (
<div>
<div>状态: {isReady ? '就绪' : '初始化中'}</div>
<div>音频: {isMuted ? '静音' : '正常'}</div>
<div>渲染: {isRendering ? '进行中' : '空闲'}</div>
<button onClick={handleSendMessage} disabled={!isReady}>
发送消息
</button>
<button onClick={handleToggleMute} disabled={!controller}>
{isMuted ? '取消静音' : '静音'}
</button>
</div>
);
}
示例2:
const Dashboard: FC<IPilotKitProps> = props => {
const [isInactive, setIsInactive] = useState(false);
const {create, dispose} = useAaaSPilotKit();
const onInactivity = useCallback(
() => {
setIsInactive(true);
dispose();
},
[dispose]
);
useAaaSPilotKitEvents({
onInactivity
});
const restart = useCallback(
() => {
setIsInactive(false);
create();
},
[create]
);
if (isInactive) {
return (
<div>
超时
<button
onClick={restart}
>
重新开始
</button>
</div>
);
}
return (
<Dialog
{...props}
/>
);
};
注意事项
- 必须在
AaaSPilotKitProvider范围内调用 controller可能为null,请在调用前判空create/dispose用于手动控制生命周期,谨慎使用
useAaaSPilotKitEvents
将 React 组件的回调函数与底层事件总线绑定。
接口定义
function useAaaSPilotKitEvents(props: {
onReady?: () => void;
onAsrStart?: () => void;
onAsrMessage?: (payload: IAsrMessageEventPayload) => void;
onMicrophoneAvailable?: (result: MicrophoneAvailableResult) => void;
onRenderStart?: (payload: IRenderStartEventPayload) => void;
onInactivity?: (payload: IInactivityEventPayload) => void;
onBusy?: (payload: IBusyEventPayload) => void;
onInterrupt?: (payload: IInterruptEventPayload) => void;
onConversationChange?: (payload: IConversationChangeEventPayload) => void;
onIsRenderingChange?: (isRendering: boolean) => void;
onReplyStart?: (payload: IReplyStartEventPayload) => void;
onTtft?: (payload: ITtftEventPayload) => void;
onError?: (error: IErrorEventPayload) => void;
}): void;
支持的事件
| 事件 | 说明 | Payload 类型 |
|---|---|---|
onReady | 控制器初始化完成 | 无 |
onAsrStart | 开始语音识别 | 无 |
onAsrMessage | 语音识别结果 | IAsrMessageEventPayload |
onMicrophoneAvailable | 麦克风设备可用性检测结果 | MicrophoneAvailableResult |
onRenderStart | 开始渲染播报 | IRenderStartEventPayload |
onInactivity | 用户长时间无活动 | IInactivityEventPayload |
onBusy | 系统繁忙(路数超限等) | IBusyEventPayload |
onInterrupt | 对话被打断 | IInterruptEventPayload |
onConversationChange | 对话内容变化 | IConversationChangeEventPayload |
onIsRenderingChange | 播报状态变化 | boolean |
onReplyStart | 数字员工开始播报 | IReplyStartEventPayload |
onTtft | Agent首字延迟性能指标 | ITtftEventPayload |
onError | 发生错误 | IErrorEventPayload |
onMicrophoneAvailable 详解
🎙️ 麦克风设备可用性检测结果事件。
触发时机:
- 手动调用
controller.checkAudioDevice()时 - ASR 启动前自动检测(需配置
checkAudioDeviceBeforeStart: true)
Payload 类型:
interface MicrophoneAvailableResult {
available: boolean; // 设备是否可用
error?: AudioDeviceError; // 错误类型(仅当 available=false 时)
userMessage?: string; // 用户友好的错误提示文案
devices?: MediaDeviceInfo[]; // 检测到的音频设备列表
permissionState?: PermissionState; // 权限状态
}
使用示例:
function DeviceStatusAlert() {
const [deviceStatus, setDeviceStatus] = useState<string>('');
const [showAlert, setShowAlert] = useState(false);
useAaaSPilotKitEvents({
onMicrophoneAvailable: (result) => {
if (!result.available) {
// 设备不可用,显示错误提示
setDeviceStatus(result.userMessage || '设备不可用');
setShowAlert(true);
} else {
// 设备可用
setDeviceStatus('设备正常');
setShowAlert(false);
}
}
});
if (!showAlert) return null;
return (
<div className="alert alert-error">
<p>{deviceStatus}</p>
{/* 根据错误类型提供解决方案 */}
<button onClick={() => setShowAlert(false)}>知道了</button>
</div>
);
}
详细说明: 参见 Vanilla JS Events - microphone_available
使用示例
function EventHandler() {
const [asrText, setAsrText] = useState('');
const [conversations, setConversations] = useState([]);
useAaaSPilotKitEvents({
onReady: () => {
console.log('数字员工已就绪');
},
onAsrMessage: (payload) => {
setAsrText(payload.text);
if (payload.completed) {
console.log('语音识别完成:', payload.text);
}
},
onRenderStart: (payload) => {
console.log('开始播报:', payload.text);
},
onConversationChange: (payload) => {
console.log('对话更新:', payload);
},
onError: (error) => {
console.error('发生错误:', error);
// 根据错误类型处理
if (error.severity === 'critical') {
alert(`严重错误: ${error.message}`);
}
}
});
return (
<div>
<div>当前识别: {asrText}</div>
<div>对话数: {conversations.length}</div>
</div>
);
}
动态事件处理
function DynamicEventHandler() {
const [logEnabled, setLogEnabled] = useState(true);
// 事件处理器可以动态变化
useAaaSPilotKitEvents({
onAsrMessage: logEnabled ?
(payload) => console.log('ASR:', payload.text) :
undefined,
onConversationChange: useCallback((payload) => {
// 使用 useCallback 优化性能
updateConversationInState(payload);
}, [])
});
return (
<div>
<label>
<input
type="checkbox"
checked={logEnabled}
onChange={(e) => setLogEnabled(e.target.checked)}
/>
启用日志
</label>
</div>
);
}
useConversationList
监听并维护本地对话列表。
接口定义
function useConversationList(): {
conversationList: AnyConversation[];
}
返回值
conversationList: 对话列表数组
使用示例
function ConversationPanel() {
const {conversationList} = useConversationList();
return (
<div className="conversation-panel">
<div className="header">
对话记录数:({conversationList.length})
</div>
<div className="conversation-list">
{conversationList.map((conversation, index) => (
<ConversationView
key={conversation.id}
conversation={conversation}
/>
))}
</div>
</div>
);
}
useConversation
将单个对话内容转换为可渲染的列表。
接口定义
function useConversation(conversation: AnyConversation): {
conversationContents: (NAIWorkerConversationBean.IContentChangePayload & {uiId: string})[];
}
参数
conversation: 单个对话对象
返回值
conversationContents: 可渲染的内容列表,每项包含uiId用于 Reactkey
使用示例
// ConversationView 是 useConversationList 示例中的 <ConversationView ... />
function ConversationView({conversation}) {
const {conversationContents} = useConversation(conversation);
return (
<div className="conversation">
<div className="conversation-header">
{conversation.type === 'client' ? '用户' : '数字员工'}
</div>
<div className="conversation-body">
{conversationContents.map(item => (
<div
key={item.uiId}
className={`content-item ${item.completed ? 'completed' : 'typing'}`}
>
<span className="mod-label">{item.mod}</span>
<div className="content">{item.content}</div>
{!item.completed && <span className="typing-indicator">...</span>}
</div>
))}
</div>
</div>
);
}
高级用法
function EnhancedConversationView({conversation}) {
const {conversationContents} = useConversation(conversation);
// 计算总字数
const totalChars = conversationContents.reduce(
(sum, item) => sum + (item.content?.length || 0),
0
);
// 是否正在输入
const isTyping = conversationContents.some(item => !item.completed);
return (
<div className="enhanced-conversation">
<div className="stats">
字数: {totalChars} | 状态: {isTyping ? '输入中' : '完成'}
</div>
{conversationContents.map(item => (
<div key={item.uiId} className="content-item">
{item.content}
</div>
))}
</div>
);
}
与其他 Hooks 组合
function CompleteConversationSystem() {
const {controller, isReady} = useAaaSPilotKit();
const {conversationList} = useConversationList();
const [selectedIndex, setSelectedIndex] = useState(-1);
// 自动选择最新对话
useEffect(
() => {
if (conversationList.length > 0) {
setSelectedIndex(conversationList.length - 1);
}
},
[conversationList.length]
);
const selectedConversation = conversationList[selectedIndex];
return (
<div className="conversation-system">
<div className="sidebar">
{conversationList.map((conv, index) => (
<div
key={conv.id || index}
className={`conversation-item ${index === selectedIndex ? 'active' : ''}`}
onClick={() => setSelectedIndex(index)}
>
{conv.type === 'client' ? '用户' : 'AI'} - {new Date(conv.timestamp).toLocaleTimeString()}
</div>
))}
</div>
<div className="main">
{selectedConversation && (
<ConversationView conversation={selectedConversation} />
)}
</div>
</div>
);
}
useConversationEnd
监听 AIWorkerConversationBean 的 conversation_end 事件。
接口定义
function useConversationEnd(
conversation: AIWorkerConversationBean | null,
onConversationEnd?: (payload: NAIWorkerConversationBean.IConversationEndPayload) => void
): void
参数
| 参数 | 类型 | 说明 |
|---|---|---|
conversation | AIWorkerConversationBean | null | 需要监听的对话实例 |
onConversationEnd | (payload) => void | 对话完成时的回调函数 |
Payload 类型
interface IConversationEndPayload {
id: string;
text: string;
contents: IContent[];
timestamp: number;
}
使用示例
function ConversationStatus({ conversation }) {
const [status, setStatus] = useState('进行中');
useConversationEnd(
conversation instanceof AIWorkerConversationBean ? conversation : null,
(payload) => {
setStatus('已完成');
console.log('对话结束,总字数:', payload.text.length);
}
);
return <div className="status-badge">{status}</div>;
}