pygeai 0.6.0b6__py3-none-any.whl → 0.6.0b7__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.
Files changed (85) hide show
  1. pygeai/_docs/source/content/api_reference/admin.rst +161 -0
  2. pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
  3. pygeai/_docs/source/content/api_reference/auth.rst +379 -0
  4. pygeai/_docs/source/content/api_reference/health.rst +58 -0
  5. pygeai/_docs/source/content/api_reference/project.rst +20 -18
  6. pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
  7. pygeai/_docs/source/content/api_reference.rst +6 -1
  8. pygeai/_docs/source/index.rst +59 -7
  9. pygeai/_docs/source/pygeai.auth.rst +29 -0
  10. pygeai/_docs/source/pygeai.cli.commands.rst +16 -0
  11. pygeai/_docs/source/pygeai.core.utils.rst +16 -0
  12. pygeai/_docs/source/pygeai.rst +1 -0
  13. pygeai/_docs/source/pygeai.tests.auth.rst +21 -0
  14. pygeai/_docs/source/pygeai.tests.cli.commands.rst +16 -0
  15. pygeai/_docs/source/pygeai.tests.core.base.rst +8 -0
  16. pygeai/_docs/source/pygeai.tests.core.files.rst +8 -0
  17. pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
  18. pygeai/_docs/source/pygeai.tests.core.rst +1 -0
  19. pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
  20. pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
  21. pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
  22. pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
  23. pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +8 -0
  24. pygeai/_docs/source/pygeai.tests.organization.rst +8 -0
  25. pygeai/_docs/source/pygeai.tests.rst +2 -0
  26. pygeai/_docs/source/pygeai.tests.snippets.auth.rst +10 -0
  27. pygeai/_docs/source/pygeai.tests.snippets.organization.rst +40 -0
  28. pygeai/_docs/source/pygeai.tests.snippets.rst +1 -0
  29. pygeai/admin/clients.py +7 -32
  30. pygeai/assistant/clients.py +9 -44
  31. pygeai/assistant/data/clients.py +1 -0
  32. pygeai/assistant/data_analyst/clients.py +4 -13
  33. pygeai/assistant/rag/clients.py +13 -67
  34. pygeai/auth/clients.py +88 -14
  35. pygeai/auth/endpoints.py +4 -0
  36. pygeai/chat/clients.py +1 -0
  37. pygeai/cli/commands/auth.py +178 -2
  38. pygeai/cli/commands/lab/ai_lab.py +0 -2
  39. pygeai/cli/commands/organization.py +241 -0
  40. pygeai/core/base/clients.py +1 -0
  41. pygeai/core/embeddings/clients.py +3 -7
  42. pygeai/core/feedback/clients.py +3 -8
  43. pygeai/core/files/clients.py +5 -18
  44. pygeai/core/llm/clients.py +7 -26
  45. pygeai/core/models.py +107 -0
  46. pygeai/core/plugins/clients.py +3 -7
  47. pygeai/core/rerank/clients.py +3 -8
  48. pygeai/core/secrets/clients.py +8 -37
  49. pygeai/core/utils/parsers.py +32 -0
  50. pygeai/core/utils/validators.py +10 -0
  51. pygeai/evaluation/clients.py +1 -0
  52. pygeai/evaluation/dataset/clients.py +1 -0
  53. pygeai/evaluation/plan/clients.py +1 -0
  54. pygeai/evaluation/result/clients.py +1 -0
  55. pygeai/gam/clients.py +6 -25
  56. pygeai/health/clients.py +3 -7
  57. pygeai/lab/agents/clients.py +13 -53
  58. pygeai/lab/agents/endpoints.py +2 -0
  59. pygeai/lab/clients.py +1 -0
  60. pygeai/lab/processes/clients.py +24 -127
  61. pygeai/lab/strategies/clients.py +7 -25
  62. pygeai/lab/tools/clients.py +22 -67
  63. pygeai/lab/tools/endpoints.py +3 -0
  64. pygeai/organization/clients.py +122 -51
  65. pygeai/organization/endpoints.py +6 -1
  66. pygeai/organization/limits/clients.py +17 -91
  67. pygeai/organization/managers.py +157 -1
  68. pygeai/organization/mappers.py +76 -2
  69. pygeai/organization/responses.py +25 -1
  70. pygeai/proxy/clients.py +1 -0
  71. pygeai/tests/auth/test_clients.py +183 -7
  72. pygeai/tests/organization/test_clients.py +184 -1
  73. pygeai/tests/organization/test_managers.py +122 -1
  74. pygeai/tests/snippets/auth/__init__.py +0 -0
  75. pygeai/tests/snippets/organization/get_memberships.py +12 -0
  76. pygeai/tests/snippets/organization/get_organization_members.py +6 -0
  77. pygeai/tests/snippets/organization/get_project_members.py +6 -0
  78. pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
  79. pygeai/tests/snippets/organization/get_project_roles.py +6 -0
  80. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/METADATA +1 -1
  81. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/RECORD +85 -64
  82. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/WHEEL +0 -0
  83. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/entry_points.txt +0 -0
  84. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/licenses/LICENSE +0 -0
  85. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b7.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- import json
