Commit Graph

43 Commits

Author SHA1 Message Date
MrBeanDev
90b0693423 feat(thinking): return Claude thinking text to OpenAI-format clients 2026-09-26 12:02:07 +07:00
decolua
1b72f02e3b fix(opencode-go): clamp deepseek reasoning_effort "max" to "high" for mimo backends that reject it
mimo-v2.5-pro/v2.6 on the Go lane return 400 on reasoning_effort "max"
(probed live; mimo-v2.5 accepts it). The deepseek applyFormat case now honors
the declared thinking levels, and mimo-v2.5-pro gets a levels entry.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:45:40 +07:00
wismyzhizi
910db749aa feat(xiaomi-mimo): server-assisted desktop login, five account clusters, v2.6 models
Reproduce the MiMo Desktop login surface server-side so headless/Docker
deployments can link a Xiaomi account without the Desktop client. The
account session (passToken) is captured during the proxied login and
stored per connection.

- Five account clusters (cn/sgp/ams/ru/in): per-region mimo-server host
  and SSO sid, unknown region falls back to sgp
- mimo-v2.6-pro/flash/pro-ultraspeed dual-route models: account-service
  route when desktop credentials exist, cloud API (sk- key) otherwise;
  drops obsolete mimo-x-*-preview ids
- Desktop ServiceTokenManager 2-phase handshake (single serviceLogin with
  target sid, raw 64-bit nonce preserved), per-region session cache
- reasoning_effort bridged to output_config.effort; i18n runtime now
  observes characterData mutations so React text rewrites get translated
- Security hardening on the login proxy: session travels only in the
  httpOnly cookie (never in the URL), proxy branch requires dashboard
  auth, authorization/proxy-authorization never forwarded upstream, and
  upstream Set-Cookie is not replayed onto the app origin
2026-09-23 09:43:54 +07:00
Welington
0f488c7027 fix(translator): map Claude "refusal" stop_reason to content_filter and surface its explanation
Anthropic's API-level refusal (streaming classifier / ToS) ends the stream
with stop_reason "refusal", stop_details carrying the reason, zero output
tokens and no content blocks. Map refusal to content_filter in both
directions, surface stop_details.explanation as message text, and add
CLAUDE_STOP.REFUSAL to schema.
2026-09-22 15:32:48 +07:00
Rafli Ahmad Zulfikar
d1de324586 perf(usage): bound lastUsed overlay scan to 2-day window; reach max thinking tier
getUsageStats("all") shipped the entire usageHistory table to JS just to
refine lastUsed (~2s on 290K rows, on every statsEmitter update per SSE
listener). Bound the overlay to a 2-day indexed range scan; older entries
keep day-level lastUsed from usageDaily aggregates. Totals unaffected.

