import{_ as i,o as a,c as e,a4 as t}from"./chunks/framework.Cre9sSJa.js";const c=JSON.parse('{"title":"原子组件组装","description":"","frontmatter":{},"headers":[],"relativePath":"guide/integration-modes/atomic-composition.md","filePath":"guide/integration-modes/atomic-composition.md"}'),n={name:"guide/integration-modes/atomic-composition.md"};function h(l,s,p,o,k,r){return a(),e("div",null,[...s[0]||(s[0]=[t(`<h1 id="原子组件组装" tabindex="-1">原子组件组装 <a class="header-anchor" href="#原子组件组装" aria-label="Permalink to &quot;原子组件组装&quot;">​</a></h1><p>当 <code>ChatBot</code> 或 <code>AIBlueking</code> 无法满足定制化需求时，可以直接使用 <code>@blueking/chat-x</code> 的原子 UI 与 <code>@blueking/chat-helper</code> 的 SDK 组装业务，获得最大的布局与交互自由度。</p><h2 id="适用场景" tabindex="-1">适用场景 <a class="header-anchor" href="#适用场景" aria-label="Permalink to &quot;适用场景&quot;">​</a></h2><ul><li>需要非标准布局（左右分栏、嵌入复杂页面等）</li><li>需要替换默认输入区、消息气泡、工具栏等行为</li><li>需要将对话能力与现有状态管理深度整合</li></ul><h2 id="何时不应使用" tabindex="-1">何时不应使用 <a class="header-anchor" href="#何时不应使用" aria-label="Permalink to &quot;何时不应使用&quot;">​</a></h2><p>原子模式需要<strong>自行</strong>完成初始化、生命周期与状态映射，复杂度高。若只需嵌入聊天窗口或完整面板，优先：</p><ul><li><a href="./chatbot-embedded.html">ChatBot 页面嵌入模式</a></li><li><a href="./aiblueking-floating.html">AIBlueking 浮窗模式</a></li></ul><h2 id="组装步骤-与-chat-helper-当前-api-对齐" tabindex="-1">组装步骤（与 chat-helper 当前 API 对齐） <a class="header-anchor" href="#组装步骤-与-chat-helper-当前-api-对齐" aria-label="Permalink to &quot;组装步骤（与 chat-helper 当前 API 对齐）&quot;">​</a></h2><h3 id="_1-创建-aguiprotocol-与-usechathelper" tabindex="-1">1. 创建 <code>AGUIProtocol</code> 与 <code>useChatHelper</code> <a class="header-anchor" href="#_1-创建-aguiprotocol-与-usechathelper" aria-label="Permalink to &quot;1. 创建 \`AGUIProtocol\` 与 \`useChatHelper\`&quot;">​</a></h3><p><a href="__DOCS_BASE__/guide/core-features/chat-interaction.html#流式响应"><code>AGUIProtocol</code></a> 构造函数<strong>仅</strong>接收可选回调（<code>onStart</code> / <code>onMessage</code> / <code>onDone</code> / <code>onError</code>），<strong>不要</strong>传入 <code>baseURL</code>。HTTP 基址放在 <code>requestData.urlPrefix</code>。</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AGUIProtocol, useChatHelper } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@blueking/chat-helper&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> protocol</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AGUIProtocol</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  onError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">err</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(err),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> chatHelper</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useChatHelper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  requestData: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    urlPrefix: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;https://your-api.example/api/&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">    headers</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({ Authorization: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Bearer \${</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getToken</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  protocol,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="_2-注入消息模块-必须" tabindex="-1">2. 注入消息模块（必须） <a class="header-anchor" href="#_2-注入消息模块-必须" aria-label="Permalink to &quot;2. 注入消息模块（必须）&quot;">​</a></h3><p>在首次发起流式请求前调用（建议在 <code>onMounted</code> 内、<code>getAgentInfo</code> 之前亦可）：</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">protocol.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">injectMessageModule</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(chatHelper.message);</span></span></code></pre></div><p><code>AGUIProtocol</code> 依赖 <code>IMessageModule</code> 将 <code>TEXT_MESSAGE_*</code> 等事件落到消息列表；遗漏会导致流式内容无法显示。</p><h3 id="_3-初始化会话" tabindex="-1">3. 初始化会话 <a class="header-anchor" href="#_3-初始化会话" aria-label="Permalink to &quot;3. 初始化会话&quot;">​</a></h3><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getAgentInfo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.session.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getSessions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> first</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.session.list.value[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (first?.sessionCode) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.session.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">chooseSession</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(first.sessionCode);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">} </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.session.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createSession</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    { sessionCode: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`new_\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">Date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">now</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">()</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, sessionName: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;新会话&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    { loadMessages: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>注意：会话列表字段为 <code>session.list</code>，切换会话为 <code>chooseSession</code>，<strong>不是</strong> <code>sessions</code> / <code>switchSession</code>。</p><h3 id="_4-连接-chat-x-组件" tabindex="-1">4. 连接 chat-x 组件 <a class="header-anchor" href="#_4-连接-chat-x-组件" aria-label="Permalink to &quot;4. 连接 chat-x 组件&quot;">​</a></h3><ul><li>使用 <code>chatHelper.message.list</code> 作为 <code>MessageContainer</code> 的 <code>messages</code></li><li>用 <code>chatHelper.agent.isChatting</code> 映射 <code>MessageStatus</code> / <code>MessageToolsStatus</code>（与 ChatBot 内部 composable 逻辑一致）</li><li>发送消息使用 <strong><code>chatHelper.agent.chat(content, sessionCode, ...)</code></strong>，由 SDK 负责创建用户消息并打开 SSE；不要与旧文档中的 <code>message.sendMessage</code> 混淆</li></ul><p><code>MessageContainer</code>、<code>ChatInput</code> 的交互以 <strong>props 回调</strong> 为准（如 <code>onAgentAction</code>、<code>onSendMessage</code>），不是早期示例里的 <code>@cite</code> / <code>@send</code> 等自定义事件。</p><h3 id="_5-卸载清理" tabindex="-1">5. 卸载清理 <a class="header-anchor" href="#_5-卸载清理" aria-label="Permalink to &quot;5. 卸载清理&quot;">​</a></h3><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { onBeforeUnmount } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onBeforeUnmount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> code</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.session.current.value?.sessionCode;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  chatHelper.agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">abortChat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (code) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> chatHelper.agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stopChat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(code);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>当前 <code>AGUIProtocol</code> <strong>没有</strong> <code>destroy()</code> 方法；以中止请求 + 可选 <code>stopChat</code> 为主。</p><h2 id="可运行示例与-mock" tabindex="-1">可运行示例与 Mock <a class="header-anchor" href="#可运行示例与-mock" aria-label="Permalink to &quot;可运行示例与 Mock&quot;">​</a></h2><p><a href="__DOCS_BASE__/demos/atomic-assembly.html">原子组件组装示例</a> 内嵌演示<strong>不模拟</strong>小鲸初始化接口，仅 Mock <code>session_content</code> + <code>chat_completion</code>（AG-UI SSE），用于验证流式解析与 chat-x 渲染；真实 <code>urlPrefix</code> 请对接网关（如 <code>BK_API_GATEWAY_NAME</code> 等环境变量）。</p><h2 id="延伸阅读" tabindex="-1">延伸阅读 <a class="header-anchor" href="#延伸阅读" aria-label="Permalink to &quot;延伸阅读&quot;">​</a></h2><ul><li><a href="__DOCS_BASE__/guide/architecture.html">架构概览</a> — chat-x / chat-helper / ai-blueking 边界</li><li><a href="__DOCS_BASE__/guide/advanced-usage/custom-requests.html">自定义请求</a> — <code>requestData</code>、拦截器</li><li><a href="__DOCS_BASE__/guide/core-features/chat-interaction.html">聊天交互</a> — <code>AGUIProtocol</code>、AG-UI 事件类型、流式响应</li><li><a href="__DOCS_BASE__/api/chat-helper/sdk.html">chat-helper SDK API</a> — <a href="__DOCS_BASE__/api/chat-helper/sdk.html"><code>useChatHelper</code></a>、<code>EventType</code> 等完整接口</li></ul>`,28)])])}const E=i(n,[["render",h]]);export{c as __pageData,E as default};
