Composables API
Vue 3 Composition API wrapper library provides a series of composables, allowing you to easily use AaaS Pilot Kit functionality in Vue components.
Core Composables
useAaaSPilotKit
Provides controller instance and reactive state maintained within the provider.
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;
}
Return Values
| Property | Type | Description |
|---|---|---|
controller | ShallowRef<Controller | null> | Controller instance, may be null |
isReady | Ref<boolean> | Whether digital employee is ready |
isMuted | Ref<boolean> | Whether muted |
isRendering | Ref<boolean> | Whether rendering |
create | () => void | Manually create controller instance |
dispose | () => void | Manually destroy controller instance |
Usage Example
<template>
<div>
<div v-if="!isReady">Initializing...</div>
<div v-else>
<button
@click="sendMessage"
:disabled="isRendering"
>
{{isRendering ? 'Rendering' : 'Not Rendering'}}
</button>
<button @click="toggleMute">
{{isMuted ? 'Unmute' : 'Mute'}}
</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('Hello');
}
};
const toggleMute = () => {
if (controller.value) {
controller.value.mute(!isMuted.value);
}
};
</script>
Notes
- Must be called within
provideAaaSPilotKitinjection scope controller.valuemay benull, please check before calling methodscreate/disposecan be used to manually control lifecycle, such as resetting session- All returned states are readonly reactive references
useAaaSPilotKitEvents
Binds Vue component callback functions to the underlying event bus.
function useAaaSPilotKitEvents(props: IUseAaaSPilotKitEventsProps): void
Supported Events
Supported events align with IAaaSPilotKitEmitter:
| Event Name | Callback Parameter | Description |
|---|---|---|
onReady | () => void | Digital employee ready |
onAsrStart | () => void | Speech recognition started |
onAsrMessage | (payload) => void | Speech recognition result |
onMicrophoneAvailable | (result) => void | Microphone device availability check result |
onRenderStart | (payload) => void | Start rendering |
onInactivity | (payload) => void | Inactive state |
onBusy | (payload) => void | Busy state |
onInterrupt | (payload) => void | Interrupt event |
onConversationChange | (payload) => void | Conversation change |
onIsRenderingChange | (payload) => void | Rendering status change |
onReplyStart | (payload) => void | Digital employee start rendering |
onTtft | (payload) => void | Agent first token latency performance metric |
onMicrophoneAvailable Details
🎙️ Microphone device availability check result event.
Trigger Timing:
- When manually calling
controller.checkAudioDevice() - Before ASR starts automatically (requires configuration
checkAudioDeviceBeforeStart: true)
Callback Parameter Type:
interface MicrophoneAvailableResult {
available: boolean; // Whether device is available
error?: AudioDeviceError; // Error type (only when available=false)
userMessage?: string; // User-friendly error message
devices?: MediaDeviceInfo[]; // Detected audio device list
permissionState?: PermissionState; // Permission state
}
Usage Example:
<script setup lang="ts">
import { ref } from 'vue';
import { useAaaSPilotKitEvents } from '@bdky/aaas-pilot-kit-vue3';
const deviceStatus = ref<string>('');
const showAlert = ref(false);
useAaaSPilotKitEvents({
onMicrophoneAvailable: (result) => {
if (!result.available) {
// Device unavailable, show error message
deviceStatus.value = result.userMessage || 'Device unavailable';
showAlert.value = true;
} else {
// Device available
deviceStatus.value = 'Device normal';
showAlert.value = false;
}
}
});
</script>
<template>
<div v-if="showAlert" class="alert alert-error">
<p>{{ deviceStatus }}</p>
<button @click="showAlert = false">Got it</button>
</div>
</template>
Detailed Description: See Vanilla JS Events - microphone_available
Usage Example
<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('Digital employee ready');
},
onAsrStart: () => {
isListening.value = true;
},
onAsrMessage: (payload) => {
asrResults.value.push(payload.text);
console.log('ASR Result:', payload.text);
},
onRenderStart: (payload) => {
console.log('Start rendering:', payload);
},
onConversationChange: (payload) => {
console.log('Conversation content changed:', payload);
}
});
</script>
Internally uses watch to monitor controller changes, supports dynamic update of handlers within component lifecycle.
useConversationList
Monitors controller conversation_add event, maintains local conversation list.
function useConversationList(): {
conversationList: Ref<AnyConversation[]>;
}
Usage Example
<template>
<div>
<div>Total conversations: {{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>
Features
- Initial value is empty array
- New conversations automatically pushed to the end of the list
- Can be combined with
useConversationto render multiple conversation streams - Returns reactive reference, supports template direct binding
useConversation
Converts a single AnyConversation content stream to a directly renderable reactive list.
function useConversation(conversation: Ref<AnyConversation | undefined>): {
conversationContents: Ref<(NAIWorkerConversationBean.IContentChangePayload & {uiId: string})[]>;
}
Behavior Description
AIWorkerConversationBean: Progressively appends content, consecutive same type (mod) segments are merged- Client conversation: Replaces latest content to the end of the list
- All content items automatically injected with
uiId, convenient for Vuev-forkeyusage - Returns reactive reference, supports template direct binding
Usage Example
<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 ? 'Complete' : 'In Progress'}}
</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
Monitors AIWorkerConversationBean's conversation_end event.
function useConversationEnd(
conversation: Ref<AnyConversation | undefined>,
onConversationEnd?: (payload: NAIWorkerConversationBean.IConversationEndPayload) => void
): void
Parameters
| Parameter | Type | Description |
|---|---|---|
conversation | Ref<AnyConversation | undefined> | Reactive reference to conversation instance (only AIWorkerConversationBean will trigger callback) |
onConversationEnd | (payload) => void | Callback function when conversation completes |
Payload Type
interface IConversationEndPayload {
id: string;
text: string;
contents: IContent[];
timestamp: number;
}
Usage Example
<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>
Underlying Composables
useAaaSPilotKitProvider
Underlying provider implementation, returns reactive controller and state. Usually called via provideAaaSPilotKit.
function useAaaSPilotKitProvider<AS extends BaseAgentService = BaseAgentService>(
options: IOptions<AS>
): IAaaSPilotKitProvider<AS>
For complete configuration options, please refer to Vanilla JS - Configuration Options.
v1.1.0 added asr configuration support for Baidu/Azure dual ASR service providers.
injectAaaSPilotKit
Underlying dependency injection function. If you need to bridge with non-Vue code or implement composables yourself, you can use directly.
const provider = injectAaaSPilotKit();
if (!provider) {
throw new Error('AaaSPilotKit provider not injected');
}
Combination Usage Example
Complete Chat Application
App.vue - Parent Component (Provide 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: If custom agentService is not provided, this config is required
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
}
});
</script>
PilotApp.vue
<template>
<div class="chat-app">
<div class="status-bar">
<div>Status: {{isReady ? 'Ready' : 'Initializing'}}</div>
<div>{{isRendering ? 'Rendering' : 'Idle'}}</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="Enter message..."
/>
<button @click="sendMessage" :disabled="!canSend">
Send
</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('Chat ready'),
onAsrMessage: (payload) => console.log('Voice input:', payload.text),
onError: (error) => console.error('Error occurred:', error)
});
</script>
Type Definitions
Main types exported by the library:
// Provider related
export interface IAaaSPilotKitProvider<AS extends BaseAgentService = BaseAgentService>
export const AaaSPilotKitProviderKey: InjectionKey<IAaaSPilotKitProvider>
// Composables return values
export interface IUseAaaSPilotKitResult<AS extends BaseAgentService = BaseAgentService>
export interface IUseAaaSPilotKitEventsProps
export interface IUseConversationResult
export interface IUseConversationListResult