Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to `uipath_llm_client` (core package) will be documented in this file.

## [1.2.2] - 2026-02-23

### Fix
- Fixes to discovery endpoint on LLMGW

## [1.2.1] - 2026-02-18

### Fix
Expand Down
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,15 @@ The client supports two UiPath backends:
# Base installation (core client only)
pip install uipath-llm-client

# With LangChain support
pip install uipath-langchain-client

# With specific provider extras for passthrough mode
pip install "uipath-langchain-client[openai]" # OpenAI/Azure OpenAI models
pip install "uipath-langchain-client[google]" # Google Gemini models
pip install "uipath-langchain-client[anthropic]" # Anthropic Claude models
pip install "uipath-langchain-client[aws]" # AWS Bedrock models
pip install "uipath-langchain-client[azure]" # Azure AI models
pip install "uipath-langchain-client[vertexai]" # Google Vertex AI (Anthropic on Vertex)
pip install "uipath-langchain-client[fireworks]" # Fireworks AI models
pip install "uipath-langchain-client[all]" # All providers
# With optional provider extras for passthrough mode
pip install "uipath-llm-client[openai]" # OpenAI/Azure OpenAI models
pip install "uipath-llm-client[google]" # Google Gemini models
pip install "uipath-llm-client[anthropic]" # Anthropic Claude models
pip install "uipath-llm-client[all]" # All of the above
```

For LangChain support, use the separate package: `pip install uipath-langchain-client`.

### Using `uv`

1. Add the custom index to your `pyproject.toml`:
Expand Down
5 changes: 5 additions & 0 deletions packages/uipath_langchain_client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to `uipath_langchain_client` will be documented in this file.

## [1.2.2] - 2026-02-23

### Fix
- Fixes to discovery endpoint on LLMGW

## [1.2.1] - 2026-02-18

### Fix
Expand Down
2 changes: 1 addition & 1 deletion packages/uipath_langchain_client/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"langchain>=1.2.7",
"uipath-llm-client>=1.2.1",
"uipath-llm-client>=1.2.2",
]

[project.optional-dependencies]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__title__ = "UiPath LangChain Client"
__description__ = "A Python client for interacting with UiPath's LLM services via LangChain."
__version__ = "1.2.1"
__version__ = "1.2.2"
2 changes: 1 addition & 1 deletion src/uipath_llm_client/__version__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__titile__ = "UiPath LLM Client"
__description__ = "A Python client for interacting with UiPath's LLM services."
__version__ = "1.2.1"
__version__ = "1.2.2"
3 changes: 3 additions & 0 deletions src/uipath_llm_client/settings/llmgateway/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from uipath_llm_client.settings.base import UiPathAPIConfig, UiPathBaseSettings
from uipath_llm_client.settings.llmgateway.utils import LLMGatewayEndpoints
from uipath_llm_client.utils.exceptions import UiPathAPIError


class LLMGatewayBaseSettings(UiPathBaseSettings):
Expand Down Expand Up @@ -107,6 +108,8 @@ def get_available_models(self) -> list[dict[str, Any]]:
discovery_url = f"{self.base_url}/{self.org_id}/{self.tenant_id}/{LLMGatewayEndpoints.DISCOVERY_ENDPOINT.value}"
with Client(auth=self.build_auth_pipeline(), headers=self.build_auth_headers()) as client:
response = client.get(discovery_url)
if response.is_error:
raise UiPathAPIError.from_response(response)
return response.json()

@override
Expand Down
40 changes: 38 additions & 2 deletions tests/core/test_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,12 +318,12 @@ def test_validation_requires_auth_credentials(self):
LLMGatewaySettings()

def test_get_available_models(self, llmgw_env_vars):
"""Test get_available_models returns a list of models."""
"""Test get_available_models returns a list of models on success."""
with patch.dict(os.environ, llmgw_env_vars, clear=True):
settings = LLMGatewaySettings()

# Mock the HTTP request since this is a unit test
mock_response = MagicMock()
mock_response.is_error = False
mock_response.json.return_value = [
{"modelName": "gpt-4o", "vendor": "openai"},
{"modelName": "claude-3-opus", "vendor": "anthropic"},
Expand All @@ -334,6 +334,42 @@ def test_get_available_models(self, llmgw_env_vars):
assert isinstance(models, list)
assert len(models) == 2

def test_get_available_models_raises_on_http_error(self, llmgw_env_vars):
"""Test get_available_models raises UiPathAPIError on bad request / server error."""
with patch.dict(os.environ, llmgw_env_vars, clear=True):
settings = LLMGatewaySettings()

mock_response = MagicMock()
mock_response.is_error = True
mock_response.status_code = 500
mock_response.reason_phrase = "Internal Server Error"
mock_response.json.return_value = {"error": "Something went wrong"}
mock_response.request = MagicMock()
mock_response.text = ""

with patch.object(Client, "get", return_value=mock_response):
with pytest.raises(UiPathAPIError) as exc_info:
settings.get_available_models()
assert exc_info.value.status_code == 500

def test_get_available_models_raises_on_unauthorized(self, llmgw_env_vars):
"""Test get_available_models raises UiPathAuthenticationError on 401."""
with patch.dict(os.environ, llmgw_env_vars, clear=True):
settings = LLMGatewaySettings()

mock_response = MagicMock()
mock_response.is_error = True
mock_response.status_code = 401
mock_response.reason_phrase = "Unauthorized"
mock_response.json.return_value = {}
mock_response.request = MagicMock()
mock_response.text = ""

with patch.object(Client, "get", return_value=mock_response):
with pytest.raises(UiPathAuthenticationError) as exc_info:
settings.get_available_models()
assert exc_info.value.status_code == 401


# ============================================================================
# Test LLMGateway Auth Refresh Logic
Expand Down