# @cogitator-ai/next 中文文档

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

版本：0\.15\.1
npm 元数据更新时间：2026-10-29T00:50:59.615Z
中文译文更新时间：2026-11-10T10:13:15.829Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：262 kB，83 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.12\.0
- 运行依赖：3 个
- peer 依赖：next ^14\.0\.0 \|\| ^15\.0\.0 \|\| ^16\.0\.0，react ^18\.2\.0 \|\| ^19\.0\.0
- 首次发布：2026-01-26T16:58:53.384Z
- 最新版本发布：2026-10-29T00:50:59.301Z
- 近 30 天下载量：9517（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：85（近 12 个月 85 个）

## 中文简介

Next.js Cogitator AI 运行时间的集成

## 安装

```sh
npm install @cogitator-ai/next
```

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

## README

# @cogitator-ai/ 下一个

Next.js App路由器集成 Cogitator AI 运行时间. 提供流式聊天处理器,一个分批代理处理器,以及能说出以Vercel AI SDK事件流为模式的SSE协议的回放钩.

## 安装

```bash
pnpm add @cogitator-ai/next @cogitator-ai/core
```

与Next.js 14,15和16以及React 18和19合作.

## 快速启动

### 1\. 创建API 路由

```typescript
// app/api/chat/route.ts
import { Cogitator, Agent, tool } from '@cogitator-ai/core';
import { createChatHandler } from '@cogitator-ai/next';
import { z } from 'zod';

const cogitator = new Cogitator({
  llm: {
    defaultModel: 'openai/gpt-6-luna',
    providers: { openai: { apiKey: process.env.OPENAI_API_KEY! } },
  },
});

const agent = new Agent({
  name: 'assistant',
  model: 'openai/gpt-6-luna',
  instructions: 'You are a helpful assistant.',
  tools: [
    tool({
      name: 'get_weather',
      description: 'Get weather for a location',
      parameters: z.object({ location: z.string() }),
      execute: async ({ location }) => `Weather in ${location}: 72°F, sunny`,
    }),
  ],
});

export const POST = createChatHandler(cogitator, agent);
```

### 2\. 客户部分的使用

```tsx
'use client';

import { useCogitatorChat } from '@cogitator-ai/next/client';

export function Chat() {
  const { messages, input, setInput, send, isLoading } = useCogitatorChat({
    api: '/api/chat',
  });

  return (
    <div>
      {messages.map((m) => (
        <div key={m.id}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}

      <form
        onSubmit={(e) => {
          e.preventDefault();
          send();
        }}
      >
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Type a message..."
          disabled={isLoading}
        />
        <button type="submit" disabled={isLoading}>
          Send
        </button>
      </form>
    </div>
  );
}
```

## 服务器处理器

### `createChatHandler`

创建流式聊天处理器。 处理者:

