Skip to content

自定义请求

AI 小鲸 v2.0 提供了灵活的请求自定义能力,允许你配置请求头、请求体等,以适配不同的后端服务和认证方案。

requestOptions 属性

ChatBotAIBlueking 组件都接受 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

  1. ChatBot 独立模式:内部通过 useChatHelper({ requestData: { urlPrefix, headers, data } }) 创建 SDK 实例,requestOptions.headers/data 会直接映射到 requestData.headers/data
  2. AIBlueking:内部通过 useChatBootstrap({ url, requestOptions }) 初始化,同样映射到 useChatHelperrequestData

两种组件底层走的是同一条路径,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 求值,支持普通对象、零参函数、refcomputed
  • headers 合并到每个请求的 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 返回值

属性/方法类型说明
chatHelperIChatHelperSDK 实例(同步创建,生命周期内不变)
protocolAGUIProtocol流式协议实例
isReadyComputedRef<boolean>Agent 信息是否加载完成
isInitializingComputedRef<boolean>是否正在初始化中
phaseRef<BootstrapPhase>当前阶段:IDLELOADING_AGENTREADY / ERROR
errorRef<Error | null>初始化错误
agentInfoComputedRef<IAgentInfo | null>Agent 配置信息
agentNameComputedRef<string>Agent 名称
sessionListComputedRef<ISession[]>会话列表
currentSessionComputedRef<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>

All Rights Reserved. 腾讯蓝鲸 版权所有