refactor: address code review feedback on AgentLoop.from_config()

- Accept optional `provider` kwarg in from_config() to avoid double
  instantiation in _run_gateway (which already builds provider_snapshot)
- Restore try/except ValueError wrappers in serve() and agent() for
  clean error messages on provider creation failure
- Update test: _FakeAgentLoop captures provider from kwargs, restore
  strong assertion (seen["provider"] is provider)
This commit is contained in:
chengyongru 2026-05-09 14:34:11 +08:00 committed by Xubin Ren
parent 3202f58c41
commit 733b34d685
3 changed files with 30 additions and 16 deletions

View File

@ -348,13 +348,18 @@ class AgentLoop:
bus: MessageBus | None = None,
**extra: Any,
) -> AgentLoop:
"""Create an AgentLoop from config with the common parameter set."""
"""Create an AgentLoop from config with the common parameter set.
Extra keyword arguments are forwarded to ``AgentLoop.__init__``,
allowing callers to override or extend the standard config-derived
parameters (e.g. ``cron_service``, ``session_manager``).
"""
from nanobot.providers.factory import make_provider
if bus is None:
bus = MessageBus()
defaults = config.agents.defaults
provider = make_provider(config)
provider = extra.pop("provider", None) or make_provider(config)
return cls(
bus=bus,
provider=provider,

View File

@ -543,14 +543,18 @@ def serve(
sync_workspace_templates(runtime_config.workspace_path)
bus = MessageBus()
session_manager = SessionManager(runtime_config.workspace_path)
agent_loop = AgentLoop.from_config(
runtime_config, bus,
session_manager=session_manager,
image_generation_provider_configs={
"openrouter": runtime_config.providers.openrouter,
"aihubmix": runtime_config.providers.aihubmix,
},
)
try:
agent_loop = AgentLoop.from_config(
runtime_config, bus,
session_manager=session_manager,
image_generation_provider_configs={
"openrouter": runtime_config.providers.openrouter,
"aihubmix": runtime_config.providers.aihubmix,
},
)
except ValueError as exc:
console.print(f"[red]Error: {exc}[/red]")
raise typer.Exit(1) from exc
model_name = runtime_config.agents.defaults.model
console.print(f"{__logo__} Starting OpenAI-compatible API server")
@ -650,6 +654,7 @@ def _run_gateway(
# Create agent with cron service
agent = AgentLoop.from_config(
config, bus,
provider=provider_snapshot.provider,
cron_service=cron,
session_manager=session_manager,
image_generation_provider_configs={
@ -1025,10 +1030,14 @@ def agent(
else:
logger.disable("nanobot")
agent_loop = AgentLoop.from_config(
config, bus,
cron_service=cron,
)
try:
agent_loop = AgentLoop.from_config(
config, bus,
cron_service=cron,
)
except ValueError as exc:
console.print(f"[red]Error: {exc}[/red]")
raise typer.Exit(1) from exc
restart_notice = consume_restart_notice_from_env()
if restart_notice and should_show_cli_restart_notice(restart_notice, session_id):
_print_agent_response(

View File

@ -1144,7 +1144,7 @@ def test_gateway_cron_evaluator_receives_scheduled_reminder_context(
return cls(**extra)
def __init__(self, *args, **kwargs) -> None:
self.model = "test-model"
self.provider = object()
self.provider = kwargs.get("provider", object())
self.tools = {}
async def process_direct(self, *_args, **_kwargs):
@ -1209,7 +1209,7 @@ def test_gateway_cron_evaluator_receives_scheduled_reminder_context(
assert response == "Time to stretch."
assert seen["response"] == "Time to stretch."
assert seen["provider"] is not None
assert seen["provider"] is provider
assert seen["model"] == "test-model"
assert seen["task_context"] == (
"The scheduled time has arrived. Deliver this reminder to the user now, "