llama-stack-mirror/src/llama_stack/core
Ashwin Bharambe da8f014b96
feat(models): list models available via provider_data header (#3968)
## Summary

When users provide API keys via `X-LlamaStack-Provider-Data` header,
`models.list()` now returns models they can access from those providers,
not just pre-registered models from the registry.

This complements the routing fix from f88416ef8 which enabled inference
calls with `provider_id/model_id` format for unregistered models. Users
can now discover which models are available to them before making
inference requests.

The implementation reuses
`NeedsRequestProviderData.get_request_provider_data()` to validate
credentials, then dynamically fetches models from providers without
caching them since they're user-specific. Registry models take
precedence to respect any pre-configured aliases.

## Test Script

```python
#!/usr/bin/env python3
import json
import os
from openai import OpenAI

# Test 1: Without provider_data header
client = OpenAI(base_url="http://localhost:8321/v1/openai/v1", api_key="dummy")
models = client.models.list()
anthropic_without = [m.id for m in models.data if m.id and "anthropic" in m.id]
print(f"Without header: {len(models.data)} models, {len(anthropic_without)} anthropic")

# Test 2: With provider_data header containing Anthropic API key
anthropic_api_key = os.environ["ANTHROPIC_API_KEY"]
client_with_key = OpenAI(
    base_url="http://localhost:8321/v1/openai/v1",
    api_key="dummy",
    default_headers={
        "X-LlamaStack-Provider-Data": json.dumps({"anthropic_api_key": anthropic_api_key})
    }
)
models_with_key = client_with_key.models.list()
anthropic_with = [m.id for m in models_with_key.data if m.id and "anthropic" in m.id]
print(f"With header: {len(models_with_key.data)} models, {len(anthropic_with)} anthropic")
print(f"Anthropic models: {anthropic_with}")

assert len(anthropic_with) > len(anthropic_without), "Should have more anthropic models with API key"
print("\n✓ Test passed!")
```

Run with a stack that has Anthropic provider configured (but without API
key in config):
```bash
ANTHROPIC_API_KEY=sk-ant-... python test_provider_data_models.py
```
2025-10-29 14:03:03 -07:00
..
access_control chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
conversations fix: add missing shutdown methods to PromptServiceImpl and ConversationServiceImpl (#3925) 2025-10-27 13:41:38 -07:00
prompts fix: add missing shutdown methods to PromptServiceImpl and ConversationServiceImpl (#3925) 2025-10-27 13:41:38 -07:00
routers chore: remove unused methods from InferenceRouter (#3953) 2025-10-28 17:12:41 -07:00
routing_tables feat(models): list models available via provider_data header (#3968) 2025-10-29 14:03:03 -07:00
server fix(mypy): resolve provider utility and testing type issues (#3935) 2025-10-28 10:37:27 -07:00
storage chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
store chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
telemetry fix(mypy): resolve OpenTelemetry typing issues in telemetry.py (#3943) 2025-10-28 10:10:18 -07:00
ui chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
utils fix(context): prevent provider data leak between streaming requests (#3924) 2025-10-27 23:01:12 -07:00
__init__.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
build.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
client.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
common.sh chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
configure.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
datatypes.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
distribution.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
external.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
id_generation.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
inspect.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
library_client.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
providers.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
request_headers.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
resolver.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
stack.py chore(telemetry): more cleanup: remove apis.telemetry (#3919) 2025-10-27 22:20:15 -07:00
start_stack.sh chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00
testing_context.py chore(package): migrate to src/ layout (#3920) 2025-10-27 12:02:21 -07:00