budgetToLevel now maps budgets > 80384 (midpoint of 32768/128000) to
"max" instead of clamping to "xhigh", so the top reasoning tier is
reachable from large budget_tokens requests.
2026-09-22 15:08:38 +07:00
Anantachoke
7c2b1fe3e1 fix(translator): drop replayed reasoning fields for Groq/Mistral/Cerebras (#4220)
Strict OpenAI-compatible validators reject unknown assistant-message
fields: Groq 400 ("property 'reasoning_content' is unsupported"),
Mistral 422 ("extra_forbidden"), Cerebras 400 ("wrong_api_format").

Clients driving reasoning models (Hermes Agent, and anything following
the DeepSeek/Kimi convention) echo the previous turn's reasoning_content
on every assistant message, so from the second turn on every request to
these providers fails and a fallback combo silently skips them.

Add a dropMessageFields rule to paramSupport.js that strips
reasoning_content / reasoning / reasoning_details from assistant turns
for groq, mistral, and cerebras.
2026-09-21 20:02:21 +07:00
Qisthi Ramadhani
c49efdf528 fix(kiro): preserve underscores in tool names and restore sanitized names in responses
Do not collapse consecutive underscores in uniqueName so mcp__server__tool is sent intact to Kiro, attach reverse map on request translation, and restore client tool names in responses.
2026-09-17 18:14:59 +07:00
Qisthi Ramadhani
82b1bca42a fix(kiro): use neutral placeholder for tool-result-only user turns
Replace the literal 'continue' placeholder on tool-result-only user turns with 'Tool results provided.' to prevent models from treating it as a new user instruction.
2026-09-17 18:12:48 +07:00
Manan Santoki
f4f06f290c fix(translator): keep tool-result images, restore Kiro tool names, preserve thinking display
Forward images inside tool_result to OpenAI and Kiro upstreams via following user messages, restore original client tool names on Kiro responses via _toolNameMap, and preserve thinking display settings across translations.
2026-09-17 18:12:05 +07:00
KhuatHieu
13b468b889 fix(commandcode): preserve images and reasoning_effort on /alpha/generate
Command Code dropped vision and ignored client effort through the router:
image blocks became "[image omitted]", HTTP image URLs were never inlined,
and reasoning_effort landed on the envelope wrapper instead of params (so the
DeepSeek family mapping remapped low -> high). The catalog also treated
deepseek/deepseek-v4.1-flash as text-only, so the vision adapter stole those
requests to another provider.

- Map OpenAI image_url / Claude image blocks (base64 or data-URI) to the
  native {type:"image", image:"data:...;base64,...", mimeType} generate block.
- Add FORMATS.COMMANDCODE to TARGETS_NEED_BASE64 so remote http(s) images are
  inlined by the existing SSRF-safe fetcher before translation.
- Write reasoning_effort inside params for targetFormat commandcode and pass
  low|medium|high|xhigh|max through unmapped; allow it in thinkingLevels.
- Provider-scoped capabilities for commandcode/cmc: vision except the CLI
  text-only denylist, thinkingFormat commandcode, so family patterns
  (deepseek-v4 -> thinkingFormat deepseek, vision false) no longer win.
- Quota Tracker: whoami + billing credits/subscriptions (credits vs plan cap,
  5h and weekly windows), labels from AI_PROVIDERS[].name.
2026-09-16 20:17:25 +07:00
叶炜朋
73cb89143c feat(xiaomi-mimo): merge MiMo Desktop support into xiaomi-mimo as dual auth
Adds the Desktop-exclusive Preview models and the Xiaomi account-session
route to the existing xiaomi-mimo provider instead of a separate
xiaomi-desktop provider, so the dashboard shows one MiMo entry rather than
three overlapping ones.

Dual auth, same pattern as kimi — API key (sk-) covers the cloud API,
Desktop/OAuth adds the account session used by the Preview models:

- registry: category oauth, authModes [oauth, apikey], oauth block, the two
  mimo-x-*-preview models, and the invite signupUrl
- executor: routes Preview models to the account-service route with a Cookie
  session, everything else keeps the sourceFormat-matched transport
- oauth: custom ECDH encrypted-callback flow (X25519 -> SHA256 -> AES-256-GCM)
  with a loopback callback proxy, plus one-click import of the local Desktop
  auth.json
- usage: weekly quota from the account session

Fixes found while merging:

- the OAuth browser flow was dead: poll-status cleared the session before the
  client could POST /exchange, so every exchange returned 400
- a Claude-format client was sent to /v1/chat/completions instead of the
  declared /anthropic/v1/messages transport, because buildUrl ignored
  runtimeTransport
- stopXiaomiMimoProxy leaked every pending session (each holding an X25519
  private key) for the process lifetime
- the OAuth exchange did not persist the Desktop passToken, so the Preview
  models could never work after a browser sign-in

Removes dead code: the local engine token minting (mimoEngine, never called
on the request path), the model-catalog and usage routes, engineToken/
engineUrl plumbing, and an unread top-level usage block.

Adds tests/unit/xiaomi-mimo-{executor,oauth-session,oauth-proxy}.test.js —
the provider previously had none.
2026-09-10 23:42:41 +07:00
LLL
248d7da01c revert(qoder): drop the Responses usage plumbing from shared code
The merged Qoder work also rewrote shared translator/handler code so that
/v1/responses clients got token usage on response.completed. That changed
behaviour for every provider, not just Qoder: proxies saw input tokens
rise by the 2000-token context buffer, and the plain token mapping was
replaced by one that always adds input_tokens_details.

A probe confirms the Qoder benefit does not depend on those edits: the
executor's coalescer already emits one include_usage-style finish chunk, so
a Claude client receives input_tokens and cache_read_input_tokens with
every shared file at its original state. Only the Responses path relies on
the shared translator, and that path has no Qoder-owned seam to put it in.

Reverts the shared files to their pre-PR state and drops the Responses
usage test. The Cline envelope unwrap in nonStreamingHandler.js, which
landed after the PR in the same file, is kept.
2026-09-10 23:13:06 +07:00
galiehneh
998bb3d975 fix(tools): scope Claude tool type defaulting to gateways that need it (#3905)
defaultClaudeToolType() stamped tools[].type = "custom" onto every
Claude-format request carrying tools since e08ac6da. That satisfied
MiniMax (error 2013) but broke Anthropic-compatible endpoints that only
accept the legacy typeless tool shape. DeepSeek's endpoint
(api.deepseek.com/anthropic/v1/messages) whitelists its tool `type` enum
to the web_search_* variants and answers HTTP 400 "unknown variant
`custom`", so every Claude Code request routed to a DeepSeek connection
failed and surfaced as a persistent 503.

Run the defaulting only when the target provider declares the new
requireClaudeToolType quirk (MiniMax, MiniMax-CN). Add
shouldDefaultClaudeToolType(provider, finalFormat, tools, PROVIDERS) in
translator/concerns/toolCall.js so the gate is unit-testable, and cover
MiniMax keeping the explicit type, DeepSeek/Anthropic staying typeless,
non-Claude formats and tool-less requests never defaulting.

Effectively a no-op for MiniMax and a restore of the pre-e08ac6da
behaviour everywhere else. Another strict gateway now only needs the same
one-line quirk instead of a global behavioural change.
2026-09-10 23:03:53 +07:00
LLL
1f10f9e5c4 fix(qoder): report usage to all clients and stop inlining large attachments
- Coalesce Qoder's empty finish-in-delta frame with the later choices:[] usage
  frame so OpenAI and Claude clients receive prompt_tokens, completion_tokens
  and cache-hit tokens (the dashboard already saw them)
- Upload inlined images through /api/v2/image/upload like qodercli, and stub
  oversized non-image files instead of stuffing 30MB+ data URIs into
  agent_chat_generation
- Emit response.completed -> response.usage for chat-native upstreams so
  /v1/responses clients (Codex CLI, sub2api) no longer log 0/0/0
- Keep Claude message_delta.usage working when usage arrives without choices[0]
- Escalate to the smallest advertised Qoder context tier (200K/400K/1M) when
  the estimated prompt no longer fits max_input_tokens
- Pass apiKey for PAT connections and list hidden enable:false catalog keys
  from /v1/models
2026-09-10 22:08:19 +07:00
Sutarto Jordan Chrisfivo
77e6a227fe fix(claude): normalize adaptive auto effort (#3792)
Claude adaptive requests without an explicit effort are normalized to
output_config.effort: "high" instead of forwarding the unsupported
literal value "auto" which Anthropic rejects with HTTP 400.
2026-09-05 21:41:25 +07:00
Lek Huda
1fe996db6a fix(translator): route Gemini thinking through reasoning_effort on OpenAI-compatible wire 2026-09-03 09:12:34 +07:00
LucasOl1337
ac9120fde3 fix(claude): support Fable 5.1
- add claude-fable-5-1 to the Claude Code model catalog (1M context,
  permanent adaptive thinking)
- centralize the spoofed Claude Code version and update both request
  and billing identities to 2.1.257 (Fable 5.1 rejects < 2.1.251)
- send output_config.effort without the redundant thinking switch for
  permanently adaptive models
- add regression coverage for capabilities, headers, billing identity
  and adaptive-effort payload

# Conflicts:
#	open-sse/providers/registry/claude.js
#	open-sse/providers/shared.js
#	open-sse/utils/claudeCloaking.js
#	tests/__baseline__/providers-baseline.json
2026-09-02 20:42:53 +07:00
qingyong
56a40765e9 fix(translator): zai thinkingFormat sends reasoning.effort object
Z.ai / GLM-5.2+ require a top-level reasoning_effort (low/high/max)
alongside thinking:{type:"enabled"} to control reasoning depth; the zai
branch previously only set thinking and dropped reasoning_effort, so every
GLM-5.x request ran at the model default (max). Gate the field behind
GLM-5.2+ (thinkingEffortSupported in capabilities.js) since older GLM
(4.x, 5.0, 5.1, 5-turbo, 5v-turbo) do not read it, and map client levels
to the exact low/high/max values z.ai accepts.

extractThinking now checks reasoning_effort/reasoning.effort before the
thinking object so a client-supplied effort is not overwritten by
thinking:{type:"enabled"} mapping to mode:auto.

Fixes #2721
2026-08-28 12:32:41 +07:00
warelik
e08ac6dada fix(tools): default Claude tool type when missing
Strict Anthropic-compatible gateways (e.g. MiniMax) reject Claude-format
requests with HTTP 400 when tools[].type is missing. Normalize each
missing/falsy tools[].type to "custom" before dispatch when the final
request format is Claude. Built-in tool types (computer_use, bash,
web_search_*) are passed through untouched.
2026-08-28 11:16:44 +07:00
Bertho Joris
345cdcf6a5 fix(combo): detect images from Hermes and attachment payloads for Vision Adapter
Inspect images[], experimental_attachments/attachments, message-level
image/image_url/audio_url, and inline data:image|audio|pdf URIs on trailing
user turns so Vision Adapter auto-switch fires for Hermes/Ollama/Vercel AI
SDK shapes. stripOpenAI now also drops msg.images and image attachments when
the active model lacks vision support.
2026-08-13 18:30:44 +07:00
Dasep Moch Luay
41588bea01 feat(providers): add TokenRouter accurate pricing + thinking config
Adds exact per-model rates for 110 TokenRouter models (pulled from
TokenRouter's own pricing API) plus a dedicated thinkingFormat case
(reasoning_effort enum low/medium/high/xhigh/max) and the provider
logo. Provider registration itself already landed in a prior commit;
this fills in what PR #3043 added on top.
2026-08-05 16:31:03 +07:00
seakleang.nhak
86131b9ca4 feat(codex): support GPT-5.6 Max and Ultra overrides
Add "ultra" reasoning level for Codex GPT-5.6 Sol and Terra, and expose
Max for Luna (Luna falls back Ultra to Max since it is not supported
upstream). Scoped to cx/ routes only; Kiro and generic OpenAI routing
unchanged.
2026-08-05 11:39:59 +07:00
nguyenha935
16cb40fda1 fix(kiro): canonicalize tool history and route API keys correctly
Route API-key inference through Amazon Q first, enforce adjacent
one-to-one tool use/result pairs after session replay, and treat
payload-invalid HTTP 400 as terminal.
2026-07-29 19:27:41 +07:00
decolua
a6a41dfb3c Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	.gitignore
#	open-sse/handlers/chatCore.js
2026-07-16 11:59:46 +07:00
luoyide
ba508f2506 fix(thinking): send explicit thinking:{type:adaptive} alongside output_config.effort 2026-07-16 11:17:08 +07:00
Moradii.Mohammadreza
9173c29b66 feat(translator): drop temperature for all Claude models
Broaden strip rule from /claude-opus-4/i to /claude/i so temperature is
removed for every Claude model, not just opus-4. Fixes Anthropic 400 on
OpenAI-compatible routes. #1748
2026-07-15 17:08:41 +07:00
DOMANHDUC
7610f28f42 fix(gemini-cli): raise output floor for thinking and add validated toolConfig (#2486)
Gemini CLI requests with small max_tokens spend the whole output budget on
thoughts after reasoning_effort maps to thinkingConfig, returning blank
content or finish=length. Raise maxOutputTokens floors per thinking level/
budget (clamped to caps.maxOutput). Also emit toolConfig
functionCallingConfig.mode=VALIDATED for Gemini CLI tool requests to avoid
MALFORMED_FUNCTION_CALL.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 11:32:11 +07:00
thienpv
288940960a fix(translator): clamp thinking effort max->xhigh for OpenAI format (#2466)
Claude Code sends reasoning_effort "max" (its top level); OpenAI enum caps
at "xhigh" and rejects "max" with HTTP 400 "max effort not support".
applyFormat case "openai" now clamps "max"->"xhigh" before assigning
body.reasoning_effort; other levels pass through unchanged.

Add regression test covering client output_config.effort, direct
reasoning_effort, passthrough of xhigh/high, and budget_tokens capping.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-09 15:13:24 +07:00
whale9820
cfbdf06047 fix(volcengine-ark): clamp Kimi max_tokens to 32768 endpoint cap
VolcEngine Ark caps the Kimi family at max_tokens <= 32768, but the
model's advertised ceiling is far higher (Kimi-K2.7-Code resolves to
maxOutput 262144), so clampToModelMaxOutput alone leaves it uncapped and
the request 400s. Add a Kimi-scoped rule with an explicit maxOutputCap of
32768, combined with the model ceiling via min(). Covers max_tokens,
max_completion_tokens, max_output_tokens.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-09 15:10:05 +07:00
decolua
b10b807063 # v0.5.20 (2026-07-07)
## Features
- **Thinking**: per-model thinking level picker on provider page — appends `(level)` suffix to copied model names for forced reasoning effort across all formats (openai, claude, gemini, deepseek, kimi, qwen, zai, minimax, hunyuan, step)
- **RTK**: add JS-native git-log filter (#2423)
- **Caveman**: add targeted upstream-aligned style rules (#2424)
- **i18n**: add Farsi (fa) language support (#2385)

## Fixes
- **Thinking**: strip `(level)` suffix from upstream `body.model` so providers no longer reject requests
- **Translator**: preserve developer instructions in openai-responses conversion (#2434)
- **count_tokens**: count structured Anthropic blocks (#2419)
- **Volcengine-ark**: clamp GLM-5 max_tokens to model output ceiling (#2428)
- **Kimi**: normalize reasoning_effort to backend enum (#2427)
- **Claude**: reconcile max_tokens vs thinking budget and lift per-model ceiling (#2381)
- **Kiro**: deliver system prompt natively, add Opus 4.5/4.7/4.8, tolerate dash version ids (#2366)
- **Headroom**: proxy dashboard through app (#2372)
- **MITM**: recover from stale lock file on server start
2026-07-07 16:29:11 +07:00
whale
bbae990b92 fix(volcengine-ark): clamp GLM-5 max_tokens to model output ceiling (#2428)
Ark rejects max_tokens above 128000 for GLM-5.2. Add a config-driven STRIP_RULES entry that clamps max_tokens, max_completion_tokens and max_output_tokens down to the model maxOutput before the upstream call.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 11:57:04 +07:00
whale
8c068a1f5c fix(kimi): normalize reasoning_effort to backend enum (#2427)
Map auto→high, minimal→low, xhigh→max and whitelist low/medium/high/max
so Kimi/kimchi SGLang backends no longer receive invalid effort values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 11:56:39 +07:00
hodtien
54e3245ace feat(usage): track cached tokens + correct input/output/cache cost (#2209)
Normalize every provider to one cache-inclusive convention via
canonicalizeUsage() before persist, and price cached + cache_creation as
subsets of prompt_tokens in calculateCostFromTokens() to stop
double-counting. usageRepo now delegates cost math to a single source.
Surface Cached tokens/cost across dashboard (overview, tokens, cost,
details). Merge Claude message_start cache with message_delta output so
cache counts survive. Compatible LLM nodes now allow multiple API-key
connections (key pool).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 15:18:27 +07:00
Joseph Yaksich
4a54824f7f fix(param-support): handle strip rules without match/drop
Cloudflare AI rule only sets flattenContent. Treat missing match as
provider-wide and missing drop as empty list to avoid crash. Fixes #1960.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 17:20:09 +07:00
ntdung6868
3a866fe18d fix(reasoning): preserve effort through Codex translations
Carry Claude reasoning_effort/reasoning into OpenAI Chat, map into
OpenAI Responses reasoning.effort, and keep request-level effort
(incl. xhigh) across tool-result turns instead of collapsing to high.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 12:06:35 +07:00
Mink Nguyen
c4f80d30d8 fix provider thinking compatibility
- claude: handle DeepSeek thinking blocks defensively, unsigned placeholder; fix kept-vs-seen thinking detection
- gemini: clamp unsupported max/xhigh thinking levels to high
- testUtils: probe Cloud Code Assist for gemini-cli/antigravity with 401 refresh retry
- tests: add translator regression coverage

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:12:48 +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
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
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
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
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