feat(runner): support fallback candidates

Resolve fallbackModels as preset references or explicit inline provider configs so failover uses complete model settings without exposing fallback logic to the agent loop.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Xubin Ren
2026-05-13 15:34:03 +00:00
co-authored by Cursor
parent 43db848db0
commit 5efd67919b
5 changed files with 502 additions and 59 deletions
+18 -1
View File
@@ -74,6 +74,20 @@ class DreamConfig(Base):
return f"every {hours}h"
class InlineFallbackConfig(Base):
"""One inline fallback model configuration."""
model: str
provider: str
max_tokens: int | None = None
context_window_tokens: int | None = None
temperature: float | None = None
reasoning_effort: str | None = None
FallbackCandidate = str | InlineFallbackConfig
class ModelPresetConfig(Base):
"""A named set of model + generation parameters for quick switching."""
@@ -83,7 +97,6 @@ class ModelPresetConfig(Base):
context_window_tokens: int = 65_536
temperature: float = 0.1
reasoning_effort: str | None = None
fallback_models: list[str] = Field(default_factory=list)
def to_generation_settings(self) -> Any:
from nanobot.providers.base import GenerationSettings
@@ -107,6 +120,7 @@ class AgentDefaults(Base):
context_window_tokens: int = 65_536
context_block_limit: int | None = None
temperature: float = 0.1
fallback_models: list[FallbackCandidate] = Field(default_factory=list)
max_tool_iterations: int = 200
max_concurrent_subagents: int = Field(default=1, ge=1)
max_tool_result_chars: int = 16_000
@@ -288,6 +302,9 @@ class Config(BaseSettings):
name = self.agents.defaults.model_preset
if name and name != "default" and name not in self.model_presets:
raise ValueError(f"model_preset {name!r} not found in model_presets")
for fallback in self.agents.defaults.fallback_models:
if isinstance(fallback, str) and fallback not in self.model_presets:
raise ValueError(f"fallback_models entry {fallback!r} not found in model_presets")
return self
def resolve_default_preset(self) -> ModelPresetConfig: