@/ai/hooks 下提供 五个 React hook,封掉了那些写起来烦人的部分:
AbortController、流解码、轮询循环、游标分页 —— 让你的客户端代码专心写 UI。每个 hook
都纯客户端,服务端契约是普通的 JSON / text 端点,可以替换。
前置条件
- 看过 providers 文档 —— 这些 hook 调的就是 manager 暴露出来的 后端。
- API 路由挂在
/api/ai/chat、/api/ai/history、/api/credits/balance、/api/prompts/<slug>(默认值;每个 hook 都接受自定义endpoint)。 - 标准 UI 示例在
src/components/demos/{chat-demo,image-demo,document-demo}.tsx。
API 参考
useGeneration(options?)
从一个吐 UTF-8 chunk 的服务端端点流式拉文本。
签名
AbortController 和响应体解码。
src/components/demos/chat-demo.tsx。
useTask(options)
长任务:POST 启动 → 轮询到结束态。
签名
parse 把 hook 和
具体响应结构解耦。
src/components/demos/image-demo.tsx。
useCredits(endpoint?)
读当前登录用户的积分余额。
签名
/api/credits/balance。
<CreditsBadge /> 已经包了这个 hook,大多数业务不直接用。
usePrompt(slug)
按 slug 拉一个已注册的 prompt,并支持客户端渲染。
签名
<PromptVariableForm />。
render 替换 {{variable}} 占位符。服务端渲染请直接走 registry —— 见
Prompts。
useHistory(endpoint?)
当前用户的 ai_call 历史,游标分页。
签名
AICallHistoryRow 包含 provider、model、operation、status、
inputTokens、outputTokens、costMicroCents、totalMs、createdAt。每页 20 条,
游标是末行的 createdAt(ISO 字符串)。
src/components/demos/document-demo.tsx。
验证生效
- 起 dev server,登录。
- 打开
/playground/chat,输入。看text一字一字出来 —— 那就是useGeneration在流。 - 打开
/playground/image,提交 prompt。状态从queued → running → succeeded— 那就是useTask。 - 打开
/dashboard/usage。列表刷新,Load more能加更多行 —— 那就是useHistory。
常见坑
- 流式端点返回 JSON 而不是 text。
useGeneration是按 UTF-8 chunk 读 body 的。 如果路由res.json(),你会一次拿到全文而不是流。请用new Response(stream)或text/plaincontent type。 - 忘记
await generate()。 它返回的是最终文本的 Promise,发完不管也行,但不try/catch就看不到错误。 useTask.parse返回了错的状态字符串。 Hook 只在'succeeded' | 'failed' | 'cancelled'时停止轮询,其他都当「继续轮」。useCredits显示旧余额。 任何 AI 调用之后都要refetch(),manager 是异步扣 积分的,徽章不会自己更新。usePrompt在 slug 切换时 race。 同一组件里多个 slug 并发会乱序。如果会重渲 染换 slug,建议在外层用key={slug}。
官方文档
- React refs / AbortController:react.dev
- Streams API:developer.mozilla.org
- 源码:
src/ai/hooks/、src/components/demos/