Commit Graph
12 Commits
Author SHA1 Message Date
MythEclipse ac19f8f30d perf: stability and performance improvements across proxy
- Add exponential backoff (200ms-2s) between retry attempts
- Fix session retry bug: rotate proxy before retry to avoid same proxy
- Fix ACTIVE_READERS memory leak: release reader on stream done/error
- Make closeAllActiveReaders async with proper await
- WebSocket backpressure: pause upstream forwarding at 512KB buffer
- Optimize rate-limiter pruneTimestamps: avoid array reallocation
- Batch stream chunks (8 per yield) to reduce event loop overhead
- Add periodic cooldown cleanup in ProxyPool (30s interval)
- Extract shared wrapStreamWithCleanup utility to reduce duplication
- Fix fetchViaCurl temp file cleanup with proper unlink()
- Add missing ipv6Source overload to AI proxy handlers
2026-06-20 19:32:23 +07:00
MythEclipse c62de0899a fix: streaming reliability, timeout, memory leaks, and retry improvements
- Fix streaming timeout: use AbortController for connection-only timeout
  instead of AbortSignal.timeout() that kills active SSE streams
- Fix fetchViaCurl: stream body via ReadableStream instead of buffering
  entire response in memory
- Fix JWT/aichat race condition: add Promise dedup to prevent concurrent
  bootstrap calls (10 requests = 1 bootstrap, not 10)
- Fix ACTIVE_READERS memory leak: auto-remove readers on stream completion
- Fix WebSocket backpressure: log warning when client buffer exceeds 1MB
- Add SSE heartbeat/keepalive: send ': keepalive' every 15s to prevent
  LB/proxy timeout during AI thinking
- Fix SSELineBuffer: graceful overflow handling (warn + discard instead
  of throwing error that crashes stream)
- Fix transformStream tight loop: yield to event loop after each chunk
  to prevent starvation
- Fix fetchViaCurl process cleanup: use SIGKILL + proper timeout cleanup
- Add retry on 502/504: retry transient server errors before returning
  to caller (both fetchWithRetry and fetchWithSessionRetry)
2026-06-20 17:13:32 +07:00
MythEclipse 17338a7dca feat: IPv6 outbound rotation via curl --interface
- Add IPv6SourcePool for round-robin IP rotation
- fetchViaCurl: Bun.spawn + curl -6 --interface for source binding
- Auto-fallback to regular fetch when IPv6 connection fails
- Response decompression via --compressed flag
- Docker + GHCR build/deploy workflows
- 8 routable IPv6 addresses on VPS
2026-06-19 19:07:46 +07:00
MythEclipseandClaude 9bd6acddc5 feat: implement session-based sticky proxy pool with auto-failover
Add SessionProxyPool for per-session sticky proxy allocation with
load-balanced least-used selection and auto-rotation on failure.
Introduce fetchWithSessionRetry for transparent retry with proxy
rotation. Wire into AI proxy handlers (OpenAI + Anthropic) with
stream lifecycle cleanup.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 23:50:47 +07:00
MythEclipse b09bca8def feat(core): implement robust fetch utilities and stream management
Introduce a centralized `fetch-utils.ts` to handle retry logic with proxy fallback, SSE line buffering to prevent chunk-boundary corruption, and graceful shutdown via active reader tracking.

Key changes:
- Add `fetchWithRetry` for automatic direct-to-proxy failover.
- Implement `SSELineBuffer` to ensure reliable parsing of split SSE chunks.
- Add `createStreamBodyLimiter` to enforce payload limits on streaming requests.
- Refactor `ProxyPool` to decouple failure marking from rotation.
- Standardize CORS handling and environment variable configuration.
- Clean up documentation and remove obsolete skill files.
2026-06-11 03:56:26 +07:00
MythEclipse db065f788d style(anthropic-proxy): update comment formatting and add SSE utility functions
Standardize comment separators and arrow usage in documentation headers.
Additionally, introduce `accumulateSSEText` and `extractTextFromSSE` to
provide robust parsing for various SSE stream formats, including
Claude Code and OpenAI-compatible deltas.
2026-06-11 01:43:23 +07:00
MythEclipse 261f84a96e refactor(anthropic-proxy): improve SSE stream transformation logic
Refactor the backend-to-Anthropic SSE transformation to use a more robust
state machine approach. This replaces manual string building with a
structured phase-based system (`init`, `block`, `done`) to better
manage the Anthropic streaming protocol, including `message_start` and
`content_block_delta` events.

- Extract `formatContentBlockDelta` helper for consistent event formatting
- Implement phase-based state machine in `transformAnthropicStream`
- Delegate `[DONE]` handling to the stream transformer instead of
  manually emitting `message_stop`
- Improve reliability of message ID generation and event sequencing
2026-06-11 01:24:54 +07:00
MythEclipseandClaude Fable 5 2fead57d0f fix: use MODEL_ROUTES directly for Anthropic proxy routing
Remove the ANTHROPIC_MODEL_MAP layer — /v1/messages now uses the
same model names as /v1/chat/completions (deepseek-v4-flash-free,
gpt-5.4-mini-no-login, deepseek/deepseek-v4-flash). This way users
send the original model name and it routes to the correct backend.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:42:21 +07:00
MythEclipseandClaude Fable 5 2fca9febe4 fix: pass original model name to backend in Anthropic proxy
Use anthReq.model instead of backendModel so the backend receives
the user-sent model name (e.g. claude-sonnet-4) rather than the
internal mapped name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:20:20 +07:00
MythEclipseandClaude Fable 5 5974d31164 fix: avoid double markFailed in AI proxy retry loop
Response handler already calls markFailed() on non-2xx and network
errors (which rotates the proxy). The preamble at attempt >= 2 was
calling markFailed() again, double-rotating and skipping a proxy.
Changed preamble to use rotate() instead of markFailed().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:02:40 +07:00
MythEclipseandClaude Fable 5 2dfb87eac6 fix: retry AI proxy with next proxy on HTTP errors too
Previously only retried on network errors (fetch exceptions). Now also
rotates to next proxy when upstream returns non-2xx (429 rate limit,
5xx, etc). Applies to both OpenAI and Anthropic endpoints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:57:24 +07:00
MythEclipseandClaude Fable 5 4168a087a0 feat: add Anthropic-compatible AI proxy endpoint
- Create src/lib/anthropic-proxy.ts: accepts Anthropic Messages API
  format (POST /v1/messages) and routes to the same backend providers
- Anthropic model names (claude-sonnet-4, claude-3-haiku, claude-opus-4)
  map to backend models with full request/response translation
- Streaming (SSE) via Anthropic protocol: message_start,
  content_block_delta, message_stop events
- Add /v1/messages route to server with CORS and proxy pool fallback
- Reuses MODEL_ROUTES from ai-proxy.ts for consistent backend routing

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:08:32 +07:00