Commit Graph
464 Commits
Author SHA1 Message Date
Sutarto Jordan ChrisfivoandCursor 373850ee36 fix(headroom): skip unsafe responses tool history (#2132)
Guard openai-responses compression: skip Headroom when body.input
contains non-message items (function_call, function_call_output,
reasoning) to preserve the Responses contract instead of collapsing
them into chat messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:59:21 +07:00
decoluaandCursor 749c2e3f9c fix(translator): map mid-conversation system message to user in claude-to-openai
Claude Code chèn role:system cuối messages[], trước đây bị map thành assistant
khiến hội thoại không kết thúc bằng user → provider OpenAI-compat (LiteLLM)
dịch ngược Anthropic trả 400 "assistant message prefill". Map system -> user
và wrap <system-reminder> để giữ ngữ nghĩa instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:53:26 +07:00
decoluaandCursor 7fa2e7f029 feat(capabilities): refine Qwen vision/video and thinking model patterns
Add qwen omni (audio/video input), qwen3.5/3.6/3.7 (native vision/video),
and mark qwen coder & max as text-only reasoning models.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:51:56 +07:00
warelikandCursor 8d1db46beb fix(gemini): normalize contents to prevent 400 invalid_argument (#2192)
Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:38:03 +07:00
RexandCursor 9e3866658a fix(alicode): preserve cache_control for DashScope providers (#2069)
Opt-in quirk preserveCacheControl keeps cache_control on content blocks
for alicode/alicode-intl, enabling DashScope prompt caching. signature
is always stripped; all other providers unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:29:49 +07:00
Nant361andCursor 8a664d619d feat(kimchi): add Kimchi OAuth provider support
Add Kimchi as a browser-token OAuth provider routed through its
OpenAI-compatible gateway. Discover live models for /v1/models and
provider models, normalize Claude-compatible requests, and wire up
provider connection tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:29:17 +07:00
WARELIKandCursor 2d94fffe3b fix(gemini): backfill thoughtSignature and suppress stream done sentinel
Backfill DEFAULT_THINKING_AG_SIGNATURE onto functionCall parts missing it
(client history replay) and on Claude tool_use blocks, fixing 400
INVALID_ARGUMENT from Gemini-family APIs. Suppress the OpenAI-style
data: [DONE] sentinel for antigravity/gemini/vertex to avoid parser crashes.

Fixes #2193.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:28:03 +07:00
Yudhistira-OfficialandCursor 319caa2d7b fix(antigravity): strip 'deprecated' from tool schemas before Gemini
Gemini rejects the non-standard 'deprecated' keyword in nested tool
schemas with INVALID_ARGUMENT (400). Add it to UNSUPPORTED_SCHEMA_CONSTRAINTS
alongside 'optional' so it gets stripped during translation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:28:02 +07:00
whale9820 95bfc64f06 fix(codebuddy-cn): show bonus packs as one-time, not monthly-replenishing
CodeBuddy CN bonus packs ("Bonus Pack N") are one-shot credits whose
CycleEndTime equals DeductionEndTime — they expire for good and never
replenish. The dashboard rendered their resetAt as "Reset in Xd",
implying a monthly refill.

Tag bonus packs recurring:false (refill packs recurring:true) in the
usage handler, forward the flag through parseQuotaData, and word the
quota table / progress bar as "Expires in" / "Expires at" for
one-shot packs.
2026-06-29 15:22:47 +07:00
hamsa0x7andCursor eff81b1242 fix(kiro): strip leaked <thinking> tags from content stream (#2158)
CodeWhisperer leaks literal <thinking> blocks into assistantResponseEvent,
duplicating reasoning already routed via reasoningContentEvent. Track
inThinking state to strip these tags during SSE transform, handling split
chunks across tag boundaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:14:15 +07:00
jellylarperandCursor 713c563765 fix(kilocode): expose full gateway catalog in combo model picker
Add modelsFetcher + passthroughModels so the dynamic Kilo Gateway
catalog surfaces in the combo model picker, matching openrouter.js.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:12:18 +07:00
iletaiandCursor 3d20a4ccd2 fix(antigravity): strip deprecated/readOnly/writeOnly from tool schemas
Gemini/Antigravity generateContent rejects the JSON Schema annotation
keywords deprecated, readOnly, writeOnly with a 400 INVALID_ARGUMENT.
MCP tool schemas (e.g. Claude Code) commonly set deprecated:true, making
every request with such a tool fail. Add them to
UNSUPPORTED_SCHEMA_CONSTRAINTS so cleanJSONSchemaForAntigravity removes
them recursively before the request is sent.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:12:17 +07:00
decolua 526235872a Fix OpenCode Go GLM 2026-06-29 15:00:03 +07:00
Joseph YaksichandCursor 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
Sutarto Jordan ChrisfivoandCursor 639f1204d0 fix(antigravity): retry transient upstream failures
Retry short-lived 5xx/capacity errors (500/502/503/504 + message
patterns) with bounded backoff capped at 15s; honor Retry-After/reset
hints and skip when wait is too long. Keep 400 non-retryable. Enable the
retry hook for 500 alongside existing 429/503.

Deduplicate sanitized Antigravity tool names before emitting the single
functionDeclarations group to avoid upstream "Tool names must be unique"
rejections.

Add Headroom size diagnostics and phantom-savings warning when reported
token delta does not shrink the outbound payload.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 17:19:46 +07:00
ntdung6868andCursor 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
suryacagurandCursor 940a35e009 feat(blackbox): overhaul provider catalog + WebUI test support
- registry: baseUrl -> /v1/chat/completions, 10 latest models with
  upstreamModelId prefix, add thinkingConfig + serviceKinds
- capabilities: rename claude-opus-4.6 -> 4.8, bump claude-sonnet-4.6
  maxOutput 64k -> 128k
- testUtils: add blackbox case to testApiKeyConnection (GET /models)
- ollama: add minimax-m3 model

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 12:03:58 +07:00
Stevanus PangauandCursor a4f44e3e12 feat(kiro): add external_idp CLIProxyAPI import for Microsoft SSO
Import Kiro accounts authenticated via Microsoft Entra/365 SSO using
CLIProxyAPI JSON. Adds external_idp refresh path (form-encoded OAuth2,
Microsoft login host allowlist), TokenType: EXTERNAL_IDP header for
runtime and usage/quota requests, dashboard import UI, and unit tests.
Scoped to authMethod === "external_idp"; existing Kiro auth unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:42:05 +07:00
Brokenc0deandCursor 49a3ec7a72 fix(capabilities): mark Claude Opus 4.7 (dashed id) as 1M context
Registry exposes the dashed id claude-opus-4-7; matchPattern treats "."
as a literal, so it missed the dotted pattern and fell through to the
generic claude opus entry (200k / claude-budget). Add an exact entry so
it resolves to 1M context + adaptive thinking, plus a unit test covering
the dashed Opus ids.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:40:28 +07:00
Brokenc0deandCursor ab5ec52f28 feat(providers): add Venice AI provider
OpenAI-compatible apikey provider (chat/embedding/image) with dynamic
model discovery via modelsFetcher + passthroughModels. No executor needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:37:44 +07:00
EdisonPVEandCursor eb9728d084 fix(kiro): report 1M context window for claude-opus-4.8
Add 1M context capability overrides for claude-opus-4.8 and -thinking
variants, and use the resolved capability contextWindow (fallback 200k)
instead of the hardcoded 200k estimate in the Kiro executor.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:22:26 +07:00
AnkitandCursor d4d11357ab fix(headroom): translate openai-responses input through OpenAI for compression
Codex (openai-responses) body.input holds Responses items, not OpenAI
messages. Translate input -> OpenAI -> compress -> back to input so the
Responses contract is preserved. Fixes #1998

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:12:10 +07:00
Sutarto Jordan ChrisfivoandCursor fb543a1f39 fix(headroom): clarify token diagnostics vs provider billing
Distinguish Headroom-reported token deltas from outbound payload size,
scrub credentials in logs, and warn on phantom savings when compressed
JSON barely shrinks. Refs #1998

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 11:12:07 +07:00
RexandCursor d1e98d9a60 fix(codebuddy): only send reasoning params when client requests reasoning
Forcing reasoning_effort:"medium" + reasoning_summary:"auto" on plain
requests tripped CodeBuddy's content filter and returned an error (#2071).
Make reasoning params opt-in: only set reasoning_summary when the client
sent an explicit reasoning_effort; none/off still drops it.

Fixes #2071

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:51:16 +07:00
nguyenha935andCursor dae69a3916 fix(gemini): support native TTS generateContent endpoint
Pass Gemini AUDIO/TTS generateContent requests through to Google's native
v1beta endpoint instead of converting to chat, with per-credential fallback
(504 timeout, 502 fetch failure). Accept client keys from Bearer,
x-goog-api-key, or ?key= while forwarding only the configured Gemini
credential upstream. Expose native v1beta model names and rewrites, and add
Gemini 3.1 Flash TTS to the catalogs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:50:13 +07:00
caiqinzhouandCursor 1980178d02 feat(github): resolve Copilot model catalog from upstream
Fetch the live model list from the Copilot /models endpoint and surface
it through /v1/models, replacing the hardcoded github entry so newly
shipped models appear without a code change. Catalog is cached per
credential and the Copilot token is refreshed on 401/403 before retry.

Also raise the connectivity-test budget to max_tokens:16, since Claude on
Copilot emits no choices at max_tokens:1 and produced a false negative.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:38:09 +07:00
tenglongandCursor e544bfceae fix(codex): preserve Responses text format
Add "text" to Codex Responses API allowlist so text.format.json_schema
reaches upstream for structured outputs instead of being stripped.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:37:29 +07:00
Joseph YaksichandCursor c842dc8f07 fix: preserve forced streaming for json clients
Keep provider-required streaming when client prefers JSON. The
Accept: application/json branch no longer flips stream back to false
for forceStream providers, fixing 400 errors on stream-only providers
(e.g. Command Code) for Hermes / Claude Code / other JSON clients.

Fixes #2031

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:37:23 +07:00
nguyenha935andCursor ce844899ed fix(tts): resolve Gemini TTS models from catalog
Resolve Gemini TTS models from shared TTS catalog and provider registry
with a safe fallback, fixing requests resolving to models/undefined when
ttsConfig.models is empty. Add gemini-3.1-flash-tts-preview to catalogs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:32:34 +07:00
qianzeandCursor c22f11de38 fix(stream): prevent non-JSON SSE lines and duplicate [DONE] from breaking clients
- Passthrough: skip non-JSON data lines instead of forwarding raw garbage
- Translate: stop emitting redundant [DONE] sentinel (message_stop terminates)
- Add streamDoneSent flag to prevent duplicate [DONE] across transform + flush
- Warn on unexpected upstream Content-Type for streaming responses

PR #2046 by @qianze0628

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:22:53 +07:00
Mink NguyenandCursor 0d21668917 Fix usage logging dedupe and reduce stats churn
- batch console log buffer events and support batched SSE log messages
- debounce usage stats update/pending events to reduce UI/runtime churn
- avoid awaiting request-success bookkeeping before returning provider responses
- deduplicate identical usage writes in usageHistory/daily aggregates
- reduce default logger verbosity from DEBUG to INFO (overridable via LOG_LEVEL)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:22:20 +07:00
decoluaandCursor ec096d2add fix(usage): stop double-counting streaming usage at source
logUsage now only logs to console; DB write removed. Streaming usage is
recorded once via saveUsageStats (onStreamComplete), eliminating duplicate
usageHistory rows that inflated dashboard totals.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 10:22:10 +07:00
Mink NguyenandCursor 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 d9b9a192ef Fix AG 2026-06-21 18:01:33 +07:00
decoluaandCursor 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
NautilaceaeandCursor 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
swatkerandCursor 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
decoluaandCursor 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
decoluaandCursor 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
decoluaandCursor 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 YogaandCursor 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 YogaandCursor 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 ChrisfivoandCursor 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
mustafabozkayaandCursor 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
warelikandCursor 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
nguyenha935andCursor 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
decoluaandCursor 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