# ChatSession & Message API(MVP-1) 基地址:`http://localhost:8000/api`(FrankenPHP 容器 8000 端口) 认证方式:JWT,`Authorization: Bearer {token}` 自然语言:中文 ## 变更记录 - 2025-02-14:新增 ChatSession 创建、消息追加、增量查询接口;支持状态门禁与 dedupe 幂等。 - 2025-02-14:MVP-1.1 增加会话列表、会话更新(重命名/状态变更),列表附带最后一条消息摘要。 ## 领域模型 - `ChatSession`:`session_id`(UUID)、`session_name`、`status`(`OPEN`/`LOCKED`/`CLOSED`)、`last_seq` - `Message`:`message_id`(UUID)、`session_id`、`role`(`USER`/`AGENT`/`TOOL`/`SYSTEM`)、`type`(字符串)、`content`、`payload`(json)、`seq`(会话内递增)、`reply_to`(UUID)、`dedupe_key` - 幂等:`UNIQUE (session_id, dedupe_key)`;同一 dedupe_key 返回已有消息。 - 状态门禁:`CLOSED` 禁止追加,例外 `role=SYSTEM && type in [run.status, error]`;`LOCKED` 禁止 `role=USER && type=user.prompt`。 - 会话缓存:`chat_sessions.last_message_id` 记录最后一条消息;`appendMessage` 事务内同步更新 `last_seq`、`last_message_id`、`updated_at`。 ## 接口 ### 创建会话 - `POST /sessions` - 请求体字段: - `session_name` (string, 可选,<=255):会话名称。 - 响应 201 字段: - `session_id` (uuid) - `session_name` (string|null) - `status` (`OPEN|LOCKED|CLOSED`) - `last_seq` (int) - `last_message_id` (uuid|null) - `created_at` / `updated_at` ### 追加消息 - `POST /sessions/{session_id}/messages` - 请求体字段: - `role` (required, `USER|AGENT|TOOL|SYSTEM`) - `type` (required, string, <=64),如 `user.prompt`/`agent.message` 等。 - `content` (string|null) - `payload` (object|null) 作为 jsonb 存储。 - `reply_to` (uuid|null) - `dedupe_key` (string|null, <=128) 幂等键。 - 响应 201 字段: - `message_id` (uuid) - `session_id` (uuid) - `seq` (int,会话内递增) - `role` / `type` / `content` / `payload` / `reply_to` / `dedupe_key` - `created_at` - 403:违反状态门禁(CLOSED 禁止,LOCKED 禁止 user.prompt)。 - 幂等:同 session + dedupe_key 返回已有消息(同 `message_id/seq`)。 ### 按序增量查询 - `GET /sessions/{session_id}/messages?after_seq=0&limit=50` - 查询参数: - `after_seq` (int, 默认 0):仅返回大于该 seq 的消息。 - `limit` (int, 默认 50,<=200)。 - 响应 200:`data` 数组,元素字段同“追加消息”响应。 ### 会话列表 - `GET /sessions?page=1&per_page=15&status=OPEN&q=keyword` - 查询参数: - `page` (int, 默认 1) - `per_page` (int, 默认 15,<=100) - `status` (`OPEN|LOCKED|CLOSED`,可选) - `q` (string,可选,对 `session_name` ILIKE 模糊匹配) - 响应 200:分页结构(`data/links/meta`),`data` 每项字段: - `session_id, session_name, status, last_seq, created_at, updated_at` - `last_message_id` - `last_message_at` - `last_message_preview`(content 截断 120,content 为空则空字符串) - `last_message_role, last_message_type` - 排序:`updated_at` DESC ### 会话更新 - `PATCH /sessions/{session_id}` - 请求体(至少提供一项,否则 422): - `session_name` (string, 1..255,可选,自动 trim) - `status` (`OPEN|LOCKED|CLOSED`,可选) - 规则: - `CLOSED` 不可改回 `OPEN`(返回 403)。 - 任意更新都会刷新 `updated_at`。 - 响应 200 字段:同会话列表项字段。 ## cURL 示例 ```bash # 创建会话 SESSION_ID=$(curl -s -X POST http://localhost:8000/api/sessions \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"session_name":"Demo"}' | jq -r '.data.session_id') # 追加消息(支持 dedupe_key 幂等) curl -s -X POST http://localhost:8000/api/sessions/$SESSION_ID/messages \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"role":"USER","type":"user.prompt","content":"hello","dedupe_key":"k1"}' # 增量查询 curl -s "http://localhost:8000/api/sessions/$SESSION_ID/messages?after_seq=0&limit=50" \ -H "Authorization: Bearer $TOKEN" ```