pygeai 0.6.0b11__py3-none-any.whl → 0.6.0b12__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.
- pygeai/_docs/source/content/ai_lab/cli.rst +4 -4
- pygeai/_docs/source/content/ai_lab/models.rst +169 -35
- pygeai/_docs/source/content/ai_lab/runner.rst +2 -2
- pygeai/_docs/source/content/ai_lab/spec.rst +9 -9
- pygeai/_docs/source/content/ai_lab/usage.rst +34 -34
- pygeai/_docs/source/content/ai_lab.rst +1 -1
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/chat.rst +428 -2
- pygeai/_docs/source/content/api_reference/embeddings.rst +1 -1
- pygeai/_docs/source/content/api_reference/project.rst +184 -0
- pygeai/_docs/source/content/api_reference/rag.rst +2 -2
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/cli.rst +79 -2
- pygeai/_docs/source/content/debugger.rst +1 -1
- pygeai/_docs/source/content/migration.rst +19 -2
- pygeai/_docs/source/index.rst +2 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +8 -0
- pygeai/_docs/source/pygeai.rst +1 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +8 -0
- pygeai/_docs/source/pygeai.tests.rst +1 -1
- pygeai/analytics/__init__.py +0 -0
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/cli/commands/analytics.py +525 -0
- pygeai/cli/commands/base.py +16 -0
- pygeai/cli/commands/common.py +28 -24
- pygeai/cli/commands/migrate.py +75 -6
- pygeai/cli/commands/organization.py +265 -0
- pygeai/cli/commands/validators.py +144 -1
- pygeai/cli/error_handler.py +41 -6
- pygeai/cli/geai.py +99 -16
- pygeai/cli/parsers.py +75 -31
- pygeai/cli/texts/help.py +75 -6
- pygeai/core/base/clients.py +18 -4
- pygeai/core/base/session.py +46 -7
- pygeai/core/common/config.py +25 -2
- pygeai/core/common/exceptions.py +64 -1
- pygeai/core/services/rest.py +20 -2
- pygeai/evaluation/clients.py +5 -3
- pygeai/lab/agents/clients.py +3 -3
- pygeai/lab/agents/endpoints.py +2 -2
- pygeai/lab/agents/mappers.py +50 -2
- pygeai/lab/clients.py +5 -2
- pygeai/lab/managers.py +7 -9
- pygeai/lab/models.py +70 -2
- pygeai/lab/tools/clients.py +1 -59
- pygeai/migration/__init__.py +3 -1
- pygeai/migration/strategies.py +72 -3
- pygeai/organization/clients.py +110 -1
- pygeai/organization/endpoints.py +11 -7
- pygeai/organization/managers.py +134 -2
- pygeai/organization/mappers.py +28 -2
- pygeai/organization/responses.py +11 -1
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/cli/commands/test_migrate.py +14 -1
- pygeai/tests/cli/commands/test_organization.py +69 -1
- pygeai/tests/cli/test_error_handler.py +4 -4
- pygeai/tests/cli/test_geai_driver.py +1 -1
- pygeai/tests/lab/agents/test_mappers.py +128 -1
- pygeai/tests/lab/test_models.py +2 -0
- pygeai/tests/lab/tools/test_clients.py +2 -31
- pygeai/tests/organization/test_clients.py +180 -1
- pygeai/tests/organization/test_managers.py +40 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/METADATA +1 -1
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/RECORD +102 -92
- pygeai/_docs/source/pygeai.tests.snippets.assistants.data_analyst.rst +0 -37
- pygeai/_docs/source/pygeai.tests.snippets.assistants.rag.rst +0 -85
- pygeai/_docs/source/pygeai.tests.snippets.assistants.rst +0 -78
- pygeai/_docs/source/pygeai.tests.snippets.auth.rst +0 -10
- pygeai/_docs/source/pygeai.tests.snippets.chat.rst +0 -125
- pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +0 -45
- pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +0 -61
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +0 -197
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +0 -133
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +0 -37
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +0 -20
- pygeai/_docs/source/pygeai.tests.snippets.extras.rst +0 -37
- pygeai/_docs/source/pygeai.tests.snippets.files.rst +0 -53
- pygeai/_docs/source/pygeai.tests.snippets.gam.rst +0 -21
- pygeai/_docs/source/pygeai.tests.snippets.lab.agents.rst +0 -93
- pygeai/_docs/source/pygeai.tests.snippets.lab.processes.jobs.rst +0 -21
- pygeai/_docs/source/pygeai.tests.snippets.lab.processes.kbs.rst +0 -45
- pygeai/_docs/source/pygeai.tests.snippets.lab.processes.rst +0 -46
- pygeai/_docs/source/pygeai.tests.snippets.lab.rst +0 -82
- pygeai/_docs/source/pygeai.tests.snippets.lab.samples.rst +0 -21
- pygeai/_docs/source/pygeai.tests.snippets.lab.strategies.rst +0 -45
- pygeai/_docs/source/pygeai.tests.snippets.lab.tools.rst +0 -85
- pygeai/_docs/source/pygeai.tests.snippets.lab.use_cases.rst +0 -117
- pygeai/_docs/source/pygeai.tests.snippets.migrate.rst +0 -10
- pygeai/_docs/source/pygeai.tests.snippets.organization.rst +0 -109
- pygeai/_docs/source/pygeai.tests.snippets.rag.rst +0 -85
- pygeai/_docs/source/pygeai.tests.snippets.rerank.rst +0 -21
- pygeai/_docs/source/pygeai.tests.snippets.rst +0 -32
- pygeai/_docs/source/pygeai.tests.snippets.secrets.rst +0 -10
- pygeai/_docs/source/pygeai.tests.snippets.usage_limit.rst +0 -77
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/WHEEL +0 -0
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/entry_points.txt +0 -0
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/licenses/LICENSE +0 -0
- {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b12.dist-info}/top_level.txt +0 -0
pygeai/core/common/exceptions.py
CHANGED
|
@@ -7,7 +7,20 @@ class GEAIException(Exception):
|
|
|
7
7
|
|
|
8
8
|
class UnknownArgumentError(GEAIException):
|
|
9
9
|
"""Raised when an unknown or invalid command/option is provided"""
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
def __init__(self, message: str, arg: str = None, available_commands=None, available_options=None):
|
|
12
|
+
"""
|
|
13
|
+
Initialize an UnknownArgumentError with context.
|
|
14
|
+
|
|
15
|
+
:param message: str - The error message.
|
|
16
|
+
:param arg: str - The unknown argument that was provided.
|
|
17
|
+
:param available_commands: list - Available commands for suggestion.
|
|
18
|
+
:param available_options: list - Available options for suggestion.
|
|
19
|
+
"""
|
|
20
|
+
super().__init__(message)
|
|
21
|
+
self.arg = arg
|
|
22
|
+
self.available_commands = available_commands
|
|
23
|
+
self.available_options = available_options
|
|
11
24
|
|
|
12
25
|
|
|
13
26
|
class MissingRequirementException(GEAIException):
|
|
@@ -20,6 +33,56 @@ class WrongArgumentError(GEAIException):
|
|
|
20
33
|
pass
|
|
21
34
|
|
|
22
35
|
|
|
36
|
+
class ValidationError(WrongArgumentError):
|
|
37
|
+
"""
|
|
38
|
+
Raised when input validation fails with detailed context.
|
|
39
|
+
|
|
40
|
+
Extends WrongArgumentError to provide structured validation errors
|
|
41
|
+
with field-specific information and examples.
|
|
42
|
+
"""
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
message: str,
|
|
46
|
+
field: str = None,
|
|
47
|
+
expected: str = None,
|
|
48
|
+
received: str = None,
|
|
49
|
+
example: str = None
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
Initialize a ValidationError with detailed context.
|
|
53
|
+
|
|
54
|
+
:param message: str - The main error message.
|
|
55
|
+
:param field: str - Name of the field that failed validation.
|
|
56
|
+
:param expected: str - Description of what was expected.
|
|
57
|
+
:param received: str - Description of what was received.
|
|
58
|
+
:param example: str - Example of valid input.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(message)
|
|
61
|
+
self.field = field
|
|
62
|
+
self.expected = expected
|
|
63
|
+
self.received = received
|
|
64
|
+
self.example = example
|
|
65
|
+
|
|
66
|
+
def __str__(self) -> str:
|
|
67
|
+
"""
|
|
68
|
+
Format the error message with all available context.
|
|
69
|
+
|
|
70
|
+
:return: str - Formatted error message with field details.
|
|
71
|
+
"""
|
|
72
|
+
parts = [super().__str__()]
|
|
73
|
+
|
|
74
|
+
if self.field:
|
|
75
|
+
parts.append(f" Field: {self.field}")
|
|
76
|
+
if self.expected:
|
|
77
|
+
parts.append(f" Expected: {self.expected}")
|
|
78
|
+
if self.received:
|
|
79
|
+
parts.append(f" Received: {self.received}")
|
|
80
|
+
if self.example:
|
|
81
|
+
parts.append(f" Example: {self.example}")
|
|
82
|
+
|
|
83
|
+
return "\n".join(parts)
|
|
84
|
+
|
|
85
|
+
|
|
23
86
|
class ServerResponseError(GEAIException):
|
|
24
87
|
"""Raised when the server returns an error response"""
|
|
25
88
|
pass
|
pygeai/core/services/rest.py
CHANGED
|
@@ -15,19 +15,22 @@ FAILED_REQUEST_RESPONSE = ResponseMock(
|
|
|
15
15
|
|
|
16
16
|
class ApiService:
|
|
17
17
|
"""
|
|
18
|
-
Generic service for interacting with
|
|
18
|
+
Generic service for interacting with REST APIs.
|
|
19
19
|
|
|
20
20
|
:param base_url: str - The base URL of the API.
|
|
21
21
|
:param username: str - Username for basic authentication (optional).
|
|
22
22
|
:param password: str - Password for basic authentication (optional).
|
|
23
23
|
:param token: str - Bearer token for authentication (optional).
|
|
24
|
+
:param project_id: str - Project ID for OAuth authentication (optional, keyword-only).
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
def __init__(self, base_url, username: str = None, password: str = None, token: str = None
|
|
27
|
+
def __init__(self, base_url, username: str = None, password: str = None, token: str = None, *,
|
|
28
|
+
project_id: str = None):
|
|
27
29
|
self._base_url = base_url
|
|
28
30
|
self._username = username
|
|
29
31
|
self._password = password
|
|
30
32
|
self._token = token
|
|
33
|
+
self._project_id = project_id
|
|
31
34
|
|
|
32
35
|
@property
|
|
33
36
|
def base_url(self):
|
|
@@ -45,6 +48,18 @@ class ApiService:
|
|
|
45
48
|
def token(self):
|
|
46
49
|
return self._token
|
|
47
50
|
|
|
51
|
+
@token.setter
|
|
52
|
+
def token(self, token: str):
|
|
53
|
+
self._token = token
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def project_id(self):
|
|
57
|
+
return self._project_id
|
|
58
|
+
|
|
59
|
+
@project_id.setter
|
|
60
|
+
def project_id(self, project_id: str):
|
|
61
|
+
self._project_id = project_id
|
|
62
|
+
|
|
48
63
|
def get(self, endpoint: str, params: dict = None, headers: dict = None, verify: bool = True):
|
|
49
64
|
"""
|
|
50
65
|
Sends a GET request to the specified API endpoint.
|
|
@@ -403,4 +418,7 @@ class ApiService:
|
|
|
403
418
|
if "Authorization" not in headers:
|
|
404
419
|
headers["Authorization"] = f"Bearer {self.token}"
|
|
405
420
|
|
|
421
|
+
if self.project_id and "ProjectId" not in headers:
|
|
422
|
+
headers["ProjectId"] = self.project_id
|
|
423
|
+
|
|
406
424
|
return headers
|
pygeai/evaluation/clients.py
CHANGED
|
@@ -7,11 +7,13 @@ from pygeai.core.utils.validators import validate_status_code
|
|
|
7
7
|
|
|
8
8
|
class EvaluationClient(BaseClient):
|
|
9
9
|
|
|
10
|
-
def __init__(self, api_key: str = None, base_url: str = None, alias: str = "default", eval_url: str = None
|
|
11
|
-
|
|
10
|
+
def __init__(self, api_key: str = None, base_url: str = None, alias: str = "default", eval_url: str = None, *,
|
|
11
|
+
access_token: str = None, project_id: str = None):
|
|
12
|
+
super().__init__(api_key, base_url, alias, access_token=access_token, project_id=project_id)
|
|
12
13
|
eval_url = self.session.eval_url if not eval_url else eval_url
|
|
13
14
|
if not eval_url:
|
|
14
15
|
raise MissingRequirementException("EVAL URL must be defined in order to use the Evaluation module.")
|
|
15
16
|
|
|
16
17
|
self.session.eval_url = eval_url
|
|
17
|
-
self.
|
|
18
|
+
token = self.session.access_token if self.session.access_token else self.session.api_key
|
|
19
|
+
self.api_service = ApiService(base_url=self.session.eval_url, token=token, project_id=self.session.project_id)
|
pygeai/lab/agents/clients.py
CHANGED
|
@@ -5,7 +5,7 @@ from pygeai.core.common.exceptions import MissingRequirementException, InvalidAP
|
|
|
5
5
|
from pygeai.core.utils.validators import validate_status_code
|
|
6
6
|
from pygeai.core.utils.parsers import parse_json_response
|
|
7
7
|
from pygeai.lab.agents.endpoints import CREATE_AGENT_V2, LIST_AGENTS_V2, GET_AGENT_V2, CREATE_SHARING_LINK_V2, \
|
|
8
|
-
PUBLISH_AGENT_REVISION_V2, DELETE_AGENT_V2, UPDATE_AGENT_V2, UPSERT_AGENT_V2,
|
|
8
|
+
PUBLISH_AGENT_REVISION_V2, DELETE_AGENT_V2, UPDATE_AGENT_V2, UPSERT_AGENT_V2, EXPORT_AGENT_V2, IMPORT_AGENT_V2
|
|
9
9
|
from pygeai.lab.constants import VALID_ACCESS_SCOPES
|
|
10
10
|
from pygeai.lab.clients import AILabClient
|
|
11
11
|
|
|
@@ -380,7 +380,7 @@ class AgentClient(AILabClient):
|
|
|
380
380
|
if not agent_id:
|
|
381
381
|
raise MissingRequirementException("agent_id must be specified in order to export the agent")
|
|
382
382
|
|
|
383
|
-
endpoint =
|
|
383
|
+
endpoint = EXPORT_AGENT_V2.format(agentId=agent_id)
|
|
384
384
|
headers = {
|
|
385
385
|
"Authorization": self.api_service.token,
|
|
386
386
|
"ProjectId": self.project_id
|
|
@@ -410,7 +410,7 @@ class AgentClient(AILabClient):
|
|
|
410
410
|
if not data:
|
|
411
411
|
raise MissingRequirementException("data for spec must be specified in order to import the agent")
|
|
412
412
|
|
|
413
|
-
endpoint =
|
|
413
|
+
endpoint = IMPORT_AGENT_V2
|
|
414
414
|
headers = {
|
|
415
415
|
"Authorization": self.api_service.token,
|
|
416
416
|
"ProjectId": self.project_id
|
pygeai/lab/agents/endpoints.py
CHANGED
|
@@ -8,5 +8,5 @@ UPDATE_AGENT_V2 = "v2/agents/{agentId}" # PUT -> Update agent
|
|
|
8
8
|
UPSERT_AGENT_V2 = "v2/agents/{agentId}/upsert" # PUT -> Update or Insert agent
|
|
9
9
|
EXPORT_AGENT_V2 = "v2/agents/{agentId}/export" # GET -> Export agent
|
|
10
10
|
IMPORT_AGENT_V2 = "v2/agents/import" # POST -> Import agent
|
|
11
|
-
EXPORT_AGENT_V4 = "v4/agents/{agentId}/export" # GET -> Export agent
|
|
12
|
-
IMPORT_AGENT_V4 = "v4/agents/import" # POST -> Import agent
|
|
11
|
+
# EXPORT_AGENT_V4 = "v4/agents/{agentId}/export" # GET -> Export agent
|
|
12
|
+
# IMPORT_AGENT_V4 = "v4/agents/import" # POST -> Import agent
|
pygeai/lab/agents/mappers.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Optional, List
|
|
2
2
|
|
|
3
3
|
from pygeai.lab.models import Agent, AgentList, SharingLink, AgentData, Prompt, PromptOutput, PromptExample, LlmConfig, \
|
|
4
|
-
Sampling, ModelList, Model, ResourcePoolList, ResourcePool, ResourcePoolAgent, ResourcePoolTool
|
|
4
|
+
Sampling, ModelList, Model, ResourcePoolList, ResourcePool, ResourcePoolAgent, ResourcePoolTool, Permission, Property
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class AgentMapper:
|
|
@@ -38,6 +38,8 @@ class AgentMapper:
|
|
|
38
38
|
:return: Agent - The mapped `Agent` object.
|
|
39
39
|
"""
|
|
40
40
|
agent_data_data = data.get("agentData")
|
|
41
|
+
permissions_data = data.get("permissions")
|
|
42
|
+
effective_permissions_data = data.get("effectivePermissions")
|
|
41
43
|
return Agent(
|
|
42
44
|
id=data.get("id"),
|
|
43
45
|
status=data.get("status"),
|
|
@@ -51,6 +53,9 @@ class AgentMapper:
|
|
|
51
53
|
is_readonly=data.get("isReadonly"),
|
|
52
54
|
revision=data.get("revision"),
|
|
53
55
|
version=data.get("version"),
|
|
56
|
+
sharing_scope=data.get("sharingScope"),
|
|
57
|
+
permissions=cls._map_to_permission(permissions_data) if permissions_data else None,
|
|
58
|
+
effective_permissions=cls._map_to_permission(effective_permissions_data) if effective_permissions_data else None,
|
|
54
59
|
agent_data=cls._map_agent_data(agent_data_data) if agent_data_data else None
|
|
55
60
|
)
|
|
56
61
|
|
|
@@ -67,12 +72,14 @@ class AgentMapper:
|
|
|
67
72
|
models_list = data.get("models")
|
|
68
73
|
strategy_name = data.get("strategyName")
|
|
69
74
|
resource_pool_list = data.get("resourcePools")
|
|
75
|
+
properties_list = data.get("properties")
|
|
70
76
|
return AgentData(
|
|
71
77
|
prompt=cls._map_to_prompt(prompt_data) if prompt_data else None,
|
|
72
78
|
llm_config=cls._map_to_llm_config(llm_config_data) if llm_config_data else None,
|
|
73
79
|
strategy_name=strategy_name,
|
|
74
80
|
models=cls._map_to_model_list(models_list) if models_list else None,
|
|
75
|
-
resource_pools=cls._map_to_resource_pool_list(resource_pool_list) if resource_pool_list else None
|
|
81
|
+
resource_pools=cls._map_to_resource_pool_list(resource_pool_list) if resource_pool_list else None,
|
|
82
|
+
properties=cls._map_to_property_list(properties_list) if properties_list else None
|
|
76
83
|
)
|
|
77
84
|
|
|
78
85
|
@classmethod
|
|
@@ -269,3 +276,44 @@ class AgentMapper:
|
|
|
269
276
|
api_token=data.get('apiToken'),
|
|
270
277
|
shared_link=data.get('sharedLink'),
|
|
271
278
|
)
|
|
279
|
+
|
|
280
|
+
@classmethod
|
|
281
|
+
def _map_to_permission(cls, data: dict) -> Permission:
|
|
282
|
+
"""
|
|
283
|
+
Maps a dictionary to a `Permission` object.
|
|
284
|
+
|
|
285
|
+
:param data: dict - The dictionary containing permission details.
|
|
286
|
+
:return: Permission - The mapped `Permission` object, or None if data is None.
|
|
287
|
+
"""
|
|
288
|
+
if data is None:
|
|
289
|
+
return None
|
|
290
|
+
return Permission(
|
|
291
|
+
chat_sharing=data.get('chatSharing'),
|
|
292
|
+
external_execution=data.get('externalExecution')
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
@classmethod
|
|
296
|
+
def _map_to_property_list(cls, data: List[dict]) -> List[Property]:
|
|
297
|
+
"""
|
|
298
|
+
Maps a list of dictionaries to a list of `Property` objects.
|
|
299
|
+
|
|
300
|
+
:param data: List[dict] - The list of dictionaries containing property details.
|
|
301
|
+
:return: List[Property] - The mapped list of `Property` objects, or None if data is None.
|
|
302
|
+
"""
|
|
303
|
+
if data is None:
|
|
304
|
+
return None
|
|
305
|
+
return [cls._map_to_property(prop) for prop in data]
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
def _map_to_property(cls, data: dict) -> Property:
|
|
309
|
+
"""
|
|
310
|
+
Maps a dictionary to a `Property` object.
|
|
311
|
+
|
|
312
|
+
:param data: dict - The dictionary containing property details.
|
|
313
|
+
:return: Property - The mapped `Property` object.
|
|
314
|
+
"""
|
|
315
|
+
return Property(
|
|
316
|
+
data_type=data.get('dataType'),
|
|
317
|
+
key=data.get('key'),
|
|
318
|
+
value=data.get('value')
|
|
319
|
+
)
|
pygeai/lab/clients.py
CHANGED
|
@@ -7,9 +7,12 @@ from pygeai.core.utils.validators import validate_status_code
|
|
|
7
7
|
|
|
8
8
|
class AILabClient(BaseClient):
|
|
9
9
|
|
|
10
|
-
def __init__(self, api_key: str = None, base_url: str = None, alias: str = None,
|
|
11
|
-
|
|
10
|
+
def __init__(self, api_key: str = None, base_url: str = None, alias: str = None, *,
|
|
11
|
+
access_token: str = None, project_id: str = None):
|
|
12
|
+
super().__init__(api_key, base_url, alias, access_token=access_token, project_id=project_id)
|
|
12
13
|
self.project_id = project_id if project_id else self.__get_project_id(api_key, base_url, alias)
|
|
14
|
+
if self.project_id and not self.api_service.project_id:
|
|
15
|
+
self.api_service.project_id = self.project_id
|
|
13
16
|
|
|
14
17
|
def __get_project_id(self, api_key: str = None, base_url: str = None, alias: str = None):
|
|
15
18
|
response = None
|
pygeai/lab/managers.py
CHANGED
|
@@ -91,7 +91,7 @@ class AILabManager:
|
|
|
91
91
|
agent_data_prompt=agent.agent_data.prompt.to_dict() if agent.agent_data is not None else None,
|
|
92
92
|
agent_data_strategy_name=agent.agent_data.strategy_name if agent.agent_data is not None else None,
|
|
93
93
|
agent_data_llm_config=agent.agent_data.llm_config.to_dict() if agent.agent_data is not None else None,
|
|
94
|
-
agent_data_models=agent.agent_data.models.to_dict() if agent.agent_data
|
|
94
|
+
agent_data_models=agent.agent_data.models.to_dict() if agent.agent_data and agent.agent_data.models else None,
|
|
95
95
|
agent_data_resource_pools=agent.agent_data.resource_pools.to_dict() if agent.agent_data and agent.agent_data.resource_pools else None,
|
|
96
96
|
automatic_publish=automatic_publish
|
|
97
97
|
)
|
|
@@ -137,8 +137,9 @@ class AILabManager:
|
|
|
137
137
|
description=agent.description,
|
|
138
138
|
agent_data_prompt=agent.agent_data.prompt.to_dict() if agent.agent_data is not None else None,
|
|
139
139
|
agent_data_llm_config=agent.agent_data.llm_config.to_dict() if agent.agent_data is not None else None,
|
|
140
|
-
agent_data_strategy_name=agent.agent_data.strategy_name if agent.agent_data
|
|
141
|
-
agent_data_models=agent.agent_data.models.to_dict() if agent.agent_data
|
|
140
|
+
agent_data_strategy_name=agent.agent_data.strategy_name if agent.agent_data and agent.agent_data.strategy_name else None,
|
|
141
|
+
agent_data_models=agent.agent_data.models.to_dict() if agent.agent_data and agent.agent_data.models else None,
|
|
142
|
+
agent_data_resource_pools=agent.agent_data.resource_pools.to_dict() if agent.agent_data and agent.agent_data.resource_pools else None,
|
|
142
143
|
automatic_publish=automatic_publish,
|
|
143
144
|
upsert=upsert
|
|
144
145
|
)
|
|
@@ -264,8 +265,7 @@ class AILabManager:
|
|
|
264
265
|
logger.error(f"Error received while deleting agent: {error}")
|
|
265
266
|
raise APIError(f"Error received while deleting agent: {error}")
|
|
266
267
|
|
|
267
|
-
|
|
268
|
-
result = ResponseMapper.map_to_empty_response(response_data)
|
|
268
|
+
result = ResponseMapper.map_to_empty_response(response_data or "Agent deleted successfully")
|
|
269
269
|
return result
|
|
270
270
|
|
|
271
271
|
def create_tool(
|
|
@@ -431,8 +431,7 @@ class AILabManager:
|
|
|
431
431
|
logger.error(f"Error received while deleting tool: {error}")
|
|
432
432
|
raise APIError(f"Error received while deleting tool: {error}")
|
|
433
433
|
|
|
434
|
-
|
|
435
|
-
result = ResponseMapper.map_to_empty_response(response_data)
|
|
434
|
+
result = ResponseMapper.map_to_empty_response(response_data or "Tool deleted successfully")
|
|
436
435
|
return result
|
|
437
436
|
|
|
438
437
|
def list_tools(
|
|
@@ -1518,8 +1517,7 @@ class AILabManager:
|
|
|
1518
1517
|
logger.error(f"Error received while deleting knowledge base: {error}")
|
|
1519
1518
|
raise APIError(f"Error received while deleting knowledge base: {error}")
|
|
1520
1519
|
|
|
1521
|
-
|
|
1522
|
-
result = ResponseMapper.map_to_empty_response(response_data)
|
|
1520
|
+
result = ResponseMapper.map_to_empty_response(response_data or "Knowledge base deleted successfully")
|
|
1523
1521
|
return result
|
|
1524
1522
|
|
|
1525
1523
|
def list_jobs(
|
pygeai/lab/models.py
CHANGED
|
@@ -385,6 +385,38 @@ class ResourcePoolList(CustomBaseModel):
|
|
|
385
385
|
self.resource_pools.append(item)
|
|
386
386
|
|
|
387
387
|
|
|
388
|
+
class Permission(CustomBaseModel):
|
|
389
|
+
"""
|
|
390
|
+
Represents permission settings for an agent.
|
|
391
|
+
|
|
392
|
+
:param chat_sharing: Literal["none", "organization", "project"] - Chat sharing permission level.
|
|
393
|
+
:param external_execution: Literal["none", "organization", "project"] - External execution permission level.
|
|
394
|
+
"""
|
|
395
|
+
chat_sharing: Optional[Literal["none", "organization", "project"]] = Field(None, alias="chatSharing", description="Chat sharing permission level")
|
|
396
|
+
external_execution: Optional[Literal["none", "organization", "project"]] = Field(None, alias="externalExecution", description="External execution permission level")
|
|
397
|
+
|
|
398
|
+
def to_dict(self):
|
|
399
|
+
"""Convert Permission to dictionary with API aliases."""
|
|
400
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
class Property(CustomBaseModel):
|
|
404
|
+
"""
|
|
405
|
+
Represents a property key-value pair with data type.
|
|
406
|
+
|
|
407
|
+
:param data_type: str - Data type of the property (e.g., "String", "Number", "Boolean").
|
|
408
|
+
:param key: str - Property key identifier.
|
|
409
|
+
:param value: str - Property value.
|
|
410
|
+
"""
|
|
411
|
+
data_type: str = Field(..., alias="dataType", description="Data type of the property")
|
|
412
|
+
key: str = Field(..., alias="key", description="Property key identifier")
|
|
413
|
+
value: str = Field(..., alias="value", description="Property value")
|
|
414
|
+
|
|
415
|
+
def to_dict(self):
|
|
416
|
+
"""Convert Property to dictionary with API aliases."""
|
|
417
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
418
|
+
|
|
419
|
+
|
|
388
420
|
class AgentData(CustomBaseModel):
|
|
389
421
|
"""
|
|
390
422
|
Represents the detailed configuration data for an agent.
|
|
@@ -400,6 +432,7 @@ class AgentData(CustomBaseModel):
|
|
|
400
432
|
strategy_name: Optional[str] = Field("Dynamic Prompting", alias="strategyName")
|
|
401
433
|
models: Optional[Union[ModelList, List[Model]]] = Field(None, alias="models")
|
|
402
434
|
resource_pools: Optional[ResourcePoolList] = Field(None, alias="resourcePools", description="List of resource pools organizing tools and helper agents")
|
|
435
|
+
properties: Optional[List[Property]] = Field(None, alias="properties", description="List of agent properties")
|
|
403
436
|
|
|
404
437
|
@field_validator("prompt", mode="before")
|
|
405
438
|
@classmethod
|
|
@@ -418,6 +451,8 @@ class AgentData(CustomBaseModel):
|
|
|
418
451
|
@field_validator("models", mode="before")
|
|
419
452
|
@classmethod
|
|
420
453
|
def normalize_models(cls, value):
|
|
454
|
+
if value is None:
|
|
455
|
+
return None
|
|
421
456
|
if isinstance(value, ModelList):
|
|
422
457
|
return value
|
|
423
458
|
elif isinstance(value, list):
|
|
@@ -433,6 +468,13 @@ class AgentData(CustomBaseModel):
|
|
|
433
468
|
return ResourcePoolList(resource_pools=[ResourcePool.model_validate(item) if isinstance(item, dict) else item for item in value])
|
|
434
469
|
return value
|
|
435
470
|
|
|
471
|
+
@field_validator("properties", mode="before")
|
|
472
|
+
@classmethod
|
|
473
|
+
def normalize_properties(cls, value):
|
|
474
|
+
if isinstance(value, list):
|
|
475
|
+
return [Property.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
476
|
+
return value
|
|
477
|
+
|
|
436
478
|
@model_validator(mode="after")
|
|
437
479
|
def validate_resource_pools_unique_names(self):
|
|
438
480
|
if self.resource_pools:
|
|
@@ -451,8 +493,10 @@ class AgentData(CustomBaseModel):
|
|
|
451
493
|
result = {
|
|
452
494
|
"prompt": self.prompt.to_dict(),
|
|
453
495
|
"llmConfig": self.llm_config.to_dict(),
|
|
454
|
-
"
|
|
455
|
-
"
|
|
496
|
+
"strategyName": self.strategy_name,
|
|
497
|
+
"models": self.models.to_dict() if self.models else None,
|
|
498
|
+
"resourcePools": [pool.to_dict() for pool in self.resource_pools] if self.resource_pools else None,
|
|
499
|
+
"properties": [prop.to_dict() for prop in self.properties] if self.properties else None
|
|
456
500
|
}
|
|
457
501
|
return {k: v for k, v in result.items() if v is not None}
|
|
458
502
|
|
|
@@ -490,6 +534,9 @@ class Agent(CustomBaseModel):
|
|
|
490
534
|
is_readonly: Optional[bool] = Field(False, alias="isReadonly")
|
|
491
535
|
revision: Optional[int] = Field(None, alias="revision")
|
|
492
536
|
version: Optional[Union[int | float]] = Field(None, alias="version")
|
|
537
|
+
sharing_scope: Optional[str] = Field(None, alias="sharingScope", description="Sharing scope of the agent")
|
|
538
|
+
permissions: Optional[Permission] = Field(None, alias="permissions", description="Permission settings")
|
|
539
|
+
effective_permissions: Optional[Permission] = Field(None, alias="effectivePermissions", description="Effective permission settings")
|
|
493
540
|
agent_data: Optional[AgentData] = Field(None, alias="agentData")
|
|
494
541
|
|
|
495
542
|
@field_validator("name")
|
|
@@ -528,6 +575,20 @@ class Agent(CustomBaseModel):
|
|
|
528
575
|
return AgentData.model_validate(value)
|
|
529
576
|
return value
|
|
530
577
|
|
|
578
|
+
@field_validator("permissions", mode="before")
|
|
579
|
+
@classmethod
|
|
580
|
+
def normalize_permissions(cls, value):
|
|
581
|
+
if isinstance(value, dict):
|
|
582
|
+
return Permission.model_validate(value)
|
|
583
|
+
return value
|
|
584
|
+
|
|
585
|
+
@field_validator("effective_permissions", mode="before")
|
|
586
|
+
@classmethod
|
|
587
|
+
def normalize_effective_permissions(cls, value):
|
|
588
|
+
if isinstance(value, dict):
|
|
589
|
+
return Permission.model_validate(value)
|
|
590
|
+
return value
|
|
591
|
+
|
|
531
592
|
@model_validator(mode="after")
|
|
532
593
|
def check_public_name(self):
|
|
533
594
|
"""
|
|
@@ -553,6 +614,9 @@ class Agent(CustomBaseModel):
|
|
|
553
614
|
"isReadonly": self.is_readonly,
|
|
554
615
|
"revision": self.revision,
|
|
555
616
|
"version": self.version,
|
|
617
|
+
"sharingScope": self.sharing_scope,
|
|
618
|
+
"permissions": self.permissions.to_dict() if self.permissions else None,
|
|
619
|
+
"effectivePermissions": self.effective_permissions.to_dict() if self.effective_permissions else None,
|
|
556
620
|
"agentData": self.agent_data.to_dict() if self.agent_data else None
|
|
557
621
|
}
|
|
558
622
|
return {k: v for k, v in result.items() if v is not None}
|
|
@@ -918,6 +982,7 @@ class KnowledgeBase(CustomBaseModel):
|
|
|
918
982
|
artifact_type_name: Optional[List[str]] = Field(None, alias="artifactTypeName", description="List of artifact type names")
|
|
919
983
|
artifacts: Optional[List[str]] = Field(None, description="List of artifact identifiers")
|
|
920
984
|
metadata: Optional[List[str]] = Field(None, description="List of metadata identifiers")
|
|
985
|
+
created_at: Optional[str] = Field(None, alias="createdAt", description="Timestamp when the knowledge base was created")
|
|
921
986
|
|
|
922
987
|
@field_validator("artifacts")
|
|
923
988
|
@classmethod
|
|
@@ -1269,6 +1334,7 @@ class Task(CustomBaseModel):
|
|
|
1269
1334
|
:param artifact_types: Optional[List[dict]] - List of artifact types with 'name', 'description', 'isRequired', 'usageType', and 'artifactVariableKey'.
|
|
1270
1335
|
:param is_draft: Optional[bool] - Whether the task is in draft mode.
|
|
1271
1336
|
:param revision: Optional[int] - Revision number of the task.
|
|
1337
|
+
:param version: Optional[int] - Version number of the task.
|
|
1272
1338
|
:param status: Optional[str] - Current status of the task (e.g., 'active').
|
|
1273
1339
|
"""
|
|
1274
1340
|
name: str = Field(..., description="Name of the task")
|
|
@@ -1279,6 +1345,7 @@ class Task(CustomBaseModel):
|
|
|
1279
1345
|
artifact_types: Optional[Union[List[Dict[str, Any]], List[ArtifactType], ArtifactTypeList]] = Field(None, alias="artifactTypes", description="List of artifact types for the task")
|
|
1280
1346
|
is_draft: Optional[bool] = Field(None, alias="isDraft", description="Whether the task is a draft")
|
|
1281
1347
|
revision: Optional[int] = Field(None, description="Revision number of the task")
|
|
1348
|
+
version: Optional[int] = Field(None, description="Version number of the task")
|
|
1282
1349
|
status: Optional[str] = Field(None, description="Status of the task (e.g., 'active')")
|
|
1283
1350
|
|
|
1284
1351
|
@field_validator("name")
|
|
@@ -1367,6 +1434,7 @@ class Task(CustomBaseModel):
|
|
|
1367
1434
|
"artifactTypes": self.artifact_types.to_dict() if self.artifact_types else None,
|
|
1368
1435
|
"isDraft": self.is_draft,
|
|
1369
1436
|
"revision": self.revision,
|
|
1437
|
+
"version": self.version,
|
|
1370
1438
|
"status": self.status
|
|
1371
1439
|
}
|
|
1372
1440
|
return {k: v for k, v in result.items() if v is not None}
|