mcpField
T
tanstack-ai

tanstack-ai

github.com/secondsky开发240235 次安装5 周前更新
代码仓库

关于 tanstack-ai

tanstack-ai 是用于构建跨 LLM 提供方 TypeScript 聊天应用的 SDK 技能,涵盖流式响应、类型化工具、提供方适配器及 React 或 Solid 客户端模式。

主要功能

  1. 01选择提供方适配器
  2. 02流式聊天响应
  3. 03类型化工具定义与验证
  4. 04客户端和服务器工具模式
  5. 05限制 Agent 循环并设置审批

适用场景

  1. 01构建流式聊天界面
  2. 02结合服务器数据工具与 UI 操作
  3. 03为敏感工具调用添加审批步骤

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill tanstack-ai

安装后在 Claude Code 中输入/tanstack-ai确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
api-chat-route.ts
tool-definitions.ts
references/
adapter-matrix.md
react-integration.md
start-vs-next-routing.md
streaming-troubleshooting.md
tanstack-ai-cheatsheet.md
tool-patterns.md
type-safety.md
scripts/
check-ai-env.sh

详细介绍

TanStack AI(与模型提供商无关的 LLM SDK)

状态:已可用于生产环境 ✅
最后更新:2025-12-09
依赖项:Node.js 20+、TypeScript 5+;使用 @tanstack/ai-react 需要 React 19+;使用 @tanstack/ai-solid 需要 Solid 1.8+
最新版本:@tanstack/ai@latest(alpha)、@tanstack/ai-react@latest、@tanstack/ai-client@latest、适配器:@tanstack/ai-openai@latest @tanstack/ai-anthropic@latest @tanstack/ai-gemini@latest @tanstack/ai-ollama@latest


快速入门(7 分钟)

1) 安装核心包和适配器
pnpm add @tanstack/ai @tanstack/ai-react @tanstack/ai-openai
# swap adapters as needed: @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-ollama
pnpm add zod              # recommended for tool schemas

为何重要:

  • 核心包与框架无关;React 绑定只是对无头客户端的封装。 citeturn1search3
  • 适配器会屏蔽提供商的差异,因此你无需重写代码就能更换模型。 citeturn1search3
2) 发布流式聊天端点(Next.js 或 TanStack Start)
// app/api/chat/route.ts (Next.js) or src/routes/api/chat.ts (TanStack Start)
import { chat, toStreamResponse } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'
import { tools } from '@/tools/definitions' // definitions only

export async function POST(request: Request) {
  const { messages, conversationId } = await request.json()
  const stream = chat({
    adapter: openai(),
    messages,
    model: 'gpt-4o',
    tools,
  })
  return toStreamResponse(stream)
}

重要:

  • 将工具的定义传给服务端,以便 LLM 请求调用这些工具;具体实现则放在相应的运行时中。 citeturn0search7
  • 始终使用流式传输;分块响应能让 UI 保持响应灵敏,并减少 token 浪费。 citeturn0search1
3) 使用 useChat + SSE 接入客户端
// components/Chat.tsx
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'
import { clientTools } from '@tanstack/ai-client'
import { updateUIDef } from '@/tools/definitions'

const updateUI = updateUIDef.client(({ message }) => {
  alert(message)
  return { success: true }
})

export function Chat() {
  const tools = clientTools(updateUI)
  const { messages, sendMessage, isLoading, approval } = useChat({
    connection: fetchServerSentEvents('/api/chat'),
    tools,
  })

  return (
    <form onSubmit={e => { e.preventDefault(); sendMessage(e.currentTarget.prompt.value) }}>
      <textarea name="prompt" disabled={isLoading} />
      {approval?.pending && (
        <button type="button" onClick={() => approval.approve()}>
          Approve tool
        </button>
      )}
    </form>
  )
}

重要:

  • 使用 fetchServerSentEvents(或对应的适配器)来接收流式响应。 citeturn0search0
  • 客户端工具名称必须与定义完全一致,以避免出现“找不到工具”的错误。 citeturn0search7

4 步设置流程

第 1 步:安全地选择提供商和模型
  • 添加正确的适配器,并设置对应的 API 密钥(OPENAI_API_KEY、ANTHROPIC_API_KEY、GEMINI_API_KEY,或 Ollama 主机)。
  • 优先使用适配器提供的按模型选项类型,避免使用无效选项(例如,仅用于视觉的字段)。 citeturn1search3
第 2 步:统一定义工具,按运行时分别实现
// tools/definitions.ts
import { z, toolDefinition } from '@tanstack/ai'

export const getWeatherDef = toolDefinition({
  name: 'getWeather',
  description: 'Get current weather for a city',
  inputSchema: z.object({ city: z.string() }),
  needsApproval: true,
})

