From 072f084c8867a1c5c3ee096f7d88372d7e994848 Mon Sep 17 00:00:00 2001 From: al3xanndru Date: Wed, 25 Mar 2026 18:39:54 +0200 Subject: [PATCH 1/5] fix: byom not working --- .../clients/openai/chat_models.py | 11 +++++++++++ src/uipath/llm_client/settings/llmgateway/settings.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py b/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py index b448867..813ef44 100644 --- a/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py +++ b/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py @@ -60,6 +60,17 @@ async def fix_url_and_api_flavor_header_async(request: Request): self.uipath_sync_client.event_hooks["request"].append(fix_url_and_api_flavor_header) self.uipath_async_client.event_hooks["request"].append(fix_url_and_api_flavor_header_async) + correct_host = URL(base_url).host + + def fix_host_header(request: Request) -> None: + request.headers["host"] = correct_host + + async def fix_host_header_async(request: Request) -> None: + request.headers["host"] = correct_host + + self.uipath_sync_client.event_hooks["request"].append(fix_host_header) + self.uipath_async_client.event_hooks["request"].append(fix_host_header_async) + self.root_client = OpenAI( api_key="PLACEHOLDER", max_retries=0, # handled by the UiPath client diff --git a/src/uipath/llm_client/settings/llmgateway/settings.py b/src/uipath/llm_client/settings/llmgateway/settings.py index 7f2bdc7..1076668 100644 --- a/src/uipath/llm_client/settings/llmgateway/settings.py +++ b/src/uipath/llm_client/settings/llmgateway/settings.py @@ -117,7 +117,7 @@ def get_available_models(self) -> list[dict[str, Any]]: @override def validate_byo_model(self, model_info: dict[str, Any]) -> None: byom_details = model_info.get("byomDetails", {}) - operation_codes = byom_details.get("operationCodes", []) + operation_codes = byom_details.get("availableOperationCodes", []) if self.operation_code and self.operation_code not in operation_codes: raise ValueError( f"The operation code {self.operation_code} is not allowed for the model {model_info['modelName']}" From 9627a4951c6c01df1716aff8a589fac502387efd Mon Sep 17 00:00:00 2001 From: al3xanndru Date: Wed, 25 Mar 2026 18:43:48 +0200 Subject: [PATCH 2/5] fix: byom not working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrei Ancuța --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d165799..2cfea19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to `uipath_llm_client` (core package) will be documented in ## [1.5.8] - 2026-03-26 ### Fix -- Pass `base_url` to `OpenAI` and `AsyncOpenAI` constructors in `UiPathOpenAI` and `UiPathAsyncOpenAI` to ensure the correct endpoint is forwarded to the underlying SDK clients +- Set correct host for BYOM requests which resulted in 403 from cloudflare ## [1.5.7] - 2026-03-23 From 3f2f154f05f6e7aaf840b2e06ab380eb55f6cdbb Mon Sep 17 00:00:00 2001 From: Cosmin Maria Date: Thu, 26 Mar 2026 18:18:20 +0200 Subject: [PATCH 3/5] fix: use availableOperationCodes for BYOM validation, bump to 1.5.9 - Core: use availableOperationCodes field in LLMGateway BYOM validation - LangChain: remove fix_host_header event hooks from UiPathChatOpenAI - Bump both packages to 1.5.9 Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 7 ++++++- packages/uipath_langchain_client/CHANGELOG.md | 5 +++++ packages/uipath_langchain_client/pyproject.toml | 2 +- .../src/uipath_langchain_client/__version__.py | 2 +- .../clients/openai/chat_models.py | 11 ----------- src/uipath/llm_client/__version__.py | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cfea19..36c8fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,15 @@ All notable changes to `uipath_llm_client` (core package) will be documented in this file. +## [1.5.9] - 2026-03-26 + +### Fix +- Use `availableOperationCodes` field (instead of `operationCodes`) when validating BYOM operation codes + ## [1.5.8] - 2026-03-26 ### Fix -- Set correct host for BYOM requests which resulted in 403 from cloudflare +- Pass `base_url` to `OpenAI` and `AsyncOpenAI` constructors in `UiPathOpenAI` and `UiPathAsyncOpenAI` to ensure the correct endpoint is forwarded to the underlying SDK clients ## [1.5.7] - 2026-03-23 diff --git a/packages/uipath_langchain_client/CHANGELOG.md b/packages/uipath_langchain_client/CHANGELOG.md index 01559b7..dfbb01e 100644 --- a/packages/uipath_langchain_client/CHANGELOG.md +++ b/packages/uipath_langchain_client/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to `uipath_langchain_client` will be documented in this file. +## [1.5.9] - 2026-03-26 + +### Fix +- Remove `fix_host_header` event hooks from `UiPathChatOpenAI`; host header management is handled by the underlying httpx client + ## [1.5.8] - 2026-03-26 ### Fix diff --git a/packages/uipath_langchain_client/pyproject.toml b/packages/uipath_langchain_client/pyproject.toml index f4fb8c4..24d5237 100644 --- a/packages/uipath_langchain_client/pyproject.toml +++ b/packages/uipath_langchain_client/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" requires-python = ">=3.11" dependencies = [ "langchain>=1.2.13", - "uipath-llm-client>=1.5.8", + "uipath-llm-client>=1.5.9", ] [project.optional-dependencies] diff --git a/packages/uipath_langchain_client/src/uipath_langchain_client/__version__.py b/packages/uipath_langchain_client/src/uipath_langchain_client/__version__.py index 56a996d..25a37d7 100644 --- a/packages/uipath_langchain_client/src/uipath_langchain_client/__version__.py +++ b/packages/uipath_langchain_client/src/uipath_langchain_client/__version__.py @@ -1,3 +1,3 @@ __title__ = "UiPath LangChain Client" __description__ = "A Python client for interacting with UiPath's LLM services via LangChain." -__version__ = "1.5.8" +__version__ = "1.5.9" diff --git a/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py b/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py index 813ef44..b448867 100644 --- a/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py +++ b/packages/uipath_langchain_client/src/uipath_langchain_client/clients/openai/chat_models.py @@ -60,17 +60,6 @@ async def fix_url_and_api_flavor_header_async(request: Request): self.uipath_sync_client.event_hooks["request"].append(fix_url_and_api_flavor_header) self.uipath_async_client.event_hooks["request"].append(fix_url_and_api_flavor_header_async) - correct_host = URL(base_url).host - - def fix_host_header(request: Request) -> None: - request.headers["host"] = correct_host - - async def fix_host_header_async(request: Request) -> None: - request.headers["host"] = correct_host - - self.uipath_sync_client.event_hooks["request"].append(fix_host_header) - self.uipath_async_client.event_hooks["request"].append(fix_host_header_async) - self.root_client = OpenAI( api_key="PLACEHOLDER", max_retries=0, # handled by the UiPath client diff --git a/src/uipath/llm_client/__version__.py b/src/uipath/llm_client/__version__.py index 0b73842..becdd3a 100644 --- a/src/uipath/llm_client/__version__.py +++ b/src/uipath/llm_client/__version__.py @@ -1,3 +1,3 @@ __title__ = "UiPath LLM Client" __description__ = "A Python client for interacting with UiPath's LLM services." -__version__ = "1.5.8" +__version__ = "1.5.9" From d9075f2820c02a7cf757f39023d01a2d1059a52b Mon Sep 17 00:00:00 2001 From: Cosmin Maria Date: Thu, 26 Mar 2026 18:24:11 +0200 Subject: [PATCH 4/5] fix: update BYOM tests to use availableOperationCodes Co-Authored-By: Claude Sonnet 4.6 --- tests/core/test_base_client.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/core/test_base_client.py b/tests/core/test_base_client.py index 2c3928f..97cb3b7 100644 --- a/tests/core/test_base_client.py +++ b/tests/core/test_base_client.py @@ -1933,7 +1933,7 @@ def test_valid_operation_code(self, llmgw_env_vars): settings.operation_code = "code1" model_info = { "modelName": "custom-model", - "byomDetails": {"operationCodes": ["code1", "code2"]}, + "byomDetails": {"availableOperationCodes":["code1", "code2"]}, } settings.validate_byo_model(model_info) # Should not raise @@ -1943,7 +1943,7 @@ def test_invalid_operation_code_raises(self, llmgw_env_vars): settings.operation_code = "invalid-code" model_info = { "modelName": "custom-model", - "byomDetails": {"operationCodes": ["code1", "code2"]}, + "byomDetails": {"availableOperationCodes":["code1", "code2"]}, } with pytest.raises(ValueError, match="operation code"): settings.validate_byo_model(model_info) @@ -1954,7 +1954,7 @@ def test_auto_picks_first_operation_code(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"operationCodes": ["auto-code"]}, + "byomDetails": {"availableOperationCodes":["auto-code"]}, } settings.validate_byo_model(model_info) assert settings.operation_code == "auto-code" @@ -1965,7 +1965,7 @@ def test_auto_picks_first_with_warning_for_multiple(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"operationCodes": ["code1", "code2"]}, + "byomDetails": {"availableOperationCodes":["code1", "code2"]}, } with patch("uipath.llm_client.settings.llmgateway.settings.logging") as mock_logging: settings.validate_byo_model(model_info) @@ -1978,7 +1978,7 @@ def test_no_operation_codes_no_change(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"operationCodes": []}, + "byomDetails": {"availableOperationCodes":[]}, } settings.validate_byo_model(model_info) assert settings.operation_code is None From f411f5cd254619629a018ef2d18a96a3d52c39ae Mon Sep 17 00:00:00 2001 From: Cosmin Maria Date: Thu, 26 Mar 2026 18:28:01 +0200 Subject: [PATCH 5/5] chore: add pre-commit checklist to CLAUDE.md, fix test formatting Co-Authored-By: Claude Sonnet 4.6 --- .claude/CLAUDE.md | 15 +++++++++++++-- tests/core/test_base_client.py | 10 +++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index b303245..e696f11 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -95,12 +95,23 @@ Follow the existing format — newest version first, grouped by date: --- +## Pre-commit / Pre-PR Checklist + +Before every commit and before opening a PR, always run: + +```bash +ruff check && ruff format --check && pytest tests +``` + +All three must pass. Fix any lint, format, or test failures before committing. This applies when working as an AI assistant too — run the checks, fix failures, then commit. + +--- + ## PR Guidelines ### Before Opening a PR -- Run `ruff check`, `ruff format --check`, and `pyright` — all must pass. -- Run `pytest tests` — all tests must pass. +- Run the pre-commit checklist above — all must pass. - Apply versioning rules above: the CI workflow (`ci_change_version.yml`) enforces that any changed source files must have a corresponding version bump and changelog entry. ### PR Scope diff --git a/tests/core/test_base_client.py b/tests/core/test_base_client.py index 97cb3b7..4041897 100644 --- a/tests/core/test_base_client.py +++ b/tests/core/test_base_client.py @@ -1933,7 +1933,7 @@ def test_valid_operation_code(self, llmgw_env_vars): settings.operation_code = "code1" model_info = { "modelName": "custom-model", - "byomDetails": {"availableOperationCodes":["code1", "code2"]}, + "byomDetails": {"availableOperationCodes": ["code1", "code2"]}, } settings.validate_byo_model(model_info) # Should not raise @@ -1943,7 +1943,7 @@ def test_invalid_operation_code_raises(self, llmgw_env_vars): settings.operation_code = "invalid-code" model_info = { "modelName": "custom-model", - "byomDetails": {"availableOperationCodes":["code1", "code2"]}, + "byomDetails": {"availableOperationCodes": ["code1", "code2"]}, } with pytest.raises(ValueError, match="operation code"): settings.validate_byo_model(model_info) @@ -1954,7 +1954,7 @@ def test_auto_picks_first_operation_code(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"availableOperationCodes":["auto-code"]}, + "byomDetails": {"availableOperationCodes": ["auto-code"]}, } settings.validate_byo_model(model_info) assert settings.operation_code == "auto-code" @@ -1965,7 +1965,7 @@ def test_auto_picks_first_with_warning_for_multiple(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"availableOperationCodes":["code1", "code2"]}, + "byomDetails": {"availableOperationCodes": ["code1", "code2"]}, } with patch("uipath.llm_client.settings.llmgateway.settings.logging") as mock_logging: settings.validate_byo_model(model_info) @@ -1978,7 +1978,7 @@ def test_no_operation_codes_no_change(self, llmgw_env_vars): settings.operation_code = None model_info = { "modelName": "custom-model", - "byomDetails": {"availableOperationCodes":[]}, + "byomDetails": {"availableOperationCodes": []}, } settings.validate_byo_model(model_info) assert settings.operation_code is None