Commit Graph
48 Commits
Author SHA1 Message Date
MUH. IQRAM BAHRING c378f2dc90 Merge remote-tracking branch 'upstream/master' 2026-09-05 23:20:53 +08:00
louis-cai ac98dd9d32 fix(antigravity): strike-break optimistic quota readings that keep 429ing
Google's quota API can report remaining quota while generation endpoints
keep returning 429 (sprint/weekly dual-pool mismatch). handleAntigravityQuotaError
trusted remainingPercentage > 0 as healthy and returned null, causing 429 retry
loops across multi-account pools.

Add a strike-based circuit breaker to the optimistic and unavailable quota paths:
- After 3 strikes (429/409) within 60s for the same connection+model, cache-block
  that pair for 15 minutes by synthesizing an entry in the shared RAM quota cache.
- Re-assert active strike blocks across refreshes so optimistic readings cannot
  resurrect a broken pair prematurely.
- Reset strikes and clear synthesized cache entry upon successful request.
- Keep exact-resetAt handling for genuine 0% exhausted readings.

Closes #3681
2026-09-03 09:34:24 +07:00
vianhanif 15687d1913 fix(chat,docker): return 503 for rate-limited providers and bundle node-machine-id
- chat: always return 503 Service Unavailable when all credentials are rate-limited
- Dockerfile: explicitly copy node-machine-id into standalone runtime image
2026-09-03 09:25:17 +07:00
Federico Liva ee7a961633 fix: strip the [1m] context marker Claude Code appends to the model name
With the 1M-context beta enabled, Claude Code sends model: "claude-opus-5[1m]".
The marker is a client-side annotation — it matches no combo name, no alias and
no provider/model pair — so the request dies at model resolution with
"Invalid model format" and the client reports "There's an issue with the
selected model". Every request from that session fails until the beta is
switched off.

New open-sse/utils/modelMarkers.js exporting stripModelContextMarker(modelStr)
-> { model, contextMarker }. handleChat strips the marker before resolution and
normalizes body.model so downstream logging and translation see the real name.
Only a trailing marker is stripped, so a model whose name genuinely contains
brackets is left alone.

The capability itself travels in anthropic-beta: context-1m-2025-08-07, which
the default executor already forwards untouched — only the routing key needed
cleaning.

Fixes #3690.

Tests: tests/unit/model-context-marker.test.js (6 cases).
2026-09-02 20:20:32 +07:00
MUH. IQRAM BAHRING eaf204b83c Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	open-sse/handlers/chatCore.js
#	open-sse/providers/registry/index.js
#	open-sse/services/usage.js
2026-08-30 23:23:48 +08:00
snower 993c6eb469 feat(headroom): make the compression request timeout configurable
The 3000 ms timeout on /v1/compress was fixed, so busy or slow machines
timed out often and sent the LLM an inconsistently compressed body,
hurting prompt caching. Add a headroomTimeoutMs setting, thread it from
the chat handler down to compressWithHeadroom, expose it in the Token
Saver dashboard, and normalize invalid values back to the 3000 ms default.
2026-08-28 16:34:33 +07:00
Nim 1a3db1efae feat(antigravity): quota-aware routing with reset-aware fallback
On a 409/429 from Antigravity, fetch live quota to learn the exact
per-model resetAt instead of guessing a backoff, then skip only the
exhausted account/model pair until that time.

- antigravityQuota.js: in-memory quota cache, coalesced concurrent
  refreshes, 30s throttle per connection (applied to failures too),
  keeps known cache when upstream returns 401/403 error payloads
- auth.js: pre-filter exhausted account/model pairs; report the
  earliest quota reset when every account is blocked; skip the
  30-minute cooldown cap so the upstream resetAt is not truncated
- chat.js: antigravity 409/429 falls back on the RAM cache only, no
  persistent modelLock_* for this path
- Logs identify accounts by id prefix, never email or name

