Fetch available OpenAI models using a provided API key file path and/or custom API URL. Used by the preferences refresh button to load models before saving.
()
| 550 | ) |
| 551 | @pga_login_required |
| 552 | def refresh_openai_models(): |
| 553 | """ |
| 554 | Fetch available OpenAI models using a provided API key file path |
| 555 | and/or custom API URL. |
| 556 | Used by the preferences refresh button to load models before saving. |
| 557 | """ |
| 558 | from pgadmin.llm.utils import ( |
| 559 | read_api_key_file, validate_api_key_path, validate_api_url |
| 560 | ) |
| 561 | |
| 562 | data = request.get_json(force=True, silent=True) or {} |
| 563 | api_key_file = data.get('api_key_file', '') |
| 564 | api_url = data.get('api_url', '') |
| 565 | |
| 566 | if api_url and not validate_api_url(api_url): |
| 567 | return make_json_response( |
| 568 | data={'models': [], |
| 569 | 'error': 'API URL is not in the allowed list. ' |
| 570 | 'Contact your administrator to update ' |
| 571 | 'ALLOWED_LLM_API_URLS in the server ' |
| 572 | 'configuration.'}, |
| 573 | status=200 |
| 574 | ) |
| 575 | |
| 576 | api_key = None |
| 577 | if api_key_file: |
| 578 | # Capture the resolved canonical path and pass it forward so |
| 579 | # the file we open is the one we just validated (avoids a |
| 580 | # symlink-swap TOCTOU between validation and read). |
| 581 | safe_path = validate_api_key_path(api_key_file) |
| 582 | if safe_path is None: |
| 583 | return make_json_response( |
| 584 | data={'models': [], |
| 585 | 'error': 'API key file path is not permitted. ' |
| 586 | 'The file must be within your private ' |
| 587 | 'user storage directory; shared storage ' |
| 588 | 'and other locations are not allowed for ' |
| 589 | 'security reasons.'}, |
| 590 | status=200 |
| 591 | ) |
| 592 | api_key = read_api_key_file(safe_path) |
| 593 | |
| 594 | if not api_key and not api_url: |
| 595 | return make_json_response( |
| 596 | data={'models': [], 'error': 'No API key or custom URL provided'}, |
| 597 | status=200 |
| 598 | ) |
| 599 | |
| 600 | try: |
| 601 | models = _fetch_openai_models(api_key, api_url) |
| 602 | return make_json_response(data={'models': models}, status=200) |
| 603 | except LLMApiError as e: |
| 604 | return make_json_response( |
| 605 | data={'models': [], 'error': str(e)}, |
| 606 | status=200 |
| 607 | ) |
| 608 | except Exception: |
| 609 | return make_json_response( |
nothing calls this directly
no test coverage detected