export const getWeather = getWeatherDef.server(async ({ city }) => {
  const data = await fetch(`https://api.weather.gov/points?q=${city}`).then(r => r.json())
  return { summary: data.properties?.relativeLocation?.properties?.city ?? city }
})

export const showToast = getWeatherDef.client(({ city }) => {
  console.log(`Showing toast for ${city}`)
  return { acknowledged: true }
})

要点:

  • needsApproval: true 会要求用户明确批准敏感操作。 citeturn0search1
  • 工具应职责单一且具备幂等性;返回结构化对象,而不要抛出错误。 citeturn0search1
第 3 步:创建连接适配器和聊天选项
  • 服务端:使用 toStreamResponse(stream) 进行 HTTP 流式传输;使用 toServerSentEventsStream 辅助函数处理 Server-Sent Events。 citeturn0search3turn0search4
  • 客户端:使用 fetchServerSentEvents('/api/chat');如有需要,可使用适用于 websockets 的自定义适配器。 citeturn0search0
  • 配置 agentLoopStrategy(例如 maxIterations(8))以限制工具递归调用。 citeturn1search4
第 4 步:添加可观测性和防护措施
  • 记录工具执行情况和流分块以便调试;alpha 版已提供钩子,开发者工具仍在开发中。 citeturn0search1
  • 使用 Zod 验证输入;尽早失败并返回类型化的错误对象。
  • 在工具中的外部 API 调用上强制设置超时,以防 Agent 循环卡住。

关键规则

务必做到

✅ 使用流式响应;避免等待完整响应。 citeturn0search1
✅ 将定义传给服务端,将实现传给正确的运行时。 citeturn0search7
✅ 使用 Zod 模式定义工具的输入和输出,以确保不同提供商之间的类型安全。 citeturn0search1
✅ 使用 maxIterations 限制 Agent 循环,防止工具调用失控。 citeturn1search4
✅ 对具有破坏性或涉及计费的工具启用 needsApproval。 citeturn0search1

切勿这样做

❌ 在单个请求中混用提供商适配器——每次调用只实例化一个适配器。
❌ 从工具中抛出原始错误;应返回结构化错误负载。
❌ 将客户端工具的实现发送到服务端(只发送定义)。
❌ 将模型能力硬编码;应依靠适配器类型定义来处理按模型设置的选项。 citeturn0search1
❌ 跳过 API 密钥检查;应在服务端尽早失败并提供有用的错误消息。 citeturn0search1


预防已知问题

此技能可预防已记录的 3 个问题:

问题 #1:“未找到工具”/工具静默失败

原因:定义未传递给 chat();本地只有实现。
预防措施:单独导出定义,并将其包含在服务端 tools 数组中;保持名称稳定。 citeturn0search7

问题 #2:界面中的流式传输停滞

原因:服务端响应类型与客户端适配器不匹配(HTTP 分块传输与 SSE 不匹配)。
预防措施:在服务端使用 toStreamResponse,并在客户端使用 fetchServerSentEvents(或匹配的适配器)。 citeturn0search1turn0search0

问题 #3:模型选项验证错误

原因:将特定提供商的选项(例如视觉参数)发送给不支持这些选项的模型。
预防措施:使用适配器提供的类型;依靠针对各模型的选项类型,在编译时发现无效字段。 citeturn1search3


配置文件参考

.env.local(完整示例)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=
GEMINI_API_KEY=
OLLAMA_HOST=http://localhost:11434
AI_STREAM_STRATEGY=immediate

这些设置的原因:

  • 将非活动提供商留空,以避免意外调用多个提供商。
  • 示例客户端会读取 AI_STREAM_STRATEGY,以选择分块策略(立即发送或缓冲)。

常见模式

模式 1:使用有界工具的 Agent 循环
import { chat, maxIterations } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'

const stream = chat({
  adapter: openai(),
  messages,
  tools,
  agentLoopStrategy: maxIterations(8), // hard cap
})

适用场景:任何大模型可能通过工具递归调用的流程(搜索 → 总结 → 获取详情)。 citeturn1search4

模式 2:服务端与客户端工具混合使用
// server: data fetch
const fetchUser = fetchUserDef.server(async ({ id }) => db.user.find(id))

// client: UI update
const highlightUser = highlightUserDef.client(({ id }) => {
  document.querySelector(`#user-${id}`)?.classList.add('ring')
  return { highlighted: true }
})

chat({ tools: [fetchUser, highlightUser] })

适用场景:模型必须在一个循环中同时获取数据并更改界面状态。 citeturn0search1


使用打包的资源

脚本(scripts/)
  • scripts/check-ai-env.sh — 在运行开发服务器前验证所需的提供商密钥是否已配置。

用法示例:

./scripts/check-ai-env.sh
参考资料(references/)
  • references/tanstack-ai-cheatsheet.md — 精简的服务端/客户端/工具模式及故障排查提示。

