{"id":50360980,"url":"https://github.com/yangfei4913438/codex-deepseek","last_synced_at":"2026-05-30T01:30:22.234Z","repository":{"id":358255278,"uuid":"1240653940","full_name":"yangfei4913438/codex-deepseek","owner":"yangfei4913438","description":"Protocol translation proxy — converts OpenAI Responses API to DeepSeek Chat Completions API, enabling Codex to use DeepSeek models via cc-switch.","archived":false,"fork":false,"pushed_at":"2026-05-16T14:27:13.000Z","size":17,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-16T14:40:50.962Z","etag":null,"topics":["cc-switch","codex","deepseek"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yangfei4913438.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-16T11:58:28.000Z","updated_at":"2026-05-16T14:27:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yangfei4913438/codex-deepseek","commit_stats":null,"previous_names":["yangfei4913438/codex-deepseek"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/yangfei4913438/codex-deepseek","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yangfei4913438%2Fcodex-deepseek","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yangfei4913438%2Fcodex-deepseek/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yangfei4913438%2Fcodex-deepseek/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yangfei4913438%2Fcodex-deepseek/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yangfei4913438","download_url":"https://codeload.github.com/yangfei4913438/codex-deepseek/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yangfei4913438%2Fcodex-deepseek/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33677258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"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":["cc-switch","codex","deepseek"],"created_at":"2026-05-30T01:30:21.305Z","updated_at":"2026-05-30T01:30:22.229Z","avatar_url":"https://github.com/yangfei4913438.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# codex-deepseek\n\n[中文](README.zh-CN.md)\n\nPython port of [ccswitch-deepseek](https://github.com/liuzhengming/ccswitch-deepseek) — a protocol translation proxy that converts OpenAI Responses API to Chat Completions API, enabling Codex to use DeepSeek or any OpenAI-compatible model via [cc-switch](https://github.com/farion1231/cc-switch).\n\nZero external dependencies — Python standard library only.\n\nThanks to the original [ccswitch-deepseek](https://github.com/liuzhengming/ccswitch-deepseek) project for the design and protocol research.\n\n## Quick Start\n\n### 1. Configure\n\n```bash\ncp .env.example .env\n```\n\nEdit `.env` with your API key and optional settings (see [Configuration](#configuration)).\n\n### 2. Start\n\n```bash\n./start.sh\n```\n\nOr with uv directly:\n\n```bash\nuv run python -m src.main\n```\n\nThe proxy listens at `http://127.0.0.1:11435`.\n\n## Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `api_key` | — | API key (required) |\n| `base_url` | `https://api.deepseek.com` | API base URL |\n| `model` | `deepseek-v4-pro` | Model name |\n| `port` | `11435` | Server listen port |\n| `timeout` | `30` | Upstream API timeout in minutes |\n| `is_deepseek` | `true` | Set to `false` if not using a DeepSeek model |\n| `multimodal` | `false` | Set to `true` if the model supports image inputs |\n\n## Supported Providers\n\nThis proxy works with any model provider that offers an **OpenAI-compatible Chat Completions API**. Just configure `base_url`, `model`, and `api_key` accordingly.\n\n\u003e **Tip:** Some third-party model providers also support the DeepSeek-format `thinking` parameter. If the model recognizes `thinking: {type: \"enabled\"}`, you can keep `is_deepseek=true`.\n\n## How It Works\n\nCodex speaks **OpenAI Responses API**. Most AI model providers speak **Chat Completions API**.\nThis proxy translates between the two protocols in real time.\n\n### Request chain\n\n```\nCodex (app or CLI) ──▶  cc-switch  ──▶  proxy :11435  ──▶  Upstream API\n```\n\n1. Codex sends a request to cc-switch (its configured provider endpoint)\n2. cc-switch routes the request to this proxy at `/responses`\n3. The proxy translates Responses API `input` items into Chat Completions `messages`\n4. The translated request is forwarded to `{base_url}/chat/completions`\n5. The upstream API's SSE streaming response is translated back into Responses API events and returned\n\n### Translation coverage\n\n**Input (Responses → Chat Completions)**\n\n| Source | Target |\n|--------|--------|\n| `input_text` / `output_text` / `reasoning_text` | message text content |\n| `function_call` item | assistant `tool_calls` |\n| `function_call_output` item | `tool` role message |\n| `reasoning` item | skipped; `reasoning_content` retained on adjacent message |\n| `developer` role | `system` role |\n| `input_image` / `input_file` / `input_audio` | skipped with stats |\n| `instructions` | prepended system message |\n| `temperature` / `top_p` / `max_output_tokens` | passthrough |\n| `tools` / `tool_choice` | translated to Chat Completions format |\n| `thinking` / `reasoning` | thinking mode control (DeepSeek format) |\n\n**Output (Chat Completions SSE → Responses SSE)**\n\n| Chat Completions SSE event | Responses API event |\n|--------------------|---------------------|\n| first delta | `response.created` + `response.in_progress` |\n| `delta.content` | `response.output_text.delta` / `done` |\n| `delta.reasoning_content` | `response.reasoning_text.delta` / `done` |\n| `delta.tool_calls` | `response.function_call_arguments.delta` / `done` |\n| stream end | `response.output_item.done` × N + `response.completed` (with usage) |\n\n### reasoning_content recovery\n\nDeepSeek omits `reasoning_content` on tool-call assistant messages in multi-turn conversations.\nThe proxy automatically remembers reasoning from the previous turn and restores it on the next,\nso the reasoning chain stays intact across function calls.\n\n### Identity injection\n\nA system message is prepended to every request telling the model its true identity,\npreventing conflicting identity claims from Codex or other tools.\n\n## Integration with [cc-switch](https://github.com/farion1231/cc-switch)\n\n**cc-switch** is a cross-platform AI CLI management tool that handles provider configuration and request routing.\nThis proxy is an independent service; cc-switch routes Codex requests to it.\n\n### Setup\n\n**1. Start the proxy:**\n\n```bash\n./start.sh\n```\n\n**2. Add a new Codex provider in cc-switch:**\n\ncc-switch manages Codex's config files (`~/.codex/config.toml` and `~/.codex/auth.json`).\nFill in these fields when adding the provider:\n\n| Field | Value |\n|-------|-------|\n| name | `codex-deepseek` |\n| base_url | `http://127.0.0.1:11435` |\n| wire_api | `responses` |\n| requires_openai_auth | `true` |\n\nThe resulting `~/.codex/config.toml` will look like:\n\n```toml\nmodel_provider = \"custom\"\nmodel = \"deepseek-v4-pro\"\nmodel_reasoning_effort = \"high\"\n\n[model_providers.custom]\nname = \"codex-deepseek\"\nbase_url = \"http://127.0.0.1:11435\"\nwire_api = \"responses\"\nrequires_openai_auth = true\n```\n\n\u003e **Note:** Codex requires a non-empty `OPENAI_API_KEY` in `~/.codex/auth.json` to pass its client-side check, but the actual upstream authentication is handled by this proxy's own `.env` — so any placeholder value works in `auth.json`.\n\n**3. Restart your terminal** for changes to take effect.\n\n## Files\n\n| File | Description |\n|------|-------------|\n| `src/main.py` | HTTP server (stdlib `http.server`) |\n| `src/log.py` | Colored ANSI logging |\n| `src/translate.py` | Input translation (Responses → Chat) |\n| `src/sse.py` | SSE event translation (Chat → Responses) |\n| `src/recover.py` | reasoning_content auto-restore |\n| `tests/test_translate.py` | 28 unit tests |\n\n## Scripts\n\n```bash\n./start.sh   # Start the proxy server\n./test.sh    # Run unit tests\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyangfei4913438%2Fcodex-deepseek","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyangfei4913438%2Fcodex-deepseek","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyangfei4913438%2Fcodex-deepseek/lists"}