Skip to main content

Composables API

Vue 3 组合式 API 封装库提供了一系列 composables,让你可以轻松地在 Vue 组件中使用 AaaS Pilot Kit 功能。

核心 Composables

useAaaSPilotKit

提供控制器实例及提供者内部维护的响应式状态。

function useAaaSPilotKit<AS extends BaseAgentService = BaseAgentService>(): {
controller: Readonly<ShallowRef<ReturnType<typeof createAaaSPilotKit<AS>> | null>>;
isReady: Readonly<Ref<boolean>>;
isMuted: Readonly<Ref<boolean>>;
isRendering: Readonly<Ref<boolean>>;
create: () => void;
dispose: () => void;
}

返回值

属性类型描述
controllerShallowRef<Controller | null>控制器实例,可能为 null
isReadyRef<boolean>数字员工是否已就绪
isMutedRef<boolean>是否处于静音状态
isRenderingRef<boolean>是否正在播报
create() => void手动创建控制器实例
dispose() => void手动销毁控制器实例

使用示例

<template>
<div>
<div v-if="!isReady">初始化中...</div>
<div v-else>
<button
@click="sendMessage"
:disabled="isRendering"
>
{{isRendering ? '播报中' : '未播报'}}
</button>
<button @click="toggleMute">
{{isMuted ? '取消静音' : '静音'}}
</button>
</div>
</div>
</template>

<script setup lang="ts">
import {computed} from 'vue';
import {useAaaSPilotKit} from '@bdky/aaas-pilot-kit-vue3';

const {controller, isReady, isMuted, isRendering} = useAaaSPilotKit();

const canSendMessage = computed(() => {
return isReady.value && controller.value !== null;
});

const sendMessage = () => {
if (canSendMessage.value) {
controller.value!.input('你好');
}
};

const toggleMute = () => {
if (controller.value) {
controller.value.mute(!isMuted.value);
}
};
</script>

注意事项

  • 必须在 provideAaaSPilotKit 注入范围内调用
  • controller.value 可能为 null,请在调用方法前判空
  • create/dispose 可用于手动控制生命周期,例如重置会话
  • 返回的状态均为只读响应式引用

useAaaSPilotKitEvents

将 Vue 组件的回调函数与底层事件总线绑定。

function useAaaSPilotKitEvents(props: IUseAaaSPilotKitEventsProps): void

支持的事件

受支持的事件与 IAaaSPilotKitEmitter 对齐:

事件名回调参数描述
onReady() => void数字员工就绪
onAsrStart() => void语音识别开始
onAsrMessage(payload) => void语音识别结果
onMicrophoneAvailable(result) => void麦克风设备可用性检测结果
onRenderStart(payload) => void开始渲染
onInactivity(payload) => void非活跃状态
onBusy(payload) => void忙碌状态
onInterrupt(payload) => void中断事件
onConversationChange(payload) => void对话变更
onIsRenderingChange(payload) => void播报状态变更
onReplyStart(payload) => void数字员工开始播报
onTtft(payload) => voidAgent首字延迟性能指标

onMicrophoneAvailable 详解

🎙️ 麦克风设备可用性检测结果事件。

