From 856a92f0548b2b01a3bab0f6c15600d2685149e4 Mon Sep 17 00:00:00 2001 From: Yiiii0 Date: Sat, 7 Mar 2026 19:36:44 -0500 Subject: [PATCH] feat: Add Forge LLM provider support ## Changes - Automated integration updates from manager loop. Files modified: nanobot/README.md nanobot/nanobot/config/schema.py nanobot/nanobot/providers/litellm_provider.py nanobot/nanobot/providers/registry.py --- nanobot/README.md | 1 + nanobot/nanobot/config/schema.py | 1 + nanobot/nanobot/providers/litellm_provider.py | 5 ++++- nanobot/nanobot/providers/registry.py | 20 +++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/nanobot/README.md b/nanobot/README.md index d514f50b..f602d725 100644 --- a/nanobot/README.md +++ b/nanobot/README.md @@ -516,6 +516,7 @@ Config file: `~/.nanobot/config.json` | Provider | Purpose | Get API Key | |----------|---------|-------------| | `openrouter` | LLM (recommended, access to all models) | [openrouter.ai](https://openrouter.ai) | +| `forge` | LLM (API gateway, OpenAI-compatible) | [forge.tensorblock.co](https://forge.tensorblock.co) | | `anthropic` | LLM (Claude direct) | [console.anthropic.com](https://console.anthropic.com) | | `openai` | LLM (GPT direct) | [platform.openai.com](https://platform.openai.com) | | `deepseek` | LLM (DeepSeek direct) | [platform.deepseek.com](https://platform.deepseek.com) | diff --git a/nanobot/nanobot/config/schema.py b/nanobot/nanobot/config/schema.py index 5a38b32e..eaefb668 100644 --- a/nanobot/nanobot/config/schema.py +++ b/nanobot/nanobot/config/schema.py @@ -165,6 +165,7 @@ class ProvidersConfig(BaseModel): anthropic: ProviderConfig = Field(default_factory=ProviderConfig) openai: ProviderConfig = Field(default_factory=ProviderConfig) openrouter: ProviderConfig = Field(default_factory=ProviderConfig) + forge: ProviderConfig = Field(default_factory=ProviderConfig) deepseek: ProviderConfig = Field(default_factory=ProviderConfig) groq: ProviderConfig = Field(default_factory=ProviderConfig) zhipu: ProviderConfig = Field(default_factory=ProviderConfig) diff --git a/nanobot/nanobot/providers/litellm_provider.py b/nanobot/nanobot/providers/litellm_provider.py index 2dedabbe..72e7573a 100644 --- a/nanobot/nanobot/providers/litellm_provider.py +++ b/nanobot/nanobot/providers/litellm_provider.py @@ -68,7 +68,10 @@ def _setup_env(self, api_key: str, api_base: str | None, model: str) -> None: for env_name, env_val in spec.env_extras: resolved = env_val.replace("{api_key}", api_key) resolved = resolved.replace("{api_base}", effective_base) - os.environ.setdefault(env_name, resolved) + if self._gateway: + os.environ[env_name] = resolved + else: + os.environ.setdefault(env_name, resolved) def _resolve_model(self, model: str) -> str: """Resolve model name by applying provider/gateway prefixes.""" diff --git a/nanobot/nanobot/providers/registry.py b/nanobot/nanobot/providers/registry.py index 58e29d60..a0df9c04 100644 --- a/nanobot/nanobot/providers/registry.py +++ b/nanobot/nanobot/providers/registry.py @@ -80,6 +80,26 @@ def label(self) -> str: strip_model_prefix=False, model_overrides=(), ), + # Forge: OpenAI-compatible gateway. + ProviderSpec( + name="forge", + keywords=("forge",), + env_key="FORGE_API_KEY", + display_name="Forge", + litellm_prefix="openai", # route via OpenAI-compatible API + skip_prefixes=(), + env_extras=( + ("OPENAI_API_KEY", "{api_key}"), + ("FORGE_API_BASE", "{api_base}"), + ), + is_gateway=True, + is_local=False, + detect_by_key_prefix="", + detect_by_base_keyword="forge.tensorblock.co", + default_api_base="https://api.forge.tensorblock.co/v1", + strip_model_prefix=True, + model_overrides=(), + ), # AiHubMix: global gateway, OpenAI-compatible interface. # strip_model_prefix=True: it doesn't understand "anthropic/claude-3", # so we strip to bare "claude-3" then re-prefix as "openai/claude-3".