Closes #3561
2026-08-27 16:18:08 +07:00
MUH. IQRAM BAHRING fd22290a34 feat(proxy-fitness): pool fitness registry + Smart rotation + pool-scoped retry
Pool/IP fitness registry (globalThis-backed, provider::model scopes, 5-min
cooldown, provider::* wildcard) fed by pool-scoped failures: freebuff
limited-IP / model-locked gates and opencode free per-IP limits. chatCore
retries a failed pool via another pool without locking the account; new
Smart rotation strategy (per-connection + no-auth providers) skips unfit
pools. Proxy Fitness dashboard page: active-block table with provider/IP
filters, per-record Clear and provider-scoped Clear All; egress column via
pool geo enrichment. Unit tests for the registry.
2026-08-07 03:51:19 +08:00
decolua 6498b3122f feat(combos): wire capacity adapter into chat handler routing
- detectRequiredCapabilities: infer audioInput/videoInput from block
  type and embedded mime, not just vision/pdf
- handleChat / handleSingleModelChat: augment combo and single-model
  routing with capacity-adapter models when the target lacks a
  required capability, wrapped with history stripping for the
  adapter model's context window
2026-08-05 16:12:55 +07:00
decolua 13ed14568d fix(claude): remove global header cache, gate anthropic-beta by model
The global claudeHeaderCache singleton overlaid the last-seen Claude Code
client's identity headers onto every subsequent request, leaking one
client's headers (anthropic-beta, user-agent, x-stainless-*, etc.) onto
another client/account sharing the same server. Removed the singleton and
the claudeOverlay hook entirely, falling back to static per-provider
headers. anthropic-beta is now computed per-request from the requested
model, gating heavy-agent flags (advanced-tool-use, effort) to
opus/sonnet only.
2026-08-05 11:32:14 +07:00
Phuong Lambert 783e271c16 feat(gemini): add Gemini 3.6 Flash tier routing and 3.5 Flash Lite
Add gemini-3.6-flash tiered (high/medium/low) for Antigravity routing
via upstreamModelId "gemini-3.6-flash-tiered(level)" + thinkingLevel,
plus gemini-3.6-flash and gemini-3.5-flash-lite direct API models.

- getModelUpstreamId: split (level) suffix before lookup, re-append after
- Antigravity executor: preserve transformed body.model
- MITM extractModel: parse thinkingLevel for tiered model (default medium)
- Isolate Cloud Code endpoints: discovery (loadCodeAssist/onboardUser/
  quota) on PROD cloudcode-pa, chat transport on daily-cloudcode-pa
  to bypass prod 429