触发时机:

  • 手动调用 controller.checkAudioDevice()
  • ASR 启动前自动检测(需配置 checkAudioDeviceBeforeStart: true

回调参数类型:

interface MicrophoneAvailableResult {
available: boolean; // 设备是否可用
error?: AudioDeviceError; // 错误类型(仅当 available=false 时)
userMessage?: string; // 用户友好的错误提示文案
devices?: MediaDeviceInfo[]; // 检测到的音频设备列表
permissionState?: PermissionState; // 权限状态
}

使用示例:

<script setup lang="ts">
import { ref } from 'vue';
import { useAaaSPilotKitEvents } from '@baidu/ky-employee-embed-widget-vue';

const deviceStatus = ref<string>('');
const showAlert = ref(false);

useAaaSPilotKitEvents({
onMicrophoneAvailable: (result) => {
if (!result.available) {
// 设备不可用,显示错误提示
deviceStatus.value = result.userMessage || '设备不可用';
showAlert.value = true;
} else {
// 设备可用
deviceStatus.value = '设备正常';
showAlert.value = false;
}
}
});
</script>

<template>
<div v-if="showAlert" class="alert alert-error">
<p>{{ deviceStatus }}</p>
<button @click="showAlert = false">知道了</button>
</div>
</template>

详细说明: 参见 Vanilla JS Events - microphone_available

使用示例

<script setup lang="ts">
import {ref} from 'vue';
import {useAaaSPilotKitEvents} from '@bdky/aaas-pilot-kit-vue3';

const asrResults = ref<string[]>([]);
const isListening = ref(false);

useAaaSPilotKitEvents({
onReady: () => {
console.log('数字员工已就绪');
},
onAsrStart: () => {
isListening.value = true;
},
onAsrMessage: (payload) => {
asrResults.value.push(payload.text);
console.log('ASR结果:', payload.text);
},
onRenderStart: (payload) => {
console.log('开始播报:', payload);
},
onConversationChange: (payload) => {
console.log('对话内容变更:', payload);
}
});
</script>

内部使用 watch 监听控制器变化,支持在组件生命周期内动态更新处理函数。

useConversationList

监听控制器的 conversation_add 事件,维护本地对话列表。

function useConversationList(): {
conversationList: Ref<AnyConversation[]>;
}

使用示例

<template>
<div>
<div>对话总数:{{conversationList.length}}</div>
<ConversationItem
v-for="conversation in conversationList"
:key="conversation.id || conversation.type"
:conversation="conversation"
/>
</div>
</template>

<script setup lang="ts">
import {useConversationList} from '@bdky/aaas-pilot-kit-vue3';

const {conversationList} = useConversationList();
</script>

特性

  • 初始值为空数组
  • 新对话到来时自动 push 到列表末尾
  • 可与 useConversation 组合渲染多个对话流
  • 返回响应式引用,支持模板直接绑定

useConversation

将单个 AnyConversation 的内容流式转换为可直接渲染的响应式列表。

function useConversation(conversation: Ref<AnyConversation | undefined>): {
conversationContents: Ref<(NAIWorkerConversationBean.IContentChangePayload & {uiId: string})[]>;
}

行为说明

  • AIWorkerConversationBean:逐步追加内容,连续同类型 (mod) 片段会合并
  • 客户端对话:将最新内容替换到列表末尾
  • 所有内容项自动注入 uiId,便于 Vue v-forkey 使用
  • 返回响应式引用,支持模板直接绑定

使用示例

<template>
<div class="conversation">
<div
v-for="item in conversationContents"
:key="item.uiId"
:class="['message', item.mod]"
>
<div class="message-header">
<strong>{{item.mod}}</strong>
<span :class="['status', {completed: item.completed}]">
{{item.completed ? '完成' : '进行中'}}
</span>
</div>
<div class="message-content">{{item.content}}</div>
</div>
</div>
</template>

<script setup lang="ts">
import {toRef} from 'vue';
import {useConversation} from '@bdky/aaas-pilot-kit-vue3';
import type {AnyConversation} from '@bdky/aaas-pilot-kit';

const props = defineProps<{
conversation: AnyConversation | undefined;
}>();

const conversation = toRef(props, 'conversation');
const {conversationContents} = useConversation(conversation);
</script>

<style scoped>
.conversation {
max-height: 400px;
overflow-y: auto;
}

.message {
margin-bottom: 12px;
padding: 8px;
border-radius: 8px;
}

.message.user {
background-color: #e3f2fd;
}

.message.assistant {
background-color: #f5f5f5;
}

.message-header {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
}

.status.completed {
color: #4caf50;
}
</style>

useConversationEnd

监听 AIWorkerConversationBeanconversation_end 事件。

function useConversationEnd(
conversation: Ref<AnyConversation | undefined>,
onConversationEnd?: (payload: NAIWorkerConversationBean.IConversationEndPayload) => void
): void

参数

参数类型说明
conversationRef<AnyConversation | undefined>对话实例的响应式引用(仅 AIWorkerConversationBean 会触发回调)
onConversationEnd(payload) => void对话完成时的回调函数

Payload 类型

interface IConversationEndPayload {
id: string;
text: string;
contents: IContent[];
timestamp: number;
}

使用示例

<script setup lang="ts">
import {useConversationEnd} from '@bdky/aaas-pilot-kit-vue3';
import {toRef} from 'vue';
import type {AnyConversation} from '@bdky/aaas-pilot-kit';

const props = defineProps<{conversation: AnyConversation}>();
const conversationRef = toRef(props, 'conversation');

useConversationEnd(
conversationRef,
payload => {
console.log('Conversation ended:', payload.text);
console.log('Contents:', payload.contents.length);
}
);
</script>

底层 Composables

useAaaSPilotKitProvider

底层提供者实现,返回响应式的控制器和状态。通常通过 provideAaaSPilotKit 调用。

function useAaaSPilotKitProvider<AS extends BaseAgentService = BaseAgentService>(
options: IOptions<AS>
): IAaaSPilotKitProvider<AS>

injectAaaSPilotKit

底层依赖注入函数。如果需要与非 Vue 代码打通或自行实现 composables,可直接使用。

const provider = injectAaaSPilotKit();
if (!provider) {
throw new Error('AaaSPilotKit 未注入提供者');
}

组合使用示例

完整的聊天应用

App.vue - 父组件(提供 Provider)

<template>
<div class="app">
<PilotApp />
</div>
</template>

<script setup lang="ts">
import {provideAaaSPilotKit} from '@bdky/aaas-pilot-kit-vue3';
import PilotApp from './PilotApp.vue';

provideAaaSPilotKit({
token: 'your-auth-token-here',
figureId: '209337',
ttsPer: 'LITE_audiobook_female_1',
// agentConfig: 若未提供自定义 agentService,此配置必填
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
}
});
</script>

