Live-list embedding models from the provider's ``/models`` endpoint. Returns ``[]`` on any failure so callers can fall back to the curated list. When the provider's ``/models`` includes non-embedding models (typical for OpenAI-compatible endpoints), the result is filtered down to en
(
console: Console,
strings: dict[str, str],
*,
endpoint: str,
api_key: str,
provider: str,
)
| 653 | |
| 654 | |
| 655 | def fetch_embedding_models( |
| 656 | console: Console, |
| 657 | strings: dict[str, str], |
| 658 | *, |
| 659 | endpoint: str, |
| 660 | api_key: str, |
| 661 | provider: str, |
| 662 | ) -> list[str]: |
| 663 | """Live-list embedding models from the provider's ``/models`` endpoint. |
| 664 | |
| 665 | Returns ``[]`` on any failure so callers can fall back to the curated |
| 666 | list. When the provider's ``/models`` includes non-embedding models |
| 667 | (typical for OpenAI-compatible endpoints), the result is filtered down |
| 668 | to entries whose name looks like an embedding model. If filtering |
| 669 | leaves nothing, the unfiltered list is returned as a safety net. |
| 670 | """ |
| 671 | if not endpoint: |
| 672 | return [] |
| 673 | |
| 674 | models_url = _derive_embedding_models_url(endpoint, provider) |
| 675 | headers: dict[str, str] = {} |
| 676 | if api_key: |
| 677 | headers["Authorization"] = f"Bearer {api_key}" |
| 678 | |
| 679 | info(console, strings["init.fetch_models"].format(url=models_url)) |
| 680 | try: |
| 681 | with httpx.Client(timeout=5.0) as client: |
| 682 | response = client.get(models_url, headers=headers) |
| 683 | response.raise_for_status() |
| 684 | payload = response.json() |
| 685 | except Exception as exc: |
| 686 | warn(console, strings["init.fetch_models_fail"].format(error=str(exc)[:160])) |
| 687 | return [] |
| 688 | |
| 689 | raw_items: list[Any] = [] |
| 690 | if isinstance(payload, dict): |
| 691 | for key in ("data", "models"): |
| 692 | value = payload.get(key) |
| 693 | if isinstance(value, list): |
| 694 | raw_items = value |
| 695 | break |
| 696 | elif isinstance(payload, list): |
| 697 | raw_items = payload |
| 698 | |
| 699 | names: list[str] = [] |
| 700 | for item in raw_items: |
| 701 | if isinstance(item, str): |
| 702 | names.append(item) |
| 703 | elif isinstance(item, dict): |
| 704 | name = item.get("id") or item.get("name") or item.get("model") |
| 705 | if isinstance(name, str) and name: |
| 706 | names.append(name) |
| 707 | if not names: |
| 708 | warn(console, strings["init.fetch_models_fail"].format(error="empty model list")) |
| 709 | return [] |
| 710 | |
| 711 | # Mixed lists (OpenAI returns gpt-4o, dall-e, etc. alongside embeddings). |
| 712 | # Strict ``embed`` filter; if it matches nothing, return empty so the |
nothing calls this directly
no test coverage detected