Files
ars-backend/docs/ChatSession/chat-session-api.md
ROOG 318571a6d9 main: 增强会话功能,支持归档与消息检索
- 添加会话归档接口及相关服务逻辑,并确保幂等性
- 实现单条消息获取接口,校验消息所属会话
- 增加 SSE 增量推送与实时消息订阅功能
- 提供相关的测试用例覆盖新功能
- 更新接口文档,完善 OpenAPI 规范,新增多项示例
2025-12-14 21:58:05 +08:00

7.2 KiB
Raw Blame History

ChatSession & Message APIMVP-1

基地址:http://localhost:8000/apiFrankenPHP 容器 8000 端口)
认证方式JWTAuthorization: Bearer {token}
自然语言:中文

变更记录

  • 2025-02-14新增 ChatSession 创建、消息追加、增量查询接口;支持状态门禁与 dedupe 幂等。
  • 2025-02-14MVP-1.1 增加会话列表、会话更新(重命名/状态变更),列表附带最后一条消息摘要。

领域模型

  • ChatSessionsession_id(UUID)、session_namestatus(OPEN/LOCKED/CLOSED)、last_seq
  • Messagemessage_id(UUID)、session_idrole(USER/AGENT/TOOL/SYSTEM)、type(字符串)、contentpayload(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_seqlast_message_idupdated_at

接口

创建会话

  • POST /sessions
  • 请求体字段
    字段 必填 类型 说明
    session_name string(≤255) 会话名称
  • 响应 201JSON
    字段 类型 说明
    session_id uuid 主键
    session_name string null
    status enum `OPEN
    last_seq int 当前最大 seq
    last_message_id uuid null
    created_at, updated_at datetime 时间戳
  • 错误401 未授权

追加消息

  • POST /sessions/{session_id}/messages
  • 请求体字段
    字段 必填 类型 说明
    role enum `USER
    type string(≤64) user.prompt/agent.message
    content string 文本内容
    payload object jsonb 结构
    reply_to uuid 引用消息
    dedupe_key string(≤128) 幂等键
  • 响应 201JSON
    字段:message_id, session_id, seq, role, type, content, payload, reply_to, dedupe_key, created_at
  • 幂等:同 session + dedupe_key 返回已存在的消息(同 message_id/seq)。
  • 错误401 未授权403 违反状态门禁CLOSED 禁止LOCKED 禁止 user.prompt404 session 不存在422 校验失败。

按序增量查询

  • GET /sessions/{session_id}/messages?after_seq=0&limit=50
  • 查询参数
    参数 默认 类型 说明
    after_seq 0 int 仅返回 seq 大于该值
    limit 50 int(≤200) 返回数量上限
  • 响应 200data 数组,元素字段同“追加消息”响应。
  • 错误401/404/422

会话列表

  • GET /sessions?page=1&per_page=15&status=OPEN&q=keyword
  • 查询参数
    参数 默认 类型 说明
    page 1 int 分页页码
    per_page 15 int(≤100) 分页大小
    status - enum 过滤 `OPEN
    q - string ILIKE 模糊匹配 session_name
  • 响应 200分页结构data/links/metadata 每项字段:
    字段 类型 说明
    session_id uuid 会话主键
    session_name string null
    status enum `OPEN
    last_seq int 当前最大 seq
    last_message_id uuid null
    last_message_at datetime null
    last_message_preview string content 截断 120空内容返回空字符串
    last_message_role string null
    last_message_type string null
    created_at, updated_at datetime 时间戳
  • 排序:updated_at DESC
  • 错误401/422

会话更新

  • PATCH /sessions/{session_id}
  • 请求体(至少一项,否则 422
    字段 必填 类型 说明
    session_name string 1..255 自动 trim
    status enum `OPEN
  • 规则:
    • CLOSED 不可改回 OPEN(返回 403
    • 任意更新都会刷新 updated_at
  • 响应 200字段同“会话列表”项。
  • 错误401 未授权403 状态门禁404 session 不存在422 校验失败。

获取会话详情

  • GET /sessions/{session_id}
  • 响应 200字段同“会话列表”项。
  • 错误401 未授权404 session 不存在。

归档会话Archive

  • POST /sessions/{session_id}/archive
  • 行为:将 status 置为 CLOSED,更新 updated_at,幂等(重复归档返回当前状态)。
  • 响应 200字段同“会话列表”项status=CLOSED
  • 错误401 未授权404 session 不存在。

获取单条消息(带会话校验)

  • GET /sessions/{session_id}/messages/{message_id}
  • 行为:校验 message.session_id 与路径参数一致,否则 404。
  • 响应 200字段同“追加消息”响应。
  • 错误401 未授权404 不存在或不属于该会话。

SSE 实时增量

  • GET /sessions/{session_id}/sse?after_seq=123
  • 头部:Accept: text/event-stream,可带 Last-Event-ID(优先于 query用于断线续传。
  • 查询参数
    参数 默认 类型 说明
    after_seq 0 int backlog 起始 seq若有 Last-Event-ID 则覆盖)
    limit 200 int(≤500) backlog 最多条数
  • SSE 输出格式:
    id: {seq}
    event: message
    data: {...message json...}
    
    
    • id 为消息 seq,便于续传;data 为消息 JSON同追加消息响应字段
  • Backlog建立连接后先补发 seq > after_seq 的消息order asc最多 limit 条),再进入实时订阅。
  • 实时Redis channel session:{session_id}:messages 发布消息 IDSSE 侧读取后按 seq 去重、推送。
  • 心跳:周期输出 : ping 保活(生产环境)。
  • 错误401 未授权404 session 不存在。

cURL 示例

# 创建会话
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"

# 归档
curl -X POST http://localhost:8000/api/sessions/$SESSION_ID/archive \
  -H "Authorization: Bearer $TOKEN"

# 获取单条消息
curl -s http://localhost:8000/api/sessions/$SESSION_ID/messages/{message_id} \
  -H "Authorization: Bearer $TOKEN"

# SSE断线续传可带 Last-Event-ID
curl -N http://localhost:8000/api/sessions/$SESSION_ID/sse?after_seq=10 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: text/event-stream"