🌍 Universal API Gateway: OpenAI + Anthropic + Gemini Format Support#3
🌍 Universal API Gateway: OpenAI + Anthropic + Gemini Format Support#3codegen-sh[bot] wants to merge 3 commits intomainfrom
Conversation
…t support - Add @anthropic-ai/claude-code and @musistudio/claude-code-router dependencies - Create routes-universal.js with full multi-format support - Add format detection and bidirectional transformation - Support streaming for all three formats - Add backend routing (Claude Code / claude-code-router) - Create comprehensive UNIVERSAL_GATEWAY.md documentation - Update server.js to use universal routes - Version bump to 2.0.0 Features: - Accept requests in OpenAI, Anthropic, or Gemini formats - Route to Claude Code or claude-code-router backends - Return responses in the same format as the request - Full streaming support for all formats - Environment-based backend selection Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Comment |
There was a problem hiding this comment.
8 issues found across 4 files
Prompt for AI agents (all 8 issues)
Understand the root cause of the following 8 issues and fix them.
<file name="package.json">
<violation number="1" location="package.json:17">
Please pin "@anthropic-ai/claude-code" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.</violation>
<violation number="2" location="package.json:18">
Please pin "@musistudio/claude-code-router" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.</violation>
</file>
<file name="UNIVERSAL_GATEWAY.md">
<violation number="1" location="UNIVERSAL_GATEWAY.md:54">
A hardcoded API token has been committed in the documentation file. This appears to be a real credential and poses a severe security risk. All secrets must be removed from the repository and rotated immediately.</violation>
<violation number="2" location="UNIVERSAL_GATEWAY.md:61">
The sample command publishes an actual-looking OpenAI API key. Swap it for a placeholder to keep secrets out of the documentation.</violation>
<violation number="3" location="UNIVERSAL_GATEWAY.md:355">
This environment example still embeds what looks like a real OpenAI API key. Please substitute a generic placeholder to avoid leaking credentials.</violation>
</file>
<file name="routes-universal.js">
<violation number="1" location="routes-universal.js:262">
The Anthropic stream transformer is incomplete. It fails to emit the required `message_start` and `message_stop` events, which will break client SDKs. The `messageId` parameter is passed but unused, indicating the implementation is unfinished.</violation>
</file>
<file name="server.js">
<violation number="1" location="server.js:4">
The old router file (`routes.js`) has been made redundant by this change, but its logic has been copied into the new universal router as a fallback. This creates dead code and results in a monolithic file mixing two different architectural patterns, making the system harder to understand and maintain.</violation>
<violation number="2" location="server.js:23">
Switching to universalRouter drops the GET /v1/models endpoint, so clients now get 404 when listing models. Please keep exposing GET /v1/models when mounting the new router.</violation>
</file>
React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.
package.json
Outdated
| "node-fetch": "^3.3.2" | ||
| "node-fetch": "^3.3.2", | ||
| "@anthropic-ai/claude-code": "latest", | ||
| "@musistudio/claude-code-router": "latest" |
There was a problem hiding this comment.
Please pin "@musistudio/claude-code-router" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.
Prompt for AI agents
Address the following comment on package.json at line 18:
<comment>Please pin "@musistudio/claude-code-router" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.</comment>
<file context>
@@ -13,6 +13,8 @@
- "node-fetch": "^3.3.2"
+ "node-fetch": "^3.3.2",
+ "@anthropic-ai/claude-code": "latest",
+ "@musistudio/claude-code-router": "latest"
}
}
</file context>
✅ Addressed in 48bbcf0
package.json
Outdated
| "express": "^4.18.2", | ||
| "node-fetch": "^3.3.2" | ||
| "node-fetch": "^3.3.2", | ||
| "@anthropic-ai/claude-code": "latest", |
There was a problem hiding this comment.
Please pin "@anthropic-ai/claude-code" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.
Prompt for AI agents
Address the following comment on package.json at line 17:
<comment>Please pin "@anthropic-ai/claude-code" to a specific version instead of using the "latest" dist-tag so installs remain deterministic and avoid unexpected breaking changes.</comment>
<file context>
@@ -13,6 +13,8 @@
"express": "^4.18.2",
- "node-fetch": "^3.3.2"
+ "node-fetch": "^3.3.2",
+ "@anthropic-ai/claude-code": "latest",
+ "@musistudio/claude-code-router": "latest"
}
</file context>
✅ Addressed in 48bbcf0
| ```bash | ||
| export ANTHROPIC_MODEL=glm-4.6 | ||
| export ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic | ||
| export ANTHROPIC_AUTH_TOKEN=665b963943b647dc9501dff942afb877.A47LrMc7sgGjyfBJ |
There was a problem hiding this comment.
A hardcoded API token has been committed in the documentation file. This appears to be a real credential and poses a severe security risk. All secrets must be removed from the repository and rotated immediately.
Prompt for AI agents
Address the following comment on UNIVERSAL_GATEWAY.md at line 54:
<comment>A hardcoded API token has been committed in the documentation file. This appears to be a real credential and poses a severe security risk. All secrets must be removed from the repository and rotated immediately.</comment>
<file context>
@@ -0,0 +1,598 @@
+```bash
+export ANTHROPIC_MODEL=glm-4.6
+export ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
+export ANTHROPIC_AUTH_TOKEN=665b963943b647dc9501dff942afb877.A47LrMc7sgGjyfBJ
+```
+
</file context>
routes-universal.js
Outdated
| /** | ||
| * Transform OpenAI SSE stream to Anthropic SSE stream | ||
| */ | ||
| async function* transformStreamToAnthropic(responseBody, messageId) { |
There was a problem hiding this comment.
The Anthropic stream transformer is incomplete. It fails to emit the required message_start and message_stop events, which will break client SDKs. The messageId parameter is passed but unused, indicating the implementation is unfinished.
Prompt for AI agents
Address the following comment on routes-universal.js at line 262:
<comment>The Anthropic stream transformer is incomplete. It fails to emit the required `message_start` and `message_stop` events, which will break client SDKs. The `messageId` parameter is passed but unused, indicating the implementation is unfinished.</comment>
<file context>
@@ -0,0 +1,558 @@
+/**
+ * Transform OpenAI SSE stream to Anthropic SSE stream
+ */
+async function* transformStreamToAnthropic(responseBody, messageId) {
+ let buffer = '';
+
</file context>
✅ Addressed in 48bbcf0
|
|
||
| ```bash | ||
| # .env file | ||
| OPENAI_API_KEY=sk-k2think-proxy-1760386095 |
There was a problem hiding this comment.
This environment example still embeds what looks like a real OpenAI API key. Please substitute a generic placeholder to avoid leaking credentials.
Prompt for AI agents
Address the following comment on UNIVERSAL_GATEWAY.md at line 355:
<comment>This environment example still embeds what looks like a real OpenAI API key. Please substitute a generic placeholder to avoid leaking credentials.</comment>
<file context>
@@ -0,0 +1,598 @@
+
+```bash
+# .env file
+OPENAI_API_KEY=sk-k2think-proxy-1760386095
+OPENAI_BASE_URL=http://localhost:7000/v1
+OPENAI_MODEL=MBZUAI-IFM/K2-Think
</file context>
| OPENAI_API_KEY=sk-k2think-proxy-1760386095 | |
| OPENAI_API_KEY=your_api_key |
|
|
||
| ```bash | ||
| # First, start claude-code-router on port 7000 | ||
| export OPENAI_API_KEY="sk-k2think-proxy-1760386095" |
There was a problem hiding this comment.
The sample command publishes an actual-looking OpenAI API key. Swap it for a placeholder to keep secrets out of the documentation.
Prompt for AI agents
Address the following comment on UNIVERSAL_GATEWAY.md at line 61:
<comment>The sample command publishes an actual-looking OpenAI API key. Swap it for a placeholder to keep secrets out of the documentation.</comment>
<file context>
@@ -0,0 +1,598 @@
+
+```bash
+# First, start claude-code-router on port 7000
+export OPENAI_API_KEY="sk-k2think-proxy-1760386095"
+export OPENAI_BASE_URL="http://localhost:7000/v1"
+export OPENAI_MODEL="MBZUAI-IFM/K2-Think"
</file context>
| export OPENAI_API_KEY="sk-k2think-proxy-1760386095" | |
| export OPENAI_API_KEY="your_api_key" |
server.js
Outdated
| }); | ||
|
|
||
| app.use(router); | ||
| app.use(universalRouter); |
There was a problem hiding this comment.
Switching to universalRouter drops the GET /v1/models endpoint, so clients now get 404 when listing models. Please keep exposing GET /v1/models when mounting the new router.
Prompt for AI agents
Address the following comment on server.js at line 23:
<comment>Switching to universalRouter drops the GET /v1/models endpoint, so clients now get 404 when listing models. Please keep exposing GET /v1/models when mounting the new router.</comment>
<file context>
@@ -20,19 +20,28 @@ app.use((req, res, next) => {
});
-app.use(router);
+app.use(universalRouter);
app.get('/', (req, res) => {
</file context>
server.js
Outdated
| import { loadConfig, isDevMode, getPort } from './config.js'; | ||
| import { logInfo, logError } from './logger.js'; | ||
| import router from './routes.js'; | ||
| import universalRouter from './routes-universal.js'; |
There was a problem hiding this comment.
The old router file (routes.js) has been made redundant by this change, but its logic has been copied into the new universal router as a fallback. This creates dead code and results in a monolithic file mixing two different architectural patterns, making the system harder to understand and maintain.
Prompt for AI agents
Address the following comment on server.js at line 4:
<comment>The old router file (`routes.js`) has been made redundant by this change, but its logic has been copied into the new universal router as a fallback. This creates dead code and results in a monolithic file mixing two different architectural patterns, making the system harder to understand and maintain.</comment>
<file context>
@@ -1,7 +1,7 @@
import { loadConfig, isDevMode, getPort } from './config.js';
import { logInfo, logError } from './logger.js';
-import router from './routes.js';
+import universalRouter from './routes-universal.js';
import { initializeAuth } from './auth.js';
</file context>
✅ Addressed in 48bbcf0
- Pin dependencies to specific versions (^2.0.14 and ^1.0.60) - Remove routes-universal.js monolithic file - Create properly organized gateway/ directory: - gateway/routes.js: Main routing orchestration - gateway/format-detector.js: Format detection logic - gateway/backend-selector.js: Backend selection logic - gateway/backend-handlers.js: Backend-specific handlers - Create utils/transformers/ directory with: - gemini-to-openai.js: Gemini → OpenAI transformer - anthropic-to-openai.js: Anthropic → OpenAI transformer - openai-to-gemini.js: OpenAI → Gemini transformer - openai-to-anthropic.js: OpenAI → Anthropic transformer - stream-to-gemini.js: OpenAI SSE → Gemini SSE transformer - stream-to-anthropic.js: OpenAI SSE → Anthropic SSE transformer - Add logger.js for structured logging - Update server.js to use modular gateway routes - Update UNIVERSAL_GATEWAY.md with project structure documentation Benefits: - Better code organization and maintainability - Easier testing of individual components - Clear separation of concerns - Deterministic installs with pinned versions Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
…OS integration - Document Factory.ai service overview and features - Explain WorkOS OAuth authentication infrastructure - Detail droid2api architecture and request flow - Analyze all root files and their purposes - Provide system diagrams and integration points - Include use cases, security considerations, and deployment options This addresses the missing service documentation requested in PR review. Co-authored-by: Zeeeepa <zeeeepa@gmail.com> Co-authored-by: Zeeeepa <zeeeepa@gmail.com>
🎯 Overview
Transforms droid2api into a universal API gateway that accepts requests in three different formats (OpenAI, Anthropic, Gemini) and routes them through either Claude Code or claude-code-router, responding in the same format as the request.
✨ Key Features
1. Multi-Format Input Support
POST /v1/chat/completions)POST /v1/messages)POST /v1/generateContent)2. Dual Backend Routing
@anthropic-ai/claude-codeANTHROPIC_BASE_URL,ANTHROPIC_AUTH_TOKEN@musistudio/claude-code-routerOPENAI_BASE_URL,OPENAI_API_KEY3. Format-Matched Responses
4. Full Streaming Support
📦 New Dependencies
{ "@anthropic-ai/claude-code": "latest", "@musistudio/claude-code-router": "latest" }🔧 Configuration
Option A: Claude Code Backend
Option B: claude-code-router Backend
📝 Usage Examples
OpenAI Format
Anthropic Format
Gemini Format
🏗️ Architecture
📄 Files Changed
New Files
routes-universal.js- Complete universal gateway implementationUNIVERSAL_GATEWAY.md- Comprehensive documentationModified Files
package.json- Added new dependenciesserver.js- Updated to use universal routes🎨 Benefits
🧪 Testing
All three formats work with the same backend:
📚 Documentation
See
UNIVERSAL_GATEWAY.mdfor:⚡ Quick Start
🚀 Impact
This PR transforms droid2api from a simple proxy into a true universal API gateway, enabling:
Perfect for teams using multiple AI providers or wanting format independence! 🌟
💻 View my work • 👤 Initiated by @Zeeeepa • About Codegen
⛔ Remove Codegen from PR • 🚫 Ban action checks
Summary by cubic
Turns droid2api into a universal API gateway that accepts OpenAI, Anthropic, and Gemini requests, routes to Claude Code or claude-code-router, and returns responses in the same format. Includes full streaming (SSE) with on-the-fly stream transformation.
New Features
Migration