diff --git a/README.md b/README.md index 63c4ade..c1095e9 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ gui-cliproxyapi ``` **Available Scripts:** + - `start-cliproxyapi` - Start/stop/restart server - `cliproxyapi-oauth` - Login to OAuth providers - `gui-cliproxyapi` - Open GUI Control Center @@ -116,6 +117,87 @@ gui-cliproxyapi --- +## Quick Start (Linux/macOS) + +### Prerequisites + +- **Git** - Usually pre-installed, or install with `sudo apt install git` (Ubuntu) / `brew install git` (macOS) +- **Go 1.21+** (optional, for building from source) - [Download](https://go.dev/dl/) +- **curl** or **wget** - Usually pre-installed + +### Installation + +```bash +# Clone this repo +git clone https://github.com/julianromli/CLIProxyAPIPlus-Easy-Installation.git +cd CLIProxyAPIPlus-Easy-Installation + +# Make script executable and run installer +chmod +x scripts/install-cliproxyapi.sh +./scripts/install-cliproxyapi.sh + +# Or use pre-built binary (no Go required) +./scripts/install-cliproxyapi.sh --use-prebuilt +``` + +### After Installation + +Scripts are installed to `~/.local/bin/` and added to PATH automatically. + +```bash +# Reload shell config (or open new terminal) +source ~/.bashrc # or ~/.zshrc if using zsh + +# Start server in background +start-cliproxyapi --background + +# Login to providers +cliproxyapi-oauth --all + +# Open GUI Control Center (full control via browser) +gui-cliproxyapi +``` + +**Available Scripts:** + +- `start-cliproxyapi` - Start/stop/restart server +- `cliproxyapi-oauth` - Login to OAuth providers +- `gui-cliproxyapi` - Open GUI Control Center +- `update-cliproxyapi` - Update to latest version +- `uninstall-cliproxyapi` - Remove everything + +### Testing the Installation + +After installation, test if everything works: + +```bash +# 1. Check server status +start-cliproxyapi --status + +# 2. Test API endpoint +curl -H "Authorization: Bearer sk-dummy" http://localhost:8317/v1/models + +# 3. Test chat completion +curl http://localhost:8317/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-dummy" \ + -d '{ + "model": "gemini-2.5-pro", + "messages": [{"role": "user", "content": "Hello!"}] + }' + +# 4. View server logs +start-cliproxyapi --logs +``` + +Expected results: + +- `/v1/models` returns list of available models +- Chat completion returns AI response +- Logs show successful API calls + +--- + ## Usage with Different CLI Tools ### Factory Droid @@ -143,8 +225,9 @@ gui-cliproxyapi Set environment variables before running: +**Windows (PowerShell):** + ```powershell -# PowerShell $env:ANTHROPIC_BASE_URL = "http://localhost:8317/v1" $env:ANTHROPIC_API_KEY = "sk-dummy" claude @@ -160,6 +243,24 @@ $env:ANTHROPIC_BASE_URL = "http://localhost:8317/v1" $env:ANTHROPIC_API_KEY = "sk-dummy" ``` +**Linux/macOS (Bash/Zsh):** + +```bash +export ANTHROPIC_BASE_URL="http://localhost:8317/v1" +export ANTHROPIC_API_KEY="sk-dummy" +claude + +# Or in one line +ANTHROPIC_BASE_URL="http://localhost:8317/v1" ANTHROPIC_API_KEY="sk-dummy" claude +``` + +For persistent config, add to `~/.bashrc` or `~/.zshrc`: + +```bash +export ANTHROPIC_BASE_URL="http://localhost:8317/v1" +export ANTHROPIC_API_KEY="sk-dummy" +``` + ### OpenCode Create or edit `~/.opencode/config.json`: @@ -201,7 +302,7 @@ Edit `~/.continue/config.json`: }, { "title": "CLIProxy - Claude", - "provider": "openai", + "provider": "openai", "model": "claude-opus-4.5", "apiKey": "sk-dummy", "apiBase": "http://localhost:8317/v1" @@ -244,6 +345,7 @@ curl http://localhost:8317/v1/chat/completions \ ## Available Models ### Antigravity Provider + | Model ID | Description | |----------|-------------| | `gemini-claude-opus-4-5-thinking` | Claude Opus 4.5 with extended thinking | @@ -253,6 +355,7 @@ curl http://localhost:8317/v1/chat/completions \ | `gpt-oss-120b-medium` | GPT OSS 120B | ### GitHub Copilot Provider + | Model ID | Description | |----------|-------------| | `claude-opus-4.5` | Claude Opus 4.5 | @@ -260,28 +363,33 @@ curl http://localhost:8317/v1/chat/completions \ | `grok-code-fast-1` | Grok Code Fast | ### Gemini CLI Provider + | Model ID | Description | |----------|-------------| | `gemini-2.5-pro` | Gemini 2.5 Pro | | `gemini-3-pro-preview` | Gemini 3 Pro Preview | ### Codex Provider + | Model ID | Description | |----------|-------------| | `gpt-5.1-codex-max` | GPT-5.1 Codex Max | ### Qwen Provider + | Model ID | Description | |----------|-------------| | `qwen3-coder-plus` | Qwen3 Coder Plus | ### iFlow Provider + | Model ID | Description | |----------|-------------| | `glm-4.6` | GLM 4.6 | | `minimax-m2` | Minimax M2 | ### Kiro (AWS) Provider + | Model ID | Description | |----------|-------------| | `kiro-claude-opus-4.5` | Claude Opus 4.5 via Kiro | @@ -396,6 +504,7 @@ gui-cliproxyapi.ps1 -NoBrowser ``` **Features:** + - Real-time server status monitoring - Start/Stop/Restart buttons (actually work!) - OAuth login buttons for all providers @@ -474,6 +583,7 @@ MIT License - See [LICENSE](LICENSE) file. ## Contributing PRs welcome! Feel free to: + - Add support for more CLI tools - Improve documentation - Report bugs diff --git a/README_ID.md b/README_ID.md index 2de79b1..a278502 100644 --- a/README_ID.md +++ b/README_ID.md @@ -108,12 +108,94 @@ gui-cliproxyapi ``` **Script yang Tersedia:** + +- `start-cliproxyapi` - Start/stop/restart server +- `cliproxyapi-oauth` - Login ke OAuth provider +- `gui-cliproxyapi` - Buka GUI Control Center +- `update-cliproxyapi` - Update ke versi terbaru +- `uninstall-cliproxyapi` - Hapus semuanya + +--- + +## Quick Start (Linux/macOS) + +### Prasyarat + +- **Git** - Biasanya sudah terinstall, atau install dengan `sudo apt install git` (Ubuntu) / `brew install git` (macOS) +- **Go 1.21+** (opsional, untuk build dari source) - [Download](https://go.dev/dl/) +- **curl** atau **wget** - Biasanya sudah terinstall + +### Instalasi + +```bash +# Clone repo ini +git clone https://github.com/julianromli/CLIProxyAPIPlus-Easy-Installation.git +cd CLIProxyAPIPlus-Easy-Installation + +# Buat script executable dan jalankan installer +chmod +x scripts/install-cliproxyapi.sh +./scripts/install-cliproxyapi.sh + +# Atau pake binary pre-built (gak perlu Go) +./scripts/install-cliproxyapi.sh --use-prebuilt +``` + +### Setelah Instalasi + +Script diinstall ke `~/.local/bin/` dan otomatis ditambahkan ke PATH. + +```bash +# Reload shell config (atau buka terminal baru) +source ~/.bashrc # atau ~/.zshrc kalau pake zsh + +# Start server di background +start-cliproxyapi --background + +# Login ke provider +cliproxyapi-oauth --all + +# Buka GUI Control Center (kontrol penuh via browser) +gui-cliproxyapi +``` + +**Script yang Tersedia:** + - `start-cliproxyapi` - Start/stop/restart server - `cliproxyapi-oauth` - Login ke OAuth provider - `gui-cliproxyapi` - Buka GUI Control Center - `update-cliproxyapi` - Update ke versi terbaru - `uninstall-cliproxyapi` - Hapus semuanya +### Testing Instalasi + +Setelah instalasi, cek apakah semuanya berjalan: + +```bash +# 1. Cek status server +start-cliproxyapi --status + +# 2. Test endpoint API +curl -H "Authorization: Bearer sk-dummy" http://localhost:8317/v1/models + +# 3. Test chat completion +curl http://localhost:8317/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer sk-dummy" \ + -d '{ + "model": "gemini-2.5-pro", + "messages": [{"role": "user", "content": "Halo!"}] + }' + +# 4. Lihat log server +start-cliproxyapi --logs +``` + +Hasil yang diharapkan: + +- `/v1/models` mengembalikan daftar model +- Chat completion mengembalikan respon AI +- Log menunjukkan API call berhasil + --- ## Penggunaan dengan Berbagai CLI Tool @@ -143,8 +225,9 @@ gui-cliproxyapi Set environment variable sebelum running: +**Windows (PowerShell):** + ```powershell -# PowerShell $env:ANTHROPIC_BASE_URL = "http://localhost:8317/v1" $env:ANTHROPIC_API_KEY = "sk-dummy" claude @@ -160,6 +243,24 @@ $env:ANTHROPIC_BASE_URL = "http://localhost:8317/v1" $env:ANTHROPIC_API_KEY = "sk-dummy" ``` +**Linux/macOS (Bash/Zsh):** + +```bash +export ANTHROPIC_BASE_URL="http://localhost:8317/v1" +export ANTHROPIC_API_KEY="sk-dummy" +claude + +# Atau dalam satu baris +ANTHROPIC_BASE_URL="http://localhost:8317/v1" ANTHROPIC_API_KEY="sk-dummy" claude +``` + +Untuk config permanen, tambahkan ke `~/.bashrc` atau `~/.zshrc`: + +```bash +export ANTHROPIC_BASE_URL="http://localhost:8317/v1" +export ANTHROPIC_API_KEY="sk-dummy" +``` + ### OpenCode Buat atau edit `~/.opencode/config.json`: @@ -201,7 +302,7 @@ Edit `~/.continue/config.json`: }, { "title": "CLIProxy - Claude", - "provider": "openai", + "provider": "openai", "model": "claude-opus-4.5", "apiKey": "sk-dummy", "apiBase": "http://localhost:8317/v1" @@ -244,6 +345,7 @@ curl http://localhost:8317/v1/chat/completions \ ## Model yang Tersedia ### Provider Antigravity + | Model ID | Deskripsi | |----------|-----------| | `gemini-claude-opus-4-5-thinking` | Claude Opus 4.5 dengan extended thinking | @@ -253,6 +355,7 @@ curl http://localhost:8317/v1/chat/completions \ | `gpt-oss-120b-medium` | GPT OSS 120B | ### Provider GitHub Copilot + | Model ID | Deskripsi | |----------|-----------| | `claude-opus-4.5` | Claude Opus 4.5 | @@ -260,28 +363,33 @@ curl http://localhost:8317/v1/chat/completions \ | `grok-code-fast-1` | Grok Code Fast | ### Provider Gemini CLI + | Model ID | Deskripsi | |----------|-----------| | `gemini-2.5-pro` | Gemini 2.5 Pro | | `gemini-3-pro-preview` | Gemini 3 Pro Preview | ### Provider Codex + | Model ID | Deskripsi | |----------|-----------| | `gpt-5.1-codex-max` | GPT-5.1 Codex Max | ### Provider Qwen + | Model ID | Deskripsi | |----------|-----------| | `qwen3-coder-plus` | Qwen3 Coder Plus | ### Provider iFlow + | Model ID | Deskripsi | |----------|-----------| | `glm-4.6` | GLM 4.6 | | `minimax-m2` | Minimax M2 | ### Provider Kiro (AWS) + | Model ID | Deskripsi | |----------|-----------| | `kiro-claude-opus-4.5` | Claude Opus 4.5 via Kiro | @@ -396,6 +504,7 @@ gui-cliproxyapi.ps1 -NoBrowser ``` **Fitur:** + - Monitoring status server real-time - Tombol Start/Stop/Restart (beneran jalan!) - Tombol OAuth login untuk semua provider @@ -474,6 +583,7 @@ MIT License - Lihat file [LICENSE](LICENSE). ## Kontribusi PR welcome! Silakan: + - Tambah dukungan untuk CLI tool lain - Perbaiki dokumentasi - Laporkan bug diff --git a/scripts/AGENTS.md b/scripts/AGENTS.md index 6d88d5a..cd08d77 100644 --- a/scripts/AGENTS.md +++ b/scripts/AGENTS.md @@ -1,26 +1,43 @@ # AGENTS.md - Scripts Directory -> Detailed guidance for PowerShell scripts in this repository. +> Detailed guidance for installation and management scripts in this repository. ## Package Identity - **Purpose**: Automation scripts for CLIProxyAPIPlus installation/management -- **Language**: PowerShell 5.1+ (Windows-native) +- **Platform Support**: Windows (PowerShell 5.1+), Linux/macOS (Bash) - **No dependencies**: Scripts are self-contained ## Script Inventory +### PowerShell Scripts (Windows) + | Script | Purpose | Key Params | |--------|---------|------------| | `install-cliproxyapi.ps1` | Full installation | `-UsePrebuilt`, `-Force`, `-SkipOAuth` | +| `start-cliproxyapi.ps1` | Server manager | `-Background`, `-Stop`, `-Restart`, `-Status`, `-Logs` | | `update-cliproxyapi.ps1` | Update to latest | `-UsePrebuilt`, `-Force` | | `cliproxyapi-oauth.ps1` | OAuth login helper | `-All`, `-Gemini`, `-Copilot`, etc. | -| `uninstall-cliproxyapi.ps1` | Clean removal | `-All`, `-KeepAuth`, `-Force` | +| `gui-cliproxyapi.ps1` | Web GUI launcher | `-Port`, `-NoBrowser` | +| `uninstall-cliproxyapi.ps1` | Clean removal | `-All`, `-Force` | + +### Bash Scripts (Linux/macOS) + +| Script | Purpose | Key Params | +|--------|---------|------------| +| `install-cliproxyapi.sh` | Full installation | `--use-prebuilt`, `--force`, `--skip-oauth` | +| `start-cliproxyapi.sh` | Server manager | `--background`, `--stop`, `--restart`, `--status`, `--logs` | +| `update-cliproxyapi.sh` | Update to latest | `--use-prebuilt`, `--force` | +| `cliproxyapi-oauth.sh` | OAuth login helper | `--all`, `--gemini`, `--copilot`, etc. | +| `gui-cliproxyapi.sh` | Web GUI launcher | `--port`, `--no-browser` | +| `uninstall-cliproxyapi.sh` | Clean removal | `--all`, `--force` | ## Patterns & Conventions ### Script Header Template + Every script MUST have this structure: + ```powershell <# .SYNOPSIS @@ -41,20 +58,26 @@ param( $ErrorActionPreference = "Stop" ``` + ✅ DO: Copy from `install-cliproxyapi.ps1` header ### Output Functions + Use consistent colored output: + ```powershell function Write-Step { param($msg) Write-Host "`n[*] $msg" -ForegroundColor Cyan } function Write-Success { param($msg) Write-Host "[+] $msg" -ForegroundColor Green } function Write-Warning { param($msg) Write-Host "[!] $msg" -ForegroundColor Yellow } function Write-Error { param($msg) Write-Host "[-] $msg" -ForegroundColor Red } ``` + ✅ DO: See `install-cliproxyapi.ps1` lines 30-33 ### Path Variables + Always use expandable paths: + ```powershell # ✅ DO: Use environment variables $CONFIG_DIR = "$env:USERPROFILE\.cli-proxy-api" @@ -65,6 +88,7 @@ $CONFIG_DIR = "C:\Users\faiz\.cli-proxy-api" ``` ### Error Handling + ```powershell # ✅ DO: Use try-catch with specific error messages try { @@ -79,12 +103,13 @@ Some-Operation 2>$null ``` ### External Commands + ```powershell # ✅ DO: Check exit codes & git clone $REPO_URL $CLONE_DIR -if ($LASTEXITCODE -ne 0) { +if ($LASTEXITCODE -ne 0) { Write-Error "Git clone failed" - exit 1 + exit 1 } # ❌ DON'T: Assume success @@ -109,6 +134,7 @@ if ($LASTEXITCODE -ne 0) { 6. Add to README_ID.md (Indonesian version) ### Checklist for New Script + ```powershell # Verify these patterns: Select-String -Path "scripts\NEW_SCRIPT.ps1" -Pattern "\.SYNOPSIS" # Has help @@ -117,8 +143,118 @@ Select-String -Path "scripts\NEW_SCRIPT.ps1" -Pattern "ErrorActionPreference" # Select-String -Path "scripts\NEW_SCRIPT.ps1" -Pattern "env:USERPROFILE" # Uses env vars ``` +## Bash Script Patterns (Linux/macOS) + +### Script Header Template + +```bash +#!/usr/bin/env bash +# +# Script Description +# +# Detailed explanation of what this script does +# +# Author: ... +# Repo: https://github.com/... + +set -e # Exit on error + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --flag) FLAG=true; shift ;; + --param) PARAM="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done +``` + +✅ DO: Copy from `install-cliproxyapi.sh` header + +### Output Functions + +Use consistent colored output: + +```bash +# Colors +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +echo_step() { echo -e "\n${CYAN}[*] $1${NC}"; } +echo_success() { echo -e "${GREEN}[+] $1${NC}"; } +echo_warning() { echo -e "${YELLOW}[!] $1${NC}"; } +echo_error() { echo -e "${RED}[-] $1${NC}"; } +``` + +### Path Variables + +Use HOME and XDG conventions: + +```bash +BIN_DIR="$HOME/.local/bin" +CONFIG_DIR="$HOME/.cli-proxy-api" +FACTORY_DIR="$HOME/.factory" +``` + +### Error Handling + +```bash +set -e # Exit on any error + +# Check command availability +if ! command -v git &> /dev/null; then + echo_error "Git is not installed" + exit 1 +fi + +# Check file existence +if [ ! -f "$FILE" ]; then + echo_error "File not found: $FILE" + exit 1 +fi +``` + +### Cross-Platform Compatibility + +```bash +# Detect OS and architecture +OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +ARCH="$(uname -m)" + +case "$ARCH" in + x86_64) ARCH="amd64" ;; + aarch64|arm64) ARCH="arm64" ;; + *) echo_error "Unsupported: $ARCH"; exit 1 ;; +esac + +# Detect shell config file +if [ -n "$BASH_VERSION" ]; then + SHELL_RC="$HOME/.bashrc" +elif [ -n "$ZSH_VERSION" ]; then + SHELL_RC="$HOME/.zshrc" +else + SHELL_RC="$HOME/.profile" +fi +``` + +### Checklist for New Bash Script + +```bash +# Verify before commit: +grep -q "#!/usr/bin/env bash" script.sh # Has shebang +grep -q "set -e" script.sh # Has error handling +grep -q "echo_" script.sh # Uses output functions +chmod +x script.sh # Is executable +shellcheck script.sh || true # Run linter (if available) +``` + ## JIT Index Hints +### PowerShell + ```powershell # Find all param definitions Select-String -Path "*.ps1" -Pattern "\[switch\]|\[string\]" @@ -133,18 +269,45 @@ Select-String -Path "*.ps1" -Pattern "& \w+" Select-String -Path "*.ps1" -Pattern "exit \d" ``` +### Bash + +```bash +# Find all function definitions +grep -n "^[a-z_]*() {" scripts/*.sh + +# Find all echo_* calls (for UI consistency) +grep -n "echo_\(step\|success\|warning\|error\)" scripts/*.sh + +# Find all exit points +grep -n "exit [0-9]" scripts/*.sh + +# Find command checks +grep -n "command -v" scripts/*.sh +``` + ## Common Gotchas -1. **PowerShell string escaping**: Use single quotes for literals, double for variables +### PowerShell + +1. **String escaping**: Use single quotes for literals, double for variables 2. **Path separators**: Use `\` on Windows, but `/` works in most contexts 3. **Invoke-WebRequest**: May fail without `-UseBasicParsing` on older systems 4. **JSON depth**: `ConvertTo-Json` defaults to depth 2, use `-Depth 10` for nested +### Bash + +1. **Quoting variables**: Always quote: `"$VAR"` not `$VAR` (handles spaces) +2. **Command substitution**: Use `$(command)` not backticks +3. **Test expressions**: Use `[[ ]]` not `[ ]` (more robust) +4. **Temporary files**: Use `mktemp` for secure temp file creation +5. **Cross-platform paths**: Use `$HOME` not `~` in scripts +6. **Exit on error**: Always use `set -e` at script start + ## Pre-PR Checks ```powershell # Syntax check all scripts -Get-ChildItem *.ps1 | ForEach-Object { +Get-ChildItem *.ps1 | ForEach-Object { $null = [System.Management.Automation.PSParser]::Tokenize((Get-Content $_.FullName -Raw), [ref]$null) Write-Host "✓ $($_.Name)" -ForegroundColor Green } diff --git a/scripts/cliproxyapi-api-server.py b/scripts/cliproxyapi-api-server.py new file mode 100644 index 0000000..47e5090 --- /dev/null +++ b/scripts/cliproxyapi-api-server.py @@ -0,0 +1,309 @@ +#!/usr/bin/env python3 +""" +Simple HTTP API server for CLIProxyAPI-Plus management +Provides REST API endpoints for the GUI Control Center +""" + +import http.server +import socketserver +import json +import subprocess +import os +from urllib.parse import urlparse, parse_qs +from pathlib import Path + +PORT = 8318 +HOME = Path.home() +BIN_DIR = HOME / ".local" / "bin" +CONFIG_DIR = HOME / ".cli-proxy-api" + +class APIHandler(http.server.SimpleHTTPRequestHandler): + """Handler for API requests""" + + def do_GET(self): + """Handle GET requests""" + parsed = urlparse(self.path) + + if parsed.path == '/api/status': + self.handle_status() + elif parsed.path == '/api/config': + self.handle_get_config() + elif parsed.path == '/api/auth-status': + self.handle_auth_status() + elif parsed.path == '/api/models': + self.handle_models() + elif parsed.path == '/api/stats': + self.handle_stats() + elif parsed.path == '/api/update/check': + self.handle_update_check() + else: + # Serve static files (GUI) + super().do_GET() + + def do_POST(self): + """Handle POST requests""" + parsed = urlparse(self.path) + + if parsed.path == '/api/start': + self.handle_start() + elif parsed.path == '/api/stop': + self.handle_stop() + elif parsed.path == '/api/restart': + self.handle_restart() + elif parsed.path.startswith('/api/oauth/'): + provider = parsed.path.split('/')[-1] + self.handle_oauth(provider) + elif parsed.path == '/api/update/apply': + self.handle_update_apply() + else: + self.send_error(404) + + def handle_status(self): + """Get server status""" + try: + result = subprocess.run( + [str(BIN_DIR / "start-cliproxyapi"), "--status"], + capture_output=True, + text=True, + timeout=5 + ) + + # Parse output + is_running = "Server is running" in result.stdout + pid = None + if is_running: + for line in result.stdout.split('\n'): + if 'PID:' in line: + pid = line.split('PID:')[-1].strip().rstrip(')') + + response = { + "running": is_running, + "pid": pid, + "endpoint": "http://localhost:8317/v1" if is_running else None + } + + self.send_json(response) + except Exception as e: + self.send_json({"running": False, "error": str(e)}) + + def handle_start(self): + """Start the server""" + try: + result = subprocess.run( + [str(BIN_DIR / "start-cliproxyapi"), "--background"], + capture_output=True, + text=True, + timeout=10 + ) + + success = result.returncode == 0 + self.send_json({ + "success": success, + "message": result.stdout + result.stderr + }) + except Exception as e: + self.send_json({"success": False, "message": str(e)}) + + def handle_stop(self): + """Stop the server""" + try: + result = subprocess.run( + [str(BIN_DIR / "start-cliproxyapi"), "--stop"], + capture_output=True, + text=True, + timeout=10 + ) + + success = result.returncode == 0 + self.send_json({ + "success": success, + "message": result.stdout + result.stderr + }) + except Exception as e: + self.send_json({"success": False, "message": str(e)}) + + def handle_restart(self): + """Restart the server""" + try: + result = subprocess.run( + [str(BIN_DIR / "start-cliproxyapi"), "--restart"], + capture_output=True, + text=True, + timeout=15 + ) + + success = result.returncode == 0 + self.send_json({ + "success": success, + "message": result.stdout + result.stderr + }) + except Exception as e: + self.send_json({"success": False, "message": str(e)}) + + def handle_oauth(self, provider): + """Trigger OAuth login""" + provider_map = { + "gemini": "--gemini", + "antigravity": "--antigravity", + "copilot": "--copilot", + "codex": "--codex", + "claude": "--claude", + "qwen": "--qwen", + "iflow": "--iflow", + "kiro": "--kiro" + } + + flag = provider_map.get(provider.lower()) + if not flag: + self.send_json({"success": False, "message": "Unknown provider"}) + return + + try: + # Run in background, don't wait + subprocess.Popen( + [str(BIN_DIR / "cliproxyapi-oauth"), flag], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL + ) + + self.send_json({ + "success": True, + "message": f"OAuth login started for {provider}" + }) + except Exception as e: + self.send_json({"success": False, "message": str(e)}) + + def handle_get_config(self): + """Get current config""" + config_file = CONFIG_DIR / "config.yaml" + try: + if config_file.exists(): + with open(config_file, 'r') as f: + self.send_json({"config": f.read()}) + else: + self.send_json({"config": ""}) + except Exception as e: + self.send_json({"config": "", "error": str(e)}) + + def handle_auth_status(self): + """Get auth status for providers""" + try: + auth_files = list(CONFIG_DIR.glob("*.json")) + providers = { + "gemini": False, + "antigravity": False, + "copilot": False, + "codex": False, + "claude": False, + "qwen": False, + "iflow": False, + "kiro": False + } + + for f in auth_files: + name = f.stem.lower() + if "gemini" in name or "@gmail.com" in name: + providers["gemini"] = True + if "antigravity" in name: + providers["antigravity"] = True + if "copilot" in name or "github" in name: + providers["copilot"] = True + if "codex" in name: + providers["codex"] = True + if "claude" in name: + providers["claude"] = True + if "qwen" in name: + providers["qwen"] = True + if "iflow" in name: + providers["iflow"] = True + if "kiro" in name: + providers["kiro"] = True + + self.send_json(providers) + except Exception as e: + self.send_json({p: False for p in ["gemini", "antigravity", "copilot", "codex", "claude", "qwen", "iflow", "kiro"]}) + + def handle_models(self): + """Get available models""" + try: + result = subprocess.run( + ["curl", "-s", "-H", "Authorization: Bearer sk-dummy", + "http://localhost:8317/v1/models"], + capture_output=True, + text=True, + timeout=5 + ) + + if result.returncode == 0: + data = json.loads(result.stdout) + models = [m["id"] for m in data.get("data", [])] + self.send_json({"models": models}) + else: + self.send_json({"models": []}) + except Exception as e: + self.send_json({"models": [], "error": str(e)}) + + def handle_stats(self): + """Get request statistics (stub for now)""" + self.send_json({ + "totalRequests": 0, + "successRate": 0, + "avgLatency": 0, + "errors": 0 + }) + + def handle_update_check(self): + """Check for updates (stub)""" + self.send_json({ + "available": False, + "current": "6.5.64", + "latest": "6.5.64" + }) + + def handle_update_apply(self): + """Apply update""" + try: + # Run update in background + subprocess.Popen( + [str(BIN_DIR / "update-cliproxyapi"), "--use-prebuilt"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL + ) + + self.send_json({ + "success": True, + "message": "Update started in background" + }) + except Exception as e: + self.send_json({"success": False, "message": str(e)}) + + def send_json(self, data): + """Send JSON response""" + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.send_header('Access-Control-Allow-Origin', '*') + self.end_headers() + self.wfile.write(json.dumps(data).encode()) + + def log_message(self, format, *args): + """Override to reduce noise""" + pass + +def main(): + """Start the API server""" + # Change to GUI directory + gui_dir = HOME / ".local" / "share" / "cliproxyapi" / "gui" + if gui_dir.exists(): + os.chdir(gui_dir) + + with socketserver.TCPServer(("", PORT), APIHandler) as httpd: + print(f"API Server running on http://localhost:{PORT}") + print(f"GUI available at http://localhost:{PORT}") + print("Press Ctrl+C to stop") + try: + httpd.serve_forever() + except KeyboardInterrupt: + print("\nShutting down...") + +if __name__ == "__main__": + main() diff --git a/scripts/cliproxyapi-oauth.sh b/scripts/cliproxyapi-oauth.sh new file mode 100755 index 0000000..e9468d9 --- /dev/null +++ b/scripts/cliproxyapi-oauth.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash +# +# CLIProxyAPI-Plus OAuth Login Helper +# +# Interactive OAuth login for all supported providers + +set -e + +BINARY_PATH="$HOME/.local/bin/cliproxyapi-plus" +CONFIG_PATH="$HOME/.cli-proxy-api/config.yaml" + +# Colors +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +MAGENTA='\033[0;35m' +NC='\033[0m' + +echo_info() { echo -e "${CYAN}[*] $1${NC}"; } +echo_success() { echo -e "${GREEN}[+] $1${NC}"; } +echo_warning() { echo -e "${YELLOW}[!] $1${NC}"; } +echo_error() { echo -e "${RED}[-] $1${NC}"; } + +# Check prerequisites +if [ ! -f "$BINARY_PATH" ]; then + echo_error "Binary not found: $BINARY_PATH" + echo_error "Run install-cliproxyapi first" + exit 1 +fi + +if [ ! -f "$CONFIG_PATH" ]; then + echo_error "Config not found: $CONFIG_PATH" + echo_error "Run install-cliproxyapi first" + exit 1 +fi + +# Login functions +login_gemini() { + echo_info "Logging into Gemini CLI..." + "$BINARY_PATH" --config "$CONFIG_PATH" --login + echo_success "Gemini login complete" +} + +login_antigravity() { + echo_info "Logging into Antigravity..." + "$BINARY_PATH" --config "$CONFIG_PATH" --antigravity-login + echo_success "Antigravity login complete" +} + +login_copilot() { + echo_info "Logging into GitHub Copilot..." + "$BINARY_PATH" --config "$CONFIG_PATH" --github-copilot-login + echo_success "GitHub Copilot login complete" +} + +login_codex() { + echo_info "Logging into Codex..." + "$BINARY_PATH" --config "$CONFIG_PATH" --codex-login + echo_success "Codex login complete" +} + +login_claude() { + echo_info "Logging into Claude..." + "$BINARY_PATH" --config "$CONFIG_PATH" --claude-login + echo_success "Claude login complete" +} + +login_qwen() { + echo_info "Logging into Qwen..." + "$BINARY_PATH" --config "$CONFIG_PATH" --qwen-login + echo_success "Qwen login complete" +} + +login_iflow() { + echo_info "Logging into iFlow..." + "$BINARY_PATH" --config "$CONFIG_PATH" --iflow-login + echo_success "iFlow login complete" +} + +login_kiro() { + echo_info "Logging into Kiro (AWS)..." + "$BINARY_PATH" --config "$CONFIG_PATH" --kiro-aws-login + echo_success "Kiro login complete" +} + +# Login to all providers +login_all() { + echo -e "${MAGENTA}" + cat << "EOF" +============================================== + Login to All Providers +============================================== +EOF + echo -e "${NC}" + + echo_warning "This will open multiple browser windows for OAuth login." + echo_warning "Press Enter to continue or Ctrl+C to cancel..." + read + + PROVIDERS=("Gemini" "Antigravity" "GitHub Copilot" "Codex" "Claude" "Qwen" "iFlow" "Kiro") + FUNCS=(login_gemini login_antigravity login_copilot login_codex login_claude login_qwen login_iflow login_kiro) + + for i in "${!PROVIDERS[@]}"; do + echo "" + echo_info "[$((i+1))/${#PROVIDERS[@]}] ${PROVIDERS[$i]}" + ${FUNCS[$i]} || echo_warning "Failed to login to ${PROVIDERS[$i]}" + sleep 1 + done + + echo "" + echo_success "All OAuth logins complete!" +} + +# Interactive menu +show_menu() { + echo -e "${MAGENTA}" + cat << "EOF" +============================================== + CLIProxyAPI-Plus OAuth Login +============================================== +EOF + echo -e "${NC}" + + echo "Select provider to login:" + echo " 1) Gemini CLI" + echo " 2) Antigravity" + echo " 3) GitHub Copilot" + echo " 4) Codex" + echo " 5) Claude" + echo " 6) Qwen" + echo " 7) iFlow" + echo " 8) Kiro (AWS)" + echo " 9) All providers" + echo " 0) Exit" + echo "" + read -p "Enter choice [0-9]: " choice + + case $choice in + 1) login_gemini ;; + 2) login_antigravity ;; + 3) login_copilot ;; + 4) login_codex ;; + 5) login_claude ;; + 6) login_qwen ;; + 7) login_iflow ;; + 8) login_kiro ;; + 9) login_all ;; + 0) exit 0 ;; + *) echo_error "Invalid choice"; exit 1 ;; + esac +} + +# Show help +show_help() { + cat << EOF +CLIProxyAPI-Plus OAuth Login Helper + +Usage: + cliproxyapi-oauth [OPTIONS] + +Options: + --all Login to all providers + --gemini Login to Gemini CLI + --antigravity Login to Antigravity + --copilot Login to GitHub Copilot + --codex Login to Codex + --claude Login to Claude + --qwen Login to Qwen + --iflow Login to iFlow + --kiro Login to Kiro (AWS) + --help, -h Show this help + +Examples: + cliproxyapi-oauth # Interactive menu + cliproxyapi-oauth --all # Login to all + cliproxyapi-oauth --gemini --copilot # Login to specific providers +EOF +} + +# Parse arguments +if [ $# -eq 0 ]; then + show_menu + exit 0 +fi + +LOGIN_ANY=false + +while [[ $# -gt 0 ]]; do + case $1 in + --all) + login_all + LOGIN_ANY=true + shift + ;; + --gemini) + login_gemini + LOGIN_ANY=true + shift + ;; + --antigravity) + login_antigravity + LOGIN_ANY=true + shift + ;; + --copilot) + login_copilot + LOGIN_ANY=true + shift + ;; + --codex) + login_codex + LOGIN_ANY=true + shift + ;; + --claude) + login_claude + LOGIN_ANY=true + shift + ;; + --qwen) + login_qwen + LOGIN_ANY=true + shift + ;; + --iflow) + login_iflow + LOGIN_ANY=true + shift + ;; + --kiro) + login_kiro + LOGIN_ANY=true + shift + ;; + --help|-h) + show_help + exit 0 + ;; + *) + echo_error "Unknown option: $1" + echo "Run 'cliproxyapi-oauth --help' for usage" + exit 1 + ;; + esac +done + +if [ "$LOGIN_ANY" = true ]; then + echo "" + echo_success "OAuth login process complete!" + echo_info "You can now use the models with Factory Droid or other clients." +fi diff --git a/scripts/gui-cliproxyapi.sh b/scripts/gui-cliproxyapi.sh new file mode 100755 index 0000000..89339cb --- /dev/null +++ b/scripts/gui-cliproxyapi.sh @@ -0,0 +1,203 @@ +#!/usr/bin/env bash +# +# CLIProxyAPI-Plus GUI Control Center +# +# Web-based control panel for managing the proxy server + +set -e + +GUI_PORT="${1:-8318}" +NO_BROWSER=false +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --port|-p) + GUI_PORT="$2" + shift 2 + ;; + --no-browser) + NO_BROWSER=true + shift + ;; + --help|-h) + cat << EOF +CLIProxyAPI-Plus GUI Control Center + +Usage: + gui-cliproxyapi [OPTIONS] + +Options: + --port, -p PORT GUI server port (default: 8318) + --no-browser Don't auto-open browser + --help, -h Show this help + +Examples: + gui-cliproxyapi # Start GUI on port 8318 + gui-cliproxyapi --port 9000 # Use custom port +EOF + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Colors +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +MAGENTA='\033[0;35m' +NC='\033[0m' + +echo_info() { echo -e "${CYAN}[*] $1${NC}"; } +echo_success() { echo -e "${GREEN}[+] $1${NC}"; } +echo_warning() { echo -e "${YELLOW}[!] $1${NC}"; } +echo_error() { echo -e "${RED}[-] $1${NC}"; } + +# Find GUI directory +GUI_DIR="" +if [ -d "$HOME/.local/share/cliproxyapi/gui" ] && [ -f "$HOME/.local/share/cliproxyapi/gui/index.html" ]; then + GUI_DIR="$HOME/.local/share/cliproxyapi/gui" +elif [ -d "$SCRIPT_DIR/../gui" ] && [ -f "$SCRIPT_DIR/../gui/index.html" ]; then + GUI_DIR="$SCRIPT_DIR/../gui" +elif [ -d "/usr/share/cliproxyapi/gui" ] && [ -f "/usr/share/cliproxyapi/gui/index.html" ]; then + GUI_DIR="/usr/share/cliproxyapi/gui" +fi + +if [ -z "$GUI_DIR" ]; then + echo_error "GUI files not found" + echo_info "Creating temporary GUI..." + + # Create minimal GUI + TMP_GUI_DIR=$(mktemp -d) + TMP_GUI="$TMP_GUI_DIR/index.html" + GUI_DIR="$TMP_GUI_DIR" + cat > "$TMP_GUI" << 'EOFHTML' + + +
+Use these commands in your terminal:
++# Start server +start-cliproxyapi --background + +# Check status +start-cliproxyapi --status + +# Stop server +start-cliproxyapi --stop + +# Login to providers +cliproxyapi-oauth --all + +# Update +update-cliproxyapi --use-prebuilt ++
http://localhost:8317/v1
+Use this as your OpenAI API base URL
+