自定义请求
AI 小鲸 v2.0 提供了灵活的请求自定义能力,允许你配置请求头、请求体等,以适配不同的后端服务和认证方案。
requestOptions 属性
ChatBot 和 AIBlueking 组件都接受 requestOptions 属性,用于全局配置所有 HTTP 请求。这是最常用的认证配置方式:
typescript
import type { MaybeRequestValue } from '@blueking/chat-helper';
import type { MaybeRefOrGetter } from 'vue';
import type { IRequestOptions } from '@blueking/ai-blueking';
// 组件 props:整体可为 ref / computed
type RequestOptionsProp = MaybeRefOrGetter<IRequestOptions>;
interface IRequestOptions {
/** 支持对象、零参函数、ref、computed */
headers?: MaybeRequestValue<Record<string, string>>;
/** 支持对象、零参函数、ref、computed;按 HTTP 方法写入 body 或 query */
data?: MaybeRequestValue<Record<string, unknown>>;
}内部机制
当你在组件上传入 requestOptions:
- ChatBot 独立模式:内部通过
useChatHelper({ requestData: { urlPrefix, headers, data } })创建 SDK 实例,requestOptions.headers/data会直接映射到requestData.headers/data - AIBlueking:内部通过
useChatBootstrap({ url, requestOptions })初始化,同样映射到useChatHelper的requestData
两种组件底层走的是同一条路径,requestOptions 在 v2.0 中已完全适配。
基本用法
vue
<template>
<!-- ChatBot 和 AIBlueking 用法一致 -->
<ChatBot
url="/api/v1/agent/chat"
:request-options="requestOptions"
/>
</template>
<script setup lang="ts">
import { ChatBot } from '@blueking/ai-blueking';
const requestOptions = {
headers: () => ({
Authorization: `Bearer ${getToken()}`,
'X-App-Code': 'my-application',
}),
data: () => ({
app_id: 'your-app',
tenant_id: 'default',
}),
};
</script>AIBlueking 完全一致:
vue
<template>
<AIBlueking
url="/api/v1/agent/chat"
:request-options="requestOptions"
/>
</template>
<script setup lang="ts">
import { AIBlueking } from '@blueking/ai-blueking';
const requestOptions = {
headers: () => ({
Authorization: `Bearer ${getToken()}`,
'X-App-Code': 'my-application',
}),
};
</script>说明
headers/data在每次请求前通过resolveRequestValue求值,支持普通对象、零参函数、ref、computedheaders合并到每个请求的 HTTP 头data按方法自动分流:POST/PUT/PATCH/DELETE → 合并进 body;GET/HEAD/OPTIONS → 合并进 query(params)。在 Network 面板中,会话列表等 GET 应在 URL 上看到app_id等字段,发消息 POST 应在 Request Payload 中看到- 外层
requestOptions可为ref/computed,整体替换后同样生效(无需销毁重建ChatBot/AIBlueking) - 直接使用
@blueking/chat-helper时,在useChatHelper({ requestData: { headers, data } })中使用相同类型与分流规则
响应式示例(ref / computed)
推荐
需要随登录态、租户切换而更新时,优先使用内层 computed,或外层 computed<IRequestOptions>,比仅依赖函数闭包更直观。
vue
<template>
<AIBlueking url="/api/v1/agent/chat" :request-options="requestOptions" />
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { AIBlueking, type IRequestOptions } from '@blueking/ai-blueking';
const token = ref('token-alpha');
const appId = ref('my-app');
const tenantId = ref('tenant-001');
const requestOptions = computed<IRequestOptions>(() => ({
headers: {
Authorization: `Bearer ${token.value}`,
},
data: {
app_id: appId.value,
tenant_id: tenantId.value,
},
}));
// 切换 token / app_id 后,下一次 getAgentInfo、getSessions、发消息等请求即携带新值
</script>内层字段也可单独使用 computed:
typescript
const requestOptions: IRequestOptions = {
headers: computed(() => ({ Authorization: `Bearer ${token.value}` })),
data: { locale: 'zh-cn' },
};useChatBootstrap + ChatBot 组合模式
当需要更精细的控制时(如在 ChatBot 外部管理初始化流程、共享 chatHelper 给其他组件),可以使用 useChatBootstrap 创建 chatHelper 实例,再以集成模式传入 ChatBot。
这也是 AIBlueking 内部使用 ChatBot 的方式。
基本用法
vue
<template>
<div style="height: 600px;">
<ChatBot
v-if="isReady"
:chat-helper="chatHelper"
:url="url"
/>
<div v-else>初始化中...</div>
</div>
</template>
<script setup lang="ts">
import { ChatBot, useChatBootstrap } from '@blueking/ai-blueking';
const url = '/api/v1/agent/chat';
const {
chatHelper,
isReady,
agentInfo,
sessionList,
currentSession,
} = useChatBootstrap({
url,
requestOptions: {
headers: () => ({
Authorization: `Bearer ${getToken()}`,
}),
},
autoInit: true, // 自动执行 getAgentInfo + getSessions
});
</script>useChatBootstrap 返回值
| 属性/方法 | 类型 | 说明 |
|---|---|---|
chatHelper | IChatHelper | SDK 实例(同步创建,生命周期内不变) |
protocol | AGUIProtocol | 流式协议实例 |
isReady | ComputedRef<boolean> | Agent 信息是否加载完成 |
isInitializing | ComputedRef<boolean> | 是否正在初始化中 |
phase | Ref<BootstrapPhase> | 当前阶段:IDLE → LOADING_AGENT → READY / ERROR |
error | Ref<Error | null> | 初始化错误 |
agentInfo | ComputedRef<IAgentInfo | null> | Agent 配置信息 |
agentName | ComputedRef<string> | Agent 名称 |
sessionList | ComputedRef<ISession[]> | 会话列表 |
currentSession | ComputedRef<ISession | null> | 当前会话 |
initialize() | () => Promise<void> | 手动触发初始化 |
retry() | () => Promise<void> | 重试初始化 |
updateConfig(url) | (url: string) => Promise<void> | 更新 URL 并重新初始化 |
ChatBot 的两种模式
| 特性 | 独立模式 <ChatBot url="..."> | 集成模式 <ChatBot :chat-helper="helper"> |
|---|---|---|
| chatHelper 来源 | 内部自动创建 | 外部传入(如 useChatBootstrap) |
| 初始化 | 自动执行 getAgentInfo → getSessions → chooseSession | 跳过,复用外部已初始化的实例 |
| 适用场景 | 简单嵌入,快速集成 | 需要外部控制会话、共享实例 |
| 常用于 | 独立页面嵌入 | AIBlueking 内部、自定义会话列表 |
与 AIBlueking 配合
AIBlueking 内部就是用 useChatBootstrap + ChatBot 集成模式运作的。如果你需要完全自定义面板 UI(不用 AIBlueking 的浮球/拖拽),可以直接使用同样的模式:
vue
<template>
<div class="my-custom-panel">
<!-- 自定义的会话列表 -->
<aside>
<div v-for="s in sessionList" :key="s.sessionCode">{{ s.sessionName }}</div>
</aside>
<!-- ChatBot 作为聊天区域 -->
<main>
<ChatBot
v-if="isReady"
:chat-helper="chatHelper"
:url="url"
/>
</main>
</div>
</template>
<script setup lang="ts">
import { watch } from 'vue';
import { ChatBot, useChatBootstrap, SessionBusinessManager } from '@blueking/ai-blueking';
const url = '/api/chat';
const { chatHelper, isReady, sessionList, agentInfo } = useChatBootstrap({
url,
requestOptions: {
headers: () => ({ Authorization: `Bearer ${getToken()}` }),
},
});
// 创建 SessionBusinessManager 来管理会话(和 AIBlueking 内部做法一致)
const sessionManager = new SessionBusinessManager(
chatHelper.session,
chatHelper.agent,
);
// isReady 后加载最近会话
watch(isReady, async (ready) => {
if (ready) {
await sessionManager.loadRecentSession({ skipLoadSessions: true });
}
});
</script>拦截器
拦截器允许你在请求发出前和响应返回后执行自定义逻辑,适用于统一的错误处理、日志记录、数据转换等场景。
typescript
const chatHelper = useChatHelper({
interceptors: {
request: (config) => {
// 请求发出前的处理
console.log('[请求]', config.url, config.method);
// 可以修改 config 后返回
config.headers['X-Timestamp'] = Date.now().toString();
return config;
},
response: (response) => {
// 响应返回后的处理
console.log('[响应]', response.status, response.data);
// 统一错误处理
if (response.data.code !== 0) {
showError(response.data.message);
}
return response;
},
},
});请求拦截器
请求拦截器在每次 HTTP 请求发出之前执行:
typescript
interceptors: {
request: (config) => {
// config 包含:url, method, headers, data 等
// 必须返回修改后的 config
return config;
},
}常见用途:
- 添加认证信息
- 注入追踪 ID
- 请求日志记录
- 请求数据转换
响应拦截器
响应拦截器在每次 HTTP 响应返回之后执行:
typescript
interceptors: {
response: (response) => {
// response 包含:status, data, headers 等
// 必须返回 response
return response;
},
}常见用途:
- 统一错误码处理
- 响应数据转换
- 响应日志记录
- Token 过期自动刷新
完整拦截器示例
typescript
const chatHelper = useChatHelper({
interceptors: {
request: (config) => {
// 1. 注入追踪 ID
config.headers['X-Request-Id'] = crypto.randomUUID();
// 2. 记录请求日志
console.log(`[${config.method?.toUpperCase()}] ${config.url}`);
return config;
},
response: (response) => {
// 1. 统一错误处理
if (response.data?.code !== 0) {
const msg = response.data?.message || '请求失败';
// 特殊错误码处理
if (response.data?.code === 401) {
// Token 过期,跳转登录
redirectToLogin();
} else {
showError(msg);
}
}
// 2. 记录响应日志
console.log(`[响应] 状态码: ${response.status}`);
return response;
},
},
});动态请求头
在实际项目中,请求头往往需要动态生成。以下是几种常见场景:
Token 刷新
typescript
const requestOptions = {
headers: () => {
// 每次请求都获取最新 token
const token = tokenManager.getAccessToken();
return {
Authorization: `Bearer ${token}`,
};
},
};请求追踪 ID
typescript
const requestOptions = {
headers: () => ({
Authorization: `Bearer ${getToken()}`,
'X-Request-Id': crypto.randomUUID(), // 每次请求唯一 ID
'X-Trace-Id': getTraceId(), // 链路追踪 ID
'X-Client-Timestamp': Date.now().toString(), // 客户端时间戳
}),
};基于环境的配置
typescript
const requestOptions = {
headers: () => {
const base: Record<string, string> = {
'X-App-Code': APP_CODE,
};
// 开发环境添加调试头
if (import.meta.env.DEV) {
base['X-Debug-Mode'] = 'true';
base['X-Dev-User'] = 'developer';
}
return base;
},
data: () => ({
env: import.meta.env.MODE,
version: APP_VERSION,
}),
};综合示例
以下是一个包含认证、动态头部的完整配置示例:
vue
<template>
<AIBlueking
url="/api/v1/agent/chat"
:request-options="requestOptions"
/>
</template>
<script setup lang="ts">
import { AIBlueking } from '@blueking/ai-blueking';
import { useAuth } from '@/composables/auth';
import { useNotification } from '@/composables/notification';
const { getToken, refreshToken } = useAuth();
const { showError } = useNotification();
const requestOptions = {
headers: () => ({
// 动态获取最新 token
Authorization: `Bearer ${getToken()}`,
// 追踪信息
'X-Request-Id': crypto.randomUUID(),
'X-App-Code': 'my-application',
}),
data: () => ({
// 附加到每个请求的业务数据
app_id: 'my-app',
tenant_id: getCurrentTenant(),
locale: getCurrentLocale(),
}),
};
</script>