Coverage for src/lilbee/server/handlers/agent_config.py: 100%
24 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
1"""Agent-client config handlers for the HTTP server."""
3from __future__ import annotations
5import asyncio
7from lilbee.app.agent_configs.detect import detect_agent_clients
8from lilbee.app.agent_configs.document import (
9 AgentClient,
10 AgentConfigDocument,
11 build_agent_config,
12 client_serves_models,
13)
14from lilbee.app.models import installed_chat_model_refs
15from lilbee.app.services import get_services
16from lilbee.core.config import cfg
17from lilbee.providers.model_ref import with_configured_remote_chat
18from lilbee.server.auth import session_manager
19from lilbee.server.models import AgentConfigIndexResponse, AgentConfigResponse
22async def agent_config_index() -> AgentConfigIndexResponse:
23 """Every supported client, with whether its CLI is installed on this machine."""
24 # Probing walks PATH and stats candidate directories; keep it off the loop.
25 detections = await asyncio.to_thread(detect_agent_clients)
26 return AgentConfigIndexResponse.from_detections(detections)
29async def agent_config(client: AgentClient, base_url: str) -> AgentConfigResponse:
30 """One client's config, carrying *base_url* and this server's current token."""
31 # The registry walk and the served-window probe both block.
32 document = await asyncio.to_thread(_build_document, client, base_url)
33 return AgentConfigResponse.from_document(document)
36def _model_inputs(client: AgentClient) -> tuple[list[str] | None, int | None]:
37 """The chat refs and served window to advertise, or ``None`` for an MCP-only client."""
38 if not client_serves_models(client):
39 return None, None
40 refs = with_configured_remote_chat(installed_chat_model_refs(), cfg.chat_model)
41 return refs, get_services().provider.served_chat_ctx()
44def _build_document(client: AgentClient, base_url: str) -> AgentConfigDocument:
45 """Assemble *client*'s document from live server state."""
46 model_refs, chat_ctx = _model_inputs(client)
47 return build_agent_config(
48 client,
49 base_url=base_url,
50 # A server with auth disabled accepts an empty bearer, which is what a
51 # client configured from it should send.
52 api_key=session_manager.token or "",
53 model_refs=model_refs,
54 default_ref=str(cfg.chat_model) if model_refs is not None else None,
55 chat_ctx=chat_ctx,
56 )