From a45bf773ffd20846a5d18e526ffa7ba30ac7cdde Mon Sep 17 00:00:00 2001 From: Imran Khan <99342205+imranrkhan13@users.noreply.github.com> Date: Mon, 19 Oct 2026 04:37:13 -0400 Subject: [PATCH 1/4] Add get, delete and reset-settings methods for chat workspaces --- meilisearch/client.py | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/meilisearch/client.py b/meilisearch/client.py index 8003f006..426635b8 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -1360,6 +1360,80 @@ def update_chat_workspace_settings( return self.http.patch(f"chats/{workspace_uid}/settings", body=settings) + def get_chat_workspace(self, workspace_uid: str) -> dict[str, Any]: + """Get a chat workspace. + + Parameters + ---------- + workspace_uid: + Unique identifier of the chat workspace. + + Returns + ------- + workspace: + Dictionary containing the workspace uid. + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + ValueError + If workspace_uid is empty or contains path separators. + """ + self._validate_chat_workspace_uid(workspace_uid) + + return self.http.get(f"chats/{workspace_uid}") + + def delete_chat_workspace(self, workspace_uid: str) -> None: + """Delete a chat workspace and its settings. + + Parameters + ---------- + workspace_uid: + Unique identifier of the chat workspace. + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + ValueError + If workspace_uid is empty or contains path separators. + """ + self._validate_chat_workspace_uid(workspace_uid) + + self.http.delete(f"chats/{workspace_uid}") + + def reset_chat_workspace_settings(self, workspace_uid: str) -> dict[str, Any]: + """Reset the settings of a chat workspace to their default values. + + Parameters + ---------- + workspace_uid: + Unique identifier of the chat workspace. + + Returns + ------- + settings: + Dictionary containing the default workspace settings. + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + ValueError + If workspace_uid is empty or contains path separators. + """ + self._validate_chat_workspace_uid(workspace_uid) + + return self.http.delete(f"chats/{workspace_uid}/settings") + + @staticmethod + def _validate_chat_workspace_uid(workspace_uid: str) -> None: + if not workspace_uid: + raise ValueError("workspace_uid is required and cannot be empty") + if "/" in workspace_uid or "\\" in workspace_uid: + raise ValueError("Invalid workspace_uid: must not contain path separators") + @staticmethod def _base64url_encode(data: bytes) -> str: return base64.urlsafe_b64encode(data).decode("utf-8").replace("=", "") From a71b3eede214c40412d66573b4e1c1b96f6190f8 Mon Sep 17 00:00:00 2001 From: Imran Khan <99342205+imranrkhan13@users.noreply.github.com> Date: Mon, 19 Oct 2026 04:37:56 -0400 Subject: [PATCH 2/4] Add tests for chat workspace methods --- tests/client/test_chat_workspaces.py | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/client/test_chat_workspaces.py diff --git a/tests/client/test_chat_workspaces.py b/tests/client/test_chat_workspaces.py new file mode 100644 index 00000000..3358b305 --- /dev/null +++ b/tests/client/test_chat_workspaces.py @@ -0,0 +1,56 @@ +import pytest + +from meilisearch.errors import MeilisearchApiError + +WORKSPACE = "test-workspace" + + +@pytest.fixture +def chat_workspace(client): + """Enable the chat completions feature and create a workspace.""" + client.update_experimental_features({"chatCompletions": True}) + client.update_chat_workspace_settings(WORKSPACE, {"source": "openAi", "apiKey": "test-key"}) + yield WORKSPACE + try: + client.delete_chat_workspace(WORKSPACE) + except MeilisearchApiError: + pass + client.update_experimental_features({"chatCompletions": False}) + + +def test_get_chat_workspace(client, chat_workspace): + """Test that an existing workspace can be fetched.""" + assert client.get_chat_workspace(chat_workspace) == {"uid": chat_workspace} + + +def test_get_chat_workspace_not_found(client, chat_workspace): + """Test that fetching an unknown workspace raises an API error.""" + with pytest.raises(MeilisearchApiError) as exc: + client.get_chat_workspace("does-not-exist") + assert exc.value.code == "chat_not_found" + + +def test_reset_chat_workspace_settings(client, chat_workspace): + """Test that resetting settings removes the stored API key.""" + result = client.reset_chat_workspace_settings(chat_workspace) + assert result["apiKey"] is None + assert client.get_chat_workspace_settings(chat_workspace)["apiKey"] is None + + +def test_delete_chat_workspace(client, chat_workspace): + """Test that a deleted workspace can no longer be fetched.""" + client.delete_chat_workspace(chat_workspace) + with pytest.raises(MeilisearchApiError) as exc: + client.get_chat_workspace(chat_workspace) + assert exc.value.code == "chat_not_found" + + +@pytest.mark.parametrize( + "method", + ["get_chat_workspace", "delete_chat_workspace", "reset_chat_workspace_settings"], +) +@pytest.mark.parametrize("uid", ["", "a/b", "a\\b"]) +def test_chat_workspace_methods_reject_invalid_uid(client, method, uid): + """Test that an empty uid or one with path separators is rejected before any request.""" + with pytest.raises(ValueError): + getattr(client, method)(uid) From 7a19e4a4f48d1665a5ca6e00407b977ef1da524e Mon Sep 17 00:00:00 2001 From: Imran Khan <99342205+imranrkhan13@users.noreply.github.com> Date: Mon, 19 Oct 2026 07:53:59 -0400 Subject: [PATCH 3/4] Update validation for workspace_uid in client.py --- meilisearch/client.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/meilisearch/client.py b/meilisearch/client.py index 426635b8..f6d64314 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -1378,7 +1378,7 @@ def get_chat_workspace(self, workspace_uid: str) -> dict[str, Any]: MeilisearchApiError An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors ValueError - If workspace_uid is empty or contains path separators. + If workspace_uid is empty or contains path separators or URL delimiters (? or #). """ self._validate_chat_workspace_uid(workspace_uid) @@ -1397,7 +1397,7 @@ def delete_chat_workspace(self, workspace_uid: str) -> None: MeilisearchApiError An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors ValueError - If workspace_uid is empty or contains path separators. + If workspace_uid is empty or contains path separators or URL delimiters (? or #). """ self._validate_chat_workspace_uid(workspace_uid) @@ -1421,7 +1421,7 @@ def reset_chat_workspace_settings(self, workspace_uid: str) -> dict[str, Any]: MeilisearchApiError An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors ValueError - If workspace_uid is empty or contains path separators. + If workspace_uid is empty or contains path separators or URL delimiters (? or #). """ self._validate_chat_workspace_uid(workspace_uid) @@ -1433,6 +1433,8 @@ def _validate_chat_workspace_uid(workspace_uid: str) -> None: raise ValueError("workspace_uid is required and cannot be empty") if "/" in workspace_uid or "\\" in workspace_uid: raise ValueError("Invalid workspace_uid: must not contain path separators") + if "?" in workspace_uid or "#" in workspace_uid: + raise ValueError("Invalid workspace_uid: must not contain URL delimiters") @staticmethod def _base64url_encode(data: bytes) -> str: From 0bbf333f75c84eeda4dd0e973ec27be50f0628fc Mon Sep 17 00:00:00 2001 From: Imran Khan <99342205+imranrkhan13@users.noreply.github.com> Date: Mon, 19 Oct 2026 07:54:38 -0400 Subject: [PATCH 4/4] Add regression tests for ? and # in chat workspace uid Updated test to include additional invalid UID cases. --- tests/client/test_chat_workspaces.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/client/test_chat_workspaces.py b/tests/client/test_chat_workspaces.py index 3358b305..f6e41692 100644 --- a/tests/client/test_chat_workspaces.py +++ b/tests/client/test_chat_workspaces.py @@ -49,8 +49,8 @@ def test_delete_chat_workspace(client, chat_workspace): "method", ["get_chat_workspace", "delete_chat_workspace", "reset_chat_workspace_settings"], ) -@pytest.mark.parametrize("uid", ["", "a/b", "a\\b"]) +@pytest.mark.parametrize("uid", ["", "a/b", "a\\b", "a?b", "a#b"]) def test_chat_workspace_methods_reject_invalid_uid(client, method, uid): - """Test that an empty uid or one with path separators is rejected before any request.""" + """Test that an empty uid or one with path separators or URL delimiters is rejected before any request.""" with pytest.raises(ValueError): getattr(client, method)(uid)