threads

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Threads 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

生成阶段

StageDescription
IDLE
Not generating
CHOOSING_COMPONENT
Selecting which component to use
FETCHING_CONTEXT
Calling registered tools
HYDRATING_COMPONENT
Generating component props
STREAMING_RESPONSE
Actively streaming
COMPLETE
Finished successfully
ERROR
Error occurred
阶段名称描述
IDLE
未生成内容
CHOOSING_COMPONENT
选择要使用的组件
FETCHING_CONTEXT
调用已注册的工具
HYDRATING_COMPONENT
生成组件属性
STREAMING_RESPONSE
正在流式返回内容
COMPLETE
已成功完成
ERROR
发生错误

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返回值

PropertyTypeDescription
startRecording
() => void
Start recording, reset transcript
stopRecording
() => void
Stop and start transcription
isRecording
boolean
Currently recording
isTranscribing
boolean
Processing audio
transcript
string | null
Transcribed text
transcriptionError
string | null
Transcription error
mediaAccessError
string | null
Mic access error
属性名称类型描述
startRecording
() => void
开始录制,重置转录内容
stopRecording
() => void
停止录制并开始转录
isRecording
boolean
当前是否正在录制
isTranscribing
boolean
正在处理音频转录
transcript
string | null
转录后的文本
transcriptionError
string | null
转录错误信息
mediaAccessError
string | null
媒体设备访问错误信息

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返回值

PropertyTypeDescription
images
StagedImage[]
Staged images ready to send
addImage
(file: File) => Promise<void>
Add single image (throws if not image)
addImages
(files: File[]) => Promise<void>
Add multiple (only valid images kept)
removeImage
(id: string) => void
Remove by ID
clearImages
() => void
Remove all
属性名称类型描述
images
StagedImage[]
已准备好发送的待上传图片
addImage
(file: File) => Promise<void>
添加单张图片(非图片文件会抛出错误)
addImages
(files: File[]) => Promise<void>
添加多张图片(仅保留有效图片)
removeImage
(id: string) => void
根据ID移除图片
clearImages
() => void
移除所有图片

User Authentication

用户身份验证

Enable per-user thread isolation with
userToken
:
tsx
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
userToken
, each user sees only their own threads. Supports Auth0, Clerk, Supabase, WorkOS, and any OAuth 2.0 provider with JWT tokens.
通过
userToken
实现按用户隔离线程:
tsx
import { TamboProvider } from "@tambo-ai/react";

function App() {
  const userToken = useUserToken(); // 从你的身份验证提供商获取(Auth0、Clerk等)

  return (
    <TamboProvider userToken={userToken}>
      <Chat />
    </TamboProvider>
  );
}
设置
userToken
后,每个用户只能看到自己的线程。支持Auth0、Clerk、Supabase、WorkOS,以及任何支持JWT令牌的OAuth 2.0提供商。