Commit graph

580 commits

Author SHA1 Message Date
decolua
d4ecad24d3 fix(antigravity): add kind:image to image models so they show in media-providers UI
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 17:59:51 +07:00
Nautilaceae
5306bd904e feat(antigravity): native image generation support
Add image generation for Antigravity provider via gemini-3.1-flash-image
and gemini-3-pro-image, exposed through Text to Image UI and
/v1/images/generations.

- registry: serviceKinds ['llm','image'] + image model entries
- executor: image model detection + image_gen request envelope
- chatCore: force stream=false for image models (generateContent)
- nonStreamingHandler: parse inlineData -> markdown image
- imageGenerationCore: useExecutor fast-path for executor delegation
- imageProviders/antigravity: image adapter with image input support
- usage/google: image models in quota whitelist

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 17:54:32 +07:00
swatker
b4d2754d32 fix: enable vision capability for MiniMax-M3
The pattern matcher marked *minimax-m3* as vision: false, causing
9Router to strip image attachments before forwarding upstream. This
broke Claude Code / Cursor / Cline vision flows when routing through
MiniMax-M3.

Scoped vision: true to *minimax-m3* only. M2.7 and the catch-all
*minimax* pattern remain vision: false: those models are text-only
(per MiniMax docs / NVIDIA NIM model card), so forcing vision there
would send images to a model that errors instead of degrading.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 17:50:08 +07:00
decolua
36153fedbd fix(mimo-free): add Chrome User-Agent rotation to bypass anti-abuse gate
Fixes #1933 — upstream returns 403 "Illegal access" on the chat endpoint
when requests lack a browser-like User-Agent. Mirror OmniRoute mimocode
executor: rotate across 3 Chrome UA strings on both bootstrap and chat.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:51:47 +07:00
decolua
7baf293ccb fix(cloudflare-ai): flatten content-part arrays to string to avoid oneOf 400 (#1926)
Workers AI rejects OpenAI content-part array shape; flatten text parts
to a plain string per message before sending.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:46:21 +07:00
decolua
45240c19e5 fix(translator): normalize tools to Anthropic-native shape for non-Anthropic providers
Strip `type` field and fold `function.{name,description,parameters}` into
top-level {name, description, input_schema} before forwarding to Claude-format
endpoints. MiniMax (and other Anthropic-compatible providers) reject tools
carrying a `type` field with error code 2013 ("invalid tool type").

Refs #1939

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:26:17 +07:00
Janu Yoga
8321032e36 feat(codebuddy-cn): add API key auth + credit quota tracker
Two additions on top of the merged CodeBuddy CN OAuth provider:

1. API key auth — connect with a direct API key (sent as
   Authorization: Bearer), not only via OAuth device-code flow.
   - registry: add authModes ["oauth","apikey"] + hasOAuth; combined Bearer
     auth already forwards the key, token-refresh skips key connections.
   - providers POST: accept dual-auth providers (authModes includes
     "apikey") that live under category "oauth" — previously rejected as
     "Invalid provider". Also fixes the same latent gap for xai.

2. Quota tracker — surface CodeBuddy CN credit balance on the usage
   dashboard for both OAuth and API-key connections.
   - registry: add transport.usage.url (Tencent billing endpoint) +
     features.usage/usageApikey so the connection is quota-eligible.
   - new CN-scoped handler services/usage/codebuddy-cn.js: POST the billing
     meter endpoint, unwrap data.Response.Data.Accounts[]. The payload mixes
     two credit types that must not be merged:
       * refill/base ("基础体验包") — recurring allowance; cycle resets well
         before the resource expires (CycleEndTime << DeductionEndTime).
         Reads the *Cycle* balance, resetAt = next refresh. Cadence-labelled.
       * bonus ("活动赠送包") — one-shot credits that expire at CycleEndTime.
         Reads the plain Capacity balance. Labelled "Bonus Pack N".
     One quota row per package, soonest-expiring first.
   - register handler under "codebuddy-cn" in USAGE_HANDLERS.

Frontend needs no change — USAGE_SUPPORTED_PROVIDERS/USAGE_APIKEY_PROVIDERS
and the generic parseQuotaData branch already cover this shape.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:12:20 +07:00
Janu Yoga
791705ae7a feat(codebuddy-cn): add short model prefix alias "cbcn"
codebuddy-cn shipped without a short alias, making its model prefix the
longest of any provider (codebuddy-cn/glm-5.2). Add alias + uiAlias
"cbcn" so the prefix becomes cbcn/glm-5.2, consistent with qoder (qd),
kiro (kr), codex (cx). "cbcn" = CodeBuddy CN; reserves "cbai" for a
future codebuddy-ai (intl) provider.

Backward-compatible: full id codebuddy-cn/... still resolves (resolver
matches both id and alias).

Also regenerate tests/__baseline__/alias-baseline.json: idToAlias entry
codebuddy-cn now maps to cbcn, and cbcn joins the sorted modelKeys list.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:02:38 +07:00
Sutarto Jordan Chrisfivo
ed68bcedf8 fix(codex): preserve custom tools during request normalization
Add CODEX_PASSTHROUGH_TOOL_TYPES allowlist so Responses-native freeform
tools (e.g. grammar-backed apply_patch) survive normalizeCodexTools and
reach the upstream Codex Responses API intact.

Refs #1907

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:01:45 +07:00
decolua
13abe7f7f6 Fix AG 2026-06-21 15:58:38 +07:00
decolua
401d93bd5c fix(claude haiku): update handling of unsupported adaptive thinking and output_config.effort 2026-06-20 16:29:15 +07:00
mustafabozkaya
f6c2f7cae3 fix(gemini): preserve 'pattern' in antigravity tool schema translation
Remove "pattern" from UNSUPPORTED_SCHEMA_CONSTRAINTS so glob/grep tool
schemas keep the required "pattern" property for the antigravity provider.

Fixes decolua/9router#1368

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 15:31:22 +07:00
warelik
86162eeb8f fix(combo/fusion): flatten Anthropic-style tool messages in panel calls
flattenToolHistory only recognized OpenAI-style tool calls. Anthropic-compatible clients (Claude Code, /v1/messages) send tool invocations and results as tool_use/tool_result blocks inside the message content array. Since panel calls strip the tools definitions (#1859), the panel expert models received structured tool history without schemas, causing them to fail or misbehave (leading to empty responses and 503 errors).

Extend flattenToolHistory to recognize and flatten tool_use and tool_result blocks in the content array into prose text, keeping panel expert execution robust and independent of the client API format.

PR decolua/9router#1910

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 15:19:31 +07:00
nguyenha935
8efacc1147 feat(opencode-go): align Go models with official endpoints
Update OpenCode Go model catalog to match the official Go docs.
Route Qwen 3.7 and MiniMax models through /v1/messages with
Anthropic-compatible headers instead of OpenAI-compatible chat.
Keep GLM, Kimi, DeepSeek, and MiMo on /chat/completions; use
kimi-k2.7-code because the live Go API rejects kimi-k2.7 for chat
while the docs config example uses the code model ID.

PR #1931 by nguyenha935

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 15:09:11 +07:00
decolua
637dd7ae66 feat(ponytail): introduce "Ponytail" feature for minimalistic code generation 2026-06-20 15:08:11 +07:00
decolua
b55cf36d2e feat(headroom): add proxy lifecycle management + dashboard UI
Build on the optional Headroom Token Saver from Carmelo Campos
(PR: feat: add optional Headroom token saver). Add managed start/stop
of the local headroom proxy from the dashboard, install detection,
status probing, and a simplified Token Saver UI.

- detect headroom CLI + python>=3.10, probe proxy /health
- spawn/stop proxy as a detached, pid-tracked process
- /api/headroom/{status,start,stop} routes, gated local-only in dashboardGuard
- one-click Start/Stop Headroom modal, no manual config needed
- claude<->openai shape conversion for /v1/compress via 9router translators

Thanks to Carmelo Campos (@carmelogunsroses) for the original Headroom integration.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 10:09:50 +07:00
Janu Yoga
efd20be8d8 feat(provider): add CodeBuddy CN provider (copilot.tencent.com)
Add Tencent CodeBuddy CN (codebuddy-cn) OAuth provider with full support:
OAuth login (GET poll with state query param), token refresh, 15-model
catalog, /v2 inference endpoint, forced streaming, OpenAI-style reasoning,
and per-model capabilities. Renamed from codebuddy to codebuddy-cn to allow
a future codebuddy-ai variant.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-19 15:33:26 +07:00
decolua
7354c5e5f4 # v0.5.3 (2026-06-18)
## Fixes
- **Kiro**: honor thinking effort budgets
- **AG/Kiro/Xiaomi**: provider fixes
- **Combo/Fusion**: flatten tool history in panel calls to prevent 503
- **LLM selector**: show custom vision models in selector and model list
- **Image**: prevent compatible nodes from shadowing provider aliases
2026-06-18 17:36:08 +07:00
EdisonPVE
2ff11246ae fix(kiro): honor thinking effort budgets
Resolve the Kiro thinking budget from client intent (OpenAI reasoning_effort,
OpenAI Responses reasoning.effort, Claude output_config.effort, and Claude
thinking.budget_tokens) by reusing the shared thinkingUnified extractThinking
parser, then inject the resolved budget into the Kiro thinking system prefix.
Explicit none/off/disabled stops the prefix injection; synthetic -thinking
aliases keep the default budget.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 15:14:42 +07:00
decolua
3f9382dee4 Fix AG, Kiro, Xiaomi Provider 2026-06-18 14:58:00 +07:00
WARELIK
9ab14e7714 fix(combo/fusion): flatten tool history in panel calls to prevent 503
Panel models in the fusion strategy must answer in prose. When the request
carried tools or prior tool_calls/tool messages, agentic panel models kept
emitting tool_calls instead of prose, so extractPanelText() returned empty
and the engine fell into the 503 "All fusion panel models failed" branch.

Panel fan-out now strips tools/tool_choice and flattens tool turns into
assistant prose (instead of dropping them), so panels keep the context but
cannot loop on tools. The judge still receives the unmodified history.

Co-authored-by: warelik <warelik@WARELIK-MB.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 09:55:08 +07:00
Sutarto Jordan Chrisfivo
5e5e78d3e8 fix: show custom vision models in LLM selector and model list
Expose user-added imageToText custom models as vision-capable chat
models in the default LLM selector and /v1/models, map custom service
kinds to runtime capabilities, and keep typed filtering for
/v1/models/{kind}.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 09:13:27 +07:00
decolua
79df34cad7 fix: giảm spam 429 từ Claude OAuth usage endpoint
- claudeAutoPing: cache resetAt in-mem, bỏ qua poll usage cho tới gần reset
- ProviderLimits: throttle auto-refresh Claude 3 phút, nút bấm tay vẫn refresh ngay
- claude.js: 429 ở OAuth usage → cooldown 3 phút, fallback legacy (không ảnh hưởng chat)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 11:42:20 +07:00
decolua
c7d07448c5 fix(image): pin DNS-resolved IP to prevent SSRF via DNS rebinding (GHSA-cmhj-wh2f-9cgx)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 11:02:04 +07:00
fjia
7ae9fff663 fix(executors): strip params unsupported by provider/model
Add config-driven stripUnsupportedParams helper and use it in the default and github executors. Removes the deprecated temperature param for claude-opus-4 models (Anthropic 400) and consolidates github's scattered capability checks into one rule table.

Fixes #1748

Co-Authored-By: fjia <fjia@suntekcorps.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:34:53 +07:00
Daniil Schovkunov
87e5c1c6dd feat(combo): add Fusion strategy — parallel panel + judge synthesis
Adds Fusion as a third combo strategy alongside fallback/round-robin. A
fusion combo fans the prompt out to all member models in parallel, then a
configurable judge model synthesizes one final answer from the panel.

- handleFusionChat in open-sse/services/combo.js: quorum-grace collection
  caps the straggler penalty, anonymized sources prevent judge brand-bias,
  degrades to a direct answer on single survivor and 503 on total failure.
- chat.js dispatches strategy==="fusion" at both combo entry points.
- Combos dashboard: per-combo strategy Select replaces the round-robin
  toggle, fusion reveals a judge picker, plus a strategy/capacity explainer.
- tests/unit/combo-fusion.test.js covers fan-out, judge routing/default,
  quorum-grace straggler drop, single-survivor and total-failure degradation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:34:27 +07:00
decolua
37bfcc3719 open-sse agents.md 2026-06-17 10:11:39 +07:00
thienpv
706e6513c9 feat(kiro): headless API-key auth + direct Claude/Kiro route
Adds long-lived API-key (ksk_) authentication for Kiro/AWS CodeWhisperer
and a direct claude:kiro / kiro:claude translation route that avoids the
lossy OpenAI two-hop pivot.

- translator: claude-to-kiro request + kiro-to-claude response translators,
  registered on the exact source:target pair (direct route ahead of the
  OpenAI pivot in index.js). claude-to-kiro uses shared schema constants
  (ROLE/CLAUDE_BLOCK/DEFAULT_IMAGE_MIME) per app convention.
- auth: POST /api/oauth/kiro/api-key imports + validates a key via
  ListAvailableProfiles, persists authMethod="api_key" (no refresh token).
- executor: send tokentype: API_KEY header and try *.amazonaws.com hosts
  first for api-key creds; OAuth keeps kiro.dev first.
- fix: never inject the default placeholder profileArn for api-key auth
  (CodeWhisperer 403s an ARN not owned by the key's account).
- ui: API Key method in the Kiro connect modal; surface api-key accounts
  on the Quota Tracker and provider count.
- stream: env-overridable TTFT vs stall timeouts + Kiro keepalive frame.
- tests: claude-kiro-direct + kiro-profile-arn (11 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:01:30 +07:00
Khanh Le
db9ec3af61 fix(antigravity): strip optional from tool schemas before Gemini
Closes #1537, #1841

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 09:46:41 +07:00
fjia
411a589781 fix(claude-to-openai): handle OpenAI-format responses in non-streaming path
Some providers (e.g. xiaomi-tokenplan -claude models) return OpenAI-format
responses even when request was translated to Claude. Early-return now detects
choices[]. Also strip reasoning_content only when content is non-empty so
thinking models keep their only output.

Closes #1836

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 09:43:58 +07:00
decolua
d03f9fb823 Enhance configuration and model capabilities 2026-06-16 23:32:28 +07:00
decolua
b282f05549 Refactor 2026-06-15 18:18:04 +07:00
decolua
aba4c45da6 fix(translator): ESM-safe registry + tool-id pairing + responses max_tokens; add real-creds tests
- translator/index.js: replace require() with static side-effect imports (ESM-safe),
  lazy-init registry maps to survive circular import order
- openai-responses->openai: map max_output_tokens -> max_tokens (avoid leaking field upstream)
- gemini/antigravity -> openai: derive deterministic tool_call id from name so
  functionCall/functionResponse pair correctly (fixes provider tool-pairing 400s)
- add offline unit tests (finish-reason, usage, session-manager, ollama malformed args, const guard)
- add real-creds integration tests (provider-cases + all-formats matrix: 6 inbound formats x 4 scenarios)

Includes co-located provider registry refactor (pricing/capabilities/media providers) and sessionManager updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 11:38:43 +07:00
decolua
24a2d19bd7 refactor(app): RISKY pass R1-R3 — config-driven modal, cursor frame dedup, chunk helper
R1: merge AddOpenAICompatibleModal + AddAnthropicCompatibleModal → AddCompatibleModal (variant config-driven, ~180 dup removed, preserves per-variant useEffect behavior)
R3: extract readCursorFrame() helper — dedup protobuf frame header/decompress loop (JSON+SSE transforms, byte-identical)
R2: add chatChunkSse() helper, wire 7 cursor SSE scaffolds (byte-identical, cursor golden pass)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 21:54:35 +07:00
decolua
fbf973f2e7 refactor(app): DRY pass — split large files, extract shared utils
S1: delete page.new.js (1724L abandoned) + remove dead getAntigravityProjectId
S2: split large files by natural seams
  - usage.js → usage/{github,google,claude,codex,kiro,minimax,misc,shared}.js
  - media-providers page → components/{Embedding,Tts,Generic,Stt}ExampleCard.js
  - EndpointPageClient → endpointConstants.js + endpointPing.js + components/
  - tokenRefresh.js → tokenRefresh/{dedup,providers}.js
  - ProviderLimits/index.js: 16 pure fn + 9 constants → utils.js
  - oauth/providers.js: 7 pure helpers → providerHelpers.js
S3: shared utils
  - getModelKind(m, fallback) → shared/constants/models.js (replaces 20× m.kind||m.type)
  - getStatusVariant → shared/utils/connectionStatus.js (dedup ConnectionRow/ConnectionsCard)
  - sseChunk → open-sse/utils/sse.js (dedup grok-web/perplexity-web)
  - fetchWithTimeout → usage/shared.js (replace 4× AbortController pattern in google.js)
fix: enableObservability2 field name in requestDetailsRepo
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 19:31:09 +07:00
decolua
d3f61aac2f refactor(open-sse): translator DRY + schema enums, bug fixes, dead code cleanup
- Bug B1-B7: media UI m.kind||m.type, serviceKinds, gemini mediaPriority, schema kind, models/info lookup by kind
- Dead code D1-D6: safeParseJSON, drop PROVIDER_ENDPOINTS, orphan fetcher, GITHUB_CONFIG derive, getProviderConfig internal, legacy kiro file
- Translator concerns: toOpenAIUsage, toOpenAIFinish (gemini/kiro/ollama + fix kiro tool finish), thinking effort maps
- Reorg helpers/ → concerns/ (logic) + formats/ (per-format) + schema/ (pure enums: roles/blocks/finishReasons/defaults)
- Wire ~280 hardcoded role/block/finish/default literals to schema enums across 20+ files
- collapseTextParts + extractTextContent dedup
- Normalize translator fn names to openaiToXRequest / xToOpenAIResponse
- Golden tests lock behavior; 0 regression (byte-for-byte providers/alias, 26=26 known fails)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 18:49:38 +07:00
decolua
dd1e0f9bcc refactor(registry): B2 migrate to LiteLLM-style schema — unified models[] with kind field
- 71 registry files: flat `media.*Config.models` → `models[]` with `kind` field
- `media` wrapper removed → serviceKinds, *Config fields promoted top-level
- `type` field renamed to `kind` (llm/image/tts/stt/embedding/embedding/video/music)
- providers/index.js: PROVIDER_MEDIA now built from flat top-level media fields
- shared/constants/providers.js: buildProviderEntry reads flat top-level media fields
- route /v1/models: modelKind() uses kind||type; removed subConfig merge block
- models/info route: removed sub-config fallback lookup (all models in PROVIDER_MODELS)
- ttsProviders/index.js: synthesizeViaConfig reads tts models from PROVIDER_MODELS
- test-models route, helpers.js, validate route: kind||type compat
- Baselines: PROVIDERS 62/62 ✅, Alias 90/90 ✅

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 14:32:59 +07:00
decolua
e53ce79abb refactor(open-sse): B1 consolidate media endpoint URLs into registry
- image/embed/tts/search base URLs derive from media.*Config.baseUrl /
  searchViaChat.endpoint (single source); handlers read PROVIDER_MEDIA.
- ~18 hardcoded endpoints moved: bfl/fal/stability/runway/hf/gemini/
  cloudflare/recraft/sdwebui/comfyui/nanobanana image, voyage embed,
  gemini/openrouter tts, chatSearch endpoints.
- Byte-identical: PROVIDERS 62 + alias 90 baselines, image buildUrl outputs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 13:58:12 +07:00
decolua
bb9e9aa91f refactor(open-sse): registry consolidation + DRY media/oauth/adhoc cleanup
- Single-source registry: oauth clientId/tokenUrl, usage URLs, image/embed
  configs, search defaultModel, codex fixedPort, google token url derive.
- Remove 29 unused OmniRoute providers (registry 100→71); media intact.
- De-adhoc: codex literals → registry format/oauth flags; reasoningInject,
  image/embed openrouter headers + xai bodyFields config-driven.
- Add REGISTRY_TEMPLATE.js + expand PROVIDER_DEFAULTS/schema JSDoc.
- Baselines updated; PROVIDERS 62 + alias 90 byte-for-byte, golden snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 13:15:48 +07:00
decolua
9105dd0e25 refactor(open-sse): #11 — dedupe client-facing SSE_HEADERS_CORS
Gom block SSE headers + CORS lặp ở streamingHandler + responsesHandler
vào sseConstants.SSE_HEADERS_CORS. Codex format-routing giữ nguyên
(logic-driven theo kim chỉ nam DATA/LOGIC docs 07).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 22:06:59 +07:00
decolua
4da1d6dad4 refactor(open-sse): D1c — forceStream hardcode → PROVIDERS schema (#5)
chatCore providerRequiresStreaming: switch provider-name →
PROVIDERS[provider].forceStream. Thêm forceStream:true vào registry
openai/codex/commandcode. verify-providers allowlist added-fields
(forceStream/urlSuffix verified bằng golden + runtime test riêng).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 22:05:01 +07:00
decolua
ad2a3e5de3 refactor(open-sse): D1a/D1b — URL quirks → schema urlSuffix + clean debug logs
buildUrl: switch provider-name → config-driven. ?beta=true thành
urlSuffix per registry (claude/glm/kimi/minimax/minimax-cn/kimi-coding);
gemini path dùng format==="gemini"; accountId substitution giữ generic.
Xóa console.log('[DEBUG]') trong refreshCline.
Golden url-header 142 pass (byte-for-byte URL).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 22:00:57 +07:00
decolua
72ce515709 refactor(open-sse): dedupe Google OAuth client credentials (#4)
clientId/clientSecret của antigravity + gemini bị lặp 3 nơi
(registry, usage.js, src/lib/oauth). Gom vào shared.js
(ANTIGRAVITY_OAUTH_CLIENT, GOOGLE_OAUTH_CLIENT), các file spread vào.
Byte-for-byte: PROVIDERS/alias/oauth-url equal, golden 142 pass.
Thêm test guard nội dung + alias resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:53:14 +07:00
decolua
d4b95380b1 refactor(open-sse): usage.js dispatcher switch → USAGE_HANDLERS registry
Gộp switch 13 nhánh getUsageForProvider thành 1 registry object
(provider → handler), mỗi handler giữ nguyên signature/args qua ctx.
Behavior giữ nguyên (ollama vẫn chỉ nhận accessToken như cũ).
Thêm tests/unit/usage-dispatch.test.js guard dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:46:13 +07:00
decolua
6ee4555821 refactor(open-sse): DRY SSE primitives into utils/sseConstants.js
Gom SSE_DONE + SSE_HEADERS + SSE_HEADERS_NO_BUFFER vào 1 file không
phụ thuộc (tránh kéo usageDb vào executor). Áp cho kiro, cursor, qoder,
github, commandcode, perplexity-web, grok-web. Byte-for-byte verified
(headers/DONE giữ nguyên; biến thể no-buffer dùng const riêng).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:42:59 +07:00
decolua
0a8d92a6ba refactor(open-sse): #8 unify token refresh dispatch — 2 switch → 1 registry
- REFRESH_HANDLERS map (provider → handler) replaces two parallel switch blocks
- getAccessToken keeps gemini→Google + null default; refreshTokenByProvider keeps
  generic refreshAccessToken default (gemini intentionally not special-cased)
- Add token-refresh-dispatch.test.js guarding null-guards + defaults
- Existing xai/codex refresh tests still pass

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:32:52 +07:00
decolua
633b66dcb6 refactor(translator): P4 concern #5 buildUsage — apply to kiro/ollama/commandcode
- Replace 3 inline {prompt,completion,total} usage objects with buildUsage()
- Preserves ?? vs total fallback semantics (commandcode)
- Golden tests pass, identical output

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:27:22 +07:00
decolua
252bf56a9f refactor(translator): P4 concern #2 encodeDataUri — dedupe base64 data-uri building
- imageHelper.encodeDataUri(mime, base64) replaces 5 inline `data:${m};base64,${d}` templates
- Applied to gemini/claude/antigravity request + gemini response translators
- Golden tests pass, identical output

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:23:32 +07:00
decolua
4cc667253a refactor(translator): P4 concern #6 finishReasonMap — switch-by-format, default common
- concerns/finishReasonMap.js: toOpenAIFinish/fromOpenAIFinish, switch special formats, default passthrough
- Replace 3 inline switch maps (claude→oai, oai→claude, commandcode→oai)
- Golden translator tests pass, behavior identical

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:20:22 +07:00
decolua
d2b0960bf7 refactor(open-sse): P3§7 model defaults schema — centralize type/quotaFamily/strip/targetFormat
- Add providers/models/schema.js (MODEL_DEFAULTS + field resolvers)
- Accessors getModelTargetFormat/QuotaFamily/Strip use shared default resolvers
- getModelType keeps null contract unchanged; behavior verified equal
- No catalog forced into registry (models stay self-contained per docs decision)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:13:37 +07:00
decolua
5a042840fd refactor(open-sse): P3 provider registry — split into providers/registry/{id}.js
- 100 registry files: transport + models co-located per provider (Mongoose-style)
- providers/shared.js: shared Claude headers + OS/arch helpers (deduped)
- providers/models/helpers.js: withCodexReviewModels (kept dynamic)
- providers/index.js builds PROVIDERS + PROVIDER_MODELS = old API (content byte-for-byte)
- config/providers.js + providerModels.js → barrel re-export, keep accessors + runtime helpers
- Verified: PROVIDERS/MODELS/OAuth/alias byte-for-byte, golden translator tests pass, 0 new regression

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:08:37 +07:00
decolua
7134dd71db refactor(open-sse): P2 alias single-source — derive OAuth alias→id from OAUTH_ALIASES
- Export OAUTH_ALIASES as canonical id→alias source
- model.js derives 16 OAuth alias→id pairs instead of hardcoding (mmf kept out to preserve behavior)
- Add verify-alias.mjs byte-for-byte guard (133 tokens), all equal

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:48:11 +07:00
decolua
1432ac61d7 fix(open-sse): remove dead duplicate opencode provider entry
Two `opencode` keys existed; the first (localhost:4096) was silently overridden
by the later one (opencode.ai, noAuth). Drop the dead entry. Resolved PROVIDERS
output unchanged (verified byte-for-byte).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:41:41 +07:00
decolua
bb597cbced refactor(open-sse): source mimo-free/opencode base URL from PROVIDERS
CHAT_URL and opencode buildUrl base now read from PROVIDERS instead of repeating
the literal. Values identical; providers byte-for-byte + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:40:43 +07:00
decolua
64182c0484 refactor(open-sse): merge beta-url case + single-source refresh URLs (D)
buildUrl: fold kimi-coding into the shared ?beta=true case. refreshCline/
refreshKimiCoding now read URL (and kimi-coding clientId) from PROVIDERS instead
of hardcoded strings. Extend verify-oauth-urls with refresh/clientId snapshot;
URLs byte-for-byte equal, golden + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:33:38 +07:00
decolua
22f6c42738 refactor(open-sse): single-source OAuth token URLs via PROVIDERS (C2)
OAUTH_ENDPOINTS.{openai,anthropic,iflow}.token now reference PROVIDERS.*.tokenUrl
(values identical) so each backend token URL is declared once. qwen left as-is
(its appConstants/PROVIDERS values intentionally differ). Add verify-oauth-urls
script; URLs byte-for-byte equal, gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 20:22:36 +07:00
decolua
6597b81e5e refactor(open-sse): add reasoningDelta helper, dedup thinking deltas (B4)
Centralize the reasoning_content delta shape (optional assistant role) used by
claude/gemini/kiro/codex/commandcode response translators. Keeps the cross-format
convention consistent for future translators. Output byte-for-byte identical;
golden + gate clean. Ollama left as-is (mutates existing delta object).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 18:21:46 +07:00
decolua
997860aa1f refactor(open-sse): dedup fallback tool_call id helper (B3)
Add fallbackToolCallId() and apply to kiro/ollama/openai-responses response
translators (identical id shape). Leave commandcode (different order) and
request-side gemini/antigravity (random suffix) untouched. Golden + gate clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 18:12:40 +07:00
decolua
f4c39042a0 refactor(open-sse): dedup format default in PROVIDERS via resolver (C1)
Wrap PROVIDERS in defineProviders() that appends format:"openai" when omitted,
removing 72 repeated `format:"openai"` lines. Output stays byte-for-byte
identical (verified by tests/__baseline__/verify-providers.mjs deep-equal
against snapshot). No runtime fields added; consumers unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:57:51 +07:00
decolua
3a26d5fb40 refactor(open-sse): remove dead buildProviderUrl/Headers path (A1)
These translate-path builders had no runtime consumers: the translator route
uses executor.buildUrl/buildHeaders, and the barrel re-exports were unused.
Removing them eliminates the parallel URL/header build path (single source of
truth = executors). Drop their private helpers and the now-unused clineAuth
import. Golden executor snapshots + gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:34:39 +07:00
decolua
39278e9613 refactor(open-sse): extract buildUsage helper, dedup token-details (B2)
Add helpers/usageHelper.js for conditional prompt/completion token details.
Apply to gemini/codex/claude response translators; keep each provider's token
math intact. No behavior change; golden + gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:18:15 +07:00
decolua
34ea763d80 refactor(open-sse): add provider/model schema skeleton (C-prep)
New unwired modules providers/schema.js + models/schema.js with PROVIDER_DEFAULTS,
ENDPOINT_DEFAULTS, resolveProvider, MODEL_DEFAULTS, resolveModel (3-tier merge).
Foundation for upcoming registry tasks; no runtime wiring yet.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:05:42 +07:00
decolua
17202f7111 refactor(open-sse): extract chunkBuilder, dedup chat.completion.chunk (B1)
Add helpers/chunkBuilder.js; apply to claude/gemini/kiro/ollama/commandcode/
openai-responses response translators. Caller supplies id/created/model so each
keeps exact id-generation + usage semantics. Extend golden response stream to
openai-responses (codex). No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 17:05:42 +07:00
decolua
b87cf0c96a refactor(open-sse): extract safeParseJSON util, dedup tryParseJSON (B5)
Consolidate two tryParseJSON variants into helpers/jsonUtil.js with explicit
fallback param. Preserve exact per-call semantics: openai-to-claude passthrough
(fallback=str), geminiHelper null. geminiHelper keeps tryParseJSON re-export.
No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:45:10 +07:00
decolua
87fe069e9e refactor(open-sse): remove reverse coupling open-sse -> src (E2)
Move clineAuth into open-sse/shared (src re-exports back). Add standalone
open-sse/shared/machineId for codex session hashing (no @/lib/dataDir).
sttCore receives sttConfig via param instead of importing AI_PROVIDERS.
No behavior change; gate: no regression (26 known-fails unchanged).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:35:07 +07:00
decolua
515e2cc430 v0.4.77 (2026-06-13)
Features
Vercel AI Gateway: support embeddings, images and credit usage (#1183)
Add MiMo Free no-auth provider (#1789)
Vertex: support ADC authorized_user credential
Cowork: re-enable Claude Cowork with preset-only stdio MCP
Codex: bulk add accounts via JSON (#1719)
Kiro: enable multi-endpoint failover for GenerateAssistantResponse (#1722)
Fixes
Security: re-auth on DB export/import + SSRF guard on web fetch
Auth: real client IP rate-limiting + remote default-password guard
Cerebras/Mistral: strip unsupported client_metadata from downstream requests (#1742)
SiliconFlow: update baseUrl .cn → .com + curate verified model list (#1760)
Gemini-to-OpenAI: route unsigned thought parts to reasoning_content (#1752)
Claude-to-OpenAI: strip Anthropic billing header from system prompt (#1765)
Anthropic-compatible: send Bearer auth for third-party gateways (#1795)
Usage-stats: avoid partial stats on initial SSE race (#1767)
Proxy: use export default in proxy.js for Next.js 16 middleware detection
Claude passthrough: add body normalization
GitHub Copilot: refresh missing/expired token on models discovery (#1727) + add mappable gpt-5-mini/gpt-5.4-nano slots for Copilot MITM (#1653)
Kiro: auto-resolve profileArn to prevent 403 on IDC login, enhance profile ARN resolution, update endpoint to runtime.us-east-1.kiro.dev (#1713)
Tunnel: detect system-installed Tailscale via dual-socket probe (#1723) + non-blocking probes to prevent UI freeze
CommandCode: force stream=true in transformRequest (#1706)
Qoder: increase timeouts for reasoning models and improve stream handling
Dashboard: show provider node name instead of connection name in topology (#1770) + show explicit kind="llm" combos on combos page (#1684)
Docs
README: add Indonesian 9Router tutorial video (#1709)
2026-06-13 15:41:13 +07:00
saurabh321gupta
d652300e9e fix(cerebras,mistral): strip unsupported client_metadata from downstream requests
Cerebras returns 400 (wrong_api_format) and Mistral returns 422
(extra_forbidden) when the forwarded body contains client_metadata.
Remove it for these two providers before sending downstream.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 11:43:12 +07:00
Phuc Le
e6bac77696 fix(siliconflow): update baseUrl .cn -> .com + curate verified model list
Switch all siliconflow endpoints from api.siliconflow.cn to .com (chat,
validate, test, models) — the .cn host rejected valid .com-issued keys.
Replace the model list with 13 strong models verified live against the API.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 11:37:36 +07:00
Ngô Tấn Tài
b33cbb0280 feat(vercel-ai-gateway): support embeddings, images and credit usage
Extend Vercel AI Gateway beyond chat: add OpenAI-compatible embeddings
and image generation endpoints, credit balance fetch on the usage
dashboard, retry on 429, and models catalog fetcher.

Thinking/reasoning mapping is omitted pending a project-wide refactor.

Co-authored-by: Ngô Tấn Tài <tantai@newnol.io.vn>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:54:51 +07:00
Giang Truong Vu
d9b030011f fix(gemini-to-openai): route unsigned thought parts to reasoning_content
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:34:42 +07:00
Fadjrir Herlambang
b40e96d0ef feat(provider): add MiMo Free no-auth provider
Bootstrap → JWT → chat flow with auto-retry. Inject the MiMoCode
system marker required to pass the upstream 403 anti-abuse gate,
derive JWT expiry from the exp claim, and use a stable per-machine
fingerprint as the bootstrap client.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:14:21 +07:00
weimaozhen
0aaa5ab3c2 fix(claude-to-openai): strip Anthropic billing header from system prompt
Remove dynamic x-anthropic-billing-header lines from Claude system prompts
when translating to OpenAI format to keep prompt prefixes stable and improve
prompt cache hits.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:05:12 +07:00
Duong Thai Hoa Tong
9406bd1806 feat(vertex): support ADC authorized_user credential
Accept Google Application Default Credentials (authorized_user) in the
Vertex apiKey field as an alternative to Service Account JSON, for orgs
that block SA key creation. Refreshes a Bearer token via the existing
refreshGoogleToken flow and requires a project_id (quota_project_id or
providerSpecificData.projectId). SA JSON and raw key flows unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 09:55:29 +07:00
hodtien
b977bf7414 fix(anthropic-compatible): send Bearer auth for third-party gateways
Third-party Anthropic-compatible gateways that require Authorization: Bearer
(in addition to x-api-key) returned 401 missing_api_key on the forward path.
For non-official upstreams, also send Bearer <apiKey> alongside x-api-key.
Official api.anthropic.com behavior is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 09:45:59 +07:00
decolua
b309261166 enhance Kiro profile ARN resolution 2026-06-13 09:28:55 +07:00
decolua
4443903900 fix: add normalization for Claude passthrough bodies 2026-06-08 15:37:01 +07:00
decolua
f8c59227f6 fix(kiro): auto-resolve profileArn to prevent 403 on IDC login
AWS OIDC IDC/Builder-ID tokens omit profileArn, so CodeWhisperer calls
return 403 "User is not authorized". Resolve it natively via the
ListAvailableProfiles API instead of reading Kiro IDE profile.json.

- providers.js: add fetchKiroProfileArn() and resolve on poll (new logins)
- tokenRefresh.js: backfill profileArn on refresh so existing IDC
  connections self-heal without re-login

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 09:45:58 +07:00
thienpv
c24efe80f0 feat(kiro): enable multi-endpoint failover for GenerateAssistantResponse
Wire the Kiro provider into BaseExecutor baseUrls fallback so a request
advances across the three CodeWhisperer surfaces (runtime kiro.dev,
codewhisperer, q) on 429 and network/5xx errors.

- providers.js: add baseUrls[] (newest endpoint first); keep baseUrl as default
- kiro.js: replace the hand-rolled single-endpoint loop with super.execute()
  delegation plus EventStream to SSE transform on success

Note: the three hosts are alternate DNS surfaces of one regional service. AWS
throttles per authenticated identity (token plus profileArn), not per hostname,
so this is edge-level failover, not extra 429 quota.

Co-authored-by: thienpv <pvtcwd@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 09:44:53 +07:00
Mr. Nasıl
c5815ad3f0 fix(commandcode): force stream=true in transformRequest
CommandCode upstream only speaks NDJSON streaming; the executor always
wraps it as OpenAI SSE. Force body.stream=true so non-stream client
requests still produce a parseable upstream stream (router aggregates
SSE→JSON downstream).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 09:21:52 +07:00
decolua
137a25e9ac fix(qoder): increase timeouts for reasoning models and improve stream handling 2026-06-08 09:17:33 +07:00
decolua
9caea88528 fix(codex): harden streaming timeouts + Responses terminal events
Raise stall/connect timeouts to 60s (configurable per-provider), accept
codex response.done, and always emit a terminal response.failed + [DONE]
for Responses passthrough when a stream closes, stalls, or aborts before
a terminal event — preventing codex clients from hanging.

Co-authored-by: jonathanli12 <jonathanli12@users.noreply.github.com>
Co-authored-by: rifuki <rifuki@users.noreply.github.com>
Co-authored-by: nguyenha935 <nguyenha935@users.noreply.github.com>
Co-authored-by: trananhtung <trananhtung@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 16:07:43 +07:00
Claude Code
c785051360 fix(claude): forced tool_choice 400 on cc/ OAuth route
convertOpenAIToolChoice mapped {type:"function"} verbatim and cloakClaudeTools
left tool_choice.name unsuffixed, both rejected by Claude on the cc/ path.
Map forced-function to {type:"tool",name}, allowlist Claude-valid types, and
suffix tool_choice.name when it targets a renamed client tool.

Fixes #1592

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:54:01 +07:00
arden1601
047792205f feat(caveman): add wenyan classical Chinese levels and sync upstream prompts
Add wenyan-lite/wenyan/wenyan-ultra levels for max token compression,
sync SHARED_EXAMPLES/AUTO_CLARITY/PERSISTENCE across all levels, and
expose 3 wenyan buttons in endpoint settings UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:35:08 +07:00
Farhan Usman
4fc02e67e5 fix(minimax): echo reasoning_content on follow-up turns to avoid 400
MiniMax requires reasoning_content echoed back on assistant messages in
multi-turn/tool-call conversations. Add minimax and minimax-cn to
PROVIDER_RULES (scope all), same fix as DeepSeek (#1543).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:25:12 +07:00
Simon Shi
8ad95542da fix(kiro): handle 400 on tool-bearing history without client tools
Kiro requires a non-empty currentMessage tools array whenever history
references any tool use, else returns "Improperly formed request" (400).
Clients trip this by omitting tools on follow-ups after client-side
compaction.

- flattenToolInteractions(): no client tools -> collapse tool_use/result
  to text so the "tools required" rule never fires
- reconcileOrphanedToolResults(): client tools -> salvage orphaned
  results as text, keep matched ones, guard co-located tools array
- safeJSONParse(): guard tool-call argument parsing against bad JSON
- merge consecutive user userInputMessageContext; null-guard
  currentMessage for assistant-only input

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:23:47 +07:00
Giao Ho
0850f0a470 fix(mitm): Kiro binary EventStream crash + add models & TTS tool filtering
- server.js: isBinaryData() skips binary AWS EventStream bodies (fix JSON parse crash)
- kiro.js: isBinaryEventStream detection + migrate to pipeTransformedEventStream pipeline
- base.js: add pipeTransformedSSE / pipeTransformedEventStream helpers
- chatCore.js: filter tool messages + tools for TTS models via getModelType()
- providerModels.js: add getModelType()
- cliTools.js: add gpt-5-mini (Copilot), glm-5 & minimax-m2.5 (Kiro)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 11:31:52 +07:00
Kevin Le
c233c7c8fc fix(codex): durable OAuth refresh lifecycle
Add shared OAuth credential lifecycle manager with provider-aware refresh
decisions. Implement CodexExecutor.refreshCredentials so 401/403 retry
refresh works for Codex, track lastRefreshAt and refresh before the
upstream stale-token window, preserve omitted idToken, and add
per-connection single-flight refresh to avoid refresh-token rotation races.

Merged from PR #1664.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 11:04:36 +07:00
therunnas
61d546627e fix(qoder): allow qmodel_latest model key
- Add qmodel_latest to QODER_MODEL_MAP
- Expose qmodel_latest in static Qoder provider catalog (qd)
- Generalize executor comment so model set does not go stale
- Add unit coverage for the new model key + catalog

Closes #1638

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:44:37 +07:00
AbdoKnbGit
e6c09aad15 feat(antigravity): add gemini-3.5-flash-extra-low (Low) model
- Add gemini-3.5-flash-extra-low across CLI menu, provider models, usage, pricing
- Add MITM synonyms (high/medium/extra-low) and split pattern so Low no longer falls through to Medium
- Strip models/ prefix in getMappedModel for AG public name normalization

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:42:47 +07:00
Mr_NoboDy
40cfa63eb8 feat(xiaomi-tokenplan): add Claude-native MiMo V2.5 Pro alias via dedicated executor
Add mimo-v2.5-pro-claude alias routing to the Xiaomi TokenPlan Anthropic-compatible
/anthropic/v1/messages endpoint. Logic lives in a dedicated XiaomiTokenplanExecutor
(config-driven via targetFormat) instead of the shared DefaultExecutor.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:36:03 +07:00
zhangweihong
12c97ad46f feat(qoder): fetch latest model + nút import model trên dashboard
Merge PR #1642 (decolua/9router) — chỉ lấy code + i18n, bỏ test/docs/package.json.

- qoder.js: bỏ guard QODER_MODEL_MAP cứng, resolve model_config qua dynamic API (hỗ trợ qmodel_latest không cần sửa code)
- dashboard page: thêm nút "Fetch Qoder Models" tự import model list vào aliases
- i18n zh-CN: thêm key cho nút fetch

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:22:03 +07:00
decolua
8671468360 Merge PR #1628: fix(model-test) route image and STT probes to their real endpoints
Route image model tests to /api/v1/images/generations and STT to
/api/v1/audio/transcriptions instead of forcing all non-embedding
models through chat completions. Adds kind-aware pingModelByKind,
hf->huggingface alias, and silent WAV sample for STT reachability.

Scoped to dashboard/internal model testing only; runtime inference
routing is unchanged.

Author: yicone <yicone@gmail.com>
Closes #1628
2026-06-06 10:03:32 +07:00
hodtien
41f94ce8c8 fix(minimax): Bổ sung MiniMax-M3 + cập nhật Quota Tracker coding/CN
Squash-merge PR #1631 (decolua/9router) — chỉ lấy file code + test, bỏ docs.

- feat(minimax): add MiniMax-M3 to intl + cn provider models (targetFormat claude)
- feat(minimax): add MiniMax-M3 pricing entry
- fix(minimax): translate Claude body khi content=null (M3 thinking-only)
- fix(minimax): hiển thị quota M-series bucket "general"/"MiniMax-M*" + percent-only
- test: minimax usage / model registration / pricing

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 10:01:05 +07:00
yicone
e414975d0c Fix model test routing for image providers 2026-06-02 21:14:36 +08:00
decolua
e9ae21a723 # v0.4.66 (2026-05-29)
## Features
- Add Qoder provider: device-flow OAuth, COSY signing, WAF-bypass body encoding, live model catalog, dashboard quota tracker, 11 models (#1372)
- Add new models: Claude Opus 4.8 (Claude Code), GPT 5.4 Mini (Codex)

## Fixes
- DeepSeek thinking mode: echo `reasoning_content` back on follow-up/tool-call turns so OpenCode-free and custom providers no longer 400 with "reasoning_content must be passed back" (#1543)
- Reasoning injector: match deepseek/kimi model ids case-insensitively (covers custom providers using capitalized model names)
- OpenCode suggested-models: include free models without the `-free` suffix, e.g. `big-pickle` (#1535)

## Improvements
- Codex: trim sunset models, keep gpt-5.5 / gpt-5.4 / gpt-5.3-codex family, add gpt-5.4-mini
- volcengine-ark: refresh model list (add DeepSeek-V4-Flash/Pro, drop EOL entries)
- Lower stream stall timeout 35s → 30s for faster hang detection
2026-05-29 17:48:01 +07:00
Simon Shi
4baaa5c7aa Feat : qoder provider 2026-05-29 17:36:27 +07:00
Simon Shi
53c0eefa00 chore(qoder): rename display label from "Qoder AI" to "Qoder" 2026-05-29 17:36:27 +07:00
Simon Shi
af7f6b1de2 feat(qoder): show in Quota Tracker dashboard
Wire Qoder credits into the Quota Tracker card grid:

- Add `qoder` to USAGE_SUPPORTED_PROVIDERS so the connection passes the
  isUsageEligible filter at /api/providers/client and shows up in
  providerOptions on the dashboard.
- Reshape getQoderUsage so quota records (user, organization) live under
  `quotas` and scalar metadata (totalUsagePercentage, isQuotaExceeded,
  expiresAt) are siblings — the parser used to walk Object.entries(quotas)
  and would have rendered `totalUsagePercentage: 0.42` as a "0/0" row.
- Surface Qoder's expiresAt as resetAt on each quota record so the card
  shows when credits reset.
- Add a parser branch in ProviderLimits/utils.js: rename internal keys
  (user → "Personal", organization → "Organization"), drop empty org
  buckets so personal accounts don't render a misleading "0/0 Organization"
  row, and forward remaining/unit so the QuotaProgressBar can use them.
- Add Qoder's brand color (#EC4899) to ProviderLimitCard's color map.

42 tests still pass; build clean.
2026-05-29 17:36:27 +07:00
Simon Shi
935462ce8f test(qoder): add regression coverage for review-fix changes
Adds 18 new tests covering the bugs fixed in the previous commit so they
can't silently regress:

- parseExpiry (7 tests): numeric ms-epoch input, numeric strings handled
  before Date.parse so "1700000000" doesn't get year-interpreted, RFC3339
  strings, expires_in:0 honored as already-expired, 30-day fallback only
  when both inputs are missing/invalid

- normalizeMessages (4 tests): system hoisting, multipart text flatten,
  multiple system joining, empty input

- wrapQoderSSE (6 tests): the fixed cases — trailing partial line drained
  in flush(), no chunks forwarded after [DONE], embedded newlines stripped
  from inner body, error envelope produces error chunk + [DONE], non-ok
  responses returned unchanged

- expose parseExpiry from auth.js, expose normalizeMessages/wrapQoderSSE
  via __test__ from the executor (internals only — not part of the public
  API). Marked with comment so the surface is intentional.

42 tests total (24 original + 18 new). Build still clean.
2026-05-29 17:36:27 +07:00
Simon Shi
620b59ca0b fix(qoder): address review findings
Correctness:
- testUtils: drop checkExpiry so the userinfo URL probe actually runs (revoked
  tokens used to look "active" until local 30-day expiry passed)
- auth.parseExpiry: handle numeric expiresAt, swap parseInt before Date.parse
  so "2026" doesn't get interpreted as year-2026, treat expires_in:0 as
  already-expired instead of fabricating a 30-day default
- providers.mapTokens: synthesize email from userId when fetchUserInfo fails
  so OAuth dedup works (re-logins no longer accumulate "Account N" rows)

SSE wrapper:
- wrapQoderSSE: add !doneEmitted guard on success branch (chunks could leak
  past [DONE] when an error envelope shared a TCP packet with a valid one)
- flush(): finalize TextDecoder + drain trailing buffer so the chunk carrying
  finish_reason is delivered when upstream closes without a final \n
- sanitize literal \n inside inner OpenAI body so SSE framing stays intact

Robustness:
- executor: wrap buildCosyHeaders in try/catch so a missing accessToken
  returns 401 (re-auth) instead of bubbling as 500
- executor: short-circuit on missing accessToken before signing
- executor: plumb proxyOptions/signal through buildQoderRequestBody so
  proxy-only networks can fetch the model_config catalog
- qoderModels: dedupe concurrent first-time misses with an in-flight Promise
  map (parallel chat windows now do 1 upstream fetch instead of N)
- qoderModels: check signal.aborted before addEventListener so a pre-aborted
  parent signal cancels the inner fetch immediately
- auth: AbortController + 15s timeout on pollDeviceToken / fetchUserInfo to
  prevent hung sockets when openapi.qoder.sh stalls mid-response

UX:
- OAuthModal: derive polling deadline from device-code expires_in (qoder
  publishes 300s; the previous fixed 120s caused timeouts when users took
  more than 2 minutes on the consent page)

Cleanup:
- delete src/lib/oauth/services/qoder.js — referenced removed config fields
  (clientId/clientSecret/tokenUrl/authorizeUrl) and was re-exported from
  services/index.js, so any future caller would TypeError on first use
2026-05-29 17:36:27 +07:00
Simon Shi
a6fd84691b feat(qoder): port Kiro-style provider integration with COSY signing
Replaces the Qoder placeholder with a real free-tier provider:

- Device-flow OAuth: PKCE + nonce generated locally, user authorizes at
  qoder.com/device/selectAccounts, poll openapi.qoder.sh until token
- COSY signing (RSA-1024 + AES-128-CBC + MD5) for chat / model-list
- WAF-bypass body encoding (custom-alphabet base64 + thirds rearrange)
- Live model_config catalog from /algo/api/v2/model/list, cached 1h
- 11 models registered (auto/ultimate/performance/efficient/lite +
  6 frontier *model ids)
- Usage fetcher for openapi.qoder.sh/api/v2/quota/usage
- Dashboard live-models resolver, provider test, OAuth modal hookup
- 24 unit tests covering encoder, PKCE, COSY headers, sigPath stripping
2026-05-29 17:36:27 +07:00
decolua
468c61b2ac Added new models for Claude Opus 4.8 and GPT 5.4 Mini.
Disabled Cowork
2026-05-29 17:36:27 +07:00
Delcado
88224b80ca
fix: never route GitHub Copilot Gemini/Claude models to /responses (#1062) (#1536)
GitHub Copilot's /responses endpoint only serves OpenAI (gpt/codex)
models. gemini-3.1-pro-preview was failing on /chat/completions with a
"not supported" error, getting cached as a codex model, then escalated
to /responses where it 400s with "does not support Responses API".

Add GithubExecutor.supportsResponsesEndpoint() and gate both the cached
/responses route and the 400-fallback on it, so Gemini/Claude always
stay on /chat/completions and the real upstream error surfaces.

Adds tests/unit/github-responses-routing.test.js (5 tests).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 15:40:42 +07:00
decolua
9742074b38 # v0.4.63 (2026-05-26)
## Fixes
- proxyFetch: restore missing `Readable` import causing runtime `ReferenceError` in DNS-bypass fetch path

## Improvements
- Lower stream stall timeout from 60s → 35s for faster hang detection
2026-05-26 23:16:21 +07:00
decolua
146310a3a3 Fix Bug 2026-05-26 23:09:19 +07:00
decolua
ac2fee7305 # v0.4.62 (2026-05-26)
## Fixes
- Codex: auto-retry when upstream drops mid-stream (no more hangs)
- Codex: fix random 400/404 errors, tool-calling failures, and unstable prompt cache
- MITM: support Antigravity 2.x
- Sanitize Read tool args to prevent retry loops from non-Anthropic models (#1144)
- Implement json_schema fallback for OpenAI-compatible providers without native Structured Output (#1343)
- Strip empty Read pages argument in OpenAI-to-Claude translator (#1354)
- Forward Gemini output dimensions for embeddings (#1366)
- Resolve setState-in-effect errors in dashboard components (#1362)
- Gemini CLI: reuse stored OAuth project IDs for quota checks and show clearer setup guidance when the project is missing (#1271, #1428)
2026-05-26 13:15:59 +07:00
decolua
0065bbbdfd # v0.4.62 (2026-05-26)
## Fixes
- Codex: auto-retry when upstream drops mid-stream (no more hangs)
- Codex: fix random 400/404 errors, tool-calling failures, and unstable prompt cache
- MITM: support Antigravity 2.x (updated IDE version detection and DNS/cert flow)
- Sanitize Read tool args to prevent retry loops from non-Anthropic models (#1144)
- Implement json_schema fallback for OpenAI-compatible providers without native Structured Output (#1343)
- Strip empty Read pages argument in OpenAI-to-Claude translator (#1354)
- Forward Gemini output dimensions for embeddings (#1366)
- Resolve setState-in-effect errors in dashboard components (#1362)
- Gemini CLI: reuse stored OAuth project IDs for quota checks and show clearer setup guidance when the project is missing (#1271, #1428)
2026-05-26 12:46:30 +07:00
mustafabozkaya
f3176b4b23 fix: implement json_schema fallback for OpenAI-compatible providers (#1343)
When json_schema response_format is sent to models that do not natively
support Structured Output (e.g. DeepSeek/Ollama/local LLMs via
openai-compatible-* providers), they often return empty or malformed
content.

Detect response_format.type === "json_schema", inject the schema into the
system prompt, and downgrade response_format to json_object so Structured
Output works transparently across openai-compatible providers.

Gated to provider.startsWith("openai-compatible-") so providers with
native Structured Output support are not downgraded.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 11:35:39 +07:00
decolua
a648a42bdb Fix codex 2026-05-26 11:35:39 +07:00
decolua
b876e0225a Refactor Tunnel 2026-05-26 11:35:39 +07:00
GodrezJr2
96a9a2b36d
fix: sanitize Read tool args to prevent retry loops from non-Anthropic models (#1144)
* fix: sanitize Read tool args to prevent retry loops from non-Anthropic models

* fix: sanitize invalid Read pages from tool args

Non-Anthropic models sometimes emit optional Read args like pages: "" for
non-PDF files, which Claude Code rejects before the tool runs. Drop invalid
pages values, keep valid PDF page ranges, and coerce numeric string bounds
before clamping limit/offset.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:33:38 +07:00
Delcado
dcc46f2eee
Reuse Gemini CLI project ID for usage (#1428) 2026-05-26 11:23:47 +07:00
Hamsa_M
315dcaa37a
fix: strip empty Read pages argument in OpenAI-to-Claude translator (#1354)
Some OpenAI-compatible providers emit optional string tool parameters
as empty strings (e.g. pages: "") instead of omitting them. Claude
Code rejects pages: "" as invalid, breaking the Read tool for
non-PDF files routed through 9router.

Add sanitizeToolArguments() that parses tool-call arguments and
removes known optional empty-string fields before emitting
input_json_delta back to Claude format. Currently handles the
Read tool pages field specifically.

Includes regression test.

Fixes #1278

Co-authored-by: JoJo <noreply@github.com>
2026-05-23 09:27:13 +07:00
YourAnsh
2604b46847
fix (#1361)
Co-authored-by: Ansh7473 <Ansh7473@users.noreply.github.com>
2026-05-23 09:26:10 +07:00
nguyenha935
7bc97eae7b
fix(embeddings): forward Gemini output dimensions (#1366)
Co-authored-by: GoClaw Operator <operator@goclaw>
2026-05-23 09:23:26 +07:00
decolua
6b0dc09239 Merge PR #1300: tailscale Windows fix, quota pagination, SSE abort handling
- fix(tunnel): cross-platform tailscale probes without shell redirection
- feat(usage): paginate provider limits with page size controls
- feat(providers): stop control for one-by-one connection testing
- fix(sse): close stream gracefully on abort/disconnect instead of pipe errors
- ui(quota): simplify header, always show pagination in one row

Co-authored-by: philau2512 <dplau25122002@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 12:15:07 +07:00
Muhammad Mugni Hadi
d976f4cc87 feat(xai): add xAI Grok provider with OAuth + API key auth + image
Adapted from PR #1286 (mugnimaestra/feat/xai-grok-provider) to match
existing app architecture. Includes:

- OAuth 2.0 with PKCE on loopback port 56121 (Grok Build)
- API key auth path (console.x.ai)
- Token refresh wiring (open-sse + sse tokenRefresh)
- Dashboard OAuth modal with fixed-port flow + manual code fallback
- Provider registry entries (OAuth + API key)
- xAI image generation via OpenAI-compatible adapter
  (grok-2-image-1212 model, no size/quality/style params)

Excludes (intentionally, to match app patterns):
- Custom xAI Responses executor (DefaultExecutor handles /chat/completions)
- xAI-specific translators (app uses OpenAI as intermediate format)
- Image edits (not supported by current imageGenerationCore)
- Video endpoints (app has no video subsystem yet)
- CLI xai-login command

Refs decolua#1286

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 11:33:18 +07:00
Noé Rivera
e3cab135ef
fix: decode Composer cursor thinking output (#1310) 2026-05-21 09:52:30 +07:00
decolua
613a0a819a # v0.4.55 (2026-05-18)
## Features
- Xiaomi MiMo Token Plan: region selector (Singapore / China / Europe) — keys are cluster-specific
- Antigravity: risk confirmation dialog before first connection
- Gemini CLI: surface upstream retry delay on 429 errors

## Fixes
- MITM: cannot kill process on macOS under sudo (lsof not found in PATH)
- Stream: false-positive stall timeout on Claude reasoning / Kiro responses
- Tunnel: cannot re-enable after disable (stuck state)
- Tunnel: cloudflared error messages now include log tail for easier debugging
- Language switcher: applies selected locale immediately on close (#1234)
- Antigravity OAuth: metadata now matches the official client

## Improvements
- Gemini CLI: bump engine to 0.34.0
- Re-hide `qwen` (OAuth EOL) and `iflow` (not ready) providers
2026-05-18 16:26:35 +07:00
NoxzRCW
3e52af35e2 feat(gemini-cli): wrap CloudCode payload and surface 429 retryDelay
- Send { project, model, request } envelope expected by Cloud Code Assist
- Parse google.rpc.RetryInfo from 429 responses to expose retry hint

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 15:23:38 +07:00
NoxzRCW
eaf770a28e chore(gemini-cli): bump version to 0.34.0 and refine user-agent
- GEMINI_CLI_VERSION 0.31.0 -> 0.34.0
- UA now appends `terminal` suffix and maps ia32 -> x86

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 15:23:38 +07:00
Z User
8daa953ef6 fix(oauth): align antigravity OAuth metadata with official client headers
Fixes #1226

The Antigravity OAuth flow sent inconsistent client metadata between
the token acquisition phase and the API usage phase. String enum values
(IDE_UNSPECIFIED, PLATFORM_UNSPECIFIED) were used during OAuth token
exchange + loadCodeAssist + onboardUser, while numeric enums (ideType: 9,
platform: <computed>, pluginType: 2) were used in runtime API calls.
Google detected this fingerprint mismatch and blocked 9router accounts.

Replace all string enum occurrences with the correct numeric values:

- src/lib/oauth/constants/oauth.js: loadCodeAssistClientMetadata now
  uses getOAuthPlatformEnum() for platform and numeric 9/2 for
  ideType/pluginType, matching getOAuthClientMetadata()
- src/lib/oauth/services/antigravity.js: getMetadata() now delegates
  to getOAuthClientMetadata() instead of returning hardcoded strings
- src/lib/oauth/providers.js: postExchange metadata now uses
  getOAuthClientMetadata() instead of inline string enums
- open-sse/services/usage.js: getGeminiSubscriptionInfo body now uses
  CLIENT_METADATA (already imported from appConstants.js) instead of
  inline string enums
2026-05-18 15:23:37 +07:00
Muhammad Zakir Ramadhan
94960c6cf5
fix: enhance stall detection in stream handling for improved disconne… (#1243)
* fix: enhance stall detection in stream handling for improved disconnect management

* fix: improve stall detection handling in pipeWithDisconnect to prevent stale aborts
2026-05-18 12:00:33 +07:00
decolua
9abbb8ad9b # v0.4.52 (2026-05-17)
## Features
- Add Vercel AI Gateway provider support (#1183)
- rtk: Kiro format tool result compression — handle conversationState.history & currentMessage, preserve error results, ~13.6% savings (#1194)

## Fixes
- openclaw: normalize agent.model object form `{primary, fallbacks}` before .startsWith → fix TypeError & 'not configured' status (#1216)
- Usage Details pagination: stay inside mobile viewport <640px (#1218)
- Fix test model error
- Fix MIMO provider in Codex
- Disable log file creation when using MITM AG
2026-05-17 16:37:26 +07:00
Ngô Tấn Tài
9326589452
Add Vercel AI Gateway provider support (#1183) 2026-05-17 15:16:25 +07:00
Zanuar Tri Romadon
e03b28138a
feat(rtk): add Kiro format support for tool result compression (#1194)
- Add compressKiroFormat() to handle conversationState.history and currentMessage
- Compress toolResults[].content[].text in Kiro's AWS CodeWhisperer format
- Preserve error tool results (status === 'error')
- Add 7 comprehensive tests covering all edge cases
- Verified with real usage: 13.6% savings on npm install output
2026-05-17 15:13:37 +07:00
decolua
4a575f21a2 https://github.com/decolua/9router/pull/1167
https://github.com/decolua/9router/pull/1166
2026-05-16 11:20:08 +07:00
decolua
3cca2252a6 chore: add buildOutput RTK filter, drop legacy cloud sync, internal cleanup
- feat(rtk): buildOutput filter + autodetect for npm/yarn/cargo logs
- chore: remove unused cloud sync module and related routes
- ui: hide deprecated providers (qwen, iflow, antigravity)
- chore: minor tray/cli/internal adjustments
2026-05-16 10:54:41 +07:00
anhvandev
75904b8c27
feat(open-sse): add blackbox provider with bb alias (#1143) 2026-05-15 10:50:19 +07:00
decolua
d26db17f5f Add xiaomi token plan provider 2026-05-15 10:29:25 +07:00
Aqil Aziz
da00a25eef
feat: add DeepSeek V4 Pro effort aliases (#950) 2026-05-14 10:39:34 +07:00
Fresent
d1613e8ad5
Fix issue with Ollama usage not being tracked and shown in 9router UI (#1102)
Co-authored-by: Abhi <abhi@fresent.com>
2026-05-14 09:58:18 +07:00
YourAnsh
eaccb19f59
feat: add DeepSeek TUI as CLI tool in dashboard (#1088)
Co-authored-by: Ansh7473 <your-github-email@example.com>
2026-05-13 22:40:42 +07:00
Thiên Toán
74c9879e8e
feat: add minimax tts support (#1043) 2026-05-13 15:34:10 +07:00
Aleksei
ea44ca049e
Add Codex GPT 5.5 image support (#991) 2026-05-12 09:26:13 +07:00
decolua
8f4d29caa4 # v0.4.30 (2026-05-11)
## Features
- MCP stdio→SSE bridge: expose local stdio MCP plugins over SSE (api/mcp/[plugin]/sse, /message)
- Dynamic Linux cert resolution + NSS DB injection (Debian/Arch/Fedora/openSUSE, Chrome/Chromium/Firefox incl. snap) (#1010)
- Cowork tool: expanded settings UI & API
- GitBook docs (DocsContent, DocsLayout)
## Fixes
- OAuth callback postMessage scoped to expected origins (CWE-1385) (#998)
- Re-enable TLS verification on DNS-bypass fetch (CWE-295) (#998)
- Normalize `developer` role → `system` for OpenAI-format providers (Deepseek, Groq, …) (#1011, closes #773)
- Respect `PORT` env in internal model-test fetch (#1014)
- Dropdown text readability in dark theme on usage page (#997)
## Improvements
- Refactor Claude CLI spoof headers into shared constant
- Tool deduper utility in open-sse handlers
2026-05-12 09:19:50 +07:00
Tran Hoang Nguyen
80a2bfcfd7
fix: normalize developer role to system for OpenAI-format providers (#1011)
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
2026-05-11 15:57:28 +07:00
decolua
7ad538bcf2 # v0.4.29 (2026-05-10)
## 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
2026-05-10 21:56:40 +07:00
@aaronjmars
52c38cf94c
fix(security): scope OAuth callback postMessage targets and re-enable TLS verification on DNS-bypass fetch (#998)
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>
2026-05-10 21:10:48 +07:00
Tran Long
c734913b3f
Update DeepSeek model pricing and add V4 Pro (#938)
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>
2026-05-09 10:11:39 +07:00
Aleksei
787d248030
Add Cloudflare Workers AI image generation (#973) 2026-05-09 09:53:39 +07:00
decolua
ad661c1286 feat: enhance CommandCode integration with improved message handling 2026-05-07 23:02:07 +07:00
decolua
b72a443bd3 feat: add CommandCode provider support 2026-05-07 23:01:33 +07:00
decolua
0d61a1d546 feat: add OllamaLocalExecutor and update provider handling
- 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.
2026-05-07 16:42:36 +07:00
Muhammad Mugni Hadi
7f93df3a92
feat: add audio input support for Gemini translation (#913)
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
2026-05-07 15:51:30 +07:00
decolua
5c62e73cc6 - Cowork: ComboFormModal
- 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-*)
2026-05-07 15:45:09 +07:00
decolua
d4bc42e1f5 feat: add STT support, Gemini TTS, and expand usage tracking
- Speech-to-Text: full pipeline with sttCore handler, /v1/audio/transcriptions
  endpoint, sttConfig for OpenAI, Gemini, Groq, Deepgram, AssemblyAI,
  HuggingFace, NVIDIA Parakeet; new 9router-stt skill
- Gemini TTS: add gemini provider with 30 prebuilt voices and TTS_PROVIDER_CONFIG
- Usage: implement GLM (intl/cn) and MiniMax (intl/cn) quota fetchers; refactor
  Gemini CLI usage to use retrieveUserQuota with per-model buckets
- Disabled models: lowdb-backed disabledModelsDb + /api/models/disabled route
- Header search: reusable Zustand store (headerSearchStore) wired into Header
- CLI tools: add Claude Cowork tool card and cowork-settings API
- Providers: introduce mediaPriority sorting in getProvidersByKind, add
  Kimi K2.6, reorder hermes, drop qwen STT kind
- UI: expand media-providers/[kind]/[id] page (+314), enhance OAuthModal,
  ModelSelectModal, ProviderTopology, ProxyPools, ProviderLimits
- Assets: refresh provider PNGs (alicode, byteplus, cloudflare-ai, nvidia,
  ollama, vertex, volcengine-ark) and add aws-polly, fal-ai, jina-ai, recraft,
  runwayml, stability-ai, topaz, black-forest-labs
2026-05-05 10:32:59 +07:00
decolua
9c6be62a54 Feat : Skills 2026-05-04 11:29:02 +07:00
decolua
4ba546afe7 Enhance token refresh logic and improve MITM server handling
- 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.
2026-05-03 22:10:03 +07:00
Anurag Saxena
8bdaeedb28
fix: strip stream_options for qwen non-streaming Claude Code requests (closes #557) (#663) 2026-05-03 15:21:43 +07:00
Anurag Saxena
67ca219fbf
fix: update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (closes #574) (#687) 2026-05-03 15:18:45 +07:00
Rezky Hamid
a463ee00ff
feat(codex): add review model quota support (#836) 2026-05-03 14:57:33 +07:00
Zhen
14ff538f2e
Improve mobile layouts and restore Cloudflare provider (#840)
Co-authored-by: Delynn Assistant <zhen@dkzhen.org>
2026-05-03 14:55:43 +07:00
decolua
f410061e70 Refactor proxyFetch and enhance MediaProviderDetailPage layout
- Removed the isCloud check from proxyFetch.js, simplifying the fetch patching logic.
- Updated MediaProviderDetailPage to include a new section for API key retrieval, improving user experience with clearer layout and additional notice text.
- Enhanced ConnectionRow to better handle email display names.
- Improved ProviderDetailPage to conditionally render provider notices and API key links.
- Refactored localDb, requestDetailsDb, and usageDb to remove unnecessary isCloud checks, streamlining database interactions.
- Updated OAuthModal to combine waiting and manual input steps for a more cohesive user flow.
- Added API key URLs to several providers in providers.js for better accessibility.
2026-05-01 17:03:13 +07:00
decolua
f8d2a9ff76 Merge branch 'master' of https://github.com/decolua/9router 2026-05-01 16:37:11 +07:00
Abhishek Divekar
3f17ee0e21
Add sticky round-robin for combos (#831)
Made-with: Cursor
2026-05-01 16:36:36 +07:00
decolua
b0da7c1211 Add Xiaomi MiMo provider support
- Introduced Xiaomi MiMo as a new provider in providerModels.js and providers.js.
- Updated model alias mapping in model.js to include Xiaomi MiMo.
- Enhanced validation route to support Xiaomi MiMo API endpoints.
- Added Xiaomi MiMo to APIKEY_PROVIDERS with relevant details.

This update expands the range of supported providers, improving integration capabilities.
2026-05-01 16:32:25 +07:00
thuanhuynhh
9ca388972c
Update providerModels.js (#818)
KIMI K2.5 will be deprecated on 05/05/2026. Update latest Minimax version
2026-05-01 16:20:40 +07:00
Rezky Hamid
30b114ab75
fix: strip output_config for MiniMax (#820) 2026-05-01 16:16:01 +07:00
decolua
936d65ae1c Enhance chat handling and introduce Caveman feature
- Refactored handleChatCore to include Caveman functionality, allowing for terse-style system prompts to reduce output token usage.
- Updated APIPageClient to manage Caveman settings, including enabling/disabling and selecting compression levels.
- Adjusted AntigravityExecutor to consolidate function declarations for compatibility with Gemini.
- Removed unnecessary console logs during translator initialization across multiple routes.
2026-04-30 18:00:38 +07:00
decolua
512e3de371 Update version to 0.4.9, enhance README with Trendshift badge, and add new embedding models to providerModels.js. Refactor TTS handling to support additional providers and improve API key validation for media providers. 2026-04-29 11:34:39 +07:00
decolua
e8aa5e2222 Fix : Add reasoning_content placeholder for DeepSeek thinking models 2026-04-29 09:34:24 +07:00
decolua
8f81363675 Enhance token refresh functionality across multiple executors
- Updated refreshCredentials methods in various executors (Antigravity, Base, Default, Github, Kiro) to accept optional proxyOptions for improved proxy handling.
- Modified token refresh logic to utilize proxy-aware fetch for better network management.
- Enhanced usage retrieval functions to support proxy options, ensuring seamless integration with proxy configurations.
- Updated ModelSelectModal and ProviderInfoCard components to incorporate kind filtering for improved user experience in model selection.
- Added validation for API keys in the provider validation route, including support for webSearch/webFetch providers.
2026-04-28 17:28:57 +07:00
decolua
1bb621317d Add Cloudflare AI provider support and enhance connection management
- Introduced Cloudflare AI as a new provider with specific configurations in providerModels.js and providers.js.
- Updated DefaultExecutor to handle account ID resolution for Cloudflare AI connections.
- Enhanced AddApiKeyModal and EditConnectionModal to include account ID input for Cloudflare AI.
- Implemented validation for Cloudflare AI API key connections in testUtils.js and route.js.
- Updated UI components to reflect changes in provider management and connection handling.
2026-04-28 11:07:39 +07:00
decolua
111e78940a Refactor cloudflared process management to improve port-specific termination and enhance tunnel management. Update Antigravity cloaking comments for clarity. 2026-04-28 10:20:31 +07:00
decolua
a3032f7a3e Merge branch 'pr-779-review' 2026-04-28 10:16:23 +07:00
Zhen
85959aac22
Fix quota reset timestamp parsing (#768)
Co-authored-by: Delynn Assistant <zhen@dkzhen.org>
2026-04-28 10:05:54 +07:00
Manuel B.
58a821d687
fix: granular reasoning_effort handling for Claude models (#791)
- github.js: split thinking vs reasoning_effort stripping
  - thinking (Claude-native format) still stripped for all Claude on Copilot
  - reasoning_effort now passed through for Opus 4.6 and Sonnet 4.6
  - still stripped for Haiku 4.5 and Opus 4.7 (rejected upstream)
  - reasoning_effort "none" stripped for all models (not all support it)
- openai-to-claude.js: map reasoning_effort → thinking.budget_tokens
  for direct Anthropic backend (none→skip, low→4096, medium→8192,
  high→16384, xhigh→32768)

Previously reasoning_effort was stripped for ALL Claude models,
meaning Opus 4.6 via Copilot never received thinking configuration.

AI-generated commit by Claude Opus 4.6 (Anthropic)
2026-04-28 09:49:27 +07:00
lukmanfauzie
c43f8c54d4 fix: Antigravity INVALID_ARGUMENT errors and Copilot agent mode parity 2026-04-26 19:53:08 +08:00
lukmanfauzie
222e22fa53 Fix GitHub Copilot agent mode with Antigravity
Co-authored-by: Copilot <copilot@github.com>
2026-04-26 17:47:13 +08:00
decolua
83418e8a9d Add codex to image providers 2026-04-25 17:01:40 +07:00
decolua
14ff69bf90 - Added BytePlus Provider 2026-04-25 17:00:39 +07:00
decolua
0b8bed5793 Enhance image and embedding provider support
- Added new image models for GPT 5.2, 5.3, and 5.4, including capabilities for text-to-image and editing.
- Updated embedding handling to include optional dimensions in requests.
- Introduced support for custom embedding providers, allowing dynamic fetching and validation of custom nodes.
- Improved image generation handling with Codex integration, including progress tracking and error handling.
- Enhanced UI components to support adding custom embeddings and displaying their status.
2026-04-25 16:22:30 +07:00
decolua
cca615eaff - Cap maximum cooldown for rate limit handling in account unavailability and single-model chat flows
- Dynamic custom model fetching for model selection
2026-04-24 16:14:18 +07:00
decolua
030fb34f88 - Updated markAccountUnavailable function to accept resetsAtMs for precise cooldown management.
- Added email backfill functionality for Codex OAuth connections to improve account information accuracy.
2026-04-24 11:36:16 +07:00
decolua
0aff9a502c fix: enhance retry logic and configuration for HTTP status codes 2026-04-24 10:07:08 +07:00
decolua
65f11a603e feat: add Azure OpenAI provider support 2026-04-24 10:04:59 +07:00
decolua
5abc9e5c74 add GPT 5.5 model 2026-04-24 09:51:05 +07:00
kenlin
f2e7a98ce0
feat: add built-in Volcengine Ark provider support (#741)
Add Volcengine Ark as a first-class API key provider with official model presets, endpoint configuration, API key validation, model discovery, connection testing, provider logo, and runtime alias mapping for `ark/*` model IDs.

Made-with: Cursor

Co-authored-by: kingsy <kingsylin@vip.qq.com>
2026-04-24 09:28:50 +07:00
decolua
368f4c3e7f - Added Hermes tool to CLI tools and updated related components. 2026-04-23 16:39:31 +07:00
decolua
8de9aae90c Feature : RTK compress 2026-04-22 15:36:51 +07:00
decolua
81cef7d022 Update version 2026-04-22 14:22:47 +07:00
decolua
45731ae639 feat: add OpenCode Go provider and support for custom models
- Introduced OpenCode Go provider with relevant configurations.
- Enhanced model management by allowing users to add and delete custom models.
- Updated UI components to support model selection for image types.
- Adjusted sidebar visibility to include image media kinds.
2026-04-22 14:16:21 +07:00
decolua
abb04c5366 feat: add support for Grok Web and Perplexity Web providers 2026-04-22 11:58:53 +07:00
decolua
eeb2dc9e30 fix(providerModels): remove deprecated DeepSeek 3.1 entry from provider models 2026-04-22 10:47:38 +07:00
anuragg-saxenaa
4638cf0e81 fix(ollama-local): support custom host URL for remote Ollama servers (closes #578)
Add a shared resolveOllamaLocalHost() helper and wire it through the
executor, models/validate/test routes, so users can point ollama-local
at a remote Ollama instance instead of being locked to localhost:11434.

Also expose the host as an "Ollama Host URL" field in AddApiKeyModal
(empty = default localhost:11434), making the option reachable from the
dashboard without hand-editing db.json.

Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Made-with: Cursor
2026-04-22 10:45:46 +07:00
Anurag Saxena
94ab0d715d
fix: update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (closes #572) (#683)
* fix: make version update banner clickable to copy install command (closes #598)

* fix: resolve ollama-local baseUrl from providerSpecificData.baseUrl for remote Ollama hosts (closes #578)

* fix: add Ollama Cloud to usage/quota tracking (closes #681)

* fix: update Qwen OAuth URLs from chat.qwen.ai to qwen.ai per issue #572
2026-04-22 10:32:28 +07:00
Anurag Saxena
37f7e97348
fix: force Agent mode in Cursor protobuf when User-Agent contains Claude Code (closes #643) (#692) 2026-04-22 10:24:58 +07:00
omar-nahhas
95841f9a48 fix(github): preserve reasoning_effort for non-Claude models (#713)
The previous blanket strip in GithubExecutor.transformRequest removed
`thinking` AND `reasoning_effort` for every GitHub-routed model to avoid
Claude-on-Copilot 400s from OpenClaw. That regressed GPT-5 family support
(gh/gpt-5-mini honors reasoning_effort: low/medium/high).

Make supportsThinking(model) model-aware — return false only for Claude
models, so the strip fires only where the upstream actually rejects these
fields.

Benchmarks on /v1/chat/completions via GitHub Copilot:
  effort=(none) → 64 reasoning_tokens, ~2.0s
  effort=low    → 0  reasoning_tokens, ~1.55s
  effort=medium → 64 reasoning_tokens, ~1.9s
  effort=high   → 128 reasoning_tokens, ~2.2s

Made-with: Cursor
2026-04-22 10:23:31 +07:00
Bexultan
4b9a955c4b
chore: refresh provider model list (#723) 2026-04-22 09:57:52 +07:00
decolua
6ab9927a28 fix: update backoff configuration and improve CLI detection messages
- Added installation guides for manual configuration in DroidToolCard.js and other tool cards to assist users in setting up the necessary CLI tools.
2026-04-17 12:54:50 +07:00
anuragg-saxenaa
afe09f3f14 fix(github): strip thinking/reasoning_effort for Copilot chat completions (closes #623)
GitHub Copilot /chat/completions endpoint does not support the thinking
or reasoning_effort fields. OpenClaw sends thinking: { type: "enabled" }
for Claude models which causes a 400 Bad Request.

Added supportsThinking() and strip both fields in transformRequest before
sending to the upstream endpoint.

Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Made-with: Cursor
2026-04-17 12:54:50 +07:00
Anurag Saxena
2e8784cf79
fix: show quota auth expired message for Kiro social auth accounts (closes #588) (#620)
* fix: add multi-model support for Factory Droid CLI tool (closes #521)

* fix: show quota auth expired message for Kiro social auth accounts (closes #588)
2026-04-17 12:24:35 +07:00
anuragg-saxenaa
d0ace2a3cf fix(codex): await image URL fetches before sending to upstream (closes #575)
Remote HTTP(S) image URLs are fetched and inlined as base64 data URIs
in a new prefetchImages() step run before super.execute(), so the body
sent to Codex contains resolved image bytes instead of URLs the backend
cannot access.

Scope is limited to the Codex executor — base executor and other
providers are untouched.

Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Made-with: Cursor
2026-04-17 12:15:10 +07:00
anuragg-saxenaa
6e8aaab299 fix: strip enumDescriptions from tool schema in antigravity-to-openai (closes #566)
Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Made-with: Cursor
2026-04-17 12:15:10 +07:00
decolua
3977edc460 Enhance error formatting to include low-level cause details, update HeaderMenu to use MenuItem component for better structure, and improve LanguageSwitcher to support controlled open state. Update subproject commit status. 2026-04-17 12:15:10 +07:00
decolua
75c4598da0 Add marked package, update Qwen executor for OAuth handling, and enhance changelog styles 2026-04-17 12:15:10 +07:00
Anurag Saxena
3badf1cbb6
fix: add Blackbox AI as a supported provider (closes #599) (#630)
* fix: add multi-model support for Factory Droid CLI tool (closes #521)

* Add Claude Opus 4.7 to cc and cl provider lists

RESEARCH confirmed GA release April 16, 2026. Adding to:
- cc (Claude Code): claude-opus-4-7
- cl (Cline): anthropic/claude-opus-4.7

Refs: TICKET-20260416-ENG-O4.7-001

* fix: add Blackbox AI as a supported provider (closes #599)
2026-04-17 12:06:00 +07:00
Anurag Saxena
554bbfceed
fix: strip temperature parameter for gpt-5.4 model (closes #536) (#612) 2026-04-17 12:02:53 +07:00
Anurag Saxena
aa67198e75
fix: add GLM-5 and MiniMax-M2.5 models to Kiro provider (closes #580) (#611) 2026-04-17 12:02:07 +07:00