threads
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseThreads and Input
线程与输入
Manages conversations, suggestions, voice input, and image attachments.
管理对话、建议、语音输入和图片附件。
Quick Start
快速开始
tsx
const { thread, sendThreadMessage, isIdle } = useTamboThread();
await sendThreadMessage("Hello", { streamResponse: true });tsx
const { thread, sendThreadMessage, isIdle } = useTamboThread();
await sendThreadMessage("Hello", { streamResponse: true });Thread Management
线程管理
Access and manage the current thread:
tsx
import { useTamboThread } from "@tambo-ai/react";
function Chat() {
const {
thread, // Current thread with messages
sendThreadMessage, // Send user message
isIdle, // True when not generating
generationStage, // Current stage (IDLE, STREAMING_RESPONSE, etc.)
switchCurrentThread, // Switch to different thread
inputValue, // Current input field value
setInputValue, // Update input field
} = useTamboThread();
const handleSend = async () => {
await sendThreadMessage(inputValue, { streamResponse: true });
setInputValue("");
};
return (
<div>
{thread?.messages.map((msg) => (
<div key={msg.id}>
{msg.content.map((part, i) =>
part.type === "text" ? <p key={i}>{part.text}</p> : null,
)}
{msg.renderedComponent}
</div>
))}
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleSend} disabled={!isIdle}>
Send
</button>
</div>
);
}访问并管理当前线程:
tsx
import { useTamboThread } from "@tambo-ai/react";
function Chat() {
const {
thread, // 当前包含消息的线程
sendThreadMessage, // 发送用户消息
isIdle, // 未生成内容时为true
generationStage, // 当前阶段(IDLE、STREAMING_RESPONSE等)
switchCurrentThread, // 切换到其他线程
inputValue, // 当前输入框的值
setInputValue, // 更新输入框内容
} = useTamboThread();
const handleSend = async () => {
await sendThreadMessage(inputValue, { streamResponse: true });
setInputValue("");
};
return (
<div>
{thread?.messages.map((msg) => (
<div key={msg.id}>
{msg.content.map((part, i) =>
part.type === "text" ? <p key={i}>{part.text}</p> : null,
)}
{msg.renderedComponent}
</div>
))}
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleSend} disabled={!isIdle}>
发送
</button>
</div>
);
}Generation Stages
生成阶段
| Stage | Description |
|---|---|
| Not generating |
| Selecting which component to use |
| Calling registered tools |
| Generating component props |
| Actively streaming |
| Finished successfully |
| Error occurred |
| 阶段名称 | 描述 |
|---|---|
| 未生成内容 |
| 选择要使用的组件 |
| 调用已注册的工具 |
| 生成组件属性 |
| 正在流式返回内容 |
| 已成功完成 |
| 发生错误 |
Thread List
线程列表
Manage multiple conversations:
tsx
import { useTamboThread, useTamboThreadList } from "@tambo-ai/react";
function ThreadSidebar() {
const { data: threads, isPending } = useTamboThreadList();
const { thread, switchCurrentThread } = useTamboThread();
if (isPending) return <Skeleton />;
return (
<ul>
{threads?.items.map((t) => (
<li key={t.id}>
<button
onClick={() => switchCurrentThread(t.id)}
className={thread?.id === t.id ? "active" : ""}
>
{t.name || "Untitled"}
</button>
</li>
))}
</ul>
);
}管理多个对话:
tsx
import { useTamboThread, useTamboThreadList } from "@tambo-ai/react";
function ThreadSidebar() {
const { data: threads, isPending } = useTamboThreadList();
const { thread, switchCurrentThread } = useTamboThread();
if (isPending) return <Skeleton />;
return (
<ul>
{threads?.items.map((t) => (
<li key={t.id}>
<button
onClick={() => switchCurrentThread(t.id)}
className={thread?.id === t.id ? "active" : ""}
>
{t.name || "无标题"}
</button>
</li>
))}
</ul>
);
}Suggestions
智能建议
AI-generated follow-up suggestions after each assistant message:
tsx
import { useTamboSuggestions } from "@tambo-ai/react";
function Suggestions() {
const { suggestions, isLoading, accept, isAccepting } = useTamboSuggestions({
maxSuggestions: 3, // 1-10, default 3
});
if (isLoading) return <Skeleton />;
return (
<div className="suggestions">
{suggestions.map((s) => (
<button
key={s.id}
onClick={() => accept(s)} // Sets input value
// onClick={() => accept(s, true)} // Sets and auto-submits
disabled={isAccepting}
>
{s.title}
</button>
))}
</div>
);
}每条助手消息后由AI生成的后续建议:
tsx
import { useTamboSuggestions } from "@tambo-ai/react";
function Suggestions() {
const { suggestions, isLoading, accept, isAccepting } = useTamboSuggestions({
maxSuggestions: 3, // 1-10,默认值为3
});
if (isLoading) return <Skeleton />;
return (
<div className="suggestions">
{suggestions.map((s) => (
<button
key={s.id}
onClick={() => accept(s)} // 设置输入框内容
// onClick={() => accept(s, true)} // 设置并自动提交
disabled={isAccepting}
>
{s.title}
</button>
))}
</div>
);
}Custom Suggestions
自定义建议
Override auto-generated suggestions:
tsx
const { setCustomSuggestions } = useTamboContextAttachment();
setCustomSuggestions([
{ id: "1", title: "Edit this", detailedSuggestion: "...", messageId: "" },
{ id: "2", title: "Add feature", detailedSuggestion: "...", messageId: "" },
]);
// Clear to return to auto-generated
setCustomSuggestions(null);覆盖自动生成的建议:
tsx
const { setCustomSuggestions } = useTamboContextAttachment();
setCustomSuggestions([
{ id: "1", title: "编辑此内容", detailedSuggestion: "...", messageId: "" },
{ id: "2", title: "添加功能", detailedSuggestion: "...", messageId: "" },
]);
// 清除自定义建议,恢复为自动生成
setCustomSuggestions(null);Voice Input
语音输入
Speech-to-text transcription:
tsx
import { useTamboVoice } from "@tambo-ai/react";
function VoiceButton() {
const {
startRecording,
stopRecording,
isRecording,
isTranscribing,
transcript,
transcriptionError,
mediaAccessError,
} = useTamboVoice();
return (
<div>
<button onClick={isRecording ? stopRecording : startRecording}>
{isRecording ? "Stop" : "Record"}
</button>
{isTranscribing && <span>Transcribing...</span>}
{transcript && <p>{transcript}</p>}
{transcriptionError && <p className="error">{transcriptionError}</p>}
</div>
);
}语音转文字转录功能:
tsx
import { useTamboVoice } from "@tambo-ai/react";
function VoiceButton() {
const {
startRecording,
stopRecording,
isRecording,
isTranscribing,
transcript,
transcriptionError,
mediaAccessError,
} = useTamboVoice();
return (
<div>
<button onClick={isRecording ? stopRecording : startRecording}>
{isRecording ? "停止" : "录制"}
</button>
{isTranscribing && <span>转录中...</span>}
{transcript && <p>{transcript}</p>}
{transcriptionError && <p className="error">{transcriptionError}</p>}
</div>
);
}Voice Hook Returns
语音Hook返回值
| Property | Type | Description |
|---|---|---|
| | Start recording, reset transcript |
| | Stop and start transcription |
| | Currently recording |
| | Processing audio |
| | Transcribed text |
| | Transcription error |
| | Mic access error |
| 属性名称 | 类型 | 描述 |
|---|---|---|
| | 开始录制,重置转录内容 |
| | 停止录制并开始转录 |
| | 当前是否正在录制 |
| | 正在处理音频转录 |
| | 转录后的文本 |
| | 转录错误信息 |
| | 媒体设备访问错误信息 |
Image Attachments
图片附件
Manage images in message input:
tsx
import { useMessageImages } from "@tambo-ai/react";
function ImageInput() {
const { images, addImage, addImages, removeImage, clearImages } =
useMessageImages();
const handleFiles = async (files: FileList) => {
await addImages(Array.from(files)); // Only valid images added
};
return (
<div>
<input
type="file"
accept="image/*"
multiple
onChange={(e) => handleFiles(e.target.files!)}
/>
{images.map((img) => (
<div key={img.id}>
<img src={img.preview} alt={img.file.name} />
<button onClick={() => removeImage(img.id)}>Remove</button>
</div>
))}
</div>
);
}管理消息输入中的图片:
tsx
import { useMessageImages } from "@tambo-ai/react";
function ImageInput() {
const { images, addImage, addImages, removeImage, clearImages } =
useMessageImages();
const handleFiles = async (files: FileList) => {
await addImages(Array.from(files)); // 仅添加有效的图片
};
return (
<div>
<input
type="file"
accept="image/*"
multiple
onChange={(e) => handleFiles(e.target.files!)}
/>
{images.map((img) => (
<div key={img.id}>
<img src={img.preview} alt={img.file.name} />
<button onClick={() => removeImage(img.id)}>移除</button>
</div>
))}
</div>
);
}Image Hook Returns
图片Hook返回值
| Property | Type | Description |
|---|---|---|
| | Staged images ready to send |
| | Add single image (throws if not image) |
| | Add multiple (only valid images kept) |
| | Remove by ID |
| | Remove all |
| 属性名称 | 类型 | 描述 |
|---|---|---|
| | 已准备好发送的待上传图片 |
| | 添加单张图片(非图片文件会抛出错误) |
| | 添加多张图片(仅保留有效图片) |
| | 根据ID移除图片 |
| | 移除所有图片 |
User Authentication
用户身份验证
Enable per-user thread isolation with :
userTokentsx
import { TamboProvider } from "@tambo-ai/react";
function App() {
const userToken = useUserToken(); // From your auth provider (Auth0, Clerk, etc.)
return (
<TamboProvider userToken={userToken}>
<Chat />
</TamboProvider>
);
}With , each user sees only their own threads. Supports Auth0, Clerk, Supabase, WorkOS, and any OAuth 2.0 provider with JWT tokens.
userToken通过实现按用户隔离线程:
userTokentsx
import { TamboProvider } from "@tambo-ai/react";
function App() {
const userToken = useUserToken(); // 从你的身份验证提供商获取(Auth0、Clerk等)
return (
<TamboProvider userToken={userToken}>
<Chat />
</TamboProvider>
);
}设置后,每个用户只能看到自己的线程。支持Auth0、Clerk、Supabase、WorkOS,以及任何支持JWT令牌的OAuth 2.0提供商。
userToken