This release represents a comprehensive transformation of the codebase from Codex to LLMX, enhanced with LiteLLM integration to support 100+ LLM providers through a unified API. ## Major Changes ### Phase 1: Repository & Infrastructure Setup - Established new repository structure and branching strategy - Created comprehensive project documentation (CLAUDE.md, LITELLM-SETUP.md) - Set up development environment and tooling configuration ### Phase 2: Rust Workspace Transformation - Renamed all Rust crates from `codex-*` to `llmx-*` (30+ crates) - Updated package names, binary names, and workspace members - Renamed core modules: codex.rs → llmx.rs, codex_delegate.rs → llmx_delegate.rs - Updated all internal references, imports, and type names - Renamed directories: codex-rs/ → llmx-rs/, codex-backend-openapi-models/ → llmx-backend-openapi-models/ - Fixed all Rust compilation errors after mass rename ### Phase 3: LiteLLM Integration - Integrated LiteLLM for multi-provider LLM support (Anthropic, OpenAI, Azure, Google AI, AWS Bedrock, etc.) - Implemented OpenAI-compatible Chat Completions API support - Added model family detection and provider-specific handling - Updated authentication to support LiteLLM API keys - Renamed environment variables: OPENAI_BASE_URL → LLMX_BASE_URL - Added LLMX_API_KEY for unified authentication - Enhanced error handling for Chat Completions API responses - Implemented fallback mechanisms between Responses API and Chat Completions API ### Phase 4: TypeScript/Node.js Components - Renamed npm package: @codex/codex-cli → @valknar/llmx - Updated TypeScript SDK to use new LLMX APIs and endpoints - Fixed all TypeScript compilation and linting errors - Updated SDK tests to support both API backends - Enhanced mock server to handle multiple API formats - Updated build scripts for cross-platform packaging ### Phase 5: Configuration & Documentation - Updated all configuration files to use LLMX naming - Rewrote README and documentation for LLMX branding - Updated config paths: ~/.codex/ → ~/.llmx/ - Added comprehensive LiteLLM setup guide - Updated all user-facing strings and help text - Created release plan and migration documentation ### Phase 6: Testing & Validation - Fixed all Rust tests for new naming scheme - Updated snapshot tests in TUI (36 frame files) - Fixed authentication storage tests - Updated Chat Completions payload and SSE tests - Fixed SDK tests for new API endpoints - Ensured compatibility with Claude Sonnet 4.5 model - Fixed test environment variables (LLMX_API_KEY, LLMX_BASE_URL) ### Phase 7: Build & Release Pipeline - Updated GitHub Actions workflows for LLMX binary names - Fixed rust-release.yml to reference llmx-rs/ instead of codex-rs/ - Updated CI/CD pipelines for new package names - Made Apple code signing optional in release workflow - Enhanced npm packaging resilience for partial platform builds - Added Windows sandbox support to workspace - Updated dotslash configuration for new binary names ### Phase 8: Final Polish - Renamed all assets (.github images, labels, templates) - Updated VSCode and DevContainer configurations - Fixed all clippy warnings and formatting issues - Applied cargo fmt and prettier formatting across codebase - Updated issue templates and pull request templates - Fixed all remaining UI text references ## Technical Details **Breaking Changes:** - Binary name changed from `codex` to `llmx` - Config directory changed from `~/.codex/` to `~/.llmx/` - Environment variables renamed (CODEX_* → LLMX_*) - npm package renamed to `@valknar/llmx` **New Features:** - Support for 100+ LLM providers via LiteLLM - Unified authentication with LLMX_API_KEY - Enhanced model provider detection and handling - Improved error handling and fallback mechanisms **Files Changed:** - 578 files modified across Rust, TypeScript, and documentation - 30+ Rust crates renamed and updated - Complete rebrand of UI, CLI, and documentation - All tests updated and passing **Dependencies:** - Updated Cargo.lock with new package names - Updated npm dependencies in llmx-cli - Enhanced OpenAPI models for LLMX backend This release establishes LLMX as a standalone project with comprehensive LiteLLM integration, maintaining full backward compatibility with existing functionality while opening support for a wide ecosystem of LLM providers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Sebastian Krüger <support@pivoine.art>
116 lines
3.8 KiB
Bash
116 lines
3.8 KiB
Bash
#!/bin/bash
|
|
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
|
|
IFS=$'\n\t' # Stricter word splitting
|
|
|
|
# Read allowed domains from file
|
|
ALLOWED_DOMAINS_FILE="/etc/codex/allowed_domains.txt"
|
|
if [ -f "$ALLOWED_DOMAINS_FILE" ]; then
|
|
ALLOWED_DOMAINS=()
|
|
while IFS= read -r domain; do
|
|
ALLOWED_DOMAINS+=("$domain")
|
|
done < "$ALLOWED_DOMAINS_FILE"
|
|
echo "Using domains from file: ${ALLOWED_DOMAINS[*]}"
|
|
else
|
|
# Fallback to default domains
|
|
ALLOWED_DOMAINS=("api.openai.com")
|
|
echo "Domains file not found, using default: ${ALLOWED_DOMAINS[*]}"
|
|
fi
|
|
|
|
# Ensure we have at least one domain
|
|
if [ ${#ALLOWED_DOMAINS[@]} -eq 0 ]; then
|
|
echo "ERROR: No allowed domains specified"
|
|
exit 1
|
|
fi
|
|
|
|
# Flush existing rules and delete existing ipsets
|
|
iptables -F
|
|
iptables -X
|
|
iptables -t nat -F
|
|
iptables -t nat -X
|
|
iptables -t mangle -F
|
|
iptables -t mangle -X
|
|
ipset destroy allowed-domains 2>/dev/null || true
|
|
|
|
# First allow DNS and localhost before any restrictions
|
|
# Allow outbound DNS
|
|
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
|
|
# Allow inbound DNS responses
|
|
iptables -A INPUT -p udp --sport 53 -j ACCEPT
|
|
# Allow localhost
|
|
iptables -A INPUT -i lo -j ACCEPT
|
|
iptables -A OUTPUT -o lo -j ACCEPT
|
|
|
|
# Create ipset with CIDR support
|
|
ipset create allowed-domains hash:net
|
|
|
|
# Resolve and add other allowed domains
|
|
for domain in "${ALLOWED_DOMAINS[@]}"; do
|
|
echo "Resolving $domain..."
|
|
ips=$(dig +short A "$domain")
|
|
if [ -z "$ips" ]; then
|
|
echo "ERROR: Failed to resolve $domain"
|
|
exit 1
|
|
fi
|
|
|
|
while read -r ip; do
|
|
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
|
echo "ERROR: Invalid IP from DNS for $domain: $ip"
|
|
exit 1
|
|
fi
|
|
echo "Adding $ip for $domain"
|
|
ipset add allowed-domains "$ip"
|
|
done < <(echo "$ips")
|
|
done
|
|
|
|
# Get host IP from default route
|
|
HOST_IP=$(ip route | grep default | cut -d" " -f3)
|
|
if [ -z "$HOST_IP" ]; then
|
|
echo "ERROR: Failed to detect host IP"
|
|
exit 1
|
|
fi
|
|
|
|
HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\.[0-9]*$/.0\/24/")
|
|
echo "Host network detected as: $HOST_NETWORK"
|
|
|
|
# Set up remaining iptables rules
|
|
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
|
|
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT
|
|
|
|
# Set default policies to DROP first
|
|
iptables -P INPUT DROP
|
|
iptables -P FORWARD DROP
|
|
iptables -P OUTPUT DROP
|
|
|
|
# First allow established connections for already approved traffic
|
|
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
|
|
# Then allow only specific outbound traffic to allowed domains
|
|
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
|
|
|
# Append final REJECT rules for immediate error responses
|
|
# For TCP traffic, send a TCP reset; for UDP, send ICMP port unreachable.
|
|
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
|
|
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
|
|
iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
|
|
iptables -A OUTPUT -p udp -j REJECT --reject-with icmp-port-unreachable
|
|
iptables -A FORWARD -p tcp -j REJECT --reject-with tcp-reset
|
|
iptables -A FORWARD -p udp -j REJECT --reject-with icmp-port-unreachable
|
|
|
|
echo "Firewall configuration complete"
|
|
echo "Verifying firewall rules..."
|
|
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
|
echo "ERROR: Firewall verification failed - was able to reach https://example.com"
|
|
exit 1
|
|
else
|
|
echo "Firewall verification passed - unable to reach https://example.com as expected"
|
|
fi
|
|
|
|
# Always verify OpenAI API access is working
|
|
if ! curl --connect-timeout 5 https://api.openai.com >/dev/null 2>&1; then
|
|
echo "ERROR: Firewall verification failed - unable to reach https://api.openai.com"
|
|
exit 1
|
|
else
|
|
echo "Firewall verification passed - able to reach https://api.openai.com as expected"
|
|
fi
|