-   运行代理服务器, 启用符号流并转发 `text-*`, (中文(简体) ), `tool-*` 财务报告和审定财务报表 `finish` 发生时的事件
-   使用该 **上次用户消息** 作为运行输入,对话历史由 `threadId` (配置) `memory` 编辑 `Cogitator` (见A/CN.9/WG.III/WP.III/WP.1号文件)。 没有一条,处理器打开一条新线条,并在其中命名 `start` 事件,以及 `finish` 事件重复,并且 `useCogitatorChat` 自动通过
-   通行证申请 `metadata` 运行为 `context`键 `acceptContext` 允许: 运行发送 `context` 作为所提供应用程序的数据,提交该模型,因此,默认情况下,请求使用 `metadata` 拒绝使用 `400`
-   写入 `: keep-alive` 注释每 `sseHeartbeatMs` (默认5 s, `0` 关闭( 关闭它 ) , 而运行是静默的, 因此代理或平台不会关闭在慢工具上等待的流
-   当客户端断开时中止运行( r)`req.signal`),除非 `resumableStreams` 打开( 见 [可恢复流](https://npmcn.com/package/%40cogitator-ai/next/#readme-resumable-streams)(中文(简体) )
-   仅读取 JSON 天体(`415` 页:1 `text/plain` 和表单,浏览器在没有飞行前的情况下发送到源头),验证正体(JSON对象, `messages` 数组, 非空白 `threadId`对象 `metadata`页:1 `multitaskStrategy` 联 合 国 `enqueue`, (中文(简体) ), `reject`, (中文(简体) ), `interrupt` 或者说 `rollback`),将其限制在1 MB(另作413个)并返回 `400` 当没有用户消息时

```typescript
import { createChatHandler } from '@cogitator-ai/next';

export const POST = createChatHandler(cogitator, agent, {
  // Custom input parsing
  parseInput: async (req) => {
    const body = await req.json();
    return {
      messages: body.messages,
      threadId: body.threadId,
      metadata: body.metadata,
    };
  },

  // Pre-processing hook — the returned object is merged into the run options
  // (e.g. userId, threadId, timeout). Streaming callbacks and the abort
  // signal are always managed by the handler. Throw an error with a `status`
  // property to reject the request with that status (default 401).
  beforeRun: async (req, input) => {
    console.log('Starting chat with', input.messages.length, 'messages');
    return { userId: 'user-123' };
  },

  // Post-processing hook — runs before the `finish` event; if it throws,
  // the client receives an `error` event instead of `finish`
  afterRun: async (result) => {
    console.log('Chat completed:', result.output);
  },
});
```

### 可恢复流

与 `resumableStreams`运行会超过一个中断的连接 客户端会从它停止的地方取出它的流. `useCogitatorChat` 客户端本身是否:

```typescript
// app/api/chat/route.ts
const handler = createChatHandler(cogitator, agent, {
  beforeRun: async (req) => ({ userId: await userIdFrom(req) }),
  resumableStreams: { owner: (req) => (req ? userIdFrom(req) : undefined) },
});
export const POST = handler;
export const DELETE = handler;

// app/api/chat/resume/route.ts
const resume = createResumeHandler(cogitator, agent, {
  stream: true,
  beforeRun: async (req) => ({ userId: await userIdFrom(req) }),
  resumableStreams: { owner: (req) => (req ? userIdFrom(req) : undefined) },
});
export const POST = resume;
export const DELETE = resume;
```

-   每个事件都带有SSE `id`, (中文(简体) ), `<streamId>:<seq>`,而一个断开的客户端不再停止运行(该客户端 `signal` `beforeRun` 返回仍然如此.
-   同样的要求再次与 `Last-Event-ID: <id>` 重新连接而不是启动运行: 答案重放 id 之后的事件, 然后跟踪运行到 `finish` 或者说 `error`。 。 。 . `?lastEventId=<id>` 也起作用了,但它把ID放入了URL和日志中,因此更喜欢标题.
-   `DELETE` 同一路线 `?streamId=<streamId>` 取消运行( e)`204`:其溪流以 `STREAM_CANCELLED`。 。 。 . `useCogitatorChat` 送来 `stop()`, (中文(简体) ), `reload()` 和每一次其他的中断, 所以一个停止的答案不会去 花象征性的.
-   重新连接和取消读取无正文和运行 `beforeRun` 也没有 `deps`,它的副作用会重复。 溪流注定 `owner(req)`: 只有拥有同一所有者的请求才能在 `authorizeThread(req, threadId)` 在溪流的线上(`403 THREAD_FORBIDDEN`) (中文(简体) ). 与 `beforeRun`, (中文(简体) ), `owner` 需要处理器投出。 无 `beforeRun` 每个打电话的人都是匿名的 任何人,未知或过期的溪流得到 `404 STREAM_NOT_FOUND`,一个错误的id `400 INVALID_INPUT`。 。 。 .
-   不再保存的事件后重新连接( 多于 `maxEvents` 从此以后 `error` 事件为 `STREAM_RESUME_GAP`无人跟踪 `detachedTimeoutMs` (5分钟)停止,每跑一次 `until` 中止, 这样流会以 `STREAM_ABORTED`时的新流 `maxStreams` 溪流都会被拒绝 `503 STREAM_LIMIT_REACHED`。 。 。 .
-   `true` 将事件保存在处理器的记忆中:每条溪流有1000个事件,一个完成的溪流5分钟,1000个溪流(`{ maxEvents, retentionMs, maxStreams, detachedTimeoutMs }` ”)。 在没有服务器的平台或若干实例中,重新连接或取消可能到达未启动运行的实例:通过 a `store` 共享(`StreamReplayStore` 从 `@cogitator-ai/server-shared`,由 Redis 支持或与 pub/sub 类似,并运行在某个函数可能超过其请求的地方.

### `createAgentHandler`

为长跑任务创建分批(非流)处理器. 默认解析器是每个 Cogitator 适配器股份的验证器: 一个非空格字符串 `input`,可选对象 `context` 仅使用密钥 `acceptContext` 允许( 无默认的, 因为模型读取 `context` 作为所提供的应用程序的数据),可选的非空白 `threadId` 和可选 `multitaskStrategy` (单位:千美元)`400 { error: { message, code: 'INVALID_INPUT' } }` 否则, `415` 对于一个不是JSON的身体。 A 类 `parseInput` 由你自己决定 如果客户端断开, 运行将被中止 .

```typescript
import { createAgentHandler } from '@cogitator-ai/next';

export const POST = createAgentHandler(cogitator, researchAgent, {
  parseInput: async (req) => {
    const body = await req.json();
    return {
      input: body.query,
      context: body.context,
      threadId: body.threadId,
    };
  },
});
```

反应格式 :

```json
{
  "output": "Research results...",
  "threadId": "thread-abc",
  "usage": {
    "inputTokens": 150,
    "outputTokens": 500,
    "totalTokens": 650
  },
  "toolCalls": [{ "id": "call_1", "name": "search", "arguments": { "q": "AI" } }],
  "status": "completed",
  "traceId": "trace-xyz"
}
```

答案是每个 Cogitator 适配器返回的相同对象(`toAgentRunResponse()` 联 合 国 `@cogitator-ai/server-shared`: `reasoning`, (中文(简体) ), `structured`, (中文(简体) ), `structuredError`, (中文(简体) ), `truncated`, (中文(简体) ), `blocked` 财务报告和审定财务报表 `iterationLimitReached` 应用时出现。 它从不携带系统即时,历史或追踪跨度,其属性具有原始工具参数和错误: `traceId` 将答案链接到您的痕迹,以及 `afterRun` 接收整个 `RunResult`运行等待 [核准数](https://npmcn.com/package/%40cogitator-ai/next/#readme-approvals) 答题 `"status": "paused"` 联合国 `pendingApprovals`运行失败 `CogitatorError` 答题 `{ "error": { "message": message, "code": code } }` 带有该错误状态(例如 `429 LLM_RATE_LIMITED`)和a 数据 `Retry-After` 当供应商说什么时候再试时, 标题 。 服务器上记录了任何其他错误并回答为 `500 { "error": { "message": "Internal server error", "code": "INTERNAL_ERROR" } }`,因此其文本(连接字符串,文件路径)从未到达客户端. 每个Cogitator适配器都会在这个信封中回答错误. 当 `afterRun` 掷出.

### 多个用户

当几个人共享服务器时,返回呼叫者的 `userId` 从 `beforeRun`达到 `cogitator.run`,使每个 `threadId` 给创建它运行的用户:

```typescript
export const POST = createChatHandler(cogitator, agent, {
  beforeRun: async (req) => {
    const user = await getSession(req);
    if (!user) throw Object.assign(new Error('Unauthorized'), { status: 401 });
    return { userId: user.id };
  },
});
```

A 类 `threadId` 属于另一个用户的,在使用该模型之前被拒绝: `createAgentHandler` 答题 `403` 与 `code: "THREAD_ACCESS_DENIED"`,以及 `createChatHandler` 以 `error` 带有密码的事件。 没有 `userId`,呼叫者只能使用没有主人的线程.

每个处理器还采用服务器合同中其他 Cogitator 适配器共享的选项:

```typescript
export const POST = createChatHandler(cogitator, agent, {
  beforeRun: async (req) => ({ userId: (await getSession(req))?.id }),
  anonymous: 'deny',
  authorizeThread: (req, threadId) => threadId.startsWith(`${tenantOf(req)}:`),
  deps: (req) => ({ db: databaseFor(tenantOf(req)) }),
});
```

-   `anonymous: 'deny'` 答题 `401 UNAUTHORIZED` 何时 `beforeRun` 返回无 `userId` (默认) `'allow'` 让这些来电者进来.
-   `authorizeThread(req, threadId)` 在运行开始前询问关于线程的要求名称,以及 `false` 答题 `403 THREAD_FORBIDDEN`。 。 。 .
-   `deps(req)` 给运行 `deps` (单位:千美元)`context.deps` 永远不要从身体读取。 A 类 `deps` 那个 `beforeRun` 返回战胜它.

### 核准

一个工具与 `requiresApproval` 在执行前暂停运行。 运行时间将运行的检查点保存在服务器上, 每个线程; 客户端只看到等待决定的内容 :

-   `createAgentHandler` 答案为 `"status": "paused"` 财务报告和审定财务报表 `pendingApprovals` (单位:千美元)`toolCallId`, (中文(简体) ), `toolName`, (中文(简体) ), `arguments`, (中文(简体) ), `description`, (中文(简体) ), `sideEffects`) (中文(简体) ).
-   `createChatHandler` 发送 `{"type":"approval-required","threadId":"…","approvals":[…]}` 刚刚 `finish`。 。 。 .

`createResumeHandler` 继续运行。 这需要 `{ threadId, decisions?, defaultDecision? }`,在决定是 `{ approved: true }` 或者说 `{ approved: false, reason? }` 由工具调用 id. 授权的电话运行,拒绝的电话以理由回答模型,而电话未决定的电话再次暂停运行. 把电话拿回来 `userId` 从 `beforeRun` 至于其他处理器:只有运行属于的用户可以恢复运行.

```typescript
// app/api/chat/resume/route.ts
import { createResumeHandler } from '@cogitator-ai/next';

export const POST = createResumeHandler(cogitator, agent, {
  stream: true,
  beforeRun: async (req) => ({ userId: (await getSession(req)).id }),
});
```

默认它回答像 `createAgentHandler`; 与 `stream: true` 它流出 其余的跑象 `createChatHandler`,这是什么 `useCogitatorChat` 想要 想要吗? 另一个用户运行的答案 `403 THREAD_ACCESS_DENIED`,线程没有暂停运行 `409 RUN_NOT_PAUSED` (单位:千美元) `error` 流经时的事件).

在客户身上, `useCogitatorChat({ api, resumeApi })` 曝光情况 `pendingApprovals` 继续运行到一个新的助理消息:

```tsx
'use client';

import { useCogitatorChat } from '@cogitator-ai/next/client';

export function Chat() {
  const { messages, pendingApprovals, approve, deny, isLoading } = useCogitatorChat({
    api: '/api/chat',
    resumeApi: '/api/chat/resume',
  });

  return (
    <div>
      {messages.map((m) => (
        <p key={m.id}>{m.content}</p>
      ))}
      {pendingApprovals.length > 0 && (
        <div>
          {pendingApprovals.map((call) => (
            <p key={call.toolCallId}>
              {call.toolName}: {JSON.stringify(call.arguments)}
            </p>
          ))}
          <button disabled={isLoading} onClick={() => approve()}>
            Approve
          </button>
          <button disabled={isLoading} onClick={() => deny('Not approved')}>
            Deny
          </button>
        </div>
      )}
    </div>
  );
}
```

每一次通话决定,使用一次 `resume({ decisions: { [toolCallId]: { approved: true } }, defaultDecision: { approved: false } })`。 。 。 .

`approve()` 财务报告和审定财务报表 `deny(reason?)` 回答每个待发的电话, `approveAlways()` 批准他们,并节省每个人的 `suggestedRule` (见 [权限](https://cogitator.app/docs/tools/permissions#always-allow)) (中文(简体) ). 一旦恢复程序被接受,当服务器再也没有任何暂停时,批准就明确了(`409`)),或者当用户发送了新消息,从而拒绝了服务器上的等待呼叫. 一个JSON `resumeApi` 也起作用:其答复作为一个助理信息附上. `useCogitatorAgent({ api, resumeApi })` 曝光情况 `pendingApprovals` 最后结果和 `resume(decisions)`。 。 。 .

工具也可以向用户提问 `context.interrupt()`,它暂停运行的方式相同. `createAgentHandler` 然后用 `interrupts` (单位:千美元)`id`, (中文(简体) ), `kind`, (中文(简体) ), `reason`, (中文(简体) ), `message`, (中文(简体) ), `responseSchema`, (中文(简体) ), `expiresAt`, (中文(简体) ), `toolCallId`, (中文(简体) ), `toolName`),以及 `createChatHandler` 发送 `{"type":"interrupt-required","threadId":"…","interrupts":[…]}` 改为 `approval-required`。 。 。 . `createResumeHandler` 以中断 id 的方式获取答案 `responses`两个钩子都把问题暴露为 `pendingInterrupts` 并用 `resume({ responses: { [id]: answer } })`。 。 。 . `useCogitatorChat` 还有电话 `onInterruptRequired`。一个与其 `responseSchema` 拒绝使用 `400 INTERRUPT_ANSWER_INVALID`后发送 `expiresAt` 与 `410 INTERRUPT_EXPIRED` (流线) `createResumeHandler` 两者都作为 `error` 与此相关的事件 `code`) (中文(简体) ).

命名线索的运行也可能命名为 `multitaskStrategy` 当线程在这个 Cogitator 中已经运行时 : `enqueue` 等待运行, `reject` 拒绝新运行 `THREAD_BUSY`, (中文(简体) ), `interrupt` 停止运行( 它失败) `RUN_INTERRUPTED`和 `rollback` 停止它和从它开始的树枝. `createAgentHandler` 从身体读出来 `multitaskStrategy` 并用 `409`。 。 。 . `createChatHandler` 读它,但它的溪已经回答 `200` 发送 `start` 当跑步遇到另一跑道时,它会把它们当作一条 `error` 与此相关的事件 `code`。没有一个 科吉塔克 `multitaskStrategy` 适用.

`useCogitatorChat({ multitaskStrategy })` 发送它与每一个消息。 没有一个人, `send` 中止先流的请求, 一如既往。 与 `interrupt` 或者说 `rollback` 它让服务器停止运行 旧的答案会一直停留到它得到的 钩子会忽略它发出的其他信息,包括 `RUN_INTERRUPTED` 错误, 因为关闭连接本身会在服务器看到新信件之前中止运行 `rollback` 就会失去分出点 旧请求一旦完成就会中止,或者当新请求失败时立即中止(a) `403` 例如,它从来就没有隐蔽过。 与 `enqueue` 或者说 `reject` 它让请求独处,让服务器决定:运行后一个被排列的答案流,一个被拒绝的消息最后会进入 `error` 财务报告和审定财务报表 `onError` 而运行中的答案继续. `isLoading` 留下来 `true` 直到每个请求都得到满足 `stop` 全部停止,包括交给服务器的.

在新对话中, 服务器选择线索并将其命名于 `start`根据战略发出的信息,在它提出请求之前,它已经指定了它的线程等待 `start`,因此信件共享一线程而不是各启动一线程(一个结束而不命名一线程的请求让下一条消息启动自己的一线程). 批准和问题属于暂停的请求:当后一消息运行在线程上时,服务器放弃了暂停运行,所以 `pendingApprovals` 财务报告和审定财务报表 `pendingInterrupts` 清除信件完成后, 或者显示自己的暂停 。 一个被拒绝的消息从未运行过,所以在它停留之前暂停.

### `createAGUIHandler`

代理给 AG-UI 1.0 客户端,如 CopilotKit 或 a `@ag-ui/client` `HttpAgent`: 它需要一个 `RunAgentInput` 和流 AG-UI 事件。 AG-UI线程是跑的内存线程,最后一条消息(用户)是新转弯, `resume` 条目立即回答暂停运行的每次中断, `state` 是运行状态和 `context` 简介。 子代理流作为 AG-UI 子代理, 数据部分作为活动, 状态变化为 `STATE_DELTA`,然后暂停运行结束 `RUN_FINISHED` 和结果 `interrupt`。 。 。 .

```typescript
// app/api/agui/route.ts
import { createAGUIHandler } from '@cogitator-ai/next';

export const POST = createAGUIHandler(cogitator, agent, {
  beforeRun: async (req) => ({ userId: await userIdFrom(req) }),
});
```

### 触发和收件箱(实验)

`createTriggerHandler` 财务报告和审定财务报表 `createInboxHandler` 服务于 API 触发器的路径,webhooks 及其运行时触发器管理器结果的收件箱. 自己开始经理.

```typescript
// lib/cogitator.ts
export const cog = new Cogitator({ experimental_triggers: { agents, routines } });
await cog.experimental_triggers?.start();
export const inbox = createInboxHandler(cog.experimental_triggers!, {
  auth: async (req) => ({ userId: await userIdOf(req) }),
});

// app/api/triggers/[id]/[route]/route.ts
export const POST = createTriggerHandler(cog.experimental_triggers!);

// app/api/inbox/route.ts
export const { GET } = inbox;

// app/api/inbox/[id]/route.ts
export const { PATCH } = inbox;
```

| 路线 | 认证 | 体质 |
| --- | --- | --- |
| `POST /api/triggers/:id/fire` | 扳机本身的无记名符号 | `{ "text": "..." }`原始读取 |
| `POST /api/triggers/:id/webhook` | 发送者的签名(HMAC、GitHub、Mailgun、Postmark、SendGrid、Slack) | 任何内容类型, 读取原始 |
| `GET /api/inbox` | `auth` 财务报告和审定财务报表 `anonymous` | `?status=unread&kind=failure&routineId=...&limit=20&before=<ms>` |
| `PATCH /api/inbox/:id` | `auth` 财务报告和审定财务报表 `anonymous` | `{ "status": "read" | "unread" | "archived" }` |

触发处理器本身不认证任何内容:一个触发器按来时的准确顺序检查指使或签名,读取任何内容类型(JSON,表单,多部分)的原始内容可达10个MiB并从未解析或再串行. 一个更大的身体答案 `413 PAYLOAD_TOO_LARGE`,则a `route` 其他 `fire` 财务报告和审定财务报表 `webhook` `404`它以状态、JSON身体和触发器管理器头来回答, `{ error: { code, message } }` 在拒绝。 收件箱的处理者从 `auth` (单位:千美元)`{ userId }`, (中文(简体) ), `undefined` 给匿名电话的 一个没有用户代号的呼叫者,这是每个没有用户代号的呼叫者 `auth`获取 `401 UNAUTHORIZED` 除非 `anonymous: 'allow'` 已经设定了,然后他们就看到没有一件的物品。 呼叫者只看到并更改其项目 `userId`,另一个用户的项目答案 `404 NOT_FOUND`。 。 。 . `params` 可以是承诺(后15后)或物体本身.

## 客户钩

### `useCogitatorChat`

全能聊天钩 有流支持.

```typescript
const {
  // State
  messages, // ChatMessage[]
  input, // string
  isLoading, // boolean
  error, // Error | null
  threadId, // string | undefined

  // Actions
  setInput, // (value: string) => void
  send, // (input?: string, metadata?: Record<string, unknown>) => Promise<void>
  stop, // () => void
  reload, // () => Promise<void>
  setThreadId, // (id: string) => void

  // Message management
  appendMessage, // (message: ChatMessage) => void
  clearMessages, // () => void
  setMessages, // (messages: ChatMessage[]) => void

  // Approvals (see "Approvals")
  pendingApprovals, // PendingApproval[]
  pendingInterrupts, // PendingInterrupt[], the questions the run's tools asked
  resume, // (decisions: ResumeDecisions) => Promise<void>, answers go in `responses`
  approve, // () => Promise<void>
  deny, // (reason?: string) => Promise<void>
} = useCogitatorChat({
  api: '/api/chat',
  threadId: 'optional-thread-id',
  initialMessages: [],
  headers: { 'X-Custom-Header': 'value' },

  // Callbacks
  onError: (error) => console.error(error),
  onFinish: (message) => console.log('Done:', message),
  onToolCall: (toolCall) => console.log('Tool called:', toolCall.name),
  onToolResult: (result) => console.log('Tool result:', result.result, result.presentation),
  onToolCallDropped: (toolCallId) => console.log('Never ran:', toolCallId), // removed from the message
  onReasoning: (delta) => console.log('Thinking:', delta),
  onApprovalRequired: (approvals) => console.log('Waiting for approval:', approvals),
  onInterruptRequired: (interrupts) => console.log('Waiting for answers:', interrupts),

  // Endpoint of a createResumeHandler, for resume/approve/deny
  resumeApi: '/api/chat/resume',

  // Sent with every message, for a thread that already has a run going on
  multitaskStrategy: 'enqueue',

  // Retry configuration
  retry: {
    maxRetries: 3,
    delay: 1000,
    backoff: 'exponential', // 1s, 2s, 4s
  },

  // Resume a stream that drops mid-run (default, false turns it off)
  reconnect: { attempts: 3, delayMs: 1000 },
});
```

#### 重新连接

对付一个处理者 `resumableStreams`,它的事件携带的ID, 钩保留了它得到的最后一次事件的ID。 当流落到跑道中间时(网络失败,或者身体在运行前结束) `finish` 或者说 `error`),它再次以 `Last-Event-ID` 和助理消息继续, 没有丢失或重复的事件。 等着 `delayMs` 在第一次重接之前, 和两倍的时间之前, 之后放弃 `attempts` 在失败或未带来事件的一行中重新连接, 并有最后一个错误( 连续结束的流) `finish` 放弃吧 `The stream ended before the run finished`从来没有一个解答像它做了. `STREAM_NOT_FOUND` (服务器不再保留流)和 `STREAM_RESUME_GAP` (它在 id 之后丢失了事件) 以该错误结束请求: 呼叫 `setMessages` 与线程的线程 从自己的线程赶上. `stop()`, (中文(简体) ), `reload()` 和中断当前信件的新信件也取消其在服务器上的运行(`DELETE` 与 `?streamId=`) (中文(简体) ). 无相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.

#### 随元数据发送

```typescript
// Basic send
await send('Hello!');

// Send with metadata (passed to the run as `context` on the server,
// for the keys the handler accepts: createChatHandler(cogitator, agent, { acceptContext: ['priority'] }))
await send('Analyze this', {
  priority: 'high',
});

// Send using input state
setInput('My message');
await send();
```

#### 信件管理

```typescript
// Add a system message
appendMessage({
  id: crypto.randomUUID(),
  role: 'system',
  content: 'Context updated.',
});

// Clear conversation
clearMessages();

// Replace all messages
setMessages([{ id: '1', role: 'user', content: 'New conversation' }]);
```

### `useCogitatorAgent`

非分流批量请求的钩(研究、分析等).

```typescript
const {
  run, // (input: AgentInput) => Promise<void>
  result, // AgentResponse | null
  reasoning, // string | undefined — result?.reasoning
  pendingApprovals, // PendingApproval[] — result?.pendingApprovals
  resume, // (decisions: ResumeDecisions) => Promise<void>
  isLoading, // boolean
  error, // Error | null
  reset, // () => void
} = useCogitatorAgent({
  api: '/api/research',
  resumeApi: '/api/research/resume',
  headers: { Authorization: 'Bearer token' },

  onError: (error) => console.error(error),
  onSuccess: (result) => console.log('Done:', result.output),

  retry: {
    maxRetries: 2,
    delay: 2000,
    backoff: 'linear',
  },
});

// Execute
await run({
  input: 'Research AI trends in 2025',
  context: { focus: 'enterprise' },
  threadId: 'research-session-1',
});

// Access result
console.log(result?.output);
console.log(result?.toolCalls);
```

## 分流协议

聊天处理器流 Server-Sent Events. 事件名称沿用了Vercel AI SDK事件流风格,但有效载荷是Cogitator的自有`tool-call-*`, (中文(简体) ), `message` 错误, `usage`编号 :`threadId` ),因此使用 `useCogitatorChat` (或你自己的解析器)在客户端而不是AI SDK's `useChat`数字 :

```
data: {"type":"start","messageId":"msg-1","threadId":"thread-abc"}

data: {"type":"text-start","id":"text-1"}

data: {"type":"text-delta","id":"text-1","delta":"Hello"}

data: {"type":"text-delta","id":"text-1","delta":" world"}

data: {"type":"text-end","id":"text-1"}

data: {"type":"tool-call-start","id":"tool-1","toolName":"get_weather"}

data: {"type":"tool-call-delta","id":"tool-1","argsTextDelta":"{\"location\":\"NYC\"}"}

data: {"type":"tool-call-end","id":"tool-1"}

data: {"type":"tool-result","id":"tr-1","toolCallId":"tool-1","result":"72°F"}

data: {"type":"finish","messageId":"msg-1","usage":{...},"threadId":"thread-abc","status":"completed"}

data: [DONE]
```

一个特工与 `reasoning: { summary: true }` 并流出其推理摘要 `reasoning-start`, (中文(简体) ), `reasoning-delta` 财务报告和审定财务报表 `reasoning-end` 事件。 文本或推理块以其第一个三角洲打开,在其它类型的块、工具呼叫或 `finish`,所以块永远不会重叠. `useCogitatorChat` 将三角洲收集到 `message.reasoning` (电话) `onReasoning` )),和"每张相" `createAgentHandler` 返回摘要为 `reasoning` 旁边 `usage.reasoningTokens`, (中文(简体) ), `usage.cachedInputTokens` 财务报告和审定财务报表 `usage.cacheWriteTokens` 当供应商报告时。 这个 `finish` 事件 `createChatHandler` 携带同样的 `usage`,这些计数包括.

暂停的跑步 [核准数](https://npmcn.com/package/%40cogitator-ai/next/#readme-approvals) 发送 `{"type":"approval-required","threadId":"…","approvals":[…]}` 打开块关闭后及关闭前 `finish`,并有一个暂停提问 它的工具被问到 `{"type":"interrupt-required","threadId":"…","interrupts":[…]}` 换个位置.

一个工具的数据部件( A)`context.data()`以下列方式抵达 `{"type":"data","id":"…","name":"…","data":…}`数字 : `useCogitatorChat` 保存每个标识中的最新值 `message.data` 并报告每个人 `onData`,瞬间`"transient":true`只有在这里。 跑步的状态是 `state-snapshot`,则 `state-delta` 贾森 补丁,钩子把它放进去 `state` (电话) `onStateChange`A级 `reset-step` 事件命名了文字和推理部分以及工具的调用,这些调用是从另一个模型上开始的一步,而钩子将它们取出消息.

如果运行失败, 打开的文本或推理块将被关闭 `{"type":"error","message":"...","code":"..."}` 发送事件代替 `finish`A级 `CogitatorError` 保存其信件和代码; 任何其它错误都会被记录在服务器上并作为 `"message":"Internal server error","code":"INTERNAL_ERROR"`。 。 。 .

协议是每个适配器 说话,从 `@cogitator-ai/server-shared`。服务器侧构件导出为自定义处理器 :

```typescript
import { StreamWriter, encodeSSE, generateId } from '@cogitator-ai/next';
import type { StreamEvent, Usage } from '@cogitator-ai/next';
```

## 类型

```typescript
interface ChatMessage {
  id: string;
  role: 'user' | 'assistant' | 'system';
  content: string;
  reasoning?: string; // reasoning summary of an assistant message
  toolCalls?: ToolCall[];
  metadata?: Record<string, unknown>;
  createdAt?: Date;
}

interface AgentInput {
  input: string;
  context?: Record<string, unknown>;
  threadId?: string;
}

interface AgentResponse {
  output: string;
  threadId: string;
  usage: {
    inputTokens: number;
    outputTokens: number;
    totalTokens: number;
    reasoningTokens?: number;
    cachedInputTokens?: number;
    cacheWriteTokens?: number;
  };
  toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[];
  reasoning?: string;
  status: 'completed' | 'paused';
  pendingApprovals?: PendingApproval[];
  structured?: unknown;
  structuredError?: string;
  truncated?: true;
  blocked?: 'content_filter' | 'refusal';
  iterationLimitReached?: true;
  traceId: string;
}

interface PendingApproval {
  toolCallId: string;
  toolName: string;
  arguments: Record<string, unknown>;
  description: string;
  sideEffects?: string[];
}

interface ResumeDecisions {
  decisions?: Record<string, { approved: true } | { approved: false; reason?: string }>;
  defaultDecision?: { approved: true } | { approved: false; reason?: string };
}

interface RetryConfig {
  maxRetries?: number; // default: 0
  delay?: number; // default: 1000ms
  backoff?: 'linear' | 'exponential';
}
```

## 处理错误

两个钩子都提供出错状态和回调:

```typescript
const { error, isLoading } = useCogitatorChat({
  api: '/api/chat',
  onError: (err) => {
    toast.error(err.message);
  },
});

if (error) {
  return <div>Error: {error.message}</div>;
}
```

HTTP 失败被抛出为 `HttpError` (从 `@cogitator-ai/next/client`带有 `status` 属性和信件 `Request failed: 400 - No user message provided`。流层 `error` 事件调用 `onError` 与活动 `message` 跳过 `onFinish`。 。 。 .

在服务器上, a `beforeRun` 在客户端出错时丢出错误 `status` (单位:千美元)`400` 改为 `499`以这一地位、其信息以及 `code` (默认) `UNAUTHORIZED` (单位:千美元) `401`页:1 `CogitatorError` 答案作为失败的运行。 任何其它错误都会被记录和回答 `401 Unauthorized` 所以一个下行的会话店 永远不显示地址 A 类 `parseInput` 丢出答案 `400 INVALID_INPUT`。运行失败遵循以上规则:a `CogitatorError` 保存其信息并 `code`任何其它东西 `Internal server error` 与 `code: "INTERNAL_ERROR"`。 。 。 .

启用重试后, 即时错误( 网络故障, 408/429/ 502/ 503/ 504) 将自动重试; 后退等待被取消 `stop()`数字 :

```typescript
useCogitatorChat({
  api: '/api/chat',
  retry: {
    maxRetries: 3,
    delay: 1000,
    backoff: 'exponential',
  },
});
```

## 取消

停止与 `stop()` 函数。 部分助理信件保存在 `messages`,当连接关闭时,服务器中止代理运行。 通话 `send()` 当一个响应在流 中断它的方式相同。 当组件卸载时中止待决请求; `useCogitatorAgent` 中止上一个 `run()` 当一个新的开始和开始 `reset()`。 。 。 .

```typescript
const { send, stop, isLoading } = useCogitatorChat({ api: '/api/chat' });

// Cancel current request
if (isLoading) {
  stop();
}
```

## 文档

全向导 : [cogitator.app/docs/整合/nextjs](https://cogitator.app/docs/integrations/nextjs)

## 许可证

麻省理工学院

## 常见问题

### @cogitator-ai/next 是什么？

Next\.js Cogitator AI 运行时间的集成

### 如何安装 @cogitator-ai/next？

在项目目录运行 npm install @cogitator-ai/next，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：next（^14\.0\.0 \|\| ^15\.0\.0 \|\| ^16\.0\.0）、react（^18\.2\.0 \|\| ^19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @cogitator-ai/next 支持 TypeScript 吗？

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

### @cogitator-ai/next 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @cogitator-ai/next 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.12\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @cogitator-ai/next 可以商用吗？

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

### @cogitator-ai/next 的下载量有多少？

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

### @cogitator-ai/next 还在维护吗？

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

