[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-11170":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":14,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":19,"hasPages":19,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":15,"starSnapshotCount":15,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},11170,"CodexRosetta","JiuliNuoyi\u002FCodexRosetta","JiuliNuoyi"," Responses API ↔ Chat Completions API 双向代理，让任何兼容 Chat Completions 的后端都能驱动 Codex 等需要 Responses API 的工具，零客户端改动。支持Web_search功能（采用模拟方式，需独立设置）","",null,"Python",152,6,3,0,18,2.54,"MIT License",false,"main",[],"2026-06-12 02:02:29","# CodexRosetta\r\n\r\n**Responses API \u003C-> Chat Completions API 代理服务器**\r\n\r\nCodexRosetta 是一个轻量级代理，在 OpenAI 的 [Responses API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fresponses) 和广泛兼容的 [Chat Completions API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fchat) 之间进行双向转换。它让任何兼容 Chat Completions 的后端都能驱动需要 Responses API 格式的工具和客户端——双方都无需修改代码。\r\n\r\n## 为什么需要 CodexRosetta？\r\n\r\nOpenAI 推出了 Responses API 作为 Chat Completions 的继任者，但大多数第三方 LLM 服务商和自建后端（vLLM、Ollama、LiteLLM 等）仅支持 Chat Completions。CodexRosetta 填补了这个空白：\r\n\r\n- **用任何 LLM 驱动 Codex \u002F 类 ChatGPT 工具** — 将客户端指向 CodexRosetta，它会实时将 Responses API 请求转换为 Chat Completions 格式\r\n- **零客户端改动** — 你的工具继续发送 Responses API 请求，CodexRosetta 透明地处理转换\r\n- **流式支持** — 完整的 SSE 流式转换，包括工具调用和多轮联网搜索\r\n- **内置联网搜索** — 通过 Tavily、SearXNG、Brave 或 DuckDuckGo 模拟 Responses API 的 `web_search` 工具\r\n- **多 Key 管理** — 通过 Web 界面或 REST API 添加、轮换和切换 API Key\r\n\r\n## 快速开始\r\n\r\n### Docker Compose（推荐）\n\n包含 Redis 用于会话状态持久化：\n\r\n```bash\r\ngit clone https:\u002F\u002Fgithub.com\u002FJiuliNuoyi\u002FCodexRosetta.git\r\ncd CodexRosetta\r\ncp .env.example .env\r\n# 编辑 .env，配置上游服务商\r\ndocker compose up -d\r\n```\n\n### Docker（快速体验）\n\n```bash\ndocker run -d --name codex-rosetta -p 33131:33131 jlny\u002Fcodex-rosetta:latest\n```\n\n然后将客户端指向 `http:\u002F\u002Flocalhost:33131\u002Fv1\u002Fresponses`。\n\n### pip 安装\n\r\n```bash\r\npip install codex-rosetta\r\ncodex-rosetta\r\n```\r\n\r\n### 从源码安装\r\n\r\n```bash\r\ngit clone https:\u002F\u002Fgithub.com\u002FJiuliNuoyi\u002FCodexRosetta.git\r\ncd CodexRosetta\r\npip install .\r\ncp .env.example .env\r\n# 编辑 .env，配置上游服务商\r\ncodex-rosetta\r\n```\r\n\r\n## 工作原理\r\n\r\n```\r\n┌──────────┐    Responses API     ┌────────────────┐    Chat Completions API    ┌──────────┐\r\n│  客户端   │ ──────────────────▶ │  CodexRosetta   │ ─────────────────────────▶ │ 上游服务  │\r\n│ (Codex,   │ ◀────────────────── │                 │ ◀─────────────────────────  │  提供商  │\r\n│  等)      │    Responses API    │  ┌───────────┐  │    Chat Completions API    │          │\r\n└──────────┘    (转换回)          │  │  转换管线  │  │    (原始响应)              └──────────┘\r\n                                   │  ├───────────┤  │\r\n                                   │  │• 输入转换  │  │\r\n                                   │  │• 工具转换  │  │\r\n                                   │  │• 请求转换  ���  │\r\n                                   │  │• 流式转换  │  │\r\n                                   │  │• 响应转换  │  │\r\n                                   │  └───────────┘  │\r\n                                   └────────────────┘\r\n```\r\n\r\n### 转换管线\r\n\r\n当 Responses API 请求到达时，CodexRosetta 通过多阶段管线处理：\r\n\r\n1. **输入转换器（InputTransformer）** — 将 Responses API 的 `input` 数组转换为扁平的 Chat Completions `messages` 数组。`instructions` 变为 system 消息；`developer` 角色映射为 `system`；`function_call` \u002F `function_call_output` 分别映射为 assistant 的 tool_calls 和 tool 消息；`custom_tool_call` \u002F `custom_tool_call_output` 做同样映射。\r\n\r\n2. **工具转换器（ToolTransformer）** — 在两种格式之间转换工具定义。Function 工具从扁平结构（`name`、`parameters`、`description` 在顶层）重组为嵌套结构（包裹在 `function` 键内）。Responses API 内置工具类型（`web_search`、`file_search`、`computer_use_preview`、`code_interpreter`、`image_generation`）均为 OpenAI 云端执行的工具，Chat Completions API 中没有对应物。CodexRosetta 将它们模拟为 `__rosetta_` 前缀的普通 function 工具，其中 `web_search` 已通过第三方搜索服务实现本地替代，其余工具暂时不可用，需等待上游模型商提供支持或后续更新。\r\n\r\n3. **请求转换器（RequestConverter）** — 编排上述转换器，并映射参数：`max_output_tokens` → `max_completion_tokens`、`text.format` → `response_format`、`reasoning.effort` → `reasoning_effort`、`text.verbosity` 追加提示到 system 消息。此外处理客户端传来的 `truncation: auto`——这是 Responses API 的参数，表示上下文溢出时自动截断，由客户端（如 Codex）发出。由于 Chat Completions API 没有此参数，CodexRosetta 在代理层接管了这个逻辑：当上游返回上下文长度错误时，自动裁剪较早的消息并重试（最多 3 次）。还会清理畸形 JSON 工具调用参数。\r\n\r\n4. **上游客户端（UpstreamClient）** — 通过 `httpx` 将转换后的 Chat Completions 请求发送到配置的上游服务商，支持可配置超时（默认：连接 10s，读取 300s 以应对长流式响应）。\r\n\r\n5. **响应转换器（ResponseConverter）** — 将上游 Chat Completions 响应转换回 Responses API 格式。Assistant 消息变为 `message` 输出项；tool calls 变为 `function_call` 输出项；`__rosetta_` 前缀的函数调用反向映射回其原生内置工具类型（如 `web_search_call` 等）。转换 usage 字段（`prompt_tokens` → `input_tokens` 等）。\r\n\r\n6. **流式转换器（StreamConverter）** — 一个状态机，实时处理 Chat Completions SSE 数据块，发出 Responses API SSE 事件（`response.created`、`response.output_item.added`、`response.content_part.delta`、`response.output_item.done`、`response.completed` 等）。跟踪每个输出项的状态（文本累积、参数累积、reasoning 内容等）。\r\n\r\n### 会话状态\r\n\r\nCodexRosetta 支持 Responses API 的 `previous_response_id` 和 `conversation` 模式：\r\n\r\n- **内存存储**（默认）— 使用 TTL 驱逐策略存储会话历史，适合单实例部署\r\n- **Redis 存储** — 跨重启持久化会话，通过 `REDIS_URL` 配置\r\n\r\n会话存储会将 Responses API 的 output items（message、function_call 等）重建为 Chat Completions 格式的 messages，以便作为历史上下文拼接到下一轮请求中。\r\n\r\n### 联网搜索\r\n\r\n当 `WEB_SEARCH_ENABLED=true` 时，CodexRosetta 拦截 `__rosetta_web_search` 函数调用，查询配置的搜索服务商，并将搜索结果注入到对话中作为 tool 消息返回，然后继续请求上游模型生成回答——提供类似 OpenAI 原生联网搜索的体验。\r\n\r\n搜索结果以模拟流式方式输出（逐字符发送），使客户端能渐进式显示搜索结果。\r\n\r\n### 多轮搜索\r\n\r\n当模型在同一个响应中多次调用 `web_search` 时，CodexRosetta 自动串联搜索轮次：拦截搜索调用 → 查询搜索 API → 将结果注入 → 重新请求上游 → 继续流式输出，所有这些都在单个 SSE 连接内完成，最多循环 `WEB_SEARCH_MAX_ROUNDS` 轮。\r\n\r\n### 内置工具模拟\r\n\r\nResponses API 的部分内置工具为 OpenAI 云端执行，Chat Completions API 没有对应物。CodexRosetta 将它们模拟为 `__rosetta_` 前缀的普通 function 工具：\r\n\r\n- **web_search** — ✅ 已通过第三方搜索服务（Tavily、SearXNG、Brave、DuckDuckGo）实现本地替代，可正常使用\r\n- **file_search** — ❌ 暂时不可用，需等待上游模型商提供支持或后续更新\r\n- **computer_use_preview** — ❌ 暂时不可用，需等待上游模型商提供支持或后续更新\r\n- **code_interpreter** — ❌ 暂时不可用，需等待上游模型商提供支持或后续更新\r\n- **image_generation** — ❌ 暂时不可用，需等待上游模型商提供支持或后续更新\r\n\r\n## 项目架构\r\n\r\n```\r\ncodex_rosetta\u002F\r\n├── main.py                 # FastAPI 应用工厂、中间件注册、启动逻辑\r\n├── config.py               # 配置管理（pydantic-settings，.env 文件）\r\n├── api\u002F\r\n│   ├── router.py           # POST \u002Fv1\u002Fresponses — 主代理端点\r\n│   ├── keys_router.py      # \u002Fv1\u002Fkeys — Key 管理 REST API\r\n│   ├── settings_router.py  # \u002Fv1\u002Fsettings — 运行时设置 REST API\r\n│   ├── web_router.py       # \u002Fapp — 前端 SPA 静态文件服务\r\n│   └── dependencies.py     # FastAPI 依赖注入（upstream client、conversation store）\r\n├── converters\u002F\r\n│   ├── request_converter.py   # 请求转换编排器\r\n│   ├── response_converter.py  # 非流式响应转换\r\n│   ├── stream_converter.py    # SSE 流式状态机\r\n│   ├── input_transformer.py   # input 数组 → messages 数组\r\n│   ├── tool_transformer.py    # 工具定义转换（含内置工具模拟）\r\n│   └── content_transformer.py # 内容部件转换（input_text、input_image 等）\r\n├── builtin_tools\u002F\r\n│   ├── registry.py         # 内置工具模拟器注册表\r\n│   ├── web_search.py       # 联网搜索模拟器（已实现本地替代）\r\n│   ├── file_search.py      # 文件搜索模拟器（暂不可用）\r\n│   ├── computer_use.py     # 电脑操控模拟器（暂不可用）\r\n│   ├── code_interpreter.py # 代码解释器模拟器（暂不可用）\r\n│   └── image_generation.py # 图像生成模拟器（暂不可用）\r\n├── upstream\u002F\r\n│   ├── client.py           # 异步 HTTP 客户端（httpx）\r\n│   └── provider_adapters.py # 服务商适配器（OpenAI 直通、Anthropic\u002FGoogle 参数清理）\r\n├── state\u002F\r\n│   ├── conversation_store.py  # 内存 & Redis 会话存储\r\n│   └── stream_state.py        # 流式转换输出项状态追踪\r\n├── search\u002F\r\n│   ├── base.py             # SearchProvider 抽象基类\r\n│   ├── tavily_provider.py  # Tavily 搜索\r\n│   ├── searxng_provider.py # SearXNG 搜索\r\n│   ├── brave_provider.py   # Brave 搜索\r\n│   ├── duckduckgo_provider.py # DuckDuckGo 搜索（支持直连和远程 API）\r\n│   ├── http_provider.py    # 通用 HTTP 搜索\r\n│   └── formatter.py        # 搜索结果格式化\r\n├── models\u002F\r\n│   └── common.py           # ConversionContext、工具类型常量、__rosetta_ 前缀\r\n├── keys\u002F\r\n│   └── manager.py          # 多 Key 管理（增删改查、激活切换、JSON 持久化）\r\n├── audit\u002F\r\n│   ├── middleware.py        # 审计中间件（捕获原始请求和最终响应）\r\n│   └── logger.py           # 审计日志写入器\r\n└── utils\u002F\r\n    ├── id_generation.py    # resp_、msg_、fc_ 等 ID 生成\r\n    ├── logging.py          # Structlog 配置\r\n    └── sse.py              # SSE 事件格式化\u002F解析\r\n```\r\n\r\n## 支持的服务商\r\n\r\n| 服务商 | `UPSTREAM_PROVIDER` | 说明 |\r\n|---|---|---|\r\n| **OpenAI** | `openai` | 默认，完整支持，请求直通 |\r\n| **其他** | `other` | 任何 OpenAI 兼容 API（vLLM、Ollama、LiteLLM 等），回退为 OpenAI 直通适配器 |\r\n\r\n## 配置\r\n\r\n所有设置均可通过环境变量或 `.env` 文件配置：\r\n\r\n### 核心设置\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `UPSTREAM_BASE_URL` | `https:\u002F\u002Fapi.openai.com\u002Fv1` | 上游 Chat Completions API 地址 |\r\n| `UPSTREAM_API_KEY` | *（必填）* | 上游服务商的 API Key |\r\n| `UPSTREAM_PROVIDER` | `openai` | 服务商：`openai`、`anthropic`、`google`、`other` |\r\n| `HOST` | `0.0.0.0` | 服务监听地址 |\r\n| `PORT` | `33131` | 服务监听端口 |\r\n\r\n### 会话存储\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `REDIS_URL` | *（禁用）* | Redis 地址，用于会话持久化（如 `redis:\u002F\u002Flocalhost:6379\u002F0`） |\r\n| `MAX_CONVERSATION_HISTORY` | `100` | 每个会话保留的最大消息数 |\r\n| `CONVERSATION_TTL_SECONDS` | `3600` | 存储会话的生存时间（秒） |\r\n\r\n### 联网搜索\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `WEB_SEARCH_ENABLED` | `false` | 启用联网搜索工具 |\r\n| `WEB_SEARCH_PROVIDER` | `custom` | 搜索服务商：`tavily`、`searxng`、`brave`、`duckduckgo`、`custom` |\r\n| `WEB_SEARCH_BASE_URL` | *（空）* | 搜索 API 地址（`searxng`、`custom` 必填；`duckduckgo` 可选用于远程 API） |\r\n| `WEB_SEARCH_API_KEY` | *（空）* | 搜索 API Key（`tavily`、`brave` 必填；`searxng`、`custom`、`duckduckgo` 可选） |\r\n| `WEB_SEARCH_MAX_RESULTS` | `5` | 每次查询最大搜索结果数 |\r\n| `WEB_SEARCH_MAX_ROUNDS` | `3` | 每个响应最大搜索轮次 |\r\n| `WEB_SEARCH_SIMULATED_STREAMING_ENABLED` | `true` | 逐字符流式输出搜索结果 |\r\n| `WEB_SEARCH_SIMULATED_STREAM_DELAY_MS` | `25` | 模拟流式输出每字符延迟（毫秒） |\r\n| `WEB_SEARCH_SIMULATED_STREAM_MAX_CHARS` | `32` | 模拟流式输出每块最大字符数 |\r\n\r\n### 日志与审计\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `LOG_LEVEL` | `INFO` | 日志级别 |\r\n| `LOG_UPSTREAM_REQUESTS` | `false` | 记录完整的上游请求体 |\r\n| `LOG_UPSTREAM_RESPONSES` | `false` | 记录完整的上游响应体 |\r\n| `DEBUG_LOG_FILE` | *（禁用）* | 将 JSON 调试日志写入文件 |\r\n| `AUDIT_ENABLED` | `false` | 启用请求审计日志 |\r\n| `AUDIT_DIR` | `.\u002Faudit` | 审计日志文件目录 |\r\n\r\n### 超时设置\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `UPSTREAM_TIMEOUT_CONNECT` | `10` | 连接超时（秒） |\r\n| `UPSTREAM_TIMEOUT_READ` | `300` | 读取超时（秒）— 流式响应需设高 |\r\n\r\n### Key 管理\r\n\r\n| 变量 | 默认值 | 说明 |\r\n|---|---|---|\r\n| `KEYS_FILE` | `.\u002Fdata\u002Fkeys.json` | Key 存储文件路径 |\n\r\n完整配置参考：[.env.example](.env.example)\r\n\r\n## Web 管理界面\r\n\r\nCodexRosetta 内置管理界面，访问 `http:\u002F\u002Flocalhost:33131\u002Fapp`：\r\n\r\n- **Dashboard** — API Key 管理（添加、编辑、删除、切换激活），显示 Key 统计\r\n- **Playground** — 内置聊天测试界面，可直接测试代理转换是否正常工作\r\n- **Settings** — 运行时设置编辑（日志级别、联网搜索配置等），无需重启\r\n\r\nKey 也可以通过 `\u002Fv1\u002Fkeys` REST API 管理（支持 GET 列表、POST 添加、PUT 修改\u002F激活、DELETE 删除）。\r\n\r\n## 注意事项\r\n\r\n- **API Key 安全** — 上游 API Key 仅发送给配置的上游服务商。CodexRosetta 不会将其记录日志或传输到其他地方。`.env` 文件和 `data\u002Fkeys.json` 应妥善保管并排除在版本控制之外。\n- **流式超时** — 默认读取超时为 300 秒。如果使用长时间运行的模型，可能需要增加 `UPSTREAM_TIMEOUT_READ`。\r\n- **上下文溢出自动重试** — `truncation=auto` 是客户端（如 Codex）在 Responses API 请求中传来的参数。由于 Chat Completions API 不支持此参数，CodexRosetta 在代理层接管了这个逻辑：当上游返回上下文长度错误时，自动裁剪较早的非系统消息（每次裁剪 1\u002F4）并重试，最多 3 次。若客户端未传此参数，则超上下文直接报错。\r\n- **内置工具模拟范围** — Responses API 的内置工具均为 OpenAI 云端执行。目前仅 `web_search` 已通过第三方搜索服务实现本地替代，其余工具（`file_search`、`computer_use_preview`、`code_interpreter`、`image_generation`）暂时不可用，需等待上游模型商提供支持或后续更新。\r\n- **畸形 JSON 修复** — 某些模型（如 GLM）可能生成格式错误的工具调用参数 JSON。CodexRosetta 会自动尝试修复截断的 JSON（闭合未关闭的引号和大括号），无法修复时回退为 `{}`，防止上游返回 400 错误。\r\n- **生产环境请使用 Redis** — 默认的内存会话存储在服务重启后会丢失状态。生产环境请通过 `REDIS_URL` 配置 Redis。\r\n- **反向代理** — 如果部署在反向代理（nginx、Caddy）后面，请确保 SSE 连接不被缓冲。nginx 需添加 `proxy_buffering off;`。\r\n\r\n## 技术栈\r\n\r\n**后端：** Python 3.11+ · FastAPI · Uvicorn · httpx · Pydantic · structlog · Redis（可选）\r\n\r\n**前端：** React 19 · TypeScript · Vite · Tailwind CSS 4 · Framer Motion · Lucide\r\n\r\n## 后续规划\r\n\r\n- **Anthropic 接口接入** — 目前 Anthropic 适配器仅做了参数兼容处理，后续将支持 Anthropic 原生 Messages API 的直接接入，无需依赖 Chat Completions 兼容端点\r\n- **修复 Codex Desktop 流式输出** — 已知 Codex Desktop 客户端不支持流式输出，后续将修复此兼容性问题\r\n- **完善内置工具支持** — 逐步实现对 `file_search`、`computer_use_preview`、`code_interpreter`、`image_generation` 等 OpenAI 云端工具的本地替代\r\n\r\n## 开源协议\r\n\r\n[MIT](LICENSE)\r\n\r\n\r\n\r\n","CodexRosetta 是一个用于在 Responses API 和 Chat Completions API 之间进行双向转换的代理服务器，使得任何兼容 Chat Completions 的后端能够驱动需要 Responses API 格式的工具。其核心功能包括实时请求转换、零客户端改动、支持流式处理以及内置联网搜索功能（通过 Tavily、SearXNG、Brave 或 DuckDuckGo 模拟）。此外，它还提供了多 API Key 管理功能。该项目适用于希望使用不同 LLM 服务来驱动 Codex 或类似 ChatGPT 工具的场景，尤其适合那些需要从 Responses API 迁移到 Chat Completions API 的开发者。项目采用 Python 编写，并以 MIT License 开源。",2,"2026-06-11 03:31:18","CREATED_QUERY"]