Problem
chatbot.py maintains three separate classes (GPTBot, ClaudeBot, GeminiBot), each wrapping a different SDK. This has led to:
- Duplicated logic (~580 lines): retry, fee tracking, auth, and temperature clamping are implemented three times.
- Bugs from drift:
ClaudeBot mutates the input message list via messages.pop(0), silently losing the system prompt on retries. GeminiBot has its entire try/except commented out, so any API error crashes instead of retrying.
- Incomplete features:
max_async is accepted but never enforced; route_chatbot() supports "openai:" and "anthropic:" prefixes but not "google:".
- Maintenance cost: every new provider requires a new class, a new SDK dependency, and a new copy of all the above logic.
Goal
Replace the three classes with a single implementation backed by a unified LLM interface. The prompt layer (prompter.py, agents.py, translate.py) stays unchanged — all options below use the standard messages format.
Options
Option A: OpenAI SDK + provider-compatible endpoints
Google and Anthropic now offer OpenAI-compatible endpoints. We could keep only the openai SDK and remove anthropic and google-genai from dependencies. One ChatBot class handles all providers by varying base_url and api_key.
- Pros: zero new dependencies (removes two); no extra cost or latency.
- Cons: compatibility endpoints are relatively new and may not expose all provider-specific features; retry and fee tracking still maintained by us.
Option B: LiteLLM
LiteLLM provides litellm.acompletion() across 100+ providers with built-in retry, fallback, and usage tracking. Its core dependencies (openai, httpx, tiktoken, pydantic, etc.) largely overlap with what openlrc already has, so the actual new footprint is small.
- Pros: built-in retry/fallback and cost tracking; 100+ providers out of the box; actively maintained (42k+ stars).
- Cons: adds a dependency; one more abstraction layer between us and the provider.
Option C: OpenRouter (service)
OpenRouter is a cloud proxy with an OpenAI-compatible endpoint for 300+ models. openlrc already partially uses it (GPTBot._resolve_client_settings() has OpenRouter fallback, README recommends OPENROUTER_API_KEY).
- Pros: simplest code change — keep only
GPTBot, remove the other two classes; automatic provider-side fallback.
- Cons: OpenRouter charges a 5.5% fee on every credit purchase (with a $0.80 minimum). While per-token inference prices match the providers directly, this upfront fee is unavoidable and adds up for heavy users. Also adds network latency (extra hop through OpenRouter's proxy), and creates a hard dependency on a single commercial service — if OpenRouter goes down, all LLM calls fail.
Discussion
- Which option best fits the project?
- Are there provider-specific features (e.g. Gemini safety settings) that must be preserved?
- Should
models.py be kept for fee estimation, or delegate cost tracking to the chosen solution?
Problem
chatbot.pymaintains three separate classes (GPTBot,ClaudeBot,GeminiBot), each wrapping a different SDK. This has led to:ClaudeBotmutates the input message list viamessages.pop(0), silently losing the system prompt on retries.GeminiBothas its entiretry/exceptcommented out, so any API error crashes instead of retrying.max_asyncis accepted but never enforced;route_chatbot()supports"openai:"and"anthropic:"prefixes but not"google:".Goal
Replace the three classes with a single implementation backed by a unified LLM interface. The prompt layer (
prompter.py,agents.py,translate.py) stays unchanged — all options below use the standardmessagesformat.Options
Option A: OpenAI SDK + provider-compatible endpoints
Google and Anthropic now offer OpenAI-compatible endpoints. We could keep only the
openaiSDK and removeanthropicandgoogle-genaifrom dependencies. OneChatBotclass handles all providers by varyingbase_urlandapi_key.Option B: LiteLLM
LiteLLM provides
litellm.acompletion()across 100+ providers with built-in retry, fallback, and usage tracking. Its core dependencies (openai,httpx,tiktoken,pydantic, etc.) largely overlap with what openlrc already has, so the actual new footprint is small.Option C: OpenRouter (service)
OpenRouter is a cloud proxy with an OpenAI-compatible endpoint for 300+ models. openlrc already partially uses it (
GPTBot._resolve_client_settings()has OpenRouter fallback, README recommendsOPENROUTER_API_KEY).GPTBot, remove the other two classes; automatic provider-side fallback.Discussion
models.pybe kept for fee estimation, or delegate cost tracking to the chosen solution?