# @cloudflare/ai-chat 中文文档

规范地址：https://npmcn.com/package/%40cloudflare/ai-chat/

版本：0\.12\.2
npm 元数据更新时间：2026-10-20T15:23:05.532Z
中文译文更新时间：2026-11-10T02:53:20.054Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40cloudflare/ai-chat
原文对照：https://npmcn.com/package/%40cloudflare/ai-chat/?lang=original
源码仓库：https://github.com/cloudflare/agents

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：699 kB，13 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：ai ^6\.0\.0 \|\| ^7\.0\.0，react ^19\.0\.0，agents \>=0\.25\.0 \<1\.0\.0，@ai-sdk/react ^3\.0\.0 \|\| ^4\.0\.0
- 首次发布：2025-12-29T16:37:54.536Z
- 最新版本发布：2026-10-20T15:23:04.829Z
- 近 30 天下载量：2617373（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：63（近 12 个月 63 个）

## 中文简介

Cloudflare 代理 (x) AI SDK 聊天

## 安装

```sh
npm install @cloudflare/ai-chat
```

也可以使用：`pnpm add @cloudflare/ai-chat`、`yarn add @cloudflare/ai-chat`、`bun add @cloudflare/ai-chat`

## README

# @cloudflare/ai-chat (英语)

AI聊天代理,具有自动消息持续,可重复流出,以及工具支持等功能. 以 Cloudflare 持久物体和 [AI SDK 软件](https://ai-sdk.dev/)。 。 。 .

## 安装

```sh
npm install @cloudflare/ai-chat agents ai workers-ai-provider
```

React 客户端也需要可选 React 的同位素 :

```sh
npm install @ai-sdk/react react
```

## 快速启动

### 服务器

```typescript
import { AIChatAgent } from "@cloudflare/ai-chat";
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages } from "ai";

export class ChatAgent extends AIChatAgent {
  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });

    const result = streamText({
      model: workersai("@cf/moonshotai/kimi-k2.7-code"),
      messages: await convertToModelMessages(this.messages)
    });

    return result.toUIMessageStreamResponse();
  }
}
```

这给了你:在SQLite中自动消息持续,在断开/再连接上可重复流线,以及实时WebSocket向所有连接客户端发送.

### 客户端

```tsx
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";

function Chat() {
  const agent = useAgent({ agent: "ChatAgent" });
  const { messages, sendMessage, clearHistory, status } = useAgentChat({
    agent
  });

  return (
    <div>
      {messages.map((msg) => (
        <div key={msg.id}>
          <strong>{msg.role}:</strong>
          {msg.parts.map((part, i) =>
            part.type === "text" ? <span key={i}>{part.text}</span> : null
          )}
        </div>
      ))}

      <form
        onSubmit={(e) => {
          e.preventDefault();
          const input = e.currentTarget.elements.namedItem(
            "input"
          ) as HTMLInputElement;
          sendMessage({
            role: "user",
            parts: [{ type: "text", text: input.value }]
          });
          input.value = "";
        }}
      >
        <input name="input" placeholder="Type a message..." />
      </form>
    </div>
  );
}
```

### 朗格勒配置

```jsonc
// wrangler.jsonc
{
  "ai": { "binding": "AI" },
  "durable_objects": {
    "bindings": [{ "name": "ChatAgent", "class_name": "ChatAgent" }]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["ChatAgent"]
    }
  ]
}
```

## 工具

### 服务器侧工具

带有工具 `execute` 在服务器上自动运行的函数 :

```typescript
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, isStepCount, tool } from "ai";
import { z } from "zod";

export class ChatAgent extends AIChatAgent {
  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });

    const result = streamText({
      model: workersai("@cf/moonshotai/kimi-k2.7-code"),
      messages: await convertToModelMessages(this.messages),
      tools: {
        getWeather: tool({
          description: "Get weather for a city",
          inputSchema: z.object({ city: z.string() }),
          execute: async ({ city }) => {
            const data = await fetchWeather(city);
            return { temperature: data.temp, condition: data.condition };
          }
        })
      },
      stopWhen: isStepCount(5)
    });

    return result.toUIMessageStreamResponse();
  }
}
```

### 客户端工具

没有工具 `execute` 客户端通过 `onToolCall`。用于需要浏览器 API(地理、剪贴板、相机)的工具:

```typescript
// Server: define tool without execute
getLocation: tool({
  description: "Get the user's location from their browser",
  inputSchema: z.object({})
  // No execute -- client handles it
});
```

```tsx
// Client: handle via onToolCall
const { messages, sendMessage } = useAgentChat({
  agent,
  onToolCall: async ({ toolCall, addToolOutput }) => {
    if (toolCall.toolName === "getLocation") {
      const pos = await new Promise((resolve, reject) =>
        navigator.geolocation.getCurrentPosition(resolve, reject)
      );
      addToolOutput({
        toolCallId: toolCall.toolCallId,
        output: { lat: pos.coords.latitude, lng: pos.coords.longitude }
      });
    }
  }
});
```

### 工具审批(人-入-出)

使用 `needsApproval` 用于执行前需要用户确认的工具:

```typescript
// Server
processPayment: tool({
  description: "Process a payment",
  inputSchema: z.object({ amount: z.number(), recipient: z.string() }),
  needsApproval: async ({ amount }) => amount > 100, // Only require approval for large amounts
  execute: async ({ amount, recipient }) => charge(amount, recipient)
});
```

```tsx
// Client
const { messages, addToolApprovalResponse } = useAgentChat({ agent });

// When rendering tool parts with state === "approval-requested":
<button onClick={() => addToolApprovalResponse({ id: approvalId, approved: true })}>
  Approve
</button>
<button onClick={() => addToolApprovalResponse({ id: approvalId, approved: false })}>
  Reject
</button>
```

### 代理工具

`AIChatAgent` 子类可以用作保留、流出代理工具 父代理通过 `runAgentTool()` 或者说 `agentTool()`数字 :

```typescript
import { AIChatAgent } from "@cloudflare/ai-chat";
import { agentTool } from "agents/agent-tools";
import { convertToModelMessages, streamText } from "ai";
import { z } from "zod";

export class Summarizer extends AIChatAgent<Env> {
  protected override formatAgentToolInput(input: { text: string }, request) {
    return {
      id: `agent-tool-${request.runId}-input`,
      role: "user",
      parts: [{ type: "text", text: `Summarize:\n\n${input.text}` }]
    };
  }

  async onChatMessage() {
    const result = streamText({
      model: this.env.MODEL,
      messages: await convertToModelMessages(this.messages)
    });

    return result.toUIMessageStreamResponse();
  }
}

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage() {
    const result = streamText({
      model: this.env.MODEL,
      messages: await convertToModelMessages(this.messages),
      tools: {
        summarize: agentTool(Summarizer, {
          description: "Summarize long text in a separate retained agent.",
          inputSchema: z.object({ text: z.string() })
        })
      }
    });

    return result.toUIMessageStreamResponse();
  }
}
```

特工工具转身无头. 服务器侧工具正常工作,但 浏览器提供的客户端工具不可用,除非您单独设计 服务器侧或由父机代理的交接。 覆盖 `formatAgentToolInput()`, (中文(简体) ), `getAgentToolOutput()`,以及 `getAgentToolSummary()` 当您需要结构化 投入或产出.

## 可还原流

断开/重新连接时自动恢复流 。 不需要配置 .

当客户端断开中流时,块会被缓冲到 SQLite. 在重新连接时,客户端接收所有缓冲块并持续接收活流.

这样可以处理浏览器断开、导航和反应清理,而持久对象则继续运行。 持久聊天恢复单独处理模式调用时被拆迁的持久对象本身.

## 持久聊天恢复

每个 `AIChatAgent` 转而使用可持久恢复的纤维,因此转而可以在工人部署、可持久物体驱逐或再生过程中幸存。 指定 a `chatRecovery` 对象仅在需要调和预算或终端行为时:

```typescript
import type {
  ChatRecoveryContext,
  ChatRecoveryOptions
} from "@cloudflare/ai-chat";

export class ChatAgent extends AIChatAgent<Env> {
  override chatRecovery = {
    maxAttempts: 6,
    terminalMessage: "The assistant was interrupted. Please try again."
  };

  override async onChatRecovery(
    ctx: ChatRecoveryContext
  ): Promise<ChatRecoveryOptions> {
    console.log("Recovering", ctx.incidentId, ctx.recoveryKind);
    return {}; // persist partial output and continue/retry when possible
  }
}
```

`chatRecovery = false` 不再支持。 先前编译的仍然供应的 JavaScript `false` 接收默认持久配置。 如果自动续作不安全, 请返回 `{ continue: false }` 从 `onChatRecovery()`; 使用持久状态进行取消或副作用警卫,并为成本控制配置回收预算.

见 [`docs/agents/chat-agents.md`](https://npmcn.com/package/docs/agents/chat-agents.md#stream-recovery) 用于移徙指导、针对提供者的恢复战略和可观察活动.

通用客户端流中止/清理默认只属于本地:服务器转会继续并可在稍后恢复. 明确 `stop()` 仍然取消服务器回合 :

```tsx
const { messages, stop } = useAgentChat({ agent });
```

如果您的应用程序有意希望客户端生命周期拥有服务器生命周期, 请选择在客户端中止时取消 :

```tsx
const { messages } = useAgentChat({
  agent,
  cancelOnClientAbort: true
});
```

用于请求寿命或节能符的流量 。 明确 `stop()` 总是 服务器端取消, 不论 `cancelOnClientAbort`。 。 。 .

禁用恢复为 `resume: false`数字 :

```tsx
const { messages } = useAgentChat({ agent, resume: false });
```

## 重叠信件

当用户提交新消息,而另一个回合仍在运行时, `AIChatAgent` 可以队列、倒塌或丢弃重叠服务器侧:

```typescript
export class ChatAgent extends AIChatAgent {
  messageConcurrency = "latest";

  async onChatMessage() {
    // ...
  }
}
```

现有战略:

-   `"queue"` (默认)——按顺序处理每次提交
-   `"latest"` ——只保留最新的重叠提交并跳过任何更旧的队列重叠回合
-   `"merge"` – 队列重叠提交, 然后将队列中的用户信件崩溃为一个合并的后继用户回合
-   `"drop"` - 忽略重叠提交
-   `{ strategy: "debounce", debounceMs: 750 }` 等待一个安静的窗口, 然后运行只运行最新的提交

**选择一项战略:** 使用 `"latest"` 用于用户的焦点助理 能够修正自己在中游。 使用 `"queue"` 或者说 `"merge"` 用于通讯 每个消息都很重要的应用程序 。 使用 `"drop"` 防止双发. 使用 `"debounce"` 当用户发送短信息时.

**用户看到的:** 与 `"queue"`,每个消息都有自己的反应. 与 `"latest"`中,所有信件都出现,但只有最后一个重叠的 反应。 与 `"merge"`,重叠的信息会崩溃成一个。 与 `"drop"`中,重叠的信息会短暂出现,然后消失(倒转).

此设置只影响重叠 `sendMessage()` 提交。 重新创造, 工具的延续、核准和方案 `saveMessages()` 打电话保持 现有序列化行为。 何时 `debounceMs` 缺少或无效, `AIChatAgent` 返回到默认值 `750` 毫丝窗.

传递函数到 `saveMessages()` 以获取最新记录 转弯实际开始 —— 用于计时回调和 webhook 处理器 如果自电话发出以来消息可能有所改变:

```typescript
await this.saveMessages((messages) => [
  ...messages,
  {
    id: crypto.randomUUID(),
    role: "user",
    parts: [{ type: "text", text: "Scheduled follow-up" }]
  }
]);
```

`saveMessages()` 返回时 `{ requestId, status }`编辑 `status` 字段为 `"completed"` 当转弯时, `"skipped"` 中空飞行无效时 (例如,a) `chat-clear`),或 `"aborted"` 当外部 `AbortSignal` 已取消 这个 过 `options.signal` 取消外部程序转接, 不包含 了解内部生成的请求 id:

```typescript
const controller = new AbortController();
const result = await this.saveMessages([userMsg], {
  signal: controller.signal
});
if (result.status === "aborted") {
  // ...
}
```

这是相同的形状 `Think.saveMessages` 使用——见 [`cloudflare/agents#1406`](https://github.com/cloudflare/agents/issues/1406) 用于推动API的代理工具管弦模式。 运出 代理工具 API 在 [`docs/agents/agent-tools.md`](https://npmcn.com/package/docs/agents/agent-tools.md)。 。 。 .

## 储存管理

### 限制已存储信件

控制保存在 SQLite 的信件数量 :

```typescript
export class ChatAgent extends AIChatAgent {
  maxPersistedMessages = 200; // Keep last 200 messages

  async onChatMessage() {
    // ...
  }
}
```

当计数超过限制时,删除最旧的消息 。 这只控制存储——不影响发送给LLM的内容.

### 控制 LLM 上下文

使用 AI SDK 软件 `pruneMessages()` 以控制发送到模型中的内容,而不受存储内容的影响:

```typescript
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, pruneMessages } from "ai";

export class ChatAgent extends AIChatAgent {
  maxPersistedMessages = 200;

  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });

    const result = streamText({
      model: workersai("@cf/moonshotai/kimi-k2.7-code"),
      messages: pruneMessages({
        messages: await convertToModelMessages(this.messages),
        reasoning: "before-last-message",
        toolCalls: "before-last-2-messages"
      })
    });

    return result.toUIMessageStreamResponse();
  }
}
```

### 行大小保护

信件接近 SQLite 的 2MB 行限制会自动压缩 。 大型工具产出取而代之的是方便LLM的摘要,该摘要指示模型建议重新运行工具。 压缩信息包括 `metadata.compactedToolOutputs` 这样客户可以检测和显示这个优雅.

## 自定义请求数据

包含自定义数据,每个聊天请求使用 `body` 选项 :

```tsx
const { messages, sendMessage } = useAgentChat({
  agent,
  body: {
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    userId: "abc"
  }
});

// Or use a function for dynamic values:
body: () => ({ token: getAuthToken(), timestamp: Date.now() });
```

通过 `options.body`数字 :

```typescript
async onChatMessage(onFinish, options) {
  const { timezone, userId } = options?.body ?? {};
}
```

## API 参考

### `AIChatAgent<Env, State, Props>`

扩展 `Agent` 从 `agents` 软件包.

| 财产/方法 | 类型 | 说明 |
| --- | --- | --- |
| `messages` | `ChatMessage[]` | 当前对话消息( 从 SQLite 上载) |
| `chatRecovery` | `ChatRecoveryConfig` | 总是在持久恢复配置。 指定一个对象来调和预算和终端行为 |
| `maxPersistedMessages` | `number | undefined` | 要保存在 SQLite 中的最大消息 。 默认:无限 |
| `messageConcurrency` | `MessageConcurrency` | 货币战略 `sendMessage()` 提交。 默认 : `"queue"` |
| `onChatMessage(onFinish?, options?)` | 覆盖 | 处理收到的聊天信息 。 还原 a `Response`。 。 。 . `onFinish` 是可选的. |
| `onChatRecovery(ctx)` | 覆盖 | 聊天回合中断后自定义恢复 |
| `onChatResponse(result)` | 覆盖 | 聊天回合完成后调用. `result` 已经 `message`, (中文(简体) ), `requestId`, (中文(简体) ), `status`, (中文(简体) ), `continuation` |
| `persistMessages(messages)` | `Promise<void>` | 手动粘接信件( 通常是自动) |
| `saveMessages(messages, options?)` | `Promise<SaveMessagesResult>` | 持久性信息和触发 `onChatMessage`。接受数组或函数. `options.signal` 取消外部转弯. |
| `waitUntilStable()` | `Promise<boolean>` | 受保护的助手等待谈话完全稳定 |
| `resetTurnState()` | `void` | 保护帮助中止活动回合并取消队列的续作 |
| `hasPendingInteraction()` | `boolean` | 保护助手以检测待决工具输入或核准助理信件 |

### `useAgentChat(options)`

聊天互动的反应钩. 包装 AI SDK 的 `useChat` 与WebSocket运输.

**选项 :**

| 选项 | 类型 | 说明 |
| --- | --- | --- |
| `agent` | `ReturnType<typeof useAgent>` | 代理连接( 需要) |
| `onToolCall` | `({ toolCall, addToolOutput }) => void` | 处理客户端工具执行 |
| `autoContinueAfterToolResult` | `boolean` | 在客户端工具结果后自动继续. 默认 : `true` |
| `resume` | `boolean` | 启用流恢复 。 默认 : `true` |
| `cancelOnClientAbort` | `boolean` | 当发生通用客户端流中止/清理时取消服务器回合 。 明确 `stop()` 总是取消。 默认 : `false` |
| `body` | `object | () => object` | 按每次请求发送的自定义数据(见下文) |
| `prepareSendMessagesRequest` | `(options) => { body?, headers? }` | 按要求预先定制 |
| `getInitialMessages` | `(options) => Promise<ChatMessage[]>` | 自定义初始信件加载器 |

**回返情况:**

| 财产 | 类型 | 说明 |
| --- | --- | --- |
| `messages` | `ChatMessage[]` | 聊天消息 |
| `sendMessage` | `(message) => void` | 发送消息 |
| `clearHistory` | `() => void` | 清除对话 |
| `addToolOutput` | `({ toolCallId, output }) => void` | 提供工具输出 |
| `addToolApprovalResponse` | `({ id, approved }) => void` | 批准/拒绝一个工具 |
| `setMessages` | `(messages | updater) => void` | 设置信件( 同步到服务器) |
| `status` | `string` | `"idle"` | `"submitted"` | `"streaming"` | `"error"` |

### 出口

| 导入路径 | 它提供的东西 |
| --- | --- |
| `@cloudflare/ai-chat` | `AIChatAgent`, (中文(简体) ), `ChatMessage`, (中文(简体) ), `createToolsFromClientSchemas`, (中文(简体) ), `ChatRecoveryContext`, (中文(简体) ), `ChatRecoveryConfig` |
| `@cloudflare/ai-chat/react` | `useAgentChat` |
| `@cloudflare/ai-chat/types` | `MessageType`, (中文(简体) ), `OutgoingMessage`, (中文(简体) ), `IncomingMessage` |

## 实例

-   [恢复流式聊天](https://npmcn.com/package/examples/resumable-stream-chat/) -- 自动溪流恢复
-   [人行指南](https://npmcn.com/package/guides/human-in-the-loop/) -- 工具核准 `needsApproval` + 键 `onToolCall`
-   [游戏场](https://npmcn.com/package/examples/playground/) 所有 SDK 特性的厨房-沉积演示

## 许可证

麻省理工学院

## 常见问题

### @cloudflare/ai-chat 是什么？

Cloudflare 代理 \(x\) AI SDK 聊天

### 如何安装 @cloudflare/ai-chat？

在项目目录运行 npm install @cloudflare/ai-chat，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：ai（^6\.0\.0 \|\| ^7\.0\.0）、agents（\>=0\.25\.0 \<1\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @cloudflare/ai-chat 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @cloudflare/ai-chat 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @cloudflare/ai-chat 可以商用吗？

@cloudflare/ai-chat 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @cloudflare/ai-chat 的下载量有多少？

根据 npm 官方下载统计，@cloudflare/ai-chat 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,617,373 次，日均约 87,246 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @cloudflare/ai-chat 还在维护吗？

最新版本 0\.12\.2 发布于 2026/10/20（20 天前）；至今共发布 63 个版本，其中过去 12 个月发布了 63 个；首次发布于 2025/12/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

