Skip to main content

Common Questions (FAQ)

Basic Usage Questions

1. Why does it say "useAaaSPilotKit must be used within a component that provides AaaSPilotKit"?

Reason: provideAaaSPilotKit and useAaaSPilotKit are used in the same component.

Common Error
<!--  Error Example -->
<script setup lang="ts">
import {provideAaaSPilotKit, useAaaSPilotKit} from '@bdky/aaas-pilot-kit-vue3';

provideAaaSPilotKit(options);
const {controller} = useAaaSPilotKit(); // ❌ Error! Will throw error
</script>

Solution: Split into parent-child components

Correct Example

App.vue - Parent Component

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

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

const options = {
token: 'your-auth-token-here',
figureId: '209337',
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
}
};

provideAaaSPilotKit(options);
</script>

PilotComponent.vue - Child Component

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

const {controller, isReady} = useAaaSPilotKit(); // ✅ Correct
</script>

2. What to do if the digital employee avatar doesn't display?

Reason: Forgot to call controller.mount() to mount the digital employee rendering container.

Solution: Mount the digital employee container in the parent component

<template>
<div class="app">
<!-- Digital employee rendering container -->
<div ref="digitalHumanRef" class="digital-human-container"></div>
<PilotComponent />
</div>
</template>

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

const options = {
token: 'your-auth-token-here',
figureId: '209337',
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
}
};

const provider = provideAaaSPilotKit(options);

// Digital employee rendering container
const digitalHumanRef = ref<HTMLDivElement>();

// Mount digital employee to DOM
onMounted(() => {
if (digitalHumanRef.value) {
provider.controller.value?.mount(digitalHumanRef.value);
}
});

// Remember to destroy
onUnmounted(() => {
provider.controller.value?.dispose();
});
</script>

<style scoped>
.digital-human-container {
width: 100%;
height: 400px;
position: relative;
}
</style>

3. Why is the conversation passed through props not reactive?

Reason: Direct destructuring of props.conversation loses reactivity.

Solution: Use toRef to wrap props

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

// ✅ Correct: Use toRef to maintain reactivity
const {conversationContents} = useConversation(toRef(props, 'conversation'));

// ❌ Error: Directly passing props.conversation loses reactivity
// const {conversationContents} = useConversation(props.conversation);
</script>

Principle Explanation:

  • defineProps returns reactive props object (Proxy)
  • Direct destructuring of props.conversation loses reactivity
  • toRef(props, 'conversation') creates a ref pointing to the props property, maintaining reactive tracking

4. Why is controller.value null?

Reason: The controller is null during initialization, need to wait for isReady to be true.

Solution: Use reactive state to judge

<template>
<div>
<div v-if="!isReady">Initializing...</div>
<div v-else>
<button @click="sendMessage" :disabled="!canSend">
Send Message
</button>
</div>
</div>
</template>

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

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

// Safe status judgment
const canSend = computed(() => {
return isReady.value && !isRendering.value && controller.value !== null;
});

const sendMessage = () => {
if (canSend.value) {
controller.value!.input('Hello');
}
};
</script>

Component Structure Questions

5. How to correctly organize parent-child component structure?

Recommended component structure:

App.vue (parent component)
├── provideAaaSPilotKit()
├── Mount digital employee container
└── Child components
├── PilotComponent.vue (use useAaaSPilotKit)
├── ConversationList.vue (use useConversationList)
└── ConversationItem.vue (use useConversation)

Complete Example:

App.vue

<template>
<div class="app">
<div ref="digitalHumanRef" class="digital-human"></div>
<ConversationList />
<ChatInput />
</div>
</template>

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

const provider = provideAaaSPilotKit({
token: 'your-auth-token-here',
figureId: '209337',
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
}
});

const digitalHumanRef = ref<HTMLDivElement>();

onMounted(() => {
if (digitalHumanRef.value) {
provider.controller.value?.mount(digitalHumanRef.value);
}
});
</script>

ConversationList.vue

<template>
<div class="conversation-list">
<ConversationItem
v-for="conversation in conversationList"
:key="conversation.id"
:conversation="conversation"
/>
</div>
</template>

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

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

ConversationItem.vue

<template>
<div class="conversation-item">
<div
v-for="item in conversationContents"
:key="item.uiId"
:class="['message', item.mod]"
>
<strong>{{ item.mod }}</strong>
<div>{{ item.content }}</div>
<span>{{ item.completed ? '✓' : '...' }}</span>
</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 { conversationContents } = useConversation(toRef(props, 'conversation'));
</script>

ChatInput.vue

<template>
<div class="chat-input">
<input
v-model="inputText"
@keyup.enter="sendMessage"
:disabled="!canSend"
placeholder="Enter message..."
/>
<button @click="sendMessage" :disabled="!canSend">
Send
</button>
</div>
</template>

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

const {controller, isReady, isRendering} = useAaaSPilotKit();
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 = '';
}
};
</script>

Advanced Usage Questions

6. How to handle multiple digital employee instances?

Use Case: Need multiple independent digital employee instances in the same application (e.g., customer service + sales).

Solution: Use useAaaSPilotKitProvider + custom provide key

<template>
<div class="multi-avatar-app">
<div class="avatar-section">
<h3>Customer Service Assistant</h3>
<CustomerServicePilot />
</div>
<div class="avatar-section">
<h3>Sales Assistant</h3>
<SalesAssistantPilot />
</div>
</div>
</template>

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

