REFERENCE
SDK 範例
@asgard-js/core 與 @asgard-js/react 的用法與可以直接操作的範例。
自訂 Footer
用 renderFooter 完全取代預設 footer。當你需要客製整個輸入區(例如改成
單行 input、加上自製語音按鈕、改變排版邏輯)時用它;只是想在送出按鈕
後面加額外按鈕,請改用 footerEndActions。
取代的內建功能
renderFooter是完全取代而不是疊加:- 內建
textarea與自動高度 - 送出按鈕、麥克風按鈕
- 圖片上傳、文件上傳、export 對話紀錄
- Drag-and-drop 上傳整合
- IME 組字保護(避免中文打字途中按 Enter 直接送出)
footerEndActions槽位
以上元件全部不再渲染,由 renderer 自己負責。
- 內建
程式範例
import {
Chatbot,
useAsgardContext,
type ChatbotRef,
} from "@asgard-js/react";
import { useEffect, useRef, useState } from "react";
function MyFooter() {
const {
sendMessage,
isConnecting,
isStopping,
pendingInputValue,
setPendingInputValue,
inputPlaceholder,
} = useAsgardContext();
const [value, setValue] = useState("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
// 接收外部透過 ChatbotRef.setInputValue 塞進來的文字
useEffect(() => {
if (pendingInputValue == null) return;
setValue(pendingInputValue);
setPendingInputValue(null);
textareaRef.current?.focus();
}, [pendingInputValue, setPendingInputValue]);
const submit = () => {
const text = value.trim();
// 同時擋 isStopping:舊的 run 還沒真的結束,這時送出會有兩個 run
// 並行寫進同一份對話紀錄。草稿保留,不要清掉。
if (!text || isConnecting || isStopping) return;
sendMessage?.({ text });
setValue("");
};
return (
<div className="footer">
<textarea
ref={textareaRef}
placeholder={inputPlaceholder}
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyDown={(e) => {
// IME 組字途中不送出
if (
e.key === "Enter" &&
!e.shiftKey &&
!e.nativeEvent.isComposing
) {
e.preventDefault();
submit();
}
}}
rows={1}
/>
<button
onClick={submit}
disabled={!value.trim() || isConnecting || isStopping}
>
送出
</button>
</div>
);
}
function Demo() {
const chatbotRef = useRef<ChatbotRef>(null);
return (
<Chatbot
ref={chatbotRef}
renderFooter={() => <MyFooter />}
{...rest}
/>
);
}換掉 footer 就要自己處理停止生成內建 footer 已經處理好停止的整段流程;一旦你用
renderFooter接管,那些就都變成你的責任。 兩條規則:每個送出入口都要同時擋isStopping(不是只擋isConnecting),而且 只有canStop為真時才顯示停止控制——isConnecting一詞四義,其中只有使用者自己的回合可以停。完整說明見停止生成。
useAsgardContext常用欄位欄位 型別 說明 sendMessage(params) => void送出訊息; undefined代表 preview / 未連線isConnectingboolean是否正在等待回覆,建議用它禁用送出按鈕 isStoppingboolean已要求停止、終止事件尚未抵達;送出入口也要一起擋 canStopboolean目前這個 run 可不可以停——只有它為真時才顯示停止控制 canForceStopboolean停止逾時,可升級為強制停止(隱含 isStopping)stopGeneration(opts?) => Promise<void>要求後端暫停目前的 run pendingInputValuestring | null外部透過 ChatbotRef.setInputValue推進來的文字setPendingInputValue(v: string | null) => void消化掉 pending 值後請把它清成 nullinputPlaceholderstringChatbot props 傳入的 placeholder messagesMap<string, ConversationMessage>所有訊息(如果你要做 token 計數等用途) 與
renderMenu/ChatbotRef.setInputValue串接這個 demo 同時用了
renderMenu列出快速提問。按鈕透過chatbotRef.current?.setInputValue(prompt)把文字塞進 SDK 內部的pendingInputValue,再由你的自訂 footer 消化掉,做到「點選 → 文字填入 輸入框 → 使用者再決定要不要送」的流程。什麼時候不要用
renderFooter- 只想在送出鈕旁加按鈕:用
footerEndActions, 內建邏輯完全保留。 - 完全跳過 Chatbot UI:用 Headless 模式,自己組裝整個畫面。
- 只想在送出鈕旁加按鈕:用