aixtools 0.1.10__py3-none-any.whl → 0.1.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aixtools might be problematic. Click here for more details.

Files changed (46) hide show
  1. aixtools/_version.py +2 -2
  2. aixtools/mcp/client.py +102 -1
  3. aixtools/testing/aix_test_model.py +2 -0
  4. {aixtools-0.1.10.dist-info → aixtools-0.1.11.dist-info}/METADATA +2 -1
  5. {aixtools-0.1.10.dist-info → aixtools-0.1.11.dist-info}/RECORD +8 -45
  6. aixtools-0.1.11.dist-info/top_level.txt +1 -0
  7. aixtools-0.1.10.dist-info/top_level.txt +0 -5
  8. docker/mcp-base/Dockerfile +0 -33
  9. docker/mcp-base/zscaler.crt +0 -28
  10. notebooks/example_faulty_mcp_server.ipynb +0 -74
  11. notebooks/example_mcp_server_stdio.ipynb +0 -76
  12. notebooks/example_raw_mcp_client.ipynb +0 -84
  13. notebooks/example_tool_doctor.ipynb +0 -65
  14. scripts/config.sh +0 -28
  15. scripts/lint.sh +0 -32
  16. scripts/log_view.sh +0 -18
  17. scripts/run_example_mcp_server.sh +0 -14
  18. scripts/run_faulty_mcp_server.sh +0 -13
  19. scripts/run_server.sh +0 -29
  20. scripts/test.sh +0 -30
  21. tests/__init__.py +0 -0
  22. tests/unit/__init__.py +0 -0
  23. tests/unit/a2a/__init__.py +0 -0
  24. tests/unit/a2a/google_sdk/__init__.py +0 -0
  25. tests/unit/a2a/google_sdk/pydantic_ai_adapter/__init__.py +0 -0
  26. tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_agent_executor.py +0 -188
  27. tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_storage.py +0 -156
  28. tests/unit/a2a/google_sdk/test_card.py +0 -114
  29. tests/unit/a2a/google_sdk/test_remote_agent_connection.py +0 -413
  30. tests/unit/a2a/google_sdk/test_utils.py +0 -208
  31. tests/unit/agents/__init__.py +0 -0
  32. tests/unit/agents/test_prompt.py +0 -363
  33. tests/unit/compliance/test_private_data.py +0 -329
  34. tests/unit/google/__init__.py +0 -1
  35. tests/unit/google/test_client.py +0 -233
  36. tests/unit/mcp/__init__.py +0 -0
  37. tests/unit/mcp/test_client.py +0 -242
  38. tests/unit/server/__init__.py +0 -0
  39. tests/unit/server/test_path.py +0 -225
  40. tests/unit/server/test_utils.py +0 -362
  41. tests/unit/utils/__init__.py +0 -0
  42. tests/unit/utils/test_files.py +0 -146
  43. tests/unit/vault/__init__.py +0 -0
  44. tests/unit/vault/test_vault.py +0 -246
  45. {aixtools-0.1.10.dist-info → aixtools-0.1.11.dist-info}/WHEEL +0 -0
  46. {aixtools-0.1.10.dist-info → aixtools-0.1.11.dist-info}/entry_points.txt +0 -0