// Create different instances for different uses
const customerServiceKey = Symbol('customer-service');
const salesAssistantKey = Symbol('sales-assistant');

// Create customer service robot instance
const customerServiceProvider = useAaaSPilotKitProvider({
token: 'your-auth-token-here',
figureId: '209337',
agentConfig: {
token: 'customer-token',
robotId: 'customer-robot'
}
});

// Create sales assistant robot instance
const salesAssistantProvider = useAaaSPilotKitProvider({
token: 'your-auth-token-here',
figureId: '209338',
agentConfig: {
token: 'sales-token',
robotId: 'sales-robot'
}
});

provide(customerServiceKey, customerServiceProvider);
provide(salesAssistantKey, salesAssistantProvider);
</script>

7. How to reset session?

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

const {controller, create, dispose} = useAaaSPilotKit();

const resetSession = async () => {
// 1. Destroy current controller
dispose();

// 2. Wait for one tick to ensure destruction completes
await nextTick();

// 3. Create new controller
create();
};
</script>

Error Handling

8. How to capture and handle errors?

<template>
<div>
<div v-if="error" class="error-message">
{{ error }}
</div>
<!-- Normal content -->
</div>
</template>

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

const {controller, isReady} = useAaaSPilotKit();

// Monitor events and handle errors
useAaaSPilotKitEvents({
onReady: () => {
console.log('Digital employee ready');
},
onError: (payload) => {
// Unified error handling
console.error('Digital employee error:', payload);
}
});
</script>

Performance Optimization

9. How to optimize rendering performance for many conversations?

Problem: Conversation list too long causing page lag.

Solution 1: Pagination load

<template>
<div class="conversation-list">
<ConversationItem
v-for="conversation in visibleConversations"
:key="conversation.id"
:conversation="conversation"
/>
<button v-if="hasMore" @click="loadMore">
Load More
</button>
</div>
</template>

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

const {conversationList} = useConversationList();
const visibleCount = ref(10); // Initially show 10 items

const visibleConversations = computed(() => {
return conversationList.value.slice(0, visibleCount.value);
});

const hasMore = computed(() => {
return conversationList.value.length > visibleCount.value;
});

const loadMore = () => {
visibleCount.value += 10; // Load 10 items each time
};
</script>

Solution 2: Virtual scrolling (recommended for ultra-long lists)

Use @tanstack/vue-virtual (more modern choice):

npm

npm install @tanstack/vue-virtual

yarn

yarn add @tanstack/vue-virtual
<template>
<div ref="parentRef" class="list-container">
<div
:style="{
height: `${virtualizer.getTotalSize()}px`,
position: 'relative'
}"
>
<div
v-for="item in virtualizer.getVirtualItems()"
:key="item.key"
:style="{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${item.size}px`,
transform: `translateY(${item.start}px)`
}"
>
<ConversationItem :conversation="conversationList[item.index]" />
</div>
</div>
</div>
</template>

<script setup lang="ts">
import {ref, computed} from 'vue';
import {useVirtualizer} from '@tanstack/vue-virtual';
import {useConversationList} from '@bdky/aaas-pilot-kit-vue3';
import ConversationItem from './ConversationItem.vue';

const {conversationList} = useConversationList();
const parentRef = ref<HTMLElement>();

const virtualizer = useVirtualizer(
computed(() => ({
count: conversationList.value.length,
getScrollElement: () => parentRef.value,
estimateSize: () => 80, // Per item height
overscan: 5 // Pre-render item count
}))
);
</script>

<style scoped>
.list-container {
height: 500px;
overflow: auto;
}
</style>

Performance Comparison:

  • Pagination load: Suitable for medium-scale lists (< 1000 items), simple implementation
  • Virtual scrolling: Suitable for ultra-long lists (> 1000 items), only renders visible area, best performance

Debugging Tips

10. How to enable detailed logging in development mode?

Method: Enable debug mode (recommended)

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

const isDev = import.meta.env.DEV;

const provider = provideAaaSPilotKit({
token: 'your-auth-token-here',
figureId: '209337',
agentConfig: {
token: 'your-token',
robotId: 'your-robot-id'
},
env: isDev ? 'development' : 'production',
enableDebugMode: isDev
});

// Monitor error events to get detailed error information
useAaaSPilotKitEvents({
onError: (error) => {
console.group('🔴 Digital Employee Error Details');
console.error('Error Code:', error.code);
console.error('Error Message:', error.message);
console.error('Severity:', error.severity);
console.error('Metadata:', error.metadata);
if (error.stack) {
console.error('Error Stack:', error.stack);
}
console.groupEnd();
}
});
</script>
More Debug Options

For enableDebugMode configuration and complete error code reference, please view Vanilla SDK FAQ - How to debug issues?

Microphone Device Issues

All microphone device related issues (permissions, HTTPS requirements, device occupation, etc.) and solutions, please refer to:

👉 Vanilla JS FAQ - Microphone Device Troubleshooting

This section includes:

  • How to detect if microphone is available
  • Detailed solutions for 6 common errors (error codes 3100-3105)
  • Browser permission setting guides
  • Safari special notes
  • Complete code examples

All solutions apply equally to Vue version.

More Help

If you encounter other issues, please:

  1. View console error information - Most issues have detailed error prompts
  2. Check network connection - Ensure you can normally access the service
  3. Verify configuration parameters - Check if token, robotId, figureId are correct
  4. Version compatibility - Ensure you're using compatible Vue 3 version (>= 3.0)

Contact Information: