pygeai 0.6.0b14__py3-none-any.whl → 0.6.1__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/__init__.py +1 -2
- pygeai/_docs/source/content/api_reference/project.rst +392 -0
- pygeai/_docs/source/content/authentication.rst +130 -1
- pygeai/_docs/source/content/debugger.rst +327 -157
- pygeai/_docs/source/pygeai.core.common.rst +8 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +56 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +8 -0
- pygeai/admin/clients.py +1 -3
- pygeai/analytics/clients.py +1 -1
- pygeai/assistant/clients.py +2 -7
- pygeai/assistant/data/clients.py +0 -8
- pygeai/assistant/data_analyst/clients.py +0 -2
- pygeai/assistant/managers.py +1 -1
- pygeai/assistant/rag/clients.py +0 -2
- pygeai/assistant/rag/mappers.py +9 -11
- pygeai/auth/clients.py +26 -7
- pygeai/auth/endpoints.py +2 -1
- pygeai/chat/clients.py +2 -2
- pygeai/chat/managers.py +1 -1
- pygeai/cli/commands/admin.py +13 -25
- pygeai/cli/commands/analytics.py +31 -71
- pygeai/cli/commands/assistant.py +84 -138
- pygeai/cli/commands/auth.py +23 -46
- pygeai/cli/commands/base.py +0 -1
- pygeai/cli/commands/chat.py +218 -209
- pygeai/cli/commands/common.py +5 -5
- pygeai/cli/commands/configuration.py +79 -29
- pygeai/cli/commands/docs.py +3 -4
- pygeai/cli/commands/embeddings.py +13 -19
- pygeai/cli/commands/evaluation.py +133 -344
- pygeai/cli/commands/feedback.py +7 -15
- pygeai/cli/commands/files.py +26 -53
- pygeai/cli/commands/gam.py +28 -69
- pygeai/cli/commands/lab/ai_lab.py +96 -142
- pygeai/cli/commands/lab/common.py +1 -1
- pygeai/cli/commands/lab/spec.py +12 -32
- pygeai/cli/commands/llm.py +9 -18
- pygeai/cli/commands/migrate.py +43 -99
- pygeai/cli/commands/organization.py +223 -196
- pygeai/cli/commands/rag.py +35 -58
- pygeai/cli/commands/rerank.py +21 -25
- pygeai/cli/commands/secrets.py +39 -67
- pygeai/cli/commands/usage_limits.py +50 -136
- pygeai/cli/commands/validators.py +1 -1
- pygeai/cli/geai.py +32 -3
- pygeai/cli/geai_proxy.py +6 -2
- pygeai/cli/install_man.py +1 -1
- pygeai/cli/parsers.py +1 -1
- pygeai/core/base/clients.py +90 -21
- pygeai/core/base/mappers.py +39 -55
- pygeai/core/base/session.py +129 -18
- pygeai/core/common/config.py +50 -13
- pygeai/core/common/constants.py +8 -0
- pygeai/core/common/exceptions.py +6 -0
- pygeai/core/embeddings/clients.py +0 -1
- pygeai/core/embeddings/managers.py +0 -1
- pygeai/core/feedback/clients.py +0 -2
- pygeai/core/feedback/models.py +1 -1
- pygeai/core/files/clients.py +0 -3
- pygeai/core/files/managers.py +1 -1
- pygeai/core/files/mappers.py +4 -5
- pygeai/core/llm/clients.py +0 -1
- pygeai/core/models.py +4 -4
- pygeai/core/plugins/clients.py +0 -3
- pygeai/core/plugins/models.py +2 -2
- pygeai/core/rerank/clients.py +0 -2
- pygeai/core/secrets/clients.py +0 -2
- pygeai/core/services/rest.py +80 -14
- pygeai/core/singleton.py +24 -0
- pygeai/dbg/__init__.py +2 -2
- pygeai/dbg/debugger.py +276 -38
- pygeai/evaluation/clients.py +2 -4
- pygeai/evaluation/dataset/clients.py +0 -1
- pygeai/evaluation/plan/clients.py +0 -2
- pygeai/evaluation/result/clients.py +0 -2
- pygeai/gam/clients.py +1 -3
- pygeai/health/clients.py +1 -3
- pygeai/lab/clients.py +0 -1
- pygeai/lab/managers.py +0 -1
- pygeai/lab/models.py +0 -1
- pygeai/lab/strategies/clients.py +1 -2
- pygeai/lab/tools/clients.py +2 -2
- pygeai/lab/tools/mappers.py +1 -1
- pygeai/migration/strategies.py +5 -6
- pygeai/migration/tools.py +1 -1
- pygeai/organization/clients.py +118 -12
- pygeai/organization/endpoints.py +1 -0
- pygeai/organization/limits/clients.py +4 -6
- pygeai/organization/limits/managers.py +1 -4
- pygeai/organization/managers.py +2 -2
- pygeai/proxy/config.py +1 -0
- pygeai/proxy/managers.py +6 -5
- pygeai/tests/admin/test_clients.py +11 -11
- pygeai/tests/assistants/rag/test_clients.py +1 -1
- pygeai/tests/assistants/rag/test_models.py +1 -2
- pygeai/tests/assistants/test_clients.py +1 -1
- pygeai/tests/assistants/test_managers.py +1 -3
- pygeai/tests/auth/test_cli_configuration.py +252 -0
- pygeai/tests/auth/test_client_initialization.py +411 -0
- pygeai/tests/auth/test_clients.py +29 -27
- pygeai/tests/auth/test_config_manager.py +305 -0
- pygeai/tests/auth/test_header_injection.py +294 -0
- pygeai/tests/auth/test_oauth.py +3 -1
- pygeai/tests/auth/test_session_logging.py +119 -0
- pygeai/tests/auth/test_session_validation.py +408 -0
- pygeai/tests/auth/test_singleton_reset.py +201 -0
- pygeai/tests/chat/test_clients.py +1 -1
- pygeai/tests/chat/test_iris.py +1 -1
- pygeai/tests/chat/test_ui.py +0 -2
- pygeai/tests/cli/commands/lab/test_ai_lab.py +1 -3
- pygeai/tests/cli/commands/lab/test_common.py +0 -1
- pygeai/tests/cli/commands/test_chat.py +1 -1
- pygeai/tests/cli/commands/test_common.py +0 -1
- pygeai/tests/cli/commands/test_embeddings.py +2 -2
- pygeai/tests/cli/commands/test_evaluation.py +1 -9
- pygeai/tests/cli/commands/test_llm.py +1 -1
- pygeai/tests/cli/commands/test_migrate.py +1 -1
- pygeai/tests/cli/commands/test_rerank.py +0 -1
- pygeai/tests/cli/commands/test_secrets.py +1 -1
- pygeai/tests/cli/commands/test_show_help.py +0 -1
- pygeai/tests/cli/commands/test_validators.py +0 -1
- pygeai/tests/cli/test_credentials_flag.py +312 -0
- pygeai/tests/cli/test_error_handler.py +0 -1
- pygeai/tests/core/base/test_mappers.py +2 -2
- pygeai/tests/core/base/test_models.py +4 -4
- pygeai/tests/core/common/test_config.py +2 -7
- pygeai/tests/core/common/test_decorators.py +0 -1
- pygeai/tests/core/embeddings/test_managers.py +1 -1
- pygeai/tests/core/feedback/test_clients.py +2 -2
- pygeai/tests/core/files/test_clients.py +6 -6
- pygeai/tests/core/files/test_models.py +0 -1
- pygeai/tests/core/files/test_responses.py +0 -1
- pygeai/tests/core/llm/test_clients.py +1 -1
- pygeai/tests/core/plugins/test_clients.py +4 -4
- pygeai/tests/core/rerank/test_mappers.py +1 -3
- pygeai/tests/core/secrets/test_clients.py +2 -3
- pygeai/tests/core/services/test_rest.py +10 -10
- pygeai/tests/core/utils/test_console.py +0 -1
- pygeai/tests/dbg/test_debugger.py +95 -8
- pygeai/tests/evaluation/dataset/test_clients.py +24 -27
- pygeai/tests/evaluation/plan/test_clients.py +16 -18
- pygeai/tests/evaluation/result/test_clients.py +4 -5
- pygeai/tests/health/test_clients.py +2 -2
- pygeai/tests/integration/lab/agents/test_create_agent.py +1 -3
- pygeai/tests/integration/lab/agents/test_get_agent.py +1 -1
- pygeai/tests/integration/lab/processes/test_create_process.py +2 -2
- pygeai/tests/integration/lab/processes/test_create_task.py +2 -3
- pygeai/tests/integration/lab/processes/test_delete_process.py +0 -1
- pygeai/tests/integration/lab/processes/test_get_process.py +2 -4
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +1 -3
- pygeai/tests/integration/lab/processes/test_update_process.py +3 -9
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +1 -2
- pygeai/tests/integration/lab/tools/test_delete_tool.py +1 -1
- pygeai/tests/integration/lab/tools/test_list_tools.py +1 -1
- pygeai/tests/integration/lab/tools/test_update_tool.py +1 -1
- pygeai/tests/lab/agents/test_clients.py +17 -17
- pygeai/tests/lab/processes/test_clients.py +67 -67
- pygeai/tests/lab/processes/test_mappers.py +23 -23
- pygeai/tests/lab/spec/test_loader.py +0 -2
- pygeai/tests/lab/spec/test_parsers.py +1 -2
- pygeai/tests/lab/strategies/test_clients.py +10 -10
- pygeai/tests/lab/test_managers.py +3 -5
- pygeai/tests/lab/test_mappers.py +1 -4
- pygeai/tests/lab/tools/test_clients.py +21 -21
- pygeai/tests/lab/tools/test_mappers.py +0 -1
- pygeai/tests/organization/limits/test_clients.py +33 -33
- pygeai/tests/organization/limits/test_managers.py +7 -7
- pygeai/tests/organization/test_clients.py +78 -60
- pygeai/tests/proxy/test_clients.py +1 -1
- pygeai/tests/proxy/test_integration.py +1 -4
- pygeai/tests/proxy/test_managers.py +1 -2
- pygeai/tests/proxy/test_servers.py +1 -2
- pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +0 -1
- pygeai/tests/snippets/assistants/rag/get_documents.py +0 -1
- pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +0 -1
- pygeai/tests/snippets/chat/get_request_status.py +0 -1
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +60 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +2 -2
- pygeai/tests/snippets/embeddings/openai_base64_example.py +1 -1
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +8 -8
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +5 -5
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +3 -3
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +1 -1
- pygeai/tests/snippets/lab/agentic_flow_example_2.py +3 -4
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +2 -2
- pygeai/tests/snippets/lab/agents/delete_agent.py +1 -2
- pygeai/tests/snippets/lab/agents/get_agent.py +1 -1
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +10 -10
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +0 -1
- pygeai/tests/snippets/lab/agents/list_agents.py +1 -1
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +0 -1
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +1 -1
- pygeai/tests/snippets/lab/crud_ui.py +3 -5
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +0 -1
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +0 -1
- pygeai/tests/snippets/lab/processes/list_processes.py +1 -1
- pygeai/tests/snippets/lab/samples/summarize_files.py +0 -3
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +0 -1
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +1 -1
- pygeai/tests/snippets/lab/tools/get_tool.py +1 -1
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +0 -1
- pygeai/tests/snippets/lab/tools/set_parameters.py +1 -2
- pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +2 -3
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +1 -1
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +0 -1
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +0 -1
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +0 -1
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +0 -1
- pygeai/tests/snippets/migrate/orchestrator_examples.py +1 -1
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/METADATA +32 -7
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/RECORD +216 -205
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/WHEEL +0 -0
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/entry_points.txt +0 -0
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {pygeai-0.6.0b14.dist-info → pygeai-0.6.1.dist-info}/top_level.txt +0 -0
pygeai/cli/geai.py
CHANGED
|
@@ -64,9 +64,9 @@ class CLIDriver:
|
|
|
64
64
|
user-friendly messages.
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
-
def __init__(self, session=None) -> None:
|
|
67
|
+
def __init__(self, session=None, credentials_file=None) -> None:
|
|
68
68
|
"""
|
|
69
|
-
Initialize the CLI driver with optional session.
|
|
69
|
+
Initialize the CLI driver with optional session and credentials file.
|
|
70
70
|
|
|
71
71
|
Sets up the session to be used while running commands, either with a
|
|
72
72
|
specified alias, environment variables, or function parameters.
|
|
@@ -74,8 +74,18 @@ class CLIDriver:
|
|
|
74
74
|
|
|
75
75
|
:param session: Optional session object. If None, uses 'default' or
|
|
76
76
|
alias-specified session from command-line arguments.
|
|
77
|
+
:param credentials_file: Optional path to custom credentials file.
|
|
77
78
|
"""
|
|
79
|
+
from pygeai.core.common.config import get_settings
|
|
80
|
+
|
|
78
81
|
arguments = sys.argv
|
|
82
|
+
|
|
83
|
+
if credentials_file or "--credentials" in arguments or "--creds" in arguments:
|
|
84
|
+
if not credentials_file:
|
|
85
|
+
credentials_file = self._get_credentials_file(arguments)
|
|
86
|
+
get_settings(credentials_file=credentials_file)
|
|
87
|
+
logger.debug(f"Using custom credentials file: {credentials_file}")
|
|
88
|
+
|
|
79
89
|
if "-a" in arguments or "--alias" in arguments:
|
|
80
90
|
alias = self._get_alias(arguments)
|
|
81
91
|
session = get_session(alias)
|
|
@@ -100,6 +110,25 @@ class CLIDriver:
|
|
|
100
110
|
_ = arguments.pop(alias_index)
|
|
101
111
|
alias = arguments.pop(alias_index)
|
|
102
112
|
return alias
|
|
113
|
+
|
|
114
|
+
def _get_credentials_file(self, arguments: List[str]) -> str:
|
|
115
|
+
"""
|
|
116
|
+
Retrieves and removes credentials file path and flag from argument list.
|
|
117
|
+
|
|
118
|
+
:param arguments: List[str] - Command line arguments.
|
|
119
|
+
:return: str - The credentials file path.
|
|
120
|
+
:raises ValueError: If credentials flag is present but no value provided.
|
|
121
|
+
"""
|
|
122
|
+
creds_index = None
|
|
123
|
+
|
|
124
|
+
if "--credentials" in arguments:
|
|
125
|
+
creds_index = arguments.index("--credentials")
|
|
126
|
+
elif "--creds" in arguments:
|
|
127
|
+
creds_index = arguments.index("--creds")
|
|
128
|
+
|
|
129
|
+
_ = arguments.pop(creds_index)
|
|
130
|
+
credentials_file = arguments.pop(creds_index)
|
|
131
|
+
return credentials_file
|
|
103
132
|
|
|
104
133
|
def main(self, args: Optional[List[str]] = None) -> int:
|
|
105
134
|
"""
|
|
@@ -140,7 +169,7 @@ class CLIDriver:
|
|
|
140
169
|
arguments = []
|
|
141
170
|
|
|
142
171
|
self.process_command(command, arguments)
|
|
143
|
-
logger.debug(
|
|
172
|
+
logger.debug("Command completed successfully")
|
|
144
173
|
return ExitCode.SUCCESS
|
|
145
174
|
except UnknownArgumentError as e:
|
|
146
175
|
if hasattr(e, 'available_commands') and e.available_commands:
|
pygeai/cli/geai_proxy.py
CHANGED
|
@@ -11,6 +11,8 @@ from pygeai.proxy.managers import ServerManager
|
|
|
11
11
|
from pygeai.proxy.config import ProxySettingsManager
|
|
12
12
|
from pygeai.admin.clients import AdminClient
|
|
13
13
|
from pygeai.core.utils.console import Console, StreamWriter
|
|
14
|
+
|
|
15
|
+
|
|
14
16
|
class CustomProxyStream(StreamWriter):
|
|
15
17
|
"""
|
|
16
18
|
Custom stream writer for proxy output with color support for TTY terminals.
|
|
@@ -40,8 +42,10 @@ class CustomProxyStream(StreamWriter):
|
|
|
40
42
|
sys.stderr.write(f"{self.RED}{message}{self.RESET} {str(exception)}{end}")
|
|
41
43
|
logger.exception(f"{message}{end}", exception)
|
|
42
44
|
|
|
45
|
+
|
|
43
46
|
Console.set_writer(CustomProxyStream())
|
|
44
47
|
|
|
48
|
+
|
|
45
49
|
def load_config(path: str) -> list:
|
|
46
50
|
"""
|
|
47
51
|
Load server configuration from YAML or JSON file.
|
|
@@ -67,7 +71,7 @@ def load_config(path: str) -> list:
|
|
|
67
71
|
server_cfg['type'] = 'a2a'
|
|
68
72
|
servers.append(server_cfg)
|
|
69
73
|
|
|
70
|
-
if
|
|
74
|
+
if 'a2aServers' not in config and 'mcpServers' not in config:
|
|
71
75
|
Console.write_stderr("Error: MCP servers or A2A servers are required")
|
|
72
76
|
|
|
73
77
|
return servers
|
|
@@ -279,7 +283,7 @@ async def main():
|
|
|
279
283
|
|
|
280
284
|
return 1
|
|
281
285
|
else:
|
|
282
|
-
Console.write_stdout(
|
|
286
|
+
Console.write_stdout(" Done!")
|
|
283
287
|
Console.write_stdout(f"Organization: {result.get('organizationName')}")
|
|
284
288
|
Console.write_stdout(f"Project: {result.get('projectName')}")
|
|
285
289
|
except Exception as e:
|
pygeai/cli/install_man.py
CHANGED
|
@@ -80,7 +80,7 @@ def install_man_pages(system_wide: bool) -> int:
|
|
|
80
80
|
# For local installation, remind user to update MANPATH
|
|
81
81
|
if not system_wide:
|
|
82
82
|
manpath_cmd = f'export MANPATH={Path.home() / "share" / "man"}:$MANPATH'
|
|
83
|
-
print(
|
|
83
|
+
print("Local installation complete. Add to ~/.bashrc to update MANPATH:")
|
|
84
84
|
print(f" {manpath_cmd}")
|
|
85
85
|
|
|
86
86
|
return 0
|
pygeai/cli/parsers.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List, Tuple, Optional
|
|
2
2
|
|
|
3
3
|
from pygeai import logger
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
from pygeai.cli.commands import Command, Option
|
|
6
6
|
from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException
|
|
7
7
|
|
pygeai/core/base/clients.py
CHANGED
|
@@ -1,50 +1,120 @@
|
|
|
1
1
|
from abc import ABC
|
|
2
|
+
from pygeai import logger
|
|
2
3
|
|
|
3
4
|
from pygeai.core.base.session import get_session, Session
|
|
4
|
-
from pygeai.core.common.exceptions import MissingRequirementException
|
|
5
|
-
from pygeai.core.services.rest import
|
|
6
|
-
from pygeai.core.utils.validators import validate_status_code
|
|
5
|
+
from pygeai.core.common.exceptions import MissingRequirementException, MixedAuthenticationException
|
|
6
|
+
from pygeai.core.services.rest import GEAIApiService
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class BaseClient(ABC):
|
|
10
|
+
_logged_session_config = None
|
|
10
11
|
|
|
11
|
-
def __init__(
|
|
12
|
-
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
api_key: str = None,
|
|
15
|
+
base_url: str = None,
|
|
16
|
+
alias: str = None,
|
|
17
|
+
*,
|
|
18
|
+
access_token: str = None,
|
|
19
|
+
project_id: str = None,
|
|
20
|
+
organization_id: str = None,
|
|
21
|
+
allow_mixed_auth: bool = True
|
|
22
|
+
):
|
|
13
23
|
"""
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
Initialize a client with authentication credentials.
|
|
25
|
+
|
|
26
|
+
Authentication Options:
|
|
27
|
+
1. API Key: Provide api_key and base_url
|
|
28
|
+
2. OAuth 2.0: Provide access_token, project_id, and base_url
|
|
29
|
+
3. From credentials: Provide alias to load from config
|
|
30
|
+
|
|
16
31
|
:param api_key: GEAI API KEY to access services
|
|
17
32
|
:param base_url: URL for GEAI instance to be used
|
|
18
33
|
:param alias: Alias to use from credentials file
|
|
19
|
-
:param access_token: OAuth access token (keyword-only)
|
|
34
|
+
:param access_token: OAuth 2.0 access token (keyword-only)
|
|
20
35
|
:param project_id: Project ID for OAuth authentication (keyword-only)
|
|
36
|
+
:param organization_id: Organization ID for OAuth authentication (keyword-only)
|
|
37
|
+
:param allow_mixed_auth: Allow both api_key and access_token (default: False)
|
|
38
|
+
:raises: MissingRequirementException - If authentication configuration is incomplete
|
|
39
|
+
:raises: ValueError - If authentication configuration is invalid
|
|
21
40
|
"""
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if not (api_key and base_url) and not (access_token and base_url) and alias:
|
|
41
|
+
|
|
42
|
+
# Case 1: Use credentials from alias
|
|
43
|
+
if not (api_key or access_token) and alias:
|
|
26
44
|
self.__session = get_session(alias)
|
|
27
45
|
if not self.__session:
|
|
28
|
-
raise MissingRequirementException(
|
|
46
|
+
raise MissingRequirementException(
|
|
47
|
+
"API KEY and BASE URL must be defined in order to use this functionality"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Case 2: Direct credential provision
|
|
29
51
|
elif (api_key or access_token) and base_url:
|
|
52
|
+
# Validate auth parameters before mutating singleton session
|
|
53
|
+
if access_token and api_key and not allow_mixed_auth:
|
|
54
|
+
raise MixedAuthenticationException(
|
|
55
|
+
"Cannot specify both 'api_key' and 'access_token'. "
|
|
56
|
+
"Use 'allow_mixed_auth=True' to allow both (OAuth will take precedence)."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if access_token and not project_id:
|
|
60
|
+
raise MissingRequirementException(
|
|
61
|
+
"project_id is required when using access_token for OAuth authentication"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Get singleton session and update its properties
|
|
65
|
+
# Note: Setters automatically update auth_type via _determine_auth_type()
|
|
30
66
|
self.__session = get_session()
|
|
31
67
|
self.__session.api_key = api_key
|
|
32
68
|
self.__session.access_token = access_token
|
|
33
69
|
self.__session.project_id = project_id
|
|
70
|
+
self.__session.organization_id = organization_id
|
|
34
71
|
self.__session.base_url = base_url
|
|
72
|
+
|
|
73
|
+
# Case 3: Use default session
|
|
35
74
|
else:
|
|
36
75
|
self.__session = get_session()
|
|
37
|
-
|
|
76
|
+
|
|
38
77
|
if self.session is None:
|
|
39
|
-
raise MissingRequirementException(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
78
|
+
raise MissingRequirementException(
|
|
79
|
+
"Cannot access this functionality without setting API_KEY and BASE_URL"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Log session config only once per unique configuration
|
|
83
|
+
session_config_key = (
|
|
84
|
+
self.session.alias,
|
|
85
|
+
self.session.base_url,
|
|
86
|
+
self.session.auth_type
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if BaseClient._logged_session_config != session_config_key:
|
|
90
|
+
self._log_authentication_info()
|
|
91
|
+
BaseClient._logged_session_config = session_config_key
|
|
92
|
+
|
|
93
|
+
# Initialize API service with active token
|
|
94
|
+
token = self.session.get_active_token()
|
|
95
|
+
|
|
96
|
+
self.__api_service = GEAIApiService(
|
|
43
97
|
base_url=self.session.base_url,
|
|
44
98
|
token=token,
|
|
45
|
-
project_id=self.session.project_id
|
|
99
|
+
project_id=self.session.project_id,
|
|
100
|
+
organization_id=self.session.organization_id
|
|
46
101
|
)
|
|
47
102
|
|
|
103
|
+
def _log_authentication_info(self):
|
|
104
|
+
"""Log authentication configuration for debugging."""
|
|
105
|
+
if self.session.is_oauth():
|
|
106
|
+
logger.info("Using OAuth 2.0 authentication")
|
|
107
|
+
logger.info(f"Project ID: {self.session.project_id}")
|
|
108
|
+
if self.session.organization_id:
|
|
109
|
+
logger.info(f"Organization ID: {self.session.organization_id}")
|
|
110
|
+
elif self.session.is_api_key():
|
|
111
|
+
logger.info("Using API Key authentication")
|
|
112
|
+
else:
|
|
113
|
+
logger.warning("No authentication method configured")
|
|
114
|
+
|
|
115
|
+
logger.info(f"Base URL: {self.session.base_url}")
|
|
116
|
+
logger.info(f"Alias: {self.session.alias}")
|
|
117
|
+
|
|
48
118
|
@property
|
|
49
119
|
def session(self):
|
|
50
120
|
return self.__session
|
|
@@ -58,6 +128,5 @@ class BaseClient(ABC):
|
|
|
58
128
|
return self.__api_service
|
|
59
129
|
|
|
60
130
|
@api_service.setter
|
|
61
|
-
def api_service(self, api_service:
|
|
131
|
+
def api_service(self, api_service: GEAIApiService):
|
|
62
132
|
self.__api_service = api_service
|
|
63
|
-
|
pygeai/core/base/mappers.py
CHANGED
|
@@ -56,14 +56,10 @@ class ErrorMapper:
|
|
|
56
56
|
:param data: dict - The dictionary containing error response data.
|
|
57
57
|
:return: list[Error] - A list of `Error` objects.
|
|
58
58
|
"""
|
|
59
|
-
error_list = list()
|
|
60
59
|
errors = data.get('errors')
|
|
61
60
|
if errors is not None and any(errors):
|
|
62
|
-
for error_data in errors
|
|
63
|
-
|
|
64
|
-
error_list.append(error)
|
|
65
|
-
|
|
66
|
-
return error_list
|
|
61
|
+
return [cls.map_to_error(error_data) for error_data in errors]
|
|
62
|
+
return []
|
|
67
63
|
|
|
68
64
|
|
|
69
65
|
class ResponseMapper:
|
|
@@ -130,14 +126,10 @@ class ModelMapper:
|
|
|
130
126
|
:param data: dict - The dictionary containing the list of intents.
|
|
131
127
|
:return: list[AssistantIntent] - A list of mapped `AssistantIntent` objects.
|
|
132
128
|
"""
|
|
133
|
-
intent_list = list()
|
|
134
129
|
intents = data.get('intents')
|
|
135
130
|
if intents is not None and any(intents):
|
|
136
|
-
for intent_data in intents
|
|
137
|
-
|
|
138
|
-
intent_list.append(intent)
|
|
139
|
-
|
|
140
|
-
return intent_list
|
|
131
|
+
return [cls.map_to_intent(intent_data) for intent_data in intents]
|
|
132
|
+
return []
|
|
141
133
|
|
|
142
134
|
@classmethod
|
|
143
135
|
def map_to_intent(cls, data: dict) -> AssistantIntent:
|
|
@@ -165,14 +157,13 @@ class ModelMapper:
|
|
|
165
157
|
:param data: dict - The dictionary containing the list of revisions.
|
|
166
158
|
:return: list[AssistantRevision] - A list of mapped `AssistantRevision` objects.
|
|
167
159
|
"""
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
revisions = data.get('revisions')
|
|
161
|
+
|
|
170
162
|
if revisions is not None and any(revisions):
|
|
171
|
-
for revision_data in revisions:
|
|
172
|
-
revision = cls.map_to_revision(revision_data)
|
|
173
|
-
revision_list.append(revision)
|
|
174
163
|
|
|
175
|
-
|
|
164
|
+
return [cls.map_to_revision(revision_data) for revision_data in revisions]
|
|
165
|
+
|
|
166
|
+
return []
|
|
176
167
|
|
|
177
168
|
@classmethod
|
|
178
169
|
def map_to_revision(cls, data: dict) -> AssistantRevision:
|
|
@@ -204,14 +195,13 @@ class ModelMapper:
|
|
|
204
195
|
:param data: dict - The dictionary containing metadata information.
|
|
205
196
|
:return: list[AssistantRevisionMetadata] - A list of mapped `AssistantRevisionMetadata` objects.
|
|
206
197
|
"""
|
|
207
|
-
metadata_list = list()
|
|
208
198
|
metadata = data.get('metadata')
|
|
199
|
+
|
|
209
200
|
if metadata is not None and any(metadata):
|
|
210
|
-
for metadata_data in metadata:
|
|
211
|
-
metadata = cls.map_to_metadata(metadata_data)
|
|
212
|
-
metadata_list.append(metadata)
|
|
213
201
|
|
|
214
|
-
|
|
202
|
+
return [cls.map_to_metadata(metadata_data) for metadata_data in metadata]
|
|
203
|
+
|
|
204
|
+
return []
|
|
215
205
|
|
|
216
206
|
@classmethod
|
|
217
207
|
def map_to_metadata(cls, data: dict) -> AssistantRevisionMetadata:
|
|
@@ -254,14 +244,13 @@ class ModelMapper:
|
|
|
254
244
|
|
|
255
245
|
@classmethod
|
|
256
246
|
def map_to_search_profile_list(cls, data: dict) -> list[SearchProfile]:
|
|
257
|
-
search_profile_list = list()
|
|
258
247
|
search_profiles = data.get('searchProfiles')
|
|
248
|
+
|
|
259
249
|
if search_profiles is not None and any(search_profiles):
|
|
260
|
-
for search_profile_data in search_profiles:
|
|
261
|
-
search_profile = cls.map_to_search_profile(search_profile_data)
|
|
262
|
-
search_profile_list.append(search_profile)
|
|
263
250
|
|
|
264
|
-
|
|
251
|
+
return [cls.map_to_search_profile(search_profile_data) for search_profile_data in search_profiles]
|
|
252
|
+
|
|
253
|
+
return []
|
|
265
254
|
|
|
266
255
|
@classmethod
|
|
267
256
|
def map_to_search_profile(cls, data: dict) -> SearchProfile:
|
|
@@ -278,14 +267,13 @@ class ModelMapper:
|
|
|
278
267
|
|
|
279
268
|
@classmethod
|
|
280
269
|
def map_to_token_list(cls, data: dict) -> list[ProjectToken]:
|
|
281
|
-
token_list = list()
|
|
282
270
|
tokens = data.get('tokens')
|
|
271
|
+
|
|
283
272
|
if tokens is not None and any(tokens):
|
|
284
|
-
for token_data in tokens:
|
|
285
|
-
token = cls.map_to_token(token_data)
|
|
286
|
-
token_list.append(token)
|
|
287
273
|
|
|
288
|
-
|
|
274
|
+
return [cls.map_to_token(token_data) for token_data in tokens]
|
|
275
|
+
|
|
276
|
+
return []
|
|
289
277
|
|
|
290
278
|
@classmethod
|
|
291
279
|
def map_to_token(cls, data: dict) -> ProjectToken:
|
|
@@ -305,14 +293,13 @@ class ModelMapper:
|
|
|
305
293
|
|
|
306
294
|
@classmethod
|
|
307
295
|
def map_to_usage_limit_list(cls, data: dict) -> list[UsageLimit]:
|
|
308
|
-
usage_limit_list = list()
|
|
309
296
|
usage_limits = data.get('usageLimits')
|
|
297
|
+
|
|
310
298
|
if usage_limits is not None and any(usage_limits):
|
|
311
|
-
for usage_limit_data in usage_limits:
|
|
312
|
-
usage_limit = cls.map_to_usage_limit(usage_limit_data)
|
|
313
|
-
usage_limit_list.append(usage_limit)
|
|
314
299
|
|
|
315
|
-
|
|
300
|
+
return [cls.map_to_usage_limit(usage_limit_data) for usage_limit_data in usage_limits]
|
|
301
|
+
|
|
302
|
+
return []
|
|
316
303
|
|
|
317
304
|
@classmethod
|
|
318
305
|
def map_to_usage_limit(cls, data: dict) -> UsageLimit:
|
|
@@ -339,14 +326,13 @@ class ModelMapper:
|
|
|
339
326
|
|
|
340
327
|
@classmethod
|
|
341
328
|
def map_to_item_list(cls, data: dict) -> list[RequestItem]:
|
|
342
|
-
item_list = list()
|
|
343
329
|
items = data.get('items')
|
|
330
|
+
|
|
344
331
|
if items is not None and any(items):
|
|
345
|
-
for item_data in items:
|
|
346
|
-
item = cls.map_to_item(item_data)
|
|
347
|
-
item_list.append(item)
|
|
348
332
|
|
|
349
|
-
|
|
333
|
+
return [cls.map_to_item(item_data) for item_data in items]
|
|
334
|
+
|
|
335
|
+
return []
|
|
350
336
|
|
|
351
337
|
@classmethod
|
|
352
338
|
def map_to_item(cls, data: dict) -> RequestItem:
|
|
@@ -427,14 +413,13 @@ class ModelMapper:
|
|
|
427
413
|
|
|
428
414
|
@classmethod
|
|
429
415
|
def map_to_feature_list(cls, data: dict) -> list[WelcomeDataFeature]:
|
|
430
|
-
|
|
431
|
-
|
|
416
|
+
features = data.get('features')
|
|
417
|
+
|
|
432
418
|
if features is not None and any(features):
|
|
433
|
-
for feature_data in features:
|
|
434
|
-
feature = cls.map_to_feature(feature_data)
|
|
435
|
-
feature_list.append(feature)
|
|
436
419
|
|
|
437
|
-
|
|
420
|
+
return [cls.map_to_feature(feature_data) for feature_data in features]
|
|
421
|
+
|
|
422
|
+
return []
|
|
438
423
|
|
|
439
424
|
@classmethod
|
|
440
425
|
def map_to_feature(cls, data: dict) -> WelcomeDataFeature:
|
|
@@ -445,14 +430,13 @@ class ModelMapper:
|
|
|
445
430
|
|
|
446
431
|
@classmethod
|
|
447
432
|
def map_to_example_prompt_list(cls, data: dict) -> list[WelcomeDataExamplePrompt]:
|
|
448
|
-
|
|
449
|
-
|
|
433
|
+
examples_prompt = data.get('examplesPrompt')
|
|
434
|
+
|
|
450
435
|
if examples_prompt is not None and any(examples_prompt):
|
|
451
|
-
for example_prompt_data in examples_prompt:
|
|
452
|
-
example_prompt = cls.map_to_example_prompt(example_prompt_data)
|
|
453
|
-
example_prompt_list.append(example_prompt)
|
|
454
436
|
|
|
455
|
-
|
|
437
|
+
return [cls.map_to_example_prompt(example_prompt_data) for example_prompt_data in examples_prompt]
|
|
438
|
+
|
|
439
|
+
return []
|
|
456
440
|
|
|
457
441
|
@classmethod
|
|
458
442
|
def map_to_example_prompt(cls, data: dict) -> WelcomeDataExamplePrompt:
|