Skip to main content

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;
}

返回值

属性类型说明
controllerIAaaSPilotKitController | null控制器实例,可能为 null
isReadyboolean控制器是否已就绪
isMutedboolean是否处于静音状态
isRenderingboolean是否正在播报
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
onTtftAgent首字延迟性能指标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 用于 React key

使用示例

// 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

参数

参数类型说明
conversationAIWorkerConversationBean | 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>;
}