Deepseek API (and likely other providers) reject messages with
role: 'developer' — only accept system, user, assistant, tool.
filterToOpenAIFormat() normalizes content blocks but never touched
message roles, so developer passed through unmodified and caused
400 errors (issue #773).
Fix: add one-line developer → system mapping in filterToOpenAIFormat()
before role-specific logic. This is the common normalization point
called for all targetFormat=openai providers (Deepseek, Groq, Mistral,
Perplexity, Together, Fireworks, Cerebras, xAI, NVIDIA, etc.)
Closes#773
Internal model test routes fetched 127.0.0.1:UPDATER_CONFIG.appPort
(hardcoded 20128). When PORT env is set to a different value, the app
listens on PORT but the internal fetch still targets 20128, causing
"fetch failed" on /api/models/test and /api/providers/[id]/test-models.
Fall back to UPDATER_CONFIG.appPort only when process.env.PORT is unset.
## Features
- Add Cline & Kilo Code tool cards
- Tailscale TUN mode for stable Funnel TLS
- Sort APIKEY providers by usage, collapse to top 20
## Improvements
- Local Material Symbols font (no Google Fonts)
- Docker base: Bun → Node 22-alpine
- MITM reads aliases from JSON cache (no native sqlite)
- Stream stall timeout (2 min) in open-sse
## Fixes
- Fal.ai key test: use stable models endpoint
Two findings, neither blocked by anything else:
1. src/app/callback/page.js — the OAuth callback page posted the
{ code, state } payload to window.opener with targetOrigin "*", so any
page that opened the popup against the well-known redirect_uri received
the live OAuth code. The expectedOrigins list was already computed but
never used. Iterate over it and pass the origin per send.
2. open-sse/utils/proxyFetch.js — createBypassRequest() set
rejectUnauthorized: false on the HTTPS request that runs after the
Google-DNS-resolved real-IP fallback (used for cloudcode-pa.googleapis,
GitHub Copilot, Cursor, AWS LLM endpoints). Combined with servername:
parsedUrl.hostname this gave SNI-correct connections that nonetheless
ignored cert validation, so an on-path attacker could swap in their
own cert and read the user's API tokens / prompts. Drop the flag.
Detected by Aeon + semgrep (javascript.browser.security.wildcard-postmessage-configuration
+ problem-based-packs.insecure-transport.js-node.bypass-tls-verification).
Severity: HIGH (#1) / MEDIUM (#2).
CWEs: CWE-1385 (#1), CWE-295 (#2).
Co-authored-by: aeonframework <aeon@aeonframework.dev>
- Add global CSS rules for select elements in dark mode
- Use color-scheme property to signal dark mode to browser
- Explicitly style option elements with dark theme colors
- Fix UsageStats dropdown to use correct CSS variables (bg-surface, text-text-main)
Fixes dropdown text being unreadable in dark theme on usage page:
- Provider filter dropdown
- Table view selector (Model/Account/API Key/Endpoint)
- Pagination page size selector
Tested in Chrome and Firefox with both light and dark themes.
## Features
- Add bun:sqlite adapter with automatic runtime detection (Bun/Node)
- Add bulk API key import (format: `name|sk-key`, one per line)
## Fixes
- Fix add API key for custom providers
Update all DeepSeek model prices to match current V4 Flash pricing
($0.14/$0.28 per 1M input/output tokens), and add V4 Pro model with
its own pricing ($0.435/$0.87). Also add deepseek-v4-pro to the
provider model list.
Co-authored-by: smarthomeblack <truongbber@gmail.com>
With this single file, it becomes very easy to deploy this service on a caprover instance
All that needs to be done to do so on the caprover dashboard is:
- Create a new app with persistance
- Set these envs:
PORT=20128
HOSTNAME=0.0.0.0
NEXT_PUBLIC_BASE_URL=https://your-domain-here.com
DATA_DIR=/app/data
- Add a persistent directory with /app/data
- Set CONTAINER HTTP PORT to 20128, enable HTTPS and websockets
- Go in deployment -> Method 3 -> Set the git url to this repo on branch main and add your github email and a PAT
- Save and force build
- Introduced OllamaLocalExecutor to handle requests for the "ollama-local" provider.
- Removed the direct URL construction for "ollama-local" from BaseExecutor.
- Updated index.js to include the new OllamaLocalExecutor in the executors mapping.
- Enhanced the ProvidersPage component to support dynamic addition of OpenAI/Anthropic compatible providers.
The totalRequests on dashboard/usage overview always showed lifetime total
instead of respecting the selected period (24h/7d/30d/60d). Now calculated
from period-filtered data like other stats.
Co-authored-by: Tuan-TC <tuan-tc@users.noreply.github.com>
- Implemented handleDeselectModel function to allow users to deselect models in both ComboFormModal and ComboDetailPage.
- Updated ModelSelectModal to handle deselection and visually indicate selected models.
- Enhanced user experience by allowing models to be removed from the selection without closing the modal.
Add input_audio and audio_url content type handlers to
convertOpenAIContentToParts() in geminiHelper.js, converting
OpenAI audio format to Gemini inlineData format.
Also add audio types to VALID_OPENAI_CONTENT_TYPES in
openaiHelper.js so they are not stripped by filterToOpenAIFormat().
Fixes#912
- Introduced DEFAULT_QUICK_TUNNEL_PROTOCOL and QUICK_TUNNEL_PROTOCOLS to allow users to specify the transport protocol for quick tunnels.
- Updated spawnQuickTunnel function to utilize the specified protocol from environment variables, defaulting to HTTP/2 if not provided.
- Enhanced the child process environment to include the selected tunnel transport protocol.
- Request translation: add codeWhispererToMessages() to convert CodeWhisperer conversationState to OpenAI messages array
- Response format: replace pipeSSE() with pipeOpenAIasEventStream() to return AWS EventStream binary frames instead of SSE text
- Protocol headers: add required Smithy system headers (:message-type, :event-type, :content-type) to every EventStream frame
- Tool support: add extractTools() to convert CodeWhisperer toolSpecification to OpenAI tool format
- Tool arguments: add safeArgsString() to prevent '[object Object]' corruption during SSE accumulation
- Multi-turn context: add convertAssistantResponseMessage() and convertUserInputMessage() to preserve toolUses and toolResults in history
- Tool dispatch: send toolUseEvent.input as raw JSON string instead of parsed object to match Kiro's internal JSON.parse() expectation
- BaseUrlSelect: add cloud endpoint option, custom URL local state, always
default to first option; new cliEndpointMatch helper; CLI tool cards refactor
- API: new /v1/audio/voices and /v1/models/info; /v1/models filters disabled
models, drop unused timestamp
- initializeApp: guard tunnel/tailscale auto-resume to once-per-process
- geminiHelper: ensureObjectType for schemas with properties but no type
- skills: minor SKILL.md tweaks (chat/embeddings/image/stt/tts/web-*)
- Introduced a caching mechanism for in-flight token refresh requests to prevent race conditions and reduce unnecessary API calls.
- Added error handling for unrecoverable refresh errors, ensuring that the application can gracefully handle token reuse and invalidation scenarios.
- Updated the MITM server management to handle port 443 conflicts, allowing users to kill processes occupying the port before starting the server.
- Improved user feedback in the MitmServerCard component regarding port conflicts and admin privileges.
- Refactored the ComboList component to streamline the display of media provider combos.
This update aims to enhance the reliability and user experience of the token management and MITM functionalities.
- Updated global CSS to implement a new brand color palette and improve light/dark theme consistency.
- Enhanced the MitmServerCard component to provide clearer user feedback regarding admin privileges.
- Filtered LLM combos in the CombosPage to ensure only relevant data is displayed.
- Improved APIPageClient layout for better usability and visual consistency.
- Added functionality to save and load DNS tool states in the MITM manager.
- Updated OAuth configuration URLs for Qwen to reflect the new endpoint structure.
- Refined tunnel management logic to improve reliability and user experience.
commit 8b2ab7c9e05689c1bf55002cc79db8d22a398c75
Author: kundeng <kundeng@live.com>
Date: Mon Apr 20 11:26:58 2026 -0400
fix: send providerSpecificData in Edit modal validate calls
The Check button in the Edit modal was sending only apiKey without the
Azure endpoint/deployment/org, causing validation to fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
commit c894fa838d035ecd9a160339342371042697c327
Author: kundeng <kundeng@live.com>
Date: Mon Apr 20 01:45:13 2026 -0400
fix: persist Azure providerSpecificData and add connection test
- Read body.providerSpecificData in POST /api/providers so Azure fields
(endpoint, deployment, apiVersion, organization) are actually stored
- Add azure case to testApiKeyConnection so the Test button works
correctly instead of falling through to "not supported"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
commit 00bd1a4151f4e73616969e25d1786c87d1ec0d5e
Author: kundeng <kundeng@live.com>
Date: Mon Apr 20 01:24:39 2026 -0400
fix: add Azure validation and make Organization required
- Add Azure case to /api/providers/validate that sends a test chat
completion with api-key header and organization
- Pass Azure-specific data (endpoint, deployment, apiVersion, org) from
Add modal to validate endpoint
- Make Organization field required (needed for billing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
commit a66a04daab69b07baa4cc6b28772249e4b25ea19
Author: kundeng <kundeng@live.com>
Date: Mon Apr 20 01:15:53 2026 -0400
fix: add Azure config fields to Add API Key modal
The Add modal was missing the Azure-specific fields (endpoint, deployment,
API version, organization) — only the Edit modal had them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
commit 6ac3f4a97af8468d210594495ce754f5d7a7978a
Author: kundeng <kundeng@live.com>
Date: Mon Apr 20 01:06:45 2026 -0400
feat: add Azure OpenAI as a dedicated provider
Azure OpenAI uses a different URL scheme (deployments-based) and api-key
header auth instead of Bearer tokens. This adds a dedicated AzureExecutor
that constructs the correct URL and headers, plus dashboard UI fields for
endpoint, deployment, API version, and organization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add reusable EndpointPresetControl for CLI tool Base URL/API key
presets, stored in browser localStorage. Wire into Claude, Codex,
OpenCode, Droid, OpenClaw, Hermes, and Copilot cards. Allow
selecting preset API keys not in dashboard keys list.
Thanks @dmdfami for the contribution!
Co-authored-by: dmdfami <dmdfami@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Ensure /v1/models includes provider models added through alias mappings so compatible provider entries like huoshan/kimi-k2.6 are discoverable by clients.
Made-with: Cursor
Co-authored-by: Ken Lin <kenlin1988@foxmail.com>