Commit Graph
133 Commits
Author SHA1 Message Date
MythEclipseandClaude Opus 4.8 9a379d09b5 feat: add CastAI/Kimchi model routes via llm.kimchi.dev
Add 5 free Kimchi-dev models through CAST AI gateway:
- minimax-m3, minimax-m2.7
- kimi-k2.6, kimi-k2.7
- nemotron-3-ultra-fp4
- castai-auto (generic -> minimax-m3)

Key details:
- Endpoint: https://llm.kimchi.dev/openai/v1/chat/completions
- Required: User-Agent: kimchi/0.1.41 header
- API key hardcoded from Kimchi CLI config (for Vercel/CF deploy)
- Native SSE streaming passthrough

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 01:14:18 +07:00
3505165a3b feat: tambah konfigurasi observability Wrangler untuk konsistensi deployment (#3)
- Aktifkan logging dengan persist & invocation_logs
- Aktifkan tracing dengan persist
- Observability dashboard dimatikan (enabled: false)
- Sampling rate 100% (head_sampling_rate: 1)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:37:04 +07:00
MythEclipseandClaude Opus 4.8 eec0cd5088 feat: tambah DSML parser untuk konversi tool_calls DeepSeek ke format standar
DeepSeek models mengembalikan tool calls dalam format DSML (DeepSeek
Markup Language) di dalam text content, bukan sebagai JSON structured
tool_calls. Ini menyebabkan tool calling gagal di Claude Code.

Perubahan:
- Buat src/lib/dsml-parser.ts: parser DSML berbasis regex dengan dukungan
  streaming (DSMLAccumulator), deteksi teks sebelum/sesudah DSML, dan
  parsing parameter JSON
- Forward tools/tool_choice dari client ke backend di Anthropic & OpenAI paths
- Konversi DSML ke tool_use content blocks (Anthropic) atau tool_calls array
  (OpenAI) di response non-streaming
- Handle DSML di streaming: buffer text deltas, deteksi di akhir stream,
  emit tool_use/tool_calls events yang sesuai
- Handle tool_result blocks dari Anthropic format di assistant messages
- Tambah 29 tests untuk parser dan 18 tests untuk anthropic-proxy

Fix: #285 tests pass, 0 fail
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:25:02 +07:00
MythEclipseandClaude Opus 4.8 abc8d9d7d5 fix: izinkan content null pada assistant messages dalam validasi
Assistant messages dengan tool_calls punya content:null,
sebelumnya di-reject dengan error 'messages[N].content is required'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:53:28 +07:00
MythEclipseandClaude Opus 4.8 ff330e030e chore: hapus model scraping dari surfsense dan aichat.org
- Hapus model route gpt-5.4-mini-no-login (surfsense.com)
- Hapus 9 model route aichat.org (deepseek/deepseek-v4-flash, dll.)
- Hapus file aichat-auth.ts beserta session/CSRF auth
- Hapus kode auth injection, retry, dan cookie refresh aichat dari handleChatCompletion
- Update SSE passthrough check untuk hanya opencode + mimo-free
- Update komentar header

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 18:47:47 +07:00
Asep Haryana SaputraandGitHub c8ec62c345 fix: unwrap double-nested opencode.ai + handle reasoning_content in Anthropic handler
Two fixes for deepseek-v4-flash-free via Anthropic protocol:

1. **Non-streaming**: Apply config.adaptResponse to unwrap double-nested opencode.ai JSON response before backendToAnthropicResponse
2. **Streaming**: Extract delta.reasoning_content from DeepSeek SSE chunks wrapped in <thinking> tags

All tests pass, verified locally with both streaming and non-streaming.
2026-06-25 01:22:40 +07:00
MythEclipseandClaude Opus 4.8 fc69a0e93c refactor: konsolidasi handler ke router.ts + complexity + test coverage
=== DRY Konsolidasi ===
- handleRelay, requireAuth, handleHealth, handleIndex, getClientIP → 1x di src/lib/router.ts
- api/relay.ts, src/worker.ts, src/index.ts jadi thin wrapper

=== Dead exports ===
- 35 dead exports dibersihkan (dari router.ts, worker.ts, relay.ts)
- Duplikasi simbol dari 12 ke 3 (wajar)

=== Keamanan ===
- Default API key sk-dummy-key dihapus — requireAuth return null saat key kosong
- Semua CORS konsisten via getCorsHeaders()

=== Kompleksitas ===
- handleRequest → pecah ke validateRelayTarget, createJsonErrorResponse, dll
- transformAnthropicStream (170 baris) → 4 sub-fungsi (emitInitEvents, emitDoneEvents, etc)
- handleAnthropicMessages → handleUpstreamError, buildStreamHeaders, buildJsonHeaders
- Fix duplicate stream? field di AnthropicRequest interface

=== Test Coverage ===
- Test naik dari 171 ke 248 (+77 test)
- File baru: src/router.test.ts (requireAuth, getClientIP, CORS, health, index)
- File baru: src/relay-integration.test.ts (filterResponseHeaders, shouldSendBody, buildRelayRequest, classifyFetchError, createRelayResponse, normalizeTargetUrl, SSRF, isPrivateIp)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 23:48:16 +07:00
MythEclipseandClaude Sonnet 4.6 db281c5175 fix: unwrap double-nested opencode.ai responses in proxy
opencode.ai returns the real OpenAI-compatible response as a JSON string
inside choices[0].message.content instead of an object. Added an
adaptResponse handler that detects and unwraps this double-nesting,
merging inner usage/token counts and reasoning_content into the
standard envelope.

Also added build/ to .gitignore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 22:19:12 +07:00
MythEclipseandClaude Opus 4.8 b69f252f37 fix: remove stray 't' chars causing syntax errors in type definitions
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 21:35:58 +07:00
MythEclipseandClaude Opus 4.8 84e7d89a75 fix: hybrid default export to satisfy Vercel/Node and Bun/Workers contracts
- Export handler as default function for Vercel Serverless Function runtime.
- Attach fetch method to default export object for Bun and Cloudflare Workers compatibility.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 20:59:00 +07:00
MythEclipse ee989f72bf Merge branch 'fix/anthropic-protocol' 2026-06-24 20:47:49 +07:00
MythEclipseandClaude Opus 4.8 d1d6f607b0 fix: Vercel serverless function crash and await async completions routes
- Make generateDeviceFingerprint resilient to os.cpus() and os.hostname() returning empty or throwing in lambda sandboxes.
- Await async handleChatCompletion and handleAnthropicMessages calls in route handlers to prevent unhandled promise rejections.
- Catch runtime exceptions from completions and return clean HTTP 500 JSON error responses.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 20:40:09 +07:00
MythEclipse 57f8889573 chore: update bun.lock to match simplified package.json 2026-06-24 20:25:21 +07:00
Asep Haryana SaputraandGitHub ba2b2db851 Merge pull request #1 from MythEclipse/fix/anthropic-protocol
fix: anthropic messages validation, stream mapping, client error pars…
2026-06-24 20:19:29 +07:00
MythEclipseandClaude Opus 4.8 2171a01974 fix: anthropic messages validation, stream mapping, client error parsing, and add Cloudflare Workers deployment workflow
- Fix type mappings in OpenAIRequest and BackendConfig to handle structured message parts (cache-control).
- Stop adaptRequest crashing when message contents are objects or arrays.
- Forward stream, top_k, and stop_sequences to adaptRequest.
- Forward anthropic-version header to backend endpoints during adaptation.
- Parse structured JSON error payloads from upstream before returning generic "Upstream rejected request" error.
- Create .github/workflows/cloudflare.yml to auto-deploy on master branch pushes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:37:23 +07:00
MythEclipse e58a3ddaf8 chore: update test page defaults to api.ipify.org 2026-06-24 18:33:24 +07:00
MythEclipse 6b9dd3770e refactor: extract test page to shared module, use env var for API key 2026-06-24 18:18:49 +07:00
MythEclipse d5f8dfc1d7 fix: auto-detect base URL from window.location.origin
- public/test-api.html: value di baseUrl input kosong, apiBase() fallback ke window.location.origin,
  plus DOMContentLoaded listener utk auto-fill
- api/test-api-content.ts: sama (legacy Next.js route)
- Router.ts handleDocs() sudah pakai pendekatan ini sebelumnya
2026-06-20 21:49:37 +07:00
MythEclipse 2f2aa08264 feat: replace docs placeholder with interactive test page across all entry points
- Replace router.ts handleDocs static placeholder with full interactive test page
- Replace worker.ts handleDocs with interactive test page
- Remove dead handleDocs() from index.ts (route already serves public/test-api.html)
- Update public/test-api.html with proper model defaults (deepseek-v4-flash-free)
- Add cache_control system prompt field to Anthropic test card
- Update handleIndex() to link to Interactive Test Page
- Remove handleDocs tests from index.test.ts
2026-06-20 21:44:15 +07:00
MythEclipse ccb1523692 feat: antropik cache — default anthropic-version, forward cache headers, model features, streaming usage, tests
- Auto-default anthropic-version to 2023-06-01 for prompt caching
- Forward cache headers (x-cache, cf-cache-status, age, etc.) from backend
- Add features: ["prompt_caching"] to /v1/models response
- Extract and report actual usage tokens in streaming message_delta
- Track output char count for token estimation when backend omits it
- Cache-aware usage reporting: cache_creation_input_tokens, cache_read_input_tokens
- Comprehensive tests for cache_control preservation in content blocks & system
2026-06-20 21:38:34 +07:00
MythEclipse 7bb1b443be feat: anthropic cache support — preserve cache_control, forward anthropic-version header, report real usage tokens
- Add anthropicPassthrough flag to BackendConfig for native Anthropic backends
- Preserve cache_control on content blocks and system prompt (keep structured)
- Extract and forward anthropic-version header from client to backend
- Report actual token usage from backend response (input_tokens, output_tokens)
- Support native Anthropic passthrough (no translation) for compatible backends
- Wire anthropic-version through all entry points: index.ts, router.ts, worker.ts
2026-06-20 21:34:31 +07:00
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 35c0123529 feat: expand IPv6 pool to 18 addresses (7 base + 11 ffff range) 2026-06-19 19:38:33 +07:00
MythEclipse 2ff31eabe7 fix: include workflow paths in build trigger 2026-06-19 19:13:19 +07:00
MythEclipse d447523bb1 fix: use SHA tags instead of latest for GHCR images 2026-06-19 19:12:23 +07:00
MythEclipse 2d3776b54b fix: lowercase GHCR image name 2026-06-19 19:11:38 +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
MythEclipse cb6191902e fix: critical bugs, serverless stability, and security hardening
Bug Fixes:
- Fix rate limiter API mismatch: check() -> checkAsync() in index.ts, worker.ts, api/relay.ts
- Fix WebSocket SSRF silent drop: return error Response instead of undefined
- Fix isDevMode() default: changed from true to false (production-safe)
- Fix process.env -> env bindings in worker.ts requireAuth for Cloudflare Workers
- Fix Bun.file() crash in Workers: add try/catch with fallback
- Fix Bun.CryptoHasher -> Web Crypto API in mimo-auth.ts for Workers compat

Architecture:
- Add public methods to ProxyPool (getEntryAtIndex, getProxyUrlAtIndex, getCurrentIndex, setCurrentIndex) to remove all 'as any' casts in SessionProxyPool
- Add addProxy() method for manual proxy management
- Add loadAsync(), tryLoadAsync(), loadFromString() to ProxyPool

Serverless Stability:
- Add optional DNS rebinding protection via SSRF_DNS_CHECK env flag
- CORS cache now auto-invalidates when CORS_ORIGIN env changes
- Rate limiter max-size eviction (10k keys) prevents unbounded memory growth

Tests:
- Fix type assertions in test files (body as Record<string, unknown>)
- All 153 tests pass, typecheck clean
2026-06-19 18:10:49 +07:00
MythEclipseandClaude 6d61dcba8f prioritas langsung baru proxy
Ubah strategi retry di fetchWithRetry dan fetchWithSessionRetry:
- Langsung (direct) sebagai percobaan pertama sebelum proxy pool
- Proxy sebagai fallback jika direct gagal

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-18 01:45:34 +07:00
MythEclipseandClaude ca8de1ba00 feat: migrate deepseek route to aichat.org with all models
- Replace broken deep-seek.ai endpoint with aichat.org relay
- Add AichatSession manager with cookie/CSRF bootstrap and auto-refresh
- Add exponential backoff retry (3 attempts) for session bootstrap
- Add all 9 aichat.org model routes via shared config (zero duplication)
- Session cookies auto-refreshed from Set-Cookie on every API response
- Auto-heal: 401 triggers session re-bootstrap + retry transparently

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-18 00:02:54 +07:00
MythEclipseandClaude 778180a5dc fix: inline test-api.html as TypeScript string export for Vercel
Bun import of .html files returns HTMLBundle (not a string) in Vercel's
serverless environment, and Bun.file() has no filesystem access there.
Copy the HTML content into api/test-api-content.ts as an escaped string
export, then import it in api/relay.ts — Bun bundler inlines it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 14:14:13 +07:00
MythEclipseandClaude f8fd18612b fix: use Bun.file().text() at module scope to inline test-api.html
Bun HTML import returns HTMLBundle object on Vercel serverless, which
renders as '[object HTMLBundle]'. Using Bun.file().text() at top-level
module scope ensures Bun bundler inlines the raw string at build time.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 13:54:13 +07:00
MythEclipseandClaude bcba2c5386 fix: use text import for test-api.html in Vercel deployment
Bun HTML import returns HTMLBundle object, not a string — Vercel
renders it as '[object HTMLBundle]'. Use 'with { type: "text" }'
to import as raw string so it renders properly.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 13:51:04 +07:00
MythEclipseandClaude bc6edbef3e fix: serve test-api.html at /docs on Vercel and Worker deployments
Update api/relay.ts (Vercel entry point) and src/worker.ts (Cloudflare
Workers entry point) to serve the interactive API test console at /docs
and /test, replacing the old inline docs page.

api/relay.ts uses Bun's HTML import (bundled inline at build time)
since filesystem access is unavailable in Vercel serverless runtime.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 13:37:23 +07:00
MythEclipseandClaude aa3f96ef2d refactor: merge /test into /docs, serve test-api.html publicly
Both /docs and /test now serve the API test console (public/test-api.html),
replacing the old inline docs page.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 13:28:43 +07:00
MythEclipseandClaude e4406b586e feat: add Xiaomi MiMo Free API provider (mimo-auto)
- Add mimo-auth.ts: JWT bootstrap with device fingerprint, cached auto-refresh, 401/403 invalidation
- Add mimo-auto entry to MODEL_ROUTES with anti-abuse system message injection
- Inject JWT auth + x-session-affinity header before Mimo API fetch
- Retry once on 401/403 (invalidate JWT, re-bootstrap)
- Extend SSE passthrough for mimo-free provider
- Strip 'data:' prefix from Mimo non-streaming responses

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 13:22:07 +07:00
MythEclipse 89f0ff0f32 a 2026-06-17 12:29:54 +07:00
MythEclipseandClaude 7cbf6fd817 feat: add per-model proxy cooldown for rate-limit handling
ProxyPool:
- Add cooldowns map (host:port::model -> expiry) and cooldownDuration (60s default)
- Add markRateLimited(model) — puts current proxy in cooldown for a model
- Add isProxyInCooldown, isIndexInCooldown, isCurrentInCooldown checks
- Modify rotate(model?) — skip proxies in cooldown for the given model
- Add setCooldownDuration(ms) for configuration

SessionProxyPool:
- Add markRateLimited(sessionId, model) — delegates to underlying pool
- Modify rotateNow(sessionId, model?) — skip cooldown proxies
- Modify acquire(sessionId, model?) — skip cooldown when picking least-loaded
- Modify pickLeastUsedIndex(model?) — skip cooldown proxies in scan

fetch-utils.ts:
- Add extractModel helper — extracts model from context string
- On HTTP 429: call markRateLimited(model) before markFailed
- Pass model to rotate() / rotateNow() / acquire() throughout

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:59:16 +07:00
MythEclipseandClaude 283ed26231 fix: exhaust all proxies then direct fallback before giving up
fetchWithRetry:
- Dynamically calculate maxAttempts = pool.size + 1 (direct fallback)
- Try every proxy in pool via rotation, then direct as last resort
- Only classify as error when even direct produces no response

fetchWithSessionRetry:
- Default maxRetries = sessionPool.size + 1 instead of hardcoded 3
- Try pool.size proxy attempts (each on a different proxy via rotateNow),
  then 1 direct attempt (no proxy) before giving up
- Only classify as error if direct also returns no response

ProxyPool.rotate():
- Skip proxies that have exceeded the failure threshold (isFailed)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:45:30 +07:00
MythEclipseandClaude f1943353ef fix: rotate proxy on every failure, return proper HTTP status
- Add rotateNow() to SessionProxyPool — force-rotate session to a
  different proxy immediately (excludes current index to ensure real
  rotation). Uses round-robin scan from oldIndex+1 so all proxies
  get used, not just bouncing between two.

- fetchWithSessionRetry: call rotateNow() on every failure instead of
  markFailed() which only rotated after threshold. Return last HTTP
  response (e.g. 429) instead of classifying as 502 when we have one.

- fetchWithRetry: rotate pool on every failure for consistency.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:40:45 +07:00
MythEclipseandClaude 9c2f0a65f0 feat: add request logging to AI proxy routes
- Log session ID, model, pool size, and active session count on every
  POST /v1/chat/completions and POST /v1/messages

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:30:07 +07:00
MythEclipseandClaude 45f1b33fb6 feat: add structured logging across proxy pool and fetch utils
- fetch-utils.ts: logProxy() — logs every attempt, proxy used, success/failure
  with sessionId prefix for traceability
- proxy-pool.ts: logPool() — logs acquire/release/rotate/markFailed/markSuccess
  with active session count and proxy host info
- Both use consistent [prefix] HH:MM:SS.mmm key=value format

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:29:31 +07:00
MythEclipseandClaude 519fe3af83 fix: proxy pool now actively distributes IPs across sessions
- fetchWithRetry: use proxy on every attempt (not just fallback after direct)
- fetchWithSessionRetry: call acquire() on attempt 0 so new sessions get
  a least-loaded proxy assigned, enabling IP spread across concurrent users
- Update docstrings to reflect new strategy

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-17 04:26:26 +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
MythEclipseandClaude 6c945dcbf4 feat: add API test page at /test endpoint
- New public/test-api.html — browser-based test UI for all proxy endpoints
- Health check, model listing, Chat Completions (stream+non-stream),
  Anthropic Messages (stream+non-stream), and generic HTTP relay
- Server serves /test route from public/test-api.html

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 22:58:17 +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 47b85fb396 chore: use hardcoded dummy API key
- Replace env-based API_KEY with sk-dummy-key hardcoded
- All entry points use same key: Authorization: Bearer sk-dummy-key
- Simplifies usage for library/client consumption

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:59:01 +07:00