Coverage for src/lilbee/server/handlers/agent_config.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-11-06 08:17 +0000

1"""Agent-client config handlers for the HTTP server.""" 

2 

3from __future__ import annotations 

4 

5import asyncio 

6 

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, with_configured_chat 

15from lilbee.app.services import get_services 

16from lilbee.core.config import cfg 

17from lilbee.server.auth import session_manager 

18from lilbee.server.models import AgentConfigIndexResponse, AgentConfigResponse 

19 

20 

21async def agent_config_index() -> AgentConfigIndexResponse: 

22 """Every supported client, with whether its CLI is installed on this machine.""" 

23 # Probing walks PATH and stats candidate directories; keep it off the loop. 

24 detections = await asyncio.to_thread(detect_agent_clients) 

25 return AgentConfigIndexResponse.from_detections(detections) 

26 

27 

28async def agent_config(client: AgentClient, base_url: str) -> AgentConfigResponse: 

29 """One client's config, carrying *base_url* and this server's current token.""" 

30 # The registry walk and the served-window probe both block. 

31 document = await asyncio.to_thread(_build_document, client, base_url) 

32 return AgentConfigResponse.from_document(document) 

33 

34 

35def _model_inputs(client: AgentClient) -> tuple[list[str] | None, int | None]: 

36 """The chat refs and served window to advertise, or ``None`` for an MCP-only client.""" 

37 if not client_serves_models(client): 

38 return None, None 

39 refs = with_configured_chat(installed_chat_model_refs(), cfg.chat_model) 

40 return refs, get_services().provider.served_chat_ctx() 

41 

42 

43def _build_document(client: AgentClient, base_url: str) -> AgentConfigDocument: 

44 """Assemble *client*'s document from live server state.""" 

45 model_refs, chat_ctx = _model_inputs(client) 

46 return build_agent_config( 

47 client, 

48 base_url=base_url, 

49 # A server with auth disabled accepts an empty bearer, which is what a 

50 # client configured from it should send. 

51 api_key=session_manager.token or "", 

52 model_refs=model_refs, 

53 default_ref=str(cfg.chat_model) if model_refs is not None else None, 

54 chat_ctx=chat_ctx, 

55 )