2
- from json import JSONDecodeError
3
1
 
4
2
  from pygeai import logger
5
3
  from pygeai.assistant.endpoints import GET_ASSISTANT_DATA_V1, CREATE_ASSISTANT_V1, UPDATE_ASSISTANT_V1, BEGIN_CONVERSATION_V1, \
@@ -8,6 +6,8 @@ from pygeai.assistant.data_analyst.endpoints import GET_DATA_ANALYST_STATUS_V1,
8
6
  from pygeai.core.base.clients import BaseClient
9
7
  from pygeai.core.common.decorators import handler_server_error
10
8
  from pygeai.core.common.exceptions import InvalidAPIResponseException
9
+ from pygeai.core.utils.validators import validate_status_code
10
+ from pygeai.core.utils.parsers import parse_json_response
11
11
 
12
12
 
13
13
  class AssistantClient(BaseClient):
@@ -31,12 +31,7 @@ class AssistantClient(BaseClient):
31
31
  "detail": detail
32
32
  }
33
33
  )
34
- try:
35
- result = response.json()
36
- return result
37
- except JSONDecodeError as e:
38
- logger.error(f"Unable to get assistant data for ID '{assistant_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
39
- raise InvalidAPIResponseException(f"Unable to get assistant data for ID '{assistant_id}': {response.text}")
34
+ return parse_json_response(response, "get assistant data for ID", assistant_id=assistant_id)
40
35
 
41
36
  def create_assistant(
42
37
  self,
@@ -88,12 +83,7 @@ class AssistantClient(BaseClient):
88
83
  endpoint=CREATE_ASSISTANT_V1,
89
84
  data=data
90
85
  )
91
- try:
92
- result = response.json()
93
- return result
94
- except JSONDecodeError as e:
95
- logger.error(f"Unable to create assistant with name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
96
- raise InvalidAPIResponseException(f"Unable to create assistant with name '{name}': {response.text}")
86
+ return parse_json_response(response, "create assistant with name", name=name)
97
87
 
98
88
  def update_assistant(
99
89
  self,
@@ -165,12 +155,7 @@ class AssistantClient(BaseClient):
165
155
  endpoint=endpoint,
166
156
  data=data
167
157
  )
168
- try:
169
- result = response.json()
170
- return result
171
- except JSONDecodeError as e:
172
- logger.error(f"Unable to update assistant with ID '{assistant_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
173
- raise InvalidAPIResponseException(f"Unable to update assistant with ID '{assistant_id}': {response.text}")
158
+ return parse_json_response(response, "update assistant", assistant_id=assistant_id)
174
159
 
175
160
  def delete_assistant(
176
161
  self,
@@ -186,12 +171,7 @@ class AssistantClient(BaseClient):
186
171
  response = self.api_service.delete(
187
172
  endpoint=endpoint
188
173
  )
189
- try:
190
- result = response.json()
191
- return result
192
- except JSONDecodeError as e:
193
- logger.error(f"Unable to delete assistant with ID '{assistant_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
194
- raise InvalidAPIResponseException(f"Unable to delete assistant with ID '{assistant_id}': {response.text}")
174
+ return parse_json_response(response, "delete assistant", assistant_id=assistant_id)
195
175
 
196
176
  def send_chat_request(
197
177
  self,
@@ -223,12 +203,7 @@ class AssistantClient(BaseClient):
223
203
  endpoint=SEND_CHAT_REQUEST_V1,
224
204
  data=data
225
205
  )
226
- try:
227
- result = response.json()
228
- return result
229
- except JSONDecodeError as e:
230
- logger.error(f"Unable to send chat request to assistant '{assistant_name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
231
- raise InvalidAPIResponseException(f"Unable to send chat request to assistant '{assistant_name}': {response.text}")
206
+ return parse_json_response(response, "send chat request to assistant", assistant_name=assistant_name)
232
207
 
233
208
  def get_request_status(
234
209
  self,
@@ -244,12 +219,7 @@ class AssistantClient(BaseClient):
244
219
  response = self.api_service.get(
245
220
  endpoint=endpoint
246
221
  )
247
- try:
248
- result = response.json()
249
- return result
250
- except JSONDecodeError as e:
251
- logger.error(f"Unable to get request status for ID '{request_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
252
- raise InvalidAPIResponseException(f"Unable to get request status for ID '{request_id}': {response.text}")
222
+ return parse_json_response(response, "get request status for ID", request_id=request_id)
253
223
 
254
224
  def cancel_request(
255
225
  self,
@@ -268,12 +238,7 @@ class AssistantClient(BaseClient):
268
238
  "requestId": request_id
269
239
  }
270
240
  )
271
- try:
272
- result = response.json()
273
- return result
274
- except JSONDecodeError as e:
275
- logger.error(f"Unable to cancel request with ID '{request_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
276
- raise InvalidAPIResponseException(f"Unable to cancel request with ID '{request_id}': {response.text}")
241
+ return parse_json_response(response, "cancel request", request_id=request_id)
277
242
 
278
243
 
279
244
 
@@ -6,6 +6,7 @@ from pygeai.assistant.endpoints import GET_ASSISTANT_DATA_V1, CREATE_ASSISTANT_V
6
6
  from pygeai.assistant.data_analyst.endpoints import GET_DATA_ANALYST_STATUS_V1, EXTEND_DATA_ANALYST_DATASET_V1
7
7
  from pygeai.core.base.clients import BaseClient
8
8
  from pygeai.core.common.decorators import handler_server_error
9
+ from pygeai.core.utils.validators import validate_status_code
9
10
 
10
11
 
11
12
  class ChatWithDataAssistantClient(AssistantClient):
@@ -1,10 +1,11 @@
1
- from json import JSONDecodeError
2
1
  from pathlib import Path
3
2
 
4
3
  from pygeai import logger
5
4
  from pygeai.assistant.clients import AssistantClient
6
5
  from pygeai.assistant.data_analyst.endpoints import GET_DATA_ANALYST_STATUS_V1, EXTEND_DATA_ANALYST_DATASET_V1
7
6
  from pygeai.core.common.exceptions import InvalidAPIResponseException
7
+ from pygeai.core.utils.validators import validate_status_code
8
+ from pygeai.core.utils.parsers import parse_json_response
8
9
 
9
10
 
10
11
  class DataAnalystAssistantClient(AssistantClient):
@@ -34,12 +35,7 @@ class DataAnalystAssistantClient(AssistantClient):
34
35
  headers=headers
35
36
  )
36
37
 
37
- try:
38
- result = response.json()
39
- return result
40
- except JSONDecodeError as e:
41
- logger.error(f"Unable to get status for assistant ID '{assistant_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
42
- raise InvalidAPIResponseException(f"Unable to get status for assistant ID '{assistant_id}': {response.text}")
38
+ return parse_json_response(response, "get status for assistant ID", assistant_id=assistant_id)
43
39
 
44
40
  def extend_dataset(
45
41
  self,
@@ -69,12 +65,7 @@ class DataAnalystAssistantClient(AssistantClient):
69
65
  endpoint=endpoint,
70
66
  files=files
71
67
  )
72
- try:
73
- result = response.json()
74
- return result
75
- except JSONDecodeError as e:
76
- logger.error(f"Unable to extend dataset for assistant ID '{assistant_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
77
- raise InvalidAPIResponseException(f"Unable to extend dataset for assistant ID '{assistant_id}': {response.text}")
68
+ return parse_json_response(response, "extend dataset for assistant ID", assistant_id=assistant_id)
78
69
  finally:
79
70
  for _, file_handle in files:
80
71
  file_handle.close()
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import logging
3
- from json import JSONDecodeError
4
3
  from pathlib import Path
5
4
  from typing import Any
6
5
 
@@ -12,6 +11,8 @@ from pygeai.core.base.clients import BaseClient
12
11
  import urllib.parse
13
12
 
14
13
  from pygeai.core.common.exceptions import InvalidAPIResponseException
14
+ from pygeai.core.utils.validators import validate_status_code
15
+ from pygeai.core.utils.parsers import parse_json_response
15
16
 
16
17
 
17
18
  class RAGAssistantClient(BaseClient):
@@ -21,22 +22,12 @@ class RAGAssistantClient(BaseClient):
21
22
 
22
23
  def get_assistants_from_project(self) -> dict:
23
24
  response = self.api_service.get(endpoint=GET_ASSISTANTS_FROM_PROJECT_V1)
24
- try:
25
- result = response.json()
26
- return result
27
- except JSONDecodeError as e:
28
- logger.error(f"Unable to get assistants from project: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
29
- raise InvalidAPIResponseException(f"Unable to get assistants from project: {response.text}")
25
+ return parse_json_response(response, "get assistants from project")
30
26
 
31
27
  def get_assistant_data(self, name: str) -> dict:
32
28
  endpoint = GET_ASSISTANT_V1.format(name=name)
33
29
  response = self.api_service.get(endpoint=endpoint)
34
- try:
35
- result = response.json()
36
- return result
37
- except JSONDecodeError as e:
38
- logger.error(f"Unable to get assistant data for name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
39
- raise InvalidAPIResponseException(f"Unable to get assistant data for name '{name}': {response.text}")
30
+ return parse_json_response(response, "get assistant data for name", name=name)
40
31
 
41
32
  def create_assistant(
42
33
  self,
@@ -116,12 +107,7 @@ class RAGAssistantClient(BaseClient):
116
107
  endpoint=CREATE_ASSISTANT_V1,
117
108
  data=data
118
109
  )
119
- try:
120
- result = response.json()
121
- return result
122
- except JSONDecodeError as e:
123
- logger.error(f"Unable to create assistant with name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
124
- raise InvalidAPIResponseException(f"Unable to create assistant with name '{name}': {response.text}")
110
+ return parse_json_response(response, "create assistant with name", name=name)
125
111
 
126
112
  def update_assistant(
127
113
  self,
@@ -154,23 +140,13 @@ class RAGAssistantClient(BaseClient):
154
140
  endpoint=endpoint,
155
141
  data=data
156
142
  )
157
- try:
158
- result = response.json()
159
- return result
160
- except JSONDecodeError as e:
161
- logger.error(f"Unable to update assistant with name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
162
- raise InvalidAPIResponseException(f"Unable to update assistant with name '{name}': {response.text}")
143
+ return parse_json_response(response, "update assistant with name", name=name)
163
144
 
164
145
  def delete_assistant(self, name: str) -> dict:
165
146
  safe_name = self.get_url_safe_name(name)
166
147
  endpoint = DELETE_ASSISTANT_V1.format(name=safe_name)
167
148
  response = self.api_service.delete(endpoint=endpoint)
168
- try:
169
- result = response.json()
170
- return result
171
- except JSONDecodeError as e:
172
- logger.error(f"Unable to delete assistant with name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
173
- raise InvalidAPIResponseException(f"Unable to delete assistant with name '{name}': {response.text}")
149
+ return parse_json_response(response, "delete assistant with name", name=name)
174
150
 
175
151
  def get_documents(
176
152
  self,
@@ -187,34 +163,19 @@ class RAGAssistantClient(BaseClient):
187
163
  "count": count
188
164
  }
189
165
  )
190
- try:
191
- result = response.json()
192
- return result
193
- except JSONDecodeError as e:
194
- logger.error(f"Unable to get documents for assistant '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
195
- raise InvalidAPIResponseException(f"Unable to get documents for assistant '{name}': {response.text}")
166
+ return parse_json_response(response, "get documents for assistant", name=name)
196
167
 
197
168
  def delete_all_documents(self, name: str) -> dict:
198
169
  safe_name = self.get_url_safe_name(name)
199
170
  endpoint = DELETE_ALL_DOCUMENTS_V1.format(name=safe_name)
200
171
  response = self.api_service.delete(endpoint=endpoint)
201
- try:
202
- result = response.json()
203
- return result
204
- except JSONDecodeError as e:
205
- logger.error(f"Unable to delete all documents for assistant '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
206
- raise InvalidAPIResponseException(f"Unable to delete all documents for assistant '{name}': {response.text}")
172
+ return parse_json_response(response, "delete all documents for assistant", name=name)
207
173
 
208
174
  def retrieve_document(self, name: str, document_id: str) -> dict:
209
175
  safe_name = self.get_url_safe_name(name)
210
176
  endpoint = RETRIEVE_DOCUMENT_V1.format(name=safe_name, id=document_id)
211
177
  response = self.api_service.get(endpoint=endpoint)
212
- try:
213
- result = response.json()
214
- return result
215
- except JSONDecodeError as e:
216
- logger.error(f"Unable to retrieve document with ID '{document_id}' for assistant '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
217
- raise InvalidAPIResponseException(f"Unable to retrieve document with ID '{document_id}' for assistant '{name}': {response.text}")
178
+ return parse_json_response(response, "retrieve document", document_id=document_id)
218
179
 
219
180
  def upload_document(
220
181
  self,
@@ -234,12 +195,7 @@ class RAGAssistantClient(BaseClient):
234
195
  else:
235
196
  raise ValueError("Invalid upload_type. Use 'binary' or 'multipart'.")
236
197
 
237
- try:
238
- result = response.json()
239
- return result
240
- except JSONDecodeError as e:
241
- logger.error(f"Unable to upload document for assistant '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
242
- raise InvalidAPIResponseException(f"Unable to upload document for assistant '{name}': {response.text}")
198
+ return parse_json_response(response, "upload document for assistant", name=name)
243
199
 
244
200
  def _upload_binary_document(self, endpoint: str, file_path: str, content_type: str):
245
201
  """
@@ -310,22 +266,12 @@ class RAGAssistantClient(BaseClient):
310
266
  safe_name = self.get_url_safe_name(name)
311
267
  endpoint = DELETE_DOCUMENT_V1.format(name=safe_name, id=document_id)
312
268
  response = self.api_service.delete(endpoint=endpoint)
313
- try:
314
- result = response.json()
315
- return result
316
- except JSONDecodeError as e:
317
- logger.error(f"Unable to delete document with ID '{document_id}' for assistant '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
318
- raise InvalidAPIResponseException(f"Unable to delete document with ID '{document_id}' for assistant '{name}': {response.text}")
269
+ return parse_json_response(response, "delete document", document_id=document_id)
319
270
 
320
271
  def execute_query(self, query: dict) -> dict:
321
272
  response = self.api_service.post(
322
273
  endpoint=EXECUTE_QUERY_V1,
323
274
  data=query
324
275
  )
325
- try:
326
- result = response.json()
327
- return result
328
- except JSONDecodeError as e:
329
- logger.error(f"Unable to execute query: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
330
- raise InvalidAPIResponseException(f"Unable to execute query: {response.text}")
276
+ return parse_json_response(response, "execute query")
331
277
 
pygeai/auth/clients.py CHANGED
@@ -1,9 +1,10 @@
1
- from json import JSONDecodeError
2
-
3
1
  from pygeai import logger
4
- from pygeai.auth.endpoints import GET_USER_PROFILE_INFO, GET_OAUTH2_ACCESS_TOKEN
2
+ from pygeai.auth.endpoints import GET_USER_PROFILE_INFO, GET_OAUTH2_ACCESS_TOKEN, \
3
+ CREATE_PROJECT_API_TOKEN_V2, DELETE_PROJECT_API_TOKEN_V2, UPDATE_PROJECT_API_TOKEN_V2, GET_PROJECT_API_TOKEN_V2
5
4
  from pygeai.core.base.clients import BaseClient
6
- from pygeai.core.common.exceptions import InvalidAPIResponseException
5
+ from pygeai.core.common.exceptions import InvalidAPIResponseException, APIResponseError
6
+ from pygeai.core.utils.validators import validate_status_code
7
+ from pygeai.core.utils.parsers import parse_json_response
7
8
 
8
9
 
9
10
  class AuthClient(BaseClient):
@@ -33,11 +34,8 @@ class AuthClient(BaseClient):
33
34
  "password": password
34
35
  }
35
36
  )
36
- try:
37
- return response.json()
38
- except JSONDecodeError as e:
39
- logger.error(f"Unable to obtain Oauth2 access token: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
40
- raise InvalidAPIResponseException(f"Unable to obtain Oauth2 access token: {response.text}")
37
+ validate_status_code(response)
38
+ return parse_json_response(response, "obtain Oauth2 access token")
41
39
 
42
40
  def get_user_profile_information(self, access_token: str) -> dict:
43
41
  """
@@ -48,8 +46,84 @@ class AuthClient(BaseClient):
48
46
  """
49
47
  self.api_service.token = access_token
50
48
  response = self.api_service.get(endpoint=GET_USER_PROFILE_INFO)
51
- try:
52
- return response.json()
53
- except JSONDecodeError as e:
54
- logger.error(f"Unable to retrieve user profile information: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
55
- raise InvalidAPIResponseException(f"Unable to retrieve user profile information: {response.text}")
49
+ validate_status_code(response)
50
+ return parse_json_response(response, "retrieve user profile information")
51
+
52
+ def create_project_api_token(
53
+ self,
54
+ project_id: str,
55
+ name: str,
56
+ description: str = None
57
+ ) -> dict:
58
+ """
59
+ Creates a new API token for a project.
60
+
61
+ :param project_id: str - The project identifier (required). Will be sent as header.
62
+ :param name: str - The name of the API token (required).
63
+ :param description: str - A description of the API token (optional).
64
+ :return: dict - The API response containing the created API token details in JSON format.
65
+ """
66
+ headers = {"project-id": project_id}
67
+ data = {"name": name}
68
+ if description:
69
+ data["description"] = description
70
+
71
+ response = self.api_service.post(
72
+ endpoint=CREATE_PROJECT_API_TOKEN_V2,
73
+ data=data,
74
+ headers=headers
75
+ )
76
+ validate_status_code(response)
77
+ return parse_json_response(response, "create project API token")
78
+
79
+ def delete_project_api_token(self, api_token_id: str) -> dict:
80
+ """
81
+ Revokes an API token by setting its status to "revoked".
82
+
83
+ :param api_token_id: str - The unique identifier of the API token to delete (required).
84
+ :return: dict - The API response confirming the deletion, in JSON format.
85
+ """
86
+ endpoint = DELETE_PROJECT_API_TOKEN_V2.format(id=api_token_id)
87
+ response = self.api_service.delete(endpoint=endpoint)
88
+ validate_status_code(response)
89
+ return parse_json_response(response, "delete project API token", api_token_id=api_token_id)
90
+
91
+ def update_project_api_token(
92
+ self,
93
+ api_token_id: str,
94
+ description: str = None,
95
+ status: str = None
96
+ ) -> dict:
97
+ """
98
+ Updates an existing API token's description and/or status.
99
+
100
+ :param api_token_id: str - The unique identifier of the API token to update (required).
101
+ :param description: str - A new description for the API token (optional).
102
+ :param status: str - The new status for the API token: 'active' or 'blocked' (optional).
103
+ :return: dict - The API response containing the update result messages in JSON format.
104
+ """
105
+ endpoint = UPDATE_PROJECT_API_TOKEN_V2.format(id=api_token_id)
106
+ data = {}
107
+ if description is not None:
108
+ data["description"] = description
109
+ if status is not None:
110
+ data["status"] = status
111
+
112
+ response = self.api_service.put(
113
+ endpoint=endpoint,
114
+ data=data
115
+ )
116
+ validate_status_code(response)
117
+ return parse_json_response(response, "update project API token", api_token_id=api_token_id)
118
+
119
+ def get_project_api_token(self, api_token_id: str) -> dict:
120
+ """
121
+ Retrieves data for a specific project API token.
122
+
123
+ :param api_token_id: str - The unique identifier of the API token (required).
124
+ :return: dict - The API response containing the API token details in JSON format.
125
+ """
126
+ endpoint = GET_PROJECT_API_TOKEN_V2.format(id=api_token_id)
127
+ response = self.api_service.get(endpoint=endpoint)
128
+ validate_status_code(response)
129
+ return parse_json_response(response, "get project API token", api_token_id=api_token_id)
pygeai/auth/endpoints.py CHANGED
@@ -1,2 +1,6 @@
1
1
  GET_OAUTH2_ACCESS_TOKEN = "/oauth/access_token" # POST -> Obtain an OAuth 2.0 access token
2
2
  GET_USER_PROFILE_INFO = "/openid/userinfo" # GET -> Retrieve user profile information
3
+ CREATE_PROJECT_API_TOKEN_V2 = "v2/projects/tokens" # POST -> Create a new API token for a project
4
+ DELETE_PROJECT_API_TOKEN_V2 = "v2/projects/tokens/{id}" # DELETE -> Revoke an API token
5
+ UPDATE_PROJECT_API_TOKEN_V2 = "v2/projects/tokens/{id}" # PUT -> Update an API token
6
+ GET_PROJECT_API_TOKEN_V2 = "v2/projects/tokens/{id}" # GET -> Get data of a specific project API token
pygeai/chat/clients.py CHANGED
@@ -6,6 +6,7 @@ from pygeai import logger
6
6
  from pygeai.chat.endpoints import CHAT_V1, GENERATE_IMAGE_V1
7
7
  from pygeai.core.base.clients import BaseClient
8
8
  from pygeai.core.common.exceptions import InvalidAPIResponseException
9
+ from pygeai.core.utils.validators import validate_status_code
9
10
 
10
11
 
11
12
  class ChatClient(BaseClient):
@@ -92,6 +92,146 @@ get_user_profile_information_options = [
92
92
  ]
93
93
 
94
94
 
95
+ def create_project_api_token(option_list: list):
96
+ project_id = None
97
+ name = None
98
+ description = None
99
+ for option_flag, option_arg in option_list:
100
+ if option_flag.name == "project_id":
101
+ project_id = option_arg
102
+ if option_flag.name == "name":
103
+ name = option_arg
104
+ if option_flag.name == "description":
105
+ description = option_arg
106
+
107
+ if not (project_id and name):
108
+ raise MissingRequirementException("Cannot create project API token without project-id and name")
109
+
110
+ client = AuthClient()
111
+ result = client.create_project_api_token(
112
+ project_id=project_id,
113
+ name=name,
114
+ description=description
115
+ )
116
+ Console.write_stdout(f"Project API token created: \n{result}")
117
+
118
+
119
+ create_project_api_token_options = [
120
+ Option(
121
+ "project_id",
122
+ ["--project-id", "--pid"],
123
+ "The project identifier (required).",
124
+ True
125
+ ),
126
+ Option(
127
+ "name",
128
+ ["--name", "-n"],
129
+ "The name of the API token (required).",
130
+ True
131
+ ),
132
+ Option(
133
+ "description",
134
+ ["--description", "-d"],
135
+ "A description of the API token (optional).",
136
+ True
137
+ ),
138
+ ]
139
+
140
+
141
+ def delete_project_api_token(option_list: list):
142
+ api_token_id = None
143
+ for option_flag, option_arg in option_list:
144
+ if option_flag.name == "api_token_id":
145
+ api_token_id = option_arg
146
+
147
+ if not api_token_id:
148
+ raise MissingRequirementException("Cannot delete project API token without api-token-id")
149
+
150
+ client = AuthClient()
151
+ result = client.delete_project_api_token(api_token_id=api_token_id)
152
+ Console.write_stdout(f"Project API token deleted: \n{result}")
153
+
154
+
155
+ delete_project_api_token_options = [
156
+ Option(
157
+ "api_token_id",
158
+ ["--api-token-id", "--tid"],
159
+ "The unique identifier of the API token to delete (required).",
160
+ True
161
+ ),
162
+ ]
163
+
164
+
165
+ def update_project_api_token(option_list: list):
166
+ api_token_id = None
167
+ description = None
168
+ status = None
169
+ for option_flag, option_arg in option_list:
170
+ if option_flag.name == "api_token_id":
171
+ api_token_id = option_arg
172
+ if option_flag.name == "description":
173
+ description = option_arg
174
+ if option_flag.name == "status":
175
+ status = option_arg
176
+
177
+ if not api_token_id:
178
+ raise MissingRequirementException("Cannot update project API token without api-token-id")
179
+
180
+ client = AuthClient()
181
+ result = client.update_project_api_token(
182
+ api_token_id=api_token_id,
183
+ description=description,
184
+ status=status
185
+ )
186
+ Console.write_stdout(f"Project API token updated: \n{result}")
187
+
188
+
189
+ update_project_api_token_options = [
190
+ Option(
191
+ "api_token_id",
192
+ ["--api-token-id", "--tid"],
193
+ "The unique identifier of the API token to update (required).",
194
+ True
195
+ ),
196
+ Option(
197
+ "description",
198
+ ["--description", "-d"],
199
+ "A new description for the API token (optional).",
200
+ True
201
+ ),
202
+ Option(
203
+ "status",
204
+ ["--status"],
205
+ "The new status for the API token: 'active' or 'blocked' (optional).",
206
+ True
207
+ ),
208
+ ]
209
+
210
+
211
+ def get_project_api_token(option_list: list):
212
+ api_token_id = None
213
+ for option_flag, option_arg in option_list:
214
+ if option_flag.name == "api_token_id":
215
+ api_token_id = option_arg
216
+
217
+ if not api_token_id:
218
+ raise MissingRequirementException("Cannot get project API token without api-token-id")
219
+
220
+ client = AuthClient()
221
+ result = client.get_project_api_token(api_token_id=api_token_id)
222
+ Console.write_stdout(f"Project API token details: \n{result}")
223
+
224
+
225
+ get_project_api_token_options = [
226
+ Option(
227
+ "api_token_id",
228
+ ["--api-token-id", "--tid"],
229
+ "The unique identifier of the API token (required).",
230
+ True
231
+ ),
232
+ ]
233
+
234
+
95
235
  auth_commands = [
96
236
  Command(
97
237
  "help",
@@ -112,12 +252,48 @@ auth_commands = [
112
252
  get_oauth2_access_token_options
113
253
  ),
114
254
  Command(
115
- "get_user_profile_information_options",
255
+ "get_user_profile_information",
116
256
  ["get-user-information", "get-user-info", "gui"],
117
257
  "Retrieve user profile information",
118
- get_user_profile_information_options,
258
+ get_user_profile_information,
119
259
  ArgumentsEnum.REQUIRED,
120
260
  [],
121
261
  get_user_profile_information_options
122
262
  ),
263
+ Command(
264
+ "create_project_api_token",
265
+ ["create-project-api-token", "create-api-token", "cat"],
266
+ "Create a new API token for a project",
267
+ create_project_api_token,
268
+ ArgumentsEnum.REQUIRED,
269
+ [],
270
+ create_project_api_token_options
271
+ ),
272
+ Command(
273
+ "delete_project_api_token",
274
+ ["delete-project-api-token", "delete-api-token", "dat"],
275
+ "Revoke an API token",
276
+ delete_project_api_token,
277
+ ArgumentsEnum.REQUIRED,
278
+ [],
279
+ delete_project_api_token_options
280
+ ),
281
+ Command(
282
+ "update_project_api_token",
283
+ ["update-project-api-token", "update-api-token", "uat"],
284
+ "Update an existing API token",
285
+ update_project_api_token,
286
+ ArgumentsEnum.REQUIRED,
287
+ [],
288
+ update_project_api_token_options
289
+ ),
290
+ Command(
291
+ "get_project_api_token",
292
+ ["get-project-api-token", "get-api-token", "gat"],
293
+ "Get data of a specific project API token",
294
+ get_project_api_token,
295
+ ArgumentsEnum.REQUIRED,
296
+ [],
297
+ get_project_api_token_options
298
+ ),
123
299
  ]
@@ -472,7 +472,6 @@ def export_agent(option_list: list):
472
472
  Console.write_stdout(f"Agent spec: \n{result}")
473
473
 
474
474
 
475
-
476
475
  export_agent_options = [
477
476
  PROJECT_ID_OPTION,
478
477
  Option(
@@ -1242,7 +1241,6 @@ def export_tool(option_list: list):
1242
1241
  if option_flag.name == "file":
1243
1242
  file = option_arg
1244
1243
 
1245
-
1246
1244
  if not tool_id:
1247
1245
  raise MissingRequirementException("Tool ID must be specified.")
1248
1246