2026-07-23 16:34:24 +07:00
decoluaandCursor a625ea9fd8 refactor(log): unify request lifecycle logging with session-colored tags
Collapse scattered per-request console lines (request/routing/auth/pending/
usage/stream-usage/stream) into 3 correlated lines: request, transform,
done. Add stable per-session color tag so concurrent request lines are
easy to follow, surface thinking intent, always-on full error logging
for debug, re-enable warn level, and uppercase keyword labels. Also fix
usage overview cards wrapping (5 cards -> grid-cols-5).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 18:01:20 +07:00
Elio Bonfim Júnior dcf1927f22 feat(pxpipe): PXPIPE token saver — multimodal prompt compression (#2465)
Add pxpipe as an experimental fifth Token Saver: Claude-format request
bodies above a configurable size threshold are rendered as dense PNGs
via the pxpipe-proxy library API (transformAnthropicMessages) before
dispatch, cutting estimated input tokens by ~35-60% on token-dense
contexts. Integration follows the Headroom pattern: applied to the final
body in chatCore just before dispatch, fail-open on any error/timeout.

Managed npm install into DATA_DIR/pxpipe, dynamic loader with per-version
cache-bust, JSONL event log with rotation, /api/pxpipe/* endpoints, Token
Saver card (marked experimental) + /dashboard/pxpipe page, and per-request
Activated/Skipped annotation in Request Details. Disabled by default.
2026-07-10 16:10:42 +07:00
Carmelo CamposandCursor 50ed79fe9e fix(headroom): support Docker sidecar proxy
Treat configured Headroom proxy as running when its /health endpoint
responds, even if local headroom CLI is not installed. Dashboard
Start/Stop stays limited to local loopback proxies while external
Docker sidecars can be enabled via HEADROOM_URL.

Closes #1948

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 17:45:27 +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
WARELIKandCursor 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
Daniil SchovkunovandCursor 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
Kevin LeandCursor 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
Abhishek Divekar 3f17ee0e21 Add sticky round-robin for combos (#831)
Made-with: Cursor
2026-05-01 16:36:36 +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 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 3b1a608e8d Fix codex cache session id 2026-04-13 15:52:01 +07:00
decolua 4c28a1671d Enhance provider models and chat handling with new thinking configurations 2026-04-13 12:04:57 +07:00
kwanLeeFrmVi 1c160cc8d9 feat(claude-code): spoof TLS fingerprint and stabilize headers for Anthropic
- Add claudeHeaderCache.js to intercept and cache live Claude Code client headers
- Forward cached headers dynamically to api.anthropic.com via default.js
- Strip first-party identity headers (x-app, claude-code-* beta) for non-Anthropic upstreams
- Validate and sanitize tool call IDs to match Anthropic pattern (^[a-zA-Z0-9_-]+$)
- Skip thinking blocks when applying cache_control; fix max_tokens buffer (+1024)
- Strip cache_control from thinking blocks in openai-to-claude translator
- Comment out thoughtSignature in Gemini translator (kept for reference)
- Expand .gitignore to match all deploy*.sh variants

Co-authored-by: kwanLeeFrmVi <quanle96@outlook.com>
Closes #433

Made-with: Cursor
2026-03-30 16:27:28 +07:00
Ryan 037d013af8 fix: skip disabled providers in combo fallback instead of returning 406 (#336)
When a provider has credentials but all are disabled, return 404 (NOT_FOUND)
instead of 400 (BAD_REQUEST). The combo handler already treats 404 as a
fallbackable error, so it will skip to the next model in the chain.

Previously, the 400 status caused the combo to stop with a hard error,
killing the client (e.g., Claude Code) even though other models in the
combo chain were available.

Also changed log level from error to warn since disabled credentials
are an expected configuration state, not an error.

Fixes #334
2026-03-23 10:25:35 +07:00
decolua 3e694a383f feat(combos): add per-combo round-robin strategy
Add ability to configure round-robin strategy for individual combos,
similar to per-provider strategy overrides.

Changes:
- Add comboStrategies setting to store per-combo strategy overrides
- Add Round Robin toggle to each combo card in combos page
- Update chat handler to check combo-specific strategy before global
- Combo-specific strategy takes precedence over global comboStrategy

When enabled, each request to that combo will cycle through providers
instead of always starting with the first one.

Made-with: Cursor
2026-03-23 10:08:24 +07:00
bitgineerandAntigravity Agent 96f5e5c92a Add combo round-robin strategy to distribute load across providers (#390)
- Add comboRotationState Map to track rotation per combo
- Add getRotatedModels() to rotate model order based on strategy
- Pass comboName and comboStrategy to handleComboChat()
- Add comboStrategy setting (default: fallback)
- Add UI toggle for Combo Round Robin in profile settings

When enabled, each request to a combo starts with a different provider
instead of always starting with the first one, distributing load evenly.

Co-authored-by: Antigravity Agent <antigravity@example.com>
2026-03-23 09:52:31 +07:00
decolua adae2605bf Feat : Auto restart after crash 2026-03-14 09:37:29 +07:00
decolua 373b10ebb5 feat(chat): Enhance bypass handling and introduce CC filter naming feature
Fix : Ollam Provider response
2026-03-13 09:41:40 +07:00
decolua b0c6b61398 Refactor config 2026-03-12 16:20:46 +07:00
decolua fe49b61dfb feat: - Introduced per-provider strategy overrides in settings, allowing for more flexible connection management.
- Added new provider models: DeepSeek 3.1, DeepSeek 3.2, and Qwen3 Coder Next.
- Implemented UI changes to support round-robin strategy with sticky limits in the provider detail page.
- Improved logging to display connection names instead of IDs for better clarity.
2026-03-11 18:04:38 +07:00
decolua 50990e84b4 Fix AG MITM 2026-03-01 18:40:55 +07:00
decolua a7365c5a4e Fix : Codex on cursor 2026-03-01 15:35:41 +07:00
gen 5a015e5b4d feat(proxy): add outbound HTTP proxy support for OAuth + provider requests
- Patch Node fetch via undici ProxyAgent when HTTP_PROXY/HTTPS_PROXY/ALL_PROXY is set
- Ensure proxy patch is loaded for both chat pipeline and OAuth token exchange
- Add Dashboard Settings → Network to edit outbound proxy and apply immediately
- Persist outbound proxy settings in local db and initialize on server startup
- Move proxy helpers to src/lib/network/ for better structure
- Rename src/proxy.js → src/dashboardGuard.js to avoid naming confusion
- Re-apply proxy env after DB import
- Fix: close old dispatcher on proxy URL change to prevent connection pool leak
- Fix: idempotency guard to avoid patching globalThis.fetch multiple times

Made-with: Cursor
2026-02-28 10:11:53 +07:00
decolua 833069caac Fix MITM on window 2026-02-28 10:04:57 +07:00
QuanandCursor 07717bad60 feat: cherry-pick PR #183 — multi-provider support, PWA, dynamic models, UI improvements
Cherry-picked from decolua/9router PR #183.
Note: open-sse changes included but need further review due to extensive modifications.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-25 11:40:50 +07:00
zx07 ea67742f2a feat: implement real project ID fetching for Antigravity (#170)
* feat: implement Project ID service to fetch and cache real Project IDs from Google Cloud Code API

* fix: implement caching and cleanup for Project ID retrieval

* feat: add project ID invalidation and refresh logic after token updates

* refactor: remove unnecessary format changes

* feat: add on-demand project ID retrieval for antigravity requests
2026-02-21 23:15:18 +07:00
decolua 4cf25dc53d feat: implement API key requirement toggle 2026-02-18 13:46:14 +07:00
Nick Roth 202fee714b feat(auth): add model-level rate limit locking for multi-bucket providers (#120)
Providers like Antigravity maintain separate quota buckets per model family
(e.g. Claude vs Gemini). A 429 on claude-opus previously locked the entire
account, preventing gemini-pro requests even though its quota was full.

This adds in-memory per-model locking so that only the specific model is
skipped during account selection while other models remain accessible.

Changes:
- Add model-aware lock tracking in auth.js (Map<connectionId:model, expiry>)
- Pass model context from chat handler to auth service
- Multi-bucket behavior gated to known providers (MULTI_BUCKET_PROVIDERS set)
- No database schema changes — locks are in-memory and clear on restart

Closes #110
2026-02-15 11:35:13 +07:00
Blade096andCursor 1ae4e311b7 feat: add GLM Coding (China) provider and Usage by API Keys statistics
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 15:44:08 +07:00
Diego SouzaandCursor 3d439839d9 feat(cloud): harden sync/auth flow, SSE fallback, and update changelog
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 16:45:31 +07:00
decolua bdbe8162e7 feat(provider): add free providers and enhance error handling 2026-02-07 11:17:06 +07:00
HellodebasishsahuandCursor 127475df84 feat(codex): add GPT 5.3, fix API translation, add thinking levels
- Add GPT 5.3 Codex model with thinking level variants (none/low/medium/high/xhigh)
- Extract thinking level from model name suffix (e.g., gpt-5.3-codex-high)
- Fix Codex translation: preserve openai-responses format for Droid CLI
- Add effort level logging in request logs

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-06 09:46:11 +07:00
decolua c208f244ee Enhance chat handling. 2026-01-14 15:42:38 +07:00
Catalin StanciuandClaude Sonnet 4.5 9c3d6f4ad8 feat: implement usage tracking for AI requests
Adds local token usage tracking for all AI providers. Usage data is
captured during stream processing and stored in a local database.
Includes a new Usage tab in the Providers dashboard to visualize
historical token consumption.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 17:23:28 +07:00
decolua 18533505ef refactor: restructure translator from from-openai/to-openai to request/response folders 2026-01-09 17:14:51 +07:00
decolua 3857598de4 Initial commit 2026-01-05 09:58:59 +07:00