useLensAgent Hook
核心 React Hook,管理 Agent 對話狀態
概述
useLensAgent 是 Lens OS SDK 提供的核心 React Hook,提供完整的 Agent 互動功能:發送訊息、接收串流回應、管理對話歷史等。
基本用法
基本範例
import { useLensAgent } from "@lens-os/sdk/react";
function Chat() {
const {
messages,
isLoading,
sendMessage,
newSession,
} = useLensAgent({
endpoint: "/api/lens/agent/chat",
userId: "user-123",
});
return (
<div>
{messages.map((msg, i) => (
<div key={i}>{msg.content}</div>
))}
<button onClick={() => sendMessage("Hello!")}>
Send
</button>
</div>
);
}API 參考
Options(選項)
Options
interface UseLensAgentOptions {
// 必填
endpoint: string; // Chat API 路徑
// 選填
userId?: string; // 用戶識別碼(可由伺服器端注入)
onEvent?: (event: SSEEvent) => void; // 事件回調
}| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
endpoint | string | 是 | Chat API 路徑,例如 "/api/lens/agent/chat" |
userId | string | 否 | 用戶識別碼(可由伺服器端注入) |
onEvent | function | 否 | SSE 事件回調函式 |
Return Value(回傳值)
Return
interface UseLensAgentReturn {
// 狀態
messages: Message[]; // 對話訊息
isLoading: boolean; // 是否執行中
isInitialized: boolean; // SDK 是否初始化
sessionId: string; // 目前 Session ID
error: Error | null; // 最後一個錯誤
// 方法
sendMessage: (message: string, context?: MessageContext) => Promise<void>;
abort: () => void; // 取消目前執行
newSession: () => void; // 開始新對話
loadSession: (sessionId: string, messages: Message[]) => void;
}狀態說明
messages
對話訊息陣列,每則訊息格式如下:
Message
interface Message {
role: "user" | "assistant" | "system" | "tool";
content: string | MessageContent[];
timestamp?: Date;
}isLoading
當 Agent 正在處理訊息時為 true,可用於:
- 顯示載入指示器
- 禁用送出按鈕
- 切換停止按鈕
sessionId
目前對話的唯一識別碼,每次呼叫 newSession() 會產生新的 ID。
方法說明
sendMessage
發送訊息給 Agent:
sendMessage
// 基本用法
await sendMessage("幫我找 TypeScript 的書");
// 帶上下文(用於頁面擷取)
await sendMessage("點擊搜尋按鈕", {
currentUrl: window.location.href,
pageState: {
url: "...",
title: "...",
markdown: "...",
screenshot: "...",
actionableElements: [...],
},
});abort
取消正在執行的請求:
abort
<button onClick={isLoading ? abort : handleSend}>
{isLoading ? "停止" : "送出"}
</button>newSession
開始新對話,清除目前訊息:
newSession
<button onClick={newSession}>新對話</button>loadSession
載入歷史對話:
loadSession
const handleLoad = async (targetSessionId: string) => {
const res = await fetch(`/api/lens/agent/sessions/${targetSessionId}`);
const data = await res.json();
if (data.success) {
loadSession(targetSessionId, data.messages);
}
};事件處理
使用 onEvent 回調處理 SSE 事件:
onEvent
const { messages } = useLensAgent({
endpoint: "/api/lens/agent/chat",
userId: "user-123",
onEvent: (event) => {
switch (event.type) {
case "tool_call":
console.log("Tool started:", event.name);
// 顯示 Tool Card
break;
case "tool_result":
console.log("Tool completed:", event.name, event.result);
// 更新 Tool Card
break;
case "text":
console.log("Text:", event.content);
break;
case "error":
console.error("Error:", event.error);
break;
case "done":
console.log("Completed");
break;
}
},
});事件類型說明:
tool_call:Agent 開始執行工具,可用於顯示 Tool Cardtool_result:工具執行完成,可用於更新 Tool Card 狀態text:文字內容更新error:發生錯誤done:對話回合完成
完整範例
以下是一個包含所有功能的完整聊天元件範例:
Chat.tsx
"use client";
import { useState, useRef, useEffect } from "react";
import { useLensAgent } from "@lens-os/sdk/react";
export function Chat({ userId }: { userId: string }) {
const [input, setInput] = useState("");
const messagesEndRef = useRef<HTMLDivElement>(null);
const {
messages,
isLoading,
error,
sendMessage,
abort,
newSession,
} = useLensAgent({
endpoint: "/api/lens/agent/chat",
userId,
onEvent: (event) => {
if (event.type === "tool_call") {
console.log("Tool:", event.name);
}
},
});
// 自動捲動
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
const handleSend = async () => {
if (!input.trim() || isLoading) return;
const message = input;
setInput("");
await sendMessage(message);
};
return (
<div className="flex flex-col h-full">
{/* 訊息區 */}
<div className="flex-1 overflow-auto p-4 space-y-4">
{messages.map((msg, i) => (
<div
key={i}
className={msg.role === "user" ? "text-right" : "text-left"}
>
<span className={`inline-block p-3 rounded-lg ${
msg.role === "user" ? "bg-blue-500 text-white" : "bg-gray-100"
}`}>
{typeof msg.content === "string" ? msg.content : "..."}
</span>
</div>
))}
{isLoading && <div className="text-gray-500">思考中...</div>}
{error && <div className="text-red-500">錯誤:{error.message}</div>}
<div ref={messagesEndRef} />
</div>
{/* 輸入區 */}
<div className="border-t p-4 flex gap-2">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && handleSend()}
placeholder="輸入訊息..."
className="flex-1 border rounded px-3 py-2"
/>
<button
onClick={isLoading ? abort : handleSend}
className="bg-blue-500 text-white px-4 py-2 rounded"
>
{isLoading ? "停止" : "送出"}
</button>
<button
onClick={newSession}
className="border px-4 py-2 rounded"
>
新對話
</button>
</div>
</div>
);
}Tip
這個範例展示了基本的聊天功能。若需要更完整的元件(含 Tool Cards、Rules 選單),請參考「聊天元件」文檔。