doatlas-2 / docs /API_CONTRACT.md
Iostream-Li's picture
Add files using upload-large-folder tool
2a55985 verified

DoAtlas 前端 ↔ 后端 接口契约 v1.1

本文是前端实现所依据的完整 HTTP API 契约。后端按此实现即可与现有 React 前端对接。 Base URL:https://doaltas.cn.com(前端通过 VITE_API_BASE_URL 配置)。 所有路径以 /api 开头。

文档版本:v1.1(2026-04-20)—— 与前端 doatlas-web-v1 同步。 任何破坏性变更必须升级该版本号并在文末「变更记录」中记录。


品牌资源

资源 路径 / 用途
Logo(主) artifacts/doatlas-web/public/doatlas-logo.png —— 圆形 DNA + 大脑/双手图标,主品牌标识
Logo 组件 src/components/brand/logo.tsx,前端统一通过 <Logo /> 引用
应用名 DoAtlas(首字母 D、A 大写)
中文标语 「为生物医学研究者打造的协同工作台」
英文 tagline "DoAtlas Workbench" / "A collaborative workbench built for biomedical researchers"
主色 hsl(221 83% 53%) — 与 --primary token 对齐

后端如需在邮件、分享页 OG 图、PDF 导出等场景使用 logo,请直接复用 public/doatlas-logo.png,不要再次绘制。


0. 通用约定

0.1 请求头(前端始终发送)

Header 含义
Content-Type: application/json 除文件上传外的所有请求
Authorization: Bearer <access_token> 登录后所有请求
X-Request-ID 形如 REQ:web:<uuid-v4>,用于全链路追踪
X-Client-Version 前端版本号字符串,例如 doatlas-web-v1
Accept-Language 当前用户语言,BCP-47:zh-CNen-US。后端用于错误消息本地化、邮件模板选择

0.2 响应封装

成功:直接返回业务对象 JSON,不要嵌套 data/code/success 等外壳。

错误:HTTP 状态码 ≥ 400,body 必须是:

{
  "error": "Human readable message",
  "error_code": "snake_case_code",
  "retryable": true,
  "retry_after_seconds": 30,
  "request_id": "REQ:http:abcd1234",
  "details": { "field": "..." }
}
  • error 必填;其余可选,但建议都返回。
  • 401 触发前端清 token、跳转 /login
  • 429 时若有 retry_after_seconds,前端会按值退避。

0.3 通用 ID 前缀

类型 前缀 示例
用户 usr_ usr_01HXY...
会话 cnv_ cnv_01HXY...
消息 msg_ msg_01HXY...
文件夹/项目 fld_ fld_01HXY...
附件 att_ att_01HXY...
模型 mdl_ mdl_glm-4.6
任务/Job job_ job_01HXY...
制品 art_ art_01HXY...
分享 shr_ shr_01HXY...

ID 推荐使用 ULID 以保证可排序。

0.4 时间戳

全部 ISO-8601 UTC,例:"2026-04-20T02:11:00.123Z"

0.5 分页

游标式分页:

请求:?cursor=<opaque>&limit=20

响应:

{
  "items": [...],
  "next_cursor": "opaque-string-or-null",
  "has_more": true
}

0.6 CORS

