Co-authored-by: Quan <quanle96@outlook.com>
PR: https://github.com/decolua/9router/pull/298
Thanks to @kwanLeeFrmVi for the original implementation. Here is a summary
of changes made during review integration:
- Replaced google-auth-library with jose (already a project dependency)
for SA JSON -> OAuth2 Bearer token minting (RS256 JWT assertion flow)
- Moved auth logic (parseSaJson, refreshVertexToken, token cache) from
executor into open-sse/services/tokenRefresh.js to match project pattern
- Fixed executor to use proxyAwareFetch instead of raw fetch (proxy support)
- Simplified buildUrl: use global aiplatform.googleapis.com endpoint for
both vertex (Gemini) and vertex-partner; removed region/modelFamily fields
- Added auto-detection of GCP project_id from raw API key via probe request
(vertex-partner only, cached per key)
- Added vertex/vertex-partner cases to /api/providers/validate/route.js
- Updated model lists based on live testing:
- vertex: gemini-3.1-pro-preview, gemini-3.1-flash-lite-preview,
gemini-3-flash-preview, gemini-2.5-flash (removed gemini-2.5-pro: 404)
- vertex-partner: deepseek-v3.2, qwen3-next-80b (instruct+thinking),
glm-5 (removed Mistral/Llama: not enabled in test project)
- gemini provider: added gemini-3.1-pro-preview, gemini-3.1-flash-lite-preview
- Removed bun.lock (project uses npm/package-lock.json)
- Removed region and modelFamily UI fields (global endpoint, auto-detect)
- Kiro token auto-refresh on AccessDeniedException (from commit 2)
Made-with: Cursor
- Added new provider models: DeepSeek 3.1, DeepSeek 3.2, and Qwen3 Coder Next.
- Implemented UI changes to support round-robin strategy with sticky limits in the provider detail page.
- Improved logging to display connection names instead of IDs for better clarity.
- Centralize proxy management with reusable proxy pools
- Per-connection proxy binding with legacy fallback
- Add strictProxy option: fail hard instead of silently falling back to direct
- Resolve alicode-intl conflict: keep alicode-intl support + proxy support
Made-with: Cursor
- Implement runtime i18n using MutationObserver for automatic DOM translation
- Add language switcher dropdown in dashboard header (EN/VI/ZH)
- Support 3 languages: English (default), Tiếng Việt, 简体中文
- Add translation files: vi.json (197 entries), zh-CN.json (513 entries, cleaned)
- Translate dashboard UI: sidebar menu, header, settings, MITM page
- Use cookie-based locale persistence with /api/locale endpoint
- Zero component changes required - translations applied at runtime
- Fix Header flicker on route change with key={pathname}
Co-authored-by: eachann <each1024@qq.com>
Based on PR #247 from decolua/9router with runtime approach
Made-with: Cursor
- Add buildQwenBaseUrl function to construct URLs for Qwen resources.
- Update buildProviderUrl to support Qwen model requests.
- Enhance token refresh logic to include provider-specific data for Qwen.
- Refactor CLI Tools page to exclude MITM tools and streamline model retrieval.
- Introduce new components for MITM server management.
- Update API routes to handle Qwen-specific resource URLs and improve error handling.
* fix(translator): filter nameless hosted tools when converting Responses API to Chat format
Codex CLI sends "hosted" tools (e.g. `request_user_input`) via the OpenAI
Responses API. These tools have no explicit `name` field. The previous
`body.tools.map()` pass propagated `name: undefined` into the resulting
Chat Completions function declarations, which then became anonymous
`functionDeclarations` after the OpenAI→Gemini translation step.
Gemini strictly requires every function declaration to have a valid name
and rejects the entire request with:
GenerateContentRequest.tools[0].function_declarations[4].name:
Invalid function name. Must start with a letter or an underscore.
Fix: filter out any Responses API tool that lacks a non-empty `name`
string before converting to `{ type: "function", function: { name, ... } }`.
Named function tools are unaffected; only unnamed hosted tools are skipped.
Fixes: Gemini 400 error when Codex CLI is routed through 9router.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(gemini): convert OpenAI SSE to Gemini SSE format in /v1beta/models route
The @google/genai SDK always uses :streamGenerateContent?alt=sse for chat
and expects Gemini SSE chunk format. The upstream handleChat returns OpenAI
SSE format, causing the SDK to crash on the [DONE] sentinel.
Changes:
- Add transformOpenAISSEToGeminiSSE() using TransformStream that converts
each OpenAI SSE chunk (choices[0].delta) to Gemini SSE format
(candidates[0].content.parts) on the fly
- Drop the OpenAI [DONE] sentinel (Gemini SSE ends by stream close)
- Map finish_reason -> finishReason, attach usageMetadata on final chunk
- Support reasoning_content -> thought: true parts for thinking models
- Refactor finishReasonMap to shared FINISH_REASON_MAP constant
- Fix streaming dispatch: stream=true now calls transformOpenAISSEToGeminiSSE
instead of passing OpenAI SSE through raw
Fixes: SyntaxError: "[DONE]" is not valid JSON in Gemini CLI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Add a warning message for Windows users in AntigravityToolCard to run the terminal as Administrator for MITM functionality.
- Refactor model testing logic in ProviderDetailPage to improve state management and user experience.
- Introduce new version notification in Sidebar for available updates.
- Add a 10-second timeout for fetch requests in getAntigravityUsage and getAntigravitySubscriptionInfo functions.
- Include error logging for fetch failures in both functions.
- Update headers to include "x-request-source" for MITM bypass.
- Enhance proxyFetch with DNS resolution and MITM bypass capabilities.
- Ensure proxyFetch is loaded in the API route for proper fetch patching.
- Added eye icon button to show/hide individual API keys
- Keys hidden by default on page load for security
- Copy button always copies full key regardless of visibility state
- Implemented per-key visibility state with React useState
- Added maskKey helper to display first 8 characters + "..."
- Clean up visibility state when keys are deleted
Improves security and UX when managing API keys in the dashboard.
- Patch Node fetch via undici ProxyAgent when HTTP_PROXY/HTTPS_PROXY/ALL_PROXY is set
- Ensure proxy patch is loaded for both chat pipeline and OAuth token exchange
- Add Dashboard Settings → Network to edit outbound proxy and apply immediately
- Persist outbound proxy settings in local db and initialize on server startup
- Move proxy helpers to src/lib/network/ for better structure
- Rename src/proxy.js → src/dashboardGuard.js to avoid naming confusion
- Re-apply proxy env after DB import
- Fix: close old dispatcher on proxy URL change to prevent connection pool leak
- Fix: idempotency guard to avoid patching globalThis.fetch multiple times
Made-with: Cursor
Rename alicloud to alicode to clearly indicate Aliyun's Coding Plan service.
- Provider ID: alicode (short for Aliyun Coding)
- Model format: alicode/qwen3.5-plus
- Simplified mapping - no more bidirectional aliases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for Alibaba Cloud Bailian Coding Plan, a coding-focused AI service
that provides fixed monthly pricing for multiple models.
Changes:
- Add alicloud provider with OpenAI-compatible API endpoint
- Support 8 models: qwen3.5-plus, kimi-k2.5, glm-5, MiniMax-M2.5,
qwen3-max, qwen3-coder-next, qwen3-coder-plus, glm-4.7
- Use "ali" as provider alias (ali/model format)
- Add API key validation and connection testing
- Add frontend provider definition with "ALi" text icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added functionality to fetch and set statuses for various CLI tools (Claude, Codex, Droid, OpenClaw, Antigravity) on component mount.
- Enhanced error handling and logging in the OAuth provider test utilities and DNS management functions.
- Improved the MITM server to handle multiple target hosts and provide clearer error messages regarding port usage.
- Introduced a new ProviderDetailPage component to handle provider-specific functionalities.
- Implemented state management for connections, loading states, and model selections.
- Added API calls for fetching provider connections and model aliases.
- Included modals for OAuth and API key management.
- Enhanced user experience with model selection and saving capabilities.