client_metadata is an OpenAI Responses API-specific field. When translating
openai-responses requests to openai (Chat Completions), it leaked through
to providers like NVIDIA, which rejected it with a 400 "Unsupported
parameter". Strip it in the Responses-specific cleanup block alongside
input, instructions, store, and reasoning.
GitHub Copilot's /chat/completions and /responses endpoints never surface
prompt-cache token counts for Claude models. Route Claude models (detected
by name pattern) to Copilot's Anthropic-native /v1/messages shim via a new
executeWithMessagesEndpoint(), translating OpenAI-shape requests to Claude
natively so cache_control gets injected and cached_tokens surface.
Also fixes translateRequest()'s internal _toolNameMap being sent upstream,
which made Anthropic's strict schema reject tool-call requests with a 400 —
now stripped and threaded through response state. Removes the now-dead
response_format Claude JSON-mode workaround.
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
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>
handleStreamingResponse and buildOnStreamComplete each generated their
own streamDetailId for what should be one logical record — the
placeholder row (0 tokens) and the final row (real usage) never shared
an id, so the DB's ON CONFLICT(id) upsert never merged them, leaving a
permanent 0-token stub for every streaming request.
Share the id from buildOnStreamComplete with handleStreamingResponse
so both writes hit the same row.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add read-only GET to inspect per-credit reset inventory (status, granted,
expiry, remaining) with a Quota Tracker modal. DRY the route via shared
connection/refresh helpers; keep existing consume POST unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
Combo mixes models, so non-Claude thinking signatures leak into
conversation history. Native passthrough forwarded them verbatim and
Anthropic rejected the request. Validate signatures and drop invalid
thinking blocks, re-inserting a placeholder when tool_use requires one.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Updated capabilities for NVIDIA models to enforce OpenAI-compatible reasoning formats.
- Added new models: MiniMax M3, GLM 5.2, DeepSeek V4 Pro, DeepSeek V4 Flash, Kimi K2.6, and Nemotron 3 Ultra to the NVIDIA registry.
This enhances the provider's functionality and aligns with OpenAI standards.
IAM Identity Center (authMethod=idc) tokens failed every request with 403
"bearer token invalid". Treat idc like api_key/external_idp:
- executors/kiro.js: route idc to *.amazonaws.com CodeWhisperer surface,
region-aware from credentials.region instead of hardcoded us-east-1.
- openai-to-kiro.js / claude-to-kiro.js: send resolved profileArn or empty
for idc/external_idp, never the shared builder-id placeholder ARN.
Co-authored-by: Cursor <cursoragent@cursor.com>
Filter empty text blocks from thoughtSignature-only parts, preserve
tool_calls when functionResponse and functionCall coexist in the same
content, and skip empty regular text parts before they reach Claude.
Co-authored-by: Cursor <cursoragent@cursor.com>
Clients echo full message history each turn including reasoning_content,
which the Kimchi OpenAI gateway counts as input tokens. Multi-turn convos
balloon to 100k+ tokens and the model returns empty content.
KimchiExecutor.transformRequest now strips reasoning_content from assistant
messages when it exceeds an 8-char threshold, preserving the 1-char
placeholder injectReasoningContent sets and keeping content intact.
Co-authored-by: Cursor <cursoragent@cursor.com>
CodeBuddy CN includes "tool_calls": [] in every SSE streaming delta.
@ai-sdk/openai-compatible checks delta.tool_calls != null — an empty
array passes ([] != null is true in JS), triggering premature
reasoning-end on every reasoning chunk (0/1ms durations in OpenCode).
Strip empty tool_calls arrays in passthrough before hasValuableContent.
Zero side-effect: real tool_calls always have at least one element.
Closes#2176
Co-authored-by: Cursor <cursoragent@cursor.com>
Gemini response translation wrote OpenAI-shaped bookkeeping into the
shared state.toolCalls map, which the downstream openai-to-claude
translator uses for Claude block metadata. That pre-population skipped
blockIndex creation, so Anthropic input_json_delta events lost index.
Track Gemini function calls via state.geminiToolCallCount instead,
leaving state.toolCalls clean for the Claude translator.
Closes#2218
Co-authored-by: Cursor <cursoragent@cursor.com>
Direct MITM server startup read rootCA.key/.crt immediately and exited
when either was missing, bypassing the manager.js CA setup path.
- generate Root CA from server.js when key/cert is missing
- make generateRootCA()/generateCert() synchronous to avoid a startup
race before readFileSync
- add unit test covering synchronous Root CA creation
Co-authored-by: Cursor <cursoragent@cursor.com>
Treat response.done as a terminal OpenAI Responses stream event so
passthrough streams ending with response.done are not flagged incomplete
and no synthetic response.failed is emitted. Restore the data: [DONE]
sentinel for same-format Responses passthrough streams.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
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>
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>
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>
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>
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>
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>
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>
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.
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>
Generalize Claude 5h auto-ping into a provider-generic scheduler and add
opt-in Codex auto-ping that warms the next 5h window via a tiny gpt-5.5
request when session.resetAt slides. Default off, per-connection toggle,
failure cooldown, blocking-quota skip, drains stream before success.
Closes#2107
Co-authored-by: Cursor <cursoragent@cursor.com>
Set process DPI awareness (Per-Monitor V2 with fallbacks) and enable
WinForms visual styles before creating the tray NotifyIcon, so the
Windows context menu renders sharply on DPI-scaled displays.
Closes#2161
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
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>
Use getModelInfo instead of parseModel in /api/translator/translate
so custom OpenAI/Anthropic-compatible provider prefixes resolve
correctly, aligning the debug path with the runtime chat path.
Fixes#1083
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
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>
isBlockedIpv6() did not normalize ::ffff:<ipv4>, allowing the SSRF
filter to be bypassed. Extract and validate via isBlockedIpv4().
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
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>