后端必须允许:

  • Origin: <前端实际域名>(开发态包括 http://localhost 与 Replit 的 *.replit.dev,生产为 https://doaltas.cn.com 自身或独立前端域)
  • Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
  • Headers: Content-Type, Authorization, X-Request-ID, X-Client-Version, Accept-Language
  • Expose-Headers: X-Request-ID
  • Credentials: false(前端不依赖 cookie,token 走 Authorization 头)

0.7 国际化(i18n)

  • 前端目前支持 简体中文(zh-CN英文(en-US 两种界面语言,存储 key:localStorage.doatlas_lang(值 "zh" / "en")。
  • 用户可在「设置 → 通用 → 语言」、侧栏个人菜单的 Language 子菜单、命令面板(⌘K)以及登录页右上角快速切换。
  • 切换会立即更新:
    1. <html lang="zh-CN" | "en">
    2. Accept-Language 请求头
    3. Settings.language 字段(通过 PATCH /api/settings
  • 后端业务文本(错误信息、邮件、PDF 导出标题等)应根据 Accept-Language 切换中英两版;缺省回退到 zh-CN
  • 数据本身(用户输入、模型回复、附件名称等)保持原样,不要做翻译。
  • 模型回复语言由模型自身遵循 system_prompt / 用户上下文决定,与界面语言解耦。

0.8 鉴权与会话

  • 所有 /api/auth/* 之外的接口都需要有效的 Authorization: Bearer ...
  • 401 必须返回标准错误体;前端将清除本地 token 并跳转 /login
  • token 过期时间建议 ≥ 7 天;如使用 refresh token 模式,请在响应中提供 refresh_token,并新增 POST /api/auth/refresh 端点(可选,前端目前未要求)。
  • 公开接口(无需鉴权)目前只有 GET /api/share/{token}

1. 认证与账户

1.1 POST /api/auth/register

注册。

Body

{
  "email": "user@example.com",
  "username": "alice",
  "password": "string (>=8)",
  "invite_code": "string"
}

200

{
  "access_token": "jwt-or-opaque",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "user": { ... User ... }
}

错误码invalid_invite_codeemail_takenusername_takenweak_password

1.2 POST /api/auth/login

Body

{ "identifier": "alice 或 user@example.com", "password": "..." }

200:同 1.1。 错误码invalid_credentialsaccount_locked

1.3 POST /api/auth/logout

吊销当前 token。204

1.4 GET /api/auth/me

200

{
  "user": { ... User ... },
  "feature_flags": {
    "streaming": true,
    "voice": false,
    "attachments": true,
    "artifacts": false,
    "search": true,
    "share": true,
    "custom_instructions": true,
    "jobs": false
  }
}

feature_flags 用于前端 capability 判断;任何 flag 为 false 的功能在 UI 中会自动隐藏或显示「即将推出」。后端可按部署灰度返回不同值。

1.5 POST /api/auth/password/change

Body { "old_password": "...", "new_password": "..." }204

1.6 POST /api/auth/password/reset/request

Body { "email": "..." }204(无论邮箱是否存在都返回 204,避免枚举)。

1.7 POST /api/auth/password/reset/confirm

Body { "token": "...", "new_password": "..." }204

1.8 User 对象

{
  id: "usr_...",
  email: "user@example.com",
  username: "alice",
  display_name: "Alice",
  avatar_url: "https://... | null",
  role: "user" | "admin",
  created_at: "...",
  quota: {
    plan: "free" | "pro" | "team",
    period_start: "...",
    period_end: "...",
    tokens_limit: 5000000,
    tokens_used: 123456
  }
}

2. 会话(Conversations)

2.1 GET /api/conversations

列出会话。

Query

  • cursorlimit(默认 30,最大 100)
  • q:标题模糊搜索
  • folder_id:限定文件夹;folder_id=none 表示未归档
  • pinnedtrue|false
  • archivedtrue|false(默认 false
  • sortupdated_desc(默认)| created_desc

200

{
  "items": [ { ... ConversationSummary ... } ],
  "next_cursor": null,
  "has_more": false
}

ConversationSummary

{
  id: "cnv_...",
  title: "Trastuzumab 在 HER2+ 乳腺癌中的最新进展",
  folder_id: "fld_... | null",
  pinned: false,
  archived: false,
  model_id: "mdl_glm-4.6",
  message_count: 12,
  preview: "最近一段助手回复的前 120 字…",
  created_at: "...",
  updated_at: "...",
  last_message_at: "..."
}

2.2 POST /api/conversations

创建新会话。可同时附第一条消息(前端首问即建会话)。

Body

{
  "title": "可选;缺省由后端按首问生成",
  "model_id": "mdl_glm-4.6",
  "folder_id": null,
  "system_prompt": null,
  "first_message": {                           // 可选
    "content": "帮我查一下 PD-1 抑制剂的副作用",
    "attachment_ids": ["att_..."]
  }
}

201Conversation 完整对象。若包含 first_message,应在创建后将该消息以同步方式入库(响应里 messages 至少包含这一条 user 消息;助手回复需走流式接口)。

Conversation(详情)

{
  ...ConversationSummary,
  system_prompt: "string | null",
  share: { token: "shr_...", url: "https://..." } | null,
  // 详情可不包含 messages,独立接口拉取
}

2.3 GET /api/conversations/{id}

返回 Conversation 详情。404 not_found

2.4 PATCH /api/conversations/{id}

Body(任意字段可选)

{
  "title": "...",
  "pinned": true,
  "archived": false,
  "folder_id": "fld_... | null",
  "system_prompt": "...",
  "model_id": "mdl_..."
}

200:更新后的 Conversation

2.5 DELETE /api/conversations/{id}204

2.6 POST /api/conversations/{id}/share

开启分享。200

{ "token": "shr_...", "url": "https://doaltas.cn.com/share/shr_..." }

2.7 DELETE /api/conversations/{id}/share204

2.8 GET /api/share/{token}(无需鉴权)

公开访问已分享的会话。200:返回精简版 Conversation + 消息列表(不含敏感信息、不含工具内部参数)。


3. 消息(Messages)

3.1 GET /api/conversations/{id}/messages

Querycursorlimit(默认 50)、order=asc|desc(默认 asc,从早到晚)。

200:分页结果,items: Message[]

Message

{
  id: "msg_...",
  conversation_id: "cnv_...",
  role: "user" | "assistant" | "system" | "tool",
  status: "complete" | "streaming" | "stopped" | "error",
  content: [                                          // 多模态内容块数组
    { "type": "text", "text": "..." },
    { "type": "image", "attachment_id": "att_...", "url": "..." },
    { "type": "file",  "attachment_id": "att_...", "name": "...", "mime": "..." },
    { "type": "tool_call",   "tool_call_id": "tc_...", "name": "search_pubmed", "arguments": {...} },
    { "type": "tool_result", "tool_call_id": "tc_...", "result": {...}, "is_error": false },
    { "type": "artifact",    "artifact_id": "art_..." }
  ],
  parent_id: "msg_... | null",                        // 用于分支/重新生成
  model_id: "mdl_glm-4.6 | null",                     // assistant 才有
  stop_reason: "end_turn" | "stop_sequence" | "max_tokens" | "tool_use" | "user_stopped" | "error" | null,
  usage: { "input_tokens": 1234, "output_tokens": 567 } | null,
  feedback: { "rating": "up" | "down" | null, "reason": "..." | null } | null,
  edited: false,
  created_at: "..."
}

3.2 POST /api/conversations/{id}/messages(非流式)

不走流式时使用,返回创建的 user 消息 + 完整 assistant 回复。

Body

{
  "content": "string,纯文本",
  "attachment_ids": ["att_..."],
  "parent_id": null,
  "model_id": "mdl_glm-4.6 | null",
  "options": {
    "temperature": 0.7,
    "max_tokens": 4096,
    "tools_enabled": true
  }
}

200

{
  "user_message": { ... Message ... },
  "assistant_message": { ... Message ... }
}

3.3 POST /api/conversations/{id}/messages/stream流式 SSE

请求体同 3.2。响应 Content-Type: text/event-stream

事件协议

每条事件 event: <name> + data: <json>,以双换行分隔。后端应每 15s 发一行注释 : ping\n\n 作为心跳。

event data 字段
conversation { "conversation_id": "cnv_...", "title_updated": "新标题"| null }(仅当后端自动生成或更新标题时返回 title_updated
message_start { "user_message": Message, "assistant_message_id": "msg_...", "model_id": "..." }
content_delta { "delta": { "type": "text", "text": "片段..." } }{ "delta": { "type": "tool_call", ... } }
content_block_start { "index": 0, "block": { "type": "text" | "tool_call" | "artifact", ... } }
content_block_stop { "index": 0 }
tool_call { "tool_call_id": "tc_...", "name": "...", "arguments": {...} }
tool_result { "tool_call_id": "tc_...", "result": {...}, "is_error": false }
artifact { "artifact": Artifact }
job_started { "job_id": "job_...", "kind": "..." }
usage { "input_tokens": N, "output_tokens": N }
message_complete { "assistant_message": Message }
error { "error": "...", "error_code": "...", "request_id": "..." }

取消:客户端关闭连接 == 中止。后端应将该 assistant 消息标记 status: "stopped" 并入库。

3.4 POST /api/conversations/{id}/messages/{message_id}/regenerate

Body

{ "model_id": "mdl_... | null", "options": { ... } }

行为:以 message_id(assistant 消息)的父级为基准,再生成一条同级 assistant 消息(兄弟分支),不删除旧消息。返回与 3.3 相同的 SSE 流(接口形式上 POST,响应是 SSE)。

3.5 PATCH /api/conversations/{id}/messages/{message_id}

仅支持编辑用户消息。

Body { "content": "..." } 行为:将该消息内容更新,并把它之后的所有消息软删除(保留历史以便分支),随后客户端会立即调用 3.3 重新触发助手回复。 200:更新后的 Messageedited: true

3.6 DELETE /api/conversations/{id}/messages/{message_id}204

3.7 POST /api/conversations/{id}/messages/{message_id}/feedback

Body { "rating": "up" \| "down" \| null, "reason": "string \| null" }204

3.8 POST /api/conversations/{id}/messages/{message_id}/stop

显式停止仍在生成的消息(除关闭 SSE 连接外的兜底)。204


4. 文件夹 / 项目(Folders / Projects)

类似 ChatGPT「Projects」/Claude「Projects」,让用户把会话归类、共享系统提示与知识库。

4.1 GET /api/folders → 列表(不分页)

200

{ "items": [ { ... Folder ... } ] }

Folder

{
  id: "fld_...",
  name: "肿瘤药理研究",
  description: "Onco group shared workspace",
  color: "#2563EB | null",
  icon: "beaker | null",                  // 命名图标 key
  system_prompt: "string | null",
  conversation_count: 42,
  created_at: "...",
  updated_at: "..."
}

4.2 POST /api/folders

Body { "name", "description?", "color?", "icon?", "system_prompt?" }201 Folder

4.3 PATCH /api/folders/{id}200 Folder

4.4 DELETE /api/folders/{id}?move_to=fld_...204move_to 可选;缺省时其下会话置为 folder_id: null


5. 模型(Models)

5.1 GET /api/models

200

{
  "models": [
    {
      "id": "mdl_glm-4.6",
      "name": "GLM-4.6",
      "provider": "Zhipu",
      "description": "通用强模型,长上下文 128k",
      "context_length": 131072,
      "capabilities": ["text", "vision", "tools", "streaming"],
      "pricing": { "input_per_1k": 0, "output_per_1k": 0 },
      "default": true,
      "available": true
    }
  ]
}

6. 附件(Attachments)

6.1 POST /api/attachments

multipart/form-data:字段 file(必填),可选 purpose=chat|avatar|knowledge

201

{
  "id": "att_...",
  "name": "trial-protocol.pdf",
  "mime": "application/pdf",
  "size": 412384,
  "url": "https://...signed...",
  "thumbnail_url": "https://... | null",
  "purpose": "chat",
  "created_at": "..."
}

6.2 GET /api/attachments/{id} → 同上对象。

6.3 DELETE /api/attachments/{id}204


7. 设置(Settings)

7.1 GET /api/settings → 当前用户的全部设置。

7.2 PATCH /api/settings → 局部更新;返回更新后的完整设置。

注意:PATCH 接受任意子集,未提供的字段保持原值。嵌套对象(如 appearance)按整对象替换 —— 前端在改其中一项时会回填其他字段。

Settings

{
  appearance: {
    theme: "system" | "light" | "dark",
    density: "comfortable" | "compact",
    font_scale: 1.0,
    code_theme: "github-light" | "github-dark" | "dracula" | "..."
  },
  language: "zh-CN" | "en-US",
  default_model_id: "mdl_glm-4.6",
  send_on_enter: true,
  show_token_count: true,
  spellcheck: true,
  voice: { enabled: false, voice_id: null, speed: 1.0 },
  data_controls: {
    chat_history_enabled: true,
    improve_model_with_my_data: false,
    auto_archive_after_days: 0    // 0 关闭
  },
  beta_features: { streaming: true, code_interpreter: false },
  notifications: {
    job_completed: true,
    weekly_digest: false
  }
}

8. 个性化指令(Custom Instructions)

类似 ChatGPT 的 System-level 偏好,作用于该用户全部会话。

8.1 GET /api/custom-instructions

8.2 PUT /api/custom-instructions

{
  about_me: "string,<=1500 字",          // “你应该了解我什么”
  response_style: "string,<=1500 字",     // “你应当如何回应我”
  enabled: true
}

9. 用量与配额(Usage)

9.1 GET /api/usage?period=current|last_30d|all

{
  "period_start": "...",
  "period_end": "...",
  "tokens_used": 123456,
  "tokens_limit": 5000000,
  "by_model": [
    { "model_id": "mdl_glm-4.6", "input_tokens": 100000, "output_tokens": 23456 }
  ],
  "by_day": [
    { "date": "2026-04-19", "input_tokens": 4000, "output_tokens": 1200 }
  ]
}

10. 搜索(Search)

10.1 GET /api/search?q=...&scope=conversations|messages|all&limit=20

{
  "results": [
    {
      "type": "conversation",
      "conversation_id": "cnv_...",
      "title": "...",
      "snippet": "...<mark>关键词</mark>...",
      "matched_at": "..."
    },
    {
      "type": "message",
      "conversation_id": "cnv_...",
      "message_id": "msg_...",
      "role": "assistant",
      "snippet": "...",
      "matched_at": "..."
    }
  ]
}

11. 长任务(Jobs)

用于检索、文献分析、验证流水线等异步流程。流式过程中后端应通过 job_started 事件告知前端 job_id,前端轮询:

11.1 GET /api/jobs/{id}

{
  "id": "job_...",
  "kind": "literature_search" | "validation" | "...",
  "status": "queued" | "running" | "succeeded" | "failed" | "cancelled",
  "progress": 0.42,
  "stage": "downloading | parsing | ranking | ...",
  "started_at": "...",
  "finished_at": "...",
  "result": { ... | null },
  "artifacts": [ "art_..." ],
  "error": "string | null",
  "logs_cursor": "opaque"
}

11.2 GET /api/jobs/{id}/poll?wait=15

长轮询;后端在状态变化或 wait 秒后返回最新 Job。

11.3 POST /api/jobs/{id}/cancel204

11.4 GET /api/jobs?status=...&limit=...&cursor=... → 分页列表。


12. 制品(Artifacts)

如生成的 markdown 报告、表格、PNG/SVG 等。

12.1 GET /api/artifacts/{id}Artifact

12.2 GET /api/artifacts/{id}/content → 原始内容(按 mime 返回)。

12.3 GET /api/artifacts?conversation_id=... → 列表。

Artifact

{
  id: "art_...",
  conversation_id: "cnv_...",
  message_id: "msg_...",
  kind: "markdown" | "table" | "image" | "html" | "pdf" | "json",
  title: "...",
  mime: "text/markdown",
  size: 12345,
  preview_url: "https://... | null",
  download_url: "https://...",
  created_at: "..."
}

13. 系统(System)

13.1 GET /api/healthz{ "ok": true, "version": "1.2.3" }

13.2 GET /api/version{ "version": "1.2.3", "build": "abc1234", "commit_time": "..." }

13.3 GET /api/system/announcements → 顶栏公告(后端可下发,前端展示一次)。

{
  "items": [
    { "id": "ann_...", "level": "info"|"warning"|"critical", "title": "...", "body_md": "...", "dismissable": true, "starts_at": "...", "ends_at": "..." }
  ]
}

14. 实现优先级建议

后端按下述阶段交付即可让前端逐步可用:

P0(最小可用)

  • /auth/login /auth/register /auth/me /auth/logout
  • /conversations (GET/POST/PATCH/DELETE)
  • /conversations/{id}/messages (GET, POST 非流式)
  • /models
  • /settings (GET/PATCH)
  • /healthz

P1(流式与多轮体验)

  • /conversations/{id}/messages/stream(SSE)
  • /conversations/{id}/messages/{id}/regenerate/stopPATCHfeedback
  • /conversations/{id}/share/share/{token}

P2(项目化与个性化)

  • /folders
  • /custom-instructions
  • /attachments/usage/search

P3(长任务与制品)

  • /jobs/*/artifacts/*
  • /system/announcements

前端会按 capability 优雅降级:尚未实现的接口返回 404 时,对应 UI 自动隐藏或显示「即将推出」。同时 /api/auth/me 中的 feature_flags 会被尊重 —— 后端可在渐进上线时通过 flag 控制开关,无需前端发版。


15. 前端调用清单(实现自查)

下面是前端 src/lib/api.ts 实际调用的端点清单,供后端做接口完备性核对。任意端点缺失,前端会以 ApiError 形式抛出并展示用户友好提示。

端点 方法 触发位置
/api/auth/register POST 登录页注册 tab
/api/auth/login POST 登录页登录 tab
/api/auth/logout POST 侧栏个人菜单
/api/auth/me GET 应用启动 + useMe
/api/auth/password/change POST 设置 → 账户
/api/conversations GET, POST 侧栏列表、首问建会话
/api/conversations/{id} GET, PATCH, DELETE 会话详情/重命名/置顶/归档/删除
/api/conversations/{id}/share POST, DELETE 顶部「分享」按钮
/api/conversations/{id}/messages GET, POST 消息列表与非流式发送
/api/conversations/{id}/messages/stream POST (SSE) 默认发送路径
/api/conversations/{id}/messages/{mid}/regenerate POST (SSE) 助手消息「重新生成」
/api/conversations/{id}/messages/{mid} PATCH, DELETE 编辑用户消息、删除消息
/api/conversations/{id}/messages/{mid}/feedback POST 助手消息点赞/踩
/api/conversations/{id}/messages/{mid}/stop POST 「停止生成」按钮兜底
/api/folders GET, POST 侧栏 Projects
/api/folders/{id} PATCH, DELETE 项目编辑
/api/models GET 顶部模型选择器 + 设置
/api/attachments POST 输入框附件上传
/api/attachments/{id} GET, DELETE 附件预览/移除
/api/settings GET, PATCH 设置页所有 tab
/api/custom-instructions GET, PUT 设置 → 个性化
/api/usage?period= GET 设置 → 账户用量条
/api/search GET 命令面板搜索
/api/jobs GET 详情面板任务列表
/api/jobs/{id} GET 详情面板任务详情
/api/jobs/{id}/poll?wait= GET 详情面板长轮询
/api/jobs/{id}/cancel POST 详情面板取消任务
/api/artifacts GET 详情面板制品列表
/api/artifacts/{id} GET 详情面板制品详情
/api/artifacts/{id}/content GET (text) 制品预览
/api/share/{token} GET (无鉴权) 公开分享页
/api/healthz GET 健康探针(可选)
/api/version GET 设置 → 关于
/api/system/announcements GET 顶部公告条

16. 变更记录(Changelog)

版本 日期 变更
v1.1 2026-04-20 新增「品牌资源」「i18n(0.7)」「鉴权与会话(0.8)」章节;补充 Accept-Language 头与 feature_flags 完整列表;新增「前端调用清单」附录。无破坏性变更。
v1.0 2026-04-19 首次发布,覆盖 auth / conversations / messages(SSE) / folders / models / attachments / settings / custom instructions / usage / search / jobs / artifacts / share / system。