PilotApp.vue

<template>
<div class="chat-app">
<div class="status-bar">
<div>状态:{{isReady ? '就绪' : '初始化中'}}</div>
<div>{{isRendering ? '播报中' : '空闲'}}</div>
</div>

<div class="conversation-list">
<ConversationComponent
v-for="conversation in conversationList"
:key="conversation.id || conversation.type"
:conversation="conversation"
/>
</div>

<div class="input-area">
<input
v-model="inputText"
@keyup.enter="sendMessage"
:disabled="!canSend"
placeholder="输入消息..."
/>
<button @click="sendMessage" :disabled="!canSend">
发送
</button>
</div>
</div>
</template>

<script setup lang="ts">
import {ref, computed} from 'vue';
import {
useAaaSPilotKit,
useAaaSPilotKitEvents,
useConversationList
} from '@bdky/aaas-pilot-kit-vue3';

const {controller, isReady, isRendering} = useAaaSPilotKit();
const {conversationList} = useConversationList();

const inputText = ref('');

const canSend = computed(() => {
return isReady.value && !isRendering.value && inputText.value.trim();
});

const sendMessage = () => {
if (canSend.value && controller.value) {
controller.value.input(inputText.value);
inputText.value = '';
}
};

useAaaSPilotKitEvents({
onReady: () => console.log('聊天已就绪'),
onAsrMessage: (payload) => console.log('语音输入:', payload.text),
onError: (error) => console.error('发生错误:', error)
});
</script>

类型定义

库内导出的主要类型:

// Provider 相关
export interface IAaaSPilotKitProvider<AS extends BaseAgentService = BaseAgentService>
export const AaaSPilotKitProviderKey: InjectionKey<IAaaSPilotKitProvider>

// Composables 返回值
export interface IUseAaaSPilotKitResult<AS extends BaseAgentService = BaseAgentService>
export interface IUseAaaSPilotKitEventsProps
export interface IUseConversationResult
export interface IUseConversationListResult