# 聊天API

<cite>
**本文引用的文件**
- [src/app/api/chat/route.ts](file://src/app/api/chat/route.ts)
- [src/app/api/chat/permission/route.ts](file://src/app/api/chat/permission/route.ts)
- [src/lib/sdk/message-mapper.ts](file://src/lib/sdk/message-mapper.ts)
- [src/lib/sdk/permission-bridge.ts](file://src/lib/sdk/permission-bridge.ts)
- [src/hooks/use-chat.ts](file://src/hooks/use-chat.ts)
- [src/lib/types.ts](file://src/lib/types.ts)
- [src/lib/sdk/client.ts](file://src/lib/sdk/client.ts)
- [src/components/views/chat-view.tsx](file://src/components/views/chat-view.tsx)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件为 Forge 聊天 API 的权威参考文档，聚焦于 POST /api/chat 端点的 HTTP 方法、请求与响应格式、SSE 事件流，以及权限模式、思考模式与附件处理机制。文档同时覆盖流式响应的实现细节、客户端连接处理方式，并提供请求示例、响应格式说明与错误码定义。

## 项目结构
与聊天 API 相关的关键模块分布如下：
- 后端路由
  - 聊天主路由：src/app/api/chat/route.ts
  - 权限决策路由：src/app/api/chat/permission/route.ts
- SDK 与消息映射
  - 消息映射器：src/lib/sdk/message-mapper.ts
  - 权限桥接器：src/lib/sdk/permission-bridge.ts
  - SDK 客户端封装：src/lib/sdk/client.ts
- 前端集成
  - 聊天 Hook：src/hooks/use-chat.ts
  - 类型定义：src/lib/types.ts
  - 聊天视图（含附件上传）：src/components/views/chat-view.tsx

```mermaid
graph TB
subgraph "前端"
FE_View["ChatView 组件<br/>附件上传/发送"]
FE_Hook["use-chat Hook<br/>SSE 解析/状态管理"]
end
subgraph "后端"
API_Chat["/api/chat<br/>POST 聊天接口"]
API_Permission["/api/chat/permission<br/>POST 权限决策"]
end
subgraph "SDK 层"
SDK_Client["SDK 客户端封装<br/>createForgeQuery(...)"]
SDK_Mapper["消息映射器<br/>SSE 事件生成"]
SDK_Bridge["权限桥接器<br/>permission_request/resolved"]
end
FE_View --> FE_Hook
FE_Hook --> API_Chat
API_Chat --> SDK_Client
SDK_Client --> SDK_Mapper
SDK_Client --> SDK_Bridge
FE_Hook <- --> API_Permission
API_Permission --> SDK_Bridge
```

图表来源
- [src/app/api/chat/route.ts:74-342](file://src/app/api/chat/route.ts#L74-L342)
- [src/app/api/chat/permission/route.ts:6-41](file://src/app/api/chat/permission/route.ts#L6-L41)
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/permission-bridge.ts:62-152](file://src/lib/sdk/permission-bridge.ts#L62-L152)
- [src/hooks/use-chat.ts:314-696](file://src/hooks/use-chat.ts#L314-L696)

章节来源
- [src/app/api/chat/route.ts:74-342](file://src/app/api/chat/route.ts#L74-L342)
- [src/app/api/chat/permission/route.ts:6-41](file://src/app/api/chat/permission/route.ts#L6-L41)
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/permission-bridge.ts:62-152](file://src/lib/sdk/permission-bridge.ts#L62-L152)
- [src/hooks/use-chat.ts:314-696](file://src/hooks/use-chat.ts#L314-L696)

## 核心组件
- POST /api/chat
  - 接收 sessionId、message、permissionMode、thinkingMode、attachments 等参数
  - 基于 SDK 创建查询流，使用 TransformStream 实现即时分块输出
  - 将 SDK 消息映射为多种 SSE 事件类型，支持文本增量、工具调用、思考内容、子代理内容、权限请求/已决、完成标记与错误
- /api/chat/permission
  - 处理前端弹窗的权限决策（allow、allow_session、deny）
  - 通过全局状态在两个路由间共享权限请求上下文
- 消息映射器（MessageMapper）
  - 将 SDK 的 stream_event/assistant/tool_use 等消息转换为前端可消费的 SSE 事件
  - 支持主进程与子代理（agent）两类事件流
- 权限桥接器（PermissionBridge）
  - 在 SDK canUseTool 回调与前端交互之间建立桥梁
  - 发出 permission_request 并等待前端决策，最终返回 SDK 所需的 PermissionResult
- 前端 Hook（use-chat）
  - 建立 SSE 连接，解析事件，维护消息与流状态，支持平滑增量渲染与断线重连缓存

章节来源
- [src/app/api/chat/route.ts:74-342](file://src/app/api/chat/route.ts#L74-L342)
- [src/app/api/chat/permission/route.ts:6-41](file://src/app/api/chat/permission/route.ts#L6-L41)
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/permission-bridge.ts:62-152](file://src/lib/sdk/permission-bridge.ts#L62-L152)
- [src/hooks/use-chat.ts:314-696](file://src/hooks/use-chat.ts#L314-L696)

## 架构总览
下图展示从用户输入到流式响应的完整链路，包括权限决策与附件处理：

```mermaid
sequenceDiagram
participant U as "用户"
participant V as "ChatView 组件"
participant H as "use-chat Hook"
participant C as "/api/chat"
participant Q as "SDK 查询(createForgeQuery)"
participant M as "消息映射器(MessageMapper)"
participant P as "权限桥接器(PermissionBridge)"
U->>V : 输入消息/选择附件
V->>H : 调用 sendMessage(...)
H->>C : POST /api/chat (JSON 请求体)
C->>P : 若需要工具权限则创建 canUseTool 桥接
C->>Q : 启动 SDK 查询流
Q->>M : 逐条产生 SDK 消息
M-->>C : 映射为 SSE 事件(文本/思考/工具/子代理/权限)
C-->>H : SSE data : {...}
H-->>V : 更新消息/渲染增量
C-->>H : 发送 done/error
H-->>V : 结束/错误提示
```

图表来源
- [src/components/views/chat-view.tsx:449-483](file://src/components/views/chat-view.tsx#L449-L483)
- [src/hooks/use-chat.ts:314-696](file://src/hooks/use-chat.ts#L314-L696)
- [src/app/api/chat/route.ts:162-326](file://src/app/api/chat/route.ts#L162-L326)
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/permission-bridge.ts:62-152](file://src/lib/sdk/permission-bridge.ts#L62-L152)

## 详细组件分析

### POST /api/chat 请求与响应
- HTTP 方法与路径
  - 方法：POST
  - 路径：/api/chat
- 请求头
  - Content-Type: application/json
- 请求体字段
  - sessionId: 字符串，会话标识，必填
  - message: 字符串，用户消息内容；若为空且无附件，则视为无效
  - permissionMode: 字符串，权限模式，取值见“权限模式配置”
  - thinkingMode: 字符串，思考模式，取值见“思考模式设置”
  - attachments: 数组，附件信息数组，元素包含 name、filename、mimeType、tier
- 响应
  - Content-Type: text/event-stream
  - 使用 SSE 格式，每条数据以 data: 开头，双换行分隔
  - 流中可能包含以下事件类型：
    - text_delta：文本增量
    - thinking_delta：思考内容增量
    - thinking_start：进入思考阶段
    - tool_use：工具调用开始
    - tool_result：工具执行结果
    - tool_progress：工具进度更新
    - tool_raw_result：原始工具结果（用于调试）
    - agent_content：子代理中间内容（文本/思考/工具/结果/进度等）
    - permission_request：请求用户授权
    - permission_resolved：权限决策已处理
    - attachment：检测到文件/图片附件，随流推送
    - done：对话回合结束，携带 messageId、userMessageId、inputTokens、outputTokens
    - error：发生错误，携带 error 字段
- 错误码
  - 400：请求体非 JSON、缺少必需字段（sessionId 或 message/attachments）、权限决策无效
  - 404：指定 sessionId 不存在
  - 其他：内部异常或 SDK 返回错误，统一映射为 error 事件

章节来源
- [src/app/api/chat/route.ts:74-96](file://src/app/api/chat/route.ts#L74-L96)
- [src/app/api/chat/route.ts:147-342](file://src/app/api/chat/route.ts#L147-L342)
- [src/lib/sdk/message-mapper.ts:11-14](file://src/lib/sdk/message-mapper.ts#L11-L14)
- [src/app/api/chat/permission/route.ts:16-31](file://src/app/api/chat/permission/route.ts#L16-L31)

### 请求参数详解
- sessionId
  - 必填，用于定位会话与模型、工作区上下文
- message
  - 可选，当为空但存在附件时，系统会使用附件名称作为有效消息
- permissionMode
  - 可选，覆盖全局设置；支持 confirm（确认模式）与 full（全量放行）
- thinkingMode
  - 可选，覆盖全局与提供者特定设置；支持 off、auto、max
- attachments
  - 可选，数组，每个元素包含：
    - name：显示名称
    - filename：上传后的安全文件名
    - mimeType：媒体类型
    - tier：附件层级（如 image）

章节来源
- [src/app/api/chat/route.ts:75-96](file://src/app/api/chat/route.ts#L75-L96)
- [src/lib/types.ts:87-87](file://src/lib/types.ts#L87-L87)
- [src/lib/types.ts:24-24](file://src/lib/types.ts#L24-L24)

### 响应事件类型与语义
- 文本与思考
  - text_delta/thinking_delta：增量文本
  - thinking_start：进入长思考阶段
- 工具链路
  - tool_use：工具调用开始（含 id、name、input）
  - tool_result/tool_raw_result：工具执行结果（含 is_error、content 等）
  - tool_progress：工具耗时进度
- 子代理内容
  - agent_content：父工具 use_id 下的子代理中间内容（文本/思考/工具/结果/进度）
- 权限控制
  - permission_request：需要用户授权（包含 requestId、toolName、toolInput、toolUseId）
  - permission_resolved：权限决策已处理（包含 decision）
- 附件
  - attachment：检测到文件/图片附件，推送 { type, url, name, size?, mimeType? }
- 结束与错误
  - done：回合结束，携带 messageId、userMessageId、inputTokens、outputTokens
  - error：错误，携带 error 字符串

章节来源
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/message-mapper.ts:393-458](file://src/lib/sdk/message-mapper.ts#L393-L458)
- [src/lib/sdk/message-mapper.ts:460-475](file://src/lib/sdk/message-mapper.ts#L460-L475)
- [src/lib/sdk/message-mapper.ts:504-523](file://src/lib/sdk/message-mapper.ts#L504-L523)
- [src/lib/sdk/message-mapper.ts:525-533](file://src/lib/sdk/message-mapper.ts#L525-L533)
- [src/lib/sdk/message-mapper.ts:535-642](file://src/lib/sdk/message-mapper.ts#L535-L642)
- [src/lib/sdk/message-mapper.ts:688-703](file://src/lib/sdk/message-mapper.ts#L688-L703)

### 权限模式配置
- confirm（确认模式）
  - SDK 的 canUseTool 回调触发 permission_request，前端弹窗由用户决定 allow/allow_session/deny
  - allow_session 会自动放行该会话下的同类工具后续请求
- full（全量放行）
  - SDK 不再询问，直接允许工具调用
- 优先级
  - 请求体中的 permissionMode 优先于全局设置
  - 未提供时，按全局设置回退

章节来源
- [src/app/api/chat/route.ts:106-108](file://src/app/api/chat/route.ts#L106-L108)
- [src/app/api/chat/route.ts:167-169](file://src/app/api/chat/route.ts#L167-L169)
- [src/lib/sdk/permission-bridge.ts:187-214](file://src/lib/sdk/permission-bridge.ts#L187-L214)

### 思考模式设置
- 支持 off、auto、max
- 优先级顺序：请求体 > 提供者特定键 > 全局键 > 默认 auto
- 提供者特定键形如 thinking_mode_{providerType}

章节来源
- [src/app/api/chat/route.ts:114-118](file://src/app/api/chat/route.ts#L114-L118)
- [src/lib/types.ts:24-24](file://src/lib/types.ts#L24-L24)

### 附件处理
- 上传与预览
  - 前端通过 /api/upload 上传文件，返回 { originalName, path, filename, mimeType, tier, isImage }
  - 发送时以 attachments 数组形式传入 /api/chat
- 服务端解析
  - 将附件映射为 ForgeAttachment[]，仅信任 uploads 目录下的安全路径
  - 从文本块中的 MEDIA: 协议行与工具调用启发式提取文件路径
  - 自动复制到 uploads 目录并通过 /api/upload/{name} 访问
- 流中推送
  - 检测到附件后，立即发出 attachment 事件，前端即时渲染

章节来源
- [src/app/api/chat/route.ts:84-95](file://src/app/api/chat/route.ts#L84-L95)
- [src/app/api/chat/route.ts:240-280](file://src/app/api/chat/route.ts#L240-L280)
- [src/components/views/chat-view.tsx:422-447](file://src/components/views/chat-view.tsx#L422-L447)

### 流式响应实现机制
- TransformStream
  - 使用 TransformStream 避免 Next.js 缓冲整包响应，确保即时分块
- SSE 写入
  - writer.write(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)) 实时推送
- 异常与回退
  - SDK 抛错或“静默失败”（无块）时，自动回退到历史提示 + 新会话重试
- 完成与持久化
  - 收尾时写入 done 事件并持久化消息与会话标题

章节来源
- [src/app/api/chat/route.ts:150-159](file://src/app/api/chat/route.ts#L150-L159)
- [src/app/api/chat/route.ts:194-238](file://src/app/api/chat/route.ts#L194-L238)
- [src/app/api/chat/route.ts:282-303](file://src/app/api/chat/route.ts#L282-L303)

### 客户端连接处理
- 建立 SSE 连接
  - fetch('/api/chat') 获取可读流，逐行解析 data: 行
- 增量渲染
  - 对 text_delta/thinking_delta 使用 60fps 合并刷新，保证顺滑
  - 子代理 agent_content 采用独立 pending 状态合并刷新
- 断线与取消
  - AbortController 支持用户主动停止
  - 客户端断开时触发后端 abortController.abort()

章节来源
- [src/hooks/use-chat.ts:314-696](file://src/hooks/use-chat.ts#L314-L696)

### 权限决策流程
```mermaid
sequenceDiagram
participant SDK as "SDK(canUseTool)"
participant BR as "PermissionBridge"
participant CH as "/api/chat"
participant FE as "前端(use-chat)"
participant EP as "/api/chat/permission"
SDK->>BR : 请求工具权限
BR->>CH : emit(permission_request)
CH-->>FE : SSE permission_request
FE->>EP : POST {requestId, decision}
EP-->>BR : resolvePermission(...)
BR-->>SDK : PermissionResult(allow/deny)
```

图表来源
- [src/lib/sdk/permission-bridge.ts:62-152](file://src/lib/sdk/permission-bridge.ts#L62-L152)
- [src/app/api/chat/permission/route.ts:33-40](file://src/app/api/chat/permission/route.ts#L33-L40)
- [src/hooks/use-chat.ts:673-687](file://src/hooks/use-chat.ts#L673-L687)

## 依赖关系分析
- 路由层依赖
  - /api/chat 依赖 SDK 客户端封装、消息映射器、权限桥接器、数据库与工作区文件系统
- SDK 层依赖
  - createForgeQuery(...) 由 SDK 客户端封装提供，负责构建查询流
  - MessageMapper 将 SDK 消息映射为 SSE 事件
  - PermissionBridge 在 canUseTool 与前端之间传递决策
- 前端依赖
  - use-chat 依赖 SSE 解析、消息状态管理、附件上传与权限决策提交

```mermaid
graph LR
R["/api/chat"] --> C["SDK 客户端封装"]
R --> M["消息映射器"]
R --> B["权限桥接器"]
R --> D["数据库/文件系统"]
H["use-chat Hook"] --> R
H --> P["/api/chat/permission"]
```

图表来源
- [src/app/api/chat/route.ts:14-16](file://src/app/api/chat/route.ts#L14-L16)
- [src/lib/sdk/client.ts:14-27](file://src/lib/sdk/client.ts#L14-L27)
- [src/lib/sdk/message-mapper.ts:8-9](file://src/lib/sdk/message-mapper.ts#L8-L9)
- [src/lib/sdk/permission-bridge.ts:14-16](file://src/lib/sdk/permission-bridge.ts#L14-L16)
- [src/hooks/use-chat.ts:314-325](file://src/hooks/use-chat.ts#L314-L325)

章节来源
- [src/app/api/chat/route.ts:14-16](file://src/app/api/chat/route.ts#L14-L16)
- [src/lib/sdk/client.ts:14-27](file://src/lib/sdk/client.ts#L14-L27)
- [src/lib/sdk/message-mapper.ts:8-9](file://src/lib/sdk/message-mapper.ts#L8-L9)
- [src/lib/sdk/permission-bridge.ts:14-16](file://src/lib/sdk/permission-bridge.ts#L14-L16)
- [src/hooks/use-chat.ts:314-325](file://src/hooks/use-chat.ts#L314-L325)

## 性能考量
- 即时分块
  - 使用 TransformStream 避免整包缓冲，降低首字节延迟
- 增量渲染
  - 主文本与思考内容采用 60fps 合并刷新，提升感知流畅度
- 令牌统计
  - 通过 SDK result 中的 usage 字段记录 input/output tokens，便于成本统计
- 会话恢复与回退
  - 会话恢复失败时自动回退至历史提示 + 新会话，避免长时间阻塞

章节来源
- [src/app/api/chat/route.ts:150-159](file://src/app/api/chat/route.ts#L150-L159)
- [src/hooks/use-chat.ts:196-312](file://src/hooks/use-chat.ts#L196-L312)
- [src/lib/sdk/message-mapper.ts:688-703](file://src/lib/sdk/message-mapper.ts#L688-L703)
- [src/app/api/chat/route.ts:194-238](file://src/app/api/chat/route.ts#L194-L238)

## 故障排查指南
- 常见错误与处理
  - 400：请求体非 JSON 或缺少 sessionId/message/attachments；检查请求体格式与必填项
  - 404：sessionId 不存在；确认会话是否创建或仍存在
  - error 事件：SDK 返回错误或运行时异常；查看 error 字符串并重试
- 权限相关
  - permission_request 长时间不出现：确认前端是否正确弹窗并提交决策
  - allow_session 未生效：检查会话活动清理逻辑与超时设置
- 附件问题
  - attachment 事件缺失：检查 MEDIA: 协议行与工具调用启发式提取是否命中
  - 文件无法访问：确认 uploads 目录权限与 /api/upload/{name} 路由可用性
- 断线与取消
  - 用户点击停止：使用 AbortController 触发后端中断
  - 客户端断开：后端捕获 abort 信号并关闭 writer

章节来源
- [src/app/api/chat/route.ts:76-80](file://src/app/api/chat/route.ts#L76-L80)
- [src/app/api/chat/route.ts:104-104](file://src/app/api/chat/route.ts#L104-L104)
- [src/app/api/chat/permission/route.ts:16-31](file://src/app/api/chat/permission/route.ts#L16-L31)
- [src/lib/sdk/permission-bridge.ts:158-182](file://src/lib/sdk/permission-bridge.ts#L158-L182)
- [src/hooks/use-chat.ts:646-667](file://src/hooks/use-chat.ts#L646-L667)

## 结论
Forge 聊天 API 通过清晰的请求/响应契约与完善的 SSE 事件体系，实现了高吞吐、低延迟的流式对话体验。权限与思考模式的灵活配置满足不同场景需求，附件处理与子代理内容支持进一步增强多模态与复杂任务能力。建议在生产环境中结合令牌统计与会话清理策略，持续优化性能与稳定性。

## 附录

### 请求示例
- 发送纯文本
  - POST /api/chat
  - Body:
    - sessionId: "会话ID"
    - message: "你好"
- 发送带附件
  - POST /api/chat
  - Body:
    - sessionId: "会话ID"
    - attachments:
      - { name: "图片", filename: "abc.jpg", mimeType: "image/jpeg", tier: "image" }
      - { name: "文档", filename: "doc.txt", mimeType: "text/plain", tier: "file" }

章节来源
- [src/components/views/chat-view.tsx:467-478](file://src/components/views/chat-view.tsx#L467-L478)

### 响应事件示例
- 文本增量
  - data: {"type":"text_delta","text":"你好"}
- 工具调用
  - data: {"type":"tool_use","id":"u1","name":"WebSearch","input":{...}}
- 子代理内容
  - data: {"type":"agent_content","parent_tool_use_id":"u1","block_type":"text_delta","text":"分析中..."}
- 权限请求
  - data: {"type":"permission_request","requestId":"req1","toolName":"WebSearch","toolInput":{...},"toolUseId":"u1"}
- 完成
  - data: {"type":"done","messageId":"msg_assistant","userMessageId":"msg_user","inputTokens":120,"outputTokens":80}
- 错误
  - data: {"type":"error","error":"工具执行失败"}

章节来源
- [src/lib/sdk/message-mapper.ts:53-85](file://src/lib/sdk/message-mapper.ts#L53-L85)
- [src/lib/sdk/message-mapper.ts:393-458](file://src/lib/sdk/message-mapper.ts#L393-L458)
- [src/lib/sdk/message-mapper.ts:504-523](file://src/lib/sdk/message-mapper.ts#L504-L523)
- [src/lib/sdk/message-mapper.ts:525-533](file://src/lib/sdk/message-mapper.ts#L525-L533)
- [src/lib/sdk/message-mapper.ts:535-642](file://src/lib/sdk/message-mapper.ts#L535-L642)
- [src/lib/sdk/message-mapper.ts:688-703](file://src/lib/sdk/message-mapper.ts#L688-L703)