List available models with their metadata. Results are cached after the first successful call to avoid rate limiting. The cache is cleared when the client disconnects. If a custom ``on_list_models`` handler was provided in the client options, it is called i
(self)
| 2928 | return GetAuthStatusResponse.from_dict(result) |
| 2929 | |
| 2930 | async def list_models(self) -> list[ModelInfo]: |
| 2931 | """ |
| 2932 | List available models with their metadata. |
| 2933 | |
| 2934 | Results are cached after the first successful call to avoid rate limiting. |
| 2935 | The cache is cleared when the client disconnects. |
| 2936 | |
| 2937 | If a custom ``on_list_models`` handler was provided in the client options, |
| 2938 | it is called instead of querying the CLI server. The handler may be sync |
| 2939 | or async. |
| 2940 | |
| 2941 | Returns: |
| 2942 | A list of ModelInfo objects with model details. |
| 2943 | |
| 2944 | Raises: |
| 2945 | RuntimeError: If the client is not connected (when no custom handler is set). |
| 2946 | Exception: If not authenticated. |
| 2947 | |
| 2948 | Example: |
| 2949 | >>> models = await client.list_models() |
| 2950 | >>> for model in models: |
| 2951 | ... print(f"{model.id}: {model.name}") |
| 2952 | """ |
| 2953 | # Use asyncio lock to prevent race condition with concurrent calls |
| 2954 | async with self._models_cache_lock: |
| 2955 | # Check cache (already inside lock) |
| 2956 | if self._models_cache is not None: |
| 2957 | return list(self._models_cache) # Return a copy to prevent cache mutation |
| 2958 | |
| 2959 | if self._on_list_models: |
| 2960 | # Use custom handler instead of CLI RPC |
| 2961 | result = self._on_list_models() |
| 2962 | if inspect.isawaitable(result): |
| 2963 | models = cast(list[ModelInfo], await result) |
| 2964 | else: |
| 2965 | models = cast(list[ModelInfo], result) |
| 2966 | else: |
| 2967 | if not self._client: |
| 2968 | raise RuntimeError("Client not connected") |
| 2969 | |
| 2970 | # Cache miss - fetch from backend while holding lock |
| 2971 | response = await self._client.request("models.list", {}) |
| 2972 | models_data = response.get("models", []) |
| 2973 | models = [ModelInfo.from_dict(model) for model in models_data] |
| 2974 | |
| 2975 | # Update cache before releasing lock (copy to prevent external mutation) |
| 2976 | self._models_cache = list(models) |
| 2977 | |
| 2978 | return list(models) # Return a copy to prevent cache mutation |
| 2979 | |
| 2980 | async def list_sessions(self, filter: SessionListFilter | None = None) -> list[SessionMetadata]: |
| 2981 | """ |