pygeai 0.6.0b13__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.
Files changed (217) hide show
  1. pygeai/__init__.py +1 -2
  2. pygeai/_docs/source/content/api_reference/project.rst +392 -0
  3. pygeai/_docs/source/content/authentication.rst +130 -1
  4. pygeai/_docs/source/content/debugger.rst +327 -157
  5. pygeai/_docs/source/content/migration.rst +391 -7
  6. pygeai/_docs/source/pygeai.core.common.rst +8 -0
  7. pygeai/_docs/source/pygeai.tests.auth.rst +56 -0
  8. pygeai/_docs/source/pygeai.tests.cli.rst +8 -0
  9. pygeai/admin/clients.py +1 -3
  10. pygeai/analytics/clients.py +1 -1
  11. pygeai/assistant/clients.py +2 -7
  12. pygeai/assistant/data/clients.py +0 -8
  13. pygeai/assistant/data_analyst/clients.py +0 -2
  14. pygeai/assistant/managers.py +1 -1
  15. pygeai/assistant/rag/clients.py +0 -2
  16. pygeai/assistant/rag/mappers.py +9 -11
  17. pygeai/auth/clients.py +26 -7
  18. pygeai/auth/endpoints.py +2 -1
  19. pygeai/chat/clients.py +2 -2
  20. pygeai/chat/managers.py +1 -1
  21. pygeai/cli/commands/admin.py +13 -25
  22. pygeai/cli/commands/analytics.py +56 -88
  23. pygeai/cli/commands/assistant.py +84 -138
  24. pygeai/cli/commands/auth.py +23 -46
  25. pygeai/cli/commands/base.py +0 -1
  26. pygeai/cli/commands/chat.py +218 -209
  27. pygeai/cli/commands/common.py +5 -5
  28. pygeai/cli/commands/configuration.py +79 -29
  29. pygeai/cli/commands/docs.py +3 -4
  30. pygeai/cli/commands/embeddings.py +13 -19
  31. pygeai/cli/commands/evaluation.py +133 -344
  32. pygeai/cli/commands/feedback.py +7 -15
  33. pygeai/cli/commands/files.py +26 -53
  34. pygeai/cli/commands/gam.py +28 -69
  35. pygeai/cli/commands/lab/ai_lab.py +96 -142
  36. pygeai/cli/commands/lab/common.py +1 -1
  37. pygeai/cli/commands/lab/spec.py +12 -32
  38. pygeai/cli/commands/llm.py +9 -18
  39. pygeai/cli/commands/migrate.py +43 -99
  40. pygeai/cli/commands/organization.py +223 -196
  41. pygeai/cli/commands/rag.py +35 -58
  42. pygeai/cli/commands/rerank.py +21 -25
  43. pygeai/cli/commands/secrets.py +39 -67
  44. pygeai/cli/commands/usage_limits.py +50 -136
  45. pygeai/cli/commands/validators.py +1 -1
  46. pygeai/cli/geai.py +32 -3
  47. pygeai/cli/geai_proxy.py +6 -2
  48. pygeai/cli/install_man.py +1 -1
  49. pygeai/cli/parsers.py +1 -1
  50. pygeai/core/base/clients.py +90 -21
  51. pygeai/core/base/mappers.py +39 -55
  52. pygeai/core/base/session.py +134 -22
  53. pygeai/core/common/config.py +50 -13
  54. pygeai/core/common/constants.py +8 -0
  55. pygeai/core/common/exceptions.py +6 -0
  56. pygeai/core/embeddings/clients.py +0 -1
  57. pygeai/core/embeddings/managers.py +0 -1
  58. pygeai/core/feedback/clients.py +0 -2
  59. pygeai/core/feedback/models.py +1 -1
  60. pygeai/core/files/clients.py +0 -3
  61. pygeai/core/files/managers.py +1 -1
  62. pygeai/core/files/mappers.py +4 -5
  63. pygeai/core/llm/clients.py +0 -1
  64. pygeai/core/models.py +4 -4
  65. pygeai/core/plugins/clients.py +0 -3
  66. pygeai/core/plugins/models.py +2 -2
  67. pygeai/core/rerank/clients.py +0 -2
  68. pygeai/core/secrets/clients.py +0 -2
  69. pygeai/core/services/rest.py +80 -14
  70. pygeai/core/singleton.py +24 -0
  71. pygeai/dbg/__init__.py +2 -2
  72. pygeai/dbg/debugger.py +276 -38
  73. pygeai/evaluation/clients.py +2 -4
  74. pygeai/evaluation/dataset/clients.py +0 -1
  75. pygeai/evaluation/plan/clients.py +0 -2
  76. pygeai/evaluation/result/clients.py +0 -2
  77. pygeai/gam/clients.py +1 -3
  78. pygeai/health/clients.py +1 -3
  79. pygeai/lab/clients.py +0 -1
  80. pygeai/lab/managers.py +0 -1
  81. pygeai/lab/models.py +0 -1
  82. pygeai/lab/strategies/clients.py +1 -2
  83. pygeai/lab/tools/clients.py +2 -2
  84. pygeai/lab/tools/mappers.py +1 -1
  85. pygeai/migration/strategies.py +5 -6
  86. pygeai/migration/tools.py +1 -1
  87. pygeai/organization/clients.py +118 -12
  88. pygeai/organization/endpoints.py +1 -0
  89. pygeai/organization/limits/clients.py +4 -6
  90. pygeai/organization/limits/managers.py +1 -4
  91. pygeai/organization/managers.py +2 -2
  92. pygeai/proxy/config.py +1 -0
  93. pygeai/proxy/managers.py +6 -5
  94. pygeai/tests/admin/test_clients.py +11 -11
  95. pygeai/tests/assistants/rag/test_clients.py +1 -1
  96. pygeai/tests/assistants/rag/test_models.py +1 -2
  97. pygeai/tests/assistants/test_clients.py +1 -1
  98. pygeai/tests/assistants/test_managers.py +1 -3
  99. pygeai/tests/auth/test_cli_configuration.py +252 -0
  100. pygeai/tests/auth/test_client_initialization.py +411 -0
  101. pygeai/tests/auth/test_clients.py +29 -27
  102. pygeai/tests/auth/test_config_manager.py +305 -0
  103. pygeai/tests/auth/test_header_injection.py +294 -0
  104. pygeai/tests/auth/test_oauth.py +3 -1
  105. pygeai/tests/auth/test_session_logging.py +119 -0
  106. pygeai/tests/auth/test_session_validation.py +408 -0
  107. pygeai/tests/auth/test_singleton_reset.py +201 -0
  108. pygeai/tests/chat/test_clients.py +1 -1
  109. pygeai/tests/chat/test_iris.py +1 -1
  110. pygeai/tests/chat/test_ui.py +0 -2
  111. pygeai/tests/cli/commands/lab/test_ai_lab.py +1 -3
  112. pygeai/tests/cli/commands/lab/test_common.py +0 -1
  113. pygeai/tests/cli/commands/test_chat.py +1 -1
  114. pygeai/tests/cli/commands/test_common.py +0 -1
  115. pygeai/tests/cli/commands/test_embeddings.py +2 -2
  116. pygeai/tests/cli/commands/test_evaluation.py +1 -9
  117. pygeai/tests/cli/commands/test_llm.py +1 -1
  118. pygeai/tests/cli/commands/test_migrate.py +1 -1
  119. pygeai/tests/cli/commands/test_rerank.py +0 -1
  120. pygeai/tests/cli/commands/test_secrets.py +1 -1
  121. pygeai/tests/cli/commands/test_show_help.py +0 -1
  122. pygeai/tests/cli/commands/test_validators.py +0 -1
  123. pygeai/tests/cli/test_credentials_flag.py +312 -0
  124. pygeai/tests/cli/test_error_handler.py +0 -1
  125. pygeai/tests/core/base/test_mappers.py +2 -2
  126. pygeai/tests/core/base/test_models.py +4 -4
  127. pygeai/tests/core/common/test_config.py +2 -7
  128. pygeai/tests/core/common/test_decorators.py +0 -1
  129. pygeai/tests/core/embeddings/test_managers.py +1 -1
  130. pygeai/tests/core/feedback/test_clients.py +2 -2
  131. pygeai/tests/core/files/test_clients.py +6 -6
  132. pygeai/tests/core/files/test_models.py +0 -1
  133. pygeai/tests/core/files/test_responses.py +0 -1
  134. pygeai/tests/core/llm/test_clients.py +1 -1
  135. pygeai/tests/core/plugins/test_clients.py +4 -4
  136. pygeai/tests/core/rerank/test_mappers.py +1 -3
  137. pygeai/tests/core/secrets/test_clients.py +2 -3
  138. pygeai/tests/core/services/test_rest.py +10 -10
  139. pygeai/tests/core/utils/test_console.py +0 -1
  140. pygeai/tests/dbg/test_debugger.py +95 -8
  141. pygeai/tests/evaluation/dataset/test_clients.py +24 -27
  142. pygeai/tests/evaluation/plan/test_clients.py +16 -18
  143. pygeai/tests/evaluation/result/test_clients.py +4 -5
  144. pygeai/tests/health/test_clients.py +2 -2
  145. pygeai/tests/integration/lab/agents/test_create_agent.py +1 -3
  146. pygeai/tests/integration/lab/agents/test_get_agent.py +1 -1
  147. pygeai/tests/integration/lab/processes/test_create_process.py +2 -2
  148. pygeai/tests/integration/lab/processes/test_create_task.py +2 -3
  149. pygeai/tests/integration/lab/processes/test_delete_process.py +0 -1
  150. pygeai/tests/integration/lab/processes/test_get_process.py +2 -4
  151. pygeai/tests/integration/lab/processes/test_list_process_instances.py +1 -3
  152. pygeai/tests/integration/lab/processes/test_update_process.py +3 -9
  153. pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +1 -2
  154. pygeai/tests/integration/lab/tools/test_delete_tool.py +1 -1
  155. pygeai/tests/integration/lab/tools/test_list_tools.py +1 -1
  156. pygeai/tests/integration/lab/tools/test_update_tool.py +1 -1
  157. pygeai/tests/lab/agents/test_clients.py +17 -17
  158. pygeai/tests/lab/processes/test_clients.py +67 -67
  159. pygeai/tests/lab/processes/test_mappers.py +23 -23
  160. pygeai/tests/lab/spec/test_loader.py +0 -2
  161. pygeai/tests/lab/spec/test_parsers.py +1 -2
  162. pygeai/tests/lab/strategies/test_clients.py +10 -10
  163. pygeai/tests/lab/test_managers.py +3 -5
  164. pygeai/tests/lab/test_mappers.py +1 -4
  165. pygeai/tests/lab/tools/test_clients.py +21 -21
  166. pygeai/tests/lab/tools/test_mappers.py +0 -1
  167. pygeai/tests/organization/limits/test_clients.py +33 -33
  168. pygeai/tests/organization/limits/test_managers.py +7 -7
  169. pygeai/tests/organization/test_clients.py +78 -60
  170. pygeai/tests/proxy/test_clients.py +1 -1
  171. pygeai/tests/proxy/test_integration.py +1 -4
  172. pygeai/tests/proxy/test_managers.py +1 -2
  173. pygeai/tests/proxy/test_servers.py +1 -2
  174. pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +0 -1
  175. pygeai/tests/snippets/assistants/rag/get_documents.py +0 -1
  176. pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +0 -1
  177. pygeai/tests/snippets/chat/get_request_status.py +0 -1
  178. pygeai/tests/snippets/dbg/file_debugging.py +72 -0
  179. pygeai/tests/snippets/dbg/module_debugging.py +60 -0
  180. pygeai/tests/snippets/embeddings/cohere_example.py +2 -2
  181. pygeai/tests/snippets/embeddings/openai_base64_example.py +1 -1
  182. pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +8 -8
  183. pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +5 -5
  184. pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +3 -3
  185. pygeai/tests/snippets/lab/agentic_flow_example_1.py +1 -1
  186. pygeai/tests/snippets/lab/agentic_flow_example_2.py +3 -4
  187. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +2 -2
  188. pygeai/tests/snippets/lab/agents/delete_agent.py +1 -2
  189. pygeai/tests/snippets/lab/agents/get_agent.py +1 -1
  190. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +10 -10
  191. pygeai/tests/snippets/lab/agents/get_sharing_link.py +0 -1
  192. pygeai/tests/snippets/lab/agents/list_agents.py +1 -1
  193. pygeai/tests/snippets/lab/agents/publish_agent_revision.py +0 -1
  194. pygeai/tests/snippets/lab/agents/update_agent_properties.py +1 -1
  195. pygeai/tests/snippets/lab/crud_ui.py +3 -5
  196. pygeai/tests/snippets/lab/processes/kbs/get_kb.py +0 -1
  197. pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +0 -1
  198. pygeai/tests/snippets/lab/processes/list_processes.py +1 -1
  199. pygeai/tests/snippets/lab/samples/summarize_files.py +0 -3
  200. pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +0 -1
  201. pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +1 -1
  202. pygeai/tests/snippets/lab/tools/get_tool.py +1 -1
  203. pygeai/tests/snippets/lab/tools/publish_tool_revision.py +0 -1
  204. pygeai/tests/snippets/lab/tools/set_parameters.py +1 -2
  205. pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +2 -3
  206. pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +1 -1
  207. pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +0 -1
  208. pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +0 -1
  209. pygeai/tests/snippets/lab/use_cases/update_web_designer.py +0 -1
  210. pygeai/tests/snippets/lab/use_cases/update_web_reader.py +0 -1
  211. pygeai/tests/snippets/migrate/orchestrator_examples.py +1 -1
  212. {pygeai-0.6.0b13.dist-info → pygeai-0.6.1.dist-info}/METADATA +32 -7
  213. {pygeai-0.6.0b13.dist-info → pygeai-0.6.1.dist-info}/RECORD +217 -206
  214. {pygeai-0.6.0b13.dist-info → pygeai-0.6.1.dist-info}/WHEEL +0 -0
  215. {pygeai-0.6.0b13.dist-info → pygeai-0.6.1.dist-info}/entry_points.txt +0 -0
  216. {pygeai-0.6.0b13.dist-info → pygeai-0.6.1.dist-info}/licenses/LICENSE +0 -0
  217. {pygeai-0.6.0b13.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(f"Command completed successfully")
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 not 'a2aServers' in config and not 'mcpServers' in config:
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(f" Done!")
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(f"Local installation complete. Add to ~/.bashrc to update MANPATH:")
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
- from pygeai.cli.commands.base import base_options
4
+
5
5
  from pygeai.cli.commands import Command, Option
6
6
  from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException
7
7
 
@@ -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 ApiService
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__(self, api_key: str = None, base_url: str = None, alias: str = None, *,
12
- access_token: str = None, project_id: str = None):
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
- If commont settings are not specified, they're retrieved from default Session, based on the
15
- credential files.
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
- if access_token and not project_id:
23
- raise MissingRequirementException("project_id is required when using access_token")
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("API KEY and BASE URL must be defined in order to use this functionality")
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("Cannot access this functionality without setting API_KEY and BASE_URL")
40
-
41
- token = self.session.access_token if self.session.access_token else self.session.api_key
42
- self.__api_service = ApiService(
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: ApiService):
131
+ def api_service(self, api_service: GEAIApiService):
62
132
  self.__api_service = api_service
63
-
@@ -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
- error = cls.map_to_error(error_data)
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
- intent = cls.map_to_intent(intent_data)
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
- revision_list = list()
169
- revisions = data.get("revisions")
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
- return revision_list
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
- return metadata_list
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
- return search_profile_list
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
- return token_list
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
- return usage_limit_list
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
- return item_list
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
- feature_list = list()
431
- features = data.get("features")
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
- return feature_list
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
- example_prompt_list = list()
449
- examples_prompt = data.get("examplesPrompt")
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
- return example_prompt_list
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: