Agent SDK AI 智能對話組件 金融資訊平台嵌入式聊天 iTick SDK & 開發工具 iTick 官方 Agent SDK,為金融資訊平台提供即插即用的 AI 對話能力,支援 ShadowDOM 樣式隔離、虛擬滾動、Markdown 渲染、流式 SSE 輸出、React/Vue 3 多框架封裝。
Agent SDK 文檔
iTick AI Chat SDK — 為金融資訊平台提供即插即用的 AI 對話能力。
核心特性
- ShadowDOM 樣式隔離 — 組件樣式完全隔離,不受宿主頁面 CSS 影響
- 虛擬滾動 — 支援萬級消息量的高效能渲染
- Markdown 渲染 — 內建 GFM 格式渲染,支援表格、程式碼高亮、流式輸出
- 多語言 — 內建簡體中文、繁體中文、英文
- 主題切換 — 支援亮色/暗色/跟隨系統三種模式
- 雙模式 — 極速模式(fast)與智能分析模式(think),支援執行時切換
- 流式 SSE — 基於 Server-Sent Events 的即時流式輸出,支援取消
- 消息分段 — 支援 think 與 content 交替流式輸出,每個 think 模組獨立狀態
- 框架無關 — 核心純 TypeScript,同時提供 React / Vue 3 封裝
安裝
# 核心包(必需)
npm install @itick/chat-core
# React 封裝(可選)
npm install @itick/chat-react
# Vue 3 封裝(可選)
npm install @itick/chat-vue
也可以透過 <script> 標籤直接引入 UMD 包:
<script src="https://unpkg.com/@itick/chat-core/dist/chat-core.umd.js"></script>
<script>
const sdk = new ChatSDK.ChatSDK({ /* ... */ });
</script>
快速接入
原生 JavaScript
import { ChatSDK } from '@itick/chat-core';
const sdk = new ChatSDK({
apiUrl: 'https://agent.itick.org/agent/stream/v1',
token: 'your-api-token',
container: document.getElementById('chat-container'),
width: '100%',
height: '600px',
});
// 監聽事件
sdk.on('message:receive', ({ message }) => {
console.log('收到消息:', message.content);
});
sdk.on('error', ({ error }) => {
console.error('請求出錯:', error);
});
// 掛載到頁面
sdk.mount();
React
import { ChatWidget, type ChatWidgetRef } from '@itick/chat-react';
import { useRef } from 'react';
function App() {
const chatRef = useRef<ChatWidgetRef>(null);
return (
<ChatWidget
ref={chatRef}
apiUrl="https://agent.itick.org/agent/stream/v1"
token="your-api-token"
width="100%"
height="600px"
locale="zh-TW"
onMessageReceive={({ message }) => console.log(message)}
/>
);
}
Vue 3
<template>
<ChatWidget
ref="chatRef"
:apiUrl="apiUrl"
:token="token"
width="100%"
height="600px"
locale="zh-TW"
@messageReceive="onReceive"
/>
</template>
<script setup>
import { ref } from 'vue';
import { ChatWidget } from '@itick/chat-vue';
const chatRef = ref();
const apiUrl = 'https://agent.itick.org/agent/stream/v1';
const token = 'your-api-token';
function onReceive({ message }) {
console.log(message);
}
</script>
核心配置
| 欄位 | 類型 | 必填 | 預設值 | 描述 |
|---|---|---|---|---|
apiUrl | string | 是 | - | 流式介面位址 |
token | string | 是 | - | 認證 token,透過 HTTP Header token 欄位傳遞 |
container | HTMLElement | 是 | - | 宿主 DOM 節點 |
width | number | string | 否 | 自適應容器 | 寬度,支援數字(px)或字串 |
height | number | string | 否 | 自適應容器 | 高度 |
themeColor | string | 否 | "#4F46E5" | 主題色 |
theme | 'light' | 'dark' | 'auto' | 否 | "light" | 主題模式 |
customCSS | string | 否 | - | 注入自訂 CSS |
locale | 'zh-CN' | 'zh-TW' | 'en-US' | 否 | - | 介面語言 |
placeholder | string | 否 | 由 i18n 決定 | 輸入框占位文字 |
mode | 'fast' | 'think' | 否 | "think" | 聊天模式 |
actions | ActionsConfig | 否 | 全部顯示 | 操作按鈕顯隱配置 |
disclaimer | string | 否 | 由 i18n 決定 | 免責聲明文字 |
welcomeTitle | string | 否 | 由 i18n 決定 | 空狀態歡迎標題 |
welcomeDescription | string | 否 | 由 i18n 決定 | 空狀態歡迎描述 |
presetQuestions | string[] | 否 | 6 個金融問題 | 空狀態預設問題 |
onQuestionClick | (q: string) => void | 否 | - | 預設問題點擊回調(SDK 已自動發送消息) |
onError | (error: Error) => void | 否 | - | 錯誤回調 |
renderHistoryMessage | (msg: ChatMessage) => HTMLElement | string | 否 | - | 歷史消息自訂渲染 |
renderActions | (msg: ChatMessage, callbacks: ActionCallbacks) => HTMLElement | undefined | 否 | - | 自訂操作按鈕(追加到預設按鈕後) |
ActionsConfig
| 欄位 | 類型 | 預設值 | 描述 |
|---|---|---|---|
showCopy | boolean | true | 顯示複製按鈕 |
showRegenerate | boolean | true | 顯示重新生成按鈕 |
showLike | boolean | true | 顯示點贊按鈕 |
showShare | boolean | true | 顯示分享按鈕 |
API 文檔
ChatSDK 實例方法
生命週期
| 方法 | 描述 |
|---|---|
mount() | 掛載到容器,建立 ShadowDOM 並渲染 UI。已銷毀時拋錯 |
unmount() | 移除 ShadowDOM,取消流式請求,保留實例和消息數據 |
destroy() | 徹底銷毀實例,清空所有資源和事件監聽 |
消息管理
| 方法 | 描述 |
|---|---|
sendMessage(content: string): Promise<void> | 發送消息,自動建立使用者和 AI 消息,發起流式請求 |
clearMessages() | 清空所有消息 |
getMessages(): ChatMessage[] | 取得消息列表副本 |
setHistoryMessages(messages: ChatMessage[]) | 設定歷史消息列表 |
配置管理
| 方法 | 描述 |
|---|---|
updateConfig(partial: Partial<ChatConfig>) | 動態修改配置,觸發 UI 更新 |
getConfig(): Readonly<ChatConfig> | 取得目前配置的唯讀副本 |
外掛管理
| 方法 | 描述 |
|---|---|
registerPlugin(plugin: MessageRenderPlugin) | 註冊消息渲染外掛 |
unregisterPlugin(name: string) | 註銷外掛 |
狀態屬性
| 屬性 | 類型 | 描述 |
|---|---|---|
isMounted | boolean | 是否已掛載 |
isDestroyed | boolean | 是否已銷毀 |
事件系統
透過 sdk.on(event, handler) 註冊事件監聽,sdk.off(event, handler) 移除。
生命週期事件
| 事件 | 參數 | 觸發時機 |
|---|---|---|
mount | 無 | mount() 完成後 |
unmount | 無 | unmount() 完成後 |
destroy | 無 | destroy() 完成後 |
消息事件
| 事件 | 參數 | 觸發時機 |
|---|---|---|
message:send | { content: string } | 使用者發送消息時 |
message:receive | { message: ChatMessage } | AI 消息流式完成後 |
message:streaming | { message: ChatMessage; chunk: string } | 每次收到 content chunk |
message:thinking | { message: ChatMessage; chunk: string } | 每次收到 think chunk |
message:done | { message: ChatMessage } | 流式輸出完成(含主動取消) |
操作事件
| 事件 | 參數 | 觸發時機 |
|---|---|---|
actions:copy | { messageId, content, message } | 點擊複製按鈕 |
actions:regenerate | { messageId, message } | 點擊重新生成按鈕 |
actions:like | { messageId, content, message } | 點擊點贊按鈕 |
actions:share | { messageId, content, message } | 點擊分享按鈕 |
其他事件
| 事件 | 參數 | 觸發時機 |
|---|---|---|
error | { error: Error } | 流式請求出錯時 |
config:change | { config: ChatConfig } | updateConfig() 呼叫後 |
使用範例
sdk.on('message:streaming', ({ chunk }) => {
console.log('收到流式片段:', chunk);
});
sdk.on('message:done', ({ message }) => {
console.log('消息完成:', message.content);
});
sdk.on('actions:copy', ({ content }) => {
console.log('使用者複製了:', content);
});
消息結構
interface ChatMessage {
id: string; // 唯一識別
role: 'user' | 'assistant' | 'system';
segments: MessageSegment[]; // think 與 content 按流順序混合排列
content: string; // 所有 content 段拼接(向後相容)
timestamp: number; // 時間戳
status?: 'sending' | 'streaming' | 'done' | 'error';
metadata?: Record<string, unknown>;
}
interface MessageSegment {
type: 'think' | 'content';
content: string;
status: 'streaming' | 'done';
}
segments 陣列按流式到達順序儲存 think 和 content 塊。例如:
[think] → [content] → [think] → [content] → ...
每個 think 模組擁有獨立的 streaming/done 狀態,完成後自動折疊。
進階功能
主題切換
// 初始化時設定
const sdk = new ChatSDK({ theme: 'auto', /* ... */ });
// 執行時切換
sdk.updateConfig({ theme: 'dark' });
支援三種模式:light(亮色)、dark(暗色)、auto(跟隨系統)。
國際化
const sdk = new ChatSDK({ locale: 'zh-TW', /* ... */ });
// 執行時切換
sdk.updateConfig({ locale: 'en-US' });
支援:zh-CN(簡體中文)、zh-TW(繁體中文)、en-US(英文)。
自訂 CSS
const sdk = new ChatSDK({
customCSS: `
.chat-message-user .chat-message-bubble {
border-radius: 20px;
}
`,
/* ... */
});
CSS 透過 ShadowDOM 注入,不會影響宿主頁面。可透過 CSS 變數覆蓋主題色:
--chat-primary: #4F46E5;
--chat-primary-hover: #4338CA;
操作按鈕訂製
const sdk = new ChatSDK({
// 隱藏部分按鈕
actions: {
showLike: false,
showShare: false,
},
// 新增自訂按鈕
renderActions: (message, callbacks) => {
const btn = document.createElement('button');
btn.textContent = '收藏';
btn.addEventListener('click', () => {
callbacks.onCopy(message.content);
});
return btn;
},
/* ... */
});
模式切換
使用者可在輸入框左下角切換極速模式(fast)和智能分析模式(think)。think 模式下會展示 AI 的思考過程。
// 初始化設定
const sdk = new ChatSDK({ mode: 'fast', /* ... */ });
// 執行時切換
sdk.updateConfig({ mode: 'think' });
消息渲染外掛
外掛可以覆蓋預設的 Markdown 渲染行為:
interface MessageRenderPlugin {
name: string;
match: (message: ChatMessage) => boolean;
render: (message: ChatMessage, shadowRoot: ShadowRoot) => HTMLElement;
update?: (element: HTMLElement, message: ChatMessage) => void;
}
sdk.registerPlugin({
name: 'code-highlight',
match: (msg) => msg.content.includes('```'),
render: (msg) => {
const el = document.createElement('div');
el.innerHTML = /* 自訂渲染邏輯 */;
return el;
},
update: (el, msg) => {
el.innerHTML = /* 流式更新邏輯 */;
},
});
// 註銷外掛
sdk.unregisterPlugin('code-highlight');
注意:註冊外掛會覆蓋內建的 Markdown 渲染。外掛按註冊順序從後往前匹配,後註冊的優先級更高。
歷史消息渲染
const sdk = new ChatSDK({
renderHistoryMessage: (message) => {
// 回傳 HTML 字串或 HTMLElement
return `<div class="custom-message">${message.content}</div>`;
},
/* ... */
});
預設問題
const sdk = new ChatSDK({
presetQuestions: [
'今日美股三大指數行情如何?',
'BTC/USDT 目前價格和24小時漲跌幅?',
],
onQuestionClick: (question) => {
console.log('使用者點擊了問題:', question);
// SDK 已自動發送消息,此處僅作為通知掛鉤
},
/* ... */
});
框架整合
React
Props
| 屬性 | 類型 | 必填 | 預設值 |
|---|---|---|---|
apiUrl | string | 是 | - |
token | string | 是 | - |
width | number | string | 否 | "100%" |
height | number | string | 否 | "600px" |
themeColor | string | 否 | "#4F46E5" |
customCSS | string | 否 | - |
locale | 'zh-CN' | 'zh-TW' | 'en-US' | 否 | "zh-TW" |
placeholder | string | 否 | - |
renderHistoryMessage | (msg: ChatMessage) => HTMLElement | string | 否 | - |
onMessageSend | (payload: { content: string }) => void | 否 | - |
onMessageReceive | (payload: { message: ChatMessage }) => void | 否 | - |
onMessageStreaming | (payload: { message: ChatMessage; chunk: string }) => void | 否 | - |
onMessageDone | (payload: { message: ChatMessage }) => void | 否 | - |
onError | (payload: { error: Error }) => void | 否 | - |
onConfigChange | (payload: { config: ChatConfig }) => void | 否 | - |
Ref 方法 (ChatWidgetRef)
| 方法 | 簽名 |
|---|---|
sendMessage | (content: string) => Promise<void> |
clearMessages | () => void |
getMessages | () => ChatMessage[] |
setHistoryMessages | (messages: ChatMessage[]) => void |
registerPlugin | (plugin: MessageRenderPlugin) => void |
unregisterPlugin | (name: string) => void |
updateConfig | (partial: Partial<ChatConfig>) => void |
getSDK | () => ChatSDK | null |
注意:
apiUrl、token、width、height的 prop 變化不會觸發熱更新,需要重新掛載組件。themeColor、customCSS、locale、placeholder支援熱更新。
Vue 3
Props
與 React 相同(不含回調類 props)。
Events
| 事件 | 參數 |
|---|---|
messageSend | { content: string } |
messageReceive | { message: ChatMessage } |
messageStreaming | { message: ChatMessage; chunk: string } |
messageDone | { message: ChatMessage } |
error | { error: Error } |
configChange | { config: ChatConfig } |
Expose 方法
與 React ChatWidgetRef 完全一致,額外包含 getSDK()。
介面格式
請求格式
SDK 發送 POST 請求到 apiUrl:
Headers:
Content-Type: application/json
token: {your-token}
Accept: text/event-stream
Body:
{
"input": {
"messages": [
{ "type": "human", "content": "使用者消息內容" }
]
},
"config": {
"configurable": {
"thread_id": "{uuid}",
"enable_thinking": true
}
}
}
thread_id在實例化時自動生成,用於服務端會話保持enable_thinking根據mode配置決定(think為true,fast為false)- 只發送
role === 'user'的消息
SSE 響應格式
服務端需回傳 Content-Type: text/event-stream,每條數據格式:
data: {"type": "think", "content": "思考過程..."}
data: {"type": "content", "content": "回覆內容..."}
data: [DONE]
type: "think"— 思考過程,SDK 將其渲染為可折疊的 think 模組type: "content"— 正式回覆內容,SDK 渲染為 Markdown 氣泡[DONE]— 流結束標記
同時相容 OpenAI 格式(choices[0].delta.content)。
開發除錯
# 安裝依賴
npm install
# 構建所有包
npm run build
# 程式碼檢查
npm run lint
常見問題
如何自訂樣式?
透過 customCSS 配置注入自訂 CSS,或透過 themeColor 設定主題色。所有樣式透過 ShadowDOM 隔離,CSS 變數名以 --chat- 為前綴。
如何處理錯誤?
透過 onError 配置或 error 事件監聽:
const sdk = new ChatSDK({
onError: (error) => { /* 處理錯誤 */ },
/* ... */
});
sdk.on('error', ({ error }) => {
console.error(error);
});
如何取消流式請求?
使用者點擊發送按鈕(流式輸出中會變為停止按鈕)即可取消。程式化取消可透過 sdk.unmount() 或 sdk.destroy()。
如何保留會話上下文?
thread_id 在實例化時生成,只要不呼叫 destroy() 重建實例,同一個實例的多次對話會共享 thread_id,服務端可據此保持會話上下文。
虛擬滾動是否影響消息渲染?
不影響。虛擬滾動僅優化 DOM 節點的建立和回收,消息內容透過 segments 和 content 欄位完整保留,操作按鈕和推薦問題在消息狀態變為 done 時自動追加。