{"id":43547149,"url":"https://github.com/cjackhwang/ds2api","last_synced_at":"2026-05-01T22:00:59.017Z","repository":{"id":335806235,"uuid":"1139136822","full_name":"CJackHwang/ds2api","owner":"CJackHwang","description":"Deepseek to API: A lightweight, high-performance full-stack middleware converting client protocols to universal APIs. Supports multi-account rotation, compiled binaries, Vercel Serverless, and Docker. Compatible with Google, Claude, and OpenAI API formats.","archived":false,"fork":false,"pushed_at":"2026-04-27T07:07:47.000Z","size":4919,"stargazers_count":1666,"open_issues_count":11,"forks_count":534,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-04-27T07:22:41.037Z","etag":null,"topics":["api","claude-api","deepseek","deepseek-api","docker","freeapi","go","openai-api","proxy","proxy-server","react","vercel","vercel-deployment","zeabur"],"latest_commit_sha":null,"homepage":"https://linux.do/u/cjackhwang","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CJackHwang.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":"docs/CONTRIBUTING.en.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-21T15:14:40.000Z","updated_at":"2026-04-27T07:17:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/CJackHwang/ds2api","commit_stats":null,"previous_names":["cjackhwang/ds2api"],"tags_count":58,"template":false,"template_full_name":null,"purl":"pkg:github/CJackHwang/ds2api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CJackHwang%2Fds2api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CJackHwang%2Fds2api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CJackHwang%2Fds2api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CJackHwang%2Fds2api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CJackHwang","download_url":"https://codeload.github.com/CJackHwang/ds2api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CJackHwang%2Fds2api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32514340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","claude-api","deepseek","deepseek-api","docker","freeapi","go","openai-api","proxy","proxy-server","react","vercel","vercel-deployment","zeabur"],"created_at":"2026-02-03T19:04:24.744Z","updated_at":"2026-05-01T22:00:59.007Z","avatar_url":"https://github.com/CJackHwang.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"webui/public/ds2api-favicon.svg\" width=\"128\" height=\"128\" alt=\"DS2API icon\" /\u003e\n\u003c/p\u003e\n\n# DS2API\n\n\u003ca href=\"https://trendshift.io/repositories/24508\" target=\"_blank\"\u003e\u003cimg src=\"https://trendshift.io/api/badge/repositories/24508\" alt=\"CJackHwang%2Fds2api | Trendshift\" style=\"width: 250px; height: 55px;\" width=\"250\" height=\"55\"/\u003e\u003c/a\u003e\n\n[![License](https://img.shields.io/github/license/CJackHwang/ds2api.svg)](LICENSE)\n![Stars](https://img.shields.io/github/stars/CJackHwang/ds2api.svg)\n![Forks](https://img.shields.io/github/forks/CJackHwang/ds2api.svg)\n[![Release](https://img.shields.io/github/v/release/CJackHwang/ds2api?display_name=tag)](https://github.com/CJackHwang/ds2api/releases)\n[![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](docs/DEPLOY.md)\n\n[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/L4CFHP)\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/CJackHwang/ds2api)\n\n语言 / Language: [中文](README.MD) | [English](README.en.md)\n\n将 DeepSeek Web 对话能力转换为 OpenAI、Claude 与 Gemini 兼容 API。核心后端以 **Go** 实现，Vercel 流式桥接额外使用少量 Node Runtime，前端为 React WebUI 管理台（源码在 `webui/`，部署时自动构建到 `static/admin`）。\n\n文档入口：[文档导航](docs/README.md) / [架构说明](docs/ARCHITECTURE.md) / [接口文档](API.md)\n\n【感谢Linux.do社区及GitHub社区各位开发者对项目的支持与贡献】\n\n\u003e **重要免责声明**\n\u003e\n\u003e 本仓库仅供学习、研究、个人实验和内部验证使用，不提供任何形式的商业授权、适用性保证或结果保证。\n\u003e\n\u003e 作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。\n\u003e\n\u003e 请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认 `LICENSE`、相关协议以及你是否获得了作者的书面许可。\n\n## 目录\n\n- [架构概览（摘要）](#架构概览摘要)\n- [核心能力](#核心能力)\n- [平台兼容矩阵](#平台兼容矩阵)\n- [模型支持](#模型支持)\n  - [OpenAI 接口](#openai-接口get-v1models)\n  - [Claude 接口](#claude-接口get-anthropicv1models)\n  - [Gemini 接口](#gemini-接口)\n- [快速开始](#快速开始)\n  - [方式一：下载 Release 构建包](#方式一下载-release-构建包)\n  - [方式二：Docker 运行](#方式二docker-运行)\n  - [方式三：Vercel 部署](#方式三vercel-部署)\n  - [方式四：本地源码运行](#方式四本地源码运行)\n- [配置说明](#配置说明)\n- [鉴权模式](#鉴权模式)\n- [并发模型](#并发模型)\n- [Tool Call 适配](#tool-call-适配)\n- [本地开发抓包工具](#本地开发抓包工具)\n- [文档索引](#文档索引)\n- [测试](#测试)\n- [Release 自动构建（GitHub Actions）](#release-自动构建github-actions)\n- [免责声明](#免责声明)\n\n## 架构概览（摘要）\n\n```mermaid\nflowchart LR\n    Client[\"🖥️ 客户端 / SDK\\n(OpenAI / Claude / Gemini)\"]\n    Upstream[\"☁️ DeepSeek API\"]\n\n    subgraph DS2API[\"DS2API 4.x（模块化 HTTP surface + PromptCompat 内核）\"]\n        Router[\"chi Router + 中间件\\n(RequestID / RealIP / Logger / Recoverer / CORS)\"]\n\n        subgraph HTTP[\"HTTP API surface\"]\n            OA[\"OpenAI\\nchat / responses / files / embeddings\"]\n            CA[\"Claude\\n/anthropic/* + /v1/messages\"]\n            GA[\"Gemini\\n/v1beta/models/* + /v1/models/*\"]\n            Admin[\"Admin API\\n资源子包\"]\n            WebUI[\"WebUI\\n/admin（静态托管）\"]\n            Vercel[\"Vercel Node Stream\\n/v1/chat/completions\"]\n        end\n\n        subgraph Runtime[\"运行时核心能力\"]\n            Compat[\"PromptCompat\\n(API -\u003e 网页纯文本上下文)\"]\n            Chat[\"Chat / Responses Runtime\\n(统一工具调用与流式语义)\"]\n            Auth[\"Auth Resolver\\n(API key / bearer / x-goog-api-key)\"]\n            Pool[\"Account Pool + Queue\\n(并发槽位 + 等待队列)\"]\n            DSClient[\"DeepSeek Client\\n(Session / Auth / Completion / Files)\"]\n            Pow[\"PoW 实现\\n(纯 Go)\"]\n            Tool[\"Tool Sieve\\n(Go/Node 语义对齐)\"]\n            History[\"History Split\\n(长历史文件化)\"]\n        end\n    end\n\n    Client --\u003e Router\n    Router --\u003e OA \u0026 CA \u0026 GA\n    Router --\u003e Admin\n    Router --\u003e WebUI\n    Router --\u003e Vercel\n\n    OA --\u003e Compat\n    CA \u0026 GA --\u003e Compat\n    Compat --\u003e Chat\n    Compat -.长历史.-\u003e History\n    Vercel -.Go prepare.-\u003e Chat\n    Vercel -.Node SSE.-\u003e Tool\n    Chat --\u003e Auth\n    Chat -.账号轮询.-\u003e Pool\n    Chat -.工具调用解析.-\u003e Tool\n    Chat -.PoW 计算.-\u003e Pow\n    Auth --\u003e DSClient\n    DSClient --\u003e Upstream\n    Upstream --\u003e DSClient\n    Chat --\u003e Client\n    Vercel --\u003e Client\n```\n\n详细架构拆分与目录职责见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)。\n\n- **后端**：Go（`cmd/ds2api/`、`api/`、`internal/`），不依赖 Python 运行时\n- **前端**：React 管理台（`webui/`），运行时托管静态构建产物\n- **部署**：本地运行、Docker、Vercel Serverless、Linux systemd\n\n## 核心能力\n\n| 能力 | 说明 |\n| --- | --- |\n| OpenAI 兼容 | `GET /v1/models`、`GET /v1/models/{id}`、`POST /v1/chat/completions`、`POST /v1/responses`、`GET /v1/responses/{response_id}`、`POST /v1/embeddings`、`POST /v1/files` |\n| Claude 兼容 | `GET /anthropic/v1/models`、`POST /anthropic/v1/messages`、`POST /anthropic/v1/messages/count_tokens`（及快捷路径 `/v1/messages`、`/messages`） |\n| Gemini 兼容 | `POST /v1beta/models/{model}:generateContent`、`POST /v1beta/models/{model}:streamGenerateContent`（及 `/v1/models/{model}:*` 路径） |\n| 统一 CORS 兼容 | `/v1/*`、`/anthropic/*`、`/v1beta/models/*`、`/admin/*` 统一走同一套 CORS 策略；Vercel 上 `/v1/chat/completions` 的 Node Runtime 也对齐相同放行规则，尽量减少第三方预检请求头限制 |\n| 多账号轮询 | 自动 token 刷新、邮箱/手机号双登录方式 |\n| 并发队列控制 | 每账号 in-flight 上限 + 等待队列，动态计算建议并发值 |\n| DeepSeek PoW | 纯 Go 高性能实现（DeepSeekHashV1），毫秒级响应 |\n| Tool Calling | 防泄漏处理：非代码块高置信特征识别、`delta.tool_calls` 早发、结构化增量输出 |\n| Admin API | 配置管理、运行时设置热更新、代理管理、账号测试 / 批量测试、会话清理、导入导出、Vercel 同步、版本检查 |\n| WebUI 管理台 | `/admin` 单页应用（中英文双语、深色模式，支持查看服务器端对话记录） |\n| 运维探针 | `GET /healthz`（存活）、`GET /readyz`（就绪） |\n\nOpenAI `/v1/*` 仍是推荐的规范路径；同时支持 `/models`、`/chat/completions`、`/responses`、`/embeddings`、`/files` 等根路径快捷路由，方便只配置 DS2API 根地址的第三方客户端。\n\n## 平台兼容矩阵\n\n| 级别 | 平台 | 当前状态 |\n| --- | --- | --- |\n| P0 | Codex CLI/SDK（`wire_api=chat` / `wire_api=responses`） | ✅ |\n| P0 | OpenAI SDK（JS/Python，chat + responses） | ✅ |\n| P0 | Vercel AI SDK（openai-compatible） | ✅ |\n| P0 | Anthropic SDK（messages） | ✅ |\n| P0 | Google Gemini SDK（generateContent） | ✅ |\n| P1 | LangChain / LlamaIndex / OpenWebUI（OpenAI 兼容接入） | ✅ |\n\n## 模型支持\n\n### OpenAI 接口（`GET /v1/models`）\n\n| 模型类型 | 模型 ID | thinking | search |\n| --- | --- | --- | --- |\n| default | `deepseek-v4-flash` | 默认开启，可由请求参数控制 | ❌ |\n| default | `deepseek-v4-flash-nothinking` | 永久关闭，不受请求参数影响 | ❌ |\n| expert | `deepseek-v4-pro` | 默认开启，可由请求参数控制 | ❌ |\n| expert | `deepseek-v4-pro-nothinking` | 永久关闭，不受请求参数影响 | ❌ |\n| default | `deepseek-v4-flash-search` | 默认开启，可由请求参数控制 | ✅ |\n| default | `deepseek-v4-flash-search-nothinking` | 永久关闭，不受请求参数影响 | ✅ |\n| expert | `deepseek-v4-pro-search` | 默认开启，可由请求参数控制 | ✅ |\n| expert | `deepseek-v4-pro-search-nothinking` | 永久关闭，不受请求参数影响 | ✅ |\n| vision | `deepseek-v4-vision` | 默认开启，可由请求参数控制 | ❌ |\n| vision | `deepseek-v4-vision-nothinking` | 永久关闭，不受请求参数影响 | ❌ |\n\n除原生模型外，也支持常见 alias 输入（如 `gpt-4.1`、`gpt-5`、`gpt-5-codex`、`o3`、`claude-*`、`gemini-*` 等），但 `/v1/models` 返回的是规范化后的 DeepSeek 原生模型 ID。若 alias 名本身追加 `-nothinking` 后缀，也会映射到对应的强制关思考模型。完整 alias 行为以 [API.md](API.md#模型-alias-解析策略) 和 `config.example.json` 为准。\n当前上游视觉模型只暴露 `vision` 通道，不提供独立的联网搜索视觉变体。\n\n### Claude 接口（`GET /anthropic/v1/models`）\n\n| 当前常用模型 | 默认映射 |\n| --- | --- |\n| `claude-sonnet-4-6` | `deepseek-v4-flash` |\n| `claude-sonnet-4-6-nothinking` | `deepseek-v4-flash-nothinking` |\n| `claude-haiku-4-5`（兼容 `claude-3-5-haiku-latest`） | `deepseek-v4-flash` |\n| `claude-haiku-4-5-nothinking` | `deepseek-v4-flash-nothinking` |\n| `claude-opus-4-6` | `deepseek-v4-pro` |\n| `claude-opus-4-6-nothinking` | `deepseek-v4-pro-nothinking` |\n\n可通过配置中的 `model_aliases` 覆盖映射关系；若请求模型名带 `-nothinking`，会在最终映射结果上强制追加无思考语义。\n`/anthropic/v1/models` 除上述主别名外，还会返回 Claude 4.x snapshots、3.x 历史模型 ID 与常见 alias，便于旧客户端直接兼容。\n\n#### Claude Code 接入避坑（实测）\n\n- `ANTHROPIC_BASE_URL` 推荐直接指向 DS2API 根地址（例如 `http://127.0.0.1:5001`），Claude Code 会请求 `/v1/messages?beta=true`。\n- `ANTHROPIC_API_KEY` 需要与 `config.json` 中 `keys` 一致；建议同时保留常规 key 与 `sk-ant-*` 形态 key，兼容不同客户端校验习惯。\n- 若系统设置了代理，建议对 DS2API 地址配置 `NO_PROXY=127.0.0.1,localhost,\u003c你的主机IP\u003e`，避免本地回环请求被代理拦截。\n- 如遇“工具调用输出成文本、未执行”问题，请优先检查模型输出是否为推荐的 DSML 工具块：`\u003c|DSML|tool_calls\u003e\u003c|DSML|invoke name=\"...\"\u003e\u003c|DSML|parameter name=\"...\"\u003e...`。兼容层也接受旧式 canonical XML：`\u003ctool_calls\u003e\u003cinvoke name=\"...\"\u003e\u003cparameter name=\"...\"\u003e...`；旧式 `\u003ctools\u003e` / `\u003ctool_call\u003e` / `\u003ctool_name\u003e` / `\u003cparam\u003e`、`\u003cfunction_call\u003e`、`tool_use` 或纯 JSON `tool_calls` 片段不会执行。\n\n### Gemini 接口\n\nGemini 适配器将模型名通过 `model_aliases` 或内置规则映射到 DeepSeek 原生模型，支持 `generateContent` 和 `streamGenerateContent` 两种调用方式，并完整支持 Tool Calling（`functionDeclarations` → `functionCall` 输出）。若 Gemini 模型名带 `-nothinking` 后缀，例如 `gemini-2.5-pro-nothinking`，会映射到对应的强制关闭思考模型。\n\n## 快速开始\n\n### 部署方式优先级建议\n\n推荐按以下顺序选择部署方式：\n\n1. **下载 Release 构建包运行**：最省事，产物已编译完成，最适合大多数用户。\n2. **Docker / GHCR 镜像部署**：适合需要容器化、编排或云环境部署。\n3. **Vercel 部署**：适合已有 Vercel 环境且接受其平台约束的场景。\n4. **本地源码运行 / 自行编译**：适合开发、调试或需要自行修改代码的场景。\n\n### 通用第一步（所有部署方式）\n\n把 `config.json` 作为唯一配置源（推荐做法）：\n\n```bash\ncp config.example.json config.json\n# 编辑 config.json\n```\n\n后续部署建议：\n- 本地运行：直接读取 `config.json`\n- Docker / Vercel：由 `config.json` 生成 `DS2API_CONFIG_JSON`（Base64）注入环境变量，也可以直接写原始 JSON\n\nWebUI 管理台里的“全量配置模板”也直接复用同一份 `config.example.json`，所以更新示例文件后，前端模板会自动保持一致。\n\n### 方式一：下载 Release 构建包\n\n每次发布 Release 时，GitHub Actions 会自动构建多平台二进制包：\n\n```bash\n# 下载对应平台的压缩包后\ntar -xzf ds2api_\u003ctag\u003e_linux_amd64.tar.gz\ncd ds2api_\u003ctag\u003e_linux_amd64\ncp config.example.json config.json\n# 编辑 config.json\n./ds2api\n```\n\n### 方式二：Docker 运行\n\n```bash\n# 1. 准备环境变量和配置文件\ncp .env.example .env\ncp config.example.json config.json\n\n# 2. 编辑 .env（至少设置 DS2API_ADMIN_KEY；如需修改宿主机端口，可额外设置 DS2API_HOST_PORT）\n#    DS2API_ADMIN_KEY=请替换为强密码\n\n# 3. 启动\ndocker-compose up -d\n\n# 4. 查看日志\ndocker-compose logs -f\n```\n\n默认 `docker-compose.yml` 会把宿主机 `6011` 映射到容器内的 `5001`。如果你希望直接对外暴露 `5001`，请设置 `DS2API_HOST_PORT=5001`（或者手动调整 `ports` 配置）。\n同时默认把 `./config.json` 挂载到容器 `/data/config.json`，并设置 `DS2API_CONFIG_PATH=/data/config.json`，用于避免 `/app` 只读导致运行时 token 持久化失败。\n镜像会预创建 `/data` 并授权给非 root 的 `ds2api` 用户；如果使用单文件 bind mount，请确保宿主机 `config.json` 对容器用户可读写，例如 `chmod 644 config.json`。\n\n更新镜像：`docker-compose up -d --build`\n\n#### Zeabur 一键部署（Dockerfile）\n\n1. 点击上方 “Deploy on Zeabur” 按钮，一键部署。\n2. 部署完成后访问 `/admin`，使用 Zeabur 环境变量/模板指引中的 `DS2API_ADMIN_KEY` 登录。\n3. 在管理台导入/编辑配置（会写入并持久化到 `/data/config.json`）。\n\n说明：Zeabur 使用仓库内 `Dockerfile` 直接构建时，不需要额外传入 `BUILD_VERSION`；镜像会优先读取该构建参数，未提供时自动回退到仓库根目录的 `VERSION` 文件。\n\n### 方式三：Vercel 部署\n\n1. Fork 仓库到自己的 GitHub\n2. 在 Vercel 上导入项目\n3. 配置环境变量（最少设置 `DS2API_ADMIN_KEY`；推荐同时设置 `DS2API_CONFIG_JSON`）\n4. 部署\n\n建议先在仓库目录复制模板并填写：\n\n```bash\ncp config.example.json config.json\n# 编辑 config.json\n```\n\n推荐：先本地把 `config.json` 转成 Base64，再粘贴到 `DS2API_CONFIG_JSON`，避免 JSON 格式错误：\n\n```bash\nbase64 \u003c config.json | tr -d '\\n'\n```\n\n\u003e **流式说明**：`/v1/chat/completions` 在 Vercel 上默认走 `api/chat-stream.js`（Node Runtime）以保证实时 SSE。鉴权、账号选择、会话/PoW 准备仍由 Go 内部 prepare 接口完成；流式响应（含 `tools`）在 Node 侧执行与 Go 对齐的输出组装与防泄漏处理。虽然这里只有 OpenAI chat 流式走 Node，但 CORS 放行策略仍与 Go 主路由保持一致，统一覆盖第三方客户端预检场景。\n\n详细部署说明请参阅 [部署指南](docs/DEPLOY.md)。\n\n### 方式四：本地源码运行\n\n**前置要求**：Go 1.26+，Node.js `20.19+` 或 `22.12+`（仅在需要构建 WebUI 时）；同时确保 `npm` 可用，建议 `npm 10+`\n\n```bash\n# 1. 克隆仓库\ngit clone https://github.com/CJackHwang/ds2api.git\ncd ds2api\n\n# 2. 配置\ncp config.example.json config.json\n# 编辑 config.json，填入你的 DeepSeek 账号信息和 API key\n\n# 3. 启动\ngo run ./cmd/ds2api\n```\n\n默认本地访问地址：`http://127.0.0.1:5001`\n\n服务实际绑定：`0.0.0.0:5001`，因此同一局域网设备通常也可以通过你的内网 IP 访问。\n\n\u003e **WebUI 自动构建**：本地首次启动时，若 `static/admin` 不存在，会自动尝试执行 `npm ci`（仅在缺少依赖时）和 `npm run build -- --outDir static/admin --emptyOutDir`（需要本机有 Node.js 和 npm）。你也可以手动构建：`./scripts/build-webui.sh`\n\n## 配置说明\n\n`README` 只保留快速入口，完整字段请以 [config.example.json](config.example.json) 为模板，并参考 [部署指南](docs/DEPLOY.md#0-前置要求) 与 [API 配置最佳实践](API.md#配置最佳实践)。\n\n常用字段：\n\n- `keys` / `api_keys`：客户端访问密钥，`api_keys` 支持 `name` 与 `remark` 元信息，`keys` 继续兼容。\n- `accounts`：DeepSeek 托管账号，支持 `email` 或 `mobile` 登录，可配置代理、名称和备注。\n- `model_aliases`：OpenAI / Claude / Gemini 共用的模型 alias 映射。\n- `runtime`：账号并发、队列与 token 刷新策略，可通过 Admin Settings 热更新。\n- `auto_delete.mode`：请求结束后的远端会话清理策略，支持 `none` / `single` / `all`。\n- `history_split`：旧轮次拆分字段，已废弃并忽略，仅保留兼容旧配置。\n- `current_input_file`：唯一生效的独立拆分策略；默认开启且阈值为 `0`，触发时将完整上下文合并上传为 `DS2API_HISTORY.txt` 上下文文件。\n- 如果关闭 `current_input_file`，请求会直接透传，不上传拆分上下文文件。\n- `thinking_injection`：默认开启；在最新 user 消息末尾追加思考增强提示词，提高高强度推理与工具调用前的思考稳定性；`prompt` 留空时使用内置默认提示词。\n\n环境变量完整列表见 [部署指南](docs/DEPLOY.md)，接口鉴权规则见 [API.md](API.md#鉴权规则)。\n\n## 鉴权模式\n\n调用业务接口（`/v1/*`、`/anthropic/*`、Gemini 路由）时支持两种模式：\n\n| 模式 | 说明 |\n| --- | --- |\n| **托管账号模式** | `Bearer` 或 `x-api-key` 传入 `config.keys` 中的 key，由服务自动轮询选择账号 |\n| **直通 token 模式** | 传入 token 不在 `config.keys` 中时，直接作为 DeepSeek token 使用 |\n\n可选请求头 `X-Ds2-Target-Account`：指定使用某个托管账号（值为 email 或 mobile）。\n如果指定账号不存在，或者当前管理账号队列已满，请求会返回 `429`；当前 `429` 不附带 `Retry-After` 头。若账号存在但登录/刷新失败，则返回对应的鉴权错误。\nGemini 路由还可以使用 `x-goog-api-key`，或在没有认证头时使用 `?key=` / `?api_key=` 作为调用方凭据。\n\n## 并发模型\n\n```\n每账号可用并发 = DS2API_ACCOUNT_MAX_INFLIGHT（默认 2）\n建议并发值 = 账号数量 × 每账号并发上限\n等待队列上限 = DS2API_ACCOUNT_MAX_QUEUE（默认 = 建议并发值）\n429 阈值 = in-flight + 等待队列 ≈ 账号数量 × 4\n```\n\n- 当 in-flight 槽位满时，请求进入等待队列，**不会立即 429**\n- 超出总承载上限后才返回 `429 Too Many Requests`，当前响应不附带 `Retry-After`\n- `GET /admin/queue/status` 返回实时并发状态\n\n## Tool Call 适配\n\n当请求中带 `tools` 时，DS2API 会做防泄漏处理与结构化转译：\n\n1. 只在**非代码块上下文**启用执行型 toolcall 识别（代码块示例默认不触发）\n2. 解析层当前把 DSML 外壳视为推荐可执行调用：`\u003c|DSML|tool_calls\u003e` → `\u003c|DSML|invoke name=\"...\"\u003e` → `\u003c|DSML|parameter name=\"...\"\u003e`；兼容旧式 canonical XML `\u003ctool_calls\u003e` → `\u003cinvoke name=\"...\"\u003e` → `\u003cparameter name=\"...\"\u003e`。DSML 只是外壳别名，内部仍以 XML 解析语义为准；旧式 `\u003ctools\u003e` / `\u003ctool_call\u003e` / `\u003ctool_name\u003e` / `\u003cparam\u003e`、`\u003cfunction_call\u003e`、`tool_use` / antml 变体与纯 JSON `tool_calls` 片段都会按普通文本处理\n3. `responses` 流式严格使用官方 item 生命周期事件（`response.output_item.*`、`response.content_part.*`、`response.function_call_arguments.*`）\n4. `responses` 支持并执行 `tool_choice`（`auto`/`none`/`required`/强制函数）；`required` 违规时非流式返回 `422`，流式返回 `response.failed`\n5. 客户端请求哪种协议，就按该协议返回工具调用（OpenAI/Claude/Gemini 各自原生结构）；模型侧优先约束输出规范 XML，再由兼容层转译\n\n\u003e 说明：当前版本 parser 层以”尽量解析成功”为优先，所有格式合法的 XML 工具调用都会通过，不做工具名 allow-list 过滤。\n\u003e\n\u003e 想评估”把工具调用封装成 XML 再输入模型”的方案，可参考：`docs/toolcall-semantics.md`。\n\n## 本地开发抓包工具\n\n用于定位「responses 思考流/工具调用」等问题。开启后会自动记录最近 N 条 DeepSeek 对话上游请求体与响应体（默认 20 条，超出自动淘汰；单条响应体默认最多记录 5 MB）。\n\n启用示例：\n\n```bash\nDS2API_DEV_PACKET_CAPTURE=true \\\nDS2API_DEV_PACKET_CAPTURE_LIMIT=20 \\\ngo run ./cmd/ds2api\n```\n\n查询/清空（需 Admin JWT）：\n\n- `GET /admin/dev/captures`：查看抓包列表（最新在前）\n- `DELETE /admin/dev/captures`：清空抓包\n- `GET /admin/dev/raw-samples/query?q=关键词\u0026limit=20`：按问题关键词查询当前内存抓包，并按 `chat_session_id` 归并 `completion + continue` 链\n- `POST /admin/dev/raw-samples/save`：把命中的某条抓包链保存为 `tests/raw_stream_samples/\u003csample-id\u003e/` 回放样本\n\n返回字段包含：\n\n- `request_body`：发送给 DeepSeek 的完整请求体\n- `response_body`：上游返回的原始流式内容拼接文本\n- `response_truncated`：是否触发单条大小截断\n\n保存接口支持用 `query`、`chain_key` 或 `capture_id` 选中目标。例如：\n\n```json\n{\"query\":\"广州天气\",\"sample_id\":\"gz-weather-from-memory\"}\n```\n\n## 文档索引\n\n| 文档 | 说明 |\n| --- | --- |\n| [API.md](API.md) / [API.en.md](API.en.md) | API 接口文档（含请求/响应示例） |\n| [DEPLOY.md](docs/DEPLOY.md) / [DEPLOY.en.md](docs/DEPLOY.en.md) | 部署指南（本地/Docker/Vercel/systemd） |\n| [CONTRIBUTING.md](docs/CONTRIBUTING.md) / [CONTRIBUTING.en.md](docs/CONTRIBUTING.en.md) | 贡献指南 |\n| [TESTING.md](docs/TESTING.md) | 测试集使用指南 |\n\n## 测试\n\n详细测试指南请参阅 [docs/TESTING.md](docs/TESTING.md)。\n\n### 快速测试命令\n\n```bash\n# 本地 PR 门禁\n./scripts/lint.sh\n./tests/scripts/check-refactor-line-gate.sh\n./tests/scripts/run-unit-all.sh\nnpm run build --prefix webui\n\n# 端到端全链路测试（真实账号，生成完整请求/响应日志）\n./tests/scripts/run-live.sh\n```\n\n## Release 自动构建（GitHub Actions）\n\n工作流文件：`.github/workflows/release-artifacts.yml`\n\n- **触发条件**：默认仅在 GitHub Release `published` 时自动触发；也支持在 Actions 页面手动 `workflow_dispatch`，并填写 `release_tag` 复跑/补发\n- **构建产物**：多平台二进制包（`linux/amd64`、`linux/arm64`、`linux/armv7`、`darwin/amd64`、`darwin/arm64`、`windows/amd64`、`windows/arm64`）、Linux Docker 镜像导出包 + `sha256sums.txt`\n- **容器镜像发布**：仅推送到 GHCR（`ghcr.io/cjackhwang/ds2api`）\n- **每个二进制压缩包包含**：`ds2api` 可执行文件、`static/admin`、`config.example.json`、`.env.example`、`README.MD`、`README.en.md`、`LICENSE`\n\n## 免责声明\n\n本项目基于逆向方式实现，仅供学习、研究、个人实验和内部验证使用，不提供任何商业授权、稳定性保证或可用性保证。\n作者及仓库维护者不对因使用、修改、分发、部署或依赖本项目而产生的任何直接或间接损失、账号封禁、数据丢失、法律风险或第三方索赔负责。\n\n请勿将本项目用于违反服务条款、协议、法律法规或平台规则的场景。商业使用前请自行确认 `LICENSE`、相关协议以及你是否获得了作者的书面许可。\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjackhwang%2Fds2api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcjackhwang%2Fds2api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjackhwang%2Fds2api/lists"}