Claude 应加载这些资料的场景:排查工具路由或流式传输问题,或需要回忆确切的 API 调用时。

资源文件(assets/)
  • assets/api-chat-route.ts — 可直接复制粘贴的 API 路由模板,包含流式传输和工具。
  • assets/tool-definitions.ts — 可直接使用的 toolDefinition 示例,包含审批和 zod 架构。

何时加载参考资料

针对特定实现情境加载参考文件:

  • 适配器对比:在 OpenAI、Anthropic、Gemini 或 Ollama 适配器之间进行选择,或排查特定提供商的特殊行为时,加载 references/adapter-matrix.md。

  • React 集成详情:实现 useChat 钩子、在 React 组件中处理 SSE 流,或管理客户端工具状态时,加载 references/react-integration.md。

  • 路由设置:在 Next.js 与 TanStack Start 中设置 API 路由,或排查流式响应设置问题时,加载 references/start-vs-next-routing.md。

  • 流式传输问题:排查 SSE 连接问题、分块传递问题或 HTTP 流式传输配置时,加载 references/streaming-troubleshooting.md。

  • 快速参考:需要精简的 API 模式、工具定义语法或快速故障排查提示时,加载 references/tanstack-ai-cheatsheet.md。

  • 工具架构:实现复杂的客户端/服务端工具工作流、审批流程或混合工具模式时,加载 references/tool-patterns.md。

  • 类型安全详情:使用针对各模型的选项类型、多模态输入,或排查跨适配器的类型错误时,加载 references/type-safety.md。


高级主题

针对各模型的类型安全
  • 使用适配器类型声明,为各模型选择有效选项;避免在 chat() 中使用通用的 any 选项。 citeturn1search3
  • 对于多模态模型,发送 MIME 类型正确的 parts;不支持的模态会在编译时被发现。 citeturn1search3
工具审批体验
  • 通过 useChat 中的 approval 对象呈现;渲染批准/拒绝界面,并为每次工具调用保存决定。 citeturn0search1
  • 对于可审计的操作,应将审批决定与工具输入一并记录。
连接适配器
  • 如需最简配置,默认使用 fetchServerSentEvents(SSE);如需支持 WebSocket 或 HTTP 分块传输,则切换到自定义适配器。 citeturn0search0
  • 在客户端中使用 ImmediateStrategy,以便每个数据块到达时立即发出,适用于显示输入指示器的 UI。 citeturn0search0

依赖项

必需:

  • @tanstack/ai@latest — 核心聊天和工具引擎
  • @tanstack/ai-react@latest — React 绑定(无头用法可跳过)
  • @tanstack/ai-client@latest — 无头聊天客户端和适配器
  • 适配器:@tanstack/ai-openai@latest | @tanstack/ai-anthropic@latest | @tanstack/ai-gemini@latest | @tanstack/ai-ollama@latest 中的一个
  • zod@latest — 工具的架构验证

可选:

  • @tanstack/ai-solid@latest — Solid 绑定
  • @tanstack/react-query@latest — 缓存工具中获取的数据
  • @tanstack/start@latest — 将 AI 工具与服务端函数放在一起

官方文档


软件包版本(已于 2025-12-09 验证)

{
  "dependencies": {
    "@tanstack/ai": "latest",
    "@tanstack/ai-react": "latest",
    "@tanstack/ai-client": "latest",
    "@tanstack/ai-openai": "latest"
  },
  "devDependencies": {
    "zod": "latest"
  }
}

故障排除

问题:UI 始终收不到工具输出

解决方案:确保工具实现返回可序列化对象;避免返回 undefined。通过 clientTools(...) 注册客户端实现。

问题:“Missing API key” 响应

解决方案:运行 ./scripts/check-ai-env.sh,并在 .env.local 中设置相应的提供方密钥。在调用 chat() 前,于路由中快速失败。 citeturn0search1

问题:流式传输在第一个数据块后停止

解决方案:确认服务端返回 toStreamResponse(stream)(或 SSE 助手),并确保任何反向代理都允许分块传输。


完整配置检查清单

使用此清单验证配置:

  • 已安装核心软件包、一个适配器和 zod
  • API 路由返回包含工具定义的 toStreamResponse(stream)
  • 客户端使用 fetchServerSentEvents(或匹配的适配器),并注册客户端工具实现
  • needsApproval 路径会显示批准/拒绝 UI
  • Agent 循环已设上限(例如 maxIterations)
  • 已使用 check-ai-env.sh 验证环境密钥
  • 如果目标模型支持视觉/音频,已测试多模态输入

有疑问?遇到问题?

  1. 加载 references/tanstack-ai-cheatsheet.md,查看更多示例
  2. 使用单个提供方适配器重新执行快速入门步骤
  3. 查阅上述官方文档,了解 API 接口更新

评论

支持 Markdown