{"name":"aicli-env","version":"0.2.0","description":"Local AI router — OpenRouter/LiteLLM alternative with first-class CLI backend support","models":105,"providers":[{"id":"claude","name":"Claude CLI","type":"cli","cost":"free","models":7},{"id":"codex","name":"Codex CLI","type":"cli","cost":"free","models":7},{"id":"minimax","name":"MiniMax API","type":"api","cost":"paid","models":5},{"id":"opencode","name":"OpenCode Zen CLI (free tier)","type":"cli","cost":"free","models":10},{"id":"aihubmix","name":"AiHubMix","type":"api","cost":"free","models":54},{"id":"hetzner","name":"Hetzner AI Inference","type":"api","cost":"paid","models":4},{"id":"deepseek","name":"DeepSeek (via OpenRouter)","type":"api","cost":"paid","models":3},{"id":"local","name":"Local LLM","type":"api","cost":"free","models":1},{"id":"openrouter","name":"OpenRouter","type":"api","cost":"paid","models":10}],"endpoints":{"model_serving":{"POST /v1/chat/completions":"OpenAI-compatible chat completions — route to any backend","POST /v1/messages":"Anthropic Messages format","GET /v1/models":"List available models (filtered by API key allowedModels)"},"images":{"POST /v1/images/generations":"Image generation — OpenAI-compatible. MiniMax (minimax-image-01) or Codex CLI (gpt-image-1, gpt-5.5)"},"ocr":{"POST /v1/ocr":"OCR document — multipart upload, backends: auto/pymupdf/pdfplumber/apple-vision/ai","GET /v1/ocr/backends":"List available OCR backends"},"pdf":{"POST /v1/pdf/extract":"Extract text from PDF (PyMuPDF — Vietnamese diacritics, needsOcr detection)","POST /v1/pdf/compress":"Compress PDF — dual-engine (gsqpdf/pdfcpu), return=file for binary download","POST /v1/pdf/render":"Render PDF pages to PNG (PyMuPDF, configurable DPI)","GET /v1/pdf/capabilities":"Check available PDF processing tools"},"summarize":{"POST /v1/summarize":"Summarize text or URL — models: deepseek-v4-flash (default) → distilbart-cnn-6-6 (fallback)"},"admin_trpc":{"trpc.models.list":"Browse all models with metadata, capabilities, providers","trpc.providers.list":"List providers with CLI auto-detection and API config status","trpc.keys.list|create|update|revoke":"API key management with provider/model restrictions","trpc.usage.list|summary":"Usage logs and summary statistics"},"auth":{"POST /api/auth/sign-in/email":"Email/password sign in","POST /api/auth/sign-up/email":"Create account","POST /api/auth/forget-password":"Request password reset"},"admin_ui":{"/models":"Model catalog — browse, search, filter","/admin/keys":"API key management — restrict providers, models, view usage","/admin/providers":"Provider config — CLI auto-detect, API keys","/admin/routing":"Auto router — allowed models, provider sort, fallback","/admin/plugins":"Plugins — web search, PDF inputs, response healing","/admin/activity":"Usage activity charts","/admin/usage":"Request logs","/admin/summarize":"Summarize text or URLs using AI models","/admin/settings":"Account settings"},"task_queue":{"POST /v1.1/chat/completions":"Task-wrapped completions — auto-summarize, dispatch to pre-launched CLI pool","GET /v1.1/tasks":"List tasks for authenticated user","GET /v1.1/tasks/:taskId":"Get task status and response","GET /v1.1/pool":"Task pool stats"},"health":{"GET /healthz":"Health check"}},"docs":{"auth_header":"Authorization: Bearer aicli_<key>","alt_header":"x-api-key: aicli_<key>","sessions":{"description":"CLI backends maintain persistent sessions per API key + model. Sessions are reused across requests for lower latency.","headers":{"x-session-id":"Custom session identifier (default: 'default'). Isolates sessions per use-case.","x-session-alive-ms":"Keep session alive for this duration after last use (default: 5min, max: 30min)","x-session-destroy":"Set to 'true' to destroy the session after this request completes"},"behavior":["Each unique (apiKey, sessionId, model) tuple gets its own persistent CLI session","Sessions auto-expire after idle timeout","Context is tracked per session — auto-cleared when threshold exceeded"]},"queue":{"description":"Requests are queued with automatic retry on rate limits (429) and transient errors. Per-key configurable via ApiKey.maxRetries (default: 3).","response_headers":{"X-Job-Id":"Unique job identifier for this request (always present)","X-Queue-Position":"Queue position at time of enqueue (non-streaming only)","Retry-After":"Seconds until rate limit resets (present on 429 responses)"},"error_body":{"error.retry_after":"Seconds until provider rate limit resets (string, e.g. '120')","error.message":"Human-readable error description","error.type":"Error category: upstream_error | cli_error | rate_limit"},"behavior":["Streaming: retries transparently before first SSE chunk (client sees nothing)","Non-streaming: BullMQ job with exponential backoff (5s, 15s, 45s)","Client disconnect aborts in-flight job via Redis pub/sub","After max retries exhausted, returns final error with Retry-After header"]},"example":"curl -X POST http://localhost:3120/v1/chat/completions -H 'Authorization: Bearer aicli_...' -H 'Content-Type: application/json' -d '{\"model\":\"claude-sonnet-4-6\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'"}}