@@ -1,146 +0,0 @@
1
- """Unit tests for aixtools.utils.files module."""
2
-
3
- import unittest
4
-
5
- from aixtools.utils.files import is_text_content
6
-
7
-
8
- class TestIsTextContent(unittest.TestCase):
9
- """Test cases for is_text_content function."""
10
-
11
- def test_text_mime_types_return_true(self):
12
- """Test that text mime types return True."""
13
- text_mime_types = [
14
- "text/plain",
15
- "text/html",
16
- "text/css",
17
- "text/javascript",
18
- "text/csv",
19
- "text/xml",
20
- "text/markdown",
21
- ]
22
-
23
- for mime_type in text_mime_types:
24
- with self.subTest(mime_type=mime_type):
25
- result = is_text_content(b"some content", mime_type)
26
- self.assertTrue(result, f"MIME type {mime_type} should be detected as text")
27
-
28
- def test_application_text_mime_types_return_true(self):
29
- """Test that application text-like mime types return True."""
30
- app_text_mime_types = [
31
- "application/json",
32
- "application/xml",
33
- "application/javascript",
34
- ]
35
-
36
- for mime_type in app_text_mime_types:
37
- with self.subTest(mime_type=mime_type):
38
- result = is_text_content(b"some content", mime_type)
39
- self.assertTrue(result, f"MIME type {mime_type} should be detected as text")
40
-
41
- def test_binary_mime_types_with_valid_utf8_return_true(self):
42
- """Test that binary mime types with valid UTF-8 content return True."""
43
- binary_mime_types = [
44
- "application/octet-stream",
45
- "image/png",
46
- "video/mp4",
47
- "application/pdf",
48
- ]
49
-
50
- utf8_content = "Hello, world! 🌍".encode("utf-8")
51
-
52
- for mime_type in binary_mime_types:
53
- with self.subTest(mime_type=mime_type):
54
- result = is_text_content(utf8_content, mime_type)
55
- self.assertTrue(result, f"Valid UTF-8 content should be detected as text even with {mime_type}")
56
-
57
- def test_binary_mime_types_with_invalid_utf8_return_false(self):
58
- """Test that binary mime types with invalid UTF-8 content return False."""
59
- binary_mime_types = [
60
- "application/octet-stream",
61
- "image/png",
62
- "video/mp4",
63
- "application/pdf",
64
- ]
65
-
66
- # Create invalid UTF-8 bytes
67
- invalid_utf8_content = b'\x80\x81\x82\x83'
68
-
69
- for mime_type in binary_mime_types:
70
- with self.subTest(mime_type=mime_type):
71
- result = is_text_content(invalid_utf8_content, mime_type)
72
- self.assertFalse(result, f"Invalid UTF-8 content should not be detected as text with {mime_type}")
73
-
74
- def test_empty_mime_type_with_valid_utf8_return_true(self):
75
- """Test that empty mime type with valid UTF-8 content returns True."""
76
- utf8_content = "Hello, world!".encode("utf-8")
77
-
78
- result = is_text_content(utf8_content, "")
79
- self.assertTrue(result)
80
-
81
- def test_empty_mime_type_with_invalid_utf8_return_false(self):
82
- """Test that empty mime type with invalid UTF-8 content returns False."""
83
- invalid_utf8_content = b'\x80\x81\x82\x83'
84
-
85
- result = is_text_content(invalid_utf8_content, "")
86
- self.assertFalse(result)
87
-
88
- def test_none_mime_type_with_valid_utf8_return_true(self):
89
- """Test that None mime type with valid UTF-8 content returns True."""
90
- utf8_content = "Hello, world!".encode("utf-8")
91
-
92
- result = is_text_content(utf8_content, None) # type: ignore
93
- self.assertTrue(result)
94
-
95
- def test_none_mime_type_with_invalid_utf8_return_false(self):
96
- """Test that None mime type with invalid UTF-8 content returns False."""
97
- invalid_utf8_content = b'\x80\x81\x82\x83'
98
-
99
- result = is_text_content(invalid_utf8_content, None) # type: ignore
100
- self.assertFalse(result)
101
-
102
- def test_empty_content_with_text_mime_type_return_true(self):
103
- """Test that empty content with text mime type returns True."""
104
- result = is_text_content(b"", "text/plain")
105
- self.assertTrue(result)
106
-
107
- def test_empty_content_with_binary_mime_type_return_true(self):
108
- """Test that empty content with binary mime type returns True (empty is valid UTF-8)."""
109
- result = is_text_content(b"", "application/octet-stream")
110
- self.assertTrue(result)
111
-
112
- def test_unicode_content_return_true(self):
113
- """Test that Unicode content is properly detected as text."""
114
- unicode_strings = [
115
- "Hello, 世界!",
116
- "Café ☕",
117
- "🚀 Rocket",
118
- "Здравствуй мир",
119
- "مرحبا بالعالم",
120
- ]
121
-
122
- for unicode_str in unicode_strings:
123
- with self.subTest(content=unicode_str):
124
- utf8_content = unicode_str.encode("utf-8")
125
- result = is_text_content(utf8_content, "application/octet-stream")
126
- self.assertTrue(result, f"Unicode string '{unicode_str}' should be detected as text")
127
-
128
- def test_binary_image_data_return_false(self):
129
- """Test that actual binary image data returns False."""
130
- # PNG file header
131
- png_header = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR'
132
-
133
- result = is_text_content(png_header, "image/png")
134
- self.assertFalse(result)
135
-
136
- def test_binary_executable_data_return_false(self):
137
- """Test that binary executable data returns False."""
138
- # Binary data with invalid UTF-8 sequences
139
- binary_data = b'\x7f\x80\x81\x82\x83\x84\x85\x86'
140
-
141
- result = is_text_content(binary_data, "application/octet-stream")
142
- self.assertFalse(result)
143
-
144
-
145
- if __name__ == '__main__':
146
- unittest.main()
File without changes
@@ -1,246 +0,0 @@
1
- from unittest.mock import MagicMock, patch
2
-
3
- import pytest
4
- from hvac.exceptions import InvalidPath
5
-
6
- from aixtools.vault.vault import VaultAuthError, VaultClient
7
-
8
-
9
- @pytest.fixture
10
- def patched_vault_client():
11
- with patch("aixtools.vault.vault.hvac.Client") as mock_hvac_client_cls:
12
- fake_hvac_client = MagicMock()
13
- fake_hvac_client.is_authenticated.return_value = True
14
- mock_hvac_client_cls.return_value = fake_hvac_client
15
-
16
- client = VaultClient()
17
- return client
18
-
19
-
20
- @pytest.fixture
21
- def valid_params():
22
- return {
23
- "vault_mount_point": "secret",
24
- "path_prefix": "path",
25
- "env": "dev",
26
- "user_id": "test-user",
27
- "service_name": "test-service",
28
- "user_api_key": "test-api-key",
29
- }
30
-
31
-
32
- def test_store_user_service_api_key_success(patched_vault_client, valid_params):
33
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.return_value = {}
34
-
35
- patched_vault_client.store_user_service_api_key(
36
- user_id=valid_params["user_id"],
37
- service_name=valid_params["service_name"],
38
- user_api_key=valid_params["user_api_key"],
39
- )
40
-
41
- secret_path = (
42
- f"{valid_params['path_prefix']}/{valid_params['env']}/{valid_params['user_id']}/{valid_params['service_name']}"
43
- )
44
-
45
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.assert_called_once_with(
46
- secret_path,
47
- secret={"user-api-key": valid_params["user_api_key"]},
48
- mount_point=valid_params["vault_mount_point"],
49
- )
50
-
51
-
52
- def test_store_user_service_api_key_invalid_path(patched_vault_client, valid_params):
53
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.side_effect = Exception("Invalid Path")
54
-
55
- with pytest.raises(VaultAuthError, match="Invalid Path"):
56
- patched_vault_client.store_user_service_api_key(
57
- user_id=valid_params["user_id"],
58
- service_name=valid_params["service_name"],
59
- user_api_key=valid_params["user_api_key"],
60
- )
61
- patched_vault_client.client.assert_not_called()
62
-
63
-
64
- def test_read_user_service_api_key_success(patched_vault_client):
65
- """Test successful read of user service API key."""
66
- mock_response = {"data": {"data": {"user-api-key": "test-api-key"}}}
67
- patched_vault_client.client.secrets.kv.v2.read_secret_version.return_value = mock_response
68
-
69
- result = patched_vault_client.read_user_service_api_key(user_id="test-user", service_name="test-service")
70
-
71
- assert result == "test-api-key"
72
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
73
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
74
- )
75
-
76
-
77
- def test_read_user_service_api_key_secret_not_found(patched_vault_client):
78
- """Test read_user_service_api_key when the secret path does not exist."""
79
- patched_vault_client.client.secrets.kv.v2.read_secret_version.side_effect = InvalidPath
80
-
81
- result = patched_vault_client.read_user_service_api_key(user_id="test-user", service_name="test-service")
82
-
83
- assert result is None
84
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
85
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
86
- )
87
-
88
-
89
- def test_read_user_service_api_key_unexpected_error(patched_vault_client):
90
- """Test read_user_service_api_key when an unexpected exception occurs."""
91
- patched_vault_client.client.secrets.kv.v2.read_secret_version.side_effect = Exception("Unexpected error")
92
-
93
- with pytest.raises(VaultAuthError, match="Unexpected error"):
94
- patched_vault_client.read_user_service_api_key(user_id="test-user", service_name="test-service")
95
-
96
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
97
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
98
- )
99
-
100
-
101
- def test_store_user_service_secret_success(patched_vault_client, valid_params):
102
- """Test successful storage of complete user service secret."""
103
- secret_data = {"api_key": "test-api-key", "token": "test-token", "endpoint": "https://api.example.com"}
104
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.return_value = {}
105
-
106
- patched_vault_client.store_user_service_secret(
107
- user_id=valid_params["user_id"],
108
- service_name=valid_params["service_name"],
109
- secret_data=secret_data,
110
- )
111
-
112
- secret_path = (
113
- f"{valid_params['path_prefix']}/{valid_params['env']}/{valid_params['user_id']}/{valid_params['service_name']}"
114
- )
115
-
116
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.assert_called_once_with(
117
- secret_path,
118
- secret=secret_data,
119
- mount_point=valid_params["vault_mount_point"],
120
- )
121
-
122
-
123
- def test_store_user_service_secret_error(patched_vault_client, valid_params):
124
- """Test store_user_service_secret when an error occurs."""
125
- secret_data = {"api_key": "test-api-key", "token": "test-token"}
126
- patched_vault_client.client.secrets.kv.v2.create_or_update_secret.side_effect = Exception("Storage error")
127
-
128
- with pytest.raises(VaultAuthError, match="Storage error"):
129
- patched_vault_client.store_user_service_secret(
130
- user_id=valid_params["user_id"],
131
- service_name=valid_params["service_name"],
132
- secret_data=secret_data,
133
- )
134
-
135
-
136
- def test_read_user_service_secret_success(patched_vault_client):
137
- """Test successful read of complete user service secret."""
138
- secret_data = {"api_key": "test-api-key", "token": "test-token", "endpoint": "https://api.example.com"}
139
- mock_response = {"data": {"data": secret_data}}
140
- patched_vault_client.client.secrets.kv.v2.read_secret_version.return_value = mock_response
141
-
142
- result = patched_vault_client.read_user_service_secret(user_id="test-user", service_name="test-service")
143
-
144
- assert result == secret_data
145
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
146
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
147
- )
148
-
149
-
150
- def test_read_user_service_secret_not_found(patched_vault_client):
151
- """Test read_user_service_secret when the secret path does not exist."""
152
- patched_vault_client.client.secrets.kv.v2.read_secret_version.side_effect = InvalidPath
153
-
154
- result = patched_vault_client.read_user_service_secret(user_id="test-user", service_name="test-service")
155
-
156
- assert result is None
157
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
158
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
159
- )
160
-
161
-
162
- def test_list_user_secret_keys_success(patched_vault_client):
163
- """Test successful listing of all user secret keys."""
164
- mock_response = {"data": {"keys": ["service1/", "service2/", "service3"]}}
165
- patched_vault_client.client.secrets.kv.v2.list_secrets.return_value = mock_response
166
-
167
- result = patched_vault_client.list_user_secret_keys(user_id="test-user")
168
-
169
- assert result == ["service1", "service2", "service3"]
170
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
171
- path="path/dev/test-user", mount_point="secret"
172
- )
173
-
174
-
175
- def test_list_user_secret_keys_no_secrets(patched_vault_client):
176
- """Test listing user secret keys when no secrets exist."""
177
- mock_response = {"data": {"keys": []}}
178
- patched_vault_client.client.secrets.kv.v2.list_secrets.return_value = mock_response
179
-
180
- result = patched_vault_client.list_user_secret_keys(user_id="test-user")
181
-
182
- assert result == []
183
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
184
- path="path/dev/test-user", mount_point="secret"
185
- )
186
-
187
-
188
- def test_list_user_secret_keys_empty_response(patched_vault_client):
189
- """Test listing user secret keys when response is empty."""
190
- patched_vault_client.client.secrets.kv.v2.list_secrets.return_value = {}
191
-
192
- result = patched_vault_client.list_user_secret_keys(user_id="test-user")
193
-
194
- assert result == []
195
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
196
- path="path/dev/test-user", mount_point="secret"
197
- )
198
-
199
-
200
- def test_list_user_secret_keys_invalid_path(patched_vault_client):
201
- """Test listing user secret keys when user path does not exist."""
202
- patched_vault_client.client.secrets.kv.v2.list_secrets.side_effect = InvalidPath
203
-
204
- result = patched_vault_client.list_user_secret_keys(user_id="test-user")
205
-
206
- assert result == []
207
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
208
- path="path/dev/test-user", mount_point="secret"
209
- )
210
-
211
-
212
- def test_list_user_secret_keys_unexpected_error(patched_vault_client):
213
- """Test listing user secret keys when an unexpected exception occurs."""
214
- patched_vault_client.client.secrets.kv.v2.list_secrets.side_effect = Exception("List error")
215
-
216
- with pytest.raises(VaultAuthError, match="List error"):
217
- patched_vault_client.list_user_secret_keys(user_id="test-user")
218
-
219
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
220
- path="path/dev/test-user", mount_point="secret"
221
- )
222
-
223
-
224
- def test_list_user_secret_keys_strips_trailing_slashes(patched_vault_client):
225
- """Test that trailing slashes are properly stripped from directory names."""
226
- mock_response = {"data": {"keys": ["service1/", "service2/", "service3", "service4/"]}}
227
- patched_vault_client.client.secrets.kv.v2.list_secrets.return_value = mock_response
228
-
229
- result = patched_vault_client.list_user_secret_keys(user_id="test-user")
230
-
231
- assert result == ["service1", "service2", "service3", "service4"]
232
- patched_vault_client.client.secrets.kv.v2.list_secrets.assert_called_once_with(
233
- path="path/dev/test-user", mount_point="secret"
234
- )
235
-
236
-
237
- def test_read_user_service_secret_error(patched_vault_client):
238
- """Test read_user_service_secret when an unexpected exception occurs."""
239
- patched_vault_client.client.secrets.kv.v2.read_secret_version.side_effect = Exception("Read error")
240
-
241
- with pytest.raises(VaultAuthError, match="Read error"):
242
- patched_vault_client.read_user_service_secret(user_id="test-user", service_name="test-service")
243
-
244
- patched_vault_client.client.secrets.kv.v2.read_secret_version.assert_called_once_with(
245
- "path/dev/test-user/test-service", mount_point="secret", raise_on_deleted_version=True
246
- )