Skip to content

Releases: erans/lunaroute

v0.2.0

17 Apr 18:53

Choose a tag to compare

Codex CLI WebSocket Support for /responses (#37)

Codex CLI can now talk to LunaRoute over WebSockets. When Codex is configured with supports_websockets = true, it opens a WS upgrade on GET /v1/responses (or GET /responses for base URLs without /v1), and LunaRoute terminates the WS, drives the existing HTTP Responses pipeline upstream (stream=true always), and translates SSE events back as WS text frames.

What's included

  • GET handlers on /v1/responses and /responses that accept WS upgrades
  • Full feature parity with the HTTP path: session recording, LUNAROUTE markers (same-dialect), metrics, provider registry, codex_auth, header filtering
  • Sequential in-flight per connection; terminal-event detection; structured error frames for malformed/unsupported client frames
  • New Prometheus metrics:
    • lunaroute_ws_connections_opened_total, lunaroute_ws_connections_closed_total
    • lunaroute_ws_connection_duration_seconds
    • lunaroute_ws_frames_total{endpoint,direction,type} — labels use parsed Responses event types (response.create, response.completed, …) plus malformed_json, unsupported_event_type, invalid_request, binary, error, message

Codex configuration

openai_base_url = "http://localhost:8081/v1"

[model_providers.openai]
name = "OpenAI"
base_url = "http://localhost:8081/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
supports_websockets = true

Setting supports_websockets = false (or omitting it on older Codex versions) continues to use HTTP POST /v1/responses with SSE — fully supported.

Tests

  • Integration tests covering: WS event streaming with session recording, sequential in-flight, error frames for unsupported event types, /responses compat path
  • Unit tests for the frame parser and metric-label precedence
  • Full test suite: 937 pass, 0 fail, 43 ignored

Also in this release

  • fix: stabilize tool_mapper cleanup test under tarpaulin — a timing-sensitive test that flaked under tarpaulin's instrumentation now uses a 1s TTL margin.
  • chore: ignore .worktrees directory — Git worktrees created under .worktrees/ no longer show up in status.

Full Changelog: v0.1.12...v0.2.0

v0.1.12

04 Apr 05:26

Choose a tag to compare

Cross-Dialect Marker Routing: Anthropic → OpenAI Translation (#35)

Adds cross-dialect routing: Anthropic-format requests can now be routed to OpenAI-type providers via LUNAROUTE markers (e.g., Claude Code → Kimi K2.5 on Cloudflare). Supports both streaming (SSE with synthetic message_start) and non-streaming paths. Normal same-dialect passthrough is unchanged — zero additional cost.

How it works

When messages_passthrough() detects a marker targeting an OpenAI-type provider:

  1. Parse raw Anthropic JSON → AnthropicMessagesRequest
  2. Normalize via to_normalized()NormalizedRequest
  3. Send through OpenAIConnector.send()/.stream() via the Provider trait
  4. Convert response back via from_normalized() / stream_event_to_anthropic_events()

Tests

  • Round-trip test: Anthropic JSON → normalize → Anthropic JSON preserves content
  • Tool use round-trip: tool_use/tool_result survives normalization
  • Stream event conversion: NormalizedStreamEvent → Anthropic SSE events
  • Error SSE event serialization
  • Model override ordering verification
  • Full test suite passes (132 unit + 19 integration)

Full Changelog: v0.1.11...v0.1.12

v0.1.11

04 Apr 00:09

Choose a tag to compare

LUNAROUTE Marker-Based Provider Routing (#34)

Add [LUNAROUTE:provider_name] marker detection in passthrough request bodies to dynamically route requests to named providers. This enables Claude Code users to switch providers on-the-fly via a #!provider command (e.g., #!sonnet) without restarting sessions or changing configuration.

  • Marker-based routing: [LUNAROUTE:provider_name] markers in request bodies trigger dynamic provider switching
  • Arbitrary named providers: Config supports extra providers via serde(flatten) with optional model override
  • Both dialects: Marker detection integrated into both Anthropic and OpenAI passthrough handlers
  • Clean forwarding: Markers are stripped before forwarding to upstream providers
  • Session observability: Tags added for tracking (lunaroute:<provider>, model_override:<model>)
  • Error handling: Unknown providers fall back to default; cross-dialect mismatch returns HTTP 400

Tests

  • 19 unit tests for marker extraction and stripping
  • 3 integration tests for full extract→strip→override flow
  • 4 config validation tests

Update Minimum Rust Version to 1.94.0 (#33)

  • Bump rust-version in workspace Cargo.toml from 1.90 to 1.94
  • Update CI check job toolchain pin from 1.90 to 1.94

Full Changelog: v0.1.10...v0.1.11

v0.1.10

11 Mar 20:42

Choose a tag to compare

🌕 LunaRoute v0.1.10 - Provider Switch Notifications & Stability

Release Date: March 11, 2026


🎉 What's New

🔔 Provider Switch Notifications (#23)

LunaRoute can now automatically notify users when their request is routed to a different provider due to rate limits, errors, or circuit breaker events.

  • Automatic user notifications via injected LLM message
  • Global on/off with per-provider customization
  • Template variable substitution: ${original_provider}, ${new_provider}, ${reason}, ${model}
  • Cross-dialect failover (OpenAI ↔ Anthropic)
  • Idempotent - prevents duplicate notifications in cascading fallbacks
  • Zero overhead when disabled

Configuration Example:

routing:
  provider_switch_notification:
    enabled: true
    default_message: |
      IMPORTANT: Please inform the user that due to temporary service constraints,
      their request is being handled by an alternative AI service provider.
      Continue with their original request.

providers:
  anthropic-backup:
    type: "anthropic"
    switch_notification_message: |
      IMPORTANT: Using Claude (${model}) due to ${reason}.
      Quality remains the same. Continue with their original request.

⚡ Response-Side Gzip Compression for Passthrough Mode

Passthrough mode now supports response-side gzip compression, reducing bandwidth usage for proxied responses.


📊 Improved Analytics Chart Tooltips

Analytics charts now display detailed model statistics in tooltips for better visibility into usage patterns.


🐛 Bug Fixes

  • Fix streaming passthrough hang caused by gzip-compressed SSE responses
  • Fix transparent proxying for Claude Code passthrough mode
  • Fix Windows SQLite path parsing in UI server and import (#25) — uses SqliteConnectOptions::new().filename() instead of URL-based connection strings that fail with Windows backslash paths
  • Fix flaky test by flushing tokio file writes in session recorder
  • Fix build for reqwest 0.13: rename rustls-tls feature to rustls

📦 Dependency Updates

  • Update reqwest from 0.12 to 0.13 (#27)
  • Update mockall from 0.13 to 0.14 (#22)

📝 Changes

Pull Requests

  • feat: Add provider switch notification feature (#23) by @erans
  • Fix Windows SQLite path parsing in UI server and import (#25) by @njt
  • Update reqwest requirement from 0.12 to 0.13 (#27) by @dependabot
  • Update mockall requirement from 0.13 to 0.14 (#22) by @dependabot

Commits

  • d1ab5b0 Fix build: rename rustls-tls feature to rustls for reqwest 0.13
  • 5aae1a5 Add response-side gzip compression to passthrough mode
  • fe82d41 Fix flaky test by flushing tokio file writes in session recorder
  • 31b756d Fix streaming passthrough hang caused by gzip-compressed SSE
  • deacd81 Fix transparent proxying for Claude Code passthrough mode
  • fea0f97 Fix Windows SQLite path parsing in UI server and import
  • a6d1f38 Improve analytics chart tooltips with detailed model statistics
  • d3dfb38 Wire provider switch notification config to Router in server
  • b9f434f docs: add provider switch notification section to README
  • 95c5b3f docs: add example config for provider switch notifications
  • 7e8141d test: add comprehensive provider switch notification integration tests
  • f854f51 feat: integrate notification injection into provider switching logic
  • 29e5bb6 feat: implement Phase 4 router integration for provider switch notifications
  • fd6c1a0 feat: implement idempotency guard for notifications
  • 924cfa9 feat: implement notification message builder
  • a47cda7 feat: implement template variable substitution
  • 667193c feat: add switch_notification_message to provider configs
  • be49c05 feat: add provider_switch_notification to RoutingConfig
  • fb5fe3c feat: export notification module
  • f749eb3 feat: add ProviderSwitchNotificationConfig struct
  • d1dfc38 feat: add SwitchReason enum for provider switch notifications
  • a7246cd Add design document for provider switch notification feature
  • 831a521 Update reqwest requirement in the dependencies group
  • fcdd534 Update mockall requirement from 0.13 to 0.14

📦 Installation

Download for your platform:

  • Linux AMD64: lunaroute-server-linux-amd64-0.1.10
  • Linux ARM64: lunaroute-server-linux-arm64-0.1.10
  • macOS AMD64: lunaroute-server-darwin-amd64-0.1.10
  • macOS ARM64: lunaroute-server-darwin-arm64-0.1.10
  • Windows AMD64: lunaroute-server-windows-amd64-0.1.10.exe
  • Windows ARM64: lunaroute-server-windows-arm64-0.1.10.exe

Or build from source:

git clone https://github.com/erans/lunaroute.git
cd lunaroute
git checkout v0.1.10
cargo build --release --package lunaroute-server

🐛 Bug Reports & Feedback


Full Changelog: v0.1.9...v0.1.10

🌕 Happy coding with full visibility!

LunaRoute - Your AI Coding Assistant's Best Friend

v0.1.9

14 Nov 22:54

Choose a tag to compare

Maintenance Release

Bug: Fix stats when session go over date lines.

v0.1.8

01 Nov 00:10

Choose a tag to compare

🌕 LunaRoute v0.1.8 - One-Command Setup

Release Date: October 31, 2025


🎉 What's New

⚡ One-Command Setup with env Command

Getting started with LunaRoute is now incredibly simple:

eval $(lunaroute-server env)

That's it! This single command:

  • ✅ Starts the server in the background (detached process)
  • ✅ Configures Claude Code (ANTHROPIC_BASE_URL)
  • ✅ Configures Codex CLI (OPENAI_BASE_URL)
  • ✅ Enables both OpenAI and Anthropic APIs simultaneously
  • ✅ Tracks every token, tool call, and conversation

Example Usage:

# Basic usage - starts on port 8081
eval $(lunaroute-server env)

# Custom port
eval $(lunaroute-server env --port 8090)

# Stop the server
pkill -f "lunaroute-server serve"

🔄 Dual-Dialect Passthrough by Default

Zero configuration required! LunaRoute now defaults to both APIs:

  • OpenAI format: /v1/chat/completions
  • Anthropic format: /v1/messages
  • Zero normalization: Direct passthrough (~0.1-0.2ms latency)
  • 100% API fidelity: Preserves all response fields including extended thinking
  • Intelligent routing: gpt-* → OpenAI, claude-* → Anthropic

Before: Required explicit configuration or defaulted to Anthropic-only
Now: Both APIs enabled by default with intelligent routing


📊 Session Recording Enabled by Default

Full session tracking now works out of the box:

JSONL Writer (~/.lunaroute/sessions/)

  • Human-readable newline-delimited JSON
  • Complete request/response data per session
  • Perfect for debugging and manual inspection

SQLite Writer (~/.lunaroute/sessions.db)

  • Fast queries and analytics
  • Session metadata, tokens, performance metrics
  • Web UI integration at http://localhost:8082

What you get automatically:

  • 📊 Token tracking (input, output, thinking)
  • 🔧 Tool call logging (which tools, when, how long)
  • 💰 Cost estimation per session
  • 📈 Performance metrics (latency, overhead)
  • 🔍 Searchable conversation history

🚀 Quick Start

New Users

# Download and extract
tar -xzf lunaroute-server-*.tar.gz
chmod +x lunaroute-server

# One command to start everything
eval $(lunaroute-server env)

# Done! Both Claude Code and Codex CLI work immediately
# View sessions at http://localhost:8082

Existing Users

No breaking changes! All configurations continue to work.

New defaults when running without config:

  • ✅ Both API dialects enabled (was: Anthropic only)
  • ✅ Session recording enabled (JSONL + SQLite)
  • ✅ Access to new env command

To opt out of session recording:

session_recording:
  enabled: false

📦 Installation

Download for your platform:

  • Linux AMD64: lunaroute-server-linux-amd64-0.1.8
  • Linux ARM64: lunaroute-server-linux-arm64-0.1.8
  • macOS AMD64: lunaroute-server-darwin-amd64-0.1.8
  • macOS ARM64: lunaroute-server-darwin-arm64-0.1.8
  • Windows AMD64: lunaroute-server-windows-amd64-0.1.8.exe
  • Windows ARM64: lunaroute-server-windows-arm64-0.1.8.exe

Or build from source:

git clone https://github.com/erans/lunaroute.git
cd lunaroute
git checkout v0.1.8
cargo build --release --package lunaroute-server

🔧 Technical Details

Performance

  • Dual-dialect mode: 0.1-0.2ms latency (P95 < 0.5ms)
  • Session recording: 0.5-1ms async (non-blocking)
  • Memory: ~2MB baseline + ~1KB per request

Compatibility

  • ✅ Claude Code - Full passthrough support
  • ✅ OpenAI Codex CLI - Automatic auth integration
  • ✅ OpenCode - Standard API compatibility
  • ✅ Custom clients - Any OpenAI/Anthropic compatible tool

Testing

  • 858+ tests passing (0 failures)
  • 73.35% code coverage
  • 0 clippy warnings

📝 Changes

Commits: f947b41, 255dd6b

New Features:

  • Add lunaroute-server env command for one-command setup
  • Dual-dialect passthrough now the default (ApiDialect::Both)
  • Session recording (JSONL + SQLite) enabled by default
  • Both OpenAI and Anthropic providers enabled by default in passthrough mode

Documentation:

  • Complete README rewrite (44% reduction, better clarity)
  • Prominent one-command setup sections
  • Comprehensive env command documentation

Technical:

  • Server detaches from terminal on Unix systems
  • Health check verification before returning
  • Backward compatible with all existing configurations

🐛 Bug Reports & Feedback


🌕 Happy coding with full visibility!

LunaRoute - Your AI Coding Assistant's Best Friend

v0.1.7

29 Oct 02:59

Choose a tag to compare

What's Changed

  • Add limits-alternative routing strategy for automatic rate limit failover by @erans in #21

Full Changelog: v0.1.6...v0.1.7

v0.1.6

28 Oct 17:14

Choose a tag to compare

What's Changed

  • Add smart bypass feature for non-intercepted API paths by @erans in #20

Full Changelog: v0.1.5...v0.1.6

v0.1.5

23 Oct 19:14

Choose a tag to compare

What's Changed

  • Fix #18: Increase pool_idle_timeout from 50s to 600s (10 minutes) by @erans in #19

Full Changelog: v0.1.4...v0.1.5

v0.1.4

23 Oct 17:50

Choose a tag to compare

What's Changed

  • Fix #14: Filter Authorization header when using configured API key in Anthropic passthrough by @erans in #17

Full Changelog: v0.1.3...v0.1.4