personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add get_provider_models() API for listing models from each provider

Add list_models() to anthropic, openai, and google provider modules, each calling the SDK client.models.list() and returning raw dicts via model_dump(). Add get_provider_models() in think.providers.__init__ as a dispatcher to the selected provider module. Add unit tests covering anthropic/openai/google dispatch, unknown provider ValueError, and __all__ exports.

+130
+68
tests/test_provider_models.py
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2026 sol pbc 3 + 4 + from unittest.mock import Mock, patch 5 + 6 + import pytest 7 + 8 + import think.providers 9 + import think.providers.anthropic 10 + import think.providers.google 11 + import think.providers.openai 12 + from think.providers import get_provider_models 13 + 14 + 15 + def test_get_provider_models_anthropic(): 16 + model = Mock() 17 + model.model_dump.return_value = {"id": "claude-sonnet-4-20250514", "type": "model"} 18 + 19 + client = Mock() 20 + client.models.list.return_value = [model] 21 + 22 + with patch("think.providers.anthropic._get_anthropic_client", return_value=client): 23 + result = get_provider_models("anthropic") 24 + 25 + assert result == [{"id": "claude-sonnet-4-20250514", "type": "model"}] 26 + 27 + 28 + def test_get_provider_models_openai(): 29 + model = Mock() 30 + model.model_dump.return_value = {"id": "gpt-4o", "object": "model"} 31 + 32 + client = Mock() 33 + client.models.list.return_value = [model] 34 + 35 + with patch("think.providers.openai._get_openai_client", return_value=client): 36 + result = get_provider_models("openai") 37 + 38 + assert result == [{"id": "gpt-4o", "object": "model"}] 39 + 40 + 41 + def test_get_provider_models_google(): 42 + model = Mock() 43 + model.model_dump.return_value = { 44 + "name": "models/gemini-2.0-flash", 45 + "display_name": "Gemini 2.0 Flash", 46 + } 47 + 48 + client = Mock() 49 + client.models.list.return_value = [model] 50 + 51 + with patch("think.providers.google.get_or_create_client", return_value=client): 52 + result = get_provider_models("google") 53 + 54 + assert result == [ 55 + {"name": "models/gemini-2.0-flash", "display_name": "Gemini 2.0 Flash"} 56 + ] 57 + 58 + 59 + def test_get_provider_models_unknown(): 60 + with pytest.raises(ValueError): 61 + get_provider_models("bogus") 62 + 63 + 64 + def test_list_models_in_provider_all(): 65 + assert "list_models" in think.providers.anthropic.__all__ 66 + assert "list_models" in think.providers.openai.__all__ 67 + assert "list_models" in think.providers.google.__all__ 68 + assert "get_provider_models" in think.providers.__all__
+23
think/providers/__init__.py
··· 95 95 ] 96 96 97 97 98 + def get_provider_models(provider: str) -> list[dict]: 99 + """Get available models for a provider. 100 + 101 + Parameters 102 + ---------- 103 + provider 104 + Provider name (e.g., "google", "openai", "anthropic"). 105 + 106 + Returns 107 + ------- 108 + list[dict] 109 + List of raw model info objects returned by the provider API. 110 + 111 + Raises 112 + ------ 113 + ValueError 114 + If the provider is not registered. 115 + """ 116 + module = get_provider_module(provider) 117 + return module.list_models() 118 + 119 + 98 120 __all__ = [ 99 121 "PROVIDER_REGISTRY", 100 122 "PROVIDER_METADATA", 101 123 "get_provider_module", 102 124 "get_provider_list", 125 + "get_provider_models", 103 126 ]
+13
think/providers/anthropic.py
··· 552 552 ) 553 553 554 554 555 + def list_models() -> list[dict]: 556 + """List available Anthropic models. 557 + 558 + Returns 559 + ------- 560 + list[dict] 561 + List of raw model info objects from the Anthropic API. 562 + """ 563 + client = _get_anthropic_client() 564 + return [m.model_dump() for m in client.models.list()] 565 + 566 + 555 567 __all__ = [ 556 568 "run_cogitate", 557 569 "run_generate", 558 570 "run_agenerate", 571 + "list_models", 559 572 ]
+13
think/providers/google.py
··· 661 661 raise 662 662 663 663 664 + def list_models() -> list[dict]: 665 + """List available Google Gemini models. 666 + 667 + Returns 668 + ------- 669 + list[dict] 670 + List of raw model info objects from the Google Gemini API. 671 + """ 672 + client = get_or_create_client() 673 + return [m.model_dump() for m in client.models.list()] 674 + 675 + 664 676 __all__ = [ 665 677 "run_cogitate", 666 678 "run_generate", 667 679 "run_agenerate", 668 680 "get_or_create_client", 681 + "list_models", 669 682 ]
+13
think/providers/openai.py
··· 440 440 ) 441 441 442 442 443 + def list_models() -> list[dict]: 444 + """List available OpenAI models. 445 + 446 + Returns 447 + ------- 448 + list[dict] 449 + List of raw model info objects from the OpenAI API. 450 + """ 451 + client = _get_openai_client() 452 + return [m.model_dump() for m in client.models.list()] 453 + 454 + 443 455 __all__ = [ 444 456 "run_cogitate", 445 457 "run_generate", 446 458 "run_agenerate", 459 + "list